/*+ $Header: /home/vikas/src/nocol/lib/RCS/misc.c,v 1.13 1999/11/05 22:33:54 vikas Exp $ * */ /* * Miscellanous nocol library utility routines. Requre that the following * are defined globally: * * prognm = program name (usually argv[0]) * * -vikas@navya.com */ /* Copyright 1992 JvNCnet */ /* Copyright 1994 Vikas Aggarwal, vikas@navya.com */ /* * $Log: misc.c,v $ * Revision 1.13 1999/11/05 22:33:54 vikas * Had declared nocol_done static by mistake. * * Revision 1.12 1999/11/05 21:09:47 vikas * Patch from dbird@varadm.com to add a new function to restore the old SIGUSR1 * handler. * * Revision 1.11 1998/08/13 16:11:05 vikas * Now does not exit if it finds an empty pid file (standalone) * * Revision 1.10 1998/07/31 18:21:08 vikas * Now puts all the pid files in the PIDDIR instead of ETCDIR * * Revision 1.9 1997/02/08 12:14:25 vikas * Changed comparison of NULL to \0 * * Revision 1.8 1994/05/16 01:52:59 vikas * Added routine nocol_startup() which takes care of most of the * 'mundane' common tasks in each nocol module. * * Revision 1.7 1993/10/02 05:26:53 aggarwal * Now requires path to the PIDfile. Also assumes that 'prog' is the * name of the program being run. * * Revision 1.6 1992/06/18 21:15:00 aggarwal * Completely rewritten. No fancy stuff anymore (using fcntl or all * that). * */ #include "nocol.h" #include #include /* signal numbers */ #include #include extern char *prognm; static char *dfile; /* temp to store the datafile for done() */ static void (*old_sigusr1_handler)(); /* store old sigusr1 handler */ void nocol_done(), usr1_handler(); /* pre-declare */ /* * Called upon startup. Sets the values of 'datafile' and 'configfile'. * Calls 'standalone()', and sets up the interrupt signal handlers. */ nocol_startup(pconfigfile, pdatafile) char **pconfigfile, **pdatafile; { char *s ; if ((s = (char *)strrchr(prognm, '/')) != NULL) prognm = ++s ; /* delete path from prognm */ /* * Create PID file on startup */ s = (char *)malloc (strlen(PIDDIR) + strlen(prognm) + 4 + 2) ; sprintf(s, "%s/%s.pid\0", PIDDIR, prognm) ; if (standalone(s) == -1) /* Kill prev running process */ { fprintf(stderr, "%s: Error in standalone...exiting\n", prognm); exit (1); } else free(s) ; /* not needed anymore */ /* * Config filename */ if (pconfigfile) if (*pconfigfile == NULL || **pconfigfile == '\0') { *pconfigfile = (char *)malloc(strlen(ETCDIR) + strlen(prognm)+8); sprintf(*pconfigfile, "%s/%s-confg\0", ETCDIR, prognm); } /* * Data filename */ if (pdatafile) if (*pdatafile == NULL || **pdatafile == '\0') { *pdatafile = (char *)malloc(strlen(DATADIR)+ strlen(prognm)+ strlen(OUTPUTEXT)+ 5); sprintf(*pdatafile, "%s/%s%s\0", DATADIR, prognm, OUTPUTEXT); dfile = *pdatafile; /* store the name for nocol_done() */ } umask (002); /* Not world writable atleast */ /* * Signal handlers */ #ifdef SVR4 /* When will these guys learn!! */ bsdsignal (SIGQUIT, nocol_done); bsdsignal (SIGTERM, nocol_done); bsdsignal (SIGINT, nocol_done); bsdsignal (SIGHUP, nocol_done); old_sigusr1_handler = bsdsignal (SIGUSR1, usr1_handler); #else signal (SIGQUIT, nocol_done); /* Delete pid/data file while dying */ signal (SIGTERM, nocol_done); signal (SIGINT, nocol_done); signal (SIGHUP, nocol_done); old_sigusr1_handler = signal (SIGUSR1, usr1_handler); /* toggles debug */ #endif } /* end nocol_startup() */ /* * function which can be called by an external program to restore the * previous signal handler */ nocol_restore_sigusr1() { #ifdef SVR4 bsdsignal (SIGUSR1, old_sigusr1_handler); #else signal (SIGUSR1, old_sigusr1_handler); #endif } /*+ ** ** FUNCTION: ** ** Kill any other process and write the present PID into the ** PidFile. If cannot write to the file or if the file is locked ** by another process, it returns a value of -1 (in which case the ** calling program should EXIT). ** ** It assumes that the PidFile is "program.pid", where the pointer ** to the string "program" is passed to it. ** ** (Observe that unless the program name has been stripped of the ** path, the pid file is created in the same directory as the ** program). ** ** Method: ** See if pid file exists, create if none ** try to lock ** if cannot lock ** kill process ** if (cannot kill) ** return (-1) ** else ** lock file ** write pid, return to caller ** ** NOTE: ** I *do* know about the 'access' system call for the existability ** of a file. It just tended to screw up on the sun, so I used the simple ** 'fopen' call to test if the file exists. **/ standalone(pidfile) char *pidfile; /* path of the pid file */ { FILE *pidf ; int oldpid = 0, newpid = 0; int fd ; char hostname[MAXLINE], thishostname[MAXLINE] ; gethostname(thishostname, sizeof(thishostname) -1) ; thishostname[MAXLINE - 1] = '\0' ; if ( (pidf =fopen (pidfile, "r")) != NULL) /* file exists... */ { if (fscanf(pidf, "%d %s", &oldpid, hostname) == EOF) { fprintf(stderr, "(standalone): fscanf() error parsing old pid "); perror(pidfile) ; /* couldn't read */ /* return (-1); /* Lets not return,,, */ oldpid = 0; } fclose(pidf); if (oldpid) { if (strcmp(thishostname, hostname) != 0) /* wrong host */ { fprintf(stderr, "(standalone) %s: Program probably running on '%s'\n", prognm, hostname) ; fprintf(stderr, "Kill and delete '%s' file and restart\n",pidfile); return (-1) ; } else /* on proper host */ { if (kill (oldpid, SIGKILL) != 0 && errno != ESRCH) { fprintf(stderr, "(standalone) %s: Couldn't kill earlier process\n", prognm); perror("signal"); return (-1) ; } else sleep (5) ; /* Let other process die */ } } /* if(oldpid) */ } /* end if (pidfile could be opened) */ /* * Here only if all other processes have been killed */ newpid=getpid(); if ( (pidf = fopen(pidfile, "w")) == NULL) /* create file */ { fprintf(stderr, "(standalone): fopen "); perror(pidfile); return(-1); } fprintf (pidf, "%d\n%s\n", newpid, thishostname); /* Store present pid */ fflush(pidf); fclose(pidf) ; fprintf(stderr, "(%s).. locked pid-file, started new process\n", prognm); return (0) ; } /*+ nocol_done * FUNCTION: * * Delete the PID and the data file. Called just before exiting, typically * after recieving some sort of a terminate signal. */ void nocol_done () { char *pidfile; closeeventlog() ; fprintf (stderr, "%s: removing data, pid file.... ", prognm); pidfile = (char *)malloc (strlen(PIDDIR) + strlen(prognm) + 4 + 2) ; sprintf (pidfile, "%s/%s.pid\0", PIDDIR, prognm); unlink (pidfile); /* remove the PID file */ if (dfile && *dfile) unlink (dfile); /* delete the data file */ fprintf (stderr, "Done\n"); free(pidfile); exit (1); } /*+ * FUNCTION: * Increase 'debug' to a value of 2 before resetting it each time * it receives a SIGUSR1 signal. */ void usr1_handler() { extern int debug; if (debug < 2) ++debug; else debug = 0; /* reset if debug value is 2 */ if (debug) fprintf (stderr, "(debug) %s: recvd USR1, enabling debug= %d\n", prognm, debug); }