4 * Citadel/UX call log stats program
12 #if TIME_WITH_SYS_TIME
13 # include <sys/time.h>
17 # include <sys/time.h>
28 #include "citadel_ipc.h"
32 #define disply(x,y) printf("%20s %4.1f %4.1f %4d\n",x,((float)y)/calls,((float)y)/days,y)
34 #define GRANULARITY 100
44 void logoff(int code) {
51 if (batch_mode == 0) {
52 printf("Press return to continue...");
53 fgets(buf, 16, stdin);
59 int halfhour(time_t time)
60 { /* Returns half-hour time period of time */
63 tm = (struct tm *) localtime(&time);
64 a = (tm->tm_hour) * 3;
65 if ((tm->tm_min) > 19)
67 if ((tm->tm_min) > 39)
74 void progress(long int curr, long int max)
80 printf("--------------------------------------");
81 printf("--------------------------------------\r");
85 pos = (curr * 72) / max;
102 int main(int argc, char **argv)
104 char hostbuf[SIZ], portbuf[SIZ];
106 unsigned int LogType;
114 long cftime, cttime, aa;
115 int calls, logins, newusers;
116 int badpws, terms, drops, sleeps;
117 time_t from, to, tottime;
118 int days, hours, minutes;
121 struct caller *callers = NULL;
122 struct caller *callptr = NULL;
124 char thegraph[GRANULARITY][73];
131 for (a = 0; a < argc; ++a) {
132 if (!strcmp(argv[a], "-b"))
134 if (!strcmp(argv[a], "-p"))
139 for (a = 0; a < GRANULARITY; ++a)
141 "........................................................................");
151 for (a = 0; a < 72; ++a) {
167 logfp = fopen("citadel.log", "r");
169 perror("Could not open citadel.log");
173 printf("Scanning call log, please wait...\n");
175 while (fgets(buf, sizeof buf, logfp) != NULL) {
176 buf[strlen(buf) - 1] = 0;
179 LogTime = atol(strtok(buf, "|"));
180 LogType = atol(strtok(NULL, "|"));
181 strcpy(LogName, strtok(NULL, "|"));
183 if ( (LogType != 0) && (LogTime > 100L)
184 && (LogTime <= now) ) {
185 if ((LogTime < from) || (from == 0L))
187 if ((LogTime > to) || (to == 0L))
190 if (LogType & CL_CONNECT) {
195 strcpy(dname, LogName);
197 if (LogType & CL_LOGIN) {
200 for (callptr = callers; callptr != NULL; callptr = callptr->next) {
201 if (!strcmp(callptr->Cname, LogName)) {
203 ++callptr->Ctimescalled;
207 callptr = (struct caller *) malloc(sizeof(struct caller));
208 callptr->next = callers;
210 strcpy(callers->Cname, LogName);
211 callers->Ctimescalled = 1;
214 if (LogType & CL_NEWUSER)
216 if (LogType & CL_BADPW)
218 if (LogType & CL_TERMINATE) {
223 for (aa = cftime; aa <= cttime; aa = aa + 300L)
224 timeon[halfhour(aa)] = timeon[halfhour(aa)] + 5L;
229 if (LogType & CL_DROPCARR) {
234 for (aa = cftime; aa <= cttime; aa = aa + 300L)
235 timeon[halfhour(aa)] = timeon[halfhour(aa)] + 5L;
240 if (LogType & CL_SLEEPING) {
245 for (aa = cftime; aa <= cttime; aa = aa + 300L)
246 timeon[halfhour(aa)] = timeon[halfhour(aa)] + 5L;
258 days = (int) (tottime / 86400L);
259 hours = (int) ((tottime % 86400L) / 3600L);
260 minutes = (int) ((tottime % 3600L) / 60L);
262 printf(" Avg/Call Avg/Day Total\n");
263 disply("Calls:", calls);
264 disply("Logins:", logins);
265 disply("New users:", newusers);
266 disply("Bad pw attempts:", badpws);
267 disply("Proper logoffs:", terms);
268 disply("Carrier drops:", drops);
269 disply("Sleeping drops:", sleeps);
272 tm = (struct tm *) localtime(&from);
273 printf("From: %s", (char *) asctime(localtime(&from)));
274 printf("To: %s", (char *) asctime(localtime(&to)));
275 printf("Total report time: ");
276 printf("%d days, %d hours, %d minutes\n",
277 days, hours, minutes);
279 for (aa = from; aa <= to; aa = aa + 1200L)
280 timeup[halfhour(aa)] = timeup[halfhour(aa)] + 20L;
283 lowest = GRANULARITY - 1;
284 for (b = 0; b < 72; ++b) {
285 for (a = 0; a <= GRANULARITY; ++a) {
286 p = ((float) timeon[b]) / ((float) timeup[b]) * GRANULARITY;
289 thegraph[(GRANULARITY - 1) - a][b] = '#';
290 if (lowest > (GRANULARITY - 1) - a)
291 lowest = (GRANULARITY - 1) - a;
296 printf("\n\n\n\n\n\n");
298 b = ((GRANULARITY - lowest) / 18);
301 for (a = lowest; a < GRANULARITY; a = a + b)
302 printf("%2d%% |%s\n",
305 printf(" +------------------------------------------------------------------------\n");
306 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");
313 printf("Top 20 Callers (sorted by total number of logins)\n");
314 printf("Calls Avg/Day Username\n");
315 printf("----- ------- ------------------------------\n");
317 sortpipe = (FILE *) popen("sort |tail -20 |sort -nr", "w");
318 for (callptr = callers; callptr != NULL; callptr = callptr->next) {
319 fprintf(sortpipe, "%5d %7.2f %-30s\n",
320 callptr->Ctimescalled,
321 (((float) callptr->Ctimescalled) / ((float) days)),
325 while (callers != NULL) {
326 callptr = callers->next;
332 PC_ONLY_HERE:; /* yes this semicolon is necessary; the DEC C compiler
333 complains that a label must be followed by an actual
337 printf("Top 20 Contributing Users (post to call ratio)\n");
338 printf("P/C Ratio Username\n");
339 printf("--------- ------------------------------\n");
341 sortpipe = (FILE *) popen("sort |tail -20 |sort -nr", "w");
345 fakeargs[0] = "whobbs";
346 fakeargs[1] = "localhost";
347 fakeargs[2] = malloc(64);
348 snprintf(fakeargs[2], 64, "%d", config.c_port_number);
350 ipc = CtdlIPC_new(3, fakeargs, hostbuf, portbuf);
352 CtdlIPC_getline(ipc, buf);
353 if ((buf[0]!='2')&&(strncmp(buf,"551",3))) {
354 fprintf(stderr,"%s: %s\n",argv[0],&buf[4]);
357 CtdlIPC_putline(ipc, "LIST");
358 CtdlIPC_getline(ipc, buf);
359 if (buf[0]=='1') while (CtdlIPC_getline(ipc, buf),
360 strcmp(buf, "000")) {
361 extract(LogName, buf, 0);
362 fprintf(sortpipe, "%9.2f %-30s\n",
363 ((float) extract_int(buf,5) / (float) extract_int(buf,4)),