muse1.7b4/
muse1.7b4/config/
muse1.7b4/doc/
muse1.7b4/run/
muse1.7b4/run/db/
muse1.7b4/src/
muse1.7b4/src/db/
muse1.7b4/src/files/
muse1.7b4/src/io/
muse1.7b4/src/prog/
muse1.7b4/src/util/
/* wd.c - watchdog */
/* $Id: wd.c,v 1.7 1993/10/18 02:29:24 nils Exp $ */

#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "config.h"
#include "credits.h"
#include "externs.h"

#if defined(SYSV) || defined(HPUX) || defined(SYSV_MAYBE)
#   define  mklinebuf(fp)	setvbuf(fp, NULL, _IOLBF, 0)
#else
#   define  mklinebuf(fp)	setlinebuf(fp)
#endif

#define  DEF_MODE	0644

#define  MUSE_PROGRAM	"../bin/netmuse"
#ifdef __STDC__
#include <stdlib.h>
void main(int, char **);
void wd_init_signals(void);
void shutdown_wd(void);
void wd_init_io(void);
void restart_loop(char **);
void analyze(int, int);
void wd_sig_handler(int);
#else
void main();
void wd_init_signals();
void shutdown_wd();
void wd_init_io();
void restart_loop();
void analyze();
void wd_sig_handler();
#endif
int muse_pid;

void main(argc, argv)
     int argc;
     char *argv[];
{
  extern int setpgrp();
  switch(fork()) {
  case 0:
    setpgrp();
    break;
  case -1:
    perror("fork");
    break;
  default:
    exit(0);
    return;
  }
  wd_init_io();
  printf("------------------------------------\n");
  printf("Watchdog (wd) online (pid=%d)\n", getpid());
  
  wd_init_signals();
  
  restart_loop(argv);
  
  exit(0);
}

void wd_init_signals()
{
  signal(SIGHUP, wd_sig_handler);
  signal(SIGTERM, wd_sig_handler);
  signal(SIGUSR1, wd_sig_handler);
}

void wd_init_io()
{
#ifndef fileno
  /* sometimes stdio.h #defines this */
  extern int fileno P((FILE *));
#endif
  int fd;
  
  /* close standard input */
  fclose(stdin);
  
  /* open a link to the log file */
  fd = open(WD_LOGFILE, O_WRONLY | O_CREAT | O_APPEND, DEF_MODE);
  if ( fd < 0 )  {
    perror("open()");
    fprintf(stderr, "error opening %s for writing\n", WD_LOGFILE);
    exit(1);
  }
  
  /* attempt to convert standard output to logfile */
  close(fileno(stdout));
  if ( dup2(fd, fileno(stdout)) == -1 )  {
    perror("dup2()");
    fprintf(stderr, "error converting standard output to logfile\n");
  }
  mklinebuf(stdout);
  
  /* attempt to convert standard error to logfile */
  close(fileno(stderr));
  if ( dup2(fd, fileno(stderr)) == -1 )  {
    perror("dup2()");
    printf("error converting standard error to logfile\n");
  }
  mklinebuf(stderr);
  
  /* this logfile reference is no longer needed */
  close(fd);
}

void restart_loop(argv)
     char *argv[];
{
  int pid, status;
  struct stat statbuf;
  int now,lasttime=0;

  for (;;) {
    now = time(NULL);
    if (lasttime+300 > now) sleep(300);
    lasttime = now;
    if(stat("logs",&statbuf)<0) {
      puts("'logs' directory doesn't exist; creating it.");
      mkdir("logs",0755);
    } else if((statbuf.st_mode&S_IFMT)!=S_IFDIR) {
      puts("'logs' isn't a directory.");
      shutdown_wd();
    }
    printf ("batching off command logs\n");
    unlink("cmd_crash");
    system("(echo --;date) >cmd_crash");
    system("cat logs/commands~ logs/commands >> cmd_crash");
#ifdef TECH_EMAIL
{ char buf[1024];
  sprintf(buf,"/usr/lib/sendmail %s <cmd_crash", TECH_EMAIL);
  system(buf);
}
#endif
    /* system("/usr/lib/sendmail nils <cmd_crash"); */

    printf("Attempting to startup the MUSE\n");
    system("date");
    /* spawn a new process */
    muse_pid = fork();
    if ( muse_pid < 0 )  {
      perror("fork()");
      fprintf(stderr, "Error spawning muse program\n");
      shutdown_wd();
    }
    
    /* child process executes this if-loop */
    if ( muse_pid == 0 )  {
      argv[0]=MUSE_PROGRAM;
      /* execute the MUSE program */
      if ( execvp(MUSE_PROGRAM, argv) < 0 )  {
	perror("execvp()");
	fprintf(stderr, "Error spawning muse program\n");
	shutdown_wd();
      }
      /* this should NEVER happen */
      /* there is NO return from execvp except failure */
      exit(0);
    }
    
    /* parent process continues here... */
    printf("Sucessful startup of MUSE.  muse-pid=%d\n", muse_pid);
    
    /* wait for MUSE to stop executing */
    pid = wait(&status);
    if ( pid < 0 )  {
      perror("wait()");
      fprintf(stderr, "Error during call to wait()\n");
      shutdown_wd();
    }
    
    /* analyze reason for death of MUSE */
    analyze(pid, status);
  }
}

void analyze(pid, status)
     int pid;
     int status;
{
  int sig;
  
  if ( pid != muse_pid )  {
    fprintf(stderr, "wait() returned information on the wrong process\n");
    fprintf(stderr, "Return pid=%d, Expected pid=%d\n", pid, muse_pid);
    shutdown_wd();
  }
  else if ( (status & 0377) == 0177 )  {
    sig = (status >> 8) & 0377;
    fprintf(stderr, "Error, MUSE program suspended by signal %d\n", sig);
    shutdown_wd();
  }
  else if ( (status & 0377) != 0 )  {
    sig = status & 0177;
    printf("MUSE program terminated by signal %d\n", sig);
  }
  else  {
    status = (status >> 8) & 0377;
    printf("MUSE program terminated due to exit() with status=%d\n",
	   status);
    if ( status != 1 )
      shutdown_wd();
  }
}

void wd_sig_handler(sig)
     int sig;
{
  printf("recieved signal %d\n", sig);
  shutdown_wd();
}

void shutdown_wd()
{
  printf("shutting down watchdog program...\n");
  exit(0);
}
#ifdef SYSV
void setlinebuf(f)
     FILE *f;
{
  setbuf(f,NULL);
}
#endif