Rev 4874 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4349 | Serge | 1 | /* |
2 | FUNCTION |
||
3 | < |
||
4 | |||
5 | INDEX |
||
6 | system |
||
7 | INDEX |
||
8 | _system_r |
||
9 | |||
10 | ANSI_SYNOPSIS |
||
11 | #include |
||
12 | int system(char *<[s]>); |
||
13 | |||
14 | int _system_r(void *<[reent]>, char *<[s]>); |
||
15 | |||
16 | TRAD_SYNOPSIS |
||
17 | #include |
||
18 | int system(<[s]>) |
||
19 | char *<[s]>; |
||
20 | |||
21 | int _system_r(<[reent]>, <[s]>) |
||
22 | char *<[reent]>; |
||
23 | char *<[s]>; |
||
24 | |||
25 | DESCRIPTION |
||
26 | |||
27 | Use < |
||
28 | your system, and wait for it to finish executing. |
||
29 | |||
30 | Use ``< |
||
31 | available. |
||
32 | |||
33 | The alternate function <<_system_r>> is a reentrant version. The |
||
34 | extra argument <[reent]> is a pointer to a reentrancy structure. |
||
35 | |||
36 | RETURNS |
||
37 | < |
||
38 | <<0>> if it is not. |
||
39 | |||
40 | With a command argument, the result of < |
||
41 | returned by <>. |
||
42 | |||
43 | PORTABILITY |
||
44 | ANSI C requires < |
||
45 | command processor undefined. ANSI C does, however, specify that |
||
46 | < |
||
47 | a command processor. |
||
48 | |||
49 | POSIX.2 requires < |
||
50 | Where < |
||
51 | |||
52 | Supporting OS subroutines required: <<_exit>>, <<_execve>>, <<_fork_r>>, |
||
53 | <<_wait_r>>. |
||
54 | */ |
||
55 | |||
56 | #include <_ansi.h> |
||
57 | #include |
||
58 | #include |
||
59 | #include |
||
60 | #include |
||
61 | #include <_syslist.h> |
||
62 | #include |
||
63 | |||
4921 | Serge | 64 | #if defined (unix) || defined (__CYGWIN__) |
65 | static int _EXFUN(do_system, (struct _reent *ptr _AND _CONST char *s)); |
||
66 | #endif |
||
4349 | Serge | 67 | |
68 | int |
||
69 | _DEFUN(_system_r, (ptr, s), |
||
70 | struct _reent *ptr _AND |
||
71 | _CONST char *s) |
||
72 | { |
||
4921 | Serge | 73 | #if defined(HAVE_SYSTEM) |
74 | return _system (s); |
||
75 | ptr = ptr; |
||
76 | #elif defined(NO_EXEC) |
||
4349 | Serge | 77 | if (s == NULL) |
78 | return 0; |
||
79 | errno = ENOSYS; |
||
80 | return -1; |
||
4921 | Serge | 81 | #else |
82 | |||
83 | /* ??? How to handle (s == NULL) here is not exactly clear. |
||
84 | If _fork_r fails, that's not really a justification for returning 0. |
||
85 | For now we always return 0 and leave it to each target to explicitly |
||
86 | handle otherwise (this can always be relaxed in the future). */ |
||
87 | |||
88 | #if defined (unix) || defined (__CYGWIN__) |
||
89 | if (s == NULL) |
||
90 | return 1; |
||
91 | return do_system (ptr, s); |
||
92 | #else |
||
93 | if (s == NULL) |
||
94 | return 0; |
||
95 | errno = ENOSYS; |
||
96 | return -1; |
||
97 | #endif |
||
98 | |||
99 | #endif |
||
4349 | Serge | 100 | } |
101 | |||
102 | #ifndef _REENT_ONLY |
||
103 | |||
104 | int |
||
105 | _DEFUN(system, (s), |
||
106 | _CONST char *s) |
||
107 | { |
||
108 | return _system_r (_REENT, s); |
||
109 | } |
||
110 | |||
111 | #endif |
||
4921 | Serge | 112 | |
113 | #if defined (unix) && !defined (__CYGWIN__) && !defined(__rtems__) |
||
114 | extern char **environ; |
||
115 | |||
116 | /* Only deal with a pointer to environ, to work around subtle bugs with shared |
||
117 | libraries and/or small data systems where the user declares his own |
||
118 | 'environ'. */ |
||
119 | static char ***p_environ = &environ; |
||
120 | |||
121 | static int |
||
122 | _DEFUN(do_system, (ptr, s), |
||
123 | struct _reent *ptr _AND |
||
124 | _CONST char *s) |
||
125 | { |
||
126 | char *argv[4]; |
||
127 | int pid, status; |
||
128 | |||
129 | argv[0] = "sh"; |
||
130 | argv[1] = "-c"; |
||
131 | argv[2] = (char *) s; |
||
132 | argv[3] = NULL; |
||
133 | |||
134 | if ((pid = _fork_r (ptr)) == 0) |
||
135 | { |
||
136 | _execve ("/bin/sh", argv, *p_environ); |
||
137 | exit (100); |
||
138 | } |
||
139 | else if (pid == -1) |
||
140 | return -1; |
||
141 | else |
||
142 | { |
||
143 | int rc = _wait_r (ptr, &status); |
||
144 | if (rc == -1) |
||
145 | return -1; |
||
146 | status = (status >> 8) & 0xff; |
||
147 | return status; |
||
148 | } |
||
149 | } |
||
150 | #endif |
||
151 | |||
152 | #if defined (__CYGWIN__) |
||
153 | static int |
||
154 | _DEFUN(do_system, (ptr, s), |
||
155 | struct _reent *ptr _AND |
||
156 | _CONST char *s) |
||
157 | { |
||
158 | char *argv[4]; |
||
159 | int pid, status; |
||
160 | |||
161 | argv[0] = "sh"; |
||
162 | argv[1] = "-c"; |
||
163 | argv[2] = (char *) s; |
||
164 | argv[3] = NULL; |
||
165 | |||
166 | if ((pid = vfork ()) == 0) |
||
167 | { |
||
168 | /* ??? It's not clear what's the right path to take (pun intended :-). |
||
169 | There won't be an "sh" in any fixed location so we need each user |
||
170 | to be able to say where to find "sh". That suggests using an |
||
171 | environment variable, but after a few more such situations we may |
||
172 | have too many of them. */ |
||
173 | char *sh = getenv ("SH_PATH"); |
||
174 | if (sh == NULL) |
||
175 | sh = "/bin/sh"; |
||
176 | _execve (sh, argv, environ); |
||
177 | exit (100); |
||
178 | } |
||
179 | else if (pid == -1) |
||
180 | return -1; |
||
181 | else |
||
182 | { |
||
183 | extern int _wait (int *); |
||
184 | int rc = _wait (&status); |
||
185 | if (rc == -1) |
||
186 | return -1; |
||
187 | status = (status >> 8) & 0xff; |
||
188 | return status; |
||
189 | } |
||
190 | } |
||
191 | #endif<_wait_r><_fork_r><_execve><_exit> |