static bool SpawnIOChild(char* const* aArgs, PRProcess** aPID, PRFileDesc** aFromChildFD, PRFileDesc** aToChildFD) { PRFileDesc* toChildPipeRead; PRFileDesc* toChildPipeWrite; if (PR_CreatePipe(&toChildPipeRead, &toChildPipeWrite) != PR_SUCCESS) return false; PR_SetFDInheritable(toChildPipeRead, true); PR_SetFDInheritable(toChildPipeWrite, false); PRFileDesc* fromChildPipeRead; PRFileDesc* fromChildPipeWrite; if (PR_CreatePipe(&fromChildPipeRead, &fromChildPipeWrite) != PR_SUCCESS) { PR_Close(toChildPipeRead); PR_Close(toChildPipeWrite); return false; } PR_SetFDInheritable(fromChildPipeRead, false); PR_SetFDInheritable(fromChildPipeWrite, true); PRProcessAttr* attr = PR_NewProcessAttr(); if (!attr) { PR_Close(fromChildPipeRead); PR_Close(fromChildPipeWrite); PR_Close(toChildPipeRead); PR_Close(toChildPipeWrite); return false; } PR_ProcessAttrSetStdioRedirect(attr, PR_StandardInput, toChildPipeRead); PR_ProcessAttrSetStdioRedirect(attr, PR_StandardOutput, fromChildPipeWrite); PRProcess* process = PR_CreateProcess(aArgs[0], aArgs, nullptr, attr); PR_DestroyProcessAttr(attr); PR_Close(fromChildPipeWrite); PR_Close(toChildPipeRead); if (!process) { LOG(("ntlm_auth exec failure [%d]", PR_GetError())); PR_Close(fromChildPipeRead); PR_Close(toChildPipeWrite); return false; } *aPID = process; *aFromChildFD = fromChildPipeRead; *aToChildFD = toChildPipeWrite; return true; }
static ipcConnectionState * ConnCreate(PRFileDesc *fd) { ipcConnectionState *s = new ipcConnectionState; if (!s) return NULL; s->lock = PR_NewLock(); s->fds[SOCK].fd = NULL; s->fds[POLL].fd = PR_NewPollableEvent(); s->send_offset = 0; s->in_msg = NULL; s->shutdown = PR_FALSE; if (!s->lock || !s->fds[1].fd) { ConnDestroy(s); return NULL; } // disable inheritance of the IPC socket by children started // using non-NSPR process API PRStatus status = PR_SetFDInheritable(fd, PR_FALSE); if (status != PR_SUCCESS) { LOG(("coudn't make IPC socket non-inheritable [err=%d]\n", PR_GetError())); return NULL; } // store this only if we are going to succeed. s->fds[SOCK].fd = fd; return s; }
int main(int argc, char **argv) { PRFileDesc *sock[2]; PRStatus status; PRProcess *process; PRProcessAttr *attr; char buf[1024]; PRInt32 nBytes; PRInt32 exitCode; int idx; status = PR_NewTCPSocketPair(sock); if (status == PR_FAILURE) { fprintf(stderr, "PR_NewTCPSocketPair failed\n"); exit(1); } status = PR_SetFDInheritable(sock[0], PR_FALSE); if (status == PR_FAILURE) { fprintf(stderr, "PR_SetFDInheritable failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } status = PR_SetFDInheritable(sock[1], PR_TRUE); if (status == PR_FAILURE) { fprintf(stderr, "PR_SetFDInheritable failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } attr = PR_NewProcessAttr(); if (attr == NULL) { fprintf(stderr, "PR_NewProcessAttr failed\n"); exit(1); } status = PR_ProcessAttrSetInheritableFD(attr, sock[1], "SOCKET"); if (status == PR_FAILURE) { fprintf(stderr, "PR_ProcessAttrSetInheritableFD failed\n"); exit(1); } process = PR_CreateProcess(child_argv[0], child_argv, NULL, attr); if (process == NULL) { fprintf(stderr, "PR_CreateProcess failed\n"); exit(1); } PR_DestroyProcessAttr(attr); status = PR_Close(sock[1]); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } for (idx = 0; idx < NUM_ITERATIONS; idx++) { strcpy(buf, "ping"); printf("ping process: sending \"%s\"\n", buf); nBytes = PR_Write(sock[0], buf, 5); if (nBytes == -1) { fprintf(stderr, "PR_Write failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } memset(buf, 0, sizeof(buf)); nBytes = PR_Read(sock[0], buf, sizeof(buf)); if (nBytes == -1) { fprintf(stderr, "PR_Read failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } printf("ping process: received \"%s\"\n", buf); if (nBytes != 5) { fprintf(stderr, "ping process: expected 5 bytes but got %d bytes\n", nBytes); exit(1); } if (strcmp(buf, "pong") != 0) { fprintf(stderr, "ping process: expected \"pong\" but got \"%s\"\n", buf); exit(1); } } status = PR_Close(sock[0]); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } status = PR_WaitProcess(process, &exitCode); if (status == PR_FAILURE) { fprintf(stderr, "PR_WaitProcess failed\n"); exit(1); } if (exitCode == 0) { printf("PASS\n"); return 0; } else { printf("FAIL\n"); return 1; } }
static nsresult vboxsvcSpawnDaemon(void) { PRFileDesc *readable = nsnull, *writable = nsnull; PRProcessAttr *attr = nsnull; nsresult rv = NS_ERROR_FAILURE; PRFileDesc *devNull; // The ugly casts are necessary because the PR_CreateProcessDetached has // a const array of writable strings as a parameter. It won't write. */ char * const args[] = { (char *)VBoxSVCPath, (char *)"--auto-shutdown", 0 }; // Use a pipe to determine when the daemon process is in the position // to actually process requests. The daemon will write "READY" to the pipe. if (PR_CreatePipe(&readable, &writable) != PR_SUCCESS) goto end; PR_SetFDInheritable(writable, PR_TRUE); attr = PR_NewProcessAttr(); if (!attr) goto end; if (PR_ProcessAttrSetInheritableFD(attr, writable, VBOXSVC_STARTUP_PIPE_NAME) != PR_SUCCESS) goto end; devNull = PR_Open("/dev/null", PR_RDWR, 0); if (!devNull) goto end; PR_ProcessAttrSetStdioRedirect(attr, PR_StandardInput, devNull); PR_ProcessAttrSetStdioRedirect(attr, PR_StandardOutput, devNull); PR_ProcessAttrSetStdioRedirect(attr, PR_StandardError, devNull); if (PR_CreateProcessDetached(VBoxSVCPath, args, nsnull, attr) != PR_SUCCESS) goto end; // Close /dev/null PR_Close(devNull); // Close the child end of the pipe to make it the only owner of the // file descriptor, so that unexpected closing can be detected. PR_Close(writable); writable = nsnull; char msg[10]; RT_ZERO(msg); if ( PR_Read(readable, msg, sizeof(msg)-1) != 5 || strcmp(msg, "READY")) { /* If several clients start VBoxSVC simultaneously only one can * succeed. So treat this as success as well. */ rv = NS_OK; goto end; } rv = NS_OK; end: if (readable) PR_Close(readable); if (writable) PR_Close(writable); if (attr) PR_DestroyProcessAttr(attr); return rv; }
int main(int argc, char **argv) { char * progName = NULL; const char * pidFile = NULL; char * tmp; PRFileDesc * listen_sock; int optionsFound = 0; unsigned short port = 0; SECStatus rv; PRStatus prStatus; PRBool bindOnly = PR_FALSE; PRBool useLocalThreads = PR_FALSE; PLOptState *optstate; PLOptStatus status; tmp = strrchr(argv[0], '/'); tmp = tmp ? tmp + 1 : argv[0]; progName = strrchr(tmp, '\\'); progName = progName ? progName + 1 : tmp; PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); /* please keep this list of options in ASCII collating sequence. ** numbers, then capital letters, then lower case, alphabetical. */ optstate = PL_CreateOptState(argc, argv, "Dbhi:p:t:v"); while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { ++optionsFound; switch(optstate->option) { case 'D': noDelay = PR_TRUE; break; case 'b': bindOnly = PR_TRUE; break; case 'h': Usage(progName); exit(0); break; case 'i': pidFile = optstate->value; break; case 'p': port = PORT_Atoi(optstate->value); break; case 't': maxThreads = PORT_Atoi(optstate->value); if ( maxThreads > MAX_THREADS ) maxThreads = MAX_THREADS; if ( maxThreads < MIN_THREADS ) maxThreads = MIN_THREADS; break; case 'v': verbose++; break; default: case '?': fprintf(stderr, "Unrecognized or bad option specified.\n"); fprintf(stderr, "Run '%s -h' for usage information.\n", progName); exit(4); break; } } PL_DestroyOptState(optstate); if (status == PL_OPT_BAD) { fprintf(stderr, "Unrecognized or bad option specified.\n"); fprintf(stderr, "Run '%s -h' for usage information.\n", progName); exit(5); } if (!optionsFound) { Usage(progName); exit(51); } /* The -b (bindOnly) option is only used by the ssl.sh test * script on Linux to determine whether a previous selfserv * process has fully died and freed the port. (Bug 129701) */ if (bindOnly) { listen_sock = getBoundListenSocket(port); if (!listen_sock) { exit(1); } if (listen_sock) { PR_Close(listen_sock); } exit(0); } if (port == 0) { fprintf(stderr, "Required argument 'port' must be non-zero value\n"); exit(7); } if (pidFile) { FILE *tmpfile=fopen(pidFile,"w+"); if (tmpfile) { fprintf(tmpfile,"%d",getpid()); fclose(tmpfile); } } tmp = getenv("TMP"); if (!tmp) tmp = getenv("TMPDIR"); if (!tmp) tmp = getenv("TEMP"); /* we're an ordinary single process server. */ listen_sock = getBoundListenSocket(port); prStatus = PR_SetFDInheritable(listen_sock, PR_FALSE); if (prStatus != PR_SUCCESS) errExit("PR_SetFDInheritable"); lm = PR_NewLogModule("TestCase"); /* allocate the array of thread slots, and launch the worker threads. */ rv = launch_threads(&jobLoop, 0, 0, 0, useLocalThreads); if (rv == SECSuccess) { server_main(listen_sock, 0, 0, 0, 0); } VLOG(("selfserv: server_thread: exiting")); if (failedToNegotiateName) { fprintf(stderr, "selfserv: Failed properly negotiate server name\n"); exit(1); } PR_Cleanup(); printf("selfserv: normal termination\n"); return 0; }
nsresult sbProcess::Run() { PRStatus status; nsresult rv; // Set up to auto-kill process. sbAutoKillProcess autoSelf(this); // Operate under the process lock. { NS_ENSURE_TRUE(mProcessLock, NS_ERROR_NOT_INITIALIZED); nsAutoLock autoProcessLock(mProcessLock); // Get the number of arguments. PRUint32 argCount = mArgList.Length(); NS_ENSURE_TRUE(argCount > 0, NS_ERROR_ILLEGAL_VALUE); // Convert the UTF-16 argument list to a UTF-8 argument list. nsTArray<nsCString> argListUTF8; for (PRUint32 i = 0; i < argCount; i++) { NS_ENSURE_TRUE(argListUTF8.AppendElement (NS_ConvertUTF16toUTF8(mArgList[i])), NS_ERROR_OUT_OF_MEMORY); } // Allocate a null-terminated char* argument list and set it up for // auto-disposal. char** argList = reinterpret_cast<char**> (NS_Alloc((argCount + 1) * sizeof(char*))); NS_ENSURE_TRUE(argList, NS_ERROR_OUT_OF_MEMORY); sbAutoNSTypePtr<char*> autoArgList(argList); // Convert the argument list to a null-terminated char* argument list. for (PRUint32 i = 0; i < argCount; i++) { argList[i] = const_cast<char*>(argListUTF8[i].get()); } argList[argCount] = NULL; // Set up the process attributes and set them up for auto-disposal. PRProcessAttr* processAttr = PR_NewProcessAttr(); NS_ENSURE_TRUE(processAttr, NS_ERROR_FAILURE); sbAutoPRProcessAttr autoProcessAttr(processAttr); // Set up process stdin. if (mPipeStdinString) { // Create a process stdin pipe and set it up for auto-disposal. PRFileDesc* stdinReadFD; PRFileDesc* stdinWriteFD; status = PR_CreatePipe(&stdinReadFD, &stdinWriteFD); NS_ENSURE_TRUE(status == PR_SUCCESS, NS_ERROR_FAILURE); sbAutoPRFileDesc autoStdinReadFD(stdinReadFD); sbAutoPRFileDesc autoStdinWriteFD(stdinWriteFD); // Set up stdin pipe file descriptors. status = PR_SetFDInheritable(stdinReadFD, PR_TRUE); NS_ENSURE_TRUE(status == PR_SUCCESS, NS_ERROR_FAILURE); status = PR_SetFDInheritable(stdinWriteFD, PR_FALSE); NS_ENSURE_TRUE(status == PR_SUCCESS, NS_ERROR_FAILURE); // Fill pipe. nsCAutoString writeData = NS_ConvertUTF16toUTF8(mStdinString); PRInt32 bytesWritten; bytesWritten = PR_Write(stdinWriteFD, writeData.get(), writeData.Length()); NS_ENSURE_TRUE(bytesWritten == writeData.Length(), NS_ERROR_FAILURE); // Redirect process stdin. PR_ProcessAttrSetStdioRedirect(processAttr, PR_StandardInput, stdinReadFD); // Keep stdin read descriptor open for the process to read. Close the // stdin write descriptor so that the process gets EOF when all of the // data is read. mStdinReadFD = autoStdinReadFD.forget(); PR_Close(autoStdinWriteFD.forget()); } // Set up process stdout. if (mPipeStdoutString) { // Create a process stdout pipe and set it up for auto-disposal. PRFileDesc* stdoutReadFD; PRFileDesc* stdoutWriteFD; status = PR_CreatePipe(&stdoutReadFD, &stdoutWriteFD); NS_ENSURE_TRUE(status == PR_SUCCESS, NS_ERROR_FAILURE); sbAutoPRFileDesc autoStdoutReadFD(stdoutReadFD); sbAutoPRFileDesc autoStdoutWriteFD(stdoutWriteFD); // Set up stdout pipe file descriptors. status = PR_SetFDInheritable(stdoutReadFD, PR_FALSE); NS_ENSURE_TRUE(status == PR_SUCCESS, NS_ERROR_FAILURE); status = PR_SetFDInheritable(stdoutWriteFD, PR_TRUE); NS_ENSURE_TRUE(status == PR_SUCCESS, NS_ERROR_FAILURE); // Redirect process stdout. PR_ProcessAttrSetStdioRedirect(processAttr, PR_StandardOutput, stdoutWriteFD); // Keep descriptors. mStdoutReadFD = autoStdoutReadFD.forget(); mStdoutWriteFD = autoStdoutWriteFD.forget(); } // Create and start running the process. mBaseProcess = PR_CreateProcess(argList[0], argList, NULL, processAttr); NS_ENSURE_TRUE(mBaseProcess, NS_ERROR_FAILURE); // Wait for process done on another thread. nsCOMPtr<nsIRunnable> runnable = NS_NEW_RUNNABLE_METHOD(sbProcess, this, WaitForDone); NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); rv = NS_NewThread(getter_AddRefs(mWaitForDoneThread), runnable); NS_ENSURE_SUCCESS(rv, rv); } // Clear process auto-kill. autoSelf.forget(); return NS_OK; }