Windows Wrapper

/*
 * 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;
}