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