

/* Plus modifications made by SIGMET */

#include <errno.h>
#ifndef LINUX
#include <signal.h>
#endif  /* #ifndef LINUX */
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#define INCLUDE_UNISTD_PROTOTYPES 1
#include <unistd.h>

#include "sigtypes.h"
#include "user_lib.h"

extern char **environ;

/* ============================================================
 * Function to do an interruptable version of the system() call.
 */
int sig_system_int
(const char *command_a,           /* Shell command to run */
 void (*watchdog_a)(pid_t iPid_a) )   /* Function which can interrupt the call*/
{
  struct sigaction intsa, quitsa, sa;
  sigset_t nmask, omask;
  int pstat, pstat2;
  pid_t pid, pid2;
  
  if (command_a == NULL) return(1);  /* Always a command processor with UNIX */
  
  sa.sa_handler = SIG_IGN;
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = 0;
  
  if (sigaction(SIGINT, &sa, &intsa) == -1)    return -1;
  if (sigaction(SIGQUIT, &sa, &quitsa) == -1)  return -1;
  
  sigemptyset(&nmask);
  sigaddset(&nmask, SIGCHLD);
  if (sigprocmask(SIG_BLOCK, &nmask, &omask) == -1) return -1;

  pid = fork();
  if (pid<0)  /* Error */
    {
      sigaction(SIGINT, &intsa, NULL);
      sigaction(SIGQUIT, &quitsa, NULL);
      (void)sigprocmask(SIG_SETMASK, &omask, NULL);
      return -1;
    }
  else if (pid==0)  /* child */
    {
      sigaction(SIGINT, &intsa, NULL);
      sigaction(SIGQUIT, &quitsa, NULL);
      (void)sigprocmask(SIG_SETMASK, &omask, NULL);
      execl( "/bin/sh", "sh", "-c", command_a, (char*)0 );
      _exit(127);   /* Exec error */
    }

  /* Parent gets here on success, now fork the watchdog process. */
  pid2 = fork();
  if (pid2<0)  /* Error */
    {
      sig_signal( errno_to_message(errno) );
    }
  else if (pid2==0)  /* child */
    {
      watchdog_a(pid);
      _exit(0);
    }

  /* Do the normal wait for the command to complete */
  while (waitpid(pid, &pstat, 0) == -1) 
    {
      if (errno != EINTR) {
	pstat = -1;
	break;
      }
    }

  /* Kill the watchdog process, and wait for it */
  kill(pid2, SIGKILL);
  while (waitpid(pid2, &pstat2, 0) == -1) 
    {
      if (errno != EINTR) {
	pstat2 = -1;
	break;
      }
    }

  /* Restore previous signal actions & reset signal mask */
  sigaction(SIGINT, &intsa, NULL);
  sigaction(SIGQUIT, &quitsa, NULL);
  (void)sigprocmask(SIG_SETMASK, &omask, NULL);
  
  return (pstat);
}

/*
Int main( int argc_a, char **argv_a )
{
  system2("pwd");
  //off

  sleep(10);
}
*/




