/*
 * jpipe.h: file contenente le routine per gestire una
 *              pipeline di processi.
 * 
 * Autore:      Antonio Ospite 408/244
 * Data:        Giugno 2001
 */


#include "jpipe.h"

/*
 * prototipo della funzione che si occupa di eseguire un comando della
 * pipeline 
 */
static void launch_pipe_process (char *, pid_t, int);



/*
 * definizione della funzione execpipe() 
 */
int
execpipe (char *inputstring)
{

  pid_t pid;

  int i, j, c, len, status;

  int pfd[MAXCMD][2];

  char *word, *tmpstr, *cmdv[MAXCMD];

  c = strlen(inputstring);
  tmpstr = malloc(c+1);
  strncpy (tmpstr, inputstring, c);
  tmpstr[c]=0;
  c = 0;

  for (word = strtok (tmpstr, SEPARATOR); word;
       word = strtok (NULL, SEPARATOR))
  {
    len = strlen (word);
    if ((cmdv[c] = malloc (len)) == NULL)
      perror ("malloc");
    strcpy (cmdv[c], word);
    c++;
  }

  for (i = 0; i < c - 1; i++)	/*
				 * creo c-1 pipe, se ho c comandi 
				 */
    pipe (pfd[i]);

  for (i = 0; i < c; i++)
  {				/*
				 * creo un figlio per ogni processo 
				 */
    if ((pid = fork ()) < 0)
    {
      perror ("errore di fork");
      exit (1);
    }

    if (pid == 0)
    {

      if (i != 0)
      {
	close (STDIN_FILENO);
	dup (pfd[i - 1][READ]);
      }
      if (i != c - 1)
      {
	close (STDOUT_FILENO);
	dup (pfd[i][WRITE]);
      }

      for (j = 0; j < c - 1; j++)
      {
	close (pfd[j][READ]);
	close (pfd[j][WRITE]);
      }

      launch_pipe_process (cmdv[i], getppid (), 1);
    }

  }

  /*
   * chiusura dei descrittori di pipe 
   */
  for (j = 0; j < c - 1; j++)
  {
    close (pfd[j][READ]);
    close (pfd[j][WRITE]);
  }

  /*
   * attesa dei processi figli 
   */
  for (i = 0; i < c; i++)
  {
    if (waitpid (-1, &status, WUNTRACED) < 0)
    {
      perror ("errore di wait");
    }


    if (WIFSIGNALED (status))
      printf ("Processo terminato per un segnale (%s)\n",
	      sys_siglist[WTERMSIG (status)]);

    if (WIFSTOPPED (status))
    {
      printf ("L'esecuzione della pipeline e' stata stoppata\n");
      return 0;
    }

  }

  return 0;
}

static void
launch_pipe_process (char *command, pid_t pgid, int foreground)
{
  pid_t pid = getpid ();

  /*
   * Creazione di un nuovo gruppo di processi ed eventuale
   * assegnazione del terminale di controllo al nuovo gruppo di processi
   */
  pid = getpid ();
  if (pgid == 0)
    pgid = pid;
  setpgid (pid, pgid);
  if (foreground == 1)
    tcsetpgrp (STDIN_FILENO, pgid);

  /*
   * Si ripristina l'handling dei segnali 
   */
  signal (SIGINT, SIG_DFL);
  signal (SIGQUIT, SIG_DFL);
  signal (SIGTSTP, SIG_DFL);
  signal (SIGTTIN, SIG_DFL);
  signal (SIGTTOU, SIG_DFL);
  signal (SIGCHLD, SIG_DFL);



  /*
   * Esecuzione del nuovo processo  
   */
  execlp ("sh", "sh", "-c", command, (char *) 0);

  /*
   * Il codice che segue viene eseguito solo nel caso in cui
   * la chiamata alla exec() fallisca
   */
  perror ("Errore di exec");
  exit (1);
}


syntax highlighted by Code2HTML, v. 0.9.1