[project @ 2001-06-28 14:15:04 by simonmar]
[ghc-base.git] / cbits / system.c
1 /* 
2  * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
3  *
4  * $Id: system.c,v 1.1 2001/06/28 14:15:04 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 "HsCore.h"
13
14 #if defined(mingw32_TARGET_OS)
15 #include <windows.h>
16 #endif
17
18 HsInt
19 systemCmd(HsAddr cmd)
20 {
21 #if defined(mingw32_TARGET_OS)
22   STARTUPINFO sInfo;
23   PROCESS_INFORMATION pInfo;
24   DWORD retCode;
25
26   sInfo.cb              = sizeof(STARTUPINFO);
27   sInfo.lpReserved      = NULL;
28   sInfo.lpReserved2     = NULL;
29   sInfo.cbReserved2     = 0;
30   sInfo.lpDesktop       = NULL;
31   sInfo.lpTitle         = NULL;
32   sInfo.dwFlags         = 0;
33
34   if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &sInfo, &pInfo))
35     return -1;
36   WaitForSingleObject(pInfo.hProcess, INFINITE);
37   if (GetExitCodeProcess(pInfo.hProcess, &retCode) == 0) return -1;
38   CloseHandle(pInfo.hProcess);
39   CloseHandle(pInfo.hThread);
40   return retCode;
41 #else
42     int pid;
43     int wstat;
44
45     switch(pid = fork()) {
46     case -1:
47         if (errno != EINTR) {
48             return -1;
49         }
50     case 0:
51       {
52 #ifdef HAVE_SETITIMER
53         /* Reset the itimers in the child, so it doesn't get plagued
54          * by SIGVTALRM interrupts.
55          */
56         struct timeval tv_null = { 0, 0 };
57         struct itimerval itv;
58         itv.it_interval = tv_null;
59         itv.it_value = tv_null;
60         setitimer(ITIMER_REAL, &itv, NULL);
61         setitimer(ITIMER_VIRTUAL, &itv, NULL);
62         setitimer(ITIMER_PROF, &itv, NULL);
63 #endif
64
65         /* the child */
66         execl("/bin/sh", "sh", "-c", cmd, NULL);
67         _exit(127);
68       }
69     }
70
71     while (waitpid(pid, &wstat, 0) < 0) {
72         if (errno != EINTR) {
73             return -1;
74         }
75     }
76
77     if (WIFEXITED(wstat))
78         return WEXITSTATUS(wstat);
79     else if (WIFSIGNALED(wstat)) {
80         errno = EINTR;
81     }
82     else {
83         /* This should never happen */
84     }
85     return -1;
86 #endif
87 }