Пример #1
0
/* Close stdin, stdout, stderr.  If we're started from e.g. an SSH session,
 * then this keeps us from holding that session open artificially. */
static void
close_standard_fds(void)
{
    int null_fd = get_null_fd();
    if (null_fd >= 0) {
        dup2(null_fd, STDIN_FILENO);
        dup2(null_fd, STDOUT_FILENO);
        dup2(null_fd, STDERR_FILENO);
    }
}
Пример #2
0
/* Close stdin, stdout, stderr.  If we're started from e.g. an SSH session,
 * then this keeps us from holding that session open artificially. */
static void
close_standard_fds(void)
{
    int null_fd = get_null_fd();
    if (null_fd >= 0) {
        dup2(null_fd, STDIN_FILENO);
        dup2(null_fd, STDOUT_FILENO);
        dup2(null_fd, STDERR_FILENO);
    }

    /* Disable logging to stderr to avoid wasting CPU time. */
    vlog_set_levels(NULL, VLF_CONSOLE, VLL_OFF);
}
Пример #3
0
/* Close standard file descriptors (except any that the client has requested we
 * leave open by calling daemon_save_fd()).  If we're started from e.g. an SSH
 * session, then this keeps us from holding that session open artificially. */
void close_standard_fds(void)
{
    int null_fd = get_null_fd();
    if (null_fd >= 0) {
        int fd;

        for (fd = 0; fd < 3; fd++) {
            if (!save_fds[fd]) {
                dup2(null_fd, fd);
            }
        }
    }

    /* Disable logging to stderr to avoid wasting CPU time. */
    //vlog_set_levels(NULL, VLF_CONSOLE, VLL_OFF);
}
Пример #4
0
int spawn(const char* file, char* const* argv, char* const* envv,
    const char* cwd, int outfd) {
  int err_fds[2] = { -1, -1 };
  pid_t child_pid = 0;
  int spawn_error, r;
  size_t bytes_read;

  if (pipe(err_fds) < 0)
    goto error;

  child_pid = fork();
  if (child_pid < 0)
    goto error;
    
  if (child_pid == 0) {
    /* We are the child. */
    int e;

    close(err_fds[0]);

    if (ioctl(err_fds[1], FIOCLEX, NULL) < 0)
      goto error;

    if (dup2(get_null_fd(), 0) < 0)
      goto child_error;

    if (dup2(outfd, 1) < 0)
      goto child_error;

    if (dup2(outfd, 2) < 0)
      goto child_error;

    if (chdir(cwd) < 0)
      goto child_error;

    if (setpgrp() < 0)
      goto child_error;      

    environ = (char**) envv;
    
    execvp(file, argv);
    
   child_error:
    e = errno;
    r = write(err_fds[1], &e, sizeof e);
    USE(r);
    exit(127);
  }

  close(err_fds[1]);
  err_fds[1] = -1;

  spawn_error = 0;
  bytes_read = 0;

  while (bytes_read < sizeof spawn_error) {
    r = read(err_fds[0],
             bytes_read + (char*) &spawn_error,
             sizeof spawn_error - bytes_read);
    if (r == -1 && errno == EINTR)
      continue;
    if (r == -1)
      goto error;
    if (r == 0)
      break;
    bytes_read += r;
  }

  if (bytes_read == 4) {
    errno = spawn_error;
    goto error;
  }

  if (r != 0)
    goto error;

  close(err_fds[0]);
  return child_pid;

 error: {
    int saved_errno = errno;

    if (err_fds[0] != -1)
      close(err_fds[0]);
    if (err_fds[1] != -1)
      close(err_fds[1]);
    if (child_pid > 0)
      kill(-child_pid, SIGKILL);

    printf("spawn error %s\n", strerror(saved_errno));

    errno = saved_errno;
    return -1;
  }
}
Пример #5
0
/* Starts the process whose arguments are given in the null-terminated array
 * 'argv' and waits for it to exit.  On success returns 0 and stores the
 * process exit value (suitable for passing to process_status_msg()) in
 * '*status'.  On failure, returns a positive errno value and stores 0 in
 * '*status'.
 *
 * If 'stdout_log' is nonnull, then the subprocess's output to stdout (up to a
 * limit of PROCESS_MAX_CAPTURE bytes) is captured in a memory buffer, which
 * when this function returns 0 is stored as a null-terminated string in
 * '*stdout_log'.  The caller is responsible for freeing '*stdout_log' (by
 * passing it to free()).  When this function returns an error, '*stdout_log'
 * is set to NULL.
 *
 * If 'stderr_log' is nonnull, then it is treated like 'stdout_log' except
 * that it captures the subprocess's output to stderr. */
int
process_run_capture(char **argv, char **stdout_log, char **stderr_log,
                    int *status)
{
    struct stream s_stdout, s_stderr;
    sigset_t oldsigs;
    pid_t pid;
    int error;

    COVERAGE_INC(process_run_capture);
    if (stdout_log) {
        *stdout_log = NULL;
    }
    if (stderr_log) {
        *stderr_log = NULL;
    }
    *status = 0;
    error = process_prestart(argv);
    if (error) {
        return error;
    }

    error = stream_open(&s_stdout);
    if (error) {
        return error;
    }

    error = stream_open(&s_stderr);
    if (error) {
        stream_close(&s_stdout);
        return error;
    }

    block_sigchld(&oldsigs);
    pid = fork();
    if (pid < 0) {
        int error = errno;

        unblock_sigchld(&oldsigs);
        VLOG_WARN("fork failed: %s", strerror(error));

        stream_close(&s_stdout);
        stream_close(&s_stderr);
        *status = 0;
        return error;
    } else if (pid) {
        /* Running in parent process. */
        struct process *p;

        p = process_register(argv[0], pid);
        unblock_sigchld(&oldsigs);

        close(s_stdout.fds[1]);
        close(s_stderr.fds[1]);
        while (!process_exited(p)) {
            stream_read(&s_stdout);
            stream_read(&s_stderr);

            stream_wait(&s_stdout);
            stream_wait(&s_stderr);
            process_wait(p);
            poll_block();
        }
        stream_read(&s_stdout);
        stream_read(&s_stderr);

        if (stdout_log) {
            *stdout_log = ds_steal_cstr(&s_stdout.log);
        }
        if (stderr_log) {
            *stderr_log = ds_steal_cstr(&s_stderr.log);
        }

        stream_close(&s_stdout);
        stream_close(&s_stderr);

        *status = process_status(p);
        process_destroy(p);
        return 0;
    } else {
        /* Running in child process. */
        int max_fds;
        int i;

        fatal_signal_fork();
        unblock_sigchld(&oldsigs);

        dup2(get_null_fd(), 0);
        dup2(s_stdout.fds[1], 1);
        dup2(s_stderr.fds[1], 2);

        max_fds = get_max_fds();
        for (i = 3; i < max_fds; i++) {
            close(i);
        }

        execvp(argv[0], argv);
        fprintf(stderr, "execvp(\"%s\") failed: %s\n",
                argv[0], strerror(errno));
        exit(EXIT_FAILURE);
    }
}