412181b71319f9aeafdadc531c1bdd8add678182
[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.8 2000/03/28 14:29:13 simonmar Exp $
5  *
6  * system Runtime Support
7  */
8
9 /* The itimer stuff in this module is non-posix */
10 #define NON_POSIX_SOURCE
11
12 #include "Rts.h"
13 #include "stgio.h"
14
15 #ifdef HAVE_UNISTD_H
16 #include <unistd.h>
17 #endif
18
19 #if TIME_WITH_SYS_TIME
20 # include <sys/time.h>
21 # include <time.h>
22 #else
23 # if HAVE_SYS_TIME_H
24 #  include <sys/time.h>
25 # else
26 #  include <time.h>
27 # endif
28 #endif
29
30 #ifndef mingw32_TARGET_OS
31 # ifdef HAVE_SYS_WAIT_H
32 #  include <sys/wait.h>
33 # endif
34 #endif
35
36 #ifdef HAVE_VFORK_H
37 #include <vfork.h>
38 #endif
39
40 #ifdef HAVE_VFORK
41 #define fork vfork
42 #endif
43
44 StgInt
45 systemCmd(StgByteArray cmd)
46 {
47 #if defined(mingw32_TARGET_OS)
48   if (system(cmd) < 0) {
49      cvtErrno();
50      stdErrno();
51      return -1;
52   }
53   sleep(1);
54   return 0;
55 #else
56 #if defined(cygwin32_TARGET_OS)
57    /* The implementation of std. fork() has its problems
58       under cygwin32-b18, so we fall back on using libc's
59       system() instead. (It in turn has problems, as it
60       does not wait until the sub shell has finished before
61       returning. Using sleep() works around that.)
62   */
63   if (system(cmd) < 0) {
64      cvtErrno();
65      stdErrno();
66      return -1;
67   }
68   sleep(1);
69   return 0;
70 #else
71     int pid;
72     int wstat;
73
74     switch(pid = fork()) {
75     case -1:
76         if (errno != EINTR) {
77             cvtErrno();
78             stdErrno();
79             return -1;
80         }
81     case 0:
82       {
83 #ifdef HAVE_SETITIMER
84         /* Reset the itimers in the child, so it doesn't get plagued
85          * by SIGVTALRM interrupts.
86          */
87         struct timeval tv_null = { 0, 0 };
88         struct itimerval itv;
89         itv.it_interval = tv_null;
90         itv.it_value = tv_null;
91         setitimer(ITIMER_REAL, &itv, NULL);
92         setitimer(ITIMER_VIRTUAL, &itv, NULL);
93         setitimer(ITIMER_PROF, &itv, NULL);
94 #endif
95
96         /* the child */
97         execl("/bin/sh", "sh", "-c", cmd, NULL);
98         _exit(127);
99       }
100     }
101
102     while (waitpid(pid, &wstat, 0) < 0) {
103         if (errno != EINTR) {
104             cvtErrno();
105             stdErrno();
106             return -1;
107         }
108     }
109
110     if (WIFEXITED(wstat))
111         return WEXITSTATUS(wstat);
112     else if (WIFSIGNALED(wstat)) {
113         ghc_errtype = ERR_INTERRUPTED;
114         ghc_errstr = "system command interrupted";
115     }
116     else {
117         /* This should never happen */
118         ghc_errtype = ERR_OTHERERROR;
119         ghc_errstr = "internal error (process neither exited nor signalled)";
120     }
121     return -1;
122 #endif
123 #endif
124 }