Cygwin: mmap: allow remapping part of an existing anonymous mapping
[newlib-cygwin.git] / newlib / libc / stdlib / system.c
blobf30b7df808514b8ae71b7951357a9719dd969204
1 /*
2 FUNCTION
3 <<system>>---execute command string
5 INDEX
6 system
7 INDEX
8 _system_r
10 SYNOPSIS
11 #include <stdlib.h>
12 int system(char *<[s]>);
14 int _system_r(void *<[reent]>, char *<[s]>);
16 DESCRIPTION
18 Use <<system>> to pass a command string <<*<[s]>>> to <</bin/sh>> on
19 your system, and wait for it to finish executing.
21 Use ``<<system(NULL)>>'' to test whether your system has <</bin/sh>>
22 available.
24 The alternate function <<_system_r>> is a reentrant version. The
25 extra argument <[reent]> is a pointer to a reentrancy structure.
27 RETURNS
28 <<system(NULL)>> returns a non-zero value if <</bin/sh>> is available, and
29 <<0>> if it is not.
31 With a command argument, the result of <<system>> is the exit status
32 returned by <</bin/sh>>.
34 PORTABILITY
35 ANSI C requires <<system>>, but leaves the nature and effects of a
36 command processor undefined. ANSI C does, however, specify that
37 <<system(NULL)>> return zero or nonzero to report on the existence of
38 a command processor.
40 POSIX.2 requires <<system>>, and requires that it invoke a <<sh>>.
41 Where <<sh>> is found is left unspecified.
43 Supporting OS subroutines required: <<_exit>>, <<_execve>>, <<_fork_r>>,
44 <<_wait_r>>.
47 #include <_ansi.h>
48 #include <errno.h>
49 #include <stddef.h>
50 #include <stdlib.h>
51 #include <unistd.h>
52 #include <_syslist.h>
53 #include <reent.h>
55 #if defined (unix) || defined (__CYGWIN__)
56 static int do_system (struct _reent *ptr, const char *s);
57 #endif
59 int
60 _system_r (struct _reent *ptr,
61 const char *s)
63 #if defined(HAVE_SYSTEM)
64 return _system (s);
65 ptr = ptr;
66 #elif defined(NO_EXEC)
67 if (s == NULL)
68 return 0;
69 errno = ENOSYS;
70 return -1;
71 #else
73 /* ??? How to handle (s == NULL) here is not exactly clear.
74 If _fork_r fails, that's not really a justification for returning 0.
75 For now we always return 0 and leave it to each target to explicitly
76 handle otherwise (this can always be relaxed in the future). */
78 #if defined (unix) || defined (__CYGWIN__)
79 if (s == NULL)
80 return 1;
81 return do_system (ptr, s);
82 #else
83 if (s == NULL)
84 return 0;
85 errno = ENOSYS;
86 return -1;
87 #endif
89 #endif
92 #ifndef _REENT_ONLY
94 int
95 system (const char *s)
97 return _system_r (_REENT, s);
100 #endif
102 #if defined (unix) && !defined (__CYGWIN__) && !defined(__rtems__)
103 extern char **environ;
105 /* Only deal with a pointer to environ, to work around subtle bugs with shared
106 libraries and/or small data systems where the user declares his own
107 'environ'. */
108 static char ***p_environ = &environ;
110 static int
111 do_system (struct _reent *ptr,
112 const char *s)
114 char *argv[4];
115 int pid, status;
117 argv[0] = "sh";
118 argv[1] = "-c";
119 argv[2] = (char *) s;
120 argv[3] = NULL;
122 if ((pid = _fork_r (ptr)) == 0)
124 _execve ("/bin/sh", argv, *p_environ);
125 exit (100);
127 else if (pid == -1)
128 return -1;
129 else
131 int rc = _wait_r (ptr, &status);
132 if (rc == -1)
133 return -1;
134 status = (status >> 8) & 0xff;
135 return status;
138 #endif
140 #if defined (__CYGWIN__)
141 static int
142 do_system (struct _reent *ptr,
143 const char *s)
145 char *argv[4];
146 int pid, status;
148 argv[0] = "sh";
149 argv[1] = "-c";
150 argv[2] = (char *) s;
151 argv[3] = NULL;
153 if ((pid = vfork ()) == 0)
155 /* ??? It's not clear what's the right path to take (pun intended :-).
156 There won't be an "sh" in any fixed location so we need each user
157 to be able to say where to find "sh". That suggests using an
158 environment variable, but after a few more such situations we may
159 have too many of them. */
160 char *sh = getenv ("SH_PATH");
161 if (sh == NULL)
162 sh = "/bin/sh";
163 _execve (sh, argv, environ);
164 exit (100);
166 else if (pid == -1)
167 return -1;
168 else
170 extern int _wait (int *);
171 int rc = _wait (&status);
172 if (rc == -1)
173 return -1;
174 status = (status >> 8) & 0xff;
175 return status;
178 #endif