Fix building with compilers which don't have an integer for a patch level
[ghc-hetmet.git] / compat / cbits / rawSystem.c
1 /* 
2  * (c) The University of Glasgow 1994-2004
3  *
4  * WARNING: this file is here for backwards compatibility only.  It is
5  * not included as part of the base package, but is #included into the
6  * compiler and the runghc utility when building either of these with 
7  * an old version of GHC.
8  *
9  * shell-less system Runtime Support (see System.Cmd.rawSystem).
10  */
11
12 /* The itimer stuff in this module is non-posix */
13 /* #include "PosixSource.h" */
14
15 #include "../../../includes/ghcconfig.h"
16
17 #include <stdio.h>
18 #include <stdlib.h>
19
20 #ifdef HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
23 #ifdef HAVE_ERRNO_H
24 #include <errno.h>
25 #endif
26 #ifdef HAVE_SYS_WAIT_H
27 #include <sys/wait.h>
28 #endif
29
30 # ifdef TIME_WITH_SYS_TIME
31 #  include <sys/time.h>
32 #  include <time.h>
33 # else
34 #  ifdef HAVE_SYS_TIME_H
35 #   include <sys/time.h>
36 #  else
37 #   include <time.h>
38 #  endif
39 # endif
40
41 #include "HsFFI.h"
42
43 #if defined(mingw32_HOST_OS)
44 #include <windows.h>
45 #endif
46
47 #ifdef HAVE_VFORK_H
48 #include <vfork.h>
49 #endif
50
51 #ifdef HAVE_VFORK
52 #define fork vfork
53 #endif
54
55 #if defined(mingw32_HOST_OS)
56 /* -------------------- WINDOWS VERSION --------------------- */
57
58 HsInt
59 rawSystem(char *cmd)
60 {
61   STARTUPINFO sInfo;
62   PROCESS_INFORMATION pInfo;
63   DWORD retCode;
64
65   ZeroMemory(&sInfo, sizeof(sInfo));
66   sInfo.cb = sizeof(sInfo);
67
68   if (!CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &sInfo, &pInfo)) {
69     /* The 'TRUE' says that the created process should share
70        handles with the current process.  This is vital to ensure
71        that error messages sent to stderr actually appear on the screen.
72        Since we are going to wait for the process to terminate anyway,
73        there is no problem with such sharing. */
74
75       errno = EINVAL; // ToDo: wrong, caller should use GetLastError()
76       return -1;
77   }
78   WaitForSingleObject(pInfo.hProcess, INFINITE);
79   if (GetExitCodeProcess(pInfo.hProcess, &retCode) == 0) {
80       errno = EINVAL; // ToDo: wrong, caller should use GetLastError()
81       return -1;
82   }
83
84   CloseHandle(pInfo.hProcess);
85   CloseHandle(pInfo.hThread);
86   return retCode;
87 }
88
89 #else
90 /* -------------------- UNIX VERSION --------------------- */
91
92 HsInt
93 rawSystem(char *cmd, char **args)
94 {
95     int pid;
96     int wstat;
97
98     switch(pid = fork()) {
99     case -1:
100         {
101             return -1;
102         }
103     case 0:
104       {
105 #ifdef HAVE_SETITIMER
106         /* Reset the itimers in the child, so it doesn't get plagued
107          * by SIGVTALRM interrupts.
108          */
109         struct timeval tv_null = { 0, 0 };
110         struct itimerval itv;
111         itv.it_interval = tv_null;
112         itv.it_value = tv_null;
113         setitimer(ITIMER_REAL, &itv, NULL);
114         setitimer(ITIMER_VIRTUAL, &itv, NULL);
115         setitimer(ITIMER_PROF, &itv, NULL);
116 #endif
117
118         /* the child */
119         execvp(cmd, args);
120         _exit(127);
121       }
122     }
123
124     while (waitpid(pid, &wstat, 0) < 0) {
125         if (errno != EINTR) {
126             return -1;
127         }
128     }
129
130     if (WIFEXITED(wstat))
131         return WEXITSTATUS(wstat);
132     else if (WIFSIGNALED(wstat)) {
133         errno = EINTR;
134     }
135     else {
136         /* This should never happen */
137     }
138     return -1;
139 }
140 #endif