'STGEN.BAS  -  USRSTATS generic door
'Version 1.08  12/30/95
'Written by Joseph C. Frankiewicz

'For QuickBASIC 4.5

'Released to the public domain.

'Retrieve and display modem's on-line status reports

'requires:
'Companion program USRSTAT2.EXE
'US Robotics Courier/Sportster high-speed modems that support
'the  I6/Y6, I7, I11, and Y11 commands.

'modem init string can be modified to ATZ^M~~~AT&D1
'to use DTR switching, but modem will not store &D in NVRAM.

'install in it's own directory as a standard DOOR, no .SYS files
'used or needed.

'multi-node aware if node # is passed properly by the calling batch file

'-----------------------------------------------------------------------
 'Externs for QBSerial library, version 3.20

 DECLARE SUB OpenComm CDECL ALIAS "_open_comm" (BYVAL Port%, IRQ%, BYVAL Wlen%, BYVAL Parity%, BYVAL Bits%, BYVAL Baud&, BYVAL HS%, BYVAL FOSSIL%)
 DECLARE SUB CloseComm CDECL ALIAS "_close_comm" ()
 DECLARE FUNCTION WriteChar% CDECL (BYVAL c%)
 DECLARE FUNCTION ReadChar% CDECL ()
 DECLARE SUB transmit CDECL ALIAS "_transmit_string" (addr$)
 DECLARE FUNCTION DataWaiting% CDECL ALIAS "_data_waiting" ()
 DECLARE SUB ClearInputBuffer CDECL ALIAS "_clear_input_buffer" ()
 DECLARE SUB CarrierDetect CDECL ALIAS "_carrier_detect_flag" (BYVAL OnOff%)
 DECLARE FUNCTION CarrierLost% CDECL ALIAS "_carrier_state" ()
 DECLARE FUNCTION DriverCopyright% CDECL ()
 DECLARE SUB DTRcontrol CDECL ALIAS "_dtr" (BYVAL OnOff%)
 DECLARE SUB RTScontrol CDECL ALIAS "_rts" (BYVAL Onff%)
 DECLARE FUNCTION ModemStatus% CDECL ALIAS "_inputstatus" ()
 DECLARE SUB BREAKcontrol CDECL ALIAS "_break_state" (BYVAL state%)

'==========================================================================
'constants

 crlf$ = CHR$(&HD) + CHR$(&HA)

 tempfilepath$ = ENVIRON$("STGTMP")

'==========================================================================
'start of main code

 'catch-all error handler
 ON ERROR GOTO bombout

 LOCATE , , 1

 PRINT
 PRINT
 PRINT "STGEN (USRSTATS GENERIC) Version 1.08, 12/30/95"
 PRINT "Written by Joseph C. Frankiewicz"
 PRINT

'-----------------------------------------------
'parse command line

'command line parms:
' port : irq (0=default) :  node :  esc char (256=dtr)  : fossil  :  filename (optional)

 x$ = COMMAND$

 IF x$ = "" THEN

   PRINT "Usage is:"
   PRINT
   PRINT "STGEN <port> <irq> <node> <esc char> <fossil> <logfile> </Mx> </NOXMIT>"
   PRINT
   PRINT "        PORT: comm or FOSSIL port number, or DECIMAL base address"
   PRINT "         IRQ: 1-15, or 0 for default"
   PRINT "        NODE: BBS node number, or 0 if single-node"
   PRINT "    ESC CHAR: 0-127 matching modem S2 register, or 256=DTR toggle"
   PRINT "      FOSSIL: 0=no FOSSIL, 1=use FOSSIL"
   PRINT "     LOGFILE: optional, name of report history file"
   PRINT "         /Mx: optional, x=video mode passed to USRSTAT2.EXE"
   PRINT "     /NOXMIT: optional, use when running from a comm program instead of BBS"
   PRINT
   PRINT "      STGTMP: optional environment variable, path for temporary files, with \"
   PRINT "STGINTRO.TXT: optional file to display in door mode"
   PRINT " STGEXIT.TXT: optional file to display in door mode"
   PRINT
   GOTO bombout
 END IF

 'pick off command line options from left to right

 'add /NOXMIT at end of line, and nothing will
 'be sent out serial port.  This will allow CALLERS to use it also.

 callermode% = 0
 IF RIGHT$(x$, 7) = "/NOXMIT" THEN
    'chop that off
    x$ = LEFT$(x$, LEN(x$) - 7)
    'and set flag
    callermode% = 1
 END IF


 'set video mode, default=6

 videomode$ = "6"
 pointer = INSTR(x$, "/M")
 IF pointer > 0 THEN
    videomode$ = MID$(x$, pointer + 2, 1)
    MID$(x$, pointer, 3) = "   "
 END IF


 'now process the rest

 x$ = LTRIM$(RTRIM$(x$))
 temp$ = ""
 WHILE LEFT$(x$, 1) <> " " AND LEN(x$) > 0
 temp$ = temp$ + LEFT$(x$, 1)
    x$ = RIGHT$(x$, LEN(x$) - 1)
 WEND

 comport% = VAL(temp$)

 x$ = LTRIM$(x$)
 temp$ = ""
 WHILE LEFT$(x$, 1) <> " " AND LEN(x$) > 0
    temp$ = temp$ + LEFT$(x$, 1)
    x$ = RIGHT$(x$, LEN(x$) - 1)
 WEND

 comirq% = VAL(temp$)

 x$ = LTRIM$(x$)
 temp$ = ""
 WHILE LEFT$(x$, 1) <> " " AND LEN(x$) > 0
    temp$ = temp$ + LEFT$(x$, 1)
    x$ = RIGHT$(x$, LEN(x$) - 1)
 WEND

 bbsnode% = VAL(temp$)

 x$ = LTRIM$(x$)
 temp$ = ""
 WHILE LEFT$(x$, 1) <> " " AND LEN(x$) > 0
    temp$ = temp$ + LEFT$(x$, 1)
    x$ = RIGHT$(x$, LEN(x$) - 1)
 WEND

 escchar% = VAL(temp$)

 x$ = LTRIM$(x$)
 temp$ = ""
 WHILE LEFT$(x$, 1) <> " " AND LEN(x$) > 0
    temp$ = temp$ + LEFT$(x$, 1)
    x$ = RIGHT$(x$, LEN(x$) - 1)
 WEND

 usefossil% = VAL(temp$)

 logfile$ = LTRIM$(RTRIM$(x$))


 PRINT "PORT="; comport%; " IRQ="; comirq%; "NODE="; bbsnode%; "ESC CHAR="; escchar%; "FOSSIL="; usefossil%; " VIDEO= "; videomode$
 PRINT "LOGFILE= "; logfile$
 PRINT "STGTMP= "; tempfilepath$
 PRINT

 'open the port using default speed, 8 bits, no parity,
 'default baud rate, no flow control

 OpenComm comport%, comirq%, 8, 0, 1, 0, 0, usefossil%


 'turn off carrier detect checking
 CarrierDetect 0

 'check for local logon
 IF CarrierLost THEN
    PRINT "No carrier detected, STGEN cannot run."
    PRINT
    GOTO bombout
 END IF


'if in door mode, and if file STGINTRO.TXT is present, display it and wait for keypress

 IF callermode% = 0 THEN

    ON ERROR GOTO nointrofile

    OPEN "STGINTRO.TXT" FOR INPUT AS #1

    WHILE NOT EOF(1)
       LINE INPUT #1, x$
       PRINT x$
       transmit x$
       transmit crlf$
    WEND

    CLOSE #1

    PRINT
    PRINT "Press any key to continue...";

    transmit crlf$
    transmit "Press any key to continue..."

    zzz = TIMER + 300
    WHILE DataWaiting% = 0 AND INKEY$ = "" AND TIMER < zzz
       IF CarrierLost THEN GOTO bombout
    WEND

    ClearInputBuffer
    transmit crlf$
    PRINT

nointrofileb:

    CLOSE

    ON ERROR GOTO bombout

 END IF



'=========================

 IF callermode% = 0 THEN
    transmit crlf$
    transmit "Please wait, retrieving status info from modem..."
    'note no carriage return!
 END IF


 PRINT "Please wait, retrieving status info from modem..."
 PRINT
'=========================================================

 'delete any old TMPA and TMPB files if present

 'this is a kludge because QB has no EXIST function

 OPEN tempfilepath$ + "tmpa" + LTRIM$(RTRIM$(STR$(bbsnode%))) FOR OUTPUT AS #1
 CLOSE #1
 KILL tempfilepath$ + "tmpa" + LTRIM$(RTRIM$(STR$(bbsnode%)))

 OPEN tempfilepath$ + "tmpb" + LTRIM$(RTRIM$(STR$(bbsnode%))) FOR OUTPUT AS #1
 CLOSE #1
 KILL tempfilepath$ + "tmpb" + LTRIM$(RTRIM$(STR$(bbsnode%)))

 '==========================================================

 'open the temp  file with unique name for any node,
 'put in the current directory.
 'open the file in overwrite mode

 OPEN tempfilepath$ + "tmpa" + LTRIM$(RTRIM$(STR$(bbsnode%))) FOR OUTPUT AS #1

 '--------------------------------
 'get the modem into command mode

 IF escchar% = 256 THEN
    'since the modem is set to &D1, dropping the DTR lead
    'here will cause it to go into on-line command mode,
    'where we can issue our diagnostic commands

    'drop dtr
    DTRcontrol 0

    'wait a sec for the modem to go into command mode
    zzz = TIMER + .6
    WHILE TIMER < zzz
    WEND

    'turn dtr back on
    DTRcontrol 1

    'wait a bit so the modem sees DTR
    zzz = TIMER + .6
    WHILE TIMER < zzz
    WEND

 END IF

 IF escchar% < 256 THEN

    temp$ = CHR$(escchar%) + CHR$(escchar%) + CHR$(escchar%)

    zzz = TIMER + 1.7
    WHILE TIMER < zzz
    WEND
    transmit temp$
    zzz = TIMER + 1.7
    WHILE TIMER < zzz
    WEND
 END IF

 'if CD is gone then modem is misconfigured

 IF CarrierLost THEN
    PRINT "Modem is incorrectly configured!"
    PRINT
    GOTO bombout
 END IF

'===================================================

 'see if I'm really in command mode by sending an AT
 'and looking for OK or 0 response
 'if not in command mode, abort

 transmit "AT" + crlf$

 zzz = TIMER + .6
 WHILE TIMER < zzz
 WEND

 'now loop, grabbing chars and saving in string until no more come in

 atcheck$ = ""

 WHILE DataWaiting%
    atcheck$ = atcheck$ + CHR$(ReadChar%)
 WEND


 IF INSTR(atcheck$, "OK") = 0 AND INSTR(atcheck$, "0") = 0 THEN
    'send ato just in case
    transmit "ATO" + crlf$
    SLEEP 1
    ClearInputBuffer

    IF callermode% = 0 THEN

       transmit crlf$
       transmit "STGEN cannot get modem into command mode!"
       transmit crlf$

    END IF

    PRINT
    PRINT "STGEN cannot get modem into command mode!"
    PRINT
    GOTO bombout

 END IF


 ClearInputBuffer


 transmit "ATI11Y11" + crlf$
 GOSUB mdmtodisk


 transmit "ATI6I7O" + crlf$
 GOSUB mdmtodisk

'close the input file

 CLOSE #1


 'if not using DTR switching, send 3 backspaces
 IF escchar% <> 256 THEN
    transmit CHR$(8)
    transmit CHR$(8)
    transmit CHR$(8)
 END IF


 'now shell out to USRSTAT2 program to do the dirty work

 '-------------------------------------------------------------------------

 'use this one for USRSTAT2.EXE V3.xx
 'SHELL "USRSTAT2.EXE " + tempfilepath$ + "tmpa" + LTRIM$(RTRIM$(STR$(bbsnode%))) + " " + tempfilepath$ + "tmpb" + LTRIM$(RTRIM$(STR$(bbsnode%))) + " 0"

 'use this one for USRSTAT2.EXE V4.xx

 SHELL "USRSTAT2.EXE " + tempfilepath$ + "tmpa" + LTRIM$(RTRIM$(STR$(bbsnode%))) + " " + tempfilepath$ + "tmpb" + LTRIM$(RTRIM$(STR$(bbsnode%))) + " 0 /M" + videomode$ + " /P3"

 '-------------------------------------------------------------------------

 'empty the RX buffer just in case

 ClearInputBuffer

 'display the file
 'if return file does not exist then error handler will catch it


 'this crlf ends the PLEASE WAIT... message on caller's screen
 IF callermode% = 0 THEN
    transmit crlf$
 END IF

 OPEN tempfilepath$ + "tmpb" + LTRIM$(RTRIM$(STR$(bbsnode%))) FOR INPUT AS #1

 'append to history file also
 IF logfile$ <> "" THEN OPEN logfile$ FOR APPEND AS #2

 OPEN "CONS:" FOR OUTPUT AS #3

 WHILE NOT EOF(1)
    LINE INPUT #1, x$

    IF INSTR(x$, "MORE:") < 1 THEN

       PRINT #3, x$

       IF logfile$ <> "" THEN PRINT #2, x$
       IF callermode% = 0 THEN
          transmit x$
          transmit crlf$
       END IF
    END IF

    IF INSTR(x$, "MORE:") > 0 THEN
       PRINT
       PRINT "Press any key to continue...";

       IF callermode% = 0 THEN
          transmit "Press any key to continue..."
       END IF

       zzz = TIMER + 300
       WHILE DataWaiting% = 0 AND INKEY$ = "" AND TIMER < zzz
          IF CarrierLost THEN GOTO bombout
       WEND

       ClearInputBuffer
       IF callermode% = 0 THEN
          transmit crlf$
       END IF

       PRINT

    END IF

 WEND

 CLOSE #1

 CLOSE #3

 IF logfile$ <> "" THEN CLOSE #2
 PRINT
 PRINT "Press any key to continue...";

 IF callermode% = 0 THEN
    transmit "Press any key to continue..."
 END IF

 zzz = TIMER + 300
 WHILE DataWaiting% = 0 AND INKEY$ = "" AND TIMER < zzz
    IF CarrierLost THEN GOTO bombout
 WEND

 ClearInputBuffer
 IF callermode% = 0 THEN
    transmit crlf$
 END IF

 PRINT

 'check for forced modem retrain

 PRINT "Force modem retrain? (NO/yes) ";

 IF callermode% = 0 THEN
    transmit "Force modem retrain? (NO/yes) "
 END IF

 zzz = TIMER + 300
 yn$ = ""
 WHILE DataWaiting% = 0 AND yn$ = "" AND TIMER < zzz
    IF CarrierLost THEN GOTO bombout
    yn$ = INKEY$
 WEND

 IF DataWaiting% <> 0 THEN
    yn$ = CHR$(ReadChar%)
 END IF

 yn$ = UCASE$(yn$)

 PRINT

 IF callermode% = 0 THEN
    transmit crlf$
 END IF

 IF yn$ = "Y" THEN

    '--------------------------------
    'get the modem into command mode

    IF escchar% = 256 THEN
       'since the modem is set to &D1, dropping the DTR lead
       'here will cause it to go into on-line command mode,
       'where we can issue our diagnostic commands

       'drop dtr
       DTRcontrol 0

       'wait a sec for the modem to go into command mode
       zzz = TIMER + .5
       WHILE TIMER < zzz
       WEND

       'turn dtr back on
       DTRcontrol 1

       'wait a bit so the modem sees DTR
       zzz = TIMER + .3
       WHILE TIMER < zzz
       WEND

    END IF

    IF escchar% < 256 THEN

       temp$ = CHR$(escchar%) + CHR$(escchar%) + CHR$(escchar%)

       zzz = TIMER + 1.7
       WHILE TIMER < zzz
       WEND
       transmit temp$
       'wait for ok instead?
       zzz = TIMER + 1.7
       WHILE TIMER < zzz
       WEND
    END IF

    'if CD is gone then modem is misconfigured

    IF CarrierLost THEN
       PRINT "Modem is incorrectly configured!"
       PRINT
       GOTO bombout
    END IF

   '===================================================

    'see if im really in command mode by sending an AT
    'and looking for OK or 0 response
    'if not in command mode, abort

    transmit "AT" + crlf$

    zzz = TIMER + .6
    WHILE TIMER < zzz
    WEND

    'now loop, grabbing chars and saving in string until no more come in

    atcheck$ = ""

    WHILE DataWaiting%
       atcheck$ = atcheck$ + CHR$(ReadChar%)
    WEND


    IF INSTR(atcheck$, "OK") = 0 AND INSTR(atcheck$, "0") = 0 THEN
       'send ato just in case
       transmit "ATO" + crlf$
       zzz = TIMER + 3
       WHILE TIMER < zzz
       WEND

       ClearInputBuffer

       IF callermode% = 0 THEN

          transmit crlf$
          transmit "STGEN cannot get modem into command mode!"
          transmit crlf$

       END IF

       PRINT
       PRINT "STGEN cannot get modem into command mode!"
       PRINT
       GOTO bombout

    END IF


    ClearInputBuffer

    'issue ato1 to modem
    transmit "ATO1" + crlf$


    'wait 3 sec for the modem to process the command

    zzz = TIMER + 3
    WHILE TIMER < zzz
    WEND


    'flush RX buffer
    ClearInputBuffer

 END IF


'if in door mode, and if file STGINTRO.TXT is present, display it and wait for keypress

 IF callermode% = 0 THEN

    ON ERROR GOTO noexitfile

    OPEN "STGEXIT.TXT" FOR INPUT AS #1

    WHILE NOT EOF(1)
       LINE INPUT #1, x$
       PRINT x$
       transmit x$
       transmit crlf$
    WEND

    CLOSE #1

    PRINT
    PRINT "Press any key to continue...";

    transmit crlf$
    transmit "Press any key to continue..."

    zzz = TIMER + 300
    WHILE DataWaiting% = 0 AND INKEY$ = "" AND TIMER < zzz
       IF CarrierLost THEN GOTO bombout
    WEND

    ClearInputBuffer
    transmit crlf$
    PRINT

noexitfileb:

    CLOSE

    ON ERROR GOTO bombout

 END IF


bombout:

 CLOSE

 CloseComm

 LOCATE , , 0
 END

'end of main code

'=========================================================================
'get from modem and write to disk, file 1 is already opened

mdmtodisk:

 mbuff$ = ""

 'wait up to 5 seconds for first character to arrive
 zzzz = TIMER + 5
 WHILE TIMER < zzzz AND DataWaiting% = 0
 WEND

 'if no chars have arrived, then something is wrong, so just exit
 IF DataWaiting% = 0 THEN RETURN


mdmtodisk2:

 'loop, getting characters from modem and writing
 'to disk file until no more come in
 WHILE DataWaiting%
    mbuff$ = mbuff$ + CHR$(ReadChar%)
 WEND

 'wait up to 3 seconds to see if another character arrives
 zzzz = TIMER + 3
 WHILE TIMER < zzzz AND DataWaiting% = 0
 WEND

 'if another character came in then go back into the read loop
 IF DataWaiting% THEN GOTO mdmtodisk2

 PRINT #1, mbuff$;

 RETURN

'=========================================================

'error handler for intro file not found

nointrofile:

 RESUME nointrofileb


'error handler for exit file not found

noexitfile:

 RESUME noexitfileb

'-----------------------------------------------------------------
