/* ** $Header: /home/vikas/src/nocol/pingmon/RCS/pingmon.c,v 2.5 1998/07/31 18:31:26 vikas Exp $ */ /*+ * * DESCRIPTION * * Runs the "ping" program to monitor a site. Marks a site as UP * DOWN or UNKNOWN. It writes directly to the 'pingoutput' file * instead of to a temporary file. Uses raw i/o calls. * * This program opens the 'data file' supplied by the user and then * creates the 'pingoutput' file. It then directly reads and writes * from this file. On recieving a HUP signal, it rescans the 'data * file' supplied by the user and continues. * * */ /* * MODIFICATIONS * * $Log: pingmon.c,v $ * Revision 2.5 1998/07/31 18:31:26 vikas * Rewrite to use the new library functions. * * Revision 2.4 1994/06/09 21:15:24 vikas * Deleted the definition for inet_addr(), it is defined in arpa/inet.h * * Revision 2.3 1994/05/16 02:10:24 vikas * Major rewrite. Now uses the nocol_startup() call. * */ #ifndef lint static char rcsid[] = "$RCSfile: pingmon.c,v $ $Revision: 2.5 $ $Date: 1998/07/31 18:31:26 $" ; #endif #include "pingmon.h" /* program specific defines */ #include /* For strcat() definitions */ #include #include /* For signal numbers */ /*+ * Global variables */ static char *configfile; /* Filename with list of nodes */ static char *datafile; /* Name of output data file */ static char *sender; /* for the EVENT field */ static time_t pollinterval ; /* Time between polls */ main (ac, av) int ac; char **av; { extern char *optarg; extern int optind; int fdout = 0; /* File desc for output data file */ register int c ; char *p ; time_t starttm, polltime ; prognm = av[0] ; /* Save the program name */ #ifdef SENDER sender = SENDER ; #else /* delete the directory name */ if ((sender = (char *)strrchr (prognm , '/')) == NULL) sender = prognm ; /* no path in program name */ else sender++ ; /* skip leading '/' */ #endif ping = PING ; /* defined while compiling */ while ((c = getopt(ac, av, "do:p:")) != EOF) switch (c) { case 'd': debug++ ; break ; case 'o': /* output datafile */ datafile = optarg ; break ; case 'p': /* ping command to use */ ping = optarg ; break ; case '?': default: fprintf (stderr, "%s: Unknown flag: %c\n", prognm, optarg); help() ; goto Cleanup ; } switch ( ac - optind ) { case 0: /* default input file */ break ; case 1: configfile = av[optind]; break ; default: fprintf (stderr, "%s Error: Too many 'hosts' files\n\n", prognm); help(); goto Cleanup; } if (access(ping, F_OK | X_OK) != 0) /* check if PING is executable */ { perror (ping); nocol_done(); } nocol_startup(&configfile, &datafile); if (debug) fprintf(stderr, "(debug) %s: PING= '%s', CONFIGFILE= '%s', DATAFILE= '%s'\n", prognm, ping, configfile, datafile) ; /* setjmp (env); /* Save the environment in case */ if (fdout != 0) /* Say, recovering from longjmp */ close(fdout); openeventlog() ; /* for logging */ if ( (fdout = open(datafile, O_RDWR|O_CREAT|O_TRUNC, DATAFILE_MODE)) < 0) { fprintf(stderr, "(%s) ERROR in open datafile ", prognm); perror (datafile); goto Cleanup ; } if (init_sites(fdout, configfile) == -1 ) goto Cleanup ; /* poll_sites makes one complete pass over the list of nodes */ while (1) /* forever */ { starttm = time((time_t *)NULL) ; /* time started this cycle */ if (poll_sites(fdout) == -1) /* Polling error */ break ; if ( (polltime = time((time_t *)NULL) - starttm) < pollinterval) sleep ((unsigned)(pollinterval - polltime)); } /* HERE ONLY IF ERROR */ Cleanup: nocol_done(); } /***************** End of main *******************/ /*+ * FUNCTION: * Brief usage */ help () { static char usage[] = " [-d (debug)] [-o ] [-p ] [configfile file]\n"; fprintf(stderr, "\nUSAGE: %s %s\n\n", prognm, usage); fprintf(stderr,"\tThis program finds out the status of sites by "); fprintf(stderr,"sending out an ICMP ping request and writing\n"); fprintf(stderr,"\tthe output into the file %s\n", datafile); fprintf(stderr,"\tBy default, the list of nodes to monitor is %s\n", configfile); fprintf(stderr,"\tbut can be changed on the command line.\n"); fprintf(stderr,"\tThe 'node-file' format is:\n"); fprintf(stderr,"\t\t POLLINTERVAL <#secs>\n"); fprintf(stderr,"\t\t [TEST]\n\n"); fprintf(stderr,"\tThe program writes its pid in %s.pid and \n",prognm); fprintf(stderr,"\tif a new process starts, it kills the earlier one.\n"); fprintf(stderr,"\tSending it a SIGUSR1 signal toggles debugging.\n"); return (1); } /* ** FUNCTION ** ** init_sites ** ** This function writes to the LSTFILE. All sites in the CONFIGFILE ** file are set to UNKNOWN status. ** ** Careful while using 'localtime': the calue of the month varies from ** 0 - 11 and hence has to be incremented for the correct month. */ init_sites(fdout, configfile) int fdout ; /* Output file descriptor */ char *configfile; /* Filename of the nodes file */ { FILE *p_nodes ; EVENT v; /* Defined in NOCOL.H */ char record[MAXLINE]; struct tm *loctime ; time_t locclock ; /* Careful, don't use 'long' */ if ((p_nodes = fopen(configfile, "r")) == NULL) { fprintf(stderr, "%s error (init_sites) ", prognm) ; perror (configfile); return (-1); } /* * Fill in the static data stuff */ bzero (&v, sizeof(v)) ; locclock = time((time_t *)0); loctime = localtime((long *)&locclock); v.mon = loctime->tm_mon + 1; v.day = loctime->tm_mday; v.hour = loctime->tm_hour; v.min = loctime->tm_min; strncpy (v.sender, sender, sizeof(v.sender) - 1); strncpy (v.var.name, VARNM, sizeof (v.var.name) - 1); strncpy (v.var.units, VARUNITS, sizeof (v.var.units) - 1); v.var.threshold = PING_THRES ; /* num of packets lost */ v.nocop = SETF_UPDOUN (v.nocop, n_UNKNOWN); /* Set all to UNKNOWN */ v.severity = E_INFO ; while(fgetLine(p_nodes,record,MAXLINE) > 0 ) { char w1[MAXLINE], w2[MAXLINE], w3[MAXLINE]; /* Confg words */ int rc; /* return code */ v.nocop = 0 ; /* Init options to zero */ *w1 = *w2 = *w3 = '\0' ; rc = sscanf(record,"%s %s %s", w1, w2, w3); if (rc == 0 || *w1 == '\0' || *w1 == '#') /* Comment or blank */ continue; if (strncmp(w1, "POLLINTERVAL", 12) == 0 || strncmp(w1, "pollinterval", 12) == 0) { char *p; /* for strtol */ pollinterval = (u_long)strtol(w2, &p, 0) ; if (p == w2) { fprintf(stderr,"(%s): Error in format for POLLINTERVAL '%s'\n", prognm, w2) ; pollinterval = 0 ; /* reset to default above */ } continue ; } strncpy(v.site.name, w1, sizeof(v.site.name) - 1); strncpy(v.site.addr, w2, sizeof(v.site.addr) - 1); /* no checks */ #ifdef IPPING /* For IP, check the IP address */ if (*w2 >= '0' && *w2 <= '9') /* is a digit */ if (inet_addr(w2) == -1) /* bad address */ { fprintf(stderr, "(%s): Error in address '%s' for site '%s', ignoring\n", prognm, w2, w1); continue ; } #endif /* IPPING */ if (*w3 != '\0') /* Some other keyword */ { if (strcmp(w3, "test") == 0 || strcmp(w3, "TEST") == 0) v.nocop = v.nocop | n_TEST ; else fprintf(stderr, "%s: Ignoring unknown keyword- %s\n", prognm,w3); } if (write (fdout, (char *)&v, sizeof(v)) != sizeof(v)) { fprintf(stderr, "%s (write): %s\n", prognm, sys_errlist[errno]); exit (1) ; } } /* end: while */ fclose (p_nodes); /* Not needed any more */ return(1); /* All OK */ } /* end: init_sites() */