ad5d00c7d368403bbf5795efd35d1621de1e1a0a
[projects/cmucl/cmucl.git] / src / lisp / runprog.c
1 /*
2  * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/runprog.c,v 1.7 2005/09/15 18:26:52 rtoy Rel $
3  *
4  * Support for run-program.
5  *
6  */
7
8 #include <sys/ioctl.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <signal.h>
12 #include <stdlib.h>
13 #include <termios.h>
14 #include <unistd.h>
15
16 pid_t
17 spawn(char *program, char *argv[], char *envp[], char *pty_name,
18       int stdin, int stdout, int stderr)
19 {
20     pid_t pid;
21     sigset_t set;
22     int fd;
23
24     pid = fork();
25     if (pid != 0)
26         return pid;
27
28     /* Put us in our own process group. */
29     setsid();
30
31     /* Unblock all signals. */
32     sigemptyset(&set);
33     sigprocmask(SIG_SETMASK, &set, NULL);
34
35     /* If we are supposed to be part of some other pty, go for it. */
36     if (pty_name) {
37 #ifdef TIOCNOTTY
38         fd = open("/dev/tty", O_RDWR, 0);
39         if (fd >= 0) {
40             ioctl(fd, TIOCNOTTY, 0);
41             close(fd);
42         }
43 #endif
44
45         fd = open(pty_name, O_RDWR, 0);
46         dup2(fd, 0);
47         dup2(fd, 1);
48         dup2(fd, 2);
49         close(fd);
50     }
51
52     /* Set up stdin, stdout, and stderr. */
53     if (stdin >= 0)
54         dup2(stdin, 0);
55     if (stdout >= 0)
56         dup2(stdout, 1);
57     if (stderr >= 0)
58         dup2(stderr, 2);
59
60     /* Close all other fds. */
61     for (fd = sysconf(_SC_OPEN_MAX) - 1; fd >= 3; fd--)
62         close(fd);
63
64     /* Exec the program. */
65     execve(program, argv, envp);
66
67     /* It didn't work, so try /bin/sh. */
68     argv[0] = program;
69     argv[-1] = "sh";
70     execve("/bin/sh", argv - 1, envp);
71
72     /* The exec didn't work, flame out. */
73     exit(1);
74 }