1 /* 2 ** Sendmail 3 ** Copyright (c) 1983 Eric P. Allman 4 ** Berkeley, California 5 ** 6 ** Copyright (c) 1983 Regents of the University of California. 7 ** All rights reserved. The Berkeley software License Agreement 8 ** specifies the terms and conditions for redistribution. 9 */ 10 11 #ifndef lint 12 static char SccsId[] = "@(#)stats.c 5.5 (Berkeley) 07/25/85"; 13 #endif not lint 14 15 # include "sendmail.h" 16 17 /* 18 ** Statistics structure. 19 */ 20 21 struct statistics 22 { 23 time_t stat_itime; /* file initialization time */ 24 short stat_size; /* size of this structure */ 25 long stat_nf[MAXMAILERS]; /* # msgs from each mailer */ 26 long stat_bf[MAXMAILERS]; /* kbytes from each mailer */ 27 long stat_nt[MAXMAILERS]; /* # msgs to each mailer */ 28 long stat_bt[MAXMAILERS]; /* kbytes to each mailer */ 29 }; 30 31 struct statistics Stat; 32 extern long kbytes(); /* for _bf, _bt */ 33 /* 34 ** MARKSTATS -- mark statistics 35 */ 36 37 markstats(e, to) 38 register ENVELOPE *e; 39 register ADDRESS *to; 40 { 41 if (to == NULL) 42 { 43 /* if is possible to get mail from an unparseable address, 44 in this case, the q_mailer field is null, so that the 45 indirection below causes a dereference of a NULL pointer. 46 */ 47 if (e->e_from.q_mailer != NULL ) 48 { 49 Stat.stat_nf[e->e_from.q_mailer->m_mno]++; 50 Stat.stat_bf[e->e_from.q_mailer->m_mno] += 51 kbytes(CurEnv->e_msgsize); 52 } 53 } 54 else 55 { 56 Stat.stat_nt[to->q_mailer->m_mno]++; 57 Stat.stat_bt[to->q_mailer->m_mno] += kbytes(CurEnv->e_msgsize); 58 } 59 } 60 /* 61 ** POSTSTATS -- post statistics in the statistics file 62 ** 63 ** Parameters: 64 ** sfile -- the name of the statistics file. 65 ** 66 ** Returns: 67 ** none. 68 ** 69 ** Side Effects: 70 ** merges the Stat structure with the sfile file. 71 */ 72 73 poststats(sfile) 74 char *sfile; 75 { 76 register int fd; 77 struct statistics stat; 78 extern off_t lseek(); 79 80 if (sfile == NULL) 81 return; 82 83 (void) time(&Stat.stat_itime); 84 Stat.stat_size = sizeof Stat; 85 86 fd = open(sfile, 2); 87 if (fd < 0) 88 { 89 errno = 0; 90 return; 91 } 92 if (read(fd, (char *) &stat, sizeof stat) == sizeof stat && 93 stat.stat_size == sizeof stat) 94 { 95 /* merge current statistics into statfile */ 96 register int i; 97 98 for (i = 0; i < MAXMAILERS; i++) 99 { 100 stat.stat_nf[i] += Stat.stat_nf[i]; 101 stat.stat_bf[i] += Stat.stat_bf[i]; 102 stat.stat_nt[i] += Stat.stat_nt[i]; 103 stat.stat_bt[i] += Stat.stat_bt[i]; 104 } 105 } 106 else 107 bcopy((char *) &Stat, (char *) &stat, sizeof stat); 108 109 /* write out results */ 110 (void) lseek(fd, (off_t) 0, 0); 111 (void) write(fd, (char *) &stat, sizeof stat); 112 (void) close(fd); 113 } 114 /* 115 ** KBYTES -- given a number, returns the number of Kbytes. 116 ** 117 ** Used in statistics gathering of message sizes to try to avoid 118 ** wraparound (at least for a while.....) 119 ** 120 ** Parameters: 121 ** bytes -- actual number of bytes. 122 ** 123 ** Returns: 124 ** number of kbytes. 125 ** 126 ** Side Effects: 127 ** none. 128 ** 129 ** Notes: 130 ** This function is actually a ceiling function to 131 ** the nearest K. 132 ** Honestly folks, floating point might be better. 133 ** Or perhaps a "statistical" log method. 134 */ 135 136 long 137 kbytes(bytes) 138 long bytes; 139 { 140 return ((bytes + 999) / 1000); 141 } 142