2 * Unix support for the Lisp function RUN-PROGRAM and friends
6 * This software is part of the SBCL system. See the README file for
9 * This software is derived from the CMU CL system, which was
10 * written at Carnegie Mellon University and released into the
11 * public domain. The software is in the public domain and is
12 * provided with absolutely no warranty. See the COPYING and CREDITS
13 * files for more information.
17 /* glibc won't give us close_range without this */
21 #include "genesis/sbcl.h"
24 #include <sys/types.h>
28 #include <sys/ioctl.h>
31 #include <sys/ioctl.h>
35 #include <sys/syscall.h>
36 #include "interr.h" // for lose()
38 #ifdef LISP_FEATURE_OPENBSD
42 /* borrowed from detachtty's detachtty.c, in turn borrowed from APUE
43 * example code found at
44 * http://www.yendor.com/programming/unix/apue/pty/main.c
50 int set_noecho(int fd
)
52 struct termios stermios
;
54 if (tcgetattr(fd
, &stermios
) < 0) return 0;
56 stermios
.c_lflag
&= ~( ECHO
| /* ECHOE | ECHOK | */ ECHONL
);
57 stermios
.c_oflag
|= (ONLCR
);
58 stermios
.c_iflag
&= ~(BRKINT
);
59 stermios
.c_iflag
|= (ICANON
|ICRNL
);
61 stermios
.c_cc
[VERASE
]=0177;
62 if (tcsetattr(fd
, TCSANOW
, &stermios
) < 0) return 0;
66 #if defined(LISP_FEATURE_OPENBSD)
69 set_pty(char *pty_name
)
73 if ((fd
= open(pty_name
, O_RDWR
, 0)) == -1 ||
76 return (set_noecho(STDIN_FILENO
));
79 #else /* !LISP_FEATURE_OPENBSD */
82 set_pty(char *pty_name
)
86 #if !defined(SVR4) && !defined(__HAIKU__)
87 fd
= open("/dev/tty", O_RDWR
, 0);
89 ioctl(fd
, TIOCNOTTY
, 0);
93 if ((fd
= open(pty_name
, O_RDWR
, 0)) == -1)
103 #endif /* !LISP_FEATURE_OPENBSD */
105 int closefrom_fddir(char *dir
, int lowfd
)
111 /* This may fail if e.g. the program is running in
112 * a chroot that does not include /proc, or potentially
113 * on old kernel versions. */
117 for (ent
= readdir(d
); ent
; ent
= readdir(d
)) {
118 /* atoi will return bogus values for certain inputs, but lowfd will
119 * prevent us from closing anything we care about. */
120 fd
= atoi(ent
->d_name
);
121 if (fd
>= 0 && fd
>= lowfd
)
128 void closefds_range(unsigned int first
, unsigned int last
)
131 // Try using close_range syscall first.
132 #if defined(LISP_FEATURE_OS_PROVIDES_CLOSE_RANGE_WRAPPER)
133 // Prefer the libc wrapper, if it exists at build time.
134 fds_closed
= !close_range(first
, last
, 0);
135 #elif defined(LISP_FEATURE_LINUX) && defined(__NR_close_range)
136 // Use syscall(2) if we could detect the syscall number at build time.
137 fds_closed
= !syscall(__NR_close_range
, first
, last
, 0);
139 // Otherwise (if the syscall information isn't availble at build time or if
140 // the run time kernel doesn't support the syscall), fall back to close()
144 unsigned int close_fd
;
147 #if defined SVR4 || defined LISP_FEATURE_ANDROID
148 last
= sysconf(_SC_OPEN_MAX
)-1;
150 last
= getdtablesize()-1;
153 for (close_fd
= first
; close_fd
<= last
; close_fd
++)
160 void closefds_from(int lowfd
, int* dont_close
)
163 /* dont_close is a sorted simple-array of tagged ints */
164 uword_t length
= fixnum_value(((uword_t
*)dont_close
)[-1]);
166 for (i
= 0; i
< length
; i
++)
168 int fd
= dont_close
[i
];
169 closefds_range(lowfd
, fd
- 1);
174 #if defined(LISP_FEATURE_OPENBSD) || defined(LISP_FEATURE_NETBSD) \
175 || defined(LISP_FEATURE_DRAGONFLY) || defined(LISP_FEATURE_FREEBSD) \
176 || defined(LISP_FEATURE_SUNOS)
181 /* readdir() uses malloc, which is prone to deadlocking
182 #ifdef LISP_FEATURE_LINUX
184 fds_closed = !closefrom_fddir("/proc/self/fd/", lowfd);
186 #ifdef LISP_FEATURE_DARWIN
188 fds_closed = !closefrom_fddir("/dev/fd/", lowfd);
193 closefds_range(lowfd
, ~0U);
197 int wait_for_exec(int pid
, int channel
[2]) {
198 if ((-1 != pid
) && (-1 != channel
[1])) {
200 int bytes
= sizeof(int);
202 char *p
= (char*)&child_errno
;
204 /* Try to read child errno from channel. */
205 while ((bytes
> 0) &&
206 (n
= read(channel
[0], p
, bytes
))) {
208 if (EINTR
== errno
) {
221 waitpid(pid
, &status
, 0);
222 /* Our convention to tell Lisp that it was the exec or
223 chdir that failed, not the fork. */
224 /* FIXME: there are other values waitpid(2) can return. */
225 if (WIFEXITED(status
)) {
226 pid
= -WEXITSTATUS(status
);
234 extern char **environ
;
237 #ifdef LISP_FEATURE_OS_PROVIDES_POSIX_SPAWN
240 int pspawn(char *program
, char *argv
[], int sin
, int sout
, int serr
,
241 int search
, char *envp
[], __attribute__((unused
)) char *pty_name
,
242 __attribute__((unused
)) char *pwd
, __attribute__((unused
)) int* dont_close
)
245 posix_spawn_file_actions_t actions
;
246 posix_spawnattr_t attr
;
247 short flags
= POSIX_SPAWN_SETSIGMASK
;
249 posix_spawn_file_actions_init(&actions
);
250 posix_spawnattr_init(&attr
);
255 posix_spawnattr_setsigmask(&attr
, &sset
);
258 posix_spawn_file_actions_adddup2(&actions
, sin
, 0);
259 flags
|= POSIX_SPAWN_SETPGROUP
;
262 #ifdef LISP_FEATURE_DARWIN
263 posix_spawn_file_actions_addinherit_np(&actions
, 0);
267 posix_spawn_file_actions_adddup2(&actions
, sout
, 1);
270 #ifdef LISP_FEATURE_DARWIN
271 posix_spawn_file_actions_addinherit_np(&actions
, 1);
275 posix_spawn_file_actions_adddup2(&actions
, serr
, 2);
278 #ifdef LISP_FEATURE_DARWIN
279 posix_spawn_file_actions_addinherit_np(&actions
, 2);
283 #ifdef LISP_FEATURE_DARWIN
284 flags
|= POSIX_SPAWN_CLOEXEC_DEFAULT
;
285 #elif defined LISP_FEATURE_LINUX
286 posix_spawn_file_actions_addclosefrom_np(&actions
, 3);
289 posix_spawnattr_setflags(&attr
, flags
);
294 ret
= posix_spawnp(&pid
, program
, &actions
, &attr
, argv
, envp
);
296 ret
= posix_spawn(&pid
, program
, &actions
, &attr
, argv
, envp
);
298 posix_spawn_file_actions_destroy(&actions
);
299 posix_spawnattr_destroy(&attr
);
310 int spawn(char *program
, char *argv
[], int sin
, int sout
, int serr
,
311 int search
, char *envp
[], char *pty_name
,
313 char *pwd
, int* dont_close
)
317 int failure_code
= 2;
325 /* Put us in our own process group, but only if we need not
326 * share stdin with our parent. In the latter case we claim
327 * control of the terminal. */
329 #ifdef LISP_FEATURE_OPENBSD
331 #elif defined(LISP_FEATURE_DARWIN)
332 setpgid(0, getpid());
333 #elif defined SVR4 || defined __linux__ || defined __osf__ || defined __GLIBC__ || defined __HAIKU__
336 setpgrp(0, getpid());
339 tcsetpgrp(0, getpgrp());
342 /* unblock signals */
344 sigprocmask(SIG_SETMASK
, &sset
, NULL
);
346 /* If we are supposed to be part of some other pty, go for it. */
350 /* Set up stdin, stdout, and stderr */
358 /* Close all other fds. First arrange for the pipe fd to be the
359 * lowest free fd, then close every open fd above that. */
360 channel
[1] = dup2(channel
[1], 3);
361 closefds_from(4, dont_close
);
363 if (-1 != channel
[1]) {
364 if (-1==fcntl(channel
[1], F_SETFD
, FD_CLOEXEC
)) {
370 if (pwd
&& chdir(pwd
) < 0) {
376 /* Exec the program. */
378 execvp(program
, argv
);
380 execv(program
, argv
);
383 /* When exec or chdir fails and channel is available, send the errno value. */
384 if (-1 != channel
[1]) {
385 int our_errno
= errno
;
386 int bytes
= sizeof(int);
388 char *p
= (char*)&our_errno
;
389 while ((bytes
> 0) &&
390 (n
= write(channel
[1], p
, bytes
))) {
392 if (EINTR
== errno
) {