/* * sma -- Sendmail log analyser * * Copyright (c) 2000 - 2003 Jarkko Turkulainen. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JARKKO TURKULAINEN ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JARKKO TURKULAINEN BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Date: 2002/09/12 10:46:00 $ */ extern const char *sma_optarg; extern int sma_optind; #include "sma.h" int main(int argc, char **argv) { FILE *fp = NULL; struct host *hptr; int c; #ifdef _WIN32 int getopt(int, char **, char *); #endif /* initialize global variables: */ hosts = 0; tval = time((time_t *)NULL); curr = localtime(&tval); first.next = NULL; pname = argv[0]; /* get arguments: */ while ((c = getopt(argc, argv, "C:D:H:L:b:f:l:r:t:o:O:AFacdhinpsqvw")) != -1) switch(c) { case 'A': dcaddrflag = 1; break; case 'D': Dflag = 1; Dchar = sma_optarg; break; case 'C': Cflag = 1; Cchar = sma_optarg; break; case 'F': Fflag = 1; break; case 'H': Hflag = 1; Hchar = sma_optarg; break; case 'a': aflag = 1; break; case 'b': bflag = 1; bchar = sma_optarg; break; case 'c': cflag = 1; break; case 'd': dflag = 1; break; case 'f': fflag = 1; fchar = sma_optarg; break; case 'h': hflag = 1; break; case 'i': iflag = 1; break; case 'l': lflag = 1; lnum = atoi(sma_optarg); break; case 'L': Lflag = 1; Lchar = sma_optarg; break; case 'r': rflag = 1; rnum = atoi(sma_optarg); break; case 'n': nflag = 1; break; case 'o': oflag = 1; ochar = sma_optarg; break; case 'O': Oflag = 1; Ochar = sma_optarg; break; case 'p': pflag = 1; break; case 's': sflag = 1; break; case 't': tflag = 1; tchar = sma_optarg; break; case 'q': qflag = 1; break; case 'v': vflag = 1; break; case 'w': wflag = 1; break; default: usage(); } argc -= sma_optind; argv += sma_optind; /* Debug */ if (vflag) fprintf(stderr, "%s: running in Debug mode\n", pname); /* Check argument logic: */ if (hflag) usage(); if (cflag) copying(); if (!pgflag) pgflag = 1; /* Read in the configuration file: */ if (fchar) { if (!(fp = fopen(fchar, "r"))) fprintf(stderr, "%s: cannot open %s\n", pname, fchar); else { init(fp); (void)fclose(fp); } } else if (!Fflag) { if (!(fp = fopen(DEFAULT_CONF, "r"))) fprintf(stderr, "%s: cannot open %s, using defaults\n", pname, "configuration file"); else { fchar = DEFAULT_CONF; init(fp); (void)fclose(fp); } } /* Hash table size: */ if (!tflag || !strncmp(tchar, "normal", 6)) { asize = ASIZE_NORMAL; rsize = RSIZE_NORMAL; } else if (!strncmp(tchar, "big", 3)) { asize = ASIZE_BIG; rsize = RSIZE_BIG; } else if (!strncmp(tchar, "huge", 4)) { asize = ASIZE_HUGE; rsize = RSIZE_HUGE; } else { if (!(hsstring = strdup(tchar))) error_memory(); hastring = hsstring; if (*hsstring == ',') { hastring = NULL; if (*(hsstring + 1) == '\0') hrstring = NULL; else hrstring = ++hsstring; } while (*hsstring != '\0') { if (*hsstring == ',') { *hsstring = '\0'; if (*(hsstring + 1) == '\0') hrstring = NULL; else hrstring = ++hsstring; break; } hsstring++; } /* Address Hash table: */ if (hastring != NULL) asize = atoi(hastring); else asize = ASIZE_NORMAL; /* Relay Hash table: */ if (hrstring != NULL) rsize = atoi(hrstring); else rsize = RSIZE_NORMAL; } if (asize <= 0 || rsize <= 0) { fprintf(stderr, "%s: Illegal hash table size\n", pname); usage(); } if (!Oflag) Oflag = FORMAT_ASCII; else if (!strncmp(Ochar, "ascii", 5)) Oflag = FORMAT_ASCII; else if (!strncmp(Ochar, "html", 4)) Oflag = FORMAT_HTML; else if (!strncmp(Ochar, "clog", 4)) Oflag = FORMAT_CLOG; else { fprintf(stderr, "%s: illegal output format \"%s\".\n", pname, Ochar); exit (1); } if (aflag) Oflag = FORMAT_ASCII; if (wflag) Oflag = FORMAT_HTML; if (!Cchar) Cchar = COMMENT; if (aflag) wflag = 0; if (!bchar) bchar = BG_COLOR; if (!tbchar) tbchar = TB_COLOR; if (!bechar) bechar = BOUNCE_ADDR; if (lflag) { if (lnum <= 0) lnum = 0; lrnum = lnum; } else if (!lrflag) { lnum = LDEF; if (lnum <= 0) lnum = 0; lrnum = LRDEF; if (lrnum <= 0) lrnum = 0; } if (rflag) { if (rnum <= 0) rnum = 0; rrnum = rnum; } else if (!rrflag) { rnum = RDEF; if (rnum <= 0) rnum = 0; rrnum = RRDEF; if (rrnum <= 0) rrnum = 0; } /* Set output: */ if (ochar) { if (!(ofp = fopen(ochar, "w"))) { fprintf(stderr, "%s: cannot open %s\n", pname, ochar); ofp = stdout; } } else ofp = stdout; /* Check filter logic: */ /* Envelope and relay filters: */ if (sef || srf || ref || rrf) { if (!qflag) fprintf(stderr, "%s: setting filters\n", pname); #ifdef USE_REGEXP if (csflag) csflag = REG_EXTENDED|REG_NOSUB; else csflag = REG_EXTENDED|REG_ICASE|REG_NOSUB; #endif } if (!sef || !strncmp(sef, "*", 1)) { sef = (char *)NULL; } else { #ifdef USE_REGEXP if (*sef == '!') { if (*(sef+1) == '\0') sef = NULL; regcomp(&csef, sef+1, csflag); } else regcomp(&csef, sef, csflag); #else if (*sef == '!' && *(sef+1) == '\0') sef = (char *)NULL; #endif if (!qflag) fprintf(stderr, " envelope sender filter: %s\n", sef); } if (!srf || !strncmp(srf, "*", 1)) srf = (char *)NULL; else { #ifdef USE_REGEXP if (*srf == '!') { if (*(srf+1) == '\0') srf = NULL; regcomp(&csrf, srf+1, csflag); } else regcomp(&csrf, srf, csflag); #else if (*srf == '!' && *(srf+1) == '\0') srf = (char *)NULL; #endif if (!qflag) fprintf(stderr, " relay sender filter: %s\n", srf); } if (!ref || !strncmp(ref, "*", 1)) ref = (char *)NULL; else { #ifdef USE_REGEXP if (*ref == '!') regcomp(&cref, ref+1, csflag); else regcomp(&cref, ref, csflag); #else if (*ref == '!' && *(ref+1) == '\0') ref = (char *)NULL; #endif if (!qflag) fprintf(stderr, " envelope recipient filter: %s\n", ref); } if (!rrf || !strncmp(rrf, "*", 1)) rrf = (char *)NULL; else { #ifdef USE_REGEXP if (*rrf == '!') regcomp(&crrf, rrf+1, csflag); else regcomp(&crrf, rrf, csflag); #else if (*rrf == '!' && *(rrf+1) == '\0') rrf = (char *)NULL; #endif if (!qflag) fprintf(stderr, " relay recipient filter: %s\n", rrf); } /* Start -and end times: */ if (Dflag) { /* Read from command line.. */ if (!(sstring = strdup(Dchar))) error_memory(); tstring = sstring; if (*sstring == ',') { tstring = NULL; if (*(sstring + 1) == '\0') estring = NULL; else estring = ++sstring; } while (*sstring != '\0') { if (*sstring == ',') { *sstring = '\0'; if (*(sstring + 1) == '\0') estring = NULL; else estring = ++sstring; break; } sstring++; } /* StartTime: */ if (tstring != NULL) scan_time(&sstime, tstring); /* EndTime: */ if (estring != NULL) scan_time(&eetime, estring); } else { if (!sstring || !(strncmp(sstring, "*", 1))) sstring = NULL; else if (sscanf(sstring, "%d/%d/%d-%d:%d:%d", &syear, &smonth, &sday, &shour, &sminute, &ssecond) != 6) { sstring = NULL; if (!qflag) { fprintf(stderr, "%s: illegal StartTime, " "using (*)\n", pname); } } else { sstime = (time_t)conv_time(smonth-1, sday, shour, sminute, ssecond); if (!sstime && !qflag) fprintf(stderr, "%s: illegal StartTime, " "using (*)\n", pname); } if (!estring || !(strncmp(estring, "*", 1))) estring = NULL; else if (sscanf(estring, "%d/%d/%d-%d:%d:%d", &eyear, &emonth, &eday, &ehour, &eminute, &esecond) != 6) { if (!qflag) { fprintf(stderr, "%s: illegal EndTime, " "using (*)\n", pname); } } else { eetime = (time_t)conv_time(emonth-1, eday, ehour, eminute, esecond); if (!eetime && !qflag) fprintf(stderr, "%s: illegal EndTime, " "using (*)\n", pname); } } /* Print out configuration to stdout: */ if (pflag) { fprintf(stderr, "%s: configuration:\n", pname); dump_config(stdout); exit (0); } /* Print configuration in debug mode: */ if (vflag) { fprintf(stderr, "%s: configuration:\n", pname); dump_config(stderr); } /* loop through remaining arguments (if any) and do parsing: */ if (*argv) for (; *argv; ++argv) { if (!qflag) fprintf(stderr, "%s: opening file %s\n", pname, *argv); if (!(fp = fopen(*argv, "r"))) fprintf(stderr, "%s: cannot open %s\n", pname, *argv); else { parse(fp, *argv); (void)fclose(fp); } } else { if (!qflag) fprintf(stderr, "%s: reading from stdin\n", pname); parse(stdin, "stdin"); } /* If output format is clog, nothing to do here: */ if (Oflag == FORMAT_CLOG) exit (0); /* check host structure: */ hptr = first.next; if (!hptr || !(hptr->inum) || !(hptr->onum)) { if (!qflag) fprintf(stderr, "%s: nothing to report\n", pname); exit(1); } for (hptr = first.next; hptr; hptr = hptr->next) { /* rearrange and sort: */ sort(hptr); /* seconds between first and last log entry: */ hptr->dtime = difftime(hptr->ltime, hptr->ftime); /* first hour and day: */ hptr->fday = (localtime(&hptr->ftime))->tm_wday; hptr->fhour = (localtime(&hptr->ftime))->tm_hour; /* time distributions: */ average(hptr, hptr->idd, hptr->fidd, hptr->ihh, hptr->fihh); average(hptr, hptr->odd, hptr->fodd, hptr->ohh, hptr->fohh); } /* print: */ if (Oflag == FORMAT_HTML) html(ofp); else if (Oflag == FORMAT_ASCII) ascii(ofp); (void)fclose(ofp); /* OK: */ exit(0); }