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