Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / libcc.ansi / stdlib / system.c
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  */
5 /* $Id: system.c,v 1.5 1994/06/24 11:54:20 ceriel Exp $ */
6
7 #if     defined(_POSIX_SOURCE)
8 #include        <sys/types.h>
9 #endif
10 #include        <stdlib.h>
11 #include        <signal.h>
12
13 extern int _fork(void);
14 extern int _wait(int *);
15 extern void _exit(int);
16 extern void _execve(const char *path, const char ** argv, const char ** envp);
17 extern void _close(int);
18
19 #define FAIL    127
20
21 extern const char **_penvp;
22 static const char *exec_tab[] = {
23         "sh",                   /* argv[0] */
24         "-c",                   /* argument to the shell */
25         NULL,                   /* to be filled with user command */
26         NULL                    /* terminating NULL */
27         };
28
29 int
30 system(const char *str)
31 {
32         int pid, exitstatus, waitval;
33         int i;
34
35         if ((pid = _fork()) < 0) return str ? -1 : 0;
36
37         if (pid == 0) {
38                 for (i = 3; i <= 20; i++)
39                         _close(i);
40                 if (!str) str = "cd .";         /* just testing for a shell */
41                 exec_tab[2] = str;              /* fill in command */
42                 _execve("/bin/sh", exec_tab, _penvp);
43                 /* get here if execve fails ... */
44                 _exit(FAIL);    /* see manual page */
45         }
46         while ((waitval = _wait(&exitstatus)) != pid) {
47                 if (waitval == -1) break;
48         }
49         if (waitval == -1) {
50                 /* no child ??? or maybe interrupted ??? */
51                 exitstatus = -1;
52         }
53         if (!str) {
54                 if (exitstatus == FAIL << 8)            /* execve() failed */
55                         exitstatus = 0;
56                 else exitstatus = 1;                    /* /bin/sh exists */
57         }
58         return exitstatus;
59 }