/* spipe -- supervise a pipeline of programs
 * Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "bool.h"
#include "svcfns.h"

static unsigned part_count;
static pid_t* part_pids;
static int selfpipe[2];
static const char** part_names;

void err(const char* msg)
{
  fputs("spipe: Error: ", stderr);
  fputs(msg, stderr);
  fputc('\n', stderr);
}

void die(const char* msg)
{
  err(msg);
  exit(1);
}

bool is_pipe(const char* p)
{
  return p[0] == '|' && p[1] == 0;
}

void usage(const char* msg)
{
  if(msg)
    err(msg);
  fputs("usage: spipe dir1 dir2 ...\n", stderr);
  exit(1);
}

void parse_args(int argc, char** argv)
{
  --argc, ++argv;
  if(argc <= 0)
    usage("Too few command-line arguments");

  part_count = argc;
  part_names = (const char**)argv;
  part_pids = calloc(part_count, sizeof(pid_t));
  memset(part_pids, 0, sizeof(pid_t) * part_count);

  if(pipe(selfpipe))
    die("Could not create self pipe");
}

void stop_parts()
{
  unsigned i;
  for(i = 0; i < part_count; i++)
    if(part_pids[i])
      stop_supervise(part_names[i], part_pids[i]);
}

void start_parts()
{
  int fdout = FD_STDOUT;
  int fdout_next = -1;
  unsigned i;
  for(i = part_count; i > 0; i--) {
    int fdin = FD_STDIN;
    if(i > 1) {
      int p[2];
      if(pipe(p)) {
	die("Could not create pipe");
	stop_parts();
	exit(1);
      }
      fdin = p[0];
      fdout_next = p[1];
    }
    if(!start_supervise(part_names[i-1], fdin, fdout)) {
      stop_parts();
      exit(1);
    }
    close(fdout);
    close(fdin);
    fdout = fdout_next;
  }
}

void handle_intr(int sig)
{
  write(selfpipe[1], "", 1);
}

void mainloop()
{
  char buf[1];
  signal(SIGINT, handle_intr);
  signal(SIGQUIT, handle_intr);
  signal(SIGTERM, handle_intr);
  read(selfpipe[0], buf, 1);
  stop_parts();
  exit(0);
}

int main(int argc, char** argv)
{
  parse_args(argc, argv);
  start_parts();
  mainloop();
  return 0;
}


syntax highlighted by Code2HTML, v. 0.9.1