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 void ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsILocalFile *statusFile, nsIFile *appDir, int appArgc, char **appArgv) { nsresult rv; // Steps: // - mark update as 'applying' // - copy updater into update dir // - run updater w/ appDir as the current working dir nsCOMPtr<nsIFile> updater; if (!CopyUpdaterIntoUpdateDir(greDir, appDir, updateDir, updater)) { LOG(("failed copying updater\n")); return; } // We need to use the value returned from XRE_GetBinaryPath when attempting // to restart the running application. nsCOMPtr<nsILocalFile> appFile; #if defined(XP_MACOSX) // On OS X we need to pass the location of the xulrunner-stub executable // rather than xulrunner-bin. See bug 349737. GetXULRunnerStubPath(appArgv[0], getter_AddRefs(appFile)); #else XRE_GetBinaryPath(appArgv[0], getter_AddRefs(appFile)); #endif if (!appFile) return; #ifdef XP_WIN nsAutoString appFilePathW; rv = appFile->GetPath(appFilePathW); if (NS_FAILED(rv)) return; NS_ConvertUTF16toUTF8 appFilePath(appFilePathW); nsAutoString updaterPathW; rv = updater->GetPath(updaterPathW); if (NS_FAILED(rv)) return; NS_ConvertUTF16toUTF8 updaterPath(updaterPathW); #else nsCAutoString appFilePath; rv = appFile->GetNativePath(appFilePath); if (NS_FAILED(rv)) return; nsCAutoString updaterPath; rv = updater->GetNativePath(updaterPath); if (NS_FAILED(rv)) return; #endif // Get the directory to which the update will be applied. On Mac OSX we need // to apply the update to the Foo.app directory which is the parent of the // parent of the appDir. On other platforms we will just apply to the appDir. #if defined(XP_MACOSX) nsCAutoString applyToDir; { nsCOMPtr<nsIFile> parentDir1, parentDir2; rv = appDir->GetParent(getter_AddRefs(parentDir1)); if (NS_FAILED(rv)) return; rv = parentDir1->GetParent(getter_AddRefs(parentDir2)); if (NS_FAILED(rv)) return; rv = parentDir2->GetNativePath(applyToDir); } #elif defined(XP_WIN) nsAutoString applyToDir; rv = appDir->GetPath(applyToDir); #else nsCAutoString applyToDir; rv = appDir->GetNativePath(applyToDir); #endif if (NS_FAILED(rv)) return; #if defined(XP_WIN) nsAutoString updateDirPathW; rv = updateDir->GetPath(updateDirPathW); NS_ConvertUTF16toUTF8 updateDirPath(updateDirPathW); #else nsCAutoString updateDirPath; rv = updateDir->GetNativePath(updateDirPath); #endif if (NS_FAILED(rv)) return; // Get the current working directory. char workingDirPath[MAXPATHLEN]; rv = GetCurrentWorkingDir(workingDirPath, sizeof(workingDirPath)); if (NS_FAILED(rv)) return; if (!SetStatus(statusFile, "applying")) { LOG(("failed setting status to 'applying'\n")); return; } // Construct the PID argument for this process. If we are using execv, then // we pass "0" which is then ignored by the updater. #if defined(USE_EXECV) NS_NAMED_LITERAL_CSTRING(pid, "0"); #else nsCAutoString pid; pid.AppendInt((PRInt32) getpid()); #endif int argc = appArgc + 4; char **argv = new char*[argc + 1]; if (!argv) return; argv[0] = (char*) updaterPath.get(); argv[1] = (char*) updateDirPath.get(); argv[2] = (char*) pid.get(); if (appArgc) { argv[3] = workingDirPath; argv[4] = (char*) appFilePath.get(); for (int i = 1; i < appArgc; ++i) argv[4 + i] = appArgv[i]; argv[4 + appArgc] = nsnull; } else { argv[3] = nsnull; argc = 3; } LOG(("spawning updater process [%s]\n", updaterPath.get())); #if defined(USE_EXECV) chdir(applyToDir.get()); execv(updaterPath.get(), argv); #elif defined(XP_WIN) _wchdir(applyToDir.get()); if (!WinLaunchChild(updaterPathW.get(), appArgc + 4, argv)) return; _exit(0); #else PRStatus status; PRProcessAttr *attr; attr = PR_NewProcessAttr(); if (!attr) goto end; status = PR_ProcessAttrSetCurrentDirectory(attr, applyToDir.get()); if (status != PR_SUCCESS) goto end; #ifdef XP_MACOSX CommandLineServiceMac::SetupMacCommandLine(argc, argv, PR_TRUE); #endif PR_CreateProcessDetached(updaterPath.get(), argv, nsnull, attr); exit(0); end: PR_DestroyProcessAttr(attr); delete[] argv; #endif }
/* ///////////////////////////////////////////////////////////////////////// // actually run the installation, copying files to and fro */ static Pk11Install_Error DoInstall(JAR *jar, const char *installDir, const char *tempDir, Pk11Install_Platform *platform, PRFileDesc *feedback, PRBool noverify) { Pk11Install_File *file; Pk11Install_Error ret; char *reldir; char *dest; char *modDest; char *cp; int i; int status; char *tempname, *temp; StringList executables; StringNode *execNode; PRProcessAttr *attr; PRProcess *proc; char *argv[2]; char *envp[1]; int errcode; ret = PK11_INSTALL_UNSPECIFIED; reldir = NULL; dest = NULL; modDest = NULL; tempname = NULL; StringList_new(&executables); /* // Create Temporary directory */ tempname = PR_smprintf("%s/%s", tempDir, TEMPORARY_DIRECTORY_NAME); if (PR_Access(tempname, PR_ACCESS_EXISTS) == PR_SUCCESS) { /* Left over from previous run? Delete it. */ rm_dash_r(tempname); } if (PR_MkDir(tempname, 0700) != PR_SUCCESS) { error(PK11_INSTALL_CREATE_DIR, tempname); ret = PK11_INSTALL_CREATE_DIR; goto loser; } /* // Install all the files */ for (i = 0; i < platform->numFiles; i++) { file = &platform->files[i]; if (file->relativePath) { PRBool foundMarker = PR_FALSE; reldir = PR_Strdup(file->relativePath); /* Replace all the markers with the directories for which they stand */ while (1) { if ((cp = PL_strcasestr(reldir, ROOT_MARKER))) { /* Has a %root% marker */ *cp = '\0'; temp = PR_smprintf("%s%s%s", reldir, installDir, cp + strlen(ROOT_MARKER)); PR_Free(reldir); reldir = temp; foundMarker = PR_TRUE; } else if ((cp = PL_strcasestr(reldir, TEMP_MARKER))) { /* Has a %temp% marker */ *cp = '\0'; temp = PR_smprintf("%s%s%s", reldir, tempname, cp + strlen(TEMP_MARKER)); PR_Free(reldir); reldir = temp; foundMarker = PR_TRUE; } else { break; } } if (!foundMarker) { /* Has no markers...this isn't really a relative directory */ error(PK11_INSTALL_BOGUS_REL_DIR, file->relativePath); ret = PK11_INSTALL_BOGUS_REL_DIR; goto loser; } dest = reldir; reldir = NULL; } else if (file->absolutePath) { dest = PR_Strdup(file->absolutePath); } /* Remember if this is the module file, we'll need to add it later */ if (i == platform->modFile) { modDest = PR_Strdup(dest); } /* Remember is this is an executable, we'll need to run it later */ if (file->executable) { StringList_Append(&executables, dest); /*executables.Append(dest);*/ } /* Make sure the directory we are targetting exists */ if (make_dirs(dest, file->permissions)) { ret = PK11_INSTALL_CREATE_DIR; goto loser; } /* Actually extract the file onto the filesystem */ if (noverify) { status = JAR_extract(jar, (char *)file->jarPath, dest); } else { status = JAR_verified_extract(jar, (char *)file->jarPath, dest); } if (status) { if (status >= JAR_BASE && status <= JAR_BASE_END) { error(PK11_INSTALL_JAR_EXTRACT, file->jarPath, JAR_get_error(status)); } else { error(PK11_INSTALL_JAR_EXTRACT, file->jarPath, mySECU_ErrorString(PORT_GetError())); } ret = PK11_INSTALL_JAR_EXTRACT; goto loser; } if (feedback) { PR_fprintf(feedback, msgStrings[INSTALLED_FILE_MSG], file->jarPath, dest); } /* no NSPR command to change permissions? */ #ifdef XP_UNIX chmod(dest, file->permissions); #endif /* Memory clean-up tasks */ if (reldir) { PR_Free(reldir); reldir = NULL; } if (dest) { PR_Free(dest); dest = NULL; } } /* Make sure we found the module file */ if (!modDest) { /* Internal problem here, since every platform is supposed to have a module file */ error(PK11_INSTALL_NO_MOD_FILE, platform->moduleName); ret = PK11_INSTALL_NO_MOD_FILE; goto loser; } /* // Execute any executable files */ { argv[1] = NULL; envp[0] = NULL; for (execNode = executables.head; execNode; execNode = execNode->next) { attr = PR_NewProcessAttr(); argv[0] = PR_Strdup(execNode->str); /* Announce our intentions */ if (feedback) { PR_fprintf(feedback, msgStrings[EXEC_FILE_MSG], execNode->str); } /* start the process */ if (!(proc = PR_CreateProcess(execNode->str, argv, envp, attr))) { PR_Free(argv[0]); PR_DestroyProcessAttr(attr); error(PK11_INSTALL_EXEC_FILE, execNode->str); ret = PK11_INSTALL_EXEC_FILE; goto loser; } /* wait for it to finish */ if (PR_WaitProcess(proc, &errcode) != PR_SUCCESS) { PR_Free(argv[0]); PR_DestroyProcessAttr(attr); error(PK11_INSTALL_WAIT_PROCESS, execNode->str); ret = PK11_INSTALL_WAIT_PROCESS; goto loser; } /* What happened? */ if (errcode) { /* process returned an error */ error(PK11_INSTALL_PROC_ERROR, execNode->str, errcode); } else if (feedback) { /* process ran successfully */ PR_fprintf(feedback, msgStrings[EXEC_SUCCESS], execNode->str); } PR_Free(argv[0]); PR_DestroyProcessAttr(attr); } } /* // Add the module */ status = Pk11Install_AddNewModule((char *)platform->moduleName, (char *)modDest, platform->mechFlags, platform->cipherFlags); if (status != SECSuccess) { error(PK11_INSTALL_ADD_MODULE, platform->moduleName); ret = PK11_INSTALL_ADD_MODULE; goto loser; } if (feedback) { PR_fprintf(feedback, msgStrings[INSTALLED_MODULE_MSG], platform->moduleName); } if (feedback) { PR_fprintf(feedback, msgStrings[INSTALLATION_COMPLETE_MSG]); } ret = PK11_INSTALL_SUCCESS; loser: if (reldir) { PR_Free(reldir); } if (dest) { PR_Free(dest); } if (modDest) { PR_Free(modDest); } if (tempname) { PRFileInfo info; if (PR_GetFileInfo(tempname, &info) == PR_SUCCESS) { if (info.type == PR_FILE_DIRECTORY) { /* Recursively remove temporary directory */ if (rm_dash_r(tempname)) { error(PK11_INSTALL_REMOVE_DIR, tempname); ret = PK11_INSTALL_REMOVE_DIR; } } } PR_Free(tempname); } StringList_delete(&executables); return ret; }
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[]) { PRStatus status; // launch daemon printf("### launch daemon...\n"); PRProcessAttr *attributes = PR_NewProcessAttr(); if (attributes == nsnull) { printf("PR_NewProcessAttr() failed.\n"); return -1; } PRProcess *daemon = PR_CreateProcess("nsDnsAsyncLookup", nsnull, nsnull, attributes); if (daemon == nsnull) { printf("PR_CreateProcess failed.\n"); } else { // status = PR_DetachProcess(daemon); //if (status != 0) // printf("PR_DetachProcess returned %d\n", status); //daemon = nsnull; } PR_DestroyProcessAttr(attributes); // create socket and connect to daemon int socket_fd = 0; bool notDone = true; char buf[1024]; while(notDone) { int status = 0; fd_set fdset; FD_ZERO(&fdset); FD_SET(fileno(stdin), &fdset); if (socket_fd > 0) FD_SET(socket_fd, &fdset); status = select(getdtablehi(), &fdset, 0, 0, 0); if (status <= 0) { fprintf(stderr, "%s: select() returned %d\n", argv[0], status); exit(-1); } // which fd is set? if (FD_ISSET(fileno(stdin), &fdset)) { char *line = fgets(buf, sizeof(buf)-1, stdin); line = string_trim(line); if(!strcmp(line, "quit") || !strcmp(line, "exit")) { fprintf(stderr, "bye now.\n"); notDone = false; } else if (!strncmp(line, "abort ", 6)) { // abort id } else if (strchr(line, ' ') || strchr(line, '\t')) { fprintf(stderr, "%s: unrecognized command %s.\n", argv[0], line); } else { fprintf(stderr, "%s: looking up %s...\n", argv[0], line); // initiate dns lookup socket_fd = async_dns_lookup(line); } } if (socket_fd && FD_ISSET(socket_fd, &fdset)) { // read from socket, parse results int size = read(socket_fd, buf, 1024); if (size > 0) { // parse buffer into hostent char *p = buf; fprintf(stderr, "bytes read: %d\n", size); fprintf(stderr, "response code: %d\n", *(int *)p); p += sizeof(int); for (int i=0; i < size; i++) { if (!(i%8)) fprintf(stderr, "\n"); fprintf(stderr, "%2.2x ",(unsigned char)buf[i]); } fprintf(stderr, "\n"); hostent *h; h = bytesToHostent(p); } close(socket_fd); socket_fd = 0; } } return 0; }