1 /*
2 Copyright (c) 1990 Regents of the University of California.
3 All rights reserved.
4 */
5 /*
6 FUNCTION
7 <<system>>---execute command string
8
9 INDEX
10 system
11 INDEX
12 _system_r
13
14 SYNOPSIS
15 #include <stdlib.h>
16 int system(char *<[s]>);
17
18 int _system_r(void *<[reent]>, char *<[s]>);
19
20 DESCRIPTION
21
22 Use <<system>> to pass a command string <<*<[s]>>> to <</bin/sh>> on
23 your system, and wait for it to finish executing.
24
25 Use ``<<system(NULL)>>'' to test whether your system has <</bin/sh>>
26 available.
27
28 The alternate function <<_system_r>> is a reentrant version. The
29 extra argument <[reent]> is a pointer to a reentrancy structure.
30
31 RETURNS
32 <<system(NULL)>> returns a non-zero value if <</bin/sh>> is available, and
33 <<0>> if it is not.
34
35 With a command argument, the result of <<system>> is the exit status
36 returned by <</bin/sh>>.
37
38 PORTABILITY
39 ANSI C requires <<system>>, but leaves the nature and effects of a
40 command processor undefined. ANSI C does, however, specify that
41 <<system(NULL)>> return zero or nonzero to report on the existence of
42 a command processor.
43
44 POSIX.2 requires <<system>>, and requires that it invoke a <<sh>>.
45 Where <<sh>> is found is left unspecified.
46
47 Supporting OS subroutines required: <<_exit>>, <<_execve>>, <<_fork_r>>,
48 <<_wait_r>>.
49 */
50
51 #include <errno.h>
52 #include <stddef.h>
53 #include <stdlib.h>
54 #include <unistd.h>
55 #include <_syslist.h>
56 #include <sys/wait.h>
57
58 #if defined (unix) || defined (__CYGWIN__)
59 static int do_system (const char *s);
60 #endif
61
62 #ifndef _REENT_ONLY
63
64 int
system(const char * s)65 system (const char *s)
66 {
67 #if defined(HAVE_SYSTEM)
68 return _system (s);
69 #elif defined(NO_EXEC)
70 if (s == NULL)
71 return 0;
72 errno = ENOSYS;
73 return -1;
74 #else
75
76 /* ??? How to handle (s == NULL) here is not exactly clear.
77 If _fork_r fails, that's not really a justification for returning 0.
78 For now we always return 0 and leave it to each target to explicitly
79 handle otherwise (this can always be relaxed in the future). */
80
81 #if defined (unix) || defined (__CYGWIN__)
82 if (s == NULL)
83 return 1;
84 return do_system (s);
85 #else
86 if (s == NULL)
87 return 0;
88 errno = ENOSYS;
89 return -1;
90 #endif
91
92 #endif
93 }
94
95 #endif
96
97 #if defined (unix) && !defined (__CYGWIN__) && !defined(__rtems__)
98 extern char **environ;
99
100 /* Only deal with a pointer to environ, to work around subtle bugs with shared
101 libraries and/or small data systems where the user declares his own
102 'environ'. */
103 static char ***p_environ = &environ;
104
105 static int
do_system(const char * s)106 do_system (const char *s)
107 {
108 char *argv[4];
109 int pid, status;
110
111 argv[0] = "sh";
112 argv[1] = "-c";
113 argv[2] = (char *) s;
114 argv[3] = NULL;
115
116 if ((pid = fork ()) == 0)
117 {
118 execve ("/bin/sh", argv, *p_environ);
119 exit (100);
120 }
121 else if (pid == -1)
122 return -1;
123 else
124 {
125 int rc = wait (&status);
126 if (rc == -1)
127 return -1;
128 status = (status >> 8) & 0xff;
129 return status;
130 }
131 }
132 #endif
133
134