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