[project @ 2003-06-12 16:06:06 by simonmar]
[haskell-directory.git] / cbits / rawSystem.c
1 /* 
2  * (c) The University of Glasgow 1994-2003
3  *
4  * shell-less system Runtime Support (see System.Cmd.rawSystem).
5  */
6
7 /* The itimer stuff in this module is non-posix */
8 /* #include "PosixSource.h" */
9
10 #include "config.h"
11
12 #include <stdio.h>
13 #include <stdlib.h>
14
15 #ifdef HAVE_UNISTD_H
16 #include <unistd.h>
17 #endif
18 #ifdef HAVE_ERRNO_H
19 #include <errno.h>
20 #endif
21 #ifdef HAVE_SYS_WAIT_H
22 #include <sys/wait.h>
23 #endif
24
25 # ifdef TIME_WITH_SYS_TIME
26 #  include <sys/time.h>
27 #  include <time.h>
28 # else
29 #  ifdef HAVE_SYS_TIME_H
30 #   include <sys/time.h>
31 #  else
32 #   include <time.h>
33 #  endif
34 # endif
35
36 #include "HsFFI.h"
37
38 #if defined(mingw32_TARGET_OS)
39 #include <windows.h>
40 #endif
41
42 #ifdef HAVE_VFORK_H
43 #include <vfork.h>
44 #endif
45
46 #ifdef HAVE_VFORK
47 #define fork vfork
48 #endif
49
50 #if defined(mingw32_TARGET_OS)
51 /* -------------------- WINDOWS VERSION --------------------- */
52
53 HsInt
54 rawSystem(HsAddr cmd)
55 {
56   STARTUPINFO sInfo;
57   PROCESS_INFORMATION pInfo;
58   DWORD retCode;
59
60   sInfo.cb              = sizeof(STARTUPINFO);
61   sInfo.lpReserved      = NULL;
62   sInfo.lpReserved2     = NULL;
63   sInfo.cbReserved2     = 0;
64   sInfo.lpDesktop       = NULL;
65   sInfo.lpTitle         = NULL;
66   sInfo.dwFlags         = 0;
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     return -1;
76   WaitForSingleObject(pInfo.hProcess, INFINITE);
77   if (GetExitCodeProcess(pInfo.hProcess, &retCode) == 0) return -1;
78   CloseHandle(pInfo.hProcess);
79   CloseHandle(pInfo.hThread);
80   return retCode;
81 }
82
83 #else
84 /* -------------------- UNIX VERSION --------------------- */
85
86 HsInt
87 rawSystem(HsAddr cmd, HsAddr args)
88 {
89     int pid;
90     int wstat;
91
92     switch(pid = fork()) {
93     case -1:
94         if (errno != EINTR) {
95             return -1;
96         }
97     case 0:
98       {
99 #ifdef HAVE_SETITIMER
100         /* Reset the itimers in the child, so it doesn't get plagued
101          * by SIGVTALRM interrupts.
102          */
103         struct timeval tv_null = { 0, 0 };
104         struct itimerval itv;
105         itv.it_interval = tv_null;
106         itv.it_value = tv_null;
107         setitimer(ITIMER_REAL, &itv, NULL);
108         setitimer(ITIMER_VIRTUAL, &itv, NULL);
109         setitimer(ITIMER_PROF, &itv, NULL);
110 #endif
111
112         /* the child */
113         execvp(cmd, args);
114         _exit(127);
115       }
116     }
117
118     while (waitpid(pid, &wstat, 0) < 0) {
119         if (errno != EINTR) {
120             return -1;
121         }
122     }
123
124     if (WIFEXITED(wstat))
125         return WEXITSTATUS(wstat);
126     else if (WIFSIGNALED(wstat)) {
127         errno = EINTR;
128     }
129     else {
130         /* This should never happen */
131     }
132     return -1;
133 }
134 #endif