NEURON
system.cpp
Go to the documentation of this file.
1 /*
2 FUNCTION
3 <<system>>---execute command string
4 
5 INDEX
6  system
7 INDEX
8  _system_r
9 
10 ANSI_SYNOPSIS
11  #include <stdlib.h>
12  int system(char *<[s]>);
13 
14  int _system_r(void *<[reent]>, char *<[s]>);
15 
16 TRAD_SYNOPSIS
17  #include <stdlib.h>
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 <<system>> to pass a command string <<*<[s]>>> to <</bin/sh>> on
28 your system, and wait for it to finish executing.
29 
30 Use ``<<system(NULL)>>'' to test whether your system has <</bin/sh>>
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 <<system(NULL)>> returns a non-zero value if <</bin/sh>> is available, and
38 <<0>> if it is not.
39 
40 With a command argument, the result of <<system>> is the exit status
41 returned by <</bin/sh>>.
42 
43 PORTABILITY
44 ANSI C requires <<system>>, but leaves the nature and effects of a
45 command processor undefined. ANSI C does, however, specify that
46 <<system(NULL)>> return zero or nonzero to report on the existence of
47 a command processor.
48 
49 POSIX.2 requires <<system>>, and requires that it invoke a <<sh>>.
50 Where <<sh>> is found is left unspecified.
51 
52 Supporting OS subroutines required: <<_exit>>, <<_execve>>, <<_fork_r>>,
53 <<_wait_r>>.
54 */
55 
56 #include <errno.h>
57 #include <stddef.h>
58 #include <stdlib.h>
59 #include <unistd.h>
60 #include <_syslist.h>
61 #include <reent.h>
62 
63 #if defined (__APPLE__)
64 #include <crt_externs.h>
65 #endif
66 
67 #if defined (unix) || defined (__CYGWIN__)
68 static int do_system ();
69 #endif
70 
71 int
72 _system_r (ptr, s)
73  struct _reent *ptr;
74  _CONST char *s;
75 {
76 #if defined(HAVE_SYSTEM)
77  return _system (s);
78  ptr = ptr;
79 #elif defined(NO_EXEC)
80  if (s == NULL)
81  return 0;
82  errno = ENOSYS;
83  return -1;
84 #else
85 
86  /* ??? How to handle (s == NULL) here is not exactly clear.
87  If _fork_r fails, that's not really a justification for returning 0.
88  For now we always return 0 and leave it to each target to explicitly
89  handle otherwise (this can always be relaxed in the future). */
90 
91 #if defined (unix) || defined (__CYGWIN__)
92  if (s == NULL)
93  return 1;
94  return do_system (ptr, s);
95 #else
96  if (s == NULL)
97  return 0;
98  errno = ENOSYS;
99  return -1;
100 #endif
101 
102 #endif
103 }
104 
105 #ifndef _REENT_ONLY
106 
107 int
108 system (s)
109  _CONST char *s;
110 {
111  return _system_r (_REENT, s);
112 }
113 
114 #endif
115 
116 #if defined (unix) && !defined (__CYGWIN__) && !defined(__rtems__)
117 #if !defined(__APPLE__)
118 extern char **environ;
119 
120 /* Only deal with a pointer to environ, to work around subtle bugs with shared
121  libraries and/or small data systems where the user declares his own
122  'environ'. */
123 static char ***p_environ = &environ;
124 #endif
125 #if defined(__APPLE__)
126 static char ***p_environ = _NSGetEnviron();
127 #endif
128 
129 static int
130 do_system (ptr, s)
131  struct _reent *ptr;
132  _CONST char *s;
133 {
134  char *argv[4];
135  int pid, status;
136 
137  argv[0] = "sh";
138  argv[1] = "-c";
139  argv[2] = (char *) s;
140  argv[3] = NULL;
141 
142  if ((pid = _fork_r (ptr)) == 0)
143  {
144  _execve ("/bin/sh", argv, *p_environ);
145  exit (100);
146  }
147  else if (pid == -1)
148  return -1;
149  else
150  {
151  int rc = _wait_r (ptr, &status);
152  if (rc == -1)
153  return -1;
154  status = (status >> 8) & 0xff;
155  return status;
156  }
157 }
158 #endif
159 
160 #if defined (__CYGWIN__)
161 static int
162 do_system (ptr, s)
163  struct _reent *ptr;
164  _CONST char *s;
165 {
166  char *argv[4];
167  int pid, status;
168 
169  argv[0] = "sh";
170  argv[1] = "-c";
171  argv[2] = (char *) s;
172  argv[3] = NULL;
173 
174  if ((pid = vfork ()) == 0)
175  {
176  /* ??? It's not clear what's the right path to take (pun intended :-).
177  There won't be an "sh" in any fixed location so we need each user
178  to be able to say where to find "sh". That suggests using an
179  environment variable, but after a few more such situations we may
180  have too many of them. */
181  char *sh = getenv ("SH_PATH");
182  if (sh == NULL)
183  sh = "/bin/sh";
184  execve (sh, argv, environ);
185  exit (100);
186  }
187  else if (pid == -1)
188  return -1;
189  else
190  {
191  int rc = wait (&status);
192  if (rc == -1)
193  return -1;
194  status = (status >> 8) & 0xff;
195  return status;
196  }
197 }
198 #endif
int system(s) _CONST char *s
int _system_r(ptr, s) struct _reent *ptr
return status
_CONST char * s
Definition: system.cpp:74
errno
Definition: system.cpp:98
char * getenv(const char *s)
Definition: macprt.cpp:67
return NULL
Definition: cabcode.cpp:461
static char ** argv
Definition: inithoc.cpp:54