/* 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