[project @ 2001-02-20 03:41:31 by qrczak]
[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.11 2001/02/20 03:41:31 qrczak 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
38 #ifdef HAVE_VFORK_H
39 #include <vfork.h>
40 #endif
41
42 #ifdef HAVE_VFORK
43 #define fork vfork
44 #endif
45
46 StgInt
47 systemCmd(StgByteArray cmd)
48 {
49 #if defined(mingw32_TARGET_OS)
50    /* There's no fork() under Windows, so we fall back on using libc's
51       system() instead. (It in turn has problems, as it does not wait
52       until the sub shell has finished before returning. Using Sleep()
53       works around that.) */
54   if (system(cmd) < 0) {
55      cvtErrno();
56      stdErrno();
57      return -1;
58   }
59   Sleep(1000);
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 }