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