Merge from vendor branch OPENSSH:
[dragonfly.git] / contrib / sendmail-8.13.4 / sendmail / stats.c
1 /*
2  * Copyright (c) 1998-2002 Sendmail, Inc. and its suppliers.
3  *      All rights reserved.
4  * Copyright (c) 1983, 1995-1997 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 #include <sendmail.h>
15
16 SM_RCSID("@(#)$Id: stats.c,v 8.56 2002/06/27 22:47:37 gshapiro Exp $")
17
18 #include <sendmail/mailstats.h>
19
20 static struct statistics        Stat;
21
22 static bool     GotStats = false;       /* set when we have stats to merge */
23
24 /* See http://physics.nist.gov/cuu/Units/binary.html */
25 #define ONE_K           1000            /* one thousand (twenty-four?) */
26 #define KBYTES(x)       (((x) + (ONE_K - 1)) / ONE_K)
27 /*
28 **  MARKSTATS -- mark statistics
29 **
30 **      Parameters:
31 **              e -- the envelope.
32 **              to -- to address.
33 **              type -- type of stats this represents.
34 **
35 **      Returns:
36 **              none.
37 **
38 **      Side Effects:
39 **              changes static Stat structure
40 */
41
42 void
43 markstats(e, to, type)
44         register ENVELOPE *e;
45         register ADDRESS *to;
46         int type;
47 {
48         switch (type)
49         {
50           case STATS_QUARANTINE:
51                 if (e->e_from.q_mailer != NULL)
52                         Stat.stat_nq[e->e_from.q_mailer->m_mno]++;
53                 break;
54
55           case STATS_REJECT:
56                 if (e->e_from.q_mailer != NULL)
57                 {
58                         if (bitset(EF_DISCARD, e->e_flags))
59                                 Stat.stat_nd[e->e_from.q_mailer->m_mno]++;
60                         else
61                                 Stat.stat_nr[e->e_from.q_mailer->m_mno]++;
62                 }
63                 Stat.stat_cr++;
64                 break;
65
66           case STATS_CONNECT:
67                 if (to == NULL)
68                         Stat.stat_cf++;
69                 else
70                         Stat.stat_ct++;
71                 break;
72
73           case STATS_NORMAL:
74                 if (to == NULL)
75                 {
76                         if (e->e_from.q_mailer != NULL)
77                         {
78                                 Stat.stat_nf[e->e_from.q_mailer->m_mno]++;
79                                 Stat.stat_bf[e->e_from.q_mailer->m_mno] +=
80                                         KBYTES(e->e_msgsize);
81                         }
82                 }
83                 else
84                 {
85                         Stat.stat_nt[to->q_mailer->m_mno]++;
86                         Stat.stat_bt[to->q_mailer->m_mno] += KBYTES(e->e_msgsize);
87                 }
88                 break;
89
90           default:
91                 /* Silently ignore bogus call */
92                 return;
93         }
94
95
96         GotStats = true;
97 }
98 /*
99 **  CLEARSTATS -- clear statistics structure
100 **
101 **      Parameters:
102 **              none.
103 **
104 **      Returns:
105 **              none.
106 **
107 **      Side Effects:
108 **              clears the Stat structure.
109 */
110
111 void
112 clearstats()
113 {
114         /* clear the structure to avoid future disappointment */
115         memset(&Stat, '\0', sizeof Stat);
116         GotStats = false;
117 }
118 /*
119 **  POSTSTATS -- post statistics in the statistics file
120 **
121 **      Parameters:
122 **              sfile -- the name of the statistics file.
123 **
124 **      Returns:
125 **              none.
126 **
127 **      Side Effects:
128 **              merges the Stat structure with the sfile file.
129 */
130
131 void
132 poststats(sfile)
133         char *sfile;
134 {
135         int fd;
136         static bool entered = false;
137         long sff = SFF_REGONLY|SFF_OPENASROOT;
138         struct statistics stats;
139         extern off_t lseek();
140
141         if (sfile == NULL || *sfile == '\0' || !GotStats || entered)
142                 return;
143         entered = true;
144
145         (void) time(&Stat.stat_itime);
146         Stat.stat_size = sizeof Stat;
147         Stat.stat_magic = STAT_MAGIC;
148         Stat.stat_version = STAT_VERSION;
149
150         if (!bitnset(DBS_WRITESTATSTOSYMLINK, DontBlameSendmail))
151                 sff |= SFF_NOSLINK;
152         if (!bitnset(DBS_WRITESTATSTOHARDLINK, DontBlameSendmail))
153                 sff |= SFF_NOHLINK;
154
155         fd = safeopen(sfile, O_RDWR, 0600, sff);
156         if (fd < 0)
157         {
158                 if (LogLevel > 12)
159                         sm_syslog(LOG_INFO, NOQID, "poststats: %s: %s",
160                                   sfile, sm_errstring(errno));
161                 errno = 0;
162                 entered = false;
163                 return;
164         }
165         if (read(fd, (char *) &stats, sizeof stats) == sizeof stats &&
166             stats.stat_size == sizeof stats &&
167             stats.stat_magic == Stat.stat_magic &&
168             stats.stat_version == Stat.stat_version)
169         {
170                 /* merge current statistics into statfile */
171                 register int i;
172
173                 for (i = 0; i < MAXMAILERS; i++)
174                 {
175                         stats.stat_nf[i] += Stat.stat_nf[i];
176                         stats.stat_bf[i] += Stat.stat_bf[i];
177                         stats.stat_nt[i] += Stat.stat_nt[i];
178                         stats.stat_bt[i] += Stat.stat_bt[i];
179                         stats.stat_nr[i] += Stat.stat_nr[i];
180                         stats.stat_nd[i] += Stat.stat_nd[i];
181                         stats.stat_nq[i] += Stat.stat_nq[i];
182                 }
183                 stats.stat_cr += Stat.stat_cr;
184                 stats.stat_ct += Stat.stat_ct;
185                 stats.stat_cf += Stat.stat_cf;
186         }
187         else
188                 memmove((char *) &stats, (char *) &Stat, sizeof stats);
189
190         /* write out results */
191         (void) lseek(fd, (off_t) 0, 0);
192         (void) write(fd, (char *) &stats, sizeof stats);
193         (void) close(fd);
194
195         /* clear the structure to avoid future disappointment */
196         clearstats();
197         entered = false;
198 }