92b04f15d3212afbe6d538af4f6cde888a3cf185
[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.10 2001/02/19 16:18:38 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 #else
35   #include <windows.h> /* for Sleep */
36 #endif
37 #endif
38
39 #ifdef HAVE_VFORK_H
40 #include <vfork.h>
41 #endif
42
43 #ifdef HAVE_VFORK
44 #define fork vfork
45 #endif
46
47 StgInt
48 systemCmd(StgByteArray cmd)
49 {
50 #if defined(mingw32_TARGET_OS)
51    /* There's no fork() under Windows, so we fall back on using libc's
52       system() instead. (It in turn has problems, as it does not wait
53       until the sub shell has finished before returning. Using Sleep()
54       works around that.) */
55   if (system(cmd) < 0) {
56      cvtErrno();
57      stdErrno();
58      return -1;
59   }
60   Sleep(1000);
61   return 0;
62 #else
63     int pid;
64     int wstat;
65
66     switch(pid = fork()) {
67     case -1:
68         if (errno != EINTR) {
69             cvtErrno();
70             stdErrno();
71             return -1;
72         }
73     case 0:
74       {
75 #ifdef HAVE_SETITIMER
76         /* Reset the itimers in the child, so it doesn't get plagued
77          * by SIGVTALRM interrupts.
78          */
79         struct timeval tv_null = { 0, 0 };
80         struct itimerval itv;
81         itv.it_interval = tv_null;
82         itv.it_value = tv_null;
83         setitimer(ITIMER_REAL, &itv, NULL);
84         setitimer(ITIMER_VIRTUAL, &itv, NULL);
85         setitimer(ITIMER_PROF, &itv, NULL);
86 #endif
87
88         /* the child */
89         execl("/bin/sh", "sh", "-c", cmd, NULL);
90         _exit(127);
91       }
92     }
93
94     while (waitpid(pid, &wstat, 0) < 0) {
95         if (errno != EINTR) {
96             cvtErrno();
97             stdErrno();
98             return -1;
99         }
100     }
101
102     if (WIFEXITED(wstat))
103         return WEXITSTATUS(wstat);
104     else if (WIFSIGNALED(wstat)) {
105         ghc_errtype = ERR_INTERRUPTED;
106         ghc_errstr = "system command interrupted";
107     }
108     else {
109         /* This should never happen */
110         ghc_errtype = ERR_OTHERERROR;
111         ghc_errstr = "internal error (process neither exited nor signalled)";
112     }
113     return -1;
114 #endif
115 }