/* signaldef.c - A modified version of Stevens signal
   function (page 120 of Vol.1, Network Programming).
   This program binds the signal SIGCLD to a handler sig_cld, then it loops
   ten times. In each iteration it creates a child and pauses. The handler 
   is called when the child terminates. It collects and prints out information 
   about the defunct child. Notice that it is implemented as a loop
   because multiple SIGCLD signals may result in a single signal event.
 */

#include <signal.h>
#include <wait.h>
#include <stdio.h>
#include <sys/types.h>

typedef void Sigfunc(int); /* Sigfunc is type of function with one int arg,
                              and void return */

Sigfunc * signal(int signo, Sigfunc *func)
{
  struct sigaction act, oact;

  act.sa_handler = func;
  sigemptyset(&act.sa_mask);
  act.sa_flags = 0;
#ifdef SA_RESTART
  if (signo != SIGALRM)
    act.sa_flags |= SA_RESTART;
#endif
  if (sigaction(signo, &act, &oact) < 0)
    return (SIG_ERR);
  return (oact.sa_handler);
}


static void	sig_cld();

int
main()
{
  pid_t	pid;
  int     i;

  if (signal(SIGCLD, sig_cld) == SIG_ERR) {
    printf("signal error\n");
    exit(1);}
  for (i=0; i < 10; i++){
    if ( (pid = fork()) < 0) {
      printf("fork error\n");
      exit(1);}
    else if (pid == 0) {		/* child */
      sleep(2);
      exit(0);
    }
    pause();	/* parent */
  }
  exit(0);
}

static void
sig_cld()
{
  pid_t	pid;
  int	status;
  
  printf("SIGCLD received, ");
  while ( (pid = waitpid(-1, &status, WNOHANG)) > 0){
    printf("child pid = %d terminated\n", pid);
  }
  printf ("Returning from handler\n");
  return; 
}





