1 /* 2 * Copyright (c) 1998 Sendmail, Inc. All rights reserved. 3 * Copyright (c) 1983 Eric P. Allman. All rights reserved. 4 * Copyright (c) 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * By using this file, you agree to the terms and conditions set 8 * forth in the LICENSE file which can be found at the top level of 9 * the sendmail distribution. 10 * 11 * 12 */ 13 14 #ifndef lint 15 static char copyright[] = 16 "@(#) Copyright (c) 1988, 1993\n\ 17 The Regents of the University of California. All rights reserved.\n"; 18 #endif /* not lint */ 19 20 #ifndef lint 21 static char sccsid[] = "@(#)mailstats.c 8.29 (Berkeley) 1/25/1999"; 22 #endif /* not lint */ 23 24 #ifndef NOT_SENDMAIL 25 # define NOT_SENDMAIL 26 #endif 27 #include <sendmail.h> 28 #include <mailstats.h> 29 #include <pathnames.h> 30 31 #define MNAMELEN 20 /* max length of mailer name */ 32 33 int 34 main(argc, argv) 35 int argc; 36 char **argv; 37 { 38 extern char *optarg; 39 extern int optind; 40 struct statistics stat; 41 register int i; 42 int mno; 43 int ch, fd; 44 char *sfile; 45 char *cfile; 46 FILE *cfp; 47 bool mnames; 48 bool progmode; 49 long frmsgs = 0, frbytes = 0, tomsgs = 0, tobytes = 0, rejmsgs = 0; 50 long dismsgs = 0; 51 char mtable[MAXMAILERS][MNAMELEN+1]; 52 char sfilebuf[MAXLINE]; 53 char buf[MAXLINE]; 54 time_t now; 55 extern char *ctime(); 56 57 cfile = _PATH_SENDMAILCF; 58 sfile = NULL; 59 mnames = TRUE; 60 progmode = FALSE; 61 while ((ch = getopt(argc, argv, "C:f:op")) != -1) 62 { 63 switch (ch) 64 { 65 case 'C': 66 cfile = optarg; 67 break; 68 69 case 'f': 70 sfile = optarg; 71 break; 72 73 case 'o': 74 mnames = FALSE; 75 break; 76 77 #if _FFR_MAILSTATS_PROGMODE 78 case 'p': 79 progmode = TRUE; 80 break; 81 #endif 82 83 case '?': 84 default: 85 usage: 86 #if _FFR_MAILSTATS_PROGMODE 87 fputs("usage: mailstats [-o] [-C cffile] [-f stfile] -o -p\n", 88 stderr); 89 #else 90 fputs("usage: mailstats [-o] [-C cffile] [-f stfile] -o \n", 91 stderr); 92 #endif 93 exit(EX_USAGE); 94 } 95 } 96 argc -= optind; 97 argv += optind; 98 99 if (argc != 0) 100 goto usage; 101 102 if ((cfp = fopen(cfile, "r")) == NULL) 103 { 104 fprintf(stderr, "mailstats: "); 105 perror(cfile); 106 exit(EX_NOINPUT); 107 } 108 109 mno = 0; 110 (void) strcpy(mtable[mno++], "prog"); 111 (void) strcpy(mtable[mno++], "*file*"); 112 (void) strcpy(mtable[mno++], "*include*"); 113 114 while (fgets(buf, sizeof(buf), cfp) != NULL) 115 { 116 register char *b; 117 char *s; 118 register char *m; 119 120 b = buf; 121 switch (*b++) 122 { 123 case 'M': /* mailer definition */ 124 break; 125 126 case 'O': /* option -- see if .st file */ 127 if (strncasecmp(b, " StatusFile", 11) == 0 && 128 !(isascii(b[11]) && isalnum(b[11]))) 129 { 130 /* new form -- find value */ 131 b = strchr(b, '='); 132 if (b == NULL) 133 continue; 134 while (isascii(*++b) && isspace(*b)) 135 continue; 136 } 137 else if (*b++ != 'S') 138 { 139 /* something else boring */ 140 continue; 141 } 142 143 /* this is the S or StatusFile option -- save it */ 144 if (strlen(b) >= sizeof sfilebuf) 145 { 146 fprintf(stderr, 147 "StatusFile filename too long: %.30s...\n", 148 b); 149 exit(EX_CONFIG); 150 } 151 strcpy(sfilebuf, b); 152 b = strchr(sfilebuf, '#'); 153 if (b == NULL) 154 b = strchr(sfilebuf, '\n'); 155 if (b == NULL) 156 b = &sfilebuf[strlen(sfilebuf)]; 157 while (isascii(*--b) && isspace(*b)) 158 continue; 159 *++b = '\0'; 160 if (sfile == NULL) 161 sfile = sfilebuf; 162 163 default: 164 continue; 165 } 166 167 if (mno >= MAXMAILERS) 168 { 169 fprintf(stderr, 170 "Too many mailers defined, %d max.\n", 171 MAXMAILERS); 172 exit(EX_SOFTWARE); 173 } 174 m = mtable[mno]; 175 s = m + MNAMELEN; /* is [MNAMELEN+1] */ 176 while (*b != ',' && !(isascii(*b) && isspace(*b)) && 177 *b != '\0' && m < s) 178 *m++ = *b++; 179 *m = '\0'; 180 for (i = 0; i < mno; i++) 181 { 182 if (strcmp(mtable[i], mtable[mno]) == 0) 183 break; 184 } 185 if (i == mno) 186 mno++; 187 } 188 (void) fclose(cfp); 189 for (; mno < MAXMAILERS; mno++) 190 mtable[mno][0]='\0'; 191 192 if (sfile == NULL) 193 { 194 fprintf(stderr, "mailstats: no statistics file located\n"); 195 exit (EX_OSFILE); 196 } 197 198 if ((fd = open(sfile, O_RDONLY)) < 0 || 199 (i = read(fd, &stat, sizeof stat)) < 0) 200 { 201 fputs("mailstats: ", stderr); 202 perror(sfile); 203 exit(EX_NOINPUT); 204 } 205 if (i == 0) 206 { 207 sleep(1); 208 if ((i = read(fd, &stat, sizeof stat)) < 0) 209 { 210 fputs("mailstats: ", stderr); 211 perror(sfile); 212 exit(EX_NOINPUT); 213 } 214 else if (i == 0) 215 { 216 bzero((ARBPTR_T) &stat, sizeof stat); 217 (void) time(&stat.stat_itime); 218 } 219 } 220 if (i != 0) 221 { 222 if (stat.stat_magic != STAT_MAGIC) 223 { 224 fprintf(stderr, 225 "mailstats: incorrect magic number in %s\n", 226 sfile); 227 exit(EX_OSERR); 228 } 229 else if (stat.stat_version != STAT_VERSION) 230 { 231 fprintf(stderr, 232 "mailstats version (%d) incompatible with %s version(%d)\n", 233 STAT_VERSION, sfile, stat.stat_version); 234 exit(EX_OSERR); 235 } 236 else if (i != sizeof stat || stat.stat_size != sizeof(stat)) 237 { 238 fputs("mailstats: file size changed.\n", stderr); 239 exit(EX_OSERR); 240 } 241 } 242 243 if (progmode) 244 { 245 time(&now); 246 printf("%ld %ld\n", (long) stat.stat_itime, (long) now); 247 } 248 else 249 { 250 printf("Statistics from %s", ctime(&stat.stat_itime)); 251 printf(" M msgsfr bytes_from msgsto bytes_to msgsrej msgsdis%s\n", 252 mnames ? " Mailer" : ""); 253 } 254 for (i = 0; i < MAXMAILERS; i++) 255 { 256 if (stat.stat_nf[i] || stat.stat_nt[i] || 257 stat.stat_nr[i] || stat.stat_nd[i]) 258 { 259 char *format; 260 261 if (progmode) 262 format = "%2d %8ld %10ld %8ld %10ld %6ld %6ld"; 263 else 264 format = "%2d %8ld %10ldK %8ld %10ldK %6ld %6ld"; 265 printf(format, i, 266 stat.stat_nf[i], stat.stat_bf[i], 267 stat.stat_nt[i], stat.stat_bt[i], 268 stat.stat_nr[i], stat.stat_nd[i]); 269 if (mnames) 270 printf(" %s", mtable[i]); 271 printf("\n"); 272 frmsgs += stat.stat_nf[i]; 273 frbytes += stat.stat_bf[i]; 274 tomsgs += stat.stat_nt[i]; 275 tobytes += stat.stat_bt[i]; 276 rejmsgs += stat.stat_nr[i]; 277 dismsgs += stat.stat_nd[i]; 278 } 279 } 280 if (progmode) 281 { 282 printf(" T %8ld %10ld %8ld %10ld %6ld %6ld\n", 283 frmsgs, frbytes, tomsgs, tobytes, rejmsgs, dismsgs); 284 close(fd); 285 fd = open(sfile, O_RDWR | O_TRUNC); 286 if (fd >= 0) 287 close(fd); 288 } 289 else 290 { 291 printf("=============================================================\n"); 292 printf(" T %8ld %10ldK %8ld %10ldK %6ld %6ld\n", 293 frmsgs, frbytes, tomsgs, tobytes, rejmsgs, dismsgs); 294 } 295 exit(EX_OK); 296 } 297