home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / inetlg71.zip / INETLOG.CMD < prev    next >
OS/2 REXX Batch file  |  2000-02-10  |  42KB  |  1,225 lines

  1. /* INETLOG.CMD
  2. Copyright 1996 - 2000 by Chuck McKinnis,  Sandia Park, NM (USA) 04 Feb 2000
  3. mckinnis@attglobal.net
  4. Copyright 1995 by Jerry Levy,  Marblehead, MA (USA) 03 Nov 95
  5. jlevy@ibm.net
  6.  
  7. REXX Program to extract and totalize daily and monthly time-ons by
  8. analyzing the IBM WARP Internet Dialer log or the InJoy dialer log */
  9.  
  10. Trace 'N'
  11. version = '7.1'
  12. what_r_we = 'INETLOG  v'||version 'Copyright 1995 - 2000 by Chuck McKinnis and Jerry Levy'
  13. Parse Upper Arg otherparms
  14.  
  15. /* Where are we ? */
  16. Parse Source . . install_path .
  17. install_path = Filespec('D',install_path) || Filespec('P',install_path)
  18. ini_file = install_path || 'inetlog.ini'
  19. cfg_file = install_path || 'inetcfg.cfg'
  20. cfg_save = install_path || 'inetcfg.sav'
  21. save_path = Directory()
  22. our_path = Strip(install_path, 'T', '\')
  23. our_path = Directory(our_path)
  24. pmrexx_obj = SysSearchPath('PATH', 'PMREXX.EXE')
  25.  
  26. pmrexx = 0
  27. If Wordpos('/PMREXX', otherparms) > 0 Then
  28.    Do
  29.       If pmrexx_obj <> '' Then
  30.          pmrexx = 1
  31.       Else
  32.          Do
  33.             Say 'PMREXX.EXE is not in your current PATH'
  34.             pmrexx = 0
  35.          End
  36.    End
  37. Else
  38.    Do
  39.       If Wordpos('/NOPMREXX', otherparms) = 0 Then
  40.          Do
  41.             If pmrexx_obj <> '' Then
  42.                Do
  43.                   Parse Source . . inetlog_program .
  44.                   Address cmd '@START "Internet Log Analyzer" /PM /I' pmrexx_obj inetlog_program otherparms '/PMREXX'
  45.                   Exit 0
  46.                End
  47.             Else
  48.                Do
  49.                   Say 'PMREXX.EXE is not in your current PATH'
  50.                   pmrexx = 0
  51.                End
  52.          End
  53.       pmrexx = 0
  54.    End
  55.  
  56. /* Right to freely use, modify, distribute granted but please acknowledge
  57.    source as a courtesy if you build upon it.  Please pass on comments,
  58.    suggestions, problems to jlevy@ibm.net or mckinnis@attglobal.net
  59.    ------------------------------------
  60.    Getting Started (See readme.txt)
  61.    Program History (See changes.txt)
  62.    Use of Command-line options:  (See readme.txt)
  63.    ----------------------------------- */
  64.  
  65. /* The following are acceptable command-line parameters for special runs.
  66.     Only one of these can be used in a run and case is ignored.
  67.  
  68.       /NOPMREXX run without using PMREXX
  69.  
  70.    The following are acceptable command-line parameters (case is ignored):
  71.  
  72.    These parameters can be overridden on a run by run basis only.
  73.  
  74.       /Q<uiet> run without output to screen, default is to output results
  75.  
  76.       /C<ombined> output summary listing of both IGN and InJoy results
  77.  
  78.       /COMBINEONLY output only summary listing of both IGN and InJoy results
  79.  
  80. */
  81. If Rxfuncquery('SysDropFuncs') Then
  82.    Do
  83.       Call Rxfuncadd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
  84.       Call SysLoadFuncs
  85.    End
  86. If Rxfuncquery('RxExtra') Then
  87.    Do
  88.       Call Rxfuncadd 'RxExtra', 'RxExtras', 'RxExtra'
  89.       Call RxExtra 'LOAD'
  90.    End
  91.  
  92.  
  93. Signal On Failure Name errhandler
  94. Signal On Halt Name errhandler
  95. Signal On Syntax Name errhandler
  96.  
  97. /*========MAIN PROGRAM=========*/
  98. Call SysCls
  99.  
  100. Call Initialize_parms
  101.  
  102. If \ibm_dialer & \injoy_dialer Then
  103.    Do
  104.       Say 'You have not selected any logs to analyze'
  105.       Call Cleanup
  106.    End
  107.  
  108. If ibm_dialer Then
  109.    Do
  110.       /* gets, calculates, totalizes connect times.
  111.          Mostly a bunch of conditionals with a Call to a
  112.          data-formatting routine. All is stored in
  113.          variables for output all at once */
  114.       Call Analyze_logfile
  115.  
  116.       save_quiet = quiet
  117.       If combineonly Then
  118.          quiet = 1
  119.  
  120.       Call Outputter     /* Outputs everything to console and to disk */
  121.       quiet = save_quiet
  122.  
  123.       If \quiet & \combineonly & ibm_dialer & \pmrexx Then
  124.          answer = Say_message('IBM dialer analysis complete, Press any key to continue...')
  125.    End
  126. save_quiet = quiet
  127.  
  128. If injoy_dialer Then
  129.    Do
  130.       injoy_parms = ''
  131.       If combineonly Then
  132.          quiet = 1
  133.       If quiet Then
  134.          injoy_parms = injoy_parms '/QUIET'
  135.       If pmrexx Then
  136.          injoy_parms = injoy_parms '/PMREXX'
  137.       irc = IJoyLog(injoy_parms)
  138.       If irc = 0 Then         /* pick up any changes made by injoylog */
  139.          Call Read_config
  140.    End
  141.  
  142. quiet = save_quiet
  143. If \quiet & \combineonly & combine & injoy_dialer & \pmrexx Then
  144.    answer = Say_message('InJoy analysis complete, Press any key to continue...')
  145.  
  146. If combine & irc = 0 Then
  147.    Call Combined_output
  148.  
  149. Call Cleanup                                                 /* Exits */
  150. /*====END OF MAIN PROGRAM=======*/
  151. Initialize_parms:
  152. trace_save = Trace('N')
  153. quiet = 0
  154. combine = 0
  155. combineonly = 0
  156. Parse Value '' With c_parm
  157.  
  158. Do i = 1 To Words(otherparms)
  159.    Parse Value Word(otherparms, i) With key_word '=' key_value
  160.    Select
  161.       When Abbrev(key_word, '/COMBINEONLY') Then
  162.          c_parm = 'COMBINEONLY'
  163.       When Abbrev(key_word, '/C') Then
  164.          c_parm = 'COMBINE'
  165.       When Abbrev(key_word, '/Q') Then
  166.          quiet = 1
  167.       Otherwise Nop
  168.    End
  169. End
  170. If c_parm <> '' Then
  171.    Do
  172.       If Abbrev(c_parm, 'COMBINE') Then
  173.          combine = 1
  174.       If Abbrev(c_parm, 'COMBINEONLY') Then
  175.          combineonly = 1
  176.    End
  177.  
  178. Call Read_config
  179.  
  180. Call Check_config
  181.  
  182. If ibm_dialer Then
  183.    Do
  184.       /* Get path for connection log file and install directory */
  185.       x = Setlocal()
  186.       tcpip_etc_path = Value('ETC', ,'OS2ENVIRONMENT')
  187.       tcpip_etc_path = tcpip_etc_path || '\'
  188.       x = Endlocal()
  189.       dialer_ini = tcpip_etc_path || ibm_dialer_ini_file
  190.       Parse Value Log_file_parms(ibm_dialer_ini_file, dialer_ini) ,
  191.          With dialer_log_file dialer_log_size
  192.       log_file = dialer_log_file
  193.       /* Get full paths for output file and summary file */
  194.       output_file = data_path || ibm_output_file
  195.       summary_file = data_path || ibm_summary_file
  196.       Call Set_monthly_summary
  197.       /* initialize variables */
  198.       crlf = D2c(13) || D2c(10)         /* carriage return + linefeed */
  199.       esc = D2c(27)                               /* Escape character */
  200.       time_stamp = ''            /* Time stamp of each connect record */
  201.  
  202.       Do i = 1 To 12                             /* initialize months */
  203.          x = Right(i,2,'0')
  204.          month.x = Word('Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec',i)
  205.       End
  206.  
  207.       /* calculated variables
  208.          signons_each_day    Accumulate number of connects daily
  209.          signons_each_month  Accumulate number of connects monthly
  210.          time_on             Time, each connect  (minutes)
  211.          daily_time_on       Accumulated minutes, daily
  212.          monthly_time_on     Accumulated minutes, monthly */
  213.  
  214.       /* More variables: these we initialize as follows: */
  215.       old_m = 0           /* Storage of a 2-digit month (eg 05 = May) */
  216.       old_d = 0                              /* ... and a 2-digit day */
  217.       dcounter = 0        /* Counter increments each sign-on in a day */
  218.       mcounter = 0                   /* Same for each sign-on in a month */
  219.       monthline. = ''     /* Initialize both of these as null strings */
  220.       dayline. = '' /* These are for monthly and daily output strings */
  221.  
  222.       /* A typical line generated in the connect.log upon disconnect looks like
  223.          either this for a dialer version preceding v1.45:
  224.             11/15 19:08:38 Disconnected after 00:06:20  0 errors  0 discards'
  225.          or this style for v. 1.45 and later:
  226.             1995/11/15 19:08:38 Disconnected after 00:06:20  0 errors  0 discards
  227.          We search for a key_phrase using the RexxUtil function SysFileSearch */
  228.  
  229.       /* Word or phrase we'll search for */
  230.       key_phrase = 'Disconnected after'
  231.       user_phrase = 'dialed' /* word to search for account and userid */
  232.  
  233.       /* Here is where we Check if the output file exists.  If it does, we
  234.          overwrite it, and if not we create it.  BUT....  we don't want to
  235.          do something stupid like try to erase a vital file or the connect
  236.          logfile... */
  237.  
  238.       If \RxFileExists(log_file) Then
  239.          Do
  240.             Say 'Aborting.' log_file 'does not exist.'
  241.             Call Beep 1000,100
  242.             Call Cleanup
  243.          End
  244.  
  245.       file1 = Translate(Filespec('N', log_file))
  246.       file2 = Translate(Filespec('N', output_file))
  247.       If file2 == 'CONNECT.LOG',
  248.          | file2 == 'IPDIALER.LOG',
  249.          | file2 == 'CONFIG.SYS',
  250.          | file2 == 'AUTOEXEC.BAT',
  251.          | file2 == file1 Then
  252.          Do
  253.             Say log_file 'was entered as the dialer log file name and'
  254.             Say output_file 'was entered as the INETLOG output file name.'
  255.             Say 'These files cannot have the same name, and the names'
  256.             Say '"CONNECT.LOG, IPDIALER.LOG, CONFIG.SYS, and AUTOEXEC.BAT"'
  257.             Say 'are not permitted as INETLOG output file names.'
  258.             Say crlf
  259.             Call Beep 1000,100
  260.             Call Cleanup                            /* Error, so Exit */
  261.          End
  262.  
  263.       /* make sure that we have control of the log file */
  264.       rc = File_cmd(log_file, 'W')
  265.       If \ rc Then
  266.          Do Until rc
  267.             Say 'Log file' log_file 'returned' result
  268.             rc = File_cmd(log_file, 'C')
  269.             Say 'Unable to open' log_file
  270.             Say 'Press Esc to abort run'
  271.             answer = Say_message('Press any other key to wait 5 seconds')
  272.             If answer = esc Then
  273.                Call Cleanup
  274.             Call SysSleep 5
  275.             Call SysCls
  276.             rc = File_cmd(log_file, 'W')
  277.          End
  278.       rc = File_cmd(log_file, 'C')
  279.  
  280.       /* Backup any output file of the same name if it exists, then erase orig. */
  281.       If RxFileExists(output_file) Then
  282.          Do
  283.             Parse Var output_file fname '.' ext
  284.             Address cmd '@COPY' output_file fname||'.bak > NUL'
  285.             Call SysFileDelete output_file
  286.          End
  287.  
  288.    End
  289.  
  290. If injoy_dialer Then
  291.    Do
  292.       injoy_summary = data_path || injoy_summary_file
  293.    End
  294.  
  295. Trace (trace_save)
  296. Return                                            /* Initialize_parms */
  297.  
  298. /* read the config file */
  299. Read_config:
  300. trace_save = Trace('N')
  301. Trace 'N'
  302. If RxFileExists(cfg_file) Then            /* do we have a config file */
  303.    input_file = cfg_file
  304. Else
  305.    Do
  306.       If RxFileExists(cfg_save) Then
  307.          input_file = cfg_save
  308.       Else
  309.          Do
  310.             Call Config_sample               /* use the sample values */
  311.             input_file = 'sample'
  312.          End
  313.    End
  314.  
  315. If input_file <> 'sample' Then
  316.    Call RxRead 'data.', input_file
  317. Else
  318.    Call RxStemCopy 'cfg_sample.', 'data.'
  319. config. = ''
  320. config.0 = data.0
  321. Do i = 1 To data.0
  322.    config.i = data.i
  323.    If Abbrev(data.i, ';') | Abbrev(data.i, '[') Then
  324.       Nop
  325.    Else
  326.       Do
  327.          Parse Var data.i key_id '=' key_value
  328.          key_id = Strip(key_id)
  329.          key_value = "'" || Strip(key_value) || "'"
  330.          Interpret key_id '=' key_value
  331.       End
  332. End
  333. Call Convert_ini ini_file              /* update from an old ini file */
  334. Trace(trace_save)
  335. Return
  336.  
  337. /* convert or update config using an existing ini file */
  338. Convert_ini:
  339. trace_save = Trace('N')
  340. Trace 'N'
  341. Parse Arg ini_file
  342. If RxFileExists(ini_file) ,
  343.    & File_cmd(ini_file, 'D') > File_cmd(input_file, 'D') Then
  344.    Do
  345.       ini_key = 'IGN InJoy DataPath DisplayDailyReport PauseAsScreenFills' ,
  346.          'WarnPercent ConnectDigits MinuteDigits HourDigits'
  347.       key_key = 'ibm_dialer injoy_dialer data_path daily_report one_screen_at_a_time' ,
  348.          'warn_pct sig_x sig_min sig_hr'
  349.       /* get all keys */
  350.       xrc = SysIni(ini_file, 'COMMON', 'ALL:', 'keys.')
  351.       If keys.0 > 0 Then
  352.          Do i = 1 To keys.0                 /* get all the key values */
  353.             key_id = Word(key_key, Wordpos(keys.i, ini_key))
  354.             key_value = "'" || SysIni(ini_file, 'COMMON', keys.i) || "'"
  355.             Interpret key_id '=' key_value
  356.          End
  357.       ini_key = 'IniFileName OutputFileName SummaryFileName LastTimeStamp'
  358.       key_key = 'ibm_dialer_ini_file ibm_output_file ibm_summary_file ibm_last_time_stamp'
  359.       /* get all keys */
  360.       xrc = SysIni(ini_file, 'INETLOG', 'ALL:', 'keys.')
  361.       If keys.0 > 0 Then
  362.          Do i = 1 To keys.0                 /* get all the key values */
  363.             key_id = Word(key_key, Wordpos(keys.i, ini_key))
  364.             key_value = "'" || SysIni(ini_file, 'INETLOG', keys.i) || "'"
  365.             Interpret key_id '=' key_value
  366.          End
  367.       ini_key = 'InJoyOutput InJoySummary'
  368.       key_key = 'injoy_output_file injoy_summary_file'
  369.       /* get all keys */
  370.       xrc = SysIni(ini_file, 'IJOYLOG', 'ALL:', 'keys.')
  371.       If keys.0 > 0 Then
  372.          Do i = 1 To keys.0                 /* get all the key values */
  373.             key_id = keys.i
  374.             If Wordpos(key_id, ini_key) > 0 Then
  375.                Do
  376.                   key_id = Word(key_key, Wordpos(keys.i, ini_key))
  377.                   key_value = "'" || SysIni(ini_file, 'IJOYLOG', keys.i) || "'"
  378.                   Interpret key_id '=' key_value
  379.                End
  380.          End
  381.       injoy_total_logs = SysIni(ini_file, 'IJOYLOG', 'InJoyLogs')
  382.       log_value = ''
  383.       acct_value = ''
  384.       user_value = ''
  385.       time_value = ''
  386.       Do i = 1 To injoy_total_logs
  387.          key = 'InJoyLog_' || i
  388.          log_value = log_value SysIni(ini_file, 'IJOYLOG', key)
  389.          If log_value = 'ERROR:' Then
  390.             log_value = Word(SysIni(ini_file, 'IJOYLOG', 'InJoyLog'), i)
  391.          key = 'InJoyAcct_' || i
  392.          acct_value = acct_value SysIni(ini_file, 'IJOYLOG', key)
  393.          If acct_value = 'ERROR:' Then
  394.             acct_value = Word(SysIni(ini_file, 'IJOYLOG', 'InJoyAcct'), i)
  395.          key = 'InJoyUser_' || i
  396.          user_value = user_value SysIni(ini_file, 'IJOYLOG', key)
  397.          If user_value = 'ERROR:' Then
  398.             user_value = Word(SysIni(ini_file, 'IJOYLOG', 'InJoyUser'), i)
  399.          key = 'InJoyTimeStamp_' || i
  400.          time_value = time_value SysIni(ini_file, 'IIJOYLOG', key)
  401.          If time_value = 'ERROR:' Then
  402.             time_value = Word(SysIni(ini_file, 'IJOYLOG', 'InJoyTimeStamp'), i)
  403.       End
  404.       key_id = 'injoy_logs'
  405.       Interpret key_id '=' "'" || Strip(log_value) || "'"
  406.       key_id = 'injoy_accts'
  407.       Interpret key_id '=' "'" || Strip(acct_value) || "'"
  408.       key_id = 'injoy_users'
  409.       Interpret key_id '=' "'" || Strip(user_value) || "'"
  410.       key_id = 'injoy_times'
  411.       Interpret key_id '=' "'" || Strip(time_value) || "'"
  412.       Call Write_config
  413.       Address cmd '@rename' ini_file 'inetini.sav > nul'
  414.    End
  415. Trace(trace_save)
  416. Return
  417.  
  418. /* write the config file */
  419. Write_config:
  420. trace_save = Trace('N')
  421. Trace 'N'
  422. If RxFileExists(cfg_file) Then            /* do we have a config file */
  423.    Do
  424.       If RxFileExists(cfg_save) Then
  425.          Call SysFileDelete(cfg_save)
  426.       Address cmd '@rename' cfg_file Filespec('N', cfg_save) '> nul'
  427.    End
  428. Do i = 1 To config.0
  429.    If Abbrev(config.i, ';') | Abbrev(config.i, '[') Then
  430.       Nop
  431.    Else
  432.       Do
  433.          Parse Var config.i key_id '=' key_value
  434.          key_id = Strip(key_id)
  435.          config.i = key_id '=' Value(key_id)
  436.       End
  437. End
  438. Call RxWrite 'config.', cfg_file
  439. Trace(trace_save)
  440. Return
  441.  
  442. /* check the config file */
  443. Check_config:
  444. trace_save = Trace('N')
  445. Trace 'N'
  446. /* path to data files */
  447. If data_path = '' Then
  448.    Do
  449.       data_path = install_path || 'data\'
  450.       Call Write_config
  451.    End
  452. /* create the data path sub-directory if needed */
  453. If \RxFileExists(data_path || '*.*') Then
  454.    xrc = SysMkDir(Strip(data_path, , '\'))
  455. /* IBM dialer support */
  456. If ibm_dialer = '' Then
  457.    Do
  458.       Say 'Support the IBM dialer (y/N)?'
  459.       Parse Upper Pull ans .
  460.       key_value = Abbrev(ans, 'Y')
  461.       ibm_dialer = key_value
  462.       Call Write_config
  463.    End
  464. /* InJoy dialer support */
  465. If injoy_dialer = '' Then
  466.    Do
  467.       Say 'Support the InJoy dialer (y/N)?'
  468.       Parse Upper Pull ans .
  469.       key_value = Abbrev(ans, 'Y')
  470.       injoy_dialer = key_value
  471.       Call Write_config
  472.    End
  473.  
  474. /* process IBM dialer entries */
  475. If ibm_dialer Then
  476.    Do
  477.       /* dialer ini file */
  478.       If ibm_dialer_ini_file = '' Then
  479.          Do
  480.             Say 'Please select your IBM dialer by number'
  481.             Say '   1 - DIALER.EXE (1.67 and below)'
  482.             Say '   2 - TCPDIAL.EXE (1.69 and above)'
  483.             Parse Upper Pull ans .
  484.             Select
  485.                When ans = 1 Then
  486.                   key_value = 'dialer.ini'
  487.                When ans = 2 Then
  488.                   key_value = 'tcpdial.ini'
  489.                Otherwise Do
  490.                   Say 'You did not chose a supported dialer'
  491.                   key_value = ''
  492.                End
  493.             End
  494.             ibm_dialer_ini_file = key_value
  495.             Call Write_config
  496.          End
  497.    End
  498.  
  499. /* process InJoy dialer entries */
  500. If injoy_dialer Then
  501.    Do
  502.       If injoy_logs = '' Then
  503.          Do
  504.             /* get path to InJoy */
  505.             Say 'Enter the full path to the InJoy Dialer logs or hit enter to quit.'
  506.             Parse Upper Pull ans .
  507.             If ans <> '' Then
  508.                Do
  509.                   /* get all *.log file names */
  510.                   log_path = ans
  511.                   rc = SysFileTree(log_path || '\*.log', 'logs.', 'FO')
  512.                   /* loop through log file names to see the user wants them included */
  513.                   If rc = 0 & logs.0 > 0 Then
  514.                      Do i = 1 To logs.0
  515.                         Say 'Found InJoy log file -' logs.i
  516.                         Say 'Analyze this log (y/N)'
  517.                         Parse Upper Pull ans
  518.                         If Abbrev(ans, 'Y') Then
  519.                            Do
  520.                               injoy_logs = Space(injoy_logs logs.i)
  521.                            End
  522.                      End
  523.                   Else
  524.                      Do
  525.                         Say 'Unable to locate any logs in InJoy log path -' ans
  526.                         Say 'InJoy logs in' ans 'will not be processed.'
  527.                      End
  528.                End
  529.             Else
  530.                Say 'InJoy logs will not be processed'
  531.             injoy_accts = ''
  532.             injoy_users = ''
  533.             injoy_times = ''
  534.             Do i = 1 To Words(injoy_logs)
  535.                joylog = Word(injoy_logs, i)
  536.                joyacct = Word(injoy_accts, i)
  537.                joyuser = Word(injoy_users, i)
  538.                joytime = Word(injoy_times, i)
  539.                If joyacct = '' Then
  540.                   Do
  541.                      Say 'Enter an account id for InJoy log (enter = none)'
  542.                      Say joylog
  543.                      Parse Pull joydata
  544.                      If joydata = '' Then
  545.                         joydata = 'none'
  546.                      injoy_accts = Strip(injoy_accts joydata)
  547.                   End
  548.                If joyuser = '' Then
  549.                   Do
  550.                      Say 'Enter an user id for InJoy log (enter = none)'
  551.                      Say joylog
  552.                      Say 'and account id -' joydata
  553.                      Parse Pull joydata
  554.                      If joydata = '' Then
  555.                         joydata = 'none'
  556.                      injoy_users = Strip(injoy_users joydata)
  557.                   End
  558.                If joytime = '' Then
  559.                   Do
  560.                      joydata = 'T00000000000000'
  561.                      injoy_times = Strip(injoy_times joydata)
  562.                   End
  563.             End
  564.             Call Write_config
  565.          End
  566.    End
  567. Trace(trace_save)
  568. Return
  569.  
  570. Log_file_parms: Procedure
  571. trace_save = Trace('N')
  572. Parse Arg dialer_ini_name, dialer_ini
  573. Select
  574.    When Translate(dialer_ini_name) = 'DIALER.INI' Then
  575.       Do
  576.          dlog_eparm = 'AdvLog'
  577.          dlog_nparm = 'Cfn'
  578.          dlog_sparm = 'Cfs'
  579.       End
  580.    When Translate(dialer_ini_name) = 'TCPDIAL.INI' Then
  581.       Do
  582.          dlog_eparm = 'Common'
  583.          dlog_nparm = 'LoggingCfn'
  584.          dlog_sparm = 'LoggingCfs'
  585.       End
  586.    Otherwise Do
  587.       Say 'Unable to recognize dialer ini file'
  588.       Call Cleanup
  589.       Exit
  590.    End
  591. End
  592. dialer_log_file = Strip(SysIni(dialer_ini, dlog_eparm, dlog_nparm),,'00'x)
  593. dialer_log_size = C2d(Left(SysIni(dialer_ini, dlog_eparm, dlog_sparm),3))
  594. Trace (trace_save)
  595. Return dialer_log_file dialer_log_size
  596.  
  597. /* Now find all lines in connect.log that contain the key_phrase
  598.    string.  A typical line generated in the connect.log after
  599.    disconnect is either this for a dialer version preceding v. 1.45:
  600.     11/15 19:08:38 Disconnected after 00:06:20  0 errors  0 discards
  601.    or this style for v. 1.45 and later:
  602.     1995/11/15 19:08:38 Disconnected after 00:06:20  0 errors  0 discards
  603.    which we would parse as follows:
  604.     date  word2       word3    word4 connect_time */
  605. Analyze_logfile:
  606. trace_save = Trace('N')
  607.  
  608. Call SysFileSearch key_phrase, log_file, 'line.', 'N'
  609.  
  610. Call SysFileSearch user_phrase, log_file, 'user.', 'N'
  611.  
  612. /* this section will read backwards through the connection log file
  613.    data and attempt to assign account information and userid to each
  614.    connection log record */
  615. k = user.0
  616. Do i = line.0 To 1 By -1 While k > 0
  617.    Parse Var line.i disc_line_no .
  618.    acct_data = 'acctid=unknown userid=unknown'
  619.    j = i - 1
  620.    If j > 0 Then
  621.  
  622.    Parse Var line.j prev_disc_line_no .
  623.    Else
  624.       prev_disc_line_no = 0
  625.    If k > 0 Then
  626.       Do
  627.          Parse Var user.k user_line_no . . acctid userid .
  628.          If disc_line_no > user_line_no & user_line_no > prev_disc_line_no Then
  629.             Do
  630.                acct_data = 'acctid=' || acctid 'userid=' || userid
  631.                k = k - 1
  632.             End
  633.       End
  634.    line.i = line.i acct_data
  635. End
  636.  
  637. rc = 0
  638.  
  639. Do i = 1 To line.0
  640.    Parse Var line.i . date word2 word3 word4 connect_time remainder
  641.    If remainder = '' Then
  642.       Iterate i
  643.    Parse Var remainder . 'acctid=' acctid 'userid=' userid .
  644.    acctid = Strip(acctid)
  645.    userid = Strip(userid)
  646.    /* Date, excluding year if year is or is not present, is 5 chars: mm/dd */
  647.    date2 = Right(date,5)
  648.    /* Make all dates uniform.  If more than mm/dd (5 chars) then year
  649.       is there.  The length(date) - 6 = length of however many
  650.       characters are used for the year (4 now (e.g., 1995) but some
  651.       joker might change it to 2 (e.g., 95) We then add 1 char for the
  652.       / separator + 1 */
  653.    If Length(date) > 5 Then
  654.       year = Substr((date), 1, Length(date) -6 ) || ' '
  655.    Else
  656.       year = '     '    /* If pre v1.45 Dialer, no year, pad 5 spaces */
  657.    /* Extract the month of a connection as a 2-dig number */
  658.    mm = Substr(date2, 1, 2)
  659.    dd = Substr(date2, 4, 2)                         /* ...and the day */
  660.    /* Extract for time stamp and save */
  661.    Parse Var word2 t_hr ':' t_min ':' t_sec
  662.    If year <> '     ' Then
  663.       t_yr = Strip(year)
  664.    Else
  665.       t_yr = '    '
  666.    time_stamp = 'T' || t_yr || mm || dd || t_hr || t_min || t_sec
  667.    /* Extract the number of hours on-line */
  668.    hrs = Substr(connect_time, 1, 2)
  669.    mins = Substr(connect_time, 4, 2)                   /*... and mins */
  670.    secs = Substr(connect_time, 7, 2)                 /*...and seconds */
  671.    If hrs < 0,                                  /* If hrs is negative */
  672.       | mins < 0,                              /* or mins is negative */
  673.       |If secs < 0 Then
  674.       Call Errdst   /* or secs is negative.  Time change error? Abort */
  675.  
  676.    /* Calculate time_on for that connection */
  677.    time_on = (60*hrs + mins + (1/60)*secs)
  678.    If time_stamp > last_time_stamp Then
  679.       Call Monthly_update
  680.  
  681.    If old_d = 0 Then
  682.       Do                            /* for very first connection line */
  683.          old_m = mm
  684.          old_d = dd
  685.          old_y = year
  686.          signons_each_day = 1                           /* reset to 1 */
  687.          signons_each_month = 1
  688.          /* This and next one are timeons in minutes */
  689.          daily_time_on = time_on
  690.          monthly_time_on = time_on
  691.       End
  692.  
  693.    Else         /* continue to accumulate times if same month and day */
  694.       If old_m = mm & old_d = dd & month <> 0 Then
  695.       Do
  696.          old_y = year
  697.          signons_each_day = signons_each_day + 1
  698.          signons_each_month = signons_each_month + 1
  699.          daily_time_on = daily_time_on + time_on
  700.          monthly_time_on = monthly_time_on + time_on
  701.       End
  702.  
  703.    Else                                      /* new day of same month */
  704.       If old_m = mm & old_d <> dd Then
  705.       Do
  706.          Call Prepare_data
  707.          dcounter = dcounter + 1
  708.          year.dcounter = year
  709.          year.mcounter = year
  710.          dayline.dcounter = year.dcounter month.old_m old_d d_signons d_mins d_hhmmss d_hrs
  711.  
  712.          old_d = dd
  713.          old_y = year
  714.          signons_each_day = 1            /* Start counting over again */
  715.          signons_each_month = signons_each_month + 1
  716.          daily_time_on = time_on
  717.          monthly_time_on = monthly_time_on + time_on
  718.       End
  719.  
  720.    Else   /* for any new month, which by definition is also a new day */
  721.       If old_m <> mm & old_m <> 0 Then
  722.       Do
  723.          Call Prepare_data
  724.          dcounter = dcounter + 1
  725.          year.dcounter = old_y
  726.          dayline.dcounter = year.dcounter month.old_m old_d d_signons d_mins d_hhmmss d_hrs
  727.  
  728.          mcounter = mcounter + 1
  729.          year.mcounter = old_y
  730.          monthline.mcounter = year.mcounter month.old_m m_signons m_mins m_hhmmss m_hrs
  731.  
  732.          old_m = mm
  733.          old_d = dd
  734.          old_y = year
  735.          signons_each_day = 1
  736.          signons_each_month = 1
  737.          daily_time_on = time_on
  738.          monthly_time_on = time_on
  739.       End
  740.  
  741. End             /* end of all these If's and Else If's of searching for 
  742.                    key_phrase in all possible lines in the connect.log */
  743.  
  744. /* Now, since last day and last month is done: */
  745. Call Prepare_data
  746. dcounter = dcounter + 1
  747. year.dcounter = year
  748. dayline.dcounter = year.dcounter month.old_m old_d d_signons d_mins d_hhmmss d_hrs
  749.  
  750. mcounter = mcounter + 1
  751. year.mcounter = year
  752. monthline.mcounter = year.mcounter month.old_m m_signons m_mins m_hhmmss m_hrs
  753.  
  754. /* save the last */
  755. ibm_last_time_stamp = time_stamp
  756. Call Write_config
  757. Trace (trace_save)
  758. return                                          /* from Analyze_logfile     */
  759.  
  760. Monthly_update:
  761. s_yr = Strip(t_yr)
  762. s_mo = Strip(mm)
  763. If summary.acctid.userid.s_yr.s_mo <> '' Then
  764.    Do
  765.       Parse Var summary.acctid.userid.s_yr.s_mo s_yr s_mo s_stamp s_sess s_min .
  766.       If time_stamp > s_stamp Then
  767.          Do
  768.             s_sess = s_sess + 1
  769.             s_min = s_min + time_on
  770.             summary.acctid.userid.s_yr.s_mo = s_yr s_mo time_stamp s_sess s_min
  771.          End
  772.    End
  773. Else
  774.    Do
  775.       x = monthly.0 + 1
  776.       monthly.x = acctid userid s_yr s_mo
  777.       monthly.0 = x
  778.       summary.acctid.userid.s_yr.s_mo = s_yr s_mo time_stamp '1' time_on
  779.    End
  780. Return
  781.  
  782. Outputter:
  783. /* Now output everything to console and to file */
  784.  
  785. /* get the screen size; rows is what we are interested in */
  786. Parse Value SysTextScreenSize() With rows cols
  787. Call Stream stdin, 'C', 'OPEN READ'
  788. /* Tell us all */
  789. intro = what_r_we
  790. Call Say_out intro
  791. If otherparms <> '' Then
  792.    Do
  793.       Call Say_out crlf || 'Running with parms =' otherparms
  794.       Call Lineout output_file crlf || 'Running with parms =' otherparms
  795.    End
  796. Call Lineout output_file, intro
  797. intro = crlf || 'Analysis of' log_file '(' || Date() '@' Time() || ')'
  798. Call Say_out intro
  799. Call Lineout output_file, intro
  800. If daily_report Then
  801.    Call Say_out crlf || daily totals
  802. Call Lineout output_file, crlf || daily totals
  803. Do j = 1 To dcounter
  804.    If daily_report Then
  805.       Call Say_out dayline.j
  806.    Call Lineout output_file, dayline.j
  807.    If one_screen_at_a_time & daily_report & \quiet & \pmrexx then            
  808.    If (j - rows + 6) // (rows - 5) = 0 Then
  809.       answer = Say_message('               Press any key to continue...')
  810. End
  811.  
  812. If one_screen_at_a_time & daily_report & \quiet & \pmrexx then            
  813. If (j - rows + 6) // (rows - 5) > 5 Then
  814.    Do                                   /* If at about 5 lines to end */
  815.       answer = Say_message('   Daily Totals done, press any key for Monthlies...')
  816.       /* If decision is to do a 'Press-Any-Key to continue', reset to 0 */
  817.       j = 0
  818.    End
  819. If \ daily_report Then
  820.    j = 0
  821.  
  822. /* back up the summary file and delete it */
  823. If RxFileExists(summary_file) Then
  824.    Do
  825.       Parse Var summary_file fname '.' ext
  826.       Address cmd '@COPY' summary_file fname || '.bak > NUL'
  827.       Call SysFileDelete summary_file
  828.    End
  829. rc = File_cmd(summary_file,'W')
  830. acct_user_save = ''
  831.  
  832. Call RxSort 'monthly.', 'A'                  /* sort the summary data */
  833.  
  834. Call Summary_sample                     /* get the header information */
  835. /* insert the header info into the summary data */
  836. Do k = summary_sample.0 To 1 By -1
  837.    Call RxStemInsert 'monthly.', 1, summary_sample.k
  838. End
  839.  
  840. Do k = 1 To monthly.0
  841.    If Abbrev(monthly.k,'*') Then
  842.       Do                                   /* write comments back out */
  843.          Call Lineout summary_file, monthly.k
  844.          Iterate k
  845.       End
  846.    Parse Var monthly.k acctid userid s_yr s_mo
  847.    acct_user = acctid userid
  848.    Call Lineout summary_file, acctid userid '*' summary.acctid.userid.s_yr.s_mo
  849.    Parse Var summary.acctid.userid.s_yr.s_mo . . . s_sess s_mins
  850.    m_sess = Format(s_sess, sig_x) || 'X'
  851.    m_mins = Format(s_mins, sig_min, 2) 'mins'
  852.    mo_hh = Format(Trunc(s_mins / 60),sig_hr)
  853.    mo_mm = Right(Trunc(s_mins // 60),2,'0')
  854.    mo_ss = Right(Trunc(60 * ((s_mins // 60) - Trunc(s_mins // 60))),2,'0')
  855.    m_hhmmss = '  '||mo_hh||':'||mo_mm||':'||mo_ss
  856.    m_hrs = Format((s_mins / 60), sig_hr, 2) 'hrs'
  857.    a_sess = s_mins / s_sess
  858.    If a_sess < 60 Then
  859.       a_sess = Format(a_sess,2,0) 'mins'
  860.    Else
  861.       a_sess = Format((a_sess / 60),2,2) 'hrs'
  862.    a_sess = '- Ave =' a_sess
  863.    monthline = s_yr month.s_mo m_sess m_mins m_hhmmss m_hrs a_sess
  864.    If acct_user <> acct_user_save Then
  865.       Do
  866.          intro = crlf || 'MONTHLY TOTALS for Account(' || acctid || ') Userid(' || userid || ')'
  867.          Call Say_out intro
  868.          Call Lineout output_file, intro
  869.          acct_user_save = acct_user
  870.       End
  871.    Call Lineout output_file, monthline
  872.    monthline = s_yr month.s_mo m_sess m_hrs a_sess
  873.    Call Say_out monthline
  874.    If one_screen_at_a_time & \quiet & \pmrexx Then
  875.       If (k + j - rows + 6) // (rows - 6) = 0 Then
  876.       answer = Say_message('               Press any key to continue...')
  877. End
  878. rc = File_cmd(summary_file,'C')
  879. finished = crlf || 'End of analysis of' log_file
  880. Call Say_out finished
  881. Call Lineout output_file, finished
  882.  
  883. rc = SysFileTree(dialer_log_file, 'info.', 'F')
  884. Parse Var info.1 . . log_file_size .
  885. If dialer_log_size > 0 Then
  886.    Do
  887.       log_file_pct = Format((log_file_size / dialer_log_size) * 100,,0)
  888.       Call Say_out ''
  889.       Call Say_out 'The connection log file is at' log_file_pct || '% of the maximum'
  890.       Call Say_out 'size,' Format(dialer_log_size,,0) 'bytes, specified in the Dialer settings.'
  891.       If log_file_pct > warn_pct Then
  892.          Do
  893.             Call Say_out ''
  894.             Call Say_out 'You may want to consider running editing the'
  895.             Call Say_out dialer_log_file 'with the IBM tedit.exe'
  896.             Call Say_out ''
  897.          End
  898.    End
  899.  
  900. Return                                              /* from Outputter */
  901.  
  902. Combined_output:
  903. /* Combine output from IGN and InJoy and display */
  904.  
  905. If \injoy_dialer Then
  906.    Return
  907. If quiet Then
  908.    Return
  909.  
  910. ign. = ''
  911. ign.0 = 0
  912. If ibm_dialer Then
  913.    Do
  914.       /* read the IBM dialer summary log */
  915.       If RxFileExists(summary_file) Then
  916.          Do
  917.             Call RxRead 'data.', summary_file
  918.             Do x = 1 To data.0
  919.                If \Abbrev(data.x,'*') & data.x <> '' Then
  920.                   Do
  921.                      Parse Var data.x acctid userid '*' s_yr s_mo s_time s_data
  922.                      i = ign.0 + 1
  923.                      ign.i = Space(acctid userid s_yr s_mo s_data)
  924.                      ign.0 = i
  925.                   End
  926.             End
  927.          End
  928.    End
  929. i = ign.0 + 1                           /* make an end of file record */
  930. ign.i = Copies('FF'x, 8) Copies('FF'x, 8) Copies('FF'x, 4) 'FFFF'x
  931. ign.0 = i
  932.  
  933. joy. = ''
  934. joy.0 = 0
  935. /* read the InJoy dialer summary file */
  936. If RxFileExists(injoy_summary) Then
  937.    Do
  938.       Call RxRead 'data.', injoy_summary
  939.       Do x = 1 To data.0
  940.          If \Abbrev(data.x,'*') & data.x <> '' Then
  941.             Do
  942.                Parse Var data.x acctid userid '*' s_yr s_mo s_time s_data
  943.                acctid = Strip(acctid)
  944.                userid = Strip(userid)
  945.                s_yr = Strip(s_yr)
  946.                s_mo = Strip(s_mo)
  947.                i = joy.0 + 1
  948.                joy.i = Space(acctid userid s_yr s_mo s_data)
  949.                joy.0 = i
  950.             End
  951.       End
  952.    End
  953. i = joy.0 + 1                           /* make an end of file record */
  954. joy.i = Copies('FF'x, 8) Copies('FF'x, 8) Copies('FF'x, 4) 'FFFF'x
  955. joy.0 = i
  956.  
  957. combined. = ''
  958. combined.0 = 0
  959. i = 1
  960. j = 1
  961. Do While (i < ign.0) | (j < joy.0)
  962.    Parse Var ign.i i_acctid i_userid i_s_yr i_s_mo i_sess i_min
  963.    i_value = i_acctid || i_userid || i_s_yr || i_s_mo
  964.    Parse Var joy.j j_acctid j_userid j_s_yr j_s_mo j_sess j_min
  965.    j_value = j_acctid || j_userid || j_s_yr || j_s_mo
  966.    Select
  967.       When i_value = j_value Then
  968.          Do
  969.             t_sess = i_sess + j_sess
  970.             t_min = i_min + j_min
  971.             k = combined.0 + 1
  972.             combined.k = i_acctid i_userid i_s_yr i_s_mo t_sess t_min
  973.             combined.0 = k
  974.             i = i + 1
  975.             j = j + 1
  976.          End
  977.       When i_value < j_value Then
  978.          Do
  979.             k = combined.0 + 1
  980.             combined.k = i_acctid i_userid i_s_yr i_s_mo i_sess i_min
  981.             combined.0 = k
  982.             i = i + 1
  983.          End
  984.       When i_value > j_value Then
  985.          Do
  986.             k = combined.0 + 1
  987.             combined.k = j_acctid j_userid j_s_yr j_s_mo j_sess j_min
  988.             combined.0 = k
  989.             j = j + 1
  990.          End
  991.       Otherwise Nop
  992.    End
  993. End
  994.  
  995. acct_user_save = ''
  996. intro = what_r_we
  997. Call Say_out intro
  998. If otherparms <> '' Then
  999.    Do
  1000.       Call Say_out crlf || 'Running with parms =' otherparms
  1001.    End
  1002. intro = crlf || 'Analysis of combined IGN and InJoy log files (' || Date() '@' Time() || ')'
  1003. Call Say_out intro
  1004. Do k = 1 To combined.0
  1005.    If Abbrev(combined.k,'*') Then
  1006.       Iterate
  1007.    Parse Var combined.k acctid userid s_yr s_mo s_sess s_mins
  1008.    acct_user = acctid userid
  1009.    m_sess = Format(s_sess, sig_x) || 'X'
  1010.    m_mins = Format(s_mins, sig_min, 2) 'mins'
  1011.    mo_hh = Format(Trunc(s_mins / 60),sig_hr)
  1012.    mo_mm = Right(Trunc(s_mins // 60),2,'0')
  1013.    mo_ss = Right(Trunc(60 * ((s_mins // 60) - Trunc(s_mins // 60))),2,'0')
  1014.    m_hhmmss = '  ' || mo_hh || ':' || mo_mm || ':' || mo_ss
  1015.    m_hrs = Format((s_mins / 60), sig_hr, 2) 'hrs'
  1016.    a_sess = s_mins / s_sess
  1017.    If a_sess < 60 Then
  1018.       a_sess = Format(a_sess,2,0) 'mins'
  1019.    Else
  1020.       a_sess = Format((a_sess / 60),2,2) 'hrs'
  1021.    a_sess = '- Ave =' a_sess
  1022.    monthline = s_yr month.s_mo m_sess m_hrs a_sess
  1023.    If acct_user <> acct_user_save Then
  1024.       Do
  1025.          intro = crlf || 'MONTHLY TOTALS for Account(' || acctid || ') Userid(' || userid || '}'
  1026.          Call Say_out intro
  1027.          acct_user_save = acct_user
  1028.       End
  1029.    Call Say_out monthline
  1030.    If one_screen_at_a_time & \quiet &\pmrexx Then
  1031.       If (k + j - rows + 6) // (rows - 6) = 0 Then
  1032.       answer = Say_message('               Press any key to continue...')
  1033. End
  1034. rc = File_cmd(summary_file,'C')
  1035. finished = crlf || 'End of analysis of combined log files'
  1036. Call Say_out finished
  1037. Return                                         /* from Combine_output */
  1038.  
  1039. Prepare_data:
  1040. /* Calculates and formats what is to be put into an output line */
  1041.  
  1042. /* Signons per day or month, as, e.g.: '4X' */
  1043. d_signons = Format(signons_each_day, sig_x)||'X'
  1044. m_signons = Format(signons_each_month, sig_x)||'X'
  1045.  
  1046. /* Minutes/day, minutes/month, hrs/day, hrs/month as, e.g.: '105.50 mins or hrs' */
  1047. d_mins = Format(daily_time_on, sig_min, 2) 'mins'
  1048. d_hrs = Format((daily_time_on/60), sig_hr, 2) 'hrs'
  1049. m_mins = Format(monthly_time_on, sig_min, 2) 'mins'
  1050. m_hrs = Format((monthly_time_on/60), sig_hr, 2) 'hrs'
  1051.  
  1052. /* minutes, seconds per day or month, as 2-digit numbers; hrs can exceed 2 digs */
  1053. dy_hh = Format(Trunc(daily_time_on/60),sig_hr)            
  1054. dy_mm = Right(Trunc(daily_time_on//60),2,'0')
  1055. dy_ss = Right(Trunc(60*((daily_time_on//60) - Trunc(daily_time_on//60))),2,'0')
  1056. mo_hh = Format(Trunc(monthly_time_on/60),sig_hr)
  1057. mo_mm = Right(Trunc(monthly_time_on//60),2,'0')
  1058. mo_ss = Right(Trunc(60*((monthly_time_on//60) - Trunc(monthly_time_on//60))),2,'0')
  1059.  
  1060. /* hours, minutes, seconds per day or month, as, e.g.: '1:45:30'*/
  1061. d_hhmmss = '  '||dy_hh||':'||dy_mm||':'||dy_ss
  1062. m_hhmmss = '  '||mo_hh||':'||mo_mm||':'||mo_ss
  1063.  
  1064. Return                                                /* Prepare_data */
  1065.  
  1066. Errdst:                                /* If error due to time change */
  1067. Say 'INETLOG has found a negative number for time-on-line'
  1068. Say 'in an entry in your' log_file 'file.'
  1069. Say ''
  1070. Say 'You may have reset your clock backwards while on line, e.g.,'
  1071. Say 'while changing from Summer time (Daylight Saving Time) to'
  1072. Say 'Winter time (Standard time).'
  1073. Say ''
  1074. Say 'To fix:'
  1075. Say '   1.  Open' log_file 'in your Tiny Editor (tedit.exe)'
  1076. Say '   2.  Edit any connection time(s) that have a minus sign.'
  1077. Say '       Example (for a typical one-hour summer-to-winter time correction):'
  1078. Say ''
  1079. Say '       change'
  1080. Say '          1995/10/29 06:26:43 Disconnected after -00:-58:-4  0 errors  0 discards'
  1081. Say '             to'
  1082. Say '          1995/10/29 06:26:43 Disconnected after 00:01:56  0 errors  0 discards'
  1083. Say ''
  1084. Say '       If the error was not from a summer-time change, make whatever'
  1085. Say '       correction seems reasonable to eliminate the offending minus'
  1086. Say '       signs (like just removing them).'
  1087. Say ''
  1088. Say '   3.  Save' log_file
  1089. Say '   4.  Run EOF2CRLF to remove the EOF characters'
  1090. Say '       added by the editor.'
  1091. Say 'Aborting . . .'
  1092. Call Cleanup
  1093. Return
  1094.  
  1095. Errhandler:
  1096. Call Beep 300, 500
  1097. Say 'Rexx error' rc 'in line' sigl||':' Errortext(rc)
  1098. Say Sourceline(sigl)
  1099. Call Cleanup
  1100. Return
  1101.  
  1102. Cleanup:                                                      /* Exit */
  1103. If \quiet & \pmrexx Then
  1104.    answer = Say_message('Press any key to exit...')
  1105. Else
  1106.    Call SysSleep 2
  1107. save_path = Directory(save_path)
  1108. Exit
  1109. Return                                                 /* for Cleanup */
  1110.  
  1111. Set_monthly_summary:                           /* set monthly summary */
  1112. trace_save = Trace('N')
  1113. monthly. = ''
  1114. monthly.0 = 0
  1115. summary. = ''
  1116. s_time = 'T00000000000000'
  1117. If RxFileExists(summary_file) Then
  1118.    Do
  1119.       Call RxRead 'data.', summary_file
  1120.       Do i = 1 To data.0
  1121.          If \ Abbrev(data.i,'*') & data.i <> '' Then
  1122.             Do
  1123.                Parse Var data.i acctid userid '*' s_yr s_mo s_time s_data
  1124.                If s_yr = '' Then
  1125.                   Do
  1126.                      acctid = 'unknown'
  1127.                      userid = 'unknown'
  1128.                      Parse Var data.i s_yr s_mo s_data
  1129.                   End
  1130.                acctid = Strip(acctid)
  1131.                userid = Strip(userid)
  1132.                s_yr = Strip(s_yr)
  1133.                s_mo = Strip(s_mo)
  1134.                j = monthly.0 + 1
  1135.                monthly.j = acctid userid s_yr s_mo
  1136.                monthly.0 = j
  1137.                summary.acctid.userid.s_yr.s_mo = s_yr s_mo s_time s_data
  1138.             End
  1139.       End
  1140.       Call RxSort 'monthly.0', 'A'
  1141.    End
  1142. Else
  1143.    s_time = 'T00000000000000'       /* reset timestamp to get updates */
  1144.  
  1145. last_time_stamp = s_time
  1146. Trace (trace_save)
  1147. Return                                         /* Set_monthly_summary */
  1148.  
  1149. /* performs common Stream commands and returns 1 or a date if successful */
  1150. File_cmd: Procedure Expose result
  1151. trace_save = Trace('N')
  1152. Trace 'N'
  1153. Parse Arg file_name, command
  1154. command = Translate(command)
  1155. Select
  1156.    When command = 'X' Then
  1157.       Do
  1158.          result = Stream(file_name, 'C', 'QUERY EXISTS')
  1159.          answer = (result <> '')
  1160.       End
  1161.    When command = 'C' Then
  1162.       Do
  1163.          result = Stream(file_name, 'C', 'CLOSE')
  1164.          answer = Abbrev(result,'READY') | (result = '')
  1165.       End
  1166.    When command = 'W' Then
  1167.       Do
  1168.          result = Stream(file_name, 'C', 'OPEN WRITE')
  1169.          answer = Abbrev(result,'READY')
  1170.       End
  1171.    When command = 'R' Then
  1172.       Do
  1173.          result = Stream(file_name, 'C', 'OPEN READ')
  1174.          answer = Abbrev(result,'READY')
  1175.       End
  1176.    When command = 'D' Then
  1177.       Do
  1178.          result = Stream(file_name, 'C', 'QUERY DATETIME')
  1179.          If result <> '' Then
  1180.             Do
  1181.                Parse Var result date time
  1182.                date = Dateconv(Translate(date, '/', '-'), 'U', 'S')
  1183.                Parse Var time hr ':' min ':' sec
  1184.                answer = Strip(date) || Strip(hr) || Strip(min) || Strip(sec)
  1185.             End
  1186.          Else
  1187.             answer = '00000000000000'
  1188.       End
  1189.    Otherwise answer = 0
  1190. End
  1191. Trace (trace_save)
  1192. Return answer
  1193.  
  1194. Say_out:                             /* performs output to the screen */
  1195. Procedure Expose quiet
  1196. trace_save = Trace('N')
  1197. If quiet Then
  1198.    Return
  1199. Parse Arg line
  1200. Say line
  1201. Trace (trace_save)
  1202. Return
  1203.  
  1204. Say_message:       /* performs message output and returns key entered */
  1205. Procedure Expose quiet
  1206. trace_save = Trace('N')
  1207. Parse Arg msg
  1208. Say msg
  1209. answer = SysGetKey('NOECHO')
  1210. Trace (trace_save)
  1211. Return answer
  1212.  
  1213. Summary_sample: Procedure Expose summary_sample.
  1214. trace_save = Trace('N')
  1215. Trace 'N'
  1216. data_queue = INetSmp('summary')
  1217. old_queue = Rxqueue('Set', data_queue)
  1218. summary_sample.0 = Queued()
  1219. Do i = 1 To summary_sample.0
  1220.    Parse Pull summary_sample.i
  1221. End
  1222. rx_queue = Rxqueue('Delete', data_queue)
  1223. Trace(trace_save)
  1224. Return
  1225.