xref: /freebsd/contrib/sendmail/src/stats.c (revision 5521ff5a4d1929056e7ffc982fac3341ca54df7c)
1 /*
2  * Copyright (c) 1998-2001 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 #ifndef lint
15 static char id[] = "@(#)$Id: stats.c,v 8.36.14.5 2001/02/14 04:07:30 gshapiro Exp $";
16 #endif /* ! lint */
17 
18 #include <sendmail.h>
19 #include <sendmail/mailstats.h>
20 
21 
22 static struct statistics	Stat;
23 
24 static bool	GotStats = FALSE;	/* set when we have stats to merge */
25 
26 /* See http://physics.nist.gov/cuu/Units/binary.html */
27 #define ONE_K		1000		/* one thousand (twenty-four?) */
28 #define KBYTES(x)	(((x) + (ONE_K - 1)) / ONE_K)
29 /*
30 **  MARKSTATS -- mark statistics
31 **
32 **	Parameters:
33 **		e -- the envelope.
34 **		to -- to address.
35 **		reject -- whether this is a rejection.
36 **
37 **	Returns:
38 **		none.
39 **
40 **	Side Effects:
41 **		changes static Stat structure
42 */
43 
44 void
45 markstats(e, to, reject)
46 	register ENVELOPE *e;
47 	register ADDRESS *to;
48 	bool reject;
49 {
50 	if (reject)
51 	{
52 		if (e->e_from.q_mailer != NULL)
53 		{
54 			if (bitset(EF_DISCARD, e->e_flags))
55 				Stat.stat_nd[e->e_from.q_mailer->m_mno]++;
56 			else
57 				Stat.stat_nr[e->e_from.q_mailer->m_mno]++;
58 		}
59 		Stat.stat_cr++;
60 	}
61 	else if (to == NULL)
62 	{
63 		Stat.stat_cf++;
64 		if (e->e_from.q_mailer != NULL)
65 		{
66 			Stat.stat_nf[e->e_from.q_mailer->m_mno]++;
67 			Stat.stat_bf[e->e_from.q_mailer->m_mno] +=
68 				KBYTES(e->e_msgsize);
69 		}
70 	}
71 	else
72 	{
73 		Stat.stat_ct++;
74 		Stat.stat_nt[to->q_mailer->m_mno]++;
75 		Stat.stat_bt[to->q_mailer->m_mno] += KBYTES(e->e_msgsize);
76 	}
77 
78 
79 	GotStats = TRUE;
80 }
81 /*
82 **  CLEARSTATS -- clear statistics structure
83 **
84 **	Parameters:
85 **		none.
86 **
87 **	Returns:
88 **		none.
89 **
90 **	Side Effects:
91 **		clears the Stat structure.
92 */
93 
94 void
95 clearstats()
96 {
97 	/* clear the structure to avoid future disappointment */
98 	memset(&Stat, '\0', sizeof Stat);
99 	GotStats = FALSE;
100 }
101 /*
102 **  POSTSTATS -- post statistics in the statistics file
103 **
104 **	Parameters:
105 **		sfile -- the name of the statistics file.
106 **
107 **	Returns:
108 **		none.
109 **
110 **	Side Effects:
111 **		merges the Stat structure with the sfile file.
112 */
113 
114 void
115 poststats(sfile)
116 	char *sfile;
117 {
118 	register int fd;
119 	long sff = SFF_REGONLY|SFF_OPENASROOT;
120 	struct statistics stats;
121 	extern off_t lseek();
122 
123 	if (sfile == NULL || !GotStats)
124 		return;
125 
126 	(void) time(&Stat.stat_itime);
127 	Stat.stat_size = sizeof Stat;
128 	Stat.stat_magic = STAT_MAGIC;
129 	Stat.stat_version = STAT_VERSION;
130 
131 	if (!bitnset(DBS_WRITESTATSTOSYMLINK, DontBlameSendmail))
132 		sff |= SFF_NOSLINK;
133 	if (!bitnset(DBS_WRITESTATSTOHARDLINK, DontBlameSendmail))
134 		sff |= SFF_NOHLINK;
135 
136 	fd = safeopen(sfile, O_RDWR, 0644, sff);
137 	if (fd < 0)
138 	{
139 		if (LogLevel > 12)
140 			sm_syslog(LOG_INFO, NOQID, "poststats: %s: %s",
141 				  sfile, errstring(errno));
142 		errno = 0;
143 		return;
144 	}
145 	if (read(fd, (char *) &stats, sizeof stats) == sizeof stats &&
146 	    stats.stat_size == sizeof stats &&
147 	    stats.stat_magic == Stat.stat_magic &&
148 	    stats.stat_version == Stat.stat_version)
149 	{
150 		/* merge current statistics into statfile */
151 		register int i;
152 
153 		for (i = 0; i < MAXMAILERS; i++)
154 		{
155 			stats.stat_nf[i] += Stat.stat_nf[i];
156 			stats.stat_bf[i] += Stat.stat_bf[i];
157 			stats.stat_nt[i] += Stat.stat_nt[i];
158 			stats.stat_bt[i] += Stat.stat_bt[i];
159 			stats.stat_nr[i] += Stat.stat_nr[i];
160 			stats.stat_nd[i] += Stat.stat_nd[i];
161 		}
162 		stats.stat_cr += Stat.stat_cr;
163 		stats.stat_ct += Stat.stat_ct;
164 		stats.stat_cf += Stat.stat_cf;
165 	}
166 	else
167 		memmove((char *) &stats, (char *) &Stat, sizeof stats);
168 
169 	/* write out results */
170 	(void) lseek(fd, (off_t) 0, 0);
171 	(void) write(fd, (char *) &stats, sizeof stats);
172 	(void) close(fd);
173 
174 	/* clear the structure to avoid future disappointment */
175 	clearstats();
176 }
177