[project @ 2001-06-29 11:40:48 by simonpj]
[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.16 2001/06/29 11:40:48 simonpj 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 #if defined(mingw32_TARGET_OS)
15 #include <windows.h>
16 #endif
17
18 HsInt
19 systemCmd(HsAddr cmd)
20 {
21   /* -------------------- WINDOWS VERSION --------------------- */
22 #if defined(mingw32_TARGET_OS)
23   STARTUPINFO sInfo;
24   PROCESS_INFORMATION pInfo;
25   DWORD retCode;
26
27   sInfo.cb              = sizeof(STARTUPINFO);
28   sInfo.lpReserved      = NULL;
29   sInfo.lpReserved2     = NULL;
30   sInfo.cbReserved2     = 0;
31   sInfo.lpDesktop       = NULL;
32   sInfo.lpTitle         = NULL;
33   sInfo.dwFlags         = 0;
34
35   if (!CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &sInfo, &pInfo))
36     /* The 'TRUE' says that the created process should share
37        handles with the current process.  This is vital to ensure
38        that error messages sent to stderr actually appear on the screen.
39        Since we are going to wait for the process to terminate anyway,
40        there is no problem with such sharing. */
41
42     return -1;
43   WaitForSingleObject(pInfo.hProcess, INFINITE);
44   if (GetExitCodeProcess(pInfo.hProcess, &retCode) == 0) return -1;
45   CloseHandle(pInfo.hProcess);
46   CloseHandle(pInfo.hThread);
47   return retCode;
48
49 #else
50   /* -------------------- UNIX VERSION --------------------- */
51     int pid;
52     int wstat;
53
54     switch(pid = fork()) {
55     case -1:
56         if (errno != EINTR) {
57             return -1;
58         }
59     case 0:
60       {
61 #ifdef HAVE_SETITIMER
62         /* Reset the itimers in the child, so it doesn't get plagued
63          * by SIGVTALRM interrupts.
64          */
65         struct timeval tv_null = { 0, 0 };
66         struct itimerval itv;
67         itv.it_interval = tv_null;
68         itv.it_value = tv_null;
69         setitimer(ITIMER_REAL, &itv, NULL);
70         setitimer(ITIMER_VIRTUAL, &itv, NULL);
71         setitimer(ITIMER_PROF, &itv, NULL);
72 #endif
73
74         /* the child */
75         execl("/bin/sh", "sh", "-c", cmd, NULL);
76         _exit(127);
77       }
78     }
79
80     while (waitpid(pid, &wstat, 0) < 0) {
81         if (errno != EINTR) {
82             return -1;
83         }
84     }
85
86     if (WIFEXITED(wstat))
87         return WEXITSTATUS(wstat);
88     else if (WIFSIGNALED(wstat)) {
89         errno = EINTR;
90     }
91     else {
92         /* This should never happen */
93     }
94     return -1;
95 #endif
96 }