1 /* $Id$ */
2 
3 /***************************************************************************
4  *                                                                         *
5  *  AreaStat                                                               *
6  *  Copyleft (c) 2004-2010 by The Husky project                            *
7  *  Homepage: https://github.com/huskyproject/areastat/wiki                *
8  *                                                                         *
9  *  EchoStat Source, Version 1.06                                          *
10  *  Copyright (c) 2000 by Dmitry Rusov. (2:5090/94, rusov94@mail.ru)       *
11  *  All rights reserved.                                                   *
12  *                                                                         *
13  ***************************************************************************/
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <time.h>
19 
20 #include <huskylib/huskylib.h>
21 //#include <smapi/typedefs.h>
22 //#include <smapi/progprot.h>
23 #include <smapi/msgapi.h>
24 
25 #include "areastat.h"
26 #include "version.h"
27 
28 #define BUFSIZE 4096
29 #define nfree(a) { if (a != NULL) { free(a); a = NULL; } }
30 #define ISDIGIT(ch) ((ch) >= '0' && (ch) <= '9')
31 #define ISLWSP(ch) ((ch) == ' ' || (ch) == '\t')
32 
33 #define secs_in_day 86400
34 
35 typedef struct area {
36     char    *name;
37     char    *path;
38     char    *out_file;
39     int     type;
40 } s_area, *ps_area;
41 
42 typedef struct config {
43 
44     unsigned long by_name;
45     unsigned long by_from;
46     unsigned long by_to;
47     unsigned long by_from_to;
48     unsigned long by_total;
49     unsigned long by_size;
50     unsigned long by_qpercent;
51     unsigned long by_subj;
52     unsigned long by_date;
53     unsigned long by_wday;
54     unsigned long by_time;
55     unsigned long days_of_stat;
56     unsigned long areas_count;
57     unsigned long pkt_size;
58     unsigned char make_pkt;
59     hs_addr pkt_orig_addr;
60     hs_addr pkt_dest_addr;
61     char pkt_password[8];
62     char *pkt_from;
63     char *pkt_to;
64     char *pkt_subj;
65     char *pkt_origin;
66     char *pkt_inbound;
67     char *pkt_tearline;
68     ps_area  areas;
69 
70 } s_config, *ps_config;
71 
72 ps_config main_config;
73 
74 typedef struct unsorted_item {
75     char *name;
76     unsigned long from;
77     unsigned long to;
78 } s_unsorted_item, *ps_unsorted_item;
79 
80 typedef struct named_item {
81     char *name;
82     unsigned long count;
83 } s_named_item, *ps_named_item;
84 
85 typedef struct date_item {
86     time_t date;
87     struct tm tm_date;
88     unsigned long count;
89 } s_date_item, *ps_date_item;
90 
91 typedef struct time_item {
92     unsigned char hour;
93     unsigned long count;
94 } s_time_item, *ps_time_item;
95 
96 typedef struct size_item {
97     char *name;
98     unsigned long size;
99     unsigned long qsize;
100     float qpercent;
101 } s_size_item, *ps_size_item;
102 
103 ps_unsorted_item  global_data = NULL;
104 unsigned long gd_count = 0;
105 
106 ps_named_item from_data = NULL;
107 unsigned long fd_count = 0;
108 
109 ps_named_item to_data = NULL;
110 unsigned long td_count = 0;
111 
112 ps_named_item from_to_data = NULL;
113 unsigned long ftd_count = 0;
114 
115 ps_named_item total_data = NULL;
116 unsigned long ttd_count = 0;
117 
118 ps_named_item subj_data = NULL;
119 unsigned long sd_count = 0;
120 
121 ps_date_item date_data = NULL;
122 unsigned long dd_count = 0;
123 
124 ps_time_item time_data = NULL;
125 unsigned long tttd_count = 0;
126 
127 ps_size_item size_data = NULL;
128 unsigned long szd_count = 0;
129 
130 time_t global_msgid;
131 unsigned long days = 0;
132 unsigned long messages = 0;
133 float msgs_in_day = 0;
134 FILE * current_std;
135 FILE *out_pkt;
136 char *versionStr;
137 unsigned int isecs;
138 
139 static int aDaysFromJan1st[13] = {
140     0,                                  // Jan
141     31,                                 // Feb
142     31+28,                              // Mar
143     31+28+31,                           // Apr
144     31+28+31+30,                        // May
145     31+28+31+30+31,                     // Jun
146     31+28+31+30+31+30,                  // Jul
147     31+28+31+30+31+30+31,               // Aug
148     31+28+31+30+31+30+31+31,            // Sep
149     31+28+31+30+31+30+31+31+30,         // Oct
150     31+28+31+30+31+30+31+31+30+31,      // Nov
151     31+28+31+30+31+30+31+31+30+31+30,   // Dec
152     31+28+31+30+31+30+31+31+30+31+30+31 // Jan
153 };
154 
155 static int days_in_months[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
156 
name_comparer(const void * str1,const void * str2)157 int name_comparer(const void *str1, const void *str2)
158 {
159     return strcmp(((ps_unsorted_item)str1)->name,((ps_unsorted_item)str2)->name);
160 }
161 
ft_comparer(const void * str1,const void * str2)162 int ft_comparer(const void *str1, const void *str2)
163 {
164     return strcmp(((ps_named_item)str1)->name,((ps_named_item)str2)->name);
165 }
166 
ftc_comparer(const void * count1,const void * count2)167 int ftc_comparer(const void *count1, const void *count2)
168 {
169     if (((ps_named_item) count1) -> count > ((ps_named_item) count2) -> count) return -1;
170     if (((ps_named_item) count1) -> count == ((ps_named_item) count2) -> count) return 0;
171     return 1;
172 }
173 
size_comparer(const void * size1,const void * size2)174 int size_comparer(const void *size1, const void *size2)
175 {
176     if (((ps_size_item) size1) -> size > ((ps_size_item) size2) -> size) return -1;
177     if (((ps_size_item) size1) -> size == ((ps_size_item) size2) -> size) return 0;
178     return 1;
179 }
180 
qp_comparer(const void * qp1,const void * qp2)181 int qp_comparer(const void *qp1, const void *qp2)
182 {
183     if (((ps_size_item) qp1) -> qpercent > ((ps_size_item) qp2) -> qpercent) return -1;
184     if (((ps_size_item) qp1) -> qpercent == ((ps_size_item) qp2) -> qpercent) return 0;
185     return 1;
186 }
187 
date_comparer(const void * dt1,const void * dt2)188 int date_comparer(const void *dt1, const void *dt2)
189 {
190     if (((ps_date_item) dt1) -> date < ((ps_date_item) dt2) -> date) return -1;
191     if (((ps_date_item) dt1) -> date == ((ps_date_item) dt2) -> date) return 0;
192     return 1;
193 }
194 
do_sort_gap(unsigned long count,ps_named_item arr)195 void do_sort_gap(unsigned long count, ps_named_item arr)
196 {
197     unsigned long i=0,j=0;
198     while (j < count)
199     {
200         while (i < count)
201         {
202             i++;
203             if (i >= count && arr[i-1].count == arr[j].count)
204             {
205                 qsort (&arr[j], i-j, sizeof(s_named_item), ft_comparer);
206                 break;
207             }
208             if (arr[i].count != arr[j].count)
209             {
210                 qsort (&arr[j], i-j, sizeof(s_named_item), ft_comparer);
211                 break;
212             }
213         }
214         j = i;
215     }
216 }
217 
218 /* Next 4 routines was taken from Pete Kvitek's FMA */
219 
DoHasAddrChar(char * pch,char ch)220 int DoHasAddrChar(char * pch, char ch)
221 {
222     while (*pch && !ISLWSP(*pch))
223         if (*pch == ch) return 1;
224         else pch++;
225     return 0;
226 }
227 
DoIsAddrChar(char ch)228 int DoIsAddrChar(char ch)
229 {
230     return (ch && strchr("0123456789:/.", ch));
231 }
232 
ScanNetAddr(hs_addr * pnetAddr,char * psz)233 char * ScanNetAddr(hs_addr * pnetAddr, char * psz)
234 {
235     char * pch, * pchEnd;
236 
237     for (pch = psz; ISLWSP(*pch); pch++);
238     pchEnd = pch;
239 
240     if (DoIsAddrChar(*pch) && DoHasAddrChar(pch, ':'))
241     {
242         while (ISDIGIT(*pchEnd)) pchEnd++;
243         if (*pchEnd != ':' || pch == pchEnd) return NULL;
244         pnetAddr->zone = (unsigned short)atoi(pch);
245         pch = ++pchEnd;
246         if (!ISDIGIT(*pch) || !DoHasAddrChar(pch, '/')) return NULL;
247     }
248 
249     if (DoIsAddrChar(*pch) && DoHasAddrChar(pch, '/'))
250     {
251         while (ISDIGIT(*pchEnd)) pchEnd++;
252         if (*pchEnd != '/' || pch == pchEnd) return NULL;
253         pnetAddr->net = (unsigned short)atoi(pch);
254         pch = ++pchEnd;
255         if (!ISDIGIT(*pch)) return NULL;
256     }
257 
258     if (DoIsAddrChar(*pch) && *pch != '.')
259     {
260         while (ISDIGIT(*pchEnd)) pchEnd++;
261         pnetAddr->node = (unsigned short)atoi(pch);
262         pch = pchEnd;
263     }
264 
265     if (*pch != '.') {
266         pnetAddr->point = 0;
267     } else {
268         for (pchEnd = ++pch; ISDIGIT(*pchEnd); pchEnd++);
269         pnetAddr->point = (unsigned short)atoi(pch);
270         pch = pchEnd;
271     }
272 
273     return (pnetAddr->zone && pnetAddr->net) ? pch : NULL;
274 
275 }
276 
get_time_from_stamp(struct _stamp mtime)277 unsigned long get_time_from_stamp (struct _stamp mtime)
278 {
279     unsigned long hour, min, sec;
280     unsigned long day, mon, year;
281     unsigned long nDaysSince1970;
282     unsigned long nYearsSince1970;
283 
284     hour = mtime.time.hh;
285     min  = mtime.time.mm;
286     sec  = mtime.time.ss * 2;
287     day  = mtime.date.da;
288     mon  = mtime.date.mo;
289     year = mtime.date.yr + 80;        // Years since 1900
290 
291     nYearsSince1970 = year - 70;
292 
293     nDaysSince1970 = nYearsSince1970 * 365 + ((nYearsSince1970 + 1) / 4);
294 
295     nDaysSince1970 += aDaysFromJan1st[mon - 1] + (day - 1);
296 
297     if ((year & 3) == 0 && mon > 2) nDaysSince1970++;
298 
299     return (((unsigned long) nDaysSince1970 * (24L * 60L * 60L))
300             + ((unsigned long) hour * (60L * 60L))
301             + ((unsigned long) min * 60L)
302             +  (unsigned long) sec);
303 
304 }
305 
reading_base(unsigned long ii)306 int reading_base(unsigned long ii)
307 {
308     XMSG msg;
309     HAREA in_area;
310     HMSG in_msg;
311     void *ptr;
312     char buffer[BUFSIZE+1], *dummy, *c;
313     dword offset, msgn, qsize, textlen;
314     long got;
315     unsigned long i;
316     word t1=MSGTYPE_NOTH;
317     long nf, nt, qpos;
318     struct _minf mi;
319     time_t atime = time(NULL);
320     time_t mtime = 0, period = 0;
321     struct tm tmp_tm;
322 
323     gd_count = fd_count = td_count = ftd_count = ttd_count =
324         sd_count = dd_count = szd_count = tttd_count = 0;
325     days = 0; messages = 0; msgs_in_day = 0;
326 
327 
328     fprintf(stderr,"Scanning area %s, %s...\n",
329             main_config->areas[ii].name,main_config->areas[ii].path);
330 
331     if (main_config->areas[ii].type == 1) t1 = MSGTYPE_SDM; else
332         if (main_config->areas[ii].type == 2) t1 = MSGTYPE_SQUISH; else
333             if (main_config->areas[ii].type == 3) t1 = MSGTYPE_JAM;
334 
335     memset(&mi, '\0', sizeof mi);
336     mi.def_zone=2;
337 
338     MsgOpenApi(&mi);
339 
340     if ((in_area=MsgOpenArea((byte*)main_config->areas[ii].path, MSGAREA_NORMAL, t1))==NULL)
341     {
342       char *tl_str="unknown";
343       switch (t1)
344       {
345         case MSGTYPE_SDM: tl_str="Msg (OPUS)"; break;
346         case MSGTYPE_JAM: tl_str="Jam"; break;
347         case MSGTYPE_SQUISH: tl_str="Squish"; break;
348       }
349         fprintf(stderr,"Error opening area `%s' (type %s) for read!\n\n",
350                 main_config->areas[ii].path, tl_str);
351         exit(1);
352     }
353 
354     MsgLock(in_area);
355 
356     for (msgn=1L; msgn <= MsgHighMsg(in_area); msgn++)
357     {
358         if ((msgn % 5)==0)
359         {
360             fprintf(stderr,"Scanning msg: %lu\r",msgn);
361             fflush(stdout);
362         }
363         if ((in_msg=MsgOpenMsg(in_area,MOPEN_READ,msgn))==NULL) continue;
364         ptr = in_msg;
365         MsgReadMsg(in_msg, &msg, 0L, 0L, NULL, 0, NULL);
366         qsize = 0;
367         textlen = MsgGetTextLen(in_msg);
368         for (offset=0L; offset < textlen;)
369         {
370             if ((textlen-offset) >= BUFSIZE)
371                 got = MsgReadMsg(in_msg, NULL, offset, BUFSIZE, buffer, 0L, NULL);
372             else
373                 got = MsgReadMsg(in_msg, NULL, offset, textlen-offset, buffer, 0L, NULL);
374 
375             if (got == 0)
376                 break; /* we read 0 bytes - the end of message */
377             offset += got;
378             // find a quote
379             c = strtok (buffer, "\n\r");
380             while (c != NULL)
381             {
382                 c = strtok (NULL,"\n\r");
383                 if (c != NULL)
384                 {
385                     for (qpos = 0; qpos<10 && *c; qpos++)
386                     {
387                         if (*c == '>')
388                         {
389                             qsize += strlen (c);
390                             break;
391                         }
392                         c++;
393                     }
394                 }
395             }
396             if (got <= 0)
397                 break;
398         } /* for */
399 
400         in_msg = ptr;
401         MsgCloseMsg(in_msg);
402 
403         mtime = get_time_from_stamp(msg.date_written);
404         period = atime - mtime;
405         if (!period || period > main_config->days_of_stat * secs_in_day) continue;
406         tmp_tm = *localtime (&mtime);
407         tmp_tm.tm_mon++;
408         messages++;
409 
410         // by name
411         nf = 0; nt = 0;
412         for (i=0; i<gd_count; i++)
413         {
414             if (stricmp(global_data[i].name,msg.from) == 0)
415             {
416                 global_data[i].from++;
417                 nf = 1;
418             }
419             if (stricmp(global_data[i].name,msg.to) == 0)
420             {
421                 global_data[i].to++;
422                 nt = 1;
423             }
424         }
425 
426         if (!nf)
427         {
428             gd_count++;
429             global_data = srealloc (global_data, gd_count * sizeof(s_unsorted_item));
430             global_data[gd_count-1].name = smalloc(strlen(msg.from)+1);
431             strcpy (global_data[gd_count-1].name,msg.from);
432             global_data[gd_count-1].from = 1;
433             global_data[gd_count-1].to = 0;
434         }
435 
436 
437         if (!nt)
438         {
439             gd_count++;
440             global_data = srealloc (global_data, gd_count * sizeof(s_unsorted_item));
441             global_data[gd_count-1].name = smalloc(strlen(msg.to)+1);
442             strcpy (global_data[gd_count-1].name,msg.to);
443             global_data[gd_count-1].from = 0;
444             global_data[gd_count-1].to = 1;
445         }
446         // by from
447         if (main_config->by_from)
448         {
449             nf = 0;
450             for (i = 0; i < fd_count; i++)
451             {
452                 if (!stricmp(from_data[i].name,msg.from))
453                 {
454                     from_data[i].count++;
455                     nf = 1;
456                 }
457             }
458 
459             if (!nf)
460             {
461                 fd_count++;
462                 from_data = srealloc (from_data,fd_count * sizeof(s_named_item));
463                 from_data[fd_count-1].name = (char *) smalloc(strlen(msg.from)+1);
464                 strcpy (from_data[fd_count-1].name,msg.from);
465                 from_data[fd_count-1].count = 1;
466             }
467         }
468         // by to
469         if (main_config->by_to)
470         {
471             nf = 0;
472             for (i = 0; i < td_count; i++)
473             {
474                 if (!stricmp(to_data[i].name,msg.to))
475                 {
476                     to_data[i].count++;
477                     nf = 1;
478                 }
479             }
480 
481             if (!nf)
482             {
483                 td_count++;
484                 to_data = srealloc (to_data, td_count * sizeof(s_named_item));
485                 to_data[td_count-1].name = (char *) smalloc(strlen(msg.to)+1);
486                 strcpy (to_data[td_count-1].name,msg.to);
487                 to_data[td_count-1].count = 1;
488             }
489         }
490         // by subj
491         if (main_config->by_subj)
492         {
493             nf = 0;
494             for (i = 0; i < sd_count; i++)
495             {
496                 if (!stricmp(subj_data[i].name,msg.subj))
497                 {
498                     subj_data[i].count++;
499                     nf = 1;
500                 }
501             }
502 
503             if (!nf)
504             {
505                 sd_count++;
506                 subj_data = srealloc (subj_data, sd_count * sizeof(s_named_item));
507                 subj_data[sd_count-1].name = (char *) smalloc(strlen(msg.subj)+1);
508                 strcpy (subj_data[sd_count-1].name,msg.subj);
509                 subj_data[sd_count-1].count = 1;
510             }
511         }
512 
513         // by date
514         nf = 0;
515         for (i = 0; i < dd_count; i++)
516         {
517             if (tmp_tm.tm_mday == date_data[i].tm_date.tm_mday &&
518                 tmp_tm.tm_mon == date_data[i].tm_date.tm_mon &&
519                 tmp_tm.tm_year == date_data[i].tm_date.tm_year)
520             {
521                 date_data[i].count++;
522                 nf = 1;
523             }
524         }
525 
526         if (!nf)
527         {
528             dd_count++;
529             date_data = srealloc (date_data, dd_count * sizeof(s_date_item));
530             date_data[dd_count-1].date = mtime;
531             date_data[dd_count-1].tm_date = tmp_tm;
532             date_data[dd_count-1].count = 1;
533         }
534 
535         // by time
536         if (main_config->by_time)
537         {
538             nf = 0;
539             for (i = 0; i < tttd_count; i++)
540             {
541                 if (tmp_tm.tm_hour == time_data[i].hour)
542                 {
543                     time_data[i].count++;
544                     nf = 1;
545                 }
546             }
547 
548             if (!nf)
549             {
550                 tttd_count++;
551                 time_data = srealloc (time_data, tttd_count * sizeof(s_time_item));
552                 time_data[tttd_count-1].hour = (unsigned char)tmp_tm.tm_hour;
553                 time_data[tttd_count-1].count = 1;
554             }
555         }
556 
557         // by size
558         if (main_config->by_size)
559         {
560             nf = 0;
561             for (i = 0; i < szd_count; i++)
562             {
563                 if (!stricmp(size_data[i].name,msg.from))
564                 {
565                     size_data[i].size += offset;
566                     size_data[i].qsize += qsize;
567                     nf = 1;
568                 }
569             }
570 
571             if (!nf)
572             {
573                 szd_count++;
574                 size_data = srealloc (size_data, szd_count * sizeof(s_size_item));
575                 size_data[szd_count-1].name = (char *) smalloc(strlen(msg.from)+1);
576                 strcpy (size_data[szd_count-1].name,msg.from);
577                 size_data[szd_count-1].size = offset;
578                 size_data[szd_count-1].qsize = qsize;
579             }
580         }
581 
582         // by from -> to
583         if (main_config->by_from_to)
584         {
585 
586             nf = 0;
587             dummy = (char *) smalloc (strlen(msg.from)+strlen(msg.to)+2);
588             strcpy (dummy,msg.from);
589             strcat (dummy,"");
590             strcat (dummy,msg.to);
591             for (i = 0; i < ftd_count; i++)
592             {
593                 if (!stricmp(from_to_data[i].name,dummy))
594                 {
595                     from_to_data[i].count++;
596                     nf = 1;
597                     free(dummy);
598                 }
599             }
600 
601             if (!nf)
602             {
603                 ftd_count++;
604                 from_to_data = srealloc (from_to_data, ftd_count * sizeof(s_named_item));
605                 from_to_data[ftd_count-1].name = dummy;
606                 from_to_data[ftd_count-1].count = 1;
607             }
608         }
609 
610     } /* for msgn */
611 
612     qsort (date_data, dd_count, sizeof(s_date_item), date_comparer);
613 
614     MsgCloseArea(in_area);
615     MsgCloseApi();
616 
617     return 0;
618 }
619 
free_all()620 int free_all()
621 {
622     unsigned long i;
623 
624     for (i = 0; i<gd_count; i++)
625     {
626         free(global_data[i].name);
627     }
628 
629     if (global_data) free (global_data);
630     return 0;
631 }
632 
print_summary_statistics(unsigned long i)633 int print_summary_statistics(unsigned long i)
634 {
635     struct tm fd, ld;
636     time_t tt = time(NULL);
637 
638     if (dd_count > 0)
639     {
640         fd = date_data[0].tm_date;
641         ld = date_data[dd_count-1].tm_date;
642         days = (unsigned long)((date_data[dd_count-1].date-date_data[0].date)/secs_in_day)+1;
643 
644     } else  {
645 
646         fd = *localtime(&tt);
647         ld = *localtime(&tt);
648     }
649 
650     if (!days) days = 1;
651     fprintf(current_std,"\n --- Summary\n\n");
652 
653     fprintf(current_std,"  Area: %s\n",main_config->areas[i].name);
654     fprintf(current_std,"  Period: %s %02d %s %d - %s %02d %s %d\n",
655             weekday_ab[fd.tm_wday],fd.tm_mday,months_ab[fd.tm_mon-1],fd.tm_year+1900,
656             weekday_ab[ld.tm_wday],ld.tm_mday,months_ab[ld.tm_mon-1],ld.tm_year+1900);
657 
658     fprintf(current_std,"  Messages: %lu\n",messages);
659     fprintf(current_std,"  Total users: %lu\n",gd_count);
660     fprintf(current_std,"  Active users: %lu\n",fd_count);
661     fprintf(current_std,"  Days: %lu\n",days);
662     fprintf(current_std,"  Msgs per day: %lu\n",(unsigned long)messages/days);
663 
664     return 0;
665 }
666 
print_statistics_by_name()667 int print_statistics_by_name()
668 {
669     unsigned long i,tot_from = 0, tot_to = 0, tot_tot = 0;
670 
671     qsort (global_data, gd_count, sizeof(s_unsorted_item), name_comparer);
672 
673     fprintf(current_std,"\n --- Sorted by Name\n");
674     fprintf(current_std,"����������������������������������������������������������������������Ŀ\n");
675     fprintf(current_std,"� No. � Name                                     � From � To   � Total �\n");
676     fprintf(current_std,"����������������������������������������������������������������������Ĵ\n");
677 
678     for (i=0; i<gd_count; i++)
679     {
680         fprintf(current_std,"�%4lu.� %-41s�%6lu�%6lu�%7lu�\n",i+1,global_data[i].name,
681                 global_data[i].from,global_data[i].to,global_data[i].from+global_data[i].to);
682         tot_from += global_data[i].from;
683         tot_to += global_data[i].to;
684 
685     } /* for */
686 
687     tot_tot = tot_from+tot_to;
688     fprintf(current_std,"����������������������������������������������������������������������Ĵ\n");
689     fprintf(current_std,"�     �                                          �%6lu�%6lu�%7lu�\n",tot_from,tot_to,tot_tot);
690     fprintf(current_std,"������������������������������������������������������������������������\n");
691 
692     return 0;
693 }
694 
print_statistics_by_from()695 int print_statistics_by_from()
696 {
697     unsigned long i;
698     char diag[80],name[32];
699 
700     qsort (from_data, fd_count, sizeof(s_named_item), ftc_comparer);
701     do_sort_gap(fd_count,from_data);
702 
703     fprintf(current_std,"\n --- Sorted by From. Top %lu\n",main_config->by_from);
704 
705     fprintf(current_std,"����������������������������������������������������������������������������Ŀ\n");
706     fprintf(current_std,"� No. � Name                           � From �                              �\n");
707     fprintf(current_std,"����������������������������������������������������������������������������Ĵ\n");
708 
709     for (i=0; i < fd_count; i++)
710     {
711         unsigned long j, k;
712 
713         if (i >= main_config->by_from) break;
714 
715         strcpy(diag,"\0");
716         k = (unsigned long)((from_data[i].count/(float)(from_data[0].count))*30);
717         if (k == 0) strcpy(diag,"�"); else
718             for (j = 0;j < k ;j++) strcat(diag,"�");
719         for (j=0; j<32; j++) name[j] = '\0';
720         strncpy(name,from_data[i].name,30);
721 
722         fprintf(current_std,"�%4lu.� %-31s�%6lu�%-30s�\n",i+1,name,from_data[i].count,diag);
723 
724     } /* for */
725 
726     fprintf(current_std,"������������������������������������������������������������������������������\n");
727 
728     return 0;
729 }
730 
print_statistics_by_to()731 int print_statistics_by_to()
732 {
733     unsigned long i;
734     char diag[80],name[32];
735 
736     qsort (to_data, td_count, sizeof(s_named_item), ftc_comparer);
737     do_sort_gap(td_count,to_data);
738 
739     fprintf(current_std,"\n --- Sorted by To. Top %lu\n",main_config->by_to);
740     fprintf(current_std,"����������������������������������������������������������������������������Ŀ\n");
741     fprintf(current_std,"� No. � Name                           �  To  �                              �\n");
742     fprintf(current_std,"����������������������������������������������������������������������������Ĵ\n");
743 
744     for (i=0; i < td_count; i++)
745     {
746         unsigned long j, k;
747 
748         if (i >= main_config->by_to) break;
749 
750         strcpy(diag,"\0");
751         k = (unsigned long)((to_data[i].count/(float)(to_data[0].count))*30);
752         if (k == 0) strcpy(diag,"�"); else
753             for (j = 0;j < k ;j++) strcat(diag,"�");
754         for (j=0; j<32; j++) name[j] = '\0';
755         strncpy(name,to_data[i].name,30);
756 
757         fprintf(current_std,"�%4lu.� %-31s�%6lu�%-30s�\n",i+1,name,to_data[i].count,diag);
758 
759     } /* for */
760 
761     fprintf(current_std,"������������������������������������������������������������������������������\n");
762 
763     return 0;
764 }
765 
print_statistics_by_from_to()766 int print_statistics_by_from_to()
767 {
768     unsigned long i;
769     char diag[80],name1[32],name2[32];
770 
771     qsort (from_to_data, ftd_count, sizeof(s_named_item), ftc_comparer);
772     do_sort_gap(ftd_count,from_to_data);
773 
774     fprintf(current_std,"\n --- Sorted by From -> To. Top %lu\n",main_config->by_from_to);
775     fprintf(current_std,"����������������������������������������������������������������������������Ŀ\n");
776     fprintf(current_std,"� No. � From                 � To                    � Msgs �                �\n");
777     fprintf(current_std,"����������������������������������������������������������������������������Ĵ\n");
778 
779     for (i=0; i < ftd_count; i++)
780     {
781         unsigned long k, l, n;
782 
783         if (i >= main_config->by_from_to) break;
784 
785         strcpy(diag,"\0");
786         k = (unsigned long)((from_to_data[i].count/(float)(from_to_data[0].count))*16);
787         if (k == 0)
788             strcpy(diag,"�");
789         else
790         {
791             unsigned long j;
792 
793             for (j = 0; j < k; j++)
794                 strcat(diag,"�");
795         }
796 
797         n = 0;
798 
799         for (l=0; l<32; l++) name1[l] = '\0';
800         for (l=0; l<20; l++)
801         {
802             if (from_to_data[i].name[n] == '\0' || from_to_data[i].name[n] == '') break;
803             name1[l] = from_to_data[i].name[n];
804             n++;
805         }
806 
807         name1[l] = '\0';
808 
809         while(from_to_data[i].name[n] && from_to_data[i].name[n] != '') n++;
810 
811         for (l=0; l<32; l++) name2[l] = '\0';
812         for (l=0; l<20; l++)
813         {
814             if (from_to_data[i].name[n] == '') n++;
815             if (!from_to_data[i].name[n]) break;
816             name2[l] = from_to_data[i].name[n];
817             n++;
818         }
819 
820         name2[l] = '\0';
821 
822         fprintf(current_std,"�%4lu.� %-21s� %-22s�%6lu�%-16s�\n",i+1,name1,name2,from_to_data[i].count,diag);
823 
824     } /* for */
825 
826     fprintf(current_std,"������������������������������������������������������������������������������\n");
827 
828     return 0;
829 }
830 
print_statistics_by_total()831 int print_statistics_by_total()
832 {
833     unsigned long i;
834     char diag[80],name[32];
835 
836     for (i = 0; i < gd_count; i++)
837     {
838         ttd_count++;
839         total_data = srealloc (total_data, ttd_count * sizeof(s_named_item));
840         total_data[ttd_count-1].name = (char *) smalloc(strlen(global_data[i].name)+1);
841         strcpy (total_data[ttd_count-1].name,global_data[i].name);
842         total_data[ttd_count-1].count = global_data[i].from+global_data[i].to;
843     }
844 
845     qsort (total_data, ttd_count, sizeof(s_named_item), ftc_comparer);
846     do_sort_gap(ttd_count,total_data);
847 
848     fprintf(current_std,"\n --- Sorted by Total. Top %lu\n",main_config->by_total);
849     fprintf(current_std,"����������������������������������������������������������������������������Ŀ\n");
850     fprintf(current_std,"� No. � Name                           � Msgs �                              �\n");
851     fprintf(current_std,"����������������������������������������������������������������������������Ĵ\n");
852 
853     for (i=0; i < ttd_count; i++)
854     {
855         unsigned long k, j;
856 
857         if (i >= main_config->by_total) break;
858 
859         strcpy(diag,"\0");
860         k = (unsigned long)((total_data[i].count/(float)(total_data[0].count))*30);
861         if (k == 0) strcpy(diag,"�"); else
862             for (j = 0;j < k ;j++) strcat(diag,"�");
863         for (j=0; j<32; j++) name[j] = '\0';
864         strncpy(name,total_data[i].name,30);
865 
866         fprintf(current_std,"�%4lu.� %-31s�%6lu�%-30s�\n",i+1,name,total_data[i].count,diag);
867 
868     } /* for */
869 
870     fprintf(current_std,"������������������������������������������������������������������������������\n");
871 
872     return 0;
873 }
874 
print_statistics_by_size()875 int print_statistics_by_size()
876 {
877     unsigned long i,j;
878     char diag[80],name[32];
879 
880     qsort (size_data, szd_count, sizeof(s_size_item), size_comparer);
881 
882     fprintf(current_std,"\n --- Sorted by Size. Top %lu\n",main_config->by_size);
883     fprintf(current_std,"����������������������������������������������������������������������������Ŀ\n");
884     fprintf(current_std,"� No. � Name                     � Size  � Quote �                           �\n");
885     fprintf(current_std,"����������������������������������������������������������������������������Ĵ\n");
886 
887     for (i=0; i < szd_count; i++)
888     {
889         unsigned long k;
890 
891         if (i >= main_config->by_size) break;
892 
893         strcpy(diag,"\0");
894         k = (unsigned long)((size_data[i].size/(float)(size_data[0].size))*27);
895         if (k == 0) strcpy(diag,"�"); else
896             for (j = 0;j < k ;j++) strcat(diag,"�");
897         for (j=0; j<32; j++) name[j] = '\0';
898         strncpy(name,size_data[i].name,24);
899 
900         fprintf(current_std,"�%4lu.� %-25s�%7lu�%7lu�%-27s�\n",i+1,name,size_data[i].size,size_data[i].qsize,diag);
901 
902     } /* for */
903 
904 
905     fprintf(current_std,"������������������������������������������������������������������������������\n");
906 
907     return 0;
908 }
909 
print_statistics_by_qpercent()910 int print_statistics_by_qpercent()
911 {
912     unsigned long i;
913     char diag[80],name[32];
914 
915     for (i = 0; i < szd_count; i++)
916         size_data[i].qpercent = ((float)size_data[i].qsize/size_data[i].size)*100;
917     qsort (size_data, szd_count, sizeof(s_size_item), qp_comparer);
918 
919     fprintf(current_std,"\n --- Sorted by QPercent. Top %lu\n",main_config->by_qpercent);
920     fprintf(current_std,"����������������������������������������������������������������������������Ŀ\n");
921     fprintf(current_std,"� No. � Name                           � QPer �                              �\n");
922     fprintf(current_std,"����������������������������������������������������������������������������Ĵ\n");
923 
924     for (i=0; i < szd_count; i++)
925     {
926         unsigned long j, k;
927 
928         if (i >= main_config->by_qpercent) break;
929 
930         strcpy(diag,"\0");
931         if (size_data[0].qpercent >0 )
932             k = (unsigned long)((size_data[i].qpercent/(float)(size_data[0].qpercent))*30);
933         else k = 0;
934         for (j = 0;j < k ;j++) strcat(diag,"�");
935         for (j=0; j<32; j++) name[j] = '\0';
936         strncpy(name,size_data[i].name,30);
937 
938         fprintf(current_std,"�%4lu.� %-31s�%6.2lf�%-30s�\n",i+1,name,size_data[i].qpercent,diag);
939 
940     } /* for */
941 
942     fprintf(current_std,"������������������������������������������������������������������������������\n");
943 
944     return 0;
945 }
946 
print_statistics_by_subj()947 int print_statistics_by_subj()
948 {
949     unsigned long i;
950     char name[60];
951 
952     qsort (subj_data, sd_count, sizeof(s_named_item), ftc_comparer);
953     do_sort_gap(sd_count,subj_data);
954 
955     fprintf(current_std,"\n --- Sorted by Subj. Top %lu\n",main_config->by_subj);
956     fprintf(current_std,"����������������������������������������������������������������������Ŀ\n");
957     fprintf(current_std,"� No. � Subj                                                    � Msgs �\n");
958     fprintf(current_std,"����������������������������������������������������������������������Ĵ\n");
959 
960     for (i=0; i < sd_count; i++)
961     {
962         unsigned long j, l;
963 
964         if (i >= main_config->by_subj) break;
965 
966         l = strlen(subj_data[i].name);
967 
968         for (j = 0; j < 56; j++) name[j] = '\0';
969         for (j = 0; j < 55 && j < l; j++) name[j] = subj_data[i].name[j];
970 
971         fprintf(current_std,"�%4lu.� %-56s�%6lu�\n",i+1,name,subj_data[i].count);
972 
973     } /* for */
974 
975     fprintf(current_std,"������������������������������������������������������������������������\n");
976 
977     return 0;
978 }
979 
print_statistics_by_date()980 int print_statistics_by_date()
981 {
982     unsigned long i, maxcount;
983     char diag[80];
984 
985     fprintf(current_std,"\n --- Sorted by date\n\n");
986 
987     maxcount = 0;
988     for (i = 0; i < dd_count; i++) if (date_data[i].count > maxcount)
989         maxcount = date_data[i].count;
990 
991     for (i = 0; i < dd_count; i++)
992     {
993         unsigned long k;
994 
995         strcpy(diag,"\0");
996         k = (unsigned long)((date_data[i].count/(float)(maxcount))*59);
997         if (k == 0)
998             strcpy(diag,"�");
999         else
1000         {
1001             unsigned long j;
1002 
1003             for (j = 0; j < k; j++)
1004                 strcat(diag,"�");
1005         }
1006 
1007         fprintf(current_std," %02d-%02d-%04d %4lu �%-59s\n",date_data[i].tm_date.tm_mday,
1008                 date_data[i].tm_date.tm_mon,date_data[i].tm_date.tm_year+1900,date_data[i].count,diag);
1009 
1010     } /* for */
1011 
1012     fprintf(current_std,"                 ������������������������������������������������������������>\n");
1013 
1014     return 0;
1015 }
1016 
print_statistics_by_wdays()1017 int print_statistics_by_wdays()
1018 {
1019     unsigned long i, maxcount;
1020     unsigned long counts[7] = {0,0,0,0,0,0,0};
1021     char diag[80];
1022 
1023     fprintf(current_std,"\n --- Sorted by WeekDay\n\n");
1024 
1025     for (i = 0; i < dd_count; i++)
1026     {
1027         switch (date_data[i].tm_date.tm_wday)
1028         {
1029         case 0: {counts[0] += date_data[i].count; break;}
1030         case 1: {counts[1] += date_data[i].count; break;}
1031         case 2: {counts[2] += date_data[i].count; break;}
1032         case 3: {counts[3] += date_data[i].count; break;}
1033         case 4: {counts[4] += date_data[i].count; break;}
1034         case 5: {counts[5] += date_data[i].count; break;}
1035         case 6: {counts[6] += date_data[i].count; break;}
1036         }
1037     }
1038 
1039     maxcount = 0;
1040     for (i = 0; i <= 6; i++) if (counts[i] > maxcount) maxcount = counts[i];
1041 
1042     for (i = 0; i <= 6; i++)
1043     {
1044         unsigned long j, k;
1045 
1046         strcpy(diag,"\0");
1047         k = (unsigned long)((counts[i]/(float)(maxcount))*60);
1048         for (j = 0;j < k ;j++) strcat(diag,"�");
1049 
1050         fprintf(current_std," %s %6lu�%-60s\n",weekday_ab[i],counts[i],diag);
1051 
1052     }
1053 
1054     fprintf(current_std,"           �������������������������������������������������������������>\n");
1055     return 0;
1056 }
1057 
print_statistics_by_time()1058 int print_statistics_by_time()
1059 {
1060     unsigned long i, j, maxcount;
1061     unsigned long counts[24] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
1062     char diag[80], str1[] = "�  ", str2[] = "   ";
1063 
1064     fprintf(current_std,"\n --- Sorted by time\n\n");
1065 
1066     for (i = 0; i < tttd_count; i++)
1067     {
1068         switch (time_data[i].hour)
1069         {
1070         case 0: {counts[0] += time_data[i].count; break;}
1071         case 1: {counts[1] += time_data[i].count; break;}
1072         case 2: {counts[2] += time_data[i].count; break;}
1073         case 3: {counts[3] += time_data[i].count; break;}
1074         case 4: {counts[4] += time_data[i].count; break;}
1075         case 5: {counts[5] += time_data[i].count; break;}
1076         case 6: {counts[6] += time_data[i].count; break;}
1077         case 7: {counts[7] += time_data[i].count; break;}
1078         case 8: {counts[8] += time_data[i].count; break;}
1079         case 9: {counts[9] += time_data[i].count; break;}
1080         case 10: {counts[10] += time_data[i].count; break;}
1081         case 11: {counts[11] += time_data[i].count; break;}
1082         case 12: {counts[12] += time_data[i].count; break;}
1083         case 13: {counts[13] += time_data[i].count; break;}
1084         case 14: {counts[14] += time_data[i].count; break;}
1085         case 15: {counts[15] += time_data[i].count; break;}
1086         case 16: {counts[16] += time_data[i].count; break;}
1087         case 17: {counts[17] += time_data[i].count; break;}
1088         case 18: {counts[18] += time_data[i].count; break;}
1089         case 19: {counts[19] += time_data[i].count; break;}
1090         case 20: {counts[20] += time_data[i].count; break;}
1091         case 21: {counts[21] += time_data[i].count; break;}
1092         case 22: {counts[22] += time_data[i].count; break;}
1093         case 23: {counts[23] += time_data[i].count; break;}
1094         }
1095     }
1096 
1097     maxcount = 0;
1098     for (i = 0; i <= 23; i++) if (counts[i] > maxcount) maxcount = counts[i];
1099 
1100     for (j = 20; j > 0; j--)
1101     {
1102         strcpy(diag,"\0");
1103 
1104         for (i = 0; i <= 23; i++)
1105         {
1106             unsigned long k;
1107 
1108             k = (unsigned long)((counts[i]/(float)(maxcount))*20);
1109 
1110             if (k >= j) strcat(diag,"�� "); else
1111                 if ((j % 5) == 0) strcat (diag,str1); else  strcat (diag,str2);
1112 
1113         }
1114 
1115         if (j == 20)  fprintf(current_std,"100%%�%s\n",diag); else
1116             if (j == 15)  fprintf(current_std," 75%%�%s\n",diag); else
1117                 if (j == 10)  fprintf(current_std," 50%%�%s\n",diag); else
1118                     if (j == 5)  fprintf(current_std," 25%%�%s\n",diag); else
1119                         fprintf(current_std,"    �%s\n",diag);
1120 
1121     }
1122 
1123     fprintf(current_std,"  0%%�������������������������������������������������������������������������>\n");
1124     fprintf(current_std,"      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");
1125 
1126     return 0;
1127 }
1128 
print_err(char * s,unsigned long i)1129 void print_err(char *s, unsigned long i)
1130 {
1131     printf("Error in config (line %lu): \"%s\"\n\n",i,s);
1132     exit(2);
1133 }
1134 
read_cfg(char * cfg_name)1135 s_config *read_cfg(char *cfg_name)
1136 {
1137 
1138     FILE        *fcfg;
1139     s_config    *config;
1140     char        *s0,*s1,*s2,*s3,*s4,*buff;
1141     char        line[BUFSIZE+1];
1142     time_t      at = time (NULL);
1143     struct tm   t;
1144     unsigned long i = 0, j = 0, n, wd, md;
1145 
1146     if ((fcfg = fopen(cfg_name,"rb")) == NULL)
1147     {
1148         fprintf(stderr,"Cannot open file: \"%s\"\n\n",cfg_name);
1149         exit(2);
1150     }
1151 
1152     t = *localtime (&at);
1153 
1154     wd = t.tm_wday; if (wd == 0) wd = 7;
1155 
1156     config = (s_config *) smalloc(sizeof(s_config));
1157 
1158     memset(config, 0, sizeof(s_config));
1159 
1160     config->by_from = config->by_to = config->by_from_to = config->by_total =
1161         config->by_size = config->by_qpercent = config->by_subj = config->by_name =
1162         config->by_wday = config->by_date = config->by_time = 0;
1163 
1164     config->days_of_stat = 365;
1165 
1166     config->areas_count = 0;
1167 
1168     config->pkt_size = 10240;
1169     config->make_pkt = 0;
1170     config->pkt_orig_addr.zone = 0;
1171     config->pkt_orig_addr.net = 0;
1172     config->pkt_orig_addr.node = 0;
1173     config->pkt_orig_addr.point = 0;
1174     config->pkt_dest_addr.zone = 0;
1175     config->pkt_dest_addr.net = 0;
1176     config->pkt_dest_addr.node = 0;
1177     config->pkt_dest_addr.point = 0;
1178     for (j = 0; j<8; j++) config->pkt_password[j] = '\0';
1179     config->pkt_from = NULL;
1180     config->pkt_to = NULL;
1181     config->pkt_subj = NULL;
1182     config->pkt_origin = NULL;
1183     config->pkt_inbound = NULL;
1184     config->pkt_tearline = NULL;
1185 
1186     buff = malloc(BUFSIZE+1);
1187 
1188     while (fgets(line,BUFSIZE,fcfg))
1189     {
1190         i++;
1191 
1192         if (line == NULL) continue;
1193 
1194         j = strlen (line) - 1;
1195         while(j && (line[j] == '\r' || line[j] == '\n')) {line[j]='\0'; j--;}
1196 
1197         strcpy(buff,line);
1198 
1199         s0 = strtok(line,"\t \r\n");
1200         if (s0 == NULL) continue;
1201         if (*s0 == ';' || *s0 == '#') continue;
1202 
1203         if (!stricmp(s0,"By_Name"))
1204         {
1205             config->by_name = 1;
1206             continue;
1207         }
1208 
1209         if (!stricmp(s0,"By_Date"))
1210         {
1211             config->by_date = 1;
1212             continue;
1213         }
1214 
1215         if (!stricmp(s0,"By_WDay"))
1216         {
1217             config->by_wday = 1;
1218             continue;
1219         }
1220 
1221         if (!stricmp(s0,"By_Time"))
1222         {
1223             config->by_time = 1;
1224             continue;
1225         }
1226 
1227         if (!stricmp(s0,"By_From"))
1228         {
1229             s1 = strtok(NULL,"\t \r\n");
1230             if (s1 == NULL) print_err(buff,i);
1231             config->by_from = atoi(s1);
1232             continue;
1233         }
1234 
1235         if (!stricmp(s0,"By_To"))
1236         {
1237             s1 = strtok(NULL,"\t \r\n");
1238             if (s1 == NULL) print_err(buff,i);
1239             config->by_to = atoi(s1);
1240             continue;
1241         }
1242 
1243         if (!stricmp(s0,"By_FromTo"))
1244         {
1245             s1 = strtok(NULL,"\t \r\n");
1246             if (s1 == NULL) print_err(buff,i);
1247             config->by_from_to = atoi(s1);
1248             continue;
1249         }
1250 
1251         if (!stricmp(s0,"By_Total"))
1252         {
1253             s1 = strtok(NULL,"\t \r\n");
1254             if (s1 == NULL) print_err(buff,i);
1255             config->by_total = atoi(s1);
1256             continue;
1257         }
1258 
1259         if (!stricmp(s0,"By_Size"))
1260         {
1261             s1 = strtok(NULL,"\t \r\n");
1262             if (s1 == NULL) print_err(buff,i);
1263             config->by_size = atoi(s1);
1264             continue;
1265         }
1266 
1267         if (!stricmp(s0,"By_QPercent"))
1268         {
1269             s1 = strtok(NULL,"\t \r\n");
1270             if (s1 == NULL) print_err(buff,i);
1271             config->by_qpercent = atoi(s1);
1272             continue;
1273         }
1274 
1275         if (!stricmp(s0,"Subj_By_Total"))
1276         {
1277             s1 = strtok(NULL,"\t \r\n");
1278             if (s1 == NULL) print_err(buff,i);
1279             config->by_subj = atoi(s1);
1280             continue;
1281         }
1282 
1283         if (!stricmp(s0,"Stat_Period"))
1284         {
1285             s1 = strtok(NULL,"\t \r\n");
1286             if (s1 == NULL) print_err(buff,i);
1287             if (*s1 == 'm')
1288             {
1289                 s1++;
1290                 config->days_of_stat = atoi(s1);
1291                 if (!config->days_of_stat) print_err(buff,i);
1292                 if (config->days_of_stat > 1000) print_err(buff,i);
1293 
1294                 md = 0;
1295                 n = t.tm_mon-1;
1296 
1297                 for (j=1; j<config->days_of_stat; j++)
1298                 {
1299                     md += days_in_months[n];
1300                     if (!n) n = 11; else n--;
1301                 }
1302 
1303                 config->days_of_stat = md + (t.tm_mday - 1);
1304 
1305             } else
1306 
1307                 if (*s1 == 'w')
1308                 {
1309                     s1++;
1310                     config->days_of_stat = atoi(s1);
1311                     if (!config->days_of_stat) print_err(buff,i);
1312                     if (config->days_of_stat > 1000) print_err(buff,i);
1313                     config->days_of_stat = ( (config->days_of_stat-1) * 7 ) + (wd - 1);
1314                 } else
1315 
1316                 {
1317                     config->days_of_stat = atoi(s1);
1318                     if (!config->days_of_stat) print_err(buff,i);
1319                     if (config->days_of_stat > 32768) print_err(buff,i);
1320 
1321                 }
1322 
1323             continue;
1324         }
1325 
1326         if (!stricmp(s0,"Area"))
1327         {
1328             config->areas = srealloc(config->areas, sizeof(s_area)*(config->areas_count+1));
1329 
1330             s1 = strtok(NULL,"\t \r\n");
1331             if (s1 == NULL) print_err(buff,i);
1332 
1333             config->areas[config->areas_count].name = (char *) smalloc(strlen(s1)+1);
1334             strcpy(config->areas[config->areas_count].name,s1);
1335 
1336             s2 = strtok(NULL,"\t \r\n");
1337             if (s2 == NULL) print_err(buff,i);
1338 
1339             config->areas[config->areas_count].type = 0;
1340 
1341             if (!stricmp(s2,"msg")) config->areas[config->areas_count].type = 1; else
1342                 if (!stricmp(s2,"squish")) config->areas[config->areas_count].type = 2; else
1343                     if (!stricmp(s2,"jam")) config->areas[config->areas_count].type = 3;
1344 
1345             if (!config->areas[config->areas_count].type) print_err(buff,i);
1346 
1347 
1348             s3 = strtok(NULL,"\t \r\n");
1349             if (s3 == NULL) print_err(buff,i);
1350 
1351             config->areas[config->areas_count].path = (char *) smalloc(strlen(s3)+1);
1352             strcpy(config->areas[config->areas_count].path,s3);
1353 
1354             s4 = strtok(NULL,"\t \r\n");
1355             if (s4 == NULL) print_err(buff,i);
1356 
1357             config->areas[config->areas_count].out_file = (char *) smalloc(strlen(s4)+1);
1358             strcpy(config->areas[config->areas_count].out_file,s4);
1359 
1360             config->areas_count++;
1361 
1362             continue;
1363         }
1364 
1365         if (!stricmp(s0,"Subj_By_Total"))
1366         {
1367             s1 = strtok(NULL,"\t \r\n");
1368             if (s1 == NULL) print_err(buff,i);
1369             config->by_subj = atoi(s1);
1370             continue;
1371         }
1372 
1373         if (!stricmp(s0,"Make_Pkt"))
1374         {
1375             config->make_pkt = 1;
1376             continue;
1377         }
1378 
1379         if (!stricmp(s0,"Pkt_Size"))
1380         {
1381             s1 = strtok(NULL,"\t \r\n");
1382             if (s1 == NULL) print_err(buff,i);
1383             config->pkt_size = atoi(s1);
1384             if (!config->pkt_size) print_err(buff,i);
1385             if (config->pkt_size > 65536) print_err(buff,i);
1386             continue;
1387         }
1388 
1389         if (!stricmp(s0,"Pkt_Inbound"))
1390         {
1391             s1 = strtok(NULL,"\t \r\n");
1392             if (s1 == NULL) print_err(buff,i);
1393             config->pkt_inbound = smalloc(strlen(s1)+2);
1394             strcpy(config->pkt_inbound,s1);
1395             if (config->pkt_inbound[strlen(config->pkt_inbound)-1] != '\\')
1396                 strcat(config->pkt_inbound,"\\");
1397             continue;
1398         }
1399 
1400         if (!stricmp(s0,"Pkt_FromName"))
1401         {
1402             s1 = strtok(NULL,"\0");
1403             if (s1 == NULL) print_err(buff,i);
1404             while(*s1 && (*s1 == ' ' || *s1 == '\t')) s1++;
1405             j = strlen(s1)-1;
1406             while(j && (s1[j] == ' ' || s1[j] == '\t'))
1407             {
1408                 s1[j] = '\0'; j--;
1409             }
1410             if (!*s1) print_err(buff,i);
1411 
1412             config->pkt_from = smalloc(strlen(s1)+1);
1413             strcpy(config->pkt_from,s1);
1414 
1415             continue;
1416         }
1417 
1418         if (!stricmp(s0,"Pkt_ToName"))
1419         {
1420             s1 = strtok(NULL,"\0");
1421             if (s1 == NULL) print_err(buff,i);
1422             while(*s1 && (*s1 == ' ' || *s1 == '\t')) s1++;
1423             j = strlen(s1)-1;
1424             while(j && (s1[j] == ' ' || s1[j] == '\t'))
1425             {
1426                 s1[j] = '\0'; j--;
1427             }
1428             if (!*s1) print_err(buff,i);
1429 
1430             config->pkt_to = smalloc(strlen(s1)+1);
1431             strcpy(config->pkt_to,s1);
1432 
1433             continue;
1434         }
1435 
1436         if (!stricmp(s0,"Pkt_Subj"))
1437         {
1438             s1 = strtok(NULL,"\0");
1439             if (s1 == NULL) print_err(buff,i);
1440             while(*s1 && (*s1 == ' ' || *s1 == '\t')) s1++;
1441             j = strlen(s1)-1;
1442             while(j && (s1[j] == ' ' || s1[j] == '\t'))
1443             {
1444                 s1[j] = '\0'; j--;
1445             }
1446             if (!*s1) print_err(buff,i);
1447 
1448             config->pkt_subj = smalloc(strlen(s1)+1);
1449             strcpy(config->pkt_subj,s1);
1450 
1451             continue;
1452         }
1453 
1454         if (!stricmp(s0,"Pkt_Tearline"))
1455         {
1456           s1 = strtok(NULL,"\0");
1457           if (s1 == NULL) print_err(buff,i);
1458           while(*s1 && (*s1 == ' ' || *s1 == '\t')) s1++;
1459           j = strlen(s1)-1;
1460           while(j && (s1[j] == ' ' || s1[j] == '\t'))
1461           {
1462             s1[j] = '\0'; j--;
1463           }
1464           if (!*s1) print_err(buff,i);
1465 
1466           config->pkt_tearline = smalloc(strlen(s1)+1);
1467           strcpy(config->pkt_tearline,s1);
1468 
1469           continue;
1470         }
1471 
1472         if (!stricmp(s0,"Pkt_Origin"))
1473         {
1474             s1 = strtok(NULL,"\0");
1475             if (s1 == NULL) print_err(buff,i);
1476             while(*s1 && (*s1 == ' ' || *s1 == '\t')) s1++;
1477             j = strlen(s1)-1;
1478             while(j && (s1[j] == ' ' || s1[j] == '\t'))
1479             {
1480                 s1[j] = '\0'; j--;
1481             }
1482             if (!*s1) print_err(buff,i);
1483 
1484             config->pkt_origin = smalloc(strlen(s1)+1);
1485             strcpy(config->pkt_origin,s1);
1486 
1487             continue;
1488         }
1489 
1490         if (!stricmp(s0,"Pkt_Password"))
1491         {
1492             s1 = strtok(NULL,"\0");
1493             if (s1 == NULL) print_err(buff,i);
1494             while(*s1 && (*s1 == ' ' || *s1 == '\t')) s1++;
1495             j = strlen(s1)-1;
1496             while(j && (s1[j] == ' ' || s1[j] == '\t'))
1497             {
1498                 s1[j] = '\0'; j--;
1499             }
1500             if (!*s1) print_err(buff,i);
1501 
1502             strncpy(config->pkt_password,s1,8);
1503 
1504             continue;
1505         }
1506 
1507         if (!stricmp(s0,"Pkt_OrigAddress"))
1508         {
1509             s1 = strtok(NULL,"\t \r\n");
1510             if (s1 == NULL) print_err(buff,i);
1511 
1512             if (!ScanNetAddr(&config->pkt_orig_addr, s1)) print_err(buff,i);
1513 
1514             continue;
1515         }
1516 
1517         if (!stricmp(s0,"Pkt_DestAddress"))
1518         {
1519             s1 = strtok(NULL,"\t \r\n");
1520             if (s1 == NULL) print_err(buff,i);
1521 
1522             if (!ScanNetAddr(&config->pkt_dest_addr, s1)) print_err(buff,i);
1523 
1524             continue;
1525         }
1526 
1527         fprintf(stderr,"Unknown keyword: \"%s\"\n",s0);
1528 
1529     } /* while */
1530 
1531     fclose(fcfg);
1532 
1533     free(buff);
1534 
1535     return config;
1536 
1537 }
1538 
free_items()1539 void free_items()
1540 {
1541     unsigned long i;
1542 
1543     for (i = 0; i < gd_count; i++) nfree(global_data[i].name);
1544     nfree(global_data);
1545 
1546     if (main_config->by_from)
1547     {
1548         for (i = 0; i < fd_count; i++) nfree(from_data[i].name);
1549         nfree (from_data);
1550     }
1551 
1552     if (main_config->by_to)
1553     {
1554         for (i = 0; i < td_count; i++) nfree(to_data[i].name);
1555         nfree (to_data);
1556     }
1557 
1558     if (main_config->by_from_to)
1559     {
1560         for (i = 0; i < ftd_count; i++) nfree(from_to_data[i].name);
1561         nfree (from_to_data);
1562     }
1563 
1564     if (main_config->by_subj)
1565     {
1566         for (i = 0; i < sd_count; i++) nfree(subj_data[i].name);
1567         nfree (subj_data);
1568     }
1569 
1570     nfree(date_data);
1571 
1572     if (main_config->by_time) nfree(time_data);
1573 
1574     if (main_config->by_size)
1575     {
1576         for (i = 0; i < szd_count; i++) nfree(size_data[i].name);
1577         nfree (size_data);
1578     }
1579 
1580 }
1581 
free_config()1582 void free_config()
1583 {
1584     unsigned long i;
1585 
1586     nfree(main_config->pkt_from);
1587     nfree(main_config->pkt_to);
1588     nfree(main_config->pkt_subj);
1589     nfree(main_config->pkt_origin);
1590     nfree(main_config->pkt_inbound);
1591     nfree(main_config->pkt_tearline);
1592 
1593     for (i = 0; i < main_config->areas_count; i++)
1594     {
1595         nfree(main_config->areas[i].name);
1596         nfree(main_config->areas[i].path);
1597         nfree(main_config->areas[i].out_file);
1598     }
1599 
1600     nfree(main_config->areas);
1601     nfree(main_config);
1602 
1603 }
1604 
print_write_err()1605 void print_write_err()
1606 {
1607     fprintf(stderr,"Cannot write to pkt\n\n");
1608     exit(2);
1609 }
1610 
1611 
open_pkt()1612 int open_pkt()
1613 {
1614     PKT_hdr ph;
1615     time_t tt = time(NULL);
1616     struct tm t;
1617     unsigned int i;
1618     char packet_name[1024];
1619 
1620     t = *localtime(&tt);
1621 
1622     global_msgid++;
1623 
1624     sprintf(packet_name,"%s%08lx.pkt",main_config->pkt_inbound,(long)global_msgid);
1625 
1626     if ((out_pkt = fopen(packet_name,"wb")) == NULL)
1627     {
1628         fprintf(stderr,"Cannot open file: \"%s\" for write\n\n",packet_name);
1629         exit(2);
1630     }
1631 
1632     ph.origNode = main_config->pkt_orig_addr.node;
1633     ph.destNode = main_config->pkt_dest_addr.node;
1634     ph.year = t.tm_year+1900;
1635     ph.month = t.tm_mon;
1636     ph.day = t.tm_mday;
1637     ph.hour = t.tm_hour;
1638     ph.minute = t.tm_min;
1639     ph.second = t.tm_sec;
1640     ph.baud = 0;
1641     ph.packettype = 2;
1642     ph.origNet = main_config->pkt_orig_addr.net;
1643     ph.destNet = main_config->pkt_dest_addr.net;
1644     ph.prodcode = 254;
1645     ph.serialno = 1;
1646     for (i=0; i<8; i++) ph.password[i] = main_config->pkt_password[i];
1647     ph.origZone = main_config->pkt_orig_addr.zone;
1648     ph.destZone = main_config->pkt_dest_addr.zone;
1649     ph.auxNet = ph.origNet;
1650     ph.CapValid = 256;
1651     ph.prodcode2 = 0;
1652     ph.serialno2 = 6;
1653     ph.CapWord = 1;
1654     ph.origZone2 = ph.origZone;
1655     ph.destZone2 = ph.destZone;
1656     ph.origPoint = main_config->pkt_orig_addr.point;
1657     ph.destPoint = main_config->pkt_dest_addr.point;
1658     ph.fill_36[0] = 'X';
1659     ph.fill_36[1] = 'P';
1660     ph.fill_36[2] = 'K';
1661     ph.fill_36[3] = 'T';
1662 
1663     fwrite(&ph,sizeof(ph),1,out_pkt);
1664     if (ferror(out_pkt)) print_write_err();
1665 
1666     fwrite("\0\0",2,1,out_pkt);
1667     if (ferror(out_pkt)) print_write_err();
1668 
1669     return 0;
1670 }
1671 
write_msg_hdr(int n)1672 int write_msg_hdr(int n)
1673 {
1674     MSG_hdr mh;
1675     time_t tt = time(NULL);
1676     struct tm t;
1677     char yr[3],yy[10];
1678     char s[255];
1679 
1680     t = *localtime(&tt);
1681 
1682     mh.origNode = main_config->pkt_orig_addr.node;
1683     mh.destNode = main_config->pkt_dest_addr.node;
1684     mh.origNet = main_config->pkt_orig_addr.net;
1685     mh.destNet = main_config->pkt_dest_addr.net;
1686     mh.AttributeWord = 0;
1687     mh.cost = 0;
1688 
1689     sprintf(yy,"%04d",t.tm_year+1900);
1690 
1691     if (strlen(yy) == 4)
1692     {
1693         yr[0] = yy[2];
1694         yr[1] = yy[3];
1695         yr[2] = '\0';
1696 
1697     } else {
1698 
1699         yr[0] = '0';
1700         yr[1] = '0';
1701         yr[2] = '\0';
1702 
1703     }
1704 
1705     sprintf(mh.DateTime,"%02d %s %s  %02d:%02d:%02u",t.tm_mday,
1706             months_ab[t.tm_mon],yr,t.tm_hour,t.tm_min,isecs);
1707 
1708     isecs++;
1709     if (isecs > 59) isecs = 0; /* pseudo secs (anti dupes in squish) */
1710 
1711     fseek(out_pkt,-2L,SEEK_END);
1712 
1713     fwrite("\x02\0",2,1,out_pkt);
1714     if (ferror(out_pkt)) print_write_err();
1715 
1716     fwrite(&mh,sizeof(mh),1,out_pkt);
1717     if (ferror(out_pkt)) print_write_err();
1718 
1719     fwrite(main_config->pkt_to,strlen(main_config->pkt_to)+1,1,out_pkt);
1720     if (ferror(out_pkt)) print_write_err();
1721 
1722     fwrite(main_config->pkt_from,strlen(main_config->pkt_from)+1,1,out_pkt);
1723     if (ferror(out_pkt)) print_write_err();
1724 
1725     fwrite(main_config->pkt_subj,strlen(main_config->pkt_subj)+1,1,out_pkt);
1726     if (ferror(out_pkt)) print_write_err();
1727 
1728     fwrite("AREA:",5,1,out_pkt);
1729     if (ferror(out_pkt)) print_write_err();
1730 
1731     fwrite(main_config->areas[n].name,strlen(main_config->areas[n].name),1,out_pkt);
1732     if (ferror(out_pkt)) print_write_err();
1733 
1734     global_msgid++;
1735 
1736     if (main_config->pkt_orig_addr.point)
1737     {
1738         sprintf(s,"\r\x01MSGID: %d:%d/%d.%d %08lx",
1739                 main_config->pkt_orig_addr.zone,main_config->pkt_orig_addr.net,
1740                 main_config->pkt_orig_addr.node,main_config->pkt_orig_addr.point,
1741                 (long)global_msgid);
1742 
1743     } else {
1744 
1745         sprintf(s,"\r\x01MSGID: %d:%d/%d %08lx",
1746                 main_config->pkt_orig_addr.zone,main_config->pkt_orig_addr.net,
1747                 main_config->pkt_orig_addr.node,(long)global_msgid);
1748 
1749     }
1750 
1751     fwrite(s,strlen(s),1,out_pkt);
1752     if (ferror(out_pkt)) print_write_err();
1753 
1754     fwrite("\r\x01""FLAGS NPD\r",12,1,out_pkt);
1755     if (ferror(out_pkt)) print_write_err();
1756 
1757     if (strnicmp(main_config->pkt_tearline, versionStr, strlen(versionStr)))
1758     {
1759         sprintf(s,"\x01PID: %s\r",versionStr);
1760         fwrite(s,strlen(s),1,out_pkt);
1761         if (ferror(out_pkt)) print_write_err();
1762     }
1763 
1764     return 0;
1765 }
1766 
write_buff_to_pkt(char * buff)1767 int write_buff_to_pkt(char *buff)
1768 {
1769     fwrite (buff, strlen(buff), 1, out_pkt);
1770     if (ferror(out_pkt)) print_write_err();
1771 
1772     return 0;
1773 }
1774 
end_msg(unsigned char e)1775 int end_msg(unsigned char e)
1776 {
1777     char s[255];
1778 
1779     if (e)
1780     {
1781         sprintf(s," -== Continued in next message ==-\r");
1782 
1783         fwrite (s, strlen(s), 1, out_pkt);
1784         if (ferror(out_pkt)) print_write_err();
1785     }
1786 
1787     sprintf(s,"\r\r--- %s",main_config->pkt_tearline);
1788 
1789     fwrite (s, strlen(s), 1, out_pkt);
1790     if (ferror(out_pkt)) print_write_err();
1791 
1792     if (main_config->pkt_orig_addr.point)
1793     {
1794         sprintf(s,"\r * Origin: %s (%d:%d/%d.%d)",main_config->pkt_origin,
1795                 main_config->pkt_orig_addr.zone,main_config->pkt_orig_addr.net,
1796                 main_config->pkt_orig_addr.node,main_config->pkt_orig_addr.point);
1797 
1798     } else {
1799 
1800         sprintf(s,"\r * Origin: %s (%d:%d/%d)",main_config->pkt_origin,
1801                 main_config->pkt_orig_addr.zone,main_config->pkt_orig_addr.net,
1802                 main_config->pkt_orig_addr.node);
1803     }
1804 
1805     fwrite (s, strlen(s), 1, out_pkt);
1806     if (ferror(out_pkt)) print_write_err();
1807 
1808     sprintf(s,"\rSEEN-BY: %d/%d",main_config->pkt_orig_addr.net,
1809             main_config->pkt_orig_addr.node);
1810 
1811     fwrite (s, strlen(s), 1, out_pkt);
1812     if (ferror(out_pkt)) print_write_err();
1813 
1814     sprintf(s,"\r\x01PATH: %d/%d\r",main_config->pkt_orig_addr.net,
1815             main_config->pkt_orig_addr.node);
1816 
1817     fwrite (s, strlen(s), 1, out_pkt);
1818     if (ferror(out_pkt)) print_write_err();
1819 
1820     fwrite ("\0\0\0", 3, 1, out_pkt);
1821     if (ferror(out_pkt)) print_write_err();
1822 
1823     return 0;
1824 }
1825 
main(int argc,char * argv[])1826 int main(int argc,char *argv[])
1827 {
1828     unsigned long i, msg_size = 0;
1829     int j;
1830     char ibuff[256];
1831 
1832     global_msgid = time(NULL);
1833     global_msgid %= 0xffffffff;
1834 
1835     versionStr = GenVersionStr( "areastat", VER_MAJOR, VER_MINOR, VER_PATCH,
1836                                VER_BRANCH, cvs_date );
1837 
1838     printf("%s\n", versionStr);
1839 
1840     if (argc > 2)
1841     {
1842         fprintf(stderr,"Too many actual parameters\n\n");
1843         argc = 0;
1844     }
1845 
1846     if (argc < 2)
1847     {
1848         fprintf(stderr,"\nUsage:\tareastat <config>\n");
1849         exit(1);
1850     }
1851 
1852     main_config = read_cfg(argv[1]);
1853 
1854     if (main_config->pkt_from == NULL) main_config->pkt_from = sstrdup(versionStr);
1855     if (main_config->pkt_to == NULL) main_config->pkt_to = strdup("All");
1856     if (main_config->pkt_subj == NULL) main_config->pkt_subj = strdup("Statistics");
1857     if (main_config->pkt_origin == NULL) main_config->pkt_origin = strdup("\0");
1858     if (main_config->pkt_inbound == NULL) main_config->pkt_inbound = strdup("\0");
1859     if (main_config->pkt_tearline == NULL) main_config->pkt_tearline = sstrdup(versionStr);
1860 
1861     if (strlen(main_config->pkt_inbound) > 256)
1862     {
1863         fprintf(stderr,"Inbound path too long\n\n");
1864         exit(2);
1865     }
1866 
1867     if (strlen(main_config->pkt_tearline) > 75)
1868     {
1869       fprintf(stderr,"Tearline too long\n\n");
1870       exit(2);
1871     }
1872 
1873     if (strlen(main_config->pkt_origin) > 50)
1874     {
1875         fprintf(stderr,"Origin too long\n\n");
1876         exit(2);
1877     }
1878 
1879     for (i = 0; i < main_config->areas_count; i++)
1880     {
1881 
1882         if ((current_std = fopen(main_config->areas[i].out_file,"wb")) == NULL)
1883         {
1884             fprintf(stderr,"Cannot open file: \"%s\"\n\n",main_config->areas[i].out_file);
1885             exit(2);
1886         }
1887 
1888         reading_base(i);
1889 
1890         print_summary_statistics(i);
1891         if (main_config->by_name) print_statistics_by_name();
1892         if (main_config->by_from) print_statistics_by_from();
1893         if (main_config->by_to) print_statistics_by_to();
1894         if (main_config->by_from_to) print_statistics_by_from_to();
1895         if (main_config->by_total) print_statistics_by_total();
1896         if (main_config->by_size) print_statistics_by_size();
1897         if (main_config->by_qpercent) print_statistics_by_qpercent();
1898         if (main_config->by_subj) print_statistics_by_subj();
1899         if (main_config->by_date) print_statistics_by_date();
1900         if (main_config->by_wday) print_statistics_by_wdays();
1901         if (main_config->by_time) print_statistics_by_time();
1902 
1903         fprintf(current_std,"\n Statistics created by %s",versionStr);
1904         fprintf(current_std,"\n Written by Dmitry Rusov (C) 2000, The Husky project (C) 2004\n");
1905 
1906         fclose(current_std);
1907 
1908         if (!main_config->make_pkt)
1909         {
1910             free_items();
1911             continue;
1912         }
1913 
1914         open_pkt();
1915 
1916         if ((current_std = fopen(main_config->areas[i].out_file,"rb")) == NULL)
1917         {
1918             fprintf(stderr,"Cannot open file: \"%s\"\n\n",main_config->areas[i].out_file);
1919             exit(2);
1920         }
1921 
1922         isecs = 0;
1923 
1924         write_msg_hdr(i);
1925 
1926         if ((current_std = fopen(main_config->areas[i].out_file,"rb")) == NULL)
1927         {
1928             fprintf(stderr,"Cannot open file: \"%s\"\n\n",main_config->areas[i].out_file);
1929             exit(2);
1930         }
1931 
1932         msg_size = 0;
1933 
1934         while (fgets(ibuff,255,current_std))
1935         {
1936             if (ibuff != NULL && * ibuff)
1937             {
1938                 if (ibuff[0] == ' ' && ibuff[1] == '-' && ibuff[2] == '-'
1939                     && ibuff[3] == '-' && msg_size > main_config->pkt_size)
1940                 {
1941                     end_msg(1);
1942                     write_msg_hdr(i);
1943                     msg_size = 0;
1944                 }
1945 
1946                 j = strlen(ibuff)-1;
1947                 if (j >= 0 && ibuff[j] == '\n') ibuff[j] = '\r';
1948 
1949                 write_buff_to_pkt(ibuff);
1950                 msg_size += strlen(ibuff);
1951             }
1952         }
1953         end_msg(0);
1954         fclose(current_std);
1955         fclose(out_pkt);
1956         free_items();
1957 
1958     } /* for */
1959     free_config();
1960     fprintf(stderr,"\n\nDone!\n");
1961     return 0;
1962 }
1963