/*
* undef USE_JOB_CONTROL on systems less than 2000,XP
* These systems don't support this API, but as a consequence,
* the running time won't be limited.
*/
#define USE_JOB_CONTROL
/* This program is licensed under GPL v2.
Written by:
Johannes Berg
Alexander Schremmer
*/
/* Usage:
runlimit CPUTIME DIRECTORY EXECUTABLE [OPTS]
This will run "EXECUTABLE OPTS" in the directory DIRECTORY.
The process will be killed if it does not terminate in CPUTIME seconds.
*/
int main(int argc, char** argv) {
char cmdlinebuffer[CMDLINE_MAX], cmdlinebuffer2[CMDLINE_MAX];
char* cmdline = NULL;
STARTUPINFO startupinfo;
PROCESS_INFORMATION processinfo;
DWORD exitcode;
unsigned int joblimit; /* need to parse parameter even if not using job limits */
#ifdef USE_JOB_CONTROL
JOBOBJECT_BASIC_LIMIT_INFORMATION lpJobObjectInfo;
DWORD cbJobObjectInfoLength = sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION);
LARGE_INTEGER large_int;
lpJobObjectInfo.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_TIME;
HANDLE job = CreateJobObject(NULL, NULL);
if (job == NULL) {
fprintf(stderr, "Failed to create job object\n");
return 2;
}
#endif
startupinfo.cb = sizeof(STARTUPINFO);
startupinfo.lpReserved=NULL;
startupinfo.lpDesktop=NULL;
startupinfo.lpTitle=NULL;
startupinfo.dwFlags=0;
startupinfo.wShowWindow=0;
startupinfo.cbReserved2=0;
startupinfo.lpReserved2=NULL;
cmdlinebuffer[0] = '\0';
_dup2(1,2);
if (argc < 3)
return 2; /* bah. nothing to do */
joblimit = atoi(argv[1]);
if (!joblimit)
return 2;
#ifdef USE_JOB_CONTROL
large_int.QuadPart = 10000000 * joblimit;
lpJobObjectInfo.PerProcessUserTimeLimit = large_int;
#endif
if (argc > 3) {
_snprintf(cmdlinebuffer, CMDLINE_MAX-1, "\"%s\"", argv[3]);
for (int i = 4; i < argc; i++) {
memcpy(cmdlinebuffer2, cmdlinebuffer, CMDLINE_MAX);
_snprintf(cmdlinebuffer, CMDLINE_MAX-1, "%s \"%s\"", cmdlinebuffer2, argv[i]);
}
cmdline = &cmdlinebuffer[0];
}
if (!CreateProcess (NULL,
cmdline,
NULL,
NULL,
FALSE,
CREATE_BREAKAWAY_FROM_JOB,
NULL,
argv[2],
&startupinfo,
&processinfo)) {
fprintf(stderr, "CreateProcess failed: %i\n", GetLastError());
return 2;
} else {
CloseHandle(processinfo.hThread);
}
#ifdef USE_JOB_CONTROL
if (!SetInformationJobObject(job, JobObjectBasicLimitInformation,
&lpJobObjectInfo, cbJobObjectInfoLength)) {
fprintf(stderr, "SetInformationJobObject failed, process running uncontrolled!\n");
}
if (!AssignProcessToJobObject(job, processinfo.hProcess)) {
fprintf(stderr, "AssignProcessToJobObject failed, process running uncontrolled!\n");
}
#endif
if (WaitForSingleObject(processinfo.hProcess, INFINITE) == WAIT_FAILED) {
fprintf(stderr, "WaitForSingleObject failed with code %d\n", GetLastError());
}
if (!GetExitCodeProcess(processinfo.hProcess, &exitcode)) {
fprintf(stderr, "GetExitCodeProcess failed with %d\n", GetLastError());
exitcode = 2;
}
CloseHandle(processinfo.hProcess);
#ifdef USE_JOB_CONTROL
CloseHandle(job);
#endif
return exitcode;
}