Ejemplo n.º 1
0
int spawn(char *program, char *argv[], int sin, int sout, int serr,
          int search, char *envp[], char *pty_name, int wait)
{
    pid_t pid;
    int fd;
    int channel[2];
    sigset_t sset;

    channel[0] = -1;
    channel[1] = -1;
    if (!pipe(channel)) {
        if (-1==fcntl(channel[1], F_SETFD,  FD_CLOEXEC)) {
            close(channel[1]);
            channel[1] = -1;
        }
    }

    pid = fork();
    if (pid) {
        if ((-1 != pid) && (-1 != channel[1])) {
            int child_errno = 0;
            int bytes = sizeof(int);
            int n;
            char *p = (char*)&child_errno;
            close(channel[1]);
            /* Try to read child errno from channel. */
            while ((bytes > 0) &&
                   (n = read(channel[0], p, bytes))) {
                if (-1 == n) {
                    if (EINTR == errno) {
                        continue;
                    } else {
                        break;
                    }
                } else {
                    bytes -= n;
                    p += n;
                }
            }
            close(channel[0]);
            if (child_errno) {
                waitpid(pid, NULL, 0);
                /* Our convention to tell Lisp that it was the exec that
                 * failed, not the fork. */
                pid = -2;
                errno = child_errno;
            }
        }
        return pid;
    }
    close (channel[0]);

    /* Put us in our own process group, but only if we need not
     * share stdin with our parent. In the latter case we claim
     * control of the terminal. */
    if (sin >= 0) {
#if defined(LISP_FEATURE_HPUX) || defined(LISP_FEATURE_OPENBSD)
      setsid();
#elif defined(LISP_FEATURE_DARWIN)
      setpgid(0, getpid());
#elif defined(SVR4) || defined(__linux__) || defined(__osf__)
      setpgrp();
#else
      setpgrp(0, getpid());
#endif
    } else {
      tcsetpgrp(0, getpgrp());
    }

    /* unblock signals */
    sigemptyset(&sset);
    sigprocmask(SIG_SETMASK, &sset, NULL);

    /* If we are supposed to be part of some other pty, go for it. */
    if (pty_name)
        set_pty(pty_name);
    else {
    /* Set up stdin, stdout, and stderr */
    if (sin >= 0)
        dup2(sin, 0);
    if (sout >= 0)
        dup2(sout, 1);
    if (serr >= 0)
        dup2(serr, 2);
    }
    /* Close all other fds. */
#ifdef SVR4
    for (fd = sysconf(_SC_OPEN_MAX)-1; fd >= 3; fd--)
        if (fd != channel[1]) close(fd);
#else
    for (fd = getdtablesize()-1; fd >= 3; fd--)
        if (fd != channel[1]) close(fd);
#endif

    if (envp) {
      environ = envp;
    }
    /* Exec the program. */
    if (search)
      execvp(program, argv);
    else
      execv(program, argv);

    /* When exec fails and channel is available, send the errno value. */
    if (-1 != channel[1]) {
        int our_errno = errno;
        int bytes = sizeof(int);
        int n;
        char *p = (char*)&our_errno;
        while ((bytes > 0) &&
               (n = write(channel[1], p, bytes))) {
            if (-1 == n) {
                if (EINTR == errno) {
                    continue;
                } else {
                    break;
                }
            } else {
                bytes -= n;
                p += n;
            }
        }
        close(channel[1]);
    }
    _exit(1);
}
Ejemplo n.º 2
0
int spawn(char *program, char *argv[], int sin, int sout, int serr,
          int search, char *envp[], char *pty_name, int wait)
{
    int pid = fork();
    int fd;
    sigset_t sset;

    if (pid != 0)
        return pid;

    /* Put us in our own process group, but only if we need not
     * share stdin with our parent. In the latter case we claim
     * control of the terminal. */
    if (sin >= 0) {
#if defined(LISP_FEATURE_HPUX) || defined(LISP_FEATURE_OPENBSD)
      setsid();
#elif defined(LISP_FEATURE_DARWIN)
      setpgid(0, getpid());
#elif defined(SVR4) || defined(__linux__) || defined(__osf__)
      setpgrp();
#else
      setpgrp(0, getpid());
#endif
    } else {
      tcsetpgrp(0, getpgrp());
    }

    /* unblock signals */
    sigemptyset(&sset);
    sigprocmask(SIG_SETMASK, &sset, NULL);

    /* If we are supposed to be part of some other pty, go for it. */
    if (pty_name)
        set_pty(pty_name);
    else {
    /* Set up stdin, stdout, and stderr */
    if (sin >= 0)
        dup2(sin, 0);
    if (sout >= 0)
        dup2(sout, 1);
    if (serr >= 0)
        dup2(serr, 2);
    }
    /* Close all other fds. */
#ifdef SVR4
    for (fd = sysconf(_SC_OPEN_MAX)-1; fd >= 3; fd--)
        close(fd);
#else
    for (fd = getdtablesize()-1; fd >= 3; fd--)
        close(fd);
#endif

    environ = envp;
    /* Exec the program. */
    if (search)
      execvp(program, argv);
    else
      execv(program, argv);

    exit (1);
}