Update zoneinfo database.
[dragonfly.git] / contrib / sendmail / src / 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.55 2002/05/21 22:28:52 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 #if _FFR_QUARANTINE
51           case STATS_QUARANTINE:
52                 if (e->e_from.q_mailer != NULL)
53                         Stat.stat_nq[e->e_from.q_mailer->m_mno]++;
54                 break;
55 #endif /* _FFR_QUARANTINE */
56
57           case STATS_REJECT:
58                 if (e->e_from.q_mailer != NULL)
59                 {
60                         if (bitset(EF_DISCARD, e->e_flags))
61                                 Stat.stat_nd[e->e_from.q_mailer->m_mno]++;
62                         else
63                                 Stat.stat_nr[e->e_from.q_mailer->m_mno]++;
64                 }
65                 Stat.stat_cr++;
66                 break;
67
68           case STATS_CONNECT:
69                 if (to == NULL)
70                         Stat.stat_cf++;
71                 else
72                         Stat.stat_ct++;
73                 break;
74
75           case STATS_NORMAL:
76                 if (to == NULL)
77                 {
78                         if (e->e_from.q_mailer != NULL)
79                         {
80                                 Stat.stat_nf[e->e_from.q_mailer->m_mno]++;
81                                 Stat.stat_bf[e->e_from.q_mailer->m_mno] +=
82                                         KBYTES(e->e_msgsize);
83                         }
84                 }
85                 else
86                 {
87                         Stat.stat_nt[to->q_mailer->m_mno]++;
88                         Stat.stat_bt[to->q_mailer->m_mno] += KBYTES(e->e_msgsize);
89                 }
90                 break;
91
92           default:
93                 /* Silently ignore bogus call */
94                 return;
95         }
96
97
98         GotStats = true;
99 }
100 /*
101 **  CLEARSTATS -- clear statistics structure
102 **
103 **      Parameters:
104 **              none.
105 **
106 **      Returns:
107 **              none.
108 **
109 **      Side Effects:
110 **              clears the Stat structure.
111 */
112
113 void
114 clearstats()
115 {
116         /* clear the structure to avoid future disappointment */
117         memset(&Stat, '\0', sizeof Stat);
118         GotStats = false;
119 }
120 /*
121 **  POSTSTATS -- post statistics in the statistics file
122 **
123 **      Parameters:
124 **              sfile -- the name of the statistics file.
125 **
126 **      Returns:
127 **              none.
128 **
129 **      Side Effects:
130 **              merges the Stat structure with the sfile file.
131 */
132
133 void
134 poststats(sfile)
135         char *sfile;
136 {
137         int fd;
138         static bool entered = false;
139         long sff = SFF_REGONLY|SFF_OPENASROOT;
140         struct statistics stats;
141         extern off_t lseek();
142
143         if (sfile == NULL || *sfile == '\0' || !GotStats || entered)
144                 return;
145         entered = true;
146
147         (void) time(&Stat.stat_itime);
148         Stat.stat_size = sizeof Stat;
149         Stat.stat_magic = STAT_MAGIC;
150         Stat.stat_version = STAT_VERSION;
151
152         if (!bitnset(DBS_WRITESTATSTOSYMLINK, DontBlameSendmail))
153                 sff |= SFF_NOSLINK;
154         if (!bitnset(DBS_WRITESTATSTOHARDLINK, DontBlameSendmail))
155                 sff |= SFF_NOHLINK;
156
157         fd = safeopen(sfile, O_RDWR, 0600, sff);
158         if (fd < 0)
159         {
160                 if (LogLevel > 12)
161                         sm_syslog(LOG_INFO, NOQID, "poststats: %s: %s",
162                                   sfile, sm_errstring(errno));
163                 errno = 0;
164                 entered = false;
165                 return;
166         }
167         if (read(fd, (char *) &stats, sizeof stats) == sizeof stats &&
168             stats.stat_size == sizeof stats &&
169             stats.stat_magic == Stat.stat_magic &&
170             stats.stat_version == Stat.stat_version)
171         {
172                 /* merge current statistics into statfile */
173                 register int i;
174
175                 for (i = 0; i < MAXMAILERS; i++)
176                 {
177                         stats.stat_nf[i] += Stat.stat_nf[i];
178                         stats.stat_bf[i] += Stat.stat_bf[i];
179                         stats.stat_nt[i] += Stat.stat_nt[i];
180                         stats.stat_bt[i] += Stat.stat_bt[i];
181                         stats.stat_nr[i] += Stat.stat_nr[i];
182                         stats.stat_nd[i] += Stat.stat_nd[i];
183 #if _FFR_QUARANTINE
184                         stats.stat_nq[i] += Stat.stat_nq[i];
185 #endif /* _FFR_QUARANTINE */
186                 }
187                 stats.stat_cr += Stat.stat_cr;
188                 stats.stat_ct += Stat.stat_ct;
189                 stats.stat_cf += Stat.stat_cf;
190         }
191         else
192                 memmove((char *) &stats, (char *) &Stat, sizeof stats);
193
194         /* write out results */
195         (void) lseek(fd, (off_t) 0, 0);
196         (void) write(fd, (char *) &stats, sizeof stats);
197         (void) close(fd);
198
199         /* clear the structure to avoid future disappointment */
200         clearstats();
201         entered = false;
202 }