int main (void) { int local = 200; int* heap = malloc (sizeof (int)); *heap = 300; printf ("父进程:%d %d %d\n", global, local, *heap); pid_t pid = vfork (); if (pid == -1) { perror ("fork"); return -1; } if (pid == 0) { printf ("子进程:%d %d %d\n", ++global, ++local, ++*heap); // free (heap); // return 0; exit (0); } //sleep (1); printf ("父进程:%d %d %d\n", global, local, *heap); free (heap); return 0; }
/* This does a fork/exec in one call, using vfork(). Returns PID of new child, * -1 for failure. Runs argv[0], searching path if that has no / in it. */ pid_t spawn(char **argv) { /* Compiler should not optimize stores here */ volatile int failed; pid_t pid; // Ain't it a good place to fflush(NULL)? /* Be nice to nommu machines. */ failed = 0; pid = vfork(); if (pid < 0) /* error */ return pid; if (!pid) { /* child */ /* This macro is ok - it doesn't do NOEXEC/NOFORK tricks */ BB_EXECVP(argv[0], argv); /* We are (maybe) sharing a stack with blocked parent, * let parent know we failed and then exit to unblock parent * (but don't run atexit() stuff, which would screw up parent.) */ failed = errno; _exit(111); } /* parent */ /* Unfortunately, this is not reliable: according to standards * vfork() can be equivalent to fork() and we won't see value * of 'failed'. * Interested party can wait on pid and learn exit code. * If 111 - then it (most probably) failed to exec */ if (failed) { errno = failed; return -1; } return pid; }
int main() { int val = 0; pid_t id = vfork(); if(id < 0) { exit(1); } else if(id == 0) //child { atexit(fun); printf("this is child process.\n"); // ++g_val; // ++val; sleep(3); exit(0); } else { printf("this is father process\n"); // printf("father exit, g_val = %d, val = %d\n", g_val, val); } return 0; }
static int pipeencode(char *filename, char *argument, int fdin, int fdout) { int res; int x; #if defined(HAVE_WORKING_FORK) res = fork(); #else res = vfork(); #endif if (res < 0) cw_log(LOG_WARNING, "Fork failed\n"); if (res) return res; dup2(fdin, STDIN_FILENO); dup2(fdout, STDOUT_FILENO); for (x=0;x<256;x++) { if ((x != STDIN_FILENO && x != STDOUT_FILENO) || STDERR_FILENO == x) close(x); } cw_log(LOG_WARNING, "Launching '%s' '%s'\n", filename, argument); execlp(filename, "TEST", argument, (char *)NULL); cw_log(LOG_WARNING, "Execute of %s failed\n", filename); return -1; }
static pid_t path_pfexecve(Shell_t *shp,const char *path, char *argv[],char *const envp[],int spawn) { #if SHOPT_PFSH char resolvedpath[PATH_MAX + 1]; pid_t pid; #endif /*SHOPT_PFSH */ if(shp->vex->cur) { spawnvex_apply(shp->vex,0,0); spawnvex_apply(shp->vexp,0,SPAWN_RESET); } #if SHOPT_PFSH if(spawn) { while((pid = vfork()) < 0) _sh_fork(shp,pid, 0, (int*)0); if(pid) return(pid); } if(!sh_isoption(shp,SH_PFSH)) return(execve(path, argv, envp)); /* Solaris implements realpath(3C) using the resolvepath(2) */ /* system call so we can save us to call access(2) first */ /* we can exec the command directly instead of via pfexec(1) if */ /* there is a matching entry without attributes in exec_attr(4) */ if(!path_xattr(shp,path,resolvedpath)) return(execve(path, argv, envp)); --argv; argv[0] = argv[1]; argv[1] = resolvedpath; return(execve("/usr/bin/pfexec", argv, envp)); #else return(execve(path, argv, envp)); #endif }
int main(int argc, char const *argv[]){ int local = 999; pid_t pid; printf("before vfork\n"); show_status(getpid(), global, local); pid = vfork(); if(pid < 0){ err_sys("vfork error"); }else if (0 == pid){ printf("child process\n"); global += 111; local -= 111; show_status(getpid(), global, local); exit(EXIT_SUCCESS); }else{ printf("parent process\n"); show_status(getpid(), global, local); } exit(EXIT_SUCCESS); }
int* forkn(int n, int *buckets, int *matrix1, int n1, int m1, int *matrix2, int n2, int m2) { pid_t pid; int i, j, l; int current_line = 0; int k = 0; int *result_matrix = (int*)calloc(n1*m2, sizeof(int)); for (i = 0; i < n; i++) { if ((pid = vfork()) < 0) { printf("vfork error"); } else if (pid == 0) { printf("child "); int n_lines = buckets[k]; for (j = 0; j < n_lines; j++) { for (l = 0; l < m2; l++) { result_matrix[ID(m2,current_line,l)] = multiplyLineColumn(matrix1, matrix2, m1, m2, current_line, l); } current_line++; } k++; _exit(0); } } return result_matrix; }
int main() { pid_t pid; int i; pid = vfork(); // pid = fork(); if (pid == 0) { a = 1; for (i = 0; i < 5; i++) { printf("child %d\n", i + 1); sleep(1); } exit (EXIT_SUCCESS); } else { printf("*data %d\n", a); for (i = 0; i < 5; i++) { printf("parent %d\n", i + 1); sleep(1); } exit (EXIT_SUCCESS); } }
int main(int argc, char *argv[]) { switch (vfork()) { case -1: errExit("vfork"); case 0: if (close(STDOUT_FILENO) == -1) errMsg("close - child"); _exit(EXIT_SUCCESS); default: break; } /* Now parent closes STDOUT_FILENO twice: only the second close should fail, indicating that the close(STDOUT_FILENO) by the child did not affect the parent. */ if (close(STDOUT_FILENO) == -1) errMsg("close"); if (close(STDOUT_FILENO) == -1) errMsg("close"); exit(EXIT_SUCCESS); }
int kcinth() { u16 segment, offset; int a,b,c,d, r; segment = running->uss; offset = running->usp; a = get_word(segment, offset + 2*PA); b = get_word(segment, offset + 2*PB); c = get_word(segment, offset + 2*PC); d = get_word(segment, offset + 2*PD); switch(a){ case 0 : r = running->pid; break; case 1 : r = do_ps(); break; case 2 : r = chname(b); break; case 3 : r = kmode(); break; case 4 : r = tswitch(); break; case 5 : r = do_wait(b); break; case 6 : r = do_exit(b); break; case 7 : r = fork(); break; case 8 : r = exec(b); break; case 9 : r = vfork(); break; case 12: r = upline(b); break; case 90: r = getc(); break; case 91: color=running->pid+11; r = putc(b); break; case 99: do_exit(b); break; default: printf("invalid syscall # : %d\n", a); } put_word(r, segment, offset + 2*AX); }
EXPORT BOOL CreateProcessA(LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation){ pid_t pid = vfork(); //printf("Creating process %s %s\n", lpApplicationName, lpCommandLine); if(pid == 0){ char commandline[256]; strncpy(commandline, lpCommandLine, 255); commandline[255] = 0; // ptrace(PT_TRACE_ME, 0, 0, 0); // parse command line; int i=0; char *p = strchr(commandline, ' '); char *q = commandline; char *argv[16]; while(p){ *p = 0; argv[i++] = q; fflush(stdout); q = p + 1; p = strchr(commandline, ' '); } argv[i] = q; argv[i+1] = 0; //printf("Execing %s %s %s", argv[0], argv[1], argv[2]); fflush(stdout); execv(argv[0], argv); perror("Failed to execv!"); } else { DebugActiveProcess(pid); // ptrace(PT_ATTACH, pid, 0, 0); // ptrace(PT_DETACH, pid, 0, 0); lpProcessInformation->dwProcessId = pid; lpProcessInformation->hProcess = pid; } return 1; }
static void edit_file(const struct passwd *pas, const char *file) { const char *ptr; int pid = vfork(); if (pid < 0) /* failure */ bb_perror_msg_and_die("vfork"); if (pid) { /* parent */ wait4pid(pid); return; } /* CHILD - change user and run editor */ change_user(pas); ptr = getenv("VISUAL"); if (!ptr) { ptr = getenv("EDITOR"); if (!ptr) ptr = "vi"; } BB_EXECLP(ptr, ptr, file, NULL); bb_perror_msg_and_die("exec %s", ptr); }
R_API int r_sys_cmd (const char *str) { #if __FreeBSD__ /* freebsd system() is broken */ int st, pid, fds[2]; if (pipe (fds)) return -1; pid = vfork (); if (pid == -1) return -1; if (pid == 0) { dup2 (1, fds[1]); // char *argv[] = { "/bin/sh", "-c", str, NULL}; // execv (argv[0], argv); r_sandbox_system (str, 0); _exit (127); /* error */ } else { dup2 (1, fds[0]); waitpid (pid, &st, 0); } return WEXITSTATUS (st); #else return r_sandbox_system (str, 1); #endif }
int test_vfork() { int var; pid_t pid; var = 88; if (write(STDOUT_FILENO, fork_buf, sizeof(fork_buf) - 1) != sizeof(fork_buf) - 1) err_sys("write"); printf("before vfork\n"); if ((pid = vfork()) < 0) err_sys("fork"); else if (pid == 0) { globval++; var++; sleep(2); // exit(0); } printf("pid = %d, globval = %d, var = %d\n", (long)getpid(), globval, var); exit(0); return 0; }
int posix_spawn(pid_t *pid, const char * path, __unused void *arg, const posix_spawnattr_t *attrp, char *const argv[], char *const envp[]) { pid_t p; volatile int error; error = 0; #ifdef THERE_IS_NO_FORK /* Pray we can sanely modify signal foo */ p = vfork(); #else p = fork(); #endif switch (p) { case -1: return errno; case 0: if (attrp) { error = posix_spawnattr_handle(attrp); if (error) _exit(127); } execve(path, argv, envp); error = errno; _exit(127); default: if (error != 0) waitpid(p, NULL, WNOHANG); else if (pid != NULL) *pid = p; return error; } }
void UnistdVfork(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { ReturnValue->Val->Integer = vfork(); }
int main(int argc, char *argv[]) { int ch, exit_status, status; pid_t bill; exit_status = EXIT_SUCCESS; while ((ch = getopt(argc, argv, "h?q")) != -1) { switch (ch) { case 'q': Flag_Quiet = true; break; case 'h': case '?': default: emit_help(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc < 2) emit_help(); iTimer.it_value.tv_sec = parse_duration(*argv++); bill = vfork(); if (bill == 0) { /* child */ if (execvp(*argv, argv) == -1) err(EX_OSERR, "could not exec %s", *argv); /* NOTREACHED */ } else if (bill > 0) { /* parent */ /* do not restart the wait() after SIGALRM, skip to the end... */ if (siginterrupt(SIGALRM, 1) == -1) err(EX_SOFTWARE, "could not siginterrupt()"); if (signal(SIGALRM, handle_alarm) == SIG_ERR) err(EX_SOFTWARE, "could not setup signal()"); if (setitimer(ITIMER_REAL, &iTimer, NULL) == -1) err(EX_SOFTWARE, "could not setitimer()"); wait(&status); /* the end */ if (Kill_Bill) { if (!Flag_Quiet) warnx("duration %ld exceeded: killing pid %d", (long)iTimer.it_value.tv_sec, bill); /* * Assume child is well behaved, and does not deadlock or * otherwise require multiple signals (race condition risk) to * take down. */ if (kill(bill, SIGTERM) == -1) err(EX_OSERR, "could not kill child pid %d", bill); exit_status = EXIT_TIMEOUT; } else { /* * Pass on the child exit status. These can be illustrated * via something like: * * timeout 99 perl -e 'exit 42' ; echo $? * timeout 99 perl -e 'kill 15, $$' ; echo $? */ if (WIFEXITED(status)) exit_status = WEXITSTATUS(status); else if (WIFSIGNALED(status)) exit_status = 128 + WTERMSIG(status); } } else { err(EX_OSERR, "could not fork()"); } exit(exit_status); }
int start_pppd (struct call *c, struct ppp_opts *opts) { char a, b; char tty[80]; char *stropt[80]; struct ppp_opts *p; #ifdef USE_KERNEL struct l2tp_call_opts co; #endif int pos = 1; int fd2; #ifdef DEBUG_PPPD int x; #endif struct termios ptyconf; struct call *sc; struct tunnel *st; p = opts; stropt[0] = strdup (PPPD); while (p) { stropt[pos] = (char *) malloc (strlen (p->option) + 1); strncpy (stropt[pos], p->option, strlen (p->option) + 1); pos++; p = p->next; } stropt[pos] = NULL; if (c->pppd > 0) { log (LOG_WARN, "%s: PPP already started on call!\n", __FUNCTION__); return -EINVAL; } if (c->fd > -1) { log (LOG_WARN, "%s: file descriptor already assigned!\n", __FUNCTION__); return -EINVAL; } #ifdef USE_KERNEL if (kernel_support) { co.ourtid = c->container->ourtid; co.ourcid = c->ourcid; ioctl (server_socket, L2TPIOCGETCALLOPTS, &co); stropt[pos++] = strdup ("channel"); stropt[pos] = (char *) malloc (10); snprintf (stropt[pos], 10, "%d", co.id); pos++; stropt[pos] = NULL; } else { #endif if ((c->fd = getPtyMaster (&a, &b)) < 0) { log (LOG_WARN, "%s: unable to allocate pty, abandoning!\n", __FUNCTION__); return -EINVAL; } /* set fd opened above to not echo so we don't see read our own packets back of the file descriptor that we just wrote them to */ tcgetattr (c->fd, &ptyconf); *(c->oldptyconf) = ptyconf; ptyconf.c_cflag &= ~(ICANON | ECHO); ptyconf.c_lflag &= ~ECHO; tcsetattr (c->fd, TCSANOW, &ptyconf); snprintf (tty, sizeof (tty), "/dev/tty%c%c", a, b); fd2 = open (tty, O_RDWR); if (fd2 < 0) { log (LOG_WARN, "unable to open tty %s, cannot start pppd", tty); return -EINVAL; } stropt[pos++] = strdup(tty); stropt[pos] = NULL; #ifdef USE_KERNEL } #endif #ifdef DEBUG_PPPD log (LOG_DEBUG, "%s: I'm running: ", __FUNCTION__); for (x = 0; stropt[x]; x++) { log (LOG_DEBUG, "\"%s\" ", stropt[x]); }; log (LOG_DEBUG, "\n"); #endif #ifdef __uClinux__ c->pppd = vfork (); #else c->pppd = fork (); #endif if (c->pppd < 0) { log (LOG_WARN, "%s: unable to fork(), abandoning!\n", __FUNCTION__); return -EINVAL; } else if (!c->pppd) { /* child */ close (0); /* redundant; the dup2() below would do that, too */ close (1); /* ditto */ /* close (2); No, we want to keep the connection to /dev/null. */ /* connect the pty to stdin and stdout */ dup2 (fd2, 0); dup2 (fd2, 1); /* close all the calls pty fds */ st = tunnels.head; while (st) { sc = st->call_head; while (sc) { close (sc->fd); sc = sc->next; } st = st->next; } /* close the UDP socket fd */ close (server_socket); /* close the control pipe fd */ close (control_fd); if( c->dialing[0] ) { setenv( "CALLER_ID", c->dialing, 1 ); } execv (PPPD, stropt); log (LOG_WARN, "%s: Exec of %s failed!\n", __FUNCTION__, PPPD); _exit (1); } close (fd2); pos = 0; while (stropt[pos]) { free (stropt[pos]); pos++; }; return 0; }
int main(int argc, char *argv[]) { struct netperf_child *instance; char len_str[32]; char *args[32]; const char *host; volatile int ninst; int len, ninst_done; int opt, i, null_fd; double result; pid_t mypid; host = NULL; ninst = 2; len = 10; while ((opt = getopt(argc, argv, "i:H:l:")) != -1) { switch (opt) { case 'i': ninst = strtoul(optarg, NULL, 10); break; case 'H': host = optarg; break; case 'l': len = strtoul(optarg, NULL, 10); break; default: usage(argv[0]); } } if (ninst <= 0 || host == NULL || len <= 0) usage(argv[0]); mypid = getpid(); snprintf(len_str, sizeof(len_str), "%d", len); i = 0; args[i++] = __DECONST(char *, NETPERF_CMD); args[i++] = __DECONST(char *, "-P0"); args[i++] = __DECONST(char *, "-H"); args[i++] = __DECONST(char *, host); args[i++] = __DECONST(char *, "-l"); args[i++] = __DECONST(char *, len_str); args[i++] = __DECONST(char *, "-t"); args[i++] = __DECONST(char *, "TCP_CC"); args[i] = NULL; instance = calloc(ninst, sizeof(struct netperf_child)); if (instance == NULL) { fprintf(stderr, "calloc failed\n"); exit(1); } null_fd = open("/dev/null", O_RDWR); if (null_fd < 0) { fprintf(stderr, "open null failed: %d\n", errno); exit(1); } for (i = 0; i < ninst; ++i) { char filename[128]; snprintf(filename, sizeof(filename), TCP_CC_FILENAME, (int)mypid, i); instance[i].fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IWUSR | S_IRUSR); if (instance[i].fd < 0) { fprintf(stderr, "open %s failed: %d\n", filename, errno); exit(1); } } for (i = 0; i < ninst; ++i) { pid_t pid; pid = vfork(); if (pid == 0) { int ret; dup2(instance[i].fd, STDOUT_FILENO); dup2(null_fd, STDERR_FILENO); ret = execv(NETPERF_PATH, args); if (ret < 0) { fprintf(stderr, "execv %d failed: %d\n", i, errno); _exit(1); } /* Never reached */ abort(); } else if (pid < 0) { fprintf(stderr, "vfork %d failed: %d\n", i, errno); exit(1); } } ninst_done = 0; while (ninst_done < ninst) { pid_t pid; pid = waitpid(-1, NULL, 0); if (pid < 0) { fprintf(stderr, "waitpid failed: %d\n", errno); exit(1); } ++ninst_done; } result = 0.0; for (i = 0; i < ninst; ++i) { char line[128], filename[128]; FILE *fp; close(instance[i].fd); snprintf(filename, sizeof(filename), TCP_CC_FILENAME, (int)mypid, i); fp = fopen(filename, "r"); if (fp == NULL) { fprintf(stderr, "fopen %s failed\n", filename); exit(1); } while (fgets(line, sizeof(line), fp) != NULL) { int n, arg1, arg2, arg3, arg4; double res, arg5; n = sscanf(line, "%d%d%d%d%lf%lf", &arg1, &arg2, &arg3, &arg4, &arg5, &res); if (n == 6) { result += res; break; } } fclose(fp); unlink(filename); } printf("TCP_CC %f conns/s\n", result); exit(0); }
int main() { pid_t pid; pid_t wait_pid; int status; char *argv[] = { "Delay", "50", NULL }; char *envp[] = { NULL }; wait_pid = waitpid(666, NULL, 0); TEST(wait_pid == -1); TEST(errno == ECHILD); pid = vfork(); if((int) pid > 0) { printf("Created child with pid %d\n", (int) pid); printf("Waiting for child with pid %d to exit.\n", (int) pid); wait_pid = waitpid(pid, &status, 0); TEST((wait_pid == pid)); printf("Child %d exited with exit status %d\n", (int) wait_pid, status); TEST((status == EXIT_STATUS)); } else if(pid == 0) { printf("Exiting with status %d\n", EXIT_STATUS); _exit(EXIT_STATUS); } else { TEST(0); } pid = vfork(); if((int) pid > 0) { printf("Created child with pid %d\n", (int) pid); printf("Waiting for any child to exit.\n"); wait_pid = waitpid(-1, &status, 0); TEST((wait_pid == pid)); printf("Child %d exited with exit status %d\n", (int) wait_pid, status); TEST((status == EXIT_STATUS)); } else if(pid == 0) { printf("Exiting with status %d\n", EXIT_STATUS); _exit(EXIT_STATUS); } else { TEST(0); } pid = vfork(); if((int) pid > 0) { printf("Created child with pid %d\n", (int) pid); printf("Waiting for any child to exit without hang.\n"); wait_pid = waitpid(-1, &status, WNOHANG); if(wait_pid == 0) wait_pid = waitpid(-1, &status, 0); TEST((wait_pid == pid)); printf("Child %d exited with exit status %d\n", (int) wait_pid, status); TEST((status == EXIT_STATUS)); } else if(pid == 0) { printf("Exiting with status %d\n", EXIT_STATUS); _exit(EXIT_STATUS); } else { TEST(0); } pid = vfork(); if((int) pid > 0) { printf("Created child with pid %d\n", (int) pid); printf("Waiting for any child to exit without hang.\n"); wait_pid = waitpid(-1, &status, WNOHANG); TEST((wait_pid == 0)); printf("Child didn't exit yet\n"); wait_pid = waitpid(-1, &status, 0); TEST((wait_pid == pid)); printf("Child %d exited with exit status %d\n", (int) wait_pid, status); TEST((status == 0)); } else if(pid == 0) { execve("C:Delay", argv, envp); _exit(-1); } else { TEST(0); } }
void Subprocess::spawnInternal( std::unique_ptr<const char*[]> argv, const char* executable, Options& options, const std::vector<std::string>* env, int errFd) { // Parent work, pre-fork: create pipes std::vector<int> childFds; // Close all of the childFds as we leave this scope SCOPE_EXIT { // These are only pipes, closing them shouldn't fail for (int cfd : childFds) { CHECK_ERR(::close(cfd)); } }; int r; for (auto& p : options.fdActions_) { if (p.second == PIPE_IN || p.second == PIPE_OUT) { int fds[2]; r = ::pipe(fds); checkUnixError(r, "pipe"); PipeInfo pinfo; pinfo.direction = p.second; int cfd; if (p.second == PIPE_IN) { // Child gets reading end pinfo.parentFd = fds[1]; cfd = fds[0]; } else { pinfo.parentFd = fds[0]; cfd = fds[1]; } p.second = cfd; // ensure it gets dup2()ed pinfo.childFd = p.first; childFds.push_back(cfd); pipes_.push_back(pinfo); } } // This should already be sorted, as options.fdActions_ is DCHECK(std::is_sorted(pipes_.begin(), pipes_.end())); // Note that the const casts below are legit, per // http://pubs.opengroup.org/onlinepubs/009695399/functions/exec.html char** argVec = const_cast<char**>(argv.get()); // Set up environment std::unique_ptr<const char*[]> envHolder; char** envVec; if (env) { envHolder = cloneStrings(*env); envVec = const_cast<char**>(envHolder.get()); } else { envVec = environ; } // Block all signals around vfork; see http://ewontfix.com/7/. // // As the child may run in the same address space as the parent until // the actual execve() system call, any (custom) signal handlers that // the parent has might alter parent's memory if invoked in the child, // with undefined results. So we block all signals in the parent before // vfork(), which will cause them to be blocked in the child as well (we // rely on the fact that Linux, just like all sane implementations, only // clones the calling thread). Then, in the child, we reset all signals // to their default dispositions (while still blocked), and unblock them // (so the exec()ed process inherits the parent's signal mask) // // The parent also unblocks all signals as soon as vfork() returns. sigset_t allBlocked; r = sigfillset(&allBlocked); checkUnixError(r, "sigfillset"); sigset_t oldSignals; r = pthread_sigmask(SIG_SETMASK, &allBlocked, &oldSignals); checkPosixError(r, "pthread_sigmask"); SCOPE_EXIT { // Restore signal mask r = pthread_sigmask(SIG_SETMASK, &oldSignals, nullptr); CHECK_EQ(r, 0) << "pthread_sigmask: " << errnoStr(r); // shouldn't fail }; pid_t pid = vfork(); if (pid == 0) { int errnoValue = prepareChild(options, &oldSignals); if (errnoValue != 0) { childError(errFd, kChildFailure, errnoValue); } errnoValue = runChild(executable, argVec, envVec, options); // If we get here, exec() failed. childError(errFd, kExecFailure, errnoValue); } // In parent. Make sure vfork() succeeded. checkUnixError(pid, errno, "vfork"); // Child is alive. We have to be very careful about throwing after this // point. We are inside the constructor, so if we throw the Subprocess // object will have never existed, and the destructor will never be called. // // We should only throw if we got an error via the errFd, and we know the // child has exited and can be immediately waited for. In all other cases, // we have no way of cleaning up the child. pid_ = pid; returnCode_ = ProcessReturnCode(RV_RUNNING); }
pid_t __archive_create_child(const char *path, int *child_stdin, int *child_stdout) { pid_t child; int stdin_pipe[2], stdout_pipe[2], tmp; if (pipe(stdin_pipe) == -1) goto state_allocated; if (stdin_pipe[0] == 1 /* stdout */) { if ((tmp = dup(stdin_pipe[0])) == -1) goto stdin_opened; close(stdin_pipe[0]); stdin_pipe[0] = tmp; } if (pipe(stdout_pipe) == -1) goto stdin_opened; if (stdout_pipe[1] == 0 /* stdin */) { if ((tmp = dup(stdout_pipe[1])) == -1) goto stdout_opened; close(stdout_pipe[1]); stdout_pipe[1] = tmp; } #if HAVE_VFORK switch ((child = vfork())) { #else switch ((child = fork())) { #endif case -1: goto stdout_opened; case 0: close(stdin_pipe[1]); close(stdout_pipe[0]); if (dup2(stdin_pipe[0], 0 /* stdin */) == -1) _exit(254); if (stdin_pipe[0] != 0 /* stdin */) close(stdin_pipe[0]); if (dup2(stdout_pipe[1], 1 /* stdout */) == -1) _exit(254); if (stdout_pipe[1] != 1 /* stdout */) close(stdout_pipe[1]); execlp(path, path, (char *)NULL); _exit(254); default: close(stdin_pipe[0]); close(stdout_pipe[1]); *child_stdin = stdin_pipe[1]; fcntl(*child_stdin, F_SETFL, O_NONBLOCK); *child_stdout = stdout_pipe[0]; fcntl(*child_stdout, F_SETFL, O_NONBLOCK); } return child; stdout_opened: close(stdout_pipe[0]); close(stdout_pipe[1]); stdin_opened: close(stdin_pipe[0]); close(stdin_pipe[1]); state_allocated: return -1; } void __archive_check_child(int in, int out) { #if defined(HAVE_POLL) struct pollfd fds[2]; int idx; idx = 0; if (in != -1) { fds[idx].fd = in; fds[idx].events = POLLOUT; ++idx; } if (out != -1) { fds[idx].fd = out; fds[idx].events = POLLIN; ++idx; } poll(fds, idx, -1); /* -1 == INFTIM, wait forever */ #elif defined(HAVE_SELECT) fd_set fds_in, fds_out, fds_error; FD_ZERO(&fds_in); FD_ZERO(&fds_out); FD_ZERO(&fds_error); if (out != -1) { FD_SET(out, &fds_in); FD_SET(out, &fds_error); } if (in != -1) { FD_SET(in, &fds_out); FD_SET(in, &fds_error); } select(in < out ? out + 1 : in + 1, &fds_in, &fds_out, &fds_error, NULL); #else sleep(1); #endif }
/* ARGSUSED */ int util_pipefork( char * const *argv, /* normal argv argument list */ FILE **toCommand, /* pointer to the sending stream */ FILE **fromCommand, /* pointer to the reading stream */ int *pid) { #ifdef UNIX int forkpid, waitPid; int topipe[2], frompipe[2]; char buffer[1024]; int status; /* create the PIPES... * fildes[0] for reading from command * fildes[1] for writing to command */ if (pipe(topipe)) return(0); if (pipe(frompipe)) return(0); #ifdef __CYGWIN32__ if ((forkpid = fork()) == 0) { #else if ((forkpid = vfork()) == 0) { #endif /* child here, connect the pipes */ (void) dup2(topipe[0], fileno(stdin)); (void) dup2(frompipe[1], fileno(stdout)); (void) close(topipe[0]); (void) close(topipe[1]); (void) close(frompipe[0]); (void) close(frompipe[1]); (void) execvp(argv[0], argv); (void) sprintf(buffer, "util_pipefork: can not exec %s", argv[0]); perror(buffer); (void) _exit(1); } if (pid) { *pid = forkpid; } #ifdef __CYGWIN32__ waitPid = waitpid(-1, &status, WNOHANG); #else waitPid = wait3(&status, WNOHANG, NULL); #endif /* parent here, use slimey vfork() semantics to get return status */ if (waitPid == forkpid && WIFEXITED(status)) { return 0; } if ((*toCommand = fdopen(topipe[1], "w")) == NULL) { return 0; } if ((*fromCommand = fdopen(frompipe[0], "r")) == NULL) { return 0; } (void) close(topipe[0]); (void) close(frompipe[1]); return 1; #else (void) fprintf(stderr, "util_pipefork: not implemented on your operating system\n"); return 0; #endif }
int koo_process::_open_process() { std::string cmd = m_execname; if (!m_arguments.empty()) cmd += " " + m_arguments; #ifdef _WIN32 STARTUPINFO si = {sizeof (si)}; si.dwFlags = STARTF_USESHOWWINDOW; DWORD creationFlag = 0; if (m_create_new_window) { si.wShowWindow = SW_SHOWDEFAULT; creationFlag |= CREATE_NEW_CONSOLE; } else { //si.dwFlags |= STARTF_USESTDHANDLES; } #ifdef _DEBUG std::cout << "DEBUG_INFO: begin to exec command: " << cmd << std::endl; #endif bool result = CreateProcess(NULL, (LPSTR)cmd.c_str(), NULL, NULL, FALSE, creationFlag, NULL, m_workpath.empty() ? NULL : m_workpath.c_str(), &si, &m_proc_info); if (result) { return K_OK; } else { DWORD e = GetLastError(); return K_ERR_PROCESS_OPEN_FAILURE; } #else std::vector<std::string> arg_list; arg_list.push_back(m_execname); k_str_split(m_arguments, arg_list, " "); char* argv[64] = {0}; for (int i = 0; i < arg_list.size(); i++) { argv[i] = (char*) arg_list[i].c_str(); } __pid_t pid = vfork(); if (pid < 0) { std::cout << "fork error; failed to create process;"; _exit(0); } else if (pid == 0) { chdir(m_workpath.c_str()); execv(m_execname.c_str(), argv); } else { m_pid = pid; std::cout << "process: " << m_pid << " has been created..."; return K_OK; } #endif return K_ERR_Not_Supported; }
CGrapher::CGrapher(Parameters* param, char* title){ #ifndef WIN32 int toFils[2]; int toPere[2]; int sonPid; this->valid=1; if(pipe(toFils)<0){ perror("PipeComOpen: Creating pipes"); this->valid=0; return; } if(pipe(toPere)<0){ perror("PipeComOpen: Creating pipes"); this->valid=0; return; } switch((sonPid=vfork())){ case -1: perror("PipeComOpen: fork failed"); this->valid=0; break; case 0: /* --- here's the son --- */ if(dup2(toFils[0], fileno(stdin))<0){ perror("PipeComOpen(son): could not connect\n"); this->valid=0; abort(); } if(dup2(toPere[1], fileno(stdout))<0){ perror("PipeComOpen(son): could not connect\n"); this->valid=0; abort(); } char* pPath; pPath = getenv("EZ_PATH"); if(pPath != NULL){ pPath = strcat(pPath, "easeagrapher/EaseaGrapher.jar"); } else{ pPath = (char*)"../../easeagrapher/EaseaGrapher.jar"; } char *arg[4]; arg[0] = (char*)"java"; arg[1] = (char*)"-jar"; arg[2] = pPath; arg[3] = (char*)0; if(execvp("java",arg)<0){ perror("java not installed, please change plotStats parameter\n"); abort(); this->valid=0; } break; default : if(this->valid){ this->fWrit = (FILE *)fdopen(toFils[1],"w"); this->fRead = (FILE *)fdopen(toPere[0],"r"); this->pid = sonPid; fprintf(this->fWrit,"set term wxt persist\n"); fprintf(this->fWrit,"set grid\n"); fprintf(this->fWrit,"set xlabel \"Number of Evaluations\"\n"); fprintf(this->fWrit,"set ylabel \"Fitness\"\n"); int nbEval = param->offspringPopulationSize*param->nbGen + param->parentPopulationSize; fprintf(this->fWrit,"set xrange[0:%d]\n",nbEval); fprintf(this->fWrit,"set max eval:%d\n",nbEval); fprintf(this->fWrit,"set title:%s\n",title); if(param->remoteIslandModel){ fprintf(this->fWrit,"set island model\n"); fprintf(this->fWrit,"set max generation:%d\n",param->nbGen); } fflush(this->fWrit); } } #endif }
static int do_listen(void) { struct sockaddr_rc sa; int sk, lm; if (type == MROUTER) { if (!cache.valid) return -1; if (create_connection(cache.dst, &cache.bdaddr, type) < 0) { syslog(LOG_ERR, "Cannot connect to mRouter device. %s(%d)", strerror(errno), errno); return -1; } } if (!channel) channel = DUN_DEFAULT_CHANNEL; if (use_sdp) dun_sdp_register(&src_addr, channel, type); if (type == MROUTER) syslog(LOG_INFO, "Waiting for mRouter callback on channel %d", channel); /* Create RFCOMM socket */ sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); if (sk < 0) { syslog(LOG_ERR, "Cannot create RFCOMM socket. %s(%d)", strerror(errno), errno); return -1; } sa.rc_family = AF_BLUETOOTH; sa.rc_channel = channel; sa.rc_bdaddr = src_addr; if (bind(sk, (struct sockaddr *) &sa, sizeof(sa))) { syslog(LOG_ERR, "Bind failed. %s(%d)", strerror(errno), errno); return -1; } /* Set link mode */ lm = 0; if (master) lm |= RFCOMM_LM_MASTER; if (auth) lm |= RFCOMM_LM_AUTH; if (encrypt) lm |= RFCOMM_LM_ENCRYPT; if (secure) lm |= RFCOMM_LM_SECURE; if (lm && setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm)) < 0) { syslog(LOG_ERR, "Failed to set link mode. %s(%d)", strerror(errno), errno); return -1; } listen(sk, 10); while (!terminate) { socklen_t alen = sizeof(sa); int nsk; char ba[40]; char ch[10]; nsk = accept(sk, (struct sockaddr *) &sa, &alen); if (nsk < 0) { syslog(LOG_ERR, "Accept failed. %s(%d)", strerror(errno), errno); continue; } switch (vfork()) { case 0: break; case -1: syslog(LOG_ERR, "Fork failed. %s(%d)", strerror(errno), errno); default: close(nsk); if (type == MROUTER) { close(sk); terminate = 1; } continue; } close(sk); if (msdun && ms_dun(nsk, 1, msdun) < 0) { syslog(LOG_ERR, "MSDUN failed. %s(%d)", strerror(errno), errno); exit(0); } ba2str(&sa.rc_bdaddr, ba); sprintf(ch, "%d", channel); /* Setup environment */ setenv("DUN_BDADDR", ba, 1); setenv("DUN_CHANNEL", ch, 1); if (!dun_open_connection(nsk, pppd, pppd_opts, 0)) syslog(LOG_INFO, "New connection from %s", ba); close(nsk); exit(0); } if (use_sdp) dun_sdp_unregister(); return 0; }
int main(int argc, char **argv) { char *dst = NULL, *src = NULL; struct sigaction sa; int mode = NONE; int opt; while ((opt=getopt_long(argc, argv, main_sopts, main_lopts, NULL)) != -1) { switch(opt) { case 'l': mode = SHOW; detach = 0; break; case 's': mode = LISTEN; break; case 'c': mode = CONNECT; dst = strdup(optarg); break; case 'Q': mode = CONNECT; dst = NULL; if (optarg) search_duration = atoi(optarg); break; case 'k': mode = KILL; detach = 0; dst = strdup(optarg); break; case 'K': mode = KILL; detach = 0; dst = NULL; break; case 'P': channel = atoi(optarg); break; case 'i': src = strdup(optarg); break; case 'D': use_sdp = 0; break; case 'A': auth = 1; break; case 'E': encrypt = 1; break; case 'S': secure = 1; break; case 'M': master = 1; break; case 'n': detach = 0; break; case 'p': if (optarg) persist = atoi(optarg); else persist = 5; break; case 'C': if (optarg) use_cache = atoi(optarg); else use_cache = 2; break; case 'd': pppd = strdup(optarg); break; case 'X': if (optarg) msdun = atoi(optarg); else msdun = 10; break; case 'a': msdun = 10; type = ACTIVESYNC; break; case 'm': mode = LISTEN; dst = strdup(optarg); type = MROUTER; break; case 'u': mode = LISTEN; type = DIALUP; break; case 'h': default: printf(main_help); exit(0); } } argc -= optind; argv += optind; /* The rest is pppd options */ if (argc > 0) { for (opt = 3; argc && opt < DUN_MAX_PPP_OPTS; argc--, opt++) pppd_opts[opt] = *argv++; pppd_opts[opt] = NULL; } io_init(); if (dun_init()) return -1; /* Check non daemon modes first */ switch (mode) { case SHOW: do_show(); return 0; case KILL: do_kill(dst); return 0; case NONE: printf(main_help); return 0; } /* Initialize signals */ memset(&sa, 0, sizeof(sa)); sa.sa_flags = SA_NOCLDSTOP; sa.sa_handler = SIG_IGN; sigaction(SIGCHLD, &sa, NULL); sigaction(SIGPIPE, &sa, NULL); sa.sa_handler = sig_term; sigaction(SIGTERM, &sa, NULL); sigaction(SIGINT, &sa, NULL); sa.sa_handler = sig_hup; sigaction(SIGHUP, &sa, NULL); if (detach) { int fd; if (vfork()) exit(0); /* Direct stdin,stdout,stderr to '/dev/null' */ fd = open("/dev/null", O_RDWR); dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); close(fd); setsid(); chdir("/"); } openlog("dund", LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON); syslog(LOG_INFO, "Bluetooth DUN daemon version %s", VERSION); if (src) { src_dev = hci_devid(src); if (src_dev < 0 || hci_devba(src_dev, &src_addr) < 0) { syslog(LOG_ERR, "Invalid source. %s(%d)", strerror(errno), errno); return -1; } } if (dst) { strncpy(cache.dst, dst, sizeof(cache.dst) - 1); str2ba(dst, &cache.bdaddr); /* Disable cache invalidation */ use_cache = cache.valid = ~0; } switch (mode) { case CONNECT: do_connect(); break; case LISTEN: do_listen(); break; } return 0; }
int setup_vlan(char *name) { char *index; char *eth; char *cpy; char *state; char *argv[5]; int argc = 0; int pid; int status; cpy = strdup(name); if (!cpy) { return -1; } eth = strtok_r(cpy, ".", &state); if (!eth) { return -1; } index = strtok_r(NULL, ".", &state); if (!index) { return -1; } bzero(argv, sizeof(argv)); argv[argc++] = "vconfig"; argv[argc++] = "add"; argv[argc++] = eth; argv[argc++] = index; argv[argc] = NULL; #ifdef __uClinux__ if ((pid = vfork()) == 0) { #else if ((pid = fork()) == 0) { #endif if (execvp(argv[0], argv) < 0) { #ifdef __uClinux__ _exit(1); #else exit(1); #endif } } else if (pid < 0) { fprintf(stderr, "Couldn't fork\n"); exit(1); } if (waitpid(pid, &status, 0) < 0) { fprintf(stderr, "Error waiting for vconfig - %m\n"); return -1; } if (WEXITSTATUS(status) != 0) { return -1; } return 0; }
static BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL as_root) { char *slavedev; int master; pid_t pid, wpid; int wstat; BOOL chstat = False; /* allocate a pseudo-terminal device */ if ((master = findpty (&slavedev)) < 0) { DEBUG(3,("Cannot Allocate pty for password change: %s\n",name)); return(False); } /* * We need to temporarily stop CatchChild from eating * SIGCLD signals as it also eats the exit status code. JRA. */ CatchChildLeaveStatus(); #ifdef __uClinux__ /* Hmmm, need to check this one further... */ DEBUG(0,("%s(%d): vfork()ing\n",__FILE__,__LINE__)); if ((pid = vfork()) < 0) { #else if ((pid = fork()) < 0) { #endif DEBUG(3,("Cannot fork() child for password change: %s\n",name)); close(master); CatchChild(); return(False); } /* we now have a pty */ if (pid > 0){ /* This is the parent process */ if ((chstat = talktochild(master, chatsequence)) == False) { DEBUG(3,("Child failed to change password: %s\n",name)); kill(pid, SIGKILL); /* be sure to end this process */ } while((wpid = sys_waitpid(pid, &wstat, 0)) < 0) { if(errno == EINTR) { errno = 0; continue; } break; } if (wpid < 0) { DEBUG(3,("The process is no longer waiting!\n\n")); close(master); CatchChild(); return(False); } /* * Go back to ignoring children. */ CatchChild(); close(master); if (pid != wpid) { DEBUG(3,("We were waiting for the wrong process ID\n")); return(False); } if (WIFEXITED(wstat) == 0) { DEBUG(3,("The process exited while we were waiting\n")); return(False); } if (WEXITSTATUS(wstat) != 0) { DEBUG(3,("The status of the process exiting was %d\n", wstat)); return(False); } } else { /* CHILD */ /* * Lose any oplock capabilities. */ set_process_capability(KERNEL_OPLOCK_CAPABILITY, False); set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY, False); /* make sure it doesn't freeze */ alarm(20); if (as_root) become_root(False); DEBUG(3,("Dochild for user %s (uid=%d,gid=%d)\n",name,(int)getuid(),(int)getgid())); chstat = dochild(master, slavedev, name, passwordprogram, as_root); /* * The child should never return from dochild() .... */ DEBUG(0,("chat_with_program: Error: dochild() returned %d\n", chstat )); exit(1); } if (chstat) DEBUG(3,("Password change %ssuccessful for user %s\n", (chstat?"":"un"), name)); return (chstat); } BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root) { pstring passwordprogram; pstring chatsequence; size_t i; size_t len; strlower(name); DEBUG(3,("Password change for user: %s\n",name)); #if DEBUG_PASSWORD DEBUG(100,("Passwords: old=%s new=%s\n",oldpass,newpass)); #endif /* Take the passed information and test it for minimum criteria */ /* Minimum password length */ if (strlen(newpass) < lp_min_passwd_length()) /* too short, must be at least MINPASSWDLENGTH */ { DEBUG(0,("Password Change: user %s, New password is shorter than minimum password length = %d\n", name, lp_min_passwd_length())); return (False); /* inform the user */ } /* Password is same as old password */ if (strcmp(oldpass,newpass) == 0) /* don't allow same password */ { DEBUG(2,("Password Change: %s, New password is same as old\n",name)); /* log the attempt */ return (False); /* inform the user */ } pstrcpy(passwordprogram,lp_passwd_program()); pstrcpy(chatsequence,lp_passwd_chat()); if (!*chatsequence) { DEBUG(2,("Null chat sequence - no password changing\n")); return(False); } if (!*passwordprogram) { DEBUG(2,("Null password program - no password changing\n")); return(False); } /* * Check the old and new passwords don't contain any control * characters. */ len = strlen(oldpass); for(i = 0; i < len; i++) { if (iscntrl((int)oldpass[i])) { DEBUG(0,("chat_with_program: oldpass contains control characters (disallowed).\n")); return False; } } len = strlen(newpass); for(i = 0; i < len; i++) { if (iscntrl((int)newpass[i])) { DEBUG(0,("chat_with_program: newpass contains control characters (disallowed).\n")); return False; } } pstring_sub(passwordprogram,"%u",name); /* note that we do NOT substitute the %o and %n in the password program as this would open up a security hole where the user could use a new password containing shell escape characters */ pstring_sub(chatsequence,"%u",name); all_string_sub(chatsequence,"%o",oldpass,sizeof(pstring)); all_string_sub(chatsequence,"%n",newpass,sizeof(pstring)); return(chat_with_program(passwordprogram,name,chatsequence, as_root)); }
int main(int argc, char *argv[]) { FILE *fp; struct stat sb; size_t fplen, fptlen, len; off_t offset; int ch, debug, i, pdes[2], pid, status; char *addrp, *domain, *p, *t; char *from_path, *from_sys, *from_user; char *args[100], buf[2048], lbuf[2048]; #ifdef lint fplen = fptlen = 0; addrp = NULL; #endif debug = 0; domain = "UUCP"; /* Default "domain". */ while ((ch = getopt(argc, argv, "D:T")) != -1) switch (ch) { case 'T': debug = 1; break; case 'D': domain = optarg; break; default: usage(); } argc -= optind; argv += optind; if (argc < 1) usage(); from_path = from_sys = from_user = NULL; for (offset = 0;;) { /* Get and nul-terminate the line. */ if (fgets(lbuf, sizeof(lbuf), stdin) == NULL) exit (EX_DATAERR); if ((p = strchr(lbuf, '\n')) == NULL) err(EX_DATAERR, "line too long"); *p = '\0'; /* Parse lines until reach a non-"From" line. */ if (!strncmp(lbuf, "From ", 5)) addrp = lbuf + 5; else if (!strncmp(lbuf, ">From ", 6)) addrp = lbuf + 6; else if (offset == 0) err(EX_DATAERR, "missing or empty From line: %s", lbuf); else { *p = '\n'; break; } if (*addrp == '\0') err(EX_DATAERR, "corrupted From line: %s", lbuf); /* Use the "remote from" if it exists. */ for (p = addrp; (p = strchr(p + 1, 'r')) != NULL;) if (!strncmp(p, "remote from ", 12)) { for (t = p += 12; *t && !isspace(*t); ++t); *t = '\0'; if (debug) (void)fprintf(stderr, "remote from: %s\n", p); break; } /* Else use the string up to the last bang. */ if (p == NULL) { if (*addrp == '!') err(EX_DATAERR, "bang starts address: %s", addrp); else if ((t = strrchr(addrp, '!')) != NULL) { *t = '\0'; p = addrp; addrp = t + 1; if (*addrp == '\0') err(EX_DATAERR, "corrupted From line: %s", lbuf); if (debug) (void)fprintf(stderr, "bang: %s\n", p); } } /* 'p' now points to any system string from this line. */ if (p != NULL) { /* Nul terminate it as necessary. */ for (t = p; *t && !isspace(*t); ++t); *t = '\0'; /* If the first system, copy to the from_sys string. */ if (from_sys == NULL) { if ((from_sys = strdup(p)) == NULL) err(EX_TEMPFAIL, NULL); if (debug) (void)fprintf(stderr, "from_sys: %s\n", from_sys); } /* Concatenate to the path string. */ len = t - p; if (from_path == NULL) { fplen = 0; if ((from_path = malloc(fptlen = 256)) == NULL) err(EX_TEMPFAIL, NULL); } if (fplen + len + 2 > fptlen) { size_t newfptlen = fptlen + MAX(fplen + len + 2, 256); char *np; if ((np = realloc(from_path, newfptlen)) == NULL) err(EX_TEMPFAIL, NULL); from_path = np; fptlen = newfptlen; } memmove(from_path + fplen, p, len); fplen += len; from_path[fplen++] = '!'; from_path[fplen] = '\0'; } /* Save off from user's address; the last one wins. */ for (p = addrp; *p && !isspace(*p); ++p); *p = '\0'; if (*addrp == '\0') addrp = "<>"; free(from_user); if ((from_user = strdup(addrp)) == NULL) err(EX_TEMPFAIL, NULL); if (debug) { if (from_path != NULL) (void)fprintf(stderr, "from_path: %s\n", from_path); (void)fprintf(stderr, "from_user: %s\n", from_user); } if (offset != -1) offset = ftello(stdin); } i = 0; args[i++] = _PATH_SENDMAIL; /* Build sendmail's argument list. */ args[i++] = "-G"; /* Relay submission. */ args[i++] = "-oee"; /* No errors, just status. */ args[i++] = "-odi"; /* Deliver in foreground. */ args[i++] = "-oi"; /* Ignore '.' on a line by itself. */ /* set from system and protocol used */ #ifdef TAYLOR_ENV { char *uu_machine; uu_machine = getenv("UU_MACHINE"); /* set by Taylor UUCP's uuxqt */ if (uu_machine) from_sys = uu_machine; } #endif if (from_sys == NULL) (void)snprintf(buf, sizeof(buf), "-p%s", domain); else if (strchr(from_sys, '.') == NULL) (void)snprintf(buf, sizeof(buf), "-p%s:%s.%s", domain, from_sys, domain); else (void)snprintf(buf, sizeof(buf), "-p%s:%s", domain, from_sys); if ((args[i++] = strdup(buf)) == NULL) err(EX_TEMPFAIL, NULL); /* Set name of ``from'' person. */ (void)snprintf(buf, sizeof(buf), "-f%s%s", from_path ? from_path : "", from_user); if ((args[i++] = strdup(buf)) == NULL) err(EX_TEMPFAIL, NULL); /* * Don't copy arguments beginning with - as they will be * passed to sendmail and could be interpreted as flags. * To prevent confusion of sendmail wrap < and > around * the address (helps to pass addrs like @gw1,@gw2:aa@bb) */ while (*argv) { if (**argv == '-') err(EX_USAGE, "dash precedes argument: %s", *argv); if (strchr(*argv, ',') == NULL || strchr(*argv, '<') != NULL) args[i++] = *argv; else { if (asprintf(&args[i++], "<%s>", *argv) == -1) err(EX_TEMPFAIL, "Cannot malloc"); } argv++; } args[i] = 0; if (debug) { (void)fprintf(stderr, "sendmail arguments:\n"); for (i = 0; args[i]; i++) (void)fprintf(stderr, "\t%s\n", args[i]); } /* * If called with a regular file as standard input, seek to the right * position in the file and just exec sendmail. Could probably skip * skip the stat, but it's not unreasonable to believe that a failed * seek will cause future reads to fail. */ if (!fstat(STDIN_FILENO, &sb) && S_ISREG(sb.st_mode)) { if (lseek(STDIN_FILENO, offset, SEEK_SET) != offset) err(EX_TEMPFAIL, "stdin seek"); execv(_PATH_SENDMAIL, args); err(EX_OSERR, "%s", _PATH_SENDMAIL); } if (pipe(pdes) < 0) err(EX_OSERR, NULL); switch (pid = vfork()) { case -1: /* Err. */ err(EX_OSERR, NULL); case 0: /* Child. */ if (pdes[0] != STDIN_FILENO) { (void)dup2(pdes[0], STDIN_FILENO); (void)close(pdes[0]); } (void)close(pdes[1]); execv(_PATH_SENDMAIL, args); _exit(127); /* NOTREACHED */ } if ((fp = fdopen(pdes[1], "w")) == NULL) err(EX_OSERR, NULL); (void)close(pdes[0]); /* Copy the file down the pipe. */ do { (void)fprintf(fp, "%s", lbuf); } while (fgets(lbuf, sizeof(lbuf), stdin) != NULL); if (ferror(stdin)) err(EX_TEMPFAIL, "stdin"); if (fclose(fp)) err(EX_OSERR, NULL); if ((waitpid(pid, &status, 0)) == -1) err(EX_OSERR, "%s", _PATH_SENDMAIL); if (!WIFEXITED(status)) err(EX_OSERR, "%s: did not terminate normally", _PATH_SENDMAIL); if (WEXITSTATUS(status)) err(status, "%s: terminated with %d (non-zero) status", _PATH_SENDMAIL, WEXITSTATUS(status)); exit(EX_OK); }