system.c 2.19 KB
Newer Older
1 2 3
/* 
 * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
 *
4
 * $Id: system.c,v 1.7 2000/03/17 09:48:48 simonmar Exp $
5 6 7
 *
 * system Runtime Support
 */
8

9
#include "Rts.h"
10 11
#include "stgio.h"

12 13 14 15
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

16 17 18 19 20 21 22 23 24 25 26
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
#  include <sys/time.h>
# else
#  include <time.h>
# endif
#endif

sof's avatar
sof committed
27 28 29 30
#ifndef mingw32_TARGET_OS
# ifdef HAVE_SYS_WAIT_H
#  include <sys/wait.h>
# endif
31 32 33 34 35 36 37 38 39 40 41
#endif

#ifdef HAVE_VFORK_H
#include <vfork.h>
#endif

#ifdef HAVE_VFORK
#define fork vfork
#endif

StgInt
42
systemCmd(StgByteArray cmd)
43
{
sof's avatar
sof committed
44 45 46 47 48 49 50 51 52
#if defined(mingw32_TARGET_OS)
  if (system(cmd) < 0) {
     cvtErrno();
     stdErrno();
     return -1;
  }
  sleep(1);
  return 0;
#else
sof's avatar
sof committed
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
#if defined(cygwin32_TARGET_OS)
   /* The implementation of std. fork() has its problems
      under cygwin32-b18, so we fall back on using libc's
      system() instead. (It in turn has problems, as it
      does not wait until the sub shell has finished before
      returning. Using sleep() works around that.)
  */
  if (system(cmd) < 0) {
     cvtErrno();
     stdErrno();
     return -1;
  }
  sleep(1);
  return 0;
#else
68 69 70 71 72 73 74 75 76 77 78
    int pid;
    int wstat;

    switch(pid = fork()) {
    case -1:
	if (errno != EINTR) {
	    cvtErrno();
	    stdErrno();
	    return -1;
	}
    case 0:
79 80 81 82 83 84 85 86 87 88 89 90
      {
	/* Reset the itimers in the child, so it doesn't get plagued
	 * by SIGVTALRM interrupts.
	 */
	struct timeval tv_null = { 0, 0 };
	struct itimerval itv;
	itv.it_interval = tv_null;
	itv.it_value = tv_null;
	setitimer(ITIMER_REAL, &itv, NULL);
	setitimer(ITIMER_VIRTUAL, &itv, NULL);
	setitimer(ITIMER_PROF, &itv, NULL);

91 92 93
	/* the child */
	execl("/bin/sh", "sh", "-c", cmd, NULL);
	_exit(127);
94
      }
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
    }

    while (waitpid(pid, &wstat, 0) < 0) {
	if (errno != EINTR) {
	    cvtErrno();
	    stdErrno();
	    return -1;
	}
    }

    if (WIFEXITED(wstat))
	return WEXITSTATUS(wstat);
    else if (WIFSIGNALED(wstat)) {
	ghc_errtype = ERR_INTERRUPTED;
	ghc_errstr = "system command interrupted";
    }
    else {
	/* This should never happen */
	ghc_errtype = ERR_OTHERERROR;
	ghc_errstr = "internal error (process neither exited nor signalled)";
    }
    return -1;
sof's avatar
sof committed
117
#endif
sof's avatar
sof committed
118
#endif
119
}