📄 stafprocess.cpp
字号:
STAFProcessID_t nextFGPID = fgPIDList.front(); fgPIDList.pop_front(); if (tcsetpgrp(theTTY, nextFGPID) < 0) { STAFString errorMessage("STAFProcess::" "processMonitorThread: Error on " "tcsetpgrp(), errno: "); errorMessage += errno; STAFTrace::trace(kSTAFTraceError, errorMessage); } if (kill(nextFGPID, SIGCONT) < 0) { STAFString errorMessage("STAFProcess::" "processMonitorThread: " "Error continuing PID: "); errorMessage += nextFGPID; errorMessage += ", errno: "; errorMessage += errno; STAFTrace::trace(kSTAFTraceError, errorMessage); } } // If no process was found, lets go to sleep for some time, // unless we get posted meaning we need to create a process if (!foundProcess) { // if posted, create the process indicated in fProcessCreateInfo if (!sProcessThread.wait(MONITOR_SLEEP_SECONDS * 1000)) {#ifndef STAF_OS_NAME_ZOS // create the new process if ((sProcessCreateInfo.pid = STAF_FORK()) == 0) { // child process // setgid must be done first, as if we change the uid // first then we are not able to change the gid since // we may no longer have enough privilege to do that. if (setgid(sProcessCreateInfo.gid) < 0) { STAFTrace::trace(kSTAFTraceError, STAFString("STAFProcess::" "processMonitorThread: Child could " "not set child's gid: ") + errno); _exit(1); } if (setuid(sProcessCreateInfo.uid) < 0) { STAFTrace::trace(kSTAFTraceError, STAFString("STAFProcess::" "processMonitorThread: Child could " "not set child's uid: ") + errno); _exit(1); } if (setpgid(0, 0) < 0) { STAFTrace::trace(kSTAFTraceInfo, STAFString("STAFProcess::" "processMonitorThread: Child could " "not set child's pgid: ") + errno); _exit(1); } close(0); dup(sProcessCreateInfo.child_stdin); close(sProcessCreateInfo.child_stdin); close(1); dup(sProcessCreateInfo.child_stdout); close(sProcessCreateInfo.child_stdout); close(2); dup(sProcessCreateInfo.child_stderr); close(sProcessCreateInfo.child_stderr); // change working directory if appropriate if (sProcessCreateInfo.workdir->length() != 0) { chdir(sProcessCreateInfo.workdir->buffer()); } if (sProcessCreateInfo.envp == 0) { // overwrite memory with new process image if (execv((sProcessCreateInfo.commandType == kSTAFProcessCommand) ? sProcessCreateInfo.command->buffer() : "/bin/sh", sProcessCreateInfo.argv)) { STAFTrace::trace(kSTAFTraceError, STAFString("STAFProcess::" "processMonitorThread: Could " "not start process (execve):") + errno); _exit(1); // this is the child process } } else { // overwrite memory with new process image if (execve((sProcessCreateInfo.commandType == kSTAFProcessCommand) ? sProcessCreateInfo.command->buffer() : "/bin/sh", sProcessCreateInfo.argv, sProcessCreateInfo.envp)) { STAFTrace::trace(kSTAFTraceError, STAFString("STAFProcess::" "processMonitorThread: Could " "not start process (execve):") + errno); _exit(1); // this is the child process } } } // parent process if (setpgid(sProcessCreateInfo.pid, sProcessCreateInfo.pid) < 0) { STAFTrace::trace(kSTAFTraceInfo, STAFString("STAFProcess::" "processMonitorThread: Parent could not " "set child's pgid: ") + errno); }#else // STAF_OS_NAME_ZOS struct __inheritance inherit; // Set inheritance flags to create a new process group inherit.flags = SPAWN_SETGROUP; inherit.pgroup = SPAWN_NEWPGROUP; int fd_count = 3; int fd_map[3] = { sProcessCreateInfo.child_stdin, sProcessCreateInfo.child_stdout, sProcessCreateInfo.child_stderr }; //Set working directory if (sProcessCreateInfo.workdir->length() != 0) { inherit.flags |= SPAWN_SETCWD; inherit.cwdptr = const_cast<char *>( sProcessCreateInfo.workdir->buffer()); inherit.cwdlen = sProcessCreateInfo.workdir->length(); } //Set userid if (sProcessCreateInfo.uid != getuid()) { inherit.flags |= SPAWN_SETUSERID; // Note: The length of the inherit.userid buffer is // eight. Thus, we don't want to overwrite // anything after it. strncpy(inherit.userid, sProcessCreateInfo.userName->buffer(), 8); inherit.userid[8] = 0; } // create the new process sProcessCreateInfo.pid = __spawn2( (sProcessCreateInfo.commandType == kSTAFProcessCommand) ? sProcessCreateInfo.command->buffer() : "/bin/sh", fd_count, fd_map, &inherit, (const char**) sProcessCreateInfo.argv, (const char**) ((sProcessCreateInfo.envp == 0) ? environ : sProcessCreateInfo.envp)); // parent process if (sProcessCreateInfo.pid == -1) { STAFTrace::trace(kSTAFTraceError, STAFString("STAFProcess::" "processMonitorThread(): Could " "not start process: ") + errno); }#endif //Close file descriptors in the parent close(sProcessCreateInfo.child_stdin); close(sProcessCreateInfo.child_stdout); close(sProcessCreateInfo.child_stderr); { // acquire lock STAFMutexSemLock lock(sMonitorDataSem); // add new process to list sMonitorMap[sProcessCreateInfo.pid].push_back( ProcessMonitorInfo(sProcessCreateInfo.pid, sProcessCreateInfo.pid, sProcessCreateInfo.callback)); } // release lock // reset this thread's sem and post the process manager // so that it can deallocate any used resources sProcessThread.reset(); sProcessCreated.post(); } // if process thread was posted during wait } // if not process found by waitpid } // try block catch (STAFException &se) { se.trace("STAFProcess::ProcessMonitorThread()"); } catch (...) { STAFTrace::trace( kSTAFTraceError, "Caught unknown exception in " "STAFProcess::ProcessMonitorThread()"); } } // endless loop}STAFRC_t STAFProcessStart(STAFProcessID_t *pid, STAFProcessHandle_t *procHandle, void *data, unsigned int startDataLevel, unsigned int *osRC){ STAFString_t errorBuffer = 0; return STAFProcessStart2(pid, procHandle, data, startDataLevel, osRC, &errorBuffer);}STAFRC_t STAFProcessStart2(STAFProcessID_t *pid, STAFProcessHandle_t *procHandle, void *data, unsigned int startDataLevel, unsigned int *osRC, STAFString_t *errorBuffer){ if (data == 0) { if (errorBuffer) { STAFString errMsg = STAFString( "Invalid data provided to STAFProcessStart2()"); *errorBuffer = errMsg.adoptImpl(); } return kSTAFInvalidValue; } if (startDataLevel != 1) { if (errorBuffer) { STAFString errMsg = STAFString( "Invalid level provided to STAFProcessStart2(): ") + startDataLevel; *errorBuffer = errMsg.adoptImpl(); } return kSTAFInvalidValue; } unsigned int systemErrorCode = 0; STAFProcessStartInfoLevel1 *startData = reinterpret_cast<STAFProcessStartInfoLevel1 *>(data); InitProcessManager(); STAFString command(startData->command); struct stat fileinfo; if (startData->commandType == kSTAFProcessShell) command = command.subWord(0, 1); // Since a shell command could be "date; grep abc abc", cannot verify // that the first word (e.g. date;) is a valid command so only do this // check that the command is valid if not a shell command. if (startData->commandType != kSTAFProcessShell) { // Note: this checking is due to stat which requires a path'd file if (command.find(kUTF8_SLASH) == STAFString::kNPos) { STAFString_t path; // If no slashes found, resolve the command to form its path'd name // Note: getFilePath will always return a path that does not term- // inate with "/" STAFRC_t rc = STAFUtilUnixGetFilePath(command.getImpl(), &path, osRC); if (rc != kSTAFOk) { if (rc == kSTAFDoesNotExist) { if (osRC) *osRC = ENOENT; if (errorBuffer) { STAFString errMsg = STAFString( "Command does not exist: ") + command; *errorBuffer = errMsg.adoptImpl(); } return kSTAFBaseOSError; } if (errorBuffer) { STAFString errMsg = STAFString("Invalid command: ") + command; *errorBuffer = errMsg.adoptImpl(); } return rc; } // Command contains path of startData->command (from getFilePath // call), so here we construct something like "/usr/bin" + "/" + // "ls" = "/usr/bin/ls" // ???: This used to end with startData->command, not just command. // This messed things up when SHELL was added. There doesn't // seem to be a reason why startData->command was used instead // of just command. command = STAFString(path, STAFString::kShallow) + STAFString("/") + command; } // Check if command is a regular file and has execute perms if (stat(command.toCurrentCodePage()->buffer(), &fileinfo) == -1) { systemErrorCode = errno; if (osRC) *osRC = systemErrorCode; // set by stat if (errorBuffer) { STAFString errMsg = STAFString("Invalid command: ") + command + "\nThe command is not a file or does not have execute " "permissions.\nOS RC " + systemErrorCode; *errorBuffer = errMsg.adoptImpl(); } return kSTAFBaseOSError; } else if (!S_ISREG(fileinfo.st_mode)) { if (osRC) *osRC = ENOEXEC; // exec format error if (errorBuffer) { STAFString errMsg = STAFString("Invalid command: ") + command + "\nThe command is not a valid executable.";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -