static void run_test(/*@notnull@*/ test_runner * runner, /*@notnull@*/ unit_test * test) /*@globals fileSystem, internalState @*/ /*@modifies fileSystem, internalState, runner->buffer, test @*/ { const char * last_output; const char * last_error; int termination_status; make_command_line(runner); printf(" %s_%s: ", (test->is_requirement ? "requirement" : "unit_test"), test->code); termination_status = system(runner->buffer); test->found_exit_code = GET_EXIT_CODE(termination_status); last_output = load_file( runner->out, test->found_output, sizeof(test->found_output) ); last_error = load_file( runner->err, test->found_error, sizeof(test->found_error) ); test->unexpected_exit_code = ( test->expected_exit_code != EXIT_WHATEVER && test->found_exit_code != test->expected_exit_code ); test->unexpected_error = ( test->expected_error != ERROR_WHATEVER && is_unexpected_token(test->expected_error, last_error) ); test->unexpected_output = ( test->expected_output != OUTPUT_WHATEVER && is_unexpected_token(test->expected_output, last_output) ); if(!test->unexpected_exit_code && !test->unexpected_output && !test->unexpected_error){ test->status = STATUS_PASSED; }else if(!test->is_critical){ test->status = STATUS_WARNING; }else{ test->status = STATUS_FAILED; } if(test->status == STATUS_PASSED){ printf("%s\n", (test->is_requirement ? "fulfilled" : "passed") ); }else{ printf("%s [%c%c%c]\n", (test->is_requirement ? (test->is_critical ? "NOT FULFILLED!" : "not fulfilled") : (test->is_critical ? "FAILED!" : "failed!") ), (test->unexpected_exit_code ? 'X' : '1'), (test->unexpected_output ? 'O' : '2'), (test->unexpected_error ? 'E' : '3') ); } }
void pipeline(const char *const *argv, struct pipeline *pl) { HANDLE in_read_handle, in_write_handle; SECURITY_ATTRIBUTES sec_attr; PROCESS_INFORMATION proc_info; STARTUPINFO start_info; char *cmdline = make_command_line(argv); sec_attr.nLength = sizeof sec_attr; sec_attr.bInheritHandle = TRUE; sec_attr.lpSecurityDescriptor = NULL; if (!CreatePipe(&in_read_handle, &in_write_handle, &sec_attr, 0)) { die_windows_error("CreatePipe"); } if (!SetHandleInformation(in_write_handle, HANDLE_FLAG_INHERIT, 0)) { die_windows_error("SetHandleInformation"); } /* when in Rome... */ ZeroMemory(&proc_info, sizeof proc_info); ZeroMemory(&start_info, sizeof start_info); start_info.cb = sizeof start_info; start_info.dwFlags |= STARTF_USESTDHANDLES; if ((start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE)) == INVALID_HANDLE_VALUE || (start_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE)) == INVALID_HANDLE_VALUE) { die_windows_error("GetStdHandle"); } start_info.hStdInput = in_read_handle; if (!CreateProcess(NULL, cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &start_info, &proc_info)) { die_windows_error("CreateProcess"); } free(cmdline); if (!CloseHandle(proc_info.hThread)) { die_windows_error("CloseHandle for thread"); } if (!CloseHandle(in_read_handle)) { die_windows_error("CloseHandle"); } pl->proc_handle = proc_info.hProcess; pl->infd = _open_osfhandle((intptr_t)in_write_handle, 0); }
static int win_spawn(const char *cmd, const char **argv, const char **envp, const char *cwd, HANDLE handles[3], int background, int shell) { char *args = make_command_line(shell, cmd, argv); char *env = make_environment(envp); char *program = shell ? NULL : find_program(cmd); STARTUPINFO si; PROCESS_INFORMATION pi; BOOL result; DWORD exitcode; int i; if (!shell) { G_debug(3, "win_spawn: program = %s", program); if (!program) { G_free(args); G_free(env); return -1; } } G_debug(3, "win_spawn: args = %s", args); memset(&si, 0, sizeof(si)); si.cb = sizeof(si); si.dwFlags |= STARTF_USESTDHANDLES; si.hStdInput = handles[0]; si.hStdOutput = handles[1]; si.hStdError = handles[2]; result = CreateProcess( program, /* lpApplicationName */ args, /* lpCommandLine */ NULL, /* lpProcessAttributes */ NULL, /* lpThreadAttributes */ 1, /* bInheritHandles */ 0, /* dwCreationFlags */ env, /* lpEnvironment */ cwd, /* lpCurrentDirectory */ &si, /* lpStartupInfo */ &pi /* lpProcessInformation */ ); G_free(args); G_free(env); G_free(program); if (!result) { G_warning(_("CreateProcess() failed: error = %d"), GetLastError()); return -1; } CloseHandle(pi.hThread); for (i = 0; i < 3; i++) if (handles[i] != INVALID_HANDLE_VALUE) CloseHandle(handles[i]); if (!background) { WaitForSingleObject(pi.hProcess, INFINITE); if (!GetExitCodeProcess(pi.hProcess, &exitcode)) return -1; CloseHandle(pi.hProcess); return (int) exitcode; } CloseHandle(pi.hProcess); return pi.dwProcessId; }
/* * Description: Create the child process to be helped * * Returns: success <=> 0 * * Notes/Dependencies: */ long process_begin( HANDLE proc, char **argv, char **envp, char *exec_path, char *as_user) { sub_process *pproc = (sub_process *)proc; char *shell_name = 0; int file_not_found=0; HANDLE exec_handle; char exec_fname[MAX_PATH]; const char *path_var = NULL; char **ep; char buf[256]; DWORD bytes_returned; DWORD flags; char *command_line; STARTUPINFO startInfo; PROCESS_INFORMATION procInfo; char *envblk=NULL; /* * Shell script detection... if the exec_path starts with #! then * we want to exec shell-script-name exec-path, not just exec-path * NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl. We do not * hard-code the path to the shell or perl or whatever: Instead, we * assume it's in the path somewhere (generally, the NT tools * bin directory) */ /* Use the Makefile's value of PATH to look for the program to execute, because it could be different from Make's PATH (e.g., if the target sets its own value. */ if (envp) for (ep = envp; *ep; ep++) { if (strncmp (*ep, "PATH=", 5) == 0 || strncmp (*ep, "Path=", 5) == 0) { path_var = *ep + 5; break; } } exec_handle = find_file(exec_path, path_var, exec_fname, sizeof(exec_fname)); /* * If we couldn't open the file, just assume that Windows will be * somehow able to find and execute it. */ if (exec_handle == INVALID_HANDLE_VALUE) { file_not_found++; } else { /* Attempt to read the first line of the file */ if (ReadFile( exec_handle, buf, sizeof(buf) - 1, /* leave room for trailing NULL */ &bytes_returned, 0) == FALSE || bytes_returned < 2) { pproc->last_err = GetLastError(); pproc->lerrno = E_IO; CloseHandle(exec_handle); return(-1); } if (buf[0] == '#' && buf[1] == '!') { /* * This is a shell script... Change the command line from * exec_path args to shell_name exec_path args */ char *p; /* Make sure buf is NULL terminated */ buf[bytes_returned] = 0; /* * Depending on the file system type, etc. the first line * of the shell script may end with newline or newline-carriage-return * Whatever it ends with, cut it off. */ p= strchr(buf, '\n'); if (p) *p = 0; p = strchr(buf, '\r'); if (p) *p = 0; /* * Find base name of shell */ shell_name = strrchr( buf, '/'); if (shell_name) { shell_name++; } else { shell_name = &buf[2];/* skipping "#!" */ } } CloseHandle(exec_handle); } flags = 0; if (file_not_found) command_line = make_command_line( shell_name, exec_path, argv); else command_line = make_command_line( shell_name, exec_fname, argv); if ( command_line == NULL ) { pproc->last_err = 0; pproc->lerrno = E_NO_MEM; return(-1); } if (envp) { if (arr2envblk(envp, &envblk) ==FALSE) { pproc->last_err = 0; pproc->lerrno = E_NO_MEM; free( command_line ); return(-1); } } if ((shell_name) || (file_not_found)) { exec_path = 0; /* Search for the program in %Path% */ } else { exec_path = exec_fname; } /* * Set up inherited stdin, stdout, stderr for child */ GetStartupInfo(&startInfo); startInfo.dwFlags = STARTF_USESTDHANDLES; startInfo.lpReserved = 0; startInfo.cbReserved2 = 0; startInfo.lpReserved2 = 0; startInfo.lpTitle = shell_name ? shell_name : exec_path; startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1]; startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1]; startInfo.hStdError = (HANDLE)pproc->sv_stderr[1]; if (as_user) { if (envblk) free(envblk); return -1; } else { DB (DB_JOBS, ("CreateProcess(%s,%s,...)\n", exec_path ? exec_path : "NULL", command_line ? command_line : "NULL")); if (CreateProcess( exec_path, command_line, NULL, 0, /* default security attributes for thread */ TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */ flags, envblk, 0, /* default starting directory */ &startInfo, &procInfo) == FALSE) { pproc->last_err = GetLastError(); pproc->lerrno = E_FORK; fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n", exec_path ? exec_path : "NULL", command_line); if (envblk) free(envblk); free( command_line ); return(-1); } } pproc->pid = (pid_t)procInfo.hProcess; /* Close the thread handle -- we'll just watch the process */ CloseHandle(procInfo.hThread); /* Close the halves of the pipes we don't need */ CloseHandle((HANDLE)pproc->sv_stdin[1]); CloseHandle((HANDLE)pproc->sv_stdout[1]); CloseHandle((HANDLE)pproc->sv_stderr[1]); pproc->sv_stdin[1] = 0; pproc->sv_stdout[1] = 0; pproc->sv_stderr[1] = 0; free( command_line ); if (envblk) free(envblk); pproc->lerrno=0; return 0; }
/* * Description: Create the child process to be helped * * Returns: * * Notes/Dependencies: */ long process_begin( HANDLE proc, char **argv, char **envp, char *exec_path, char *as_user) { sub_process *pproc = (sub_process *)proc; char *shell_name = 0; int file_not_found=0; HANDLE exec_handle; char buf[256]; DWORD bytes_returned; DWORD flags; char *command_line; STARTUPINFO startInfo; PROCESS_INFORMATION procInfo; char *envblk=NULL; OFSTRUCT file_info; /* * Shell script detection... if the exec_path starts with #! then * we want to exec shell-script-name exec-path, not just exec-path * NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl. We do not * hard-code the path to the shell or perl or whatever: Instead, we * assume it's in the path somewhere (generally, the NT tools * bin directory) * We use OpenFile here because it is capable of searching the Path. */ exec_handle = find_file(exec_path, &file_info); /* * If we couldn't open the file, just assume that Win32 will be able * to find and execute it. */ if (exec_handle == (HANDLE)HFILE_ERROR) { file_not_found++; } else { /* Attempt to read the first line of the file */ if (ReadFile( exec_handle, buf, sizeof(buf) - 1, /* leave room for trailing NULL */ &bytes_returned, 0) == FALSE || bytes_returned < 2) { pproc->last_err = GetLastError(); pproc->lerrno = E_IO; CloseHandle(exec_handle); return(-1); } if (buf[0] == '#' && buf[1] == '!') { /* * This is a shell script... Change the command line from * exec_path args to shell_name exec_path args */ char *p; /* Make sure buf is NULL terminated */ buf[bytes_returned] = 0; /* * Depending on the file system type, etc. the first line * of the shell script may end with newline or newline-carriage-return * Whatever it ends with, cut it off. */ p= strchr(buf, '\n'); if (p) *p = 0; p = strchr(buf, '\r'); if (p) *p = 0; /* * Find base name of shell */ shell_name = strrchr( buf, '/'); if (shell_name) { shell_name++; } else { shell_name = &buf[2];/* skipping "#!" */ } } CloseHandle(exec_handle); } flags = 0; if (file_not_found) command_line = make_command_line( shell_name, exec_path, argv); else command_line = make_command_line( shell_name, file_info.szPathName, argv); if ( command_line == NULL ) { pproc->last_err = 0; pproc->lerrno = E_NO_MEM; return(-1); } if (envp) { if (arr2envblk(envp, &envblk) ==FALSE) { pproc->last_err = 0; pproc->lerrno = E_NO_MEM; free( command_line ); return(-1); } } if ((shell_name) || (file_not_found)) { exec_path = 0; /* Search for the program in %Path% */ } else { exec_path = file_info.szPathName; } /* * Set up inherited stdin, stdout, stderr for child */ GetStartupInfo(&startInfo); startInfo.dwFlags = STARTF_USESTDHANDLES; startInfo.lpReserved = 0; startInfo.cbReserved2 = 0; startInfo.lpReserved2 = 0; startInfo.lpTitle = shell_name ? shell_name : exec_path; startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1]; startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1]; startInfo.hStdError = (HANDLE)pproc->sv_stderr[1]; /* * See if we need to setuid to a different user. */ if (as_user) { return -1; } if (as_user) { return -1; } else { if (CreateProcess( exec_path, command_line, NULL, 0, /* default security attributes for thread */ TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */ flags, envblk, 0, /* default starting directory */ &startInfo, &procInfo) == FALSE) { pproc->last_err = GetLastError(); pproc->lerrno = E_FORK; fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n", exec_path, command_line); free( command_line ); return(-1); } } pproc->pid = (int)procInfo.hProcess; /* Close the thread handle -- we'll just watch the process */ CloseHandle(procInfo.hThread); /* Close the halves of the pipes we don't need */ if (pproc->sv_stdin) { CloseHandle((HANDLE)pproc->sv_stdin[1]); (HANDLE)pproc->sv_stdin[1] = 0; } if (pproc->sv_stdout) { CloseHandle((HANDLE)pproc->sv_stdout[1]); (HANDLE)pproc->sv_stdout[1] = 0; } if (pproc->sv_stderr) { CloseHandle((HANDLE)pproc->sv_stderr[1]); (HANDLE)pproc->sv_stderr[1] = 0; } free( command_line ); pproc->lerrno=0; return 0; }
string exec_command( const string& str ) { // Construct this before any resources are claimed string result; const char *argv[4]; // No ownership of memory // Respect the SHELL environment variable, // and drop back to using CMD.EXE argv[0] = getenv("SHELL"); if ( !argv[0] || !*argv[0] ) { // TODO: On Windows NT 4, 2K and XP this is correct; // on Windows 95, 98 and ME, this should be COMMAND.COM, // though that'll probably be unusably slow. argv[0] = "CMD.EXE"; argv[1] = "/C"; } else { // argv[1] = "-c"; } argv[2] = str.c_str(); argv[3] = NULL; // ------- // From now on we have to be careful about exceptions // as we have pipes and child processes hanging around // HANDLE hErr; if (DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_ERROR_HANDLE), GetCurrentProcess(), &hErr, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) THROW_SYSTEM_ERROR( "DuplicateHandle" ); // Two ends of the pipe: HANDLE hChildOutRd, hChildOutWr; { SECURITY_ATTRIBUTES saAttr; saAttr.nLength = sizeof (SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; if (!CreatePipe(&hChildOutRd, &hChildOutWr, &saAttr, 0)) { CloseHandle(hErr); THROW_SYSTEM_ERROR( "CreatePipe" ); } } PROCESS_INFORMATION procInfo; { string command_line( make_command_line( argv[0], argv ) ); STARTUPINFO startInfo; GetStartupInfo(&startInfo); startInfo.dwFlags = STARTF_USESTDHANDLES; startInfo.lpReserved = 0; startInfo.cbReserved2 = 0; startInfo.lpReserved2 = 0; startInfo.lpTitle = 0; startInfo.hStdInput = NULL; startInfo.hStdOutput = hChildOutWr; startInfo.hStdError = hErr; if (CreateProcess(0, // Const correctness -- we've heard of it const_cast< char* >( command_line.c_str() ), NULL, 0, // default security attributes for thread TRUE, // inherit handles (e.g. helper pipes) 0, NULL, 0, // default starting directory &startInfo, &procInfo) == FALSE) { CloseHandle(hErr); CloseHandle(hChildOutRd); CloseHandle(hChildOutWr); THROW_SYSTEM_ERROR( "CreateProcess" ); } // Close the thread handle -- we'll just watch the process CloseHandle(procInfo.hThread); } CloseHandle( hErr ); CloseHandle( hChildOutWr ); try { while (true) { const size_t buflen(4096); char buffer[buflen]; // TODO: Unicode conversions??? DWORD i; ReadFile( hChildOutRd, buffer, buflen, &i, NULL); if (i <= 0) break; // TODO: Do something more sensible result.append( buffer, i ); // Might throw } } catch( ... ) { CloseHandle( hChildOutRd ); DWORD rv = WaitForMultipleObjects( 1, &procInfo.hProcess, FALSE, INFINITE ); if ( rv == WAIT_FAILED ) abort(); throw; } CloseHandle( hChildOutRd ); DWORD rv = WaitForMultipleObjects( 1, &procInfo.hProcess, FALSE, INFINITE ); if ( rv == WAIT_FAILED ) THROW_SYSTEM_ERROR( "WaitForMultipleObjects" ); return result; }