[project @ 2001-05-18 16:54:04 by simonmar]
[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.12 2001/05/18 16:54:06 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 "HsStd.h"
13
14 HsInt
15 systemCmd(HsAddr cmd)
16 {
17 #if defined(mingw32_TARGET_OS)
18    /* There's no fork() under Windows, so we fall back on using libc's
19       system() instead. (It in turn has problems, as it does not wait
20       until the sub shell has finished before returning. Using Sleep()
21       works around that.) */
22   if (system(cmd) < 0) {
23      cvtErrno();
24      stdErrno();
25      return -1;
26   }
27   Sleep(1000);
28   return 0;
29 #else
30     int pid;
31     int wstat;
32
33     switch(pid = fork()) {
34     case -1:
35         if (errno != EINTR) {
36             return -1;
37         }
38     case 0:
39       {
40 #ifdef HAVE_SETITIMER
41         /* Reset the itimers in the child, so it doesn't get plagued
42          * by SIGVTALRM interrupts.
43          */
44         struct timeval tv_null = { 0, 0 };
45         struct itimerval itv;
46         itv.it_interval = tv_null;
47         itv.it_value = tv_null;
48         setitimer(ITIMER_REAL, &itv, NULL);
49         setitimer(ITIMER_VIRTUAL, &itv, NULL);
50         setitimer(ITIMER_PROF, &itv, NULL);
51 #endif
52
53         /* the child */
54         execl("/bin/sh", "sh", "-c", cmd, NULL);
55         _exit(127);
56       }
57     }
58
59     while (waitpid(pid, &wstat, 0) < 0) {
60         if (errno != EINTR) {
61             return -1;
62         }
63     }
64
65     if (WIFEXITED(wstat))
66         return WEXITSTATUS(wstat);
67     else if (WIFSIGNALED(wstat)) {
68         errno = EINTR;
69     }
70     else {
71         /* This should never happen */
72     }
73     return -1;
74 #endif
75 }