[project @ 2000-07-17 15:27:15 by rrt]
[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.9 2000/07/17 15:27:15 rrt 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) || defined(cygwin32_TARGET_OS)
48    /* The implementation of std. fork() has its problems
49       under cygwin32-b18, so we fall back on using libc's
50       system() instead. (It in turn has problems, as it
51       does not wait until the sub shell has finished before
52       returning. Using sleep() works around that.)
53   */
54   if (system(cmd) < 0) {
55      cvtErrno();
56      stdErrno();
57      return -1;
58   }
59   sleep(1);
60   return 0;
61 #else
62     int pid;
63     int wstat;
64
65     switch(pid = fork()) {
66     case -1:
67         if (errno != EINTR) {
68             cvtErrno();
69             stdErrno();
70             return -1;
71         }
72     case 0:
73       {
74 #ifdef HAVE_SETITIMER
75         /* Reset the itimers in the child, so it doesn't get plagued
76          * by SIGVTALRM interrupts.
77          */
78         struct timeval tv_null = { 0, 0 };
79         struct itimerval itv;
80         itv.it_interval = tv_null;
81         itv.it_value = tv_null;
82         setitimer(ITIMER_REAL, &itv, NULL);
83         setitimer(ITIMER_VIRTUAL, &itv, NULL);
84         setitimer(ITIMER_PROF, &itv, NULL);
85 #endif
86
87         /* the child */
88         execl("/bin/sh", "sh", "-c", cmd, NULL);
89         _exit(127);
90       }
91     }
92
93     while (waitpid(pid, &wstat, 0) < 0) {
94         if (errno != EINTR) {
95             cvtErrno();
96             stdErrno();
97             return -1;
98         }
99     }
100
101     if (WIFEXITED(wstat))
102         return WEXITSTATUS(wstat);
103     else if (WIFSIGNALED(wstat)) {
104         ghc_errtype = ERR_INTERRUPTED;
105         ghc_errstr = "system command interrupted";
106     }
107     else {
108         /* This should never happen */
109         ghc_errtype = ERR_OTHERERROR;
110         ghc_errstr = "internal error (process neither exited nor signalled)";
111     }
112     return -1;
113 #endif
114 }