home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / MAXLG132.ZIP / MAXLOG.C < prev    next >
C/C++ Source or Header  |  1992-06-10  |  35KB  |  1,054 lines

  1. /***************************************************************************\
  2.      MAXLOG.C
  3.  
  4.    Read Maximus callers log and store entries of interest in a data file.
  5.  
  6.    Purge the data fileback to a specified number of days.
  7.  
  8.    Written by: Pete Norloff
  9.                1/10/91
  10.  
  11.    Modified 3/2/91 to include Binkley log files.
  12.  
  13. \***************************************************************************/
  14. /* Include Files:                                                          */
  15. #define INCL_DOSFILEMGR
  16. #define INCL_DOSDATETIME
  17. #include <os2.h>
  18.  
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <process.h>
  22. #include <stdlib.h>
  23.  
  24. /***************************************************************************/
  25. /* Function Prototypes:                                                    */
  26. VOID  main(SHORT argc, CHAR *argv[]);
  27. VOID  get_date_time(CHAR *,CHAR *, LONG *, LONG *);
  28. VOID  read_configuration(VOID);
  29. SHORT extract_file_name(CHAR *,CHAR *);
  30. VOID  capture_new_data(VOID);
  31. VOID  produce_bulletins(VOID);
  32. VOID  purge_data_file(VOID);
  33. VOID  sort_dl_list(VOID);
  34. VOID  add_dl_to_list(CHAR *, LONG);
  35. VOID  write_top_dl_bulletin(VOID);
  36. VOID  write_system_usage_bulletin(VOID);
  37. VOID  count_usage_days(SHORT, SHORT *);
  38. VOID  add_call_to_graph(struct lgoff *);
  39. VOID  purge_logfile(CHAR *);
  40.  
  41. /***************************************************************************/
  42. #define MAX_DAYS       365
  43. #define MAX_LOGFILES     4
  44. #define LOGOFF           1
  45. #define DOWNLOAD         2
  46. #define FILE_REQ         3
  47. #define MAIL_SESSION_END 4
  48. #define MAX_USAGELINES 100
  49. #define MAX_DL_FILES  6000
  50.  
  51. /***************************************************************************/
  52. /* Data  Structures:                                                       */
  53. typedef struct xfr
  54. {
  55.    LONG  date;
  56.    LONG  time;
  57.    SHORT node;
  58.    LONG  filesize;
  59.    SHORT name_length;
  60. };
  61. struct xfr xfer;
  62.  
  63. typedef struct lgoff
  64. {
  65.    LONG  date;
  66.    LONG  time;
  67.    SHORT node;
  68.    LONG  duration;
  69. };
  70. struct lgoff logoff;
  71.  
  72. typedef struct dloads
  73. {
  74.    char  *filename;
  75.    SHORT dl_count;
  76.    LONG  dl_bytes;
  77. };
  78. struct dloads downloads[MAX_DL_FILES];
  79.  
  80. typedef struct usage
  81. {
  82.    USHORT n_calls;
  83.    float  hours;
  84. };
  85. static struct usage system_used[MAX_LOGFILES][366];
  86.  
  87. /***************************************************************************/
  88. /* External Variables:                                                     */
  89. SHORT n_logfiles = 0;
  90. CHAR  logfile_name[MAX_LOGFILES][256];
  91. SHORT n_binkfiles = 0;
  92. CHAR  binkfile_name[MAX_LOGFILES][256];
  93. CHAR  outbound_dir[256];
  94. SHORT dl_struct_index = 0;
  95. CHAR  bbs_name[81];
  96. SHORT summary_days;
  97. SHORT archive = FALSE;
  98. SHORT save_data = FALSE;
  99. SHORT log = FALSE;
  100. SHORT UsageLines = 10;
  101. static LONG usage_by_hour[MAX_LOGFILES][24];
  102. DATETIME datetime;
  103. ULONG  total_bytes_dl = 0;
  104.  
  105. /***************************************************************************/
  106. VOID main(SHORT argc, CHAR *argv[])
  107. {
  108.  
  109.    printf("Maxlog v1.32 - create Maximus system usage bulletins.\n");
  110.    printf("written by Pete Norloff, 1:109/347@fidonet\n\n");
  111.  
  112. /* Read in the configuration file.                                         */
  113.    read_configuration();
  114.  
  115.    if ((argc <= 1) || ((argc > 1) && (strcmpi(argv[1],"skip") != 0)))
  116.    {
  117. /*    Capture new data from the log files.                                 */
  118.       printf("Capturing new data from log file.\n");
  119.       capture_new_data();
  120.  
  121. /*    Purge data file, saving the number of days listed in the .Cfg file.  */
  122.       printf("Purging old data from file.\n");
  123.       purge_data_file();
  124.    }
  125.    else
  126.    {
  127.       printf("Not capturing new data or purging.\n");
  128.    }
  129.  
  130. /* Create the bulletins from the data.                                     */
  131.    printf("Processing Maxlog.Dat.\n");
  132.    produce_bulletins();
  133.  
  134.    printf("Done.\n");
  135. }
  136. /***************************************************************************/
  137. VOID read_configuration()
  138. {
  139.    FILE  *config;
  140.    SHORT i;
  141.    CHAR  dummy[81];
  142.    CHAR  keyword[40];
  143.  
  144. /* Get the current dte and time.  Several functions use this info.         */
  145.    DosGetDateTime(&datetime);
  146.  
  147.    if ((config=fopen("Maxlog.Cfg","r")) == NULL)
  148.    {
  149.       printf("Error opening Maxlog.Cfg\n");
  150.       exit(1);
  151.    }
  152.  
  153.    while (feof(config) == 0)
  154.    {
  155.       fscanf(config,"%s",keyword);
  156.  
  157.       if (strcmpi(keyword,"Name") == 0)
  158.       {
  159.          fgets(bbs_name,80,config);
  160. /*       Trim off the new line character from the bbs_name.                */
  161.          bbs_name[strlen(bbs_name)-1] = '\0';
  162.       }
  163.       else if (strcmpi(keyword,"NFiles") == 0)
  164.       {
  165.          fscanf(config,"%i",&n_logfiles);
  166.          if ((n_logfiles < 0) || (n_logfiles > MAX_LOGFILES))
  167.          {
  168.             printf("Invalid number of logfiles defined\n");
  169.             exit(1);
  170.          }
  171.       }
  172.       else if (strcmpi(keyword,"FileNames") == 0)
  173.       {
  174. /*       Read in the log file names.                                        */
  175.          for (i=0; i<n_logfiles; i++)
  176.          {
  177.             fscanf(config,"%s",logfile_name[i]);
  178.          }
  179.       }
  180.       else if (strcmpi(keyword,"NBinkFiles") == 0)
  181.       {
  182.          fscanf(config,"%i",&n_binkfiles);
  183.          if ((n_binkfiles < 0) || (n_binkfiles > MAX_LOGFILES))
  184.          {
  185.             printf("Invalid number of binkfiles defined\n");
  186.             exit(1);
  187.          }
  188.       }
  189.       else if (strcmpi(keyword,"Outbound") == 0)
  190.       {
  191.          fscanf(config,"%s",outbound_dir);
  192.       }
  193.       else if (strcmpi(keyword,"BinkFileNames") == 0)
  194.       {
  195. /*       Read in the log file names.                                        */
  196.          for (i=0; i<n_binkfiles; i++)
  197.          {
  198.             fscanf(config,"%s",binkfile_name[i]);
  199.          }
  200.       }
  201.       else if (keyword[0] == ';')
  202.       {
  203. /*       Comment line, read and discard line.                               */
  204.          fgets(dummy,80,config);
  205.       }
  206.       else if (strcmpi(keyword,"Days") == 0)
  207.       {
  208.          fscanf(config,"%i",&summary_days);
  209.          if ((summary_days <= 0) || (summary_days > MAX_DAYS))
  210.          {
  211.             printf("Invalid number of days defined\n");
  212.             exit(1);
  213.          }
  214.       }
  215.       else if (strcmpi(keyword,"Archive") == 0)
  216.       {
  217. /*       The presence of the keyword "archive" in the configuration file    */
  218. /*       enables the archive option which appends the log file to a file    */
  219. /*       named <filename>.sav.                                              */
  220.          archive = TRUE;
  221.       }
  222.       else if (strcmpi(keyword,"SaveData") == 0)
  223.       {
  224. /*       The presence of the keyword "SaveData" in the configuration file   */
  225. /*       enables the save data option which appends the purged entries      */
  226. /*       from the Maxlog.Dat to a file called Maxlog.Rmv.                   */
  227.          save_data = TRUE;
  228.       }
  229.       else if (strcmpi(keyword,"Log") == 0)
  230.       {
  231. /*       The presence of the keyword "Log" in the configuration file        */
  232. /*       enables the logging of activity.  This writes two lines per day to */
  233. /*       a file called Maxlog.Log, containing the number of events added    */
  234. /*       and purged each day.                                               */
  235.          log = TRUE;
  236.       }
  237.       else if (strcmpi(keyword,"UsageLines") == 0)
  238.       {
  239.          fscanf(config,"%i",&UsageLines);
  240.          if ((UsageLines < 10) || (UsageLines > MAX_USAGELINES))
  241.          {
  242.             printf("Invalid number of days UsageLines\n");
  243.             exit(1);
  244.          }
  245.       }
  246.    }
  247.    fclose(config);
  248. }
  249. /***************************************************************************/
  250. VOID capture_new_data()
  251. {
  252.    FILE   *logfile,*event;
  253.    CHAR   text[81];
  254.    LONG   date,start_time,end_time,elapsed_time,dl_time;
  255.    static CHAR  date_string[7];
  256.    SHORT  dummy;
  257.    static CHAR bytes[15];
  258.    SHORT  i;
  259.    SHORT  event_number;
  260.    CHAR   filename[255];
  261.    CHAR   dummy_string[80],file_dir[255];
  262.    SHORT  online = FALSE;
  263.    SHORT  logoffs_added = 0;
  264.    SHORT  downloads_added = 0;
  265.    ULONG  bytes_dl_added = 0;
  266.    ULONG  seconds_added = 0;
  267.  
  268. /* Open the data file for append to save the records of interest.         */
  269.    if ((event=fopen("Maxlog.Dat","ab")) == NULL)
  270.    {
  271.       printf("Error opening Maxlog.Dat\n");
  272.       exit(1);
  273.    }
  274.  
  275. /* Loop over the number of log files specified in the configuration file. */
  276.    for (i=0; i<n_logfiles; i++)
  277.    {
  278. /*    Open the log file named in the configuration file.                  */
  279.       if ((logfile=fopen(logfile_name[i],"r+b")) == NULL)
  280.       {
  281.          printf("Error opening %s\n",logfile_name[i]);
  282.          continue;
  283.       }
  284.  
  285. /*    Read a line from the file.                                          */
  286.       while(fgets(text,80,logfile) != NULL)
  287.       {
  288. /*       Ignore strings less than 23 characters in length.                */
  289.          if (strlen(text) < 23) continue;
  290.  
  291. /*       For line entry "CPS", extract the number of bytes in the file.   */
  292.          if (strncmp(&text[23],"CPS,",3) == 0)
  293.          {
  294.             sscanf(&text[28],"%i %s",&dummy,bytes);
  295.          }
  296. /*       For line entry "DL", extract the file name.                        */
  297.          if (strncmp(&text[23],"DL,",2) == 0)
  298.          {
  299. /*          Check to see if the file sent was a mail packet.  If so, ignore */
  300. /*          so, ignore.                                                     */
  301.             sscanf(&text[23],"%s %s",dummy_string,file_dir);
  302.             if (strnicmp(".qw",&file_dir[strlen(file_dir)-4],3) != 0)
  303.             {
  304.                event_number = DOWNLOAD;
  305.                xfer.node = i+1;
  306.                get_date_time(text,date_string,&date,&dl_time);
  307.                xfer.date = date;
  308.                xfer.time = dl_time;
  309.                xfer.filesize = atol(&bytes[1]);
  310.                extract_file_name(filename,&text[28]);
  311.                xfer.name_length = strlen(filename) - 1;
  312.                filename[xfer.name_length-1] = '\0';
  313.                fwrite(&event_number,sizeof(SHORT),1,event);
  314.                fwrite(&xfer,sizeof(xfer),1,event);
  315.                fwrite(filename,xfer.name_length,1,event);
  316.                downloads_added++;
  317.                bytes_dl_added += xfer.filesize;
  318.             }
  319.          }
  320.          else if (strncmp(&text[23],"Begin,",6) == 0)
  321.          {
  322. /*          Pass string to get_date_time() to calculate int date and times*/
  323.             get_date_time(text,date_string,&date,&start_time);
  324.             online = TRUE;
  325.          }
  326.          else if (strncmp(&text[23],"End,",4) == 0)
  327.          {
  328.             if (online == TRUE)
  329.             {
  330. /*             Pass string to get_date_time() to calculate int date and times*/
  331.                get_date_time(text,date_string,&date,&end_time);
  332.                event_number = LOGOFF;
  333.                logoff.node = i+1;
  334.                logoff.date = date;
  335.                logoff.time = end_time;
  336.                elapsed_time = end_time - start_time;
  337.                if (elapsed_time < 0)
  338.                {
  339.                   elapsed_time = elapsed_time + 86400L;
  340.                }
  341.                logoff.duration = elapsed_time;
  342.                fwrite(&event_number,sizeof(SHORT),1,event);
  343.                fwrite(&logoff,sizeof(logoff),1,event);
  344.                online = FALSE;
  345.                logoffs_added++;
  346.                seconds_added += logoff.duration;
  347.             }
  348.          }
  349.       }
  350.       fclose(logfile);
  351.       purge_logfile(logfile_name[i]);
  352.    }
  353.  
  354. /* Loop over the Binkley log files specified in the configuration file.   */
  355.    for (i=0; i<n_binkfiles; i++)
  356.    {
  357. /*    Open the log file named in the configuration file.                  */
  358.       if ((logfile=fopen(binkfile_name[i],"r+b")) == NULL)
  359.       {
  360.          printf("Error opening %s\n",binkfile_name[i]);
  361.          continue;
  362.       }
  363.  
  364. /*    Read a line from the file.                                          */
  365.       while(fgets(text,80,logfile) != NULL)
  366.       {
  367. /*       Ignore strings less than 23 characters in length.                */
  368.          if (strlen(text) < 23) continue;
  369.  
  370. /*       For line entry "CPS", extract the number of bytes in the file.   */
  371.          if (strncmp(&text[23],"CPS,",3) == 0)
  372.          {
  373.             sscanf(&text[28],"%i %s",&dummy,bytes);
  374.          }
  375. /*       For line entry "Sent", extract the file name.                     */
  376.          if (strncmp(&text[23],"Sent,",4) == 0)
  377.          {
  378. /*          Check to see if the file sent was from the outbound area.  If  */
  379. /*          so, ignore.                                                    */
  380. /*          Also ignore *.rsp files .tic files, and QWK packets (*.qw?).   */
  381.             sscanf(&text[23],"%s %s",dummy_string,file_dir);
  382.             if ((strnicmp(outbound_dir,file_dir,strlen(outbound_dir)) != 0) &&
  383.                 (stricmp(".rsp",&file_dir[strlen(file_dir)-4]) != 0) &&
  384.                 (stricmp(".tic",&file_dir[strlen(file_dir)-4]) != 0))
  385.             {
  386.                event_number = FILE_REQ;
  387.                xfer.node = i+1;
  388.                get_date_time(text,date_string,&date,&dl_time);
  389.                xfer.date = date;
  390.                xfer.time = dl_time;
  391.                xfer.filesize = atol(&bytes[1]);
  392.                extract_file_name(filename,&text[33]);
  393.                xfer.name_length = strlen(filename) - 1;
  394.                filename[xfer.name_length-1] = '\0';
  395.                fwrite(&event_number,sizeof(SHORT),1,event);
  396.                fwrite(&xfer,sizeof(xfer),1,event);
  397.                fwrite(filename,xfer.name_length,1,event);
  398.                downloads_added++;
  399.                bytes_dl_added += xfer.filesize;
  400.             }
  401.          }
  402.          else if (strncmp(&text[23],"Remote,",6) == 0)
  403.          {
  404. /*          Pass string to get_date_time() to calculate int date and times*/
  405.             get_date_time(text,date_string,&date,&start_time);
  406.             online = TRUE;
  407.          }
  408.          else if (strncmp(&text[23],"End ",4) == 0)
  409.          {
  410.             if (online == TRUE)
  411.             {
  412. /*             Pass string to get_date_time() to calculate int date and times*/
  413.                get_date_time(text,date_string,&date,&end_time);
  414.                event_number = MAIL_SESSION_END;
  415.                logoff.node = i+1;
  416.                logoff.date = date;
  417.                logoff.time = end_time;
  418.                elapsed_time = end_time - start_time;
  419.                if (elapsed_time < 0)
  420.                {
  421.                   elapsed_time = elapsed_time + 86400L;
  422.                }
  423.                logoff.duration = elapsed_time;
  424.                fwrite(&event_number,sizeof(SHORT),1,event);
  425.                fwrite(&logoff,sizeof(logoff),1,event);
  426.                online = FALSE;
  427.                logoffs_added++;
  428.                seconds_added += logoff.duration;
  429.             }
  430.          }
  431.       }
  432.       fclose(logfile);
  433.       purge_logfile(binkfile_name[i]);
  434.    }
  435.    fclose(event);
  436.  
  437.    if (log == TRUE)
  438.    {
  439. /*    Log the number of additions to the log file.                         */
  440.       if ((logfile=fopen("Maxlog.Log","a")) == NULL)
  441.       {
  442.          printf("Error opening Maxlog.Log\n");
  443.          return;
  444.       }
  445.       fprintf(logfile,"%02i/%02i/%02i:  ",datetime.month,datetime.day,datetime.year);
  446.       fprintf(logfile,"calls add : %3i  Min: %5i  Xfers add : %4i  bytes: %7li\n",
  447.                        logoffs_added, (SHORT)(seconds_added/60),downloads_added, bytes_dl_added);
  448.       fclose(logfile);
  449.    }
  450. }
  451. /***************************************************************************/
  452. VOID purge_logfile(CHAR *filename)
  453. {
  454.    SHORT i;
  455.    CHAR  save_file[255];
  456.  
  457. /* If the flag variable "archive" is TRUE, append log file to save file.   */
  458.    if (archive == TRUE)
  459.    {
  460. /*    Create a save_file name which has the extention ".Sav".           */
  461.       strcpy(save_file,filename);
  462.       for (i=strlen(save_file); i>0; i--)
  463.       {
  464.          if (save_file[i] == '.')
  465.          {
  466.             strcpy(&save_file[i],".Sav");
  467.             break;
  468.          }
  469.       }
  470.  
  471. /*    Make sure that the save_file name was created.                    */
  472.       if (i == 0)
  473.       {
  474.          strcat(save_file,".Sav");
  475.       }
  476.  
  477.       if (DosCopy(filename,save_file,DCPY_APPEND,0) == 0)
  478.       {
  479.          DosDelete(filename,0);
  480.       }
  481.       printf("%s archived and deleted.\n",filename);
  482.    }
  483.    else
  484. /* Just delete the old log file.                                           */
  485.    {
  486.       DosDelete(filename,0);
  487.       printf("%s deleted.\n",filename);
  488.    }
  489. }
  490. /***************************************************************************/
  491. VOID purge_data_file()
  492. {
  493.    FILE  *old_file,*new_file,*save_file,*logfile;
  494.    SHORT i;
  495.    SHORT downloads_purged = 0;
  496.    SHORT logoffs_purged = 0;
  497.    ULONG bytes_dl_purged = 0;
  498.    ULONG seconds_purged = 0;
  499.    LONG  test_date,todays_date;
  500.    LONG  days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
  501.    SHORT event_number;
  502.    CHAR  filename[255];
  503.  
  504. /* Calculate today's date.                                                 */
  505.    todays_date = 0;
  506.    for (i=0; i< datetime.month-1; i++)
  507.    {
  508.       todays_date += days[i];
  509.    }
  510.    todays_date += datetime.day;
  511.  
  512. /* Copy the .Dat file to .Bak.                                             */
  513.    DosCopy("Maxlog.Dat","Maxlog.Bak",DCPY_EXISTING,0);
  514.  
  515.    if ((old_file=fopen("Maxlog.Bak","rb")) == NULL)
  516.    {
  517.       printf("Error opening Maxlog.Bak (purge)\n");
  518.       exit(1);
  519.    }
  520.    if ((new_file=fopen("Maxlog.Dat","wb")) == NULL)
  521.    {
  522.       printf("Error opening Maxlog.Dat (purge)\n");
  523.       exit(1);
  524.    }
  525.    if (save_data == TRUE)
  526.    {
  527.       if ((save_file=fopen("Maxlog.Rmv","ab")) == NULL)
  528.       {
  529.          printf("Error opening Maxlog.Rmv (purge)\n");
  530.          exit(1);
  531.       }
  532.    }
  533.  
  534.    while (feof(old_file) == 0)
  535.    {
  536.       fread(&event_number,sizeof(SHORT),1,old_file);
  537.       switch(event_number)
  538.       {
  539.          case DOWNLOAD:
  540.          case FILE_REQ:
  541.             if (fread(&xfer,sizeof(xfer),1,old_file) == 0) break;
  542.             fread(filename,xfer.name_length,1,old_file);
  543.             test_date = (365-todays_date+xfer.date-1) % 365;
  544.             if (test_date >= 365 - summary_days - 1)
  545.             {
  546.                fwrite(&event_number,sizeof(SHORT),1,new_file);
  547.                fwrite(&xfer,sizeof(xfer),1,new_file);
  548.                fwrite(filename,xfer.name_length,1,new_file);
  549.             }
  550.             else
  551.             {
  552.                if (save_data == TRUE)
  553.                {
  554.                   fwrite(&event_number,sizeof(SHORT),1,save_file);
  555.                   fwrite(&xfer,sizeof(xfer),1,save_file);
  556.                   fwrite(filename,xfer.name_length,1,save_file);
  557.                }
  558.                downloads_purged++;
  559.                bytes_dl_purged += xfer.filesize;
  560.             }
  561.             break;
  562.  
  563.          case LOGOFF:
  564.          case MAIL_SESSION_END:
  565.             if (fread(&logoff,sizeof(logoff),1,old_file) == 0) break;
  566.             test_date = (365-todays_date+logoff.date-1) % 365;
  567.             if (test_date >= 365 - summary_days - 1)
  568.             {
  569.                fwrite(&event_number,sizeof(SHORT),1,new_file);
  570.                fwrite(&logoff,sizeof(logoff),1,new_file);
  571.             }
  572.             else
  573.             {
  574.                if (save_data == TRUE)
  575.                {
  576.                   fwrite(&event_number,sizeof(SHORT),1,save_file);
  577.                   fwrite(&logoff,sizeof(logoff),1,save_file);
  578.                }
  579.                logoffs_purged++;
  580.                seconds_purged += logoff.duration;
  581.             }
  582.             break;
  583.  
  584.          default:
  585.             printf("UNKNOWN EVENT!!! (=%i) (bug)(purge)\n",event_number);
  586.             break;
  587.       }
  588.    }
  589.  
  590.    fclose(new_file);
  591.    fclose(old_file);
  592.    if (save_data == TRUE)
  593.    {
  594.       fclose(save_file);
  595.    }
  596.  
  597.    printf("\nDownloads Purged: %i\n",downloads_purged);
  598.    printf("  Logoffs Purged: %i\n\n",logoffs_purged);
  599.  
  600.    if (log == TRUE)
  601.    {
  602. /*    Log the number of purges to the log file.                            */
  603.       if ((logfile=fopen("Maxlog.Log","a")) == NULL)
  604.       {
  605.          printf("Error opening Maxlog.Log\n");
  606.          return;
  607.       }
  608.       fprintf(logfile,"%02i/%02i/%02i:  ",datetime.month,datetime.day,datetime.year);
  609.       fprintf(logfile,"calls prgd: %3i  Min: %5i  Xfers prgd: %4i  bytes: %7li\n\n",
  610.                        logoffs_purged, (SHORT)(seconds_purged/60),downloads_purged, bytes_dl_purged);
  611.       fclose(logfile);
  612.    }
  613. }
  614. /***************************************************************************/
  615. VOID produce_bulletins()
  616. {
  617.    FILE  *event;
  618.    CHAR  filename[255];
  619.    SHORT event_number;
  620.    static LONG old_date;
  621.  
  622. /* Open the data file for append to save the records of interest.          */
  623.    if ((event=fopen("Maxlog.Dat","rb")) == NULL)
  624.    {
  625.       printf("Error opening Maxlog.Dat\n");
  626.       exit(1);
  627.    }
  628.    while (feof(event) == 0)
  629.    {
  630.       fread(&event_number,sizeof(SHORT),1,event);
  631.       switch(event_number)
  632.       {
  633.          case DOWNLOAD:
  634.          case FILE_REQ:
  635.             fread(&xfer,sizeof(xfer),1,event);
  636.             fread(filename,xfer.name_length,1,event);
  637.             add_dl_to_list(filename,xfer.filesize);
  638.             break;
  639.  
  640.          case LOGOFF:
  641.          case MAIL_SESSION_END:
  642.             fread(&logoff,sizeof(logoff),1,event);
  643.  
  644. /*          Collect the events in system_used[][].                          */
  645. /*            if (logoff.duration > 60)*/
  646.             {
  647.                system_used[logoff.node-1][logoff.date].n_calls++;
  648.                system_used[logoff.node-1][logoff.date].hours +=
  649.                                       ((float)logoff.duration / (float)3600);
  650. /*             Collect the events in the usage_by_hour array.               */
  651.                add_call_to_graph(&logoff);
  652.             }
  653.  
  654. /*          Print a few dots just to show the program is still working.     */
  655.             if (logoff.date != old_date)
  656.             {
  657.                printf(".");
  658.                old_date = logoff.date;
  659.             }
  660.             break;
  661.  
  662.          default:
  663.             printf("UNKNOWN EVENT!!! (=%i) (bug)\n",event_number);
  664.             break;
  665.       }
  666.    }
  667.    fclose(event);
  668.    printf("\n");
  669.  
  670. /* Now sort the download list.                                             */
  671.    printf("Sorting download list.\n");
  672.    sort_dl_list();
  673.  
  674. /* Write out the top downloads bulletin.                                   */
  675.    printf("Writing Top Download bulletin.\n");
  676.    write_top_dl_bulletin();
  677.  
  678. /* Write out the system usage bulletin.                                    */
  679.    printf("Writing System Usage bulletin.\n");
  680.    write_system_usage_bulletin();
  681. }
  682. /***************************************************************************/
  683. VOID sort_dl_list()
  684. {
  685.    SHORT i,j;
  686.    SHORT tmp_count;
  687.    CHAR  *tmp_name;
  688.    LONG  tmp_bytes;
  689.    SHORT sorting = TRUE;
  690.    SHORT pass_number = 0;
  691.  
  692.    while (sorting == TRUE)
  693.    {
  694.       sorting = FALSE;
  695.       for (i=0; i<dl_struct_index-1; i++)
  696.       {
  697.          if (downloads[i+1].dl_count > downloads[i].dl_count)
  698.          {
  699.             sorting = TRUE;
  700.  
  701.             tmp_name = downloads[i].filename;
  702.             tmp_count = downloads[i].dl_count;
  703.             tmp_bytes = downloads[i].dl_bytes;
  704.  
  705.             downloads[i].filename = downloads[i+1].filename;
  706.             downloads[i].dl_count = downloads[i+1].dl_count;
  707.             downloads[i].dl_bytes = downloads[i+1].dl_bytes;
  708.  
  709.             downloads[i+1].filename = tmp_name;
  710.             downloads[i+1].dl_count = tmp_count;
  711.             downloads[i+1].dl_bytes = tmp_bytes;
  712.          }
  713.       }
  714.       if (j++%10 == 0) printf(".");
  715.    }
  716.    printf("\n");
  717. }
  718. /***************************************************************************/
  719. VOID write_top_dl_bulletin()
  720. {
  721.    SHORT i;
  722.    FILE *top_dl, *all_dl;
  723.    SHORT days_used;
  724.    SHORT days_in_bulletin;
  725.    SHORT total_files_dl = 0;
  726.  
  727. /* Find out how many days this .dat file covers.                           */
  728.    count_usage_days(0, &days_used);
  729.  
  730.    if ((days_used > 0) && (days_used < summary_days))
  731.    {
  732.       days_in_bulletin = days_used;
  733.    }
  734.    else
  735.    {
  736.       days_in_bulletin = summary_days;
  737.    }
  738.  
  739. /* Open the text file to write the "All Download" bulletin.                */
  740.    if ((all_dl=fopen("All_Dl.Txt","w")) == NULL)
  741.    {
  742.       printf("Error opening All_Dl.Txt\n");
  743.       exit(1);
  744.    }
  745.  
  746.    for (i=0; i<dl_struct_index; i++)
  747.    {
  748.       fprintf(all_dl,"%3i  %s\n",downloads[i].dl_count,downloads[i].filename);
  749.       total_files_dl += downloads[i].dl_count;
  750. /* this line is removed because total_bytes_dl is now calculated in the */
  751. /* add_dl_to_list function. 1/16/92                                     */
  752. /*      total_bytes_dl += downloads[i].dl_bytes * downloads[i].dl_count;*/
  753.    }
  754.    fclose(all_dl);
  755.  
  756. /* Open the text file to write the "Top Download" bulletin.                */
  757.    if ((top_dl=fopen("Top_Dl.Txt","w")) == NULL)
  758.    {
  759.       printf("Error opening Top_Dl.Txt\n");
  760.       exit(1);
  761.    }
  762.    fprintf(top_dl,"Top Files downloaded from%s: \n",bbs_name);
  763.    fprintf(top_dl,"Generated: %02i-%02i-%02i at %02i:%02i\n",
  764.             datetime.month,datetime.day,datetime.year,
  765.             datetime.hours,datetime.minutes);
  766.  
  767.    for (i=0; i<15; i++)
  768.    {
  769.       fprintf(top_dl,"     %12s %3i     %12s %3i     %12s %3i\n",
  770.                downloads[i].filename,   downloads[i].dl_count,
  771.                downloads[i+15].filename,downloads[i+15].dl_count,
  772.                downloads[i+30].filename,downloads[i+30].dl_count);
  773.    }
  774.  
  775.    fprintf(top_dl,"\nFor a period covering the last %i days:\n",days_in_bulletin);
  776.    fprintf(top_dl,"Total number of files downloaded: %i\n",total_files_dl);
  777.    fprintf(top_dl,"Total number of K bytes downloaded: %lu\n",total_bytes_dl/1000);
  778.    fprintf(top_dl,"A total of %i different files have been downloaded\n",dl_struct_index);
  779.  
  780.    fclose(top_dl);
  781. }
  782. /***************************************************************************/
  783. VOID write_system_usage_bulletin()
  784. {
  785.    SHORT i,j,k;
  786.    FILE  *usage, *hours;
  787.    SHORT total_calls;
  788.    float total_hours;
  789.    float total_for_node;
  790.    SHORT days_used;
  791.    CHAR  filename[15];
  792.    CHAR  output_string[81];
  793.    CHAR  graph_string[4];
  794.    SHORT total_nodes;
  795.  
  796. /* Loop for the maximum of n_logfiles and n_binkfiles.                     */
  797.    total_nodes = max(n_logfiles,n_binkfiles);
  798.  
  799. /* Open the data file for append to save the records of interest.          */
  800.    if ((usage=fopen("Usage.Txt","w")) == NULL)
  801.    {
  802.       printf("Error opening Usage.Txt\n");
  803.       exit(1);
  804.    }
  805.  
  806. /* Print the whole usage structure out.                                    */
  807.    fprintf(usage,"System usage by day:\n");
  808.    fprintf(usage,"Day  ");
  809.    for (i=0; i<total_nodes; i++)
  810.    {
  811.       fprintf(usage,"Calls  Hours     ");
  812.    }
  813.    fprintf(usage,"Totals\n");
  814.    for (j=1; j<=365; j++)
  815.    {
  816.       total_calls = 0;
  817.       total_hours = 0;
  818.       fprintf(usage,"%3i  ",j);
  819.       for (i=0; i<total_nodes; i++)
  820.       {
  821.          fprintf(usage,"%5i  %5.2f     ",system_used[i][j].n_calls,
  822.                                          system_used[i][j].hours);
  823.          total_calls+= system_used[i][j].n_calls;
  824.          total_hours+= system_used[i][j].hours;
  825.       }
  826.       fprintf(usage,"%5i  %5.2f\n",total_calls,total_hours);
  827.    }
  828.  
  829.  
  830. /* Print the usage by hour table.                                          */
  831.    for (j=0; j<total_nodes; j++)
  832.    {
  833. /*    Find out how many days this .dat file covers.                        */
  834.       count_usage_days(j, &days_used);
  835.  
  836.       total_for_node = (float)0;
  837.       fprintf(usage,"\n\n");
  838.       for (i=0; i<24; i++)
  839.       {
  840.          fprintf(usage,"hour %2i: %4li  %% used: %5.2f\n",
  841.                  i,usage_by_hour[j][i],
  842.                  (float)usage_by_hour[j][i]/(float)60/(float)(days_used-1));
  843.  
  844.          total_for_node+=(float)usage_by_hour[j][i]/60;
  845.       }
  846.       fprintf(usage,"Total for this node: %5.2f\n",total_for_node);
  847.    }
  848.    fclose(usage);
  849.  
  850.    for (k=0; k<total_nodes; k++)
  851.    {
  852. /*    Find out how many days this .dat file covers.                        */
  853.       count_usage_days(k, &days_used);
  854.  
  855.       sprintf(filename,"Hours%i.Txt",k);
  856.  
  857. /*    Open the bulletin file for write.                                    */
  858.       if ((hours=fopen(filename,"w")) == NULL)
  859.       {
  860.          printf("Error opening %s\n",filename);
  861.          exit(1);
  862.       }
  863.  
  864.       fprintf(hours,"Percentage of system usage by hour, generated: %02i-%02i-%02i at %02i:%02i\n",
  865.                datetime.month,datetime.day,datetime.year,
  866.                datetime.hours,datetime.minutes);
  867.       fprintf(hours,"Summarized over the last %i days\n",days_used);
  868.  
  869.       for (i=UsageLines-1; i>=0; i--)
  870.       {
  871.          sprintf(output_string,"%3i%%  ",(i+1) * 100/UsageLines);
  872.          for (j=0; j<24; j++)
  873.          {
  874.             if (usage_by_hour[k][j]/(float)60/(float)(days_used-1) >
  875.                           (float)i / (float)UsageLines)
  876.             {
  877.                strcpy(graph_string,"   ");
  878.                graph_string[0] = 0xdb;
  879.                strcat(output_string,graph_string);
  880.             }
  881.             else
  882.             {
  883.                strcat(output_string,"   ");
  884.             }
  885.          }
  886. /*       Strip off all trailing spaces from the graph.                      */
  887.          for (j=strlen(output_string); j>0; j--)
  888.          {
  889.             if (output_string[j-1] == ' ')
  890.             {
  891.                output_string[j-1] = '\0';
  892.             }
  893.             else
  894.             {
  895.                break;
  896.             }
  897.          }
  898.          fprintf(hours,"%s\n",output_string);
  899.       }
  900.       fprintf(hours,"      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");
  901.  
  902.       fclose(hours);
  903.    }
  904. }
  905. /***************************************************************************/
  906. VOID add_call_to_graph(struct lgoff *logoff)
  907. {
  908.    SHORT i;
  909.    SHORT start_time,end_time;
  910.  
  911. /* Calculate the end time in minutes.                                      */
  912.    end_time = (short)(logoff->time/60);
  913.  
  914.    start_time = end_time - (short)(logoff->duration/60) + 1;
  915.  
  916. /* Special case for when the logon was before midnight and logoff was      */
  917. /* after midnight.                                                         */
  918.    if (start_time < 0)
  919.    {
  920.       start_time += 1440;
  921.       for (i=start_time; i<=1439; i++)
  922.       {
  923.          usage_by_hour[logoff->node-1][i/60]++;
  924.       }
  925.       start_time = 0;
  926.    }
  927.  
  928.    for (i=start_time; i<=end_time; i++)
  929.    {
  930.       usage_by_hour[logoff->node-1][i/60]++;
  931.    }
  932. }
  933. /***************************************************************************/
  934. VOID count_usage_days(SHORT node, SHORT *days_used)
  935. {
  936. /* This function just counts the number of entries in the system_used      */
  937. /* structure to obtain the number of days covered in this .dat file        */
  938.  
  939.    SHORT i;
  940.  
  941.    *days_used = 0;
  942.    for (i=1; i<=365; i++)
  943.    {
  944.       if (system_used[node][i].n_calls != 0) *days_used = (*days_used)+1;
  945.    }
  946. }
  947. /***************************************************************************/
  948. VOID add_dl_to_list(CHAR *filename, LONG bytes)
  949. {
  950.    SHORT i;
  951.  
  952. /* Loop through the downloads structure to see if this file is already in  */
  953. /* the list.                                                               */
  954.    for (i=0; i<dl_struct_index; i++)
  955.    {
  956.       if (stricmp(downloads[i].filename, filename) == 0)
  957.       {
  958.          downloads[i].dl_count++;
  959.          total_bytes_dl += bytes;
  960.          return;
  961.       }
  962.    }
  963.  
  964. /* If you get to here, the filename isn't already in the list.              */
  965.    downloads[dl_struct_index].filename = calloc(strlen(filename)+1, sizeof(CHAR));
  966.    strcpy(downloads[dl_struct_index].filename, filename);
  967.    downloads[dl_struct_index].dl_count = 1;
  968.    downloads[dl_struct_index].dl_bytes = bytes;
  969.    total_bytes_dl += bytes;
  970.    dl_struct_index++;
  971.  
  972. /* Test dl_struct_index for overflow.                                       */
  973.    if (dl_struct_index >= MAX_DL_FILES)
  974.    {
  975.       printf("ERROR: MaxLog has reached its capacity for total number of files.\n");
  976.       printf("The limit is currently set to %i.  Please contact the author.\n",MAX_DL_FILES);
  977.       exit(99);
  978.    }
  979. }
  980. /****************************************************************************/
  981. VOID get_date_time(CHAR *text, CHAR *date_string, LONG *date, LONG *time)
  982. {
  983.    LONG hour, minute, second;
  984.    LONG day;
  985.    static LONG month;
  986.    CHAR temp[10];
  987.    LONG days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
  988.    LONG i;
  989.  
  990. /* Save the date text.                                                    */
  991.    strncpy(date_string,&text[2],6);
  992.    date_string[6] = '\0';
  993.  
  994.    strncpy(temp,&text[2],2);
  995.    temp[2] = '\0';
  996.    day = atoi(temp);
  997.  
  998.    strncpy(temp,&text[9],2);
  999.    temp[2] = '\0';
  1000.    hour = atoi(temp);
  1001.  
  1002.    strncpy(temp,&text[12],2);
  1003.    temp[2] = '\0';
  1004.    minute = atoi(temp);
  1005.  
  1006.    strncpy(temp,&text[15],2);
  1007.    temp[2] = '\0';
  1008.    second = atoi(temp);
  1009.  
  1010.    strncpy(temp,&text[5],3);
  1011.    temp[3] = '\0';
  1012.    if (strcmp(temp,"Jan")  == 0) month=1;
  1013.    else if (strcmp(temp,"Feb")  == 0) month=2;
  1014.    else if (strcmp(temp,"Mar")  == 0) month=3;
  1015.    else if (strcmp(temp,"Apr")  == 0) month=4;
  1016.    else if (strcmp(temp,"May")  == 0) month=5;
  1017.    else if (strcmp(temp,"Jun")  == 0) month=6;
  1018.    else if (strcmp(temp,"Jul")  == 0) month=7;
  1019.    else if (strcmp(temp,"Aug")  == 0) month=8;
  1020.    else if (strcmp(temp,"Sep")  == 0) month=9;
  1021.    else if (strcmp(temp,"Oct")  == 0) month=10;
  1022.    else if (strcmp(temp,"Nov")  == 0) month=11;
  1023.    else if (strcmp(temp,"Dec")  == 0) month=12;
  1024.  
  1025.    *time = hour*3600L + minute*60L + second;
  1026.  
  1027.    *date = 0;
  1028.    for (i=0; i< month-1; i++)
  1029.    {
  1030.       *date += days[i];
  1031.    }
  1032.    *date += day;
  1033. }
  1034. /***************************************************************************/
  1035. SHORT extract_file_name(char target[],char source[])
  1036. {
  1037.    SHORT i;
  1038.  
  1039. /* Loop through the source string looking for a '\' character.             */
  1040.    for (i=strlen(source); i>=0; i--)
  1041.    {
  1042. /*    Once found, copy the file name portion to target and return TRUE.    */
  1043.       if (source[i] == '\\')
  1044.       {
  1045.          strcpy(target, &source[i+1]);
  1046.          return(TRUE);
  1047.       }
  1048.    }
  1049. /* If there is no "\", return the whole string.                            */
  1050.    strcpy(target, source);
  1051.    return(TRUE);
  1052. }
  1053. /***************************************************************************/
  1054.