]> code.citadel.org Git - citadel.git/blob - citadel/stats.c
* lots of warning fixes; builds with -std1 on dec unix
[citadel.git] / citadel / stats.c
1 /* Citadel/UX call log stats program
2  */
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <time.h>
7 #include <stdio.h>
8 #include <errno.h>
9 #include <string.h>
10 #include <limits.h>
11 #include "citadel.h"
12 #include "config.h"
13
14 #define disply(x,y) printf("%20s            %4.1f    %4.1f    %4d\n",x,((float)y)/calls,((float)y)/days,y)
15
16 #define GRANULARITY 100
17
18 int batch_mode = 0;
19
20 struct caller
21   {
22     struct caller *next;
23     char Cname[30];
24     int Ctimescalled;
25   };
26
27
28 void
29 prompt (void)
30 {
31   char buf[16];
32   if (batch_mode == 0)
33     {
34       printf ("Press return to continue...");
35       fgets (buf, 16, stdin);
36     }
37   else
38     {
39       printf ("\n");
40     }
41 }
42
43 int
44 halfhour (time_t time)                  /* Returns half-hour time period of time */
45                
46 {
47   int a;
48   struct tm *tm;
49   tm = (struct tm *) localtime (&time);
50   a = (tm->tm_hour) * 3;
51   if ((tm->tm_min) > 19)
52     ++a;
53   if ((tm->tm_min) > 39)
54     ++a;
55   return (a);
56 }
57
58
59
60 void
61 progress (long int curr, long int max)
62 {
63   static int dots;
64   int pos;
65
66   if (curr == 0L)
67     {
68       printf ("--------------------------------------");
69       printf ("--------------------------------------\r");
70       fflush (stdout);
71       dots = 0;
72     }
73
74   pos = (curr * 72) / max;
75   while (dots < pos)
76     {
77       putc ('*', stdout);
78       fflush (stdout);
79       ++dots;
80     }
81
82   if (dots == 72)
83     {
84       printf ("                                      ");
85       printf ("                                      \r");
86       fflush (stdout);
87     }
88
89 }
90
91
92
93
94 int
95 main (int argc, char **argv)
96 {
97   time_t LogTime;
98   unsigned int LogType;
99   char LogName[256];
100   int a, b, lowest;
101   float p, q;
102   long timeon[72];
103   long timeup[72];
104   char dname[30];
105   int sess = 0;
106   long cftime, cttime, aa;
107   int calls, logins, newusers;
108   int badpws, terms, drops, sleeps;
109   time_t from, to, tottime;
110   int days, hours, minutes;
111   char aaa[100];
112   struct tm *tm;
113   struct caller *callers = NULL;
114   struct caller *callptr = NULL;
115   FILE *sortpipe;
116   char thegraph[GRANULARITY][73];
117   int pc_only = 0;
118   char buf[256];
119   FILE *logfp;
120
121   for (a = 0; a < argc; ++a)
122     {
123       if (!strcmp (argv[a], "-b"))
124         batch_mode = 1;
125       if (!strcmp (argv[a], "-p"))
126         pc_only = 1;
127     }
128
129
130   for (a = 0; a < GRANULARITY; ++a)
131     strcpy (thegraph[a],
132             "........................................................................");
133
134   get_config ();
135
136   if (pc_only)
137     goto PC_ONLY_HERE;
138
139   if (!batch_mode)
140     printf ("Scanning call log, please wait...\n\n\n\n");
141
142   from = 0;
143   to = 0;
144   for (a = 0; a < 72; ++a)
145     {
146       timeon[a] = 0L;
147       timeup[a] = 0L;
148     }
149   cftime = 0L;
150   cttime = 0L;
151
152   calls = 0;
153   logins = 0;
154   newusers = 0;
155   badpws = 0;
156   terms = 0;
157   drops = 0;
158   sleeps = 0;
159
160
161   logfp = fopen ("citadel.log", "r");
162   if (logfp == NULL)
163     {
164       perror ("Could not open citadel.log");
165       exit (errno);
166     }
167   else
168     {
169       if (!batch_mode)
170         {
171           printf ("Scanning call log, please wait...\n");
172         }
173       while (fgets (buf, 256, logfp) != NULL)
174         {
175           buf[strlen (buf) - 1] = 0;
176
177           LogTime = atol (strtok (buf, "|"));
178           LogType = atol (strtok (NULL, "|"));
179           strcpy (LogName, strtok (NULL, "|"));
180
181           if (LogType != 0)
182             {
183               if ((LogTime < from) || (from == 0L))
184                 from = LogTime;
185               if ((LogTime > to) || (to == 0L))
186                 to = LogTime;
187               strcpy (aaa, "");
188               if (LogType & CL_CONNECT)
189                 {
190                   ++calls;
191                   ++sess;
192                   if (sess == 1)
193                     cftime = LogTime;
194                   strcpy (dname, LogName);
195                 }
196               if (LogType & CL_LOGIN)
197                 {
198                   ++logins;
199                   b = 0;
200                   for (callptr = callers; callptr != NULL; callptr = callptr->next)
201                     {
202                       if (!strcmp (callptr->Cname, LogName))
203                         {
204                           ++b;
205                           ++callptr->Ctimescalled;
206                         }
207                     }
208                   if (b == 0)
209                     {
210                       callptr = (struct caller *) malloc (sizeof (struct caller));
211                       callptr->next = callers;
212                       callers = callptr;
213                       strcpy (callers->Cname, LogName);
214                       callers->Ctimescalled = 1;
215                     }
216                 }
217               if (LogType & CL_NEWUSER)
218                 ++newusers;
219               if (LogType & CL_BADPW)
220                 ++badpws;
221               if (LogType & CL_TERMINATE)
222                 {
223                   ++terms;
224                   --sess;
225                   if (sess == 0)
226                     {
227                       cttime = LogTime;
228                       for (aa = cftime; aa <= cttime; aa = aa + 300L)
229                         timeon[halfhour (aa)] = timeon[halfhour (aa)] + 5L;
230                       cftime = 0L;
231                       cttime = 0L;
232                     }
233                 }
234               if (LogType & CL_DROPCARR)
235                 {
236                   ++drops;
237                   --sess;
238                   if (sess == 0)
239                     {
240                       cttime = LogTime;
241                       for (aa = cftime; aa <= cttime; aa = aa + 300L)
242                         timeon[halfhour (aa)] = timeon[halfhour (aa)] + 5L;
243                       cftime = 0L;
244                       cttime = 0L;
245                     }
246                 }
247               if (LogType & CL_SLEEPING)
248                 {
249                   ++sleeps;
250                   --sess;
251                   if (sess == 0)
252                     {
253                       cttime = LogTime;
254                       for (aa = cftime; aa <= cttime; aa = aa + 300L)
255                         timeon[halfhour (aa)] = timeon[halfhour (aa)] + 5L;
256                       cftime = 0L;
257                       cttime = 0L;
258                     }
259                 }
260
261               if (sess < 0)
262                 sess = 0;
263
264             }
265         }
266       fclose (logfp);
267       tottime = to - from;
268       days = (int) (tottime / 86400L);
269       hours = (int) ((tottime % 86400L) / 3600L);
270       minutes = (int) ((tottime % 3600L) / 60L);
271
272       printf ("                              Avg/Call Avg/Day  Total\n");
273       disply ("Calls:", calls);
274       disply ("Logins:", logins);
275       disply ("New users:", newusers);
276       disply ("Bad pw attempts:", badpws);
277       disply ("Proper logoffs:", terms);
278       disply ("Carrier drops:", drops);
279       disply ("Sleeping drops:", sleeps);
280
281       printf ("\n");
282       tm = (struct tm *) localtime (&from);
283       printf ("From:              %s", (char *) asctime (localtime (&from)));
284       printf ("To:                %s", (char *) asctime (localtime (&to)));
285       printf ("Total report time: ");
286       printf ("%d days, %d hours, %d minutes\n",
287               days, hours, minutes);
288
289       for (aa = from; aa <= to; aa = aa + 1200L)
290         timeup[halfhour (aa)] = timeup[halfhour (aa)] + 20L;
291       prompt ();
292
293       lowest = GRANULARITY - 1;
294       for (b = 0; b < 72; ++b)
295         {
296           for (a = 0; a <= GRANULARITY; ++a)
297             {
298               p = ((float) timeon[b]) / ((float) timeup[b]) * GRANULARITY;
299               q = (float) a;
300               if (p >= q)
301                 {
302                   thegraph[(GRANULARITY - 1) - a][b] = '#';
303                   if (lowest > (GRANULARITY - 1) - a)
304                     lowest = (GRANULARITY - 1) - a;
305                 }
306             }
307         }
308
309       printf ("\n\n\n\n\n\n");
310
311       b = ((GRANULARITY - lowest) / 18);
312       if (b < 1)
313         b = 1;
314       for (a = lowest; a < GRANULARITY; a = a + b)
315         printf ("%2d%% |%s\n",
316                 100 - (a + 1),
317                 thegraph[a]);
318       printf ("    +------------------------------------------------------------------------\n");
319       printf ("     0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23\n");
320       fflush (stdout);
321       prompt ();
322
323       printf ("\n\n\n\n");
324
325
326       printf ("Top 20 Callers (sorted by total number of logins)\n");
327       printf ("Calls Avg/Day Username\n");
328       printf ("----- ------- ------------------------------\n");
329       fflush (stdout);
330       sortpipe = (FILE *) popen ("sort |tail -20 |sort -r", "w");
331       for (callptr = callers; callptr != NULL; callptr = callptr->next)
332         {
333           fprintf (sortpipe, "%5d %7.2f %-30s\n",
334                    callptr->Ctimescalled,
335                    (((float) callptr->Ctimescalled) / ((float) days)),
336                    callptr->Cname);
337         }
338       pclose (sortpipe);
339       while (callers != NULL)
340         {
341           callptr = callers->next;
342           free (callers);
343           callers = callptr;
344         }
345       prompt ();
346
347     PC_ONLY_HERE:; /* yes this semicolon is necessary; the DEC C compiler
348                       complains that a label must be followed by an actual
349                       statement. */
350
351
352 /*
353   This report doesn't work anymore, because it requires reading the user
354   file directly, which can't happen.
355       printf ("Top 20 Contributing Users (post to call ratio)\n");
356       printf ("P/C Ratio Username\n");
357       printf ("--------- ------------------------------\n");
358       fflush (stdout);
359       sortpipe = (FILE *) popen ("sort |tail -20 |sort -r", "w");
360       fp = fopen ("usersupp", "r");
361       while ((fp != NULL)
362        && (fread ((char *) &usersupp, sizeof (struct usersupp), 1, fp) > 0))
363         {
364           fprintf (sortpipe, "%9.2f %-30s\n",
365                    ((float) usersupp.posted / (float) usersupp.timescalled),
366                    usersupp.fullname);
367         }
368       fclose (fp);
369       pclose (sortpipe);
370       exit (0);
371  */
372     }
373     return 0;
374 }