home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / BBS / USAGE18.ZIP / USAGE.C next >
C/C++ Source or Header  |  1992-09-28  |  16KB  |  512 lines

  1. /*
  2.  
  3. USAGE -- Reads one or more Maximus or Binkley logs and generates a usage graph
  4.  
  5. Version 1.8  (9/28/92)
  6.  
  7. Written by Bob Quinlan of Austin, Texas, USA
  8. Sysop of Red October at 512-834-2593 (1:382/111)
  9.  
  10. Copyright 1992 by Bob Quinlan
  11.  
  12. Compatible with Maximus 2.00 and 2.01 and BinkleyTerm 2.55 and 2.56
  13.  
  14.  
  15. This program reads one or more Maximus or Binkley logs and generates a
  16. BBS-format usage graph based on the data.  By default it will read
  17. MAX.LOG in the current directory and write USAGE.BBS.  The following
  18. switches allow you to configure it for your system and preferences:
  19.  
  20.     /Cx=y       Set color number 'x' to Avatar color 'y'.  'x' values
  21.                 mean the following:
  22.                     0 = default color
  23.                     1 = title
  24.                     2 = frame
  25.                     3 = reference text (%)
  26.                     4 = reference lines (%)
  27.                     5 = hour text
  28.                     6 = hour dots (odd hour values)
  29.                     7 = hour lines
  30.                     8 = data bars
  31.                     9 = enter prompt
  32.                 Avatar color codes are given in two-digit hexadecimal.
  33.                 The first digit sets the background color (0-7 only) and
  34.                 the second digit sets the foreground color (0-F).  Each
  35.                 digit corresponds to the following colors:
  36.                     0 = black
  37.                     1 = blue
  38.                     2 = green
  39.                     3 = cyan
  40.                     4 = red
  41.                     5 = magenta
  42.                     6 = brown
  43.                     7 = white
  44.                     8 = grey
  45.                     9 = bright blue
  46.                     A = bright green
  47.                     B = bright cyan
  48.                     C = bright red
  49.                     D = bright magenta
  50.                     E = yellow
  51.                     F = bright white
  52.                 Example: To set the data bars to yellow on blue you
  53.                 would use the switch /C8=1E.
  54.  
  55.     /Lfile      Log file to process.  Note that the /L parameter can be
  56.                 used more than once to specify several logs.  This
  57.                 feature is particularly useful if you have multiple
  58.                 lines with separate logs.
  59.  
  60.     /M          Military time.  Display the hours as 0-23.
  61.  
  62.     /Ttitle     Title for graph.  You may want to supply multiple word
  63.                 values for title.  You can separate the words by spaces
  64.                 or by underscores (which will be replaced by spaces).
  65.                 For example, both of these lines would produce the same
  66.                 results:
  67.                     usage /lmax.log /tRed October Usage
  68.                     usage /lmax.log /tRed_October_Usage
  69.  
  70.     /Ufile      The file to which the usage graph will be written. The
  71.                 .BBS extension is not automatically added.
  72.  
  73.     /V          Verbose diagnostic mode.  Prints out each log entry that
  74.                 triggers a starting or ending time.  Prints the elapsed
  75.                 time between each start/end pair.  Not recommended for
  76.                 normal use.
  77.  
  78. If you use WFC within Maximus feed USAGE the Maximus log.  If you use
  79. Binkley to answer the phone feed it the Binkley log.  You can mix log
  80. types if you have lines with different configurations.
  81.  
  82. As an example, my system has two lines, one running Binkley and the
  83. other running Maximus with WFC.  I start a new log every month and keep
  84. the previous month's around as well.  Here is how I generate my overall
  85. usage graph:
  86.  
  87. usage /lbink01l.old /lbink01.log /lmax02l.old /lmax02.log
  88. /tRed October Overall Usage
  89.  
  90. (That's all one line in my batch file.)
  91.  
  92. I have the Log Mode in Maximus set to Verbose and the LogLevel in
  93. Binkley set to 5.  If you use other settings USAGE may not register all
  94. of your system's activity.
  95.  
  96.  
  97. USAGE returns ERRORLEVEL 0 after a successful run.  ERRORLEVEL 1 is
  98. returned to indicate an error.
  99.  
  100. NOTICE:  You may use, copy, and distribute this program freely as long
  101. as you insure that both the executable and the documentation (.DOC)
  102. files are included in the distribution package.  The source code does
  103. not need to be included.  You may modify this program and document, so
  104. long as reasonable credit is given to the original author if a
  105. substantial portion of the original remains intact.  The author is not
  106. responsible for any losses which may occur either directly or indirectly
  107. as a result of using this program.
  108.  
  109. HISTORY:
  110. Version 1.8   (8/28/92) -- Added the /M switch for military time.
  111. Version 1.7   (8/25/92) -- Added the ability to pass multiple-word
  112.                            parameters using spaces.
  113. Version 1.6   (6/03/92) -- Adjusted graph to start at midnight.
  114. Version 1.5   (5/29/92) -- Improved Binkley support.  Added verbose
  115.                            diagnostic mode.
  116. Version 1.4   (5/27/92) -- Allow custom color selections.
  117. Version 1.3   (5/26/92) -- Removed event and keyboard switches.
  118.                            Added support for Binkley logs.
  119.                            Added log file sharing (again).
  120. Version 1.2   (5/14/92) -- Removed log file sharing due to compiler bug.
  121. Version 1.1   (5/13/92) -- Added log file sharing.
  122. Version 1.0   (4/22/92) -- Original release.  Written in Borland C.
  123.  
  124. Large memory model
  125. */
  126.  
  127.  
  128. #include <ctype.h>
  129. #include <errno.h>
  130. #include <fcntl.h>
  131. #include <io.h>
  132. #include <share.h>
  133. #include <stdio.h>
  134. #include <stdlib.h>
  135. #include <string.h>
  136. #include <sys\stat.h>
  137. #include <sys\types.h>
  138. #include <time.h>
  139.  
  140.  
  141. #define MAXLINE     (512)
  142. #define MAXPATH     (128)
  143. #define MAXTITLE    (72)
  144. #define MAXDATE     (7)
  145. #define MAXLOGS     (12)
  146. #define NUM_COLORS  (10)
  147.  
  148. #define DAYMINS     (1440)
  149. #define COLS        (72)
  150. #define CDIV        (DAYMINS/COLS)
  151.  
  152.  
  153. main(int argc, char *argv[])
  154. {
  155. char   logfile[MAXLOGS][MAXPATH];
  156. FILE   *logfile_fp;
  157. char   logs = 0;
  158. int    curlog = 0;
  159.  
  160. char   usefile[MAXPATH] = {"USAGE.BBS"};
  161. FILE   *usefile_fp;
  162.  
  163. char   comment[MAXLINE];
  164.  
  165. char   title[MAXTITLE] = {""};
  166.  
  167. int    online;
  168.  
  169. int    calls = 0;
  170. int    days = 0;
  171. int    time = 0;
  172.  
  173. int    military = 0;
  174. int    verbose = 0;
  175.  
  176. char   colors[NUM_COLORS] =
  177.             {
  178.             0x07,  /*  0: default color  */
  179.             0x0f,  /*  1: title  */
  180.             0x09,  /*  2: frame  */
  181.             0x0a,  /*  3: reference text  */
  182.             0x02,  /*  4: reference lines  */
  183.             0x0b,  /*  5: hour text  */
  184.             0x09,  /*  6: hour dots  */
  185.             0x03,  /*  7: hour lines  */
  186.             0x09,  /*  8: data bars  */
  187.             0x02   /*  9: enter prompt  */
  188.             };
  189.  
  190. int    use[COLS];
  191.  
  192. char   out[22][78];
  193. char   color[22][78];
  194.  
  195. char   last[MAXDATE];
  196. char   now[MAXDATE];
  197.  
  198. int    addtime;
  199. int    start;
  200. int    end;
  201.  
  202. char   curcolor = 0;
  203.  
  204. char   param = '\0';
  205.  
  206. char   line[MAXLINE];
  207. char   *ch;
  208. int    i, j, k;
  209.  
  210.  
  211. /***********/
  212. /*  USAGE  */
  213. /***********/
  214.  
  215. printf("USAGE 1.8 -- Copyright 1992 by Bob Quinlan (9/28/92)\n\n");
  216.  
  217. /*  Process switches  */
  218. for (i=1; i<argc; i++)
  219.     {
  220.     /*  Convert previous param to uppercase so single-pass switches will
  221.         not recognize it more than once  */
  222.     param = toupper(param);
  223.     /*  If new parameter set it to lower case for first pass  */
  224.     if (argv[i][0] == '/')
  225.         param = tolower(argv[i][1]);
  226.     switch (param)
  227.         {
  228.         case 'c':  /*  color  */
  229.             if (sscanf(argv[i]+2, "%x=%x", &j, &k) >= 2)
  230.                 if ((j < NUM_COLORS) && (k <= 0xff))
  231.                     colors[j] = k;
  232.                 else
  233.                     fprintf(stderr, "USAGE: Illegal value in %s\n", argv[i]);
  234.             else
  235.                 fprintf(stderr, "USAGE: Illegal format in %s\n", argv[i]);
  236.             break;
  237.         case 'l':  /*  log file  */
  238.             if (logs < MAXLOGS)
  239.                 strncpy(logfile[logs++], argv[i]+2, MAXPATH);
  240.             else
  241.                 fprintf(stderr, "USAGE: %s exceeds log limit\n",
  242.                       argv[i]+2);
  243.             break;
  244.         case 'm':  /*  military time  */
  245.             military = 1;
  246.             break;
  247.         case 'T':  /*  title: append additional words  */
  248.             strncat(title, " ", MAXTITLE);
  249.             /*  Fall through to next case!  */
  250.         case 't':  /*  title  */
  251.             strncat(title, argv[i]+((islower(param) != 0)*2), MAXTITLE);
  252.             while ((ch = strchr(title, '_')) != NULL)
  253.                 *ch = ' ';
  254.             break;
  255.         case 'u':  /*  use file  */
  256.             strncpy(usefile, argv[i]+2, MAXPATH);
  257.             break;
  258.         case 'v':
  259.             verbose = 1;
  260.             break;
  261.         default:
  262.             fprintf(stderr, "USAGE: Unknown switch: %s\n", argv[i]);
  263.             break;
  264.         }
  265.     }
  266.  
  267. /*  If not defined supply defaults  */
  268. if (*title == '\0')
  269.     strcpy(title, "SYSTEM USAGE");
  270. if (!logs)
  271.     strcpy(logfile[logs++], "MAX.LOG");
  272.  
  273. /*  Initialize usage table  */
  274. for (i=0; i<COLS; i++)
  275.     use[i] = 0;
  276.  
  277. /*  Process all log files  */
  278. while ((logfile_fp = _fsopen(logfile[curlog], "rb", SH_DENYNO)) != NULL)
  279.     {
  280.     printf("Processing %s\n", logfile[curlog]);
  281.  
  282.     online = 0;
  283.     *last = '\0';
  284.     while (fgets(line, MAXLINE, logfile_fp) != NULL)
  285.         {
  286.         /*  Ignore blank lines  */
  287.         if (*line != '\r')
  288.             {
  289.             /*  Keep track of the current date  */
  290.             strncpy(now, line+2, MAXDATE);
  291.             now[MAXDATE-1] = '\0';
  292.             /*  Increase counts when date changes  */
  293.             if (strcmp(now, last) != 0)
  294.                 {
  295.                 addtime += DAYMINS;
  296.                 days++;
  297.                 strcpy(last, now);
  298.                 printf("    %s\n", now);
  299.                 }
  300.             }
  301.  
  302.         /*  Strip and downcase the comment section of the entry  */
  303.         strcpy(comment, line+23);
  304.         strlwr(comment);
  305.  
  306.         /*  If already processing usage...  */
  307.         if (online)
  308.             {
  309.             /*  All usage ends with the next log block  */
  310.             if ((strncmp(comment, "begin, ", 7) == 0) ||
  311.                   (strncmp(comment, "connect", 7) == 0) ||
  312.                   (strncmp(comment, "re-enabling system ", 19) == 0) ||
  313.                   (strncmp(comment, "end of wazoo", 12) == 0))
  314.                 {
  315.                 calls++;
  316.                 end = atoi(line+9)*60+atoi(line+12)+addtime;
  317.                 time += end-start+1;
  318.                 /*  Increment usage once per minute  */
  319.                 for (i=start; i<=end; i++)
  320.                     {
  321.                     use[(i%DAYMINS)/CDIV]++;
  322.                     }
  323.                 online = 0;
  324.                 if (verbose)
  325.                     printf("%s---------------------->elapsed: %d\n", line,
  326.                           end-start+1);
  327.                 }
  328.             }
  329.         if (!online)
  330.             {
  331.             /*  If looking for new usage...  */
  332.             if ((strncmp(comment, "connect", 7) == 0) ||
  333.                   (strstr(comment, "with errorlevel") != NULL))
  334.                 {
  335.                 addtime = 0;
  336.                 start = atoi(line+9)*60+atoi(line+12);
  337.                 online = 1;
  338.                 if (verbose)
  339.                     printf("%s", line);
  340.                 }
  341.             }
  342.         }
  343.  
  344.     /*  Close log file  */
  345.     fclose(logfile_fp);
  346.  
  347.     /*  Check for last log processed  */
  348.     if (++curlog >= logs)
  349.         break;
  350.     }
  351.  
  352. /*  Check for finish before last log processed  */
  353. if (curlog < logs)
  354.     {
  355.     fprintf(stderr, "USAGE: Unable to open the log file: %s\n",
  356.           logfile[curlog]);
  357.     exit(1);
  358.     }
  359.  
  360. /*  Initialize virtual screen  */
  361. for (i=0; i<22; i++)
  362.     for (j=0; j<78; j++)
  363.         {
  364.         out[i][j] = ' ';
  365.         color[i][j] = colors[0];
  366.         }
  367.  
  368. /*  Draw frame  */
  369. for (i=77-COLS; i<77; i++)
  370.     {
  371.     out[0][i] = 205;
  372.     color[0][i] = colors[2];
  373.     out[20][i] = 205;
  374.     color[20][i] = colors[2];
  375.     }
  376. for (i=1; i<20; i++)
  377.     {
  378.     out[i][76-COLS] = 186;
  379.     color[i][76-COLS] = colors[2];
  380.     out[i][77] = 186;
  381.     color[i][77] = colors[2];
  382.     }
  383.  
  384. /*  Draw corners  */
  385. out[0][4] = 201;
  386. color[0][4] = colors[2];
  387. out[0][77] = 187;
  388. color[0][77] = colors[2];
  389. out[20][4] = 200;
  390. color[20][4] = colors[2];
  391. out[20][77] = 188;
  392. color[20][77] = colors[2];
  393.  
  394. /*  Draw 20% references  */
  395. for (i=1; i<5; i++)
  396.     {
  397.     /*  Draw reference text  */
  398.     out[i*4][73-COLS] = ((5-i)*2)+'0';
  399.     color[i*4][73-COLS] = colors[3];
  400.     out[i*4][74-COLS] = '0';
  401.     color[i*4][74-COLS] = colors[3];
  402.     out[i*4][75-COLS] = '%';
  403.     color[i*4][75-COLS] = colors[3];
  404.     /*  Draw reference lines  */
  405.     for (j=77-COLS; j<77; j++)
  406.         {
  407.         out[i*4][j] = 196;
  408.         color[i*4][j] = colors[4];
  409.         }
  410.     }
  411.  
  412. /*  Draw hour references  */
  413. for (i=0; i<24; i++)
  414.     {
  415.     if (i%2)
  416.         {
  417.         /*  Draw dots for odd hours  */
  418.         out[21][77-COLS+COLS/24*i] = 249;
  419.         color[21][77-COLS+COLS/24*i] = colors[6];
  420.         }
  421.     else
  422.         {
  423.         /*  Draw numbers for even hours  */
  424.         k = (military) ? i : ((i+11)%12)+1;
  425.         /*  Check for one or two digits  */
  426.         if (k > 9)
  427.             {
  428.             out[21][77-COLS+COLS/24*i] = (k/10)+'0';
  429.             color[21][77-COLS+COLS/24*i] = colors[5];
  430.             out[21][78-COLS+COLS/24*i] = (k%10)+'0';
  431.             color[21][78-COLS+COLS/24*i] = colors[5];
  432.             }
  433.         else
  434.             {
  435.             out[21][77-COLS+COLS/24*i] = (k%10)+'0';
  436.             color[21][77-COLS+COLS/24*i] = colors[5];
  437.             }
  438.         }
  439.     /*  Draw hour lines  */
  440.     if ((i%4 == 0) && (i > 0))
  441.         for (j=1; j<20; j++)
  442.             {
  443.             out[j][77-COLS+COLS/24*i] = 179;
  444.             color[j][77-COLS+COLS/24*i] = colors[7];
  445.             }
  446.     }
  447.  
  448. /*  Graph data  */
  449. for (i=0; i<COLS; i++)
  450.     {
  451.     /*  Divide use counts by days (for all logs) and minutes per column  */
  452.     /*  39L = 19 rows * 2 + 1  */
  453.     use[i] = use[i]*39L/(days*CDIV);
  454.     /*  Clip to maximum height (just in case)  */
  455.     if (use[i] > 38)
  456.         use[i] = 38;
  457.     j = 0;
  458.     while (j*2 < use[i])
  459.         {
  460.         if (j*2+1 < use[i])
  461.             out[19-j][77-COLS+i] = 219;  /*  full-height block  */
  462.         else
  463.             out[19-j][77-COLS+i] = 220;  /*  half-height block  */
  464.         color[19-j][77-COLS+i] = colors[8];
  465.         j++;
  466.         }
  467.     }
  468.  
  469. /*  Open use (output) file  */
  470. if ((usefile_fp = _fsopen(usefile, "w+b", SH_DENYRW)) == NULL)
  471.     {
  472.     fprintf(stderr, "USAGE: Unable to open the use file: %s\n", usefile);
  473.     exit(1);
  474.     }
  475.  
  476. /*  Write [cls] and [moreoff] tokens  */
  477. fprintf(usefile_fp, "\x0c\x0b");
  478.  
  479. /*  Write centered title  */
  480. fprintf(usefile_fp, "\x16\x01%c   ", colors[1]);
  481. j = 39-strlen(title)/2;
  482. for (i=0; i<j; i++)
  483.     putc(' ', usefile_fp);
  484. fprintf(usefile_fp, "%s\r\n", title);
  485.  
  486. /*  Write data  */
  487. for (i=0; i<22; i++)
  488.     {
  489.     for (j=0; j<78; j++)
  490.         {
  491.         /*  Write color change tokens only when necessary  */
  492.         if (color[i][j] != curcolor)
  493.             {
  494.             curcolor = color[i][j];
  495.             fprintf(usefile_fp, "\x16\x01%c", curcolor);
  496.             }
  497.         putc(out[i][j], usefile_fp);
  498.         }
  499.     fprintf(usefile_fp, "\r\n");
  500.     }
  501.  
  502. /*  Add color and [enter] tokens  */
  503. fprintf(usefile_fp, "\x16\x01%c     \x01", colors[9]);
  504.  
  505. /*  Close use file  */
  506. fclose(usefile_fp);
  507.  
  508. return 0;
  509. }
  510.  
  511.  
  512.