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