mailstats.c revision 77352
118334Speter/* 252284Sobrien * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. 318334Speter * All rights reserved. 418334Speter * Copyright (c) 1983 Eric P. Allman. All rights reserved. 518334Speter * Copyright (c) 1988, 1993 618334Speter * The Regents of the University of California. All rights reserved. 718334Speter * 818334Speter * By using this file, you agree to the terms and conditions set 918334Speter * forth in the LICENSE file which can be found at the top level of 1018334Speter * the sendmail distribution. 1118334Speter * 1218334Speter * 1318334Speter */ 1418334Speter 1518334Speter#ifndef lint 1618334Speterstatic char copyright[] = 1718334Speter"@(#) Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.\n\ 1818334Speter All rights reserved.\n\ 1918334Speter Copyright (c) 1988, 1993\n\ 2018334Speter The Regents of the University of California. All rights reserved.\n"; 2118334Speter#endif /* ! lint */ 2218334Speter 2318334Speter#ifndef lint 2418334Speterstatic char id[] = "@(#)$Id: mailstats.c,v 8.53.16.13 2001/05/07 22:06:38 gshapiro Exp $"; 2518334Speter#endif /* ! lint */ 2618334Speter 2718334Speter/* $FreeBSD: head/contrib/sendmail/mailstats/mailstats.c 77352 2001-05-28 17:10:35Z gshapiro $ */ 2818334Speter 2918334Speter#include <unistd.h> 3018334Speter#include <stddef.h> 3118334Speter#include <stdlib.h> 3218334Speter#include <ctype.h> 3350397Sobrien#include <string.h> 3450397Sobrien#include <time.h> 3518334Speter#ifdef EX_OK 3618334Speter# undef EX_OK /* unistd.h may have another use for this */ 3718334Speter#endif /* EX_OK */ 3818334Speter#include <sysexits.h> 3918334Speter 4018334Speter#include <sendmail/sendmail.h> 4118334Speter#include <sendmail/mailstats.h> 4218334Speter#include <sendmail/pathnames.h> 4318334Speter 4418334Speter 4518334Speter#define MNAMELEN 20 /* max length of mailer name */ 4618334Speter 4718334Speter 4818334Speterint 4950397Sobrienmain(argc, argv) 5050397Sobrien int argc; 5118334Speter char **argv; 5250397Sobrien{ 5350397Sobrien register int i; 5450397Sobrien int mno; 5518334Speter int save_errno; 5650397Sobrien int ch, fd; 5750397Sobrien char *sfile; 5850397Sobrien char *cfile; 5950397Sobrien FILE *cfp; 6050397Sobrien bool mnames; 6150397Sobrien bool progmode; 6250397Sobrien long frmsgs = 0, frbytes = 0, tomsgs = 0, tobytes = 0, rejmsgs = 0; 6350397Sobrien long dismsgs = 0; 6450397Sobrien time_t now; 6550397Sobrien char mtable[MAXMAILERS][MNAMELEN + 1]; 6650397Sobrien char sfilebuf[MAXLINE]; 6750397Sobrien char buf[MAXLINE]; 6850397Sobrien struct statistics stats; 6950397Sobrien extern char *ctime(); 7050397Sobrien extern char *optarg; 7118334Speter extern int optind; 7218334Speter 7318334Speter 7418334Speter cfile = _PATH_SENDMAILCF; 7518334Speter sfile = NULL; 7618334Speter mnames = TRUE; 7718334Speter progmode = FALSE; 7818334Speter while ((ch = getopt(argc, argv, "C:f:op")) != -1) 7918334Speter { 8018334Speter switch (ch) 8118334Speter { 8218334Speter case 'C': 8318334Speter cfile = optarg; 8418334Speter break; 8518334Speter 8618334Speter case 'f': 8718334Speter sfile = optarg; 8818334Speter break; 8918334Speter 9018334Speter case 'o': 9118334Speter mnames = FALSE; 9218334Speter break; 9318334Speter 9452284Sobrien case 'p': 9552284Sobrien progmode = TRUE; 9652284Sobrien break; 9752284Sobrien 9852284Sobrien case '?': 9952284Sobrien default: 10052284Sobrien usage: 10152284Sobrien (void) fputs("usage: mailstats [-C cffile] [-f stfile] [-o] [-p]\n", 10252284Sobrien stderr); 10352284Sobrien exit(EX_USAGE); 10452284Sobrien } 10552284Sobrien } 10652284Sobrien argc -= optind; 10752284Sobrien argv += optind; 10852284Sobrien 10952284Sobrien if (argc != 0) 11052284Sobrien goto usage; 11152284Sobrien 11252284Sobrien if ((cfp = fopen(cfile, "r")) == NULL) 11318334Speter { 11418334Speter save_errno = errno; 11552284Sobrien fprintf(stderr, "mailstats: "); 11652284Sobrien errno = save_errno; 11752284Sobrien perror(cfile); 11852284Sobrien exit(EX_NOINPUT); 11952284Sobrien } 12052284Sobrien 12152284Sobrien mno = 0; 12252284Sobrien (void) strlcpy(mtable[mno++], "prog", MNAMELEN + 1); 12318334Speter (void) strlcpy(mtable[mno++], "*file*", MNAMELEN + 1); 12418334Speter (void) strlcpy(mtable[mno++], "*include*", MNAMELEN + 1); 12518334Speter 12618334Speter while (fgets(buf, sizeof(buf), cfp) != NULL) 12752284Sobrien { 12852284Sobrien register char *b; 12952284Sobrien char *s; 13018334Speter register char *m; 13118334Speter 13252284Sobrien b = buf; 13318334Speter switch (*b++) 13418334Speter { 13518334Speter case 'M': /* mailer definition */ 13618334Speter break; 13718334Speter 13818334Speter case 'O': /* option -- see if .st file */ 13918334Speter if (strncasecmp(b, " StatusFile", 11) == 0 && 14018334Speter !(isascii(b[11]) && isalnum(b[11]))) 14118334Speter { 14218334Speter /* new form -- find value */ 14318334Speter b = strchr(b, '='); 14418334Speter if (b == NULL) 14518334Speter continue; 14618334Speter while (isascii(*++b) && isspace(*b)) 14718334Speter continue; 14818334Speter } 14918334Speter else if (*b++ != 'S') 15018334Speter { 15118334Speter /* something else boring */ 15218334Speter continue; 15318334Speter } 15418334Speter 15518334Speter /* this is the S or StatusFile option -- save it */ 15618334Speter if (strlcpy(sfilebuf, b, sizeof sfilebuf) >= 15750397Sobrien sizeof sfilebuf) 15850397Sobrien { 15950397Sobrien fprintf(stderr, 16050397Sobrien "StatusFile filename too long: %.30s...\n", 16118334Speter b); 16218334Speter exit(EX_CONFIG); 16318334Speter } 16418334Speter b = strchr(sfilebuf, '#'); 16518334Speter if (b == NULL) 16618334Speter b = strchr(sfilebuf, '\n'); 16718334Speter if (b == NULL) 16850397Sobrien b = &sfilebuf[strlen(sfilebuf)]; 16918334Speter while (isascii(*--b) && isspace(*b)) 17018334Speter continue; 17118334Speter *++b = '\0'; 17218334Speter if (sfile == NULL) 17318334Speter sfile = sfilebuf; 17418334Speter 17518334Speter default: 17618334Speter continue; 17718334Speter } 17818334Speter 17918334Speter if (mno >= MAXMAILERS) 18018334Speter { 18118334Speter fprintf(stderr, 18218334Speter "Too many mailers defined, %d max.\n", 18318334Speter MAXMAILERS); 18418334Speter exit(EX_SOFTWARE); 18518334Speter } 18618334Speter m = mtable[mno]; 18718334Speter s = m + MNAMELEN; /* is [MNAMELEN + 1] */ 18818334Speter while (*b != ',' && !(isascii(*b) && isspace(*b)) && 18918334Speter *b != '\0' && m < s) 19018334Speter *m++ = *b++; 19118334Speter *m = '\0'; 19218334Speter for (i = 0; i < mno; i++) 19318334Speter { 19418334Speter if (strcmp(mtable[i], mtable[mno]) == 0) 19518334Speter break; 19618334Speter } 19718334Speter if (i == mno) 19850397Sobrien mno++; 19918334Speter } 20018334Speter (void) fclose(cfp); 20118334Speter for (; mno < MAXMAILERS; mno++) 20218334Speter mtable[mno][0]='\0'; 20318334Speter 20418334Speter if (sfile == NULL) 20518334Speter { 20618334Speter fprintf(stderr, "mailstats: no statistics file located\n"); 20718334Speter exit (EX_OSFILE); 20818334Speter } 20918334Speter 21018334Speter fd = open(sfile, O_RDONLY); 21118334Speter if ((fd < 0) || (i = read(fd, &stats, sizeof stats)) < 0) 21218334Speter { 21318334Speter save_errno = errno; 21418334Speter (void) fputs("mailstats: ", stderr); 21518334Speter errno = save_errno; 21618334Speter perror(sfile); 21718334Speter exit(EX_NOINPUT); 21818334Speter } 21918334Speter if (i == 0) 22018334Speter { 22118334Speter (void) sleep(1); 22218334Speter if ((i = read(fd, &stats, sizeof stats)) < 0) 22318334Speter { 22418334Speter save_errno = errno; 22518334Speter (void) fputs("mailstats: ", stderr); 22618334Speter errno = save_errno; 22718334Speter perror(sfile); 22818334Speter exit(EX_NOINPUT); 22918334Speter } 23050397Sobrien else if (i == 0) 23150397Sobrien { 23250397Sobrien memset((ARBPTR_T) &stats, '\0', sizeof stats); 23350397Sobrien (void) time(&stats.stat_itime); 23450397Sobrien } 23552284Sobrien } 23652284Sobrien if (i != 0) 23752284Sobrien { 23852284Sobrien if (stats.stat_magic != STAT_MAGIC) 23952284Sobrien { 24052284Sobrien fprintf(stderr, 24152284Sobrien "mailstats: incorrect magic number in %s\n", 24252284Sobrien sfile); 24352284Sobrien exit(EX_OSERR); 24452284Sobrien } 24552284Sobrien else if (stats.stat_version != STAT_VERSION) 24618334Speter { 24718334Speter fprintf(stderr, 24818334Speter "mailstats version (%d) incompatible with %s version (%d)\n", 24918334Speter STAT_VERSION, sfile, stats.stat_version); 25018334Speter exit(EX_OSERR); 25118334Speter } 25218334Speter else if (i != sizeof stats || stats.stat_size != sizeof(stats)) 25318334Speter { 25418334Speter (void) fputs("mailstats: file size changed.\n", stderr); 25518334Speter exit(EX_OSERR); 25618334Speter } 25718334Speter } 25818334Speter 25918334Speter if (progmode) 26018334Speter { 26118334Speter (void) time(&now); 26250397Sobrien printf("%ld %ld\n", (long) stats.stat_itime, (long) now); 26318334Speter } 26418334Speter else 26518334Speter { 26618334Speter printf("Statistics from %s", ctime(&stats.stat_itime)); 26718334Speter printf(" M msgsfr bytes_from msgsto bytes_to msgsrej msgsdis%s\n", 26818334Speter mnames ? " Mailer" : ""); 26918334Speter } 27018334Speter for (i = 0; i < MAXMAILERS; i++) 27118334Speter { 27218334Speter if (stats.stat_nf[i] || stats.stat_nt[i] || 27350397Sobrien stats.stat_nr[i] || stats.stat_nd[i]) 27418334Speter { 27518334Speter char *format; 27618334Speter 27718334Speter if (progmode) 27818334Speter format = "%2d %8ld %10ld %8ld %10ld %6ld %6ld"; 27918334Speter else 28018334Speter format = "%2d %8ld %10ldK %8ld %10ldK %6ld %6ld"; 28150397Sobrien printf(format, i, 28250397Sobrien stats.stat_nf[i], stats.stat_bf[i], 28350397Sobrien stats.stat_nt[i], stats.stat_bt[i], 28450397Sobrien stats.stat_nr[i], stats.stat_nd[i]); 28550397Sobrien if (mnames) 28650397Sobrien printf(" %s", mtable[i]); 28750397Sobrien printf("\n"); 28850397Sobrien frmsgs += stats.stat_nf[i]; 28950397Sobrien frbytes += stats.stat_bf[i]; 29050397Sobrien tomsgs += stats.stat_nt[i]; 29150397Sobrien tobytes += stats.stat_bt[i]; 29250397Sobrien rejmsgs += stats.stat_nr[i]; 29350397Sobrien dismsgs += stats.stat_nd[i]; 29450397Sobrien } 29550397Sobrien } 29650397Sobrien if (progmode) 29750397Sobrien { 29850397Sobrien printf(" T %8ld %10ld %8ld %10ld %6ld %6ld\n", 29950397Sobrien frmsgs, frbytes, tomsgs, tobytes, rejmsgs, dismsgs); 30050397Sobrien printf(" C %8ld %8ld %6ld\n", 30150397Sobrien stats.stat_cf, stats.stat_ct, stats.stat_cr); 30250397Sobrien (void) close(fd); 30350397Sobrien fd = open(sfile, O_RDWR | O_TRUNC); 30450397Sobrien if (fd >= 0) 30550397Sobrien (void) close(fd); 30650397Sobrien } 30750397Sobrien else 30850397Sobrien { 30950397Sobrien printf("=============================================================\n"); 31050397Sobrien printf(" T %8ld %10ldK %8ld %10ldK %6ld %6ld\n", 31150397Sobrien frmsgs, frbytes, tomsgs, tobytes, rejmsgs, dismsgs); 31250397Sobrien printf(" C %8ld %10s %8ld %10s %6ld\n", 31350397Sobrien stats.stat_cf, "", stats.stat_ct, "", stats.stat_cr); 31450397Sobrien } 31550397Sobrien exit(EX_OK); 31650397Sobrien /* NOTREACHED */ 31750397Sobrien return EX_OK; 31850397Sobrien} 31950397Sobrien