Subversion Repositories Kolibri OS

Rev

Rev 4874 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
/*
2
FUNCTION
3
<>---execute command string
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 <> to pass a command string <<*<[s]>>> to <> on
28
your system, and wait for it to finish executing.
29
 
30
Use ``<>'' to test whether your system has <>
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
<> returns a non-zero value if <> is available, and
38
<<0>> if it is not.
39
 
40
With a command argument, the result of <> is the exit status
41
returned by <>.
42
 
43
PORTABILITY
44
ANSI C requires <>, but leaves the nature and effects of a
45
command processor undefined.  ANSI C does, however, specify that
46
<> return zero or nonzero to report on the existence of
47
a command processor.
48
 
49
POSIX.2 requires <>, and requires that it invoke a <>.
50
Where <> is found is left unspecified.
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