[project @ 1999-02-01 10:33:18 by simonm]
[ghc-hetmet.git] / ghc / lib / std / cbits / system.c
1 /* 
2  * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
3  *
4  * $Id: system.c,v 1.4 1999/01/07 15:42:33 simonm Exp $
5  *
6  * system Runtime Support
7  */
8
9 #include "Rts.h"
10 #include "stgio.h"
11
12 #ifdef HAVE_UNISTD_H
13 #include <unistd.h>
14 #endif
15
16 #ifdef HAVE_SYS_WAIT_H
17 #include <sys/wait.h>
18 #endif
19
20 #ifdef HAVE_VFORK_H
21 #include <vfork.h>
22 #endif
23
24 #ifdef HAVE_VFORK
25 #define fork vfork
26 #endif
27
28 StgInt
29 systemCmd(cmd)
30 StgByteArray cmd;
31 {
32 #if defined(cygwin32_TARGET_OS)
33    /* The implementation of std. fork() has its problems
34       under cygwin32-b18, so we fall back on using libc's
35       system() instead. (It in turn has problems, as it
36       does not wait until the sub shell has finished before
37       returning. Using sleep() works around that.)
38   */
39   if (system(cmd) < 0) {
40      cvtErrno();
41      stdErrno();
42      return -1;
43   }
44   sleep(1);
45   return 0;
46 #else
47     int pid;
48     int wstat;
49
50     switch(pid = fork()) {
51     case -1:
52         if (errno != EINTR) {
53             cvtErrno();
54             stdErrno();
55             return -1;
56         }
57     case 0:
58         /* the child */
59         execl("/bin/sh", "sh", "-c", cmd, NULL);
60         _exit(127);
61     }
62
63     while (waitpid(pid, &wstat, 0) < 0) {
64         if (errno != EINTR) {
65             cvtErrno();
66             stdErrno();
67             return -1;
68         }
69     }
70
71     if (WIFEXITED(wstat))
72         return WEXITSTATUS(wstat);
73     else if (WIFSIGNALED(wstat)) {
74         ghc_errtype = ERR_INTERRUPTED;
75         ghc_errstr = "system command interrupted";
76     }
77     else {
78         /* This should never happen */
79         ghc_errtype = ERR_OTHERERROR;
80         ghc_errstr = "internal error (process neither exited nor signalled)";
81     }
82     return -1;
83 #endif
84 }