static int Sclose_process(void *handle) { process_context *pc; int fd = process_fd(handle, &pc); if ( fd >= 0 ) { int which = (int)(uintptr_t)handle & 0x3; int rc; rc = (*Sfilefunctions.close)((void*)(uintptr_t)fd); pc->open_mask &= ~(1<<which); DEBUG(Sdprintf("Closing fd[%d]; mask = 0x%x\n", which, pc->open_mask)); if ( !pc->open_mask ) { int rcw = wait_for_process(pc); return rcw ? 0 : -1; } return rc; } return -1; }
int wmain(int argc, wchar_t* argv[]) { void* proc2; start_redirection_server(); if (argc==1) { do_mainA(); proc2 = create_process(do_mainB, "B", "rw", fids); if (proc2) start_process(proc2); else perror("Failed to start processB: "); if (proc2) { int exit; do_piping(); exit=wait_for_process(proc2); printf("wait_for_process returned %d\r\n", exit); } } else { do_mainB(); } return 0; }
int exec_kid1(FILE *in, FILE *out, void *user_arg) { int kid2; FILE *kid2out; int status; const char *fileconv = ((kid1_userdata_t *)user_arg)->fileconv; const char *alreadyread = ((kid1_userdata_t *)user_arg)->alreadyread; kid2 = start_process("kid2", exec_kid2, (void *)alreadyread, NULL, &kid2out); if (kid2 < 0) return EXIT_PRNERR_NORETRY_BAD_SETTINGS; if (spooler != SPOOLER_CUPS) _log("file converter command: %s\n", fileconv); if (dup2(fileno(kid2out), fileno(stdin)) < 0) { _log("kid1: Could not dup stdin\n"); fclose(kid2out); return EXIT_PRNERR_NORETRY_BAD_SETTINGS; } if (dup2(fileno(out), fileno(stdout)) < 0) { _log("kid1: Could not dup stdout\n"); fclose(kid2out); return EXIT_PRNERR_NORETRY_BAD_SETTINGS; } if (debug && !redirect_log_to_stderr()) { _log("Could not dup logh to stderr\n"); fclose(kid2out); return EXIT_PRNERR_NORETRY_BAD_SETTINGS; } /* Actually run the thing... */ status = run_system_process("fileconverter", fileconv); fclose(out); fclose(kid2out); fclose(stdin); fclose(stdout); if (WIFEXITED(status)) { if (WEXITSTATUS(status) == 0) { wait_for_process(kid2); _log("kid1 finished\n"); return EXIT_PRINTED; } } else if (WIFSIGNALED(status)) { switch (WTERMSIG(status)) { case SIGUSR1: return EXIT_PRNERR; case SIGUSR2: return EXIT_PRNERR_NORETRY; case SIGTTIN: return EXIT_ENGAGED; } } return EXIT_PRNERR; }
int close_fileconverter_handle(FILE *fileconverter_handle, pid_t fileconverter_pid) { int status; _log("\nClosing file converter\n"); fclose(fileconverter_handle); status = wait_for_process(fileconverter_pid); if (WIFEXITED(status)) return WEXITSTATUS(status); else return EXIT_PRNERR_NORETRY_BAD_SETTINGS; }
int shell( int argc, char *argv[] ) { init_shell(); // initialize the shell pid_t pid = getpid(); // get current processe's PID pid_t ppid = getppid(); // get parent's PID pid_t cpid, tcpid, cpgid; print_welcome( argv[0], pid, ppid ); print_prompt(); char *s = malloc(INPUT_STRING_SIZE + 1); // user input string while( (s = freadln(stdin)) ){ // read in the input string process *p = create_process( s ); if( p != NULL ){ // do we need to run a newly created process? cpid = fork(); // fork off a child if( cpid == 0 ) { // child p->pid = getpid(); launch_process( p ); } // if( cpid == 0 ) else if( cpid > 0 ){ // parent p->pid = cpid; if( shell_is_interactive ){ // are we running shell from a terminal? // put 'p' into its own process group // since our shell is not supporting pipes, we treat // each process by itself as a 'job' to be done if( setpgid( cpid, cpid ) < 0 ) printf( "Failed to put the child into its own process group.\n" ); if( p->background ) put_in_background( p, false ); else put_in_foreground( p, false ); } // if( shell_is_interactive ) else wait_for_process( p ); } // else if( cpid > 0 ) else // fork() failed printf( "fork() failed\n" ); } // if( p != NULL ) print_prompt(); } // while return EXIT_SUCCESS; } // shell
static int spawn_and_wait(int argc, char **argv) { int rv = EX_SOFTWARE; pid_t pid = fork(); assert(argc > 1); switch (pid) { case -1: perror("fork"); rv = EX_OSERR; break; /* NOTREACHED */ case 0: execvp(argv[0], argv); perror("exec"); rv = EX_SOFTWARE; break; /* NOTREACHED */ default: rv = wait_for_process(pid); } return rv; }
static int external_passwd_quality (krb5_context context, krb5_principal principal, krb5_data *pwd, const char *opaque, char *message, size_t length) { krb5_error_code ret; const char *program; char *p; pid_t child; int status; char reply[1024]; FILE *in = NULL, *out = NULL, *error = NULL; if (memchr(pwd->data, '\n', pwd->length) != NULL) { snprintf(message, length, "password contains newline, " "not valid for external test"); return 1; } program = krb5_config_get_string(context, NULL, "password_quality", "external_program", NULL); if (program == NULL) { snprintf(message, length, "external password quality " "program not configured"); return 1; } ret = krb5_unparse_name(context, principal, &p); if (ret) { strlcpy(message, "out of memory", length); return 1; } child = pipe_execv(&in, &out, &error, program, program, p, NULL); if (child < 0) { snprintf(message, length, "external password quality " "program failed to execute for principal %s", p); free(p); return 1; } fprintf(in, "principal: %s\n" "new-password: %.*s\n" "end\n", p, (int)pwd->length, (char *)pwd->data); fclose(in); if (fgets(reply, sizeof(reply), out) == NULL) { if (fgets(reply, sizeof(reply), error) == NULL) { snprintf(message, length, "external password quality " "program failed without error"); } else { reply[strcspn(reply, "\n")] = '\0'; snprintf(message, length, "External password quality " "program failed: %s", reply); } fclose(out); fclose(error); wait_for_process(child); return 1; } reply[strcspn(reply, "\n")] = '\0'; fclose(out); fclose(error); status = wait_for_process(child); if (SE_IS_ERROR(status) || SE_PROCSTATUS(status) != 0) { snprintf(message, length, "external program failed: %s", reply); free(p); return 1; } if (strcmp(reply, "APPROVED") != 0) { snprintf(message, length, "%s", reply); free(p); return 1; } free(p); return 0; }
int exec_program_v(const char *working_directory, struct strbuf *output, struct strbuf *error_output, int flags, const char **argv) { int fdout[2], fderr[2]; int s1 = -1, s2 = -1; /* backups of stdin, stdout, stderr */ pid_t pid; int status = 0; int ret; struct strbuf strout = STRBUF_INIT, strerr = STRBUF_INIT; if (!output) output = &strout; if (!error_output) error_output = &strerr; reporter *debug = QUIETMODE & flags ? _debug_git : _debug_git_mbox; if (!git_path()) { debug("[ERROR] Could not find git path"); return -1; } if (pipe(fdout) < 0) { return -ERR_RUN_COMMAND_PIPE; } s1 = dup(1); dup2(fdout[1], 1); flags |= WAITMODE; if (pipe(fderr) < 0) { if (output) close_pair(fdout); return -ERR_RUN_COMMAND_PIPE; } s2 = dup(2); dup2(fderr[1], 2); flags |= WAITMODE; pid = fork_process(argv[0], argv, working_directory); if (s1 >= 0) dup2(s1, 1), close(s1); if (s2 >= 0) dup2(s2, 2), close(s2); if (pid < 0) { close_pair(fdout); close_pair(fderr); return -ERR_RUN_COMMAND_FORK; } close(fdout[1]); close(fderr[1]); if (WAITMODE & flags) { ret = wait_for_process(pid, MAX_PROCESSING_TIME, &status); if (ret) { if (ret < 0) { debug_git("[ERROR] wait_for_process failed (%d); " "wd: %s; cmd: %s", status, working_directory, argv[0]); status = -1; } strbuf_read(output, fdout[0], 0); debug_git("STDOUT:\r\n%s\r\n*** end of STDOUT ***\r\n", output->buf); strbuf_read(error_output, fderr[0], 0); debug_git("STDERR:\r\n%s\r\n*** end of STDERR ***\r\n", error_output->buf); } else { status = -ERR_RUN_COMMAND_WAITPID_NOEXIT; debug_git("[ERROR] process timed out; " "wd: %s; cmd: %s", working_directory, argv[0]); } } close_process(pid); close(fdout[0]); close(fderr[0]); strbuf_release(&strerr); strbuf_release(&strout); return status; }
static bool decrypt(const char *privkeyfile, const char *keyfile, const char *input, const char *output) { uint8_t buf[KERNELDUMP_BUFFER_SIZE], key[KERNELDUMP_KEY_MAX_SIZE]; EVP_CIPHER_CTX ctx; const EVP_CIPHER *cipher; FILE *fp; struct kerneldumpkey *kdk; RSA *privkey; int ifd, kfd, ofd, olen, privkeysize; ssize_t bytes; pid_t pid; PJDLOG_ASSERT(privkeyfile != NULL); PJDLOG_ASSERT(keyfile != NULL); PJDLOG_ASSERT(input != NULL); PJDLOG_ASSERT(output != NULL); privkey = NULL; /* * Decrypt a core dump in a child process so we can unlink a partially * decrypted core if the child process fails. */ pid = fork(); if (pid == -1) { pjdlog_errno(LOG_ERR, "Unable to create child process"); return (false); } if (pid > 0) return (wait_for_process(pid) == 0); kfd = open(keyfile, O_RDONLY); if (kfd == -1) { pjdlog_errno(LOG_ERR, "Unable to open %s", keyfile); goto failed; } ifd = open(input, O_RDONLY); if (ifd == -1) { pjdlog_errno(LOG_ERR, "Unable to open %s", input); goto failed; } ofd = open(output, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (ofd == -1) { pjdlog_errno(LOG_ERR, "Unable to open %s", output); goto failed; } fp = fopen(privkeyfile, "r"); if (fp == NULL) { pjdlog_errno(LOG_ERR, "Unable to open %s", privkeyfile); goto failed; } if (cap_enter() < 0 && errno != ENOSYS) { pjdlog_errno(LOG_ERR, "Unable to enter capability mode"); goto failed; } privkey = RSA_new(); if (privkey == NULL) { pjdlog_error("Unable to allocate an RSA structure: %s", ERR_error_string(ERR_get_error(), NULL)); goto failed; } EVP_CIPHER_CTX_init(&ctx); kdk = read_key(kfd); close(kfd); if (kdk == NULL) goto failed; privkey = PEM_read_RSAPrivateKey(fp, &privkey, NULL, NULL); fclose(fp); if (privkey == NULL) { pjdlog_error("Unable to read data from %s.", privkeyfile); goto failed; } privkeysize = RSA_size(privkey); if (privkeysize != (int)kdk->kdk_encryptedkeysize) { pjdlog_error("RSA modulus size mismatch: equals %db and should be %ub.", 8 * privkeysize, 8 * kdk->kdk_encryptedkeysize); goto failed; } switch (kdk->kdk_encryption) { case KERNELDUMP_ENC_AES_256_CBC: cipher = EVP_aes_256_cbc(); break; default: pjdlog_error("Invalid encryption algorithm."); goto failed; } if (RSA_private_decrypt(kdk->kdk_encryptedkeysize, kdk->kdk_encryptedkey, key, privkey, RSA_PKCS1_PADDING) != sizeof(key)) { pjdlog_error("Unable to decrypt key: %s", ERR_error_string(ERR_get_error(), NULL)); goto failed; } RSA_free(privkey); privkey = NULL; EVP_DecryptInit_ex(&ctx, cipher, NULL, key, kdk->kdk_iv); EVP_CIPHER_CTX_set_padding(&ctx, 0); explicit_bzero(key, sizeof(key)); do { bytes = read(ifd, buf, sizeof(buf)); if (bytes < 0) { pjdlog_errno(LOG_ERR, "Unable to read data from %s", input); goto failed; } else if (bytes == 0) { break; } if (bytes > 0) { if (EVP_DecryptUpdate(&ctx, buf, &olen, buf, bytes) == 0) { pjdlog_error("Unable to decrypt core."); goto failed; } } else { if (EVP_DecryptFinal_ex(&ctx, buf, &olen) == 0) { pjdlog_error("Unable to decrypt core."); goto failed; } } if (olen == 0) continue; if (write(ofd, buf, olen) != olen) { pjdlog_errno(LOG_ERR, "Unable to write data to %s", output); goto failed; } } while (bytes > 0); explicit_bzero(buf, sizeof(buf)); EVP_CIPHER_CTX_cleanup(&ctx); exit(0); failed: explicit_bzero(key, sizeof(key)); explicit_bzero(buf, sizeof(buf)); RSA_free(privkey); EVP_CIPHER_CTX_cleanup(&ctx); exit(1); }
int run_system_process(const char *name, const char *command) { int pid = start_system_process(name, command, NULL, NULL); return wait_for_process(pid); }
ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL roken_detach_prep(int argc, char **argv, char *special_arg) { pid_t child; char buf[1]; ssize_t bytes; int status; pipefds[0] = -1; pipefds[1] = -1; #ifdef WIN32 if (_pipe(pipefds, 4, O_BINARY) == -1) err(1, "failed to setup to detach daemon (_pipe failed)"); #else if (pipe(pipefds) == -1) err(1, "failed to setup to detach daemon (pipe failed)"); #endif #ifndef WIN32 fflush(stdout); child = fork(); #else { intptr_t child_handle; int write_side; size_t i; char *fildes; char **new_argv; new_argv = calloc(argc + 2, sizeof(*new_argv)); if (new_argv == NULL) err(1, "Out of memory"); write_side = _dup(pipefds[1]); /* The new fd will be inherited */ if (write_side == -1) err(1, "Out of memory"); if (asprintf(&fildes, "%d", write_side) == -1 || fildes == NULL) err(1, "failed to setup to detach daemon (_dup failed)"); new_argv[0] = argv[0]; new_argv[1] = special_arg; new_argv[2] = fildes; for (i = 1; argv[i] != NULL; i++) new_argv[i + 1] = argv[i]; new_argv[argc + 2] = NULL; _flushall(); child_handle = spawnvp(_P_NOWAIT, argv[0], new_argv); if (child_handle == -1) child = (pid_t)-1; else child = GetProcessId((HANDLE)child_handle); } #endif if (child == (pid_t)-1) err(1, "failed to setup to fork daemon (fork failed)"); #ifndef WIN32 if (child == 0) { int fd; (void) close(pipefds[0]); pipefds[0] = -1; /* * Keep stdout/stderr for now so output and errors prior to * detach_finish() can be seen by the user. */ fd = open(_PATH_DEVNULL, O_RDWR, 0); if (fd == -1) err(1, "failed to open /dev/null"); (void) dup2(fd, STDIN_FILENO); if (fd > STDERR_FILENO) (void) close(fd); return; } #endif (void) close(pipefds[1]); pipefds[1] = -1; do { bytes = read(pipefds[0], buf, sizeof(buf)); } while (bytes == -1 && errno == EINTR); (void) close(pipefds[0]); pipefds[0] = -1; if (bytes == -1) { /* * No need to wait for the process. We've killed it. If it * doesn't want to exit, we'd have to wait potentially forever, * but we want to indicate failure to the user as soon as * possible. A wait with timeout would end the same way * (attempting to kill the process). */ err(1, "failed to setup daemon child (read from child pipe)"); } if (bytes == 0) { warnx("daemon child preparation failed, waiting for child"); status = wait_for_process(child); if (SE_IS_ERROR(status) || SE_PROCSTATUS(status) != 0) errx(SE_PROCSTATUS(status), "daemon child preparation failed (child exited)"); } _exit(0); }