newlib-cygwin/newlib/libc/stdlib/system.c

179 lines
3.8 KiB
C
Raw Normal View History

2000-02-18 03:39:52 +08:00
/*
FUNCTION
<<system>>---execute command string
INDEX
system
INDEX
_system_r
SYNOPSIS
2000-02-18 03:39:52 +08:00
#include <stdlib.h>
int system(char *<[s]>);
int _system_r(void *<[reent]>, char *<[s]>);
DESCRIPTION
Use <<system>> to pass a command string <<*<[s]>>> to <</bin/sh>> on
your system, and wait for it to finish executing.
Use ``<<system(NULL)>>'' to test whether your system has <</bin/sh>>
2000-02-18 03:39:52 +08:00
available.
The alternate function <<_system_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure.
RETURNS
<<system(NULL)>> returns a non-zero value if <</bin/sh>> is available, and
<<0>> if it is not.
With a command argument, the result of <<system>> is the exit status
returned by <</bin/sh>>.
PORTABILITY
ANSI C requires <<system>>, but leaves the nature and effects of a
command processor undefined. ANSI C does, however, specify that
<<system(NULL)>> return zero or nonzero to report on the existence of
a command processor.
POSIX.2 requires <<system>>, and requires that it invoke a <<sh>>.
Where <<sh>> is found is left unspecified.
Supporting OS subroutines required: <<_exit>>, <<_execve>>, <<_fork_r>>,
<<_wait_r>>.
*/
2008-12-11 Craig Howland <howland@LGSInnovations.com> * libc/include/sys/lock.h: Add void cast to avoid "statement has no effect" warnings from gcc. * libc/include/sys/stdio.h: Ditto. * libc/include/sys/time.h: Correct gettimeofday() prototype. * libc/stdlib/__exp10.c: Add #include "std.h" for function prototype. * libc/stdlib/__ten_mu.c: Ditto. * libc/stdlib/std.h: Correct __exp10's ANSI prototype. * libc/stdlib/ldtoa.c: Change eiisinf definition to ANSI form. (Are already others in file without _ansi method, so did not bother.) * libc/stdlib/system.c: Use _ansi forms for function prototypes and definitions. * libc/time/mktime.c: Ditto. * libc/misc/__dprintf.c: Ditto. * libc/include/stdio.h: Add function prototypes for _fgetc_r, _fgetpos_r, _fsetpos_r, _freopen_r, _rewind_r, freopen64, _freopen64_r, _funopen_r, and _fopencookie_r. * libc/include/reent.h: Add function prototype for _stat64_r, align _execve_r prototype with POSIX definition for execve. * libc/reent/execr.c: Align function prototype with POSIX definition. * libc/stdio/asniprintf.c: Add #include "local.h". * libc/stdio/vasniprintf.c: Ditto. * libc/stdio/fread.c: Remove unused variable newcount. * libc/stdio/local.h: Add function prototype for __sccl. * libc/stdio/open_memstream.c: Remove unused variable flags. * libc/stdio/vfscanf.c: Proper prototyping for ccfn, remove prototype for __sccl since now in local.h. * libc/string/memcpy.c: Add #include <string.h> (for real and for traditional synopsis), remove extraneous stddef.h and limits.h. * libc/syscalls/sysclose.c: Add #include <unistd.h>. * libc/syscalls/sysfork.c: Ditto. * libc/syscalls/sysgetpid.c: Ditto. * libc/syscalls/sysexecve.c: Add #include <unistd.h>, align function prototype with POSIX definition. * libc/syscalls/sysfstat.c: Add #include <sys/stat.h>. * libc/syscalls/sysgettod.c: Correct sys/times.h to sys/time.h. * libc/syscalls/syskill.c: Add #include <signal.h>. * libc/syscalls/syslink.c: Add #include <unistd.h>, fix prototype. * libc/syscalls/sysunlink.c: Ditto. * libc/syscalls/sysstat.c: Add #include <sys/stat.h>, fix prototype. * libc/syscalls/syswait.c: Add #include <sys/wait.h>, fix prototype.
2008-12-12 01:27:56 +08:00
#include <_ansi.h>
2000-02-18 03:39:52 +08:00
#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
2000-02-18 03:39:52 +08:00
#include <_syslist.h>
#include <reent.h>
2000-02-18 03:39:52 +08:00
#if defined (unix) || defined (__CYGWIN__)
static int do_system (struct _reent *ptr, const char *s);
2000-02-18 03:39:52 +08:00
#endif
int
_system_r (struct _reent *ptr,
const char *s)
2000-02-18 03:39:52 +08:00
{
#if defined(HAVE_SYSTEM)
return _system (s);
ptr = ptr;
#elif defined(NO_EXEC)
2000-02-18 03:39:52 +08:00
if (s == NULL)
return 0;
errno = ENOSYS;
return -1;
#else
/* ??? How to handle (s == NULL) here is not exactly clear.
If _fork_r fails, that's not really a justification for returning 0.
For now we always return 0 and leave it to each target to explicitly
handle otherwise (this can always be relaxed in the future). */
#if defined (unix) || defined (__CYGWIN__)
2000-02-18 03:39:52 +08:00
if (s == NULL)
return 1;
return do_system (ptr, s);
#else
if (s == NULL)
return 0;
errno = ENOSYS;
return -1;
#endif
#endif
}
#ifndef _REENT_ONLY
int
system (const char *s)
2000-02-18 03:39:52 +08:00
{
return _system_r (_REENT, s);
}
#endif
#if defined (unix) && !defined (__CYGWIN__) && !defined(__rtems__)
extern char **environ;
/* Only deal with a pointer to environ, to work around subtle bugs with shared
libraries and/or small data systems where the user declares his own
'environ'. */
static char ***p_environ = &environ;
2000-02-18 03:39:52 +08:00
static int
do_system (struct _reent *ptr,
const char *s)
2000-02-18 03:39:52 +08:00
{
char *argv[4];
int pid, status;
argv[0] = "sh";
argv[1] = "-c";
argv[2] = (char *) s;
argv[3] = NULL;
if ((pid = _fork_r (ptr)) == 0)
{
_execve ("/bin/sh", argv, *p_environ);
2000-02-18 03:39:52 +08:00
exit (100);
}
else if (pid == -1)
return -1;
else
{
int rc = _wait_r (ptr, &status);
if (rc == -1)
return -1;
status = (status >> 8) & 0xff;
return status;
}
}
#endif
#if defined (__CYGWIN__)
2000-02-18 03:39:52 +08:00
static int
do_system (struct _reent *ptr,
const char *s)
2000-02-18 03:39:52 +08:00
{
char *argv[4];
int pid, status;
argv[0] = "sh";
argv[1] = "-c";
argv[2] = (char *) s;
argv[3] = NULL;
if ((pid = vfork ()) == 0)
{
/* ??? It's not clear what's the right path to take (pun intended :-).
There won't be an "sh" in any fixed location so we need each user
to be able to say where to find "sh". That suggests using an
environment variable, but after a few more such situations we may
have too many of them. */
char *sh = getenv ("SH_PATH");
if (sh == NULL)
sh = "/bin/sh";
_execve (sh, argv, environ);
exit (100);
}
else if (pid == -1)
return -1;
else
{
extern int _wait (int *);
2000-02-18 03:39:52 +08:00
int rc = _wait (&status);
if (rc == -1)
return -1;
status = (status >> 8) & 0xff;
return status;
}
}
#endif