/*═════════════════════════════════════════════════════════════════════════╗
║ INTENTION: ║
║ ---------- ║
║ This Script is intended to be used as a small ZOC-HOST for remote ║
║ access. The intention is 99.9999% availability, whatever happens on ║
║ the remote side or on the line. ║
║ ║
║ Warranty: ║
║ --------- ║
║ There no warranty whatsoever. Take it, use it, modify it or leave it. ║
║ ║
║ Directory Scheme ║
║ ---------------- ║
║ This Script is written for following directory scheme: ║
║ (Files marked with ** belong to this package.) ║
║ Files KfRxHost.Std and KfRxHost.Con must be adapted to your equipment. ║
║ The files delivered are just samples. ║
║ ║
║ ZOC-DIRECTORY─┐ ║
║ ├──KFRXHOST─────────┬───────HOST ║
║ │ │ │ │ ║
║ │ **KfRxHost.Pw │ Standard Host Directory ║
║ │ (Passwords) │ Contains files to be send to ║
║ │ │ Remote ║
║ │ │ (Directory can be changed by ║
║ │ │ SuperAuthority) ║
║ │ │ ║
║ │ └───────REMOTE ║
║ │ │ ║
║ │ Files received from Remote ║
║ │ ║
║ ├──LOG ║
║ │ │ ║
║ │ KfRxHost.Log ║
║ │ ║
║ ├──SCRIPT ║
║ │ │ ║
║ │ **KfRxHost ║
║ │ (This Script) ║
║ │ ║
║ └──OPTIONS ║
║ │ ║
║ **KfRxHost.Con The host option file for connection ║
║ **KfRxHost.Std The standard option file, likely ║
║ to be a copy of option file STANDARD ║
║ ║
║ PassWords ║
║ --------- ║
║ Passwords are kept in file KfRxHost.Pw. This file may contain any ║
║ number of pass words. ║
║ ║
║ Authorities: ║
║ Two Levels of Authority are implemented: ║
║ Guest Authority. Allows Host->Remote transfer from one ║
║ Directory (HOST\HOST). ║
║ Super Authority. Allows Change of Host->Remote Directory ║
║ ║
║ Format: ║
║ Column 1: ║
║ G The following Word is a Password for Guest Authority ║
║ S The following Word is a Password for Super Authority ║
║ x Anything else than G or S is treated as comment ║
║ ║
║ Calling KfRxHost from PhoneBook: ║
║ -------------------------------- ║
║ May give problems by needing manual interventions on (probably ║
║ unattended) host when disconnecting. ║
║ ║
║ IMPORTANT!!! Notes: ║
║ ------------------- ║
║ - Set ASC DELAY in HostOpts options transfer to 0. ║
║ - Set CD Valid in HostOpts options transfer ON. ║
║ - EMULATION is supposed to be set to ANSI. ║
║ - It is strongly recommended to select OVERRIDE in HostOpts Transfer ║
║ to avoid question on the eventually unattended Host. ║
║ ║
║ Conventions writing this Procedure: ║
║ ----------------------------------- ║
║ - All Global Variables start with "G._". EG: G._Filename is a ║
║ global variable. This makes it easier to make this variables known ║
║ to the Expose Statement. ║
║ Local variables must not begin with "_", under certain circumstances, ║
║ this would lead to confusion with global variables. ║
║ EG: G._Anton could probably be confused with _Anton ║
║ ║
╚═════════════════════════════════════════════════════════════════════════*/
/*═════════════════════════════════════════════════════════════════════════╗
║ Constants and Variables to be adapted for your needs: ║
║ (Look for line ******* START of SETTING DEFAULTS *******) ║
║ NAME Type Comment Original Defaults ║
║ G._DirHost String Directory for Host->Remote "KFRXHOST\HOST\" ║
║ G._DirRemote String Directory for Remote->Host "KFRXHOST\REMOTE\" ║
║ G._DriveHost String Drive for Host->Remote Path of ZOC ║
║ G._HostOpts String Option File for connection "KfRxHost.Con" ║
║ G._LogInWait Digit Maximum Wait during LogIn 20 ║
║ G._MaxWait Digit Max. Wait for remote input 1000 ║
║ G._WakeUpTime Digit Ring remote if no input 300 ║
║ G._NumOfRings Digit Number of Rings 2 ║
║ G._PassWordFile String Name of PassWordFile "KFRXHOST\KfRxHost.Pw"║
║ G._ProcLog String LogFile "Log\KfRxHost.Log" ║
║ G._ProcLogOn Digit 0 no logging, 1 logging. 1 ║
║ G._ProcName String Name of this REXX-Procedure "KfRxHost" ║
║ G._StdOpts String Standard Option File "KfRxHost.Std" ║
║ ║
╚═════════════════════════════════════════════════════════════════════════*/
/*═════════════════════════════════════════════════════════════════════════╗
║ Main ║
╚═════════════════════════════════════════════════════════════════════════*/
Main:
/*──────────────────────────────────────────────────────────────────────┐
│ Set Error Exits and End │
└──────────────────────────────────────────────────────────────────────*/
Signal on Error Name ProgTerm
Signal on Failure Name ProgTerm
Signal on Halt Name ProgTerm
Signal on Syntax Name ProgTerm
/*──────────────────────────────────────────────────────────────────────┐
│ Set Version │
└──────────────────────────────────────────────────────────────────────*/
G._ProcVers = "2.0" /* Version */
/*──────────────────────────────────────────────────────────────────────┐
│ Set drive and directory where program was started from │
└──────────────────────────────────────────────────────────────────────*/
G._PrgDir = Directory()
G._PrgDrive = Left(G._PrgDir, 2)
G._PrgDir = SubStr(G._PrgDir,3)
/*══════════════════════════════════════════════════════════════════════╗
║ ******* START of SETTING DEFAULTS ******* ║
╚══════════════════════════════════════════════════════════════════════*/
G._DriveHost = G._PrgDrive /* Cur. Drive for Host->Remote */
G._DirHost = G._PrgDir"\KFRXHOST\Host\" /* Dir for Host->Remote */
G._DirRemote = G._PrgDir"\KFRXHOST\Remote\" /* Dir for Remote->Host */
G._ProcName = "KfRxHost" /* Name of this REXX-Prozedure */
G._NumOfRings = 2 /* Number of Rings */
G._MaxWait = 1000 /* Max Wait for Inp. from Remote */
G._WakeUpTime = 300 /* Ring remote if no input */
G._LogInWait = 20 /* Maximum Wait during LogIn */
G._PassWordFile = "KFRXHOST\KfRxHost.Pw" /* Name of Pass Word File */
G._ProcLog = "LOG\"G._ProcName".Log" /* LogFile */
G._ProcLogOn = 1 /* Set Logging on */
G._StdOpts = "KfRxHost.Std" /* Standard Option File */
G._HostOpts = "KfRxHost.Con" /* Option File for connect */
/*══════════════════════════════════════════════════════════════════════╗
║ ******* END of SETTING DEFAULTS ******* ║
╚══════════════════════════════════════════════════════════════════════*/
/*──────────────────────────────────────────────────────────────────────┐
│ Set G._Test to 1 for easier handling of password etc. │
│ PassWord is then "S" for Super, "G" for Guest │
└──────────────────────────────────────────────────────────────────────*/
G._Test = 0
/*──────────────────────────────────────────────────────────────────────┐
│ Address ZOC environment and Turnoff Host Echo │
└──────────────────────────────────────────────────────────────────────*/
ADDRESS ZOC
SETHOST 0
/*──────────────────────────────────────────────────────────────────────┐
│ Set Special Characters and Sequences │
└──────────────────────────────────────────────────────────────────────*/
G._ClearScreen = "^[[2J^[[1H"
G._CrLf = "^M^J"
G._Cr = "^M"
G._Bs = "^H"
G._Bell = "^G"
/*──────────────────────────────────────────────────────────────────────┐
│ Set Constants and Variables │
└──────────────────────────────────────────────────────────────────────*/
G._LeftBlanks = " "
G._ListSize = 15
G._TempFile1 = "HostTmp1.tmp"
G._TempFile2 = "HostTmp2.tmp"
/*──────────────────────────────────────────────────────────────────────┐
│ contains list of known drives x:s,x:s, etc │
│ x: = drive, s = FileSystem (H or F) │
└──────────────────────────────────────────────────────────────────────*/
G._FileSysList = ""
/*──────────────────────────────────────────────────────────────────────┐
│ Set DownLoad Path │
└──────────────────────────────────────────────────────────────────────*/
SETDLPATH G._DirRemote
/*──────────────────────────────────────────────────────────────────────┐
│ Setup for Logging │
└──────────────────────────────────────────────────────────────────────*/
LOGGING 0
IF G._ProcLog <> "" then LOGNAME G._ProcLog
/*──────────────────────────────────────────────────────────────────────┐
│ MainLoop │
└──────────────────────────────────────────────────────────────────────*/
MainLoop:
DO Forever
/*───────────────────────────────────────────────────────────────────┐
│ Address ZOC environment and Turnoff Host Echo │
└───────────────────────────────────────────────────────────────────*/
ADDRESS ZOC
SETHOST 0
WRITELN "Setting up for Connection"
SEND "ATS0=0"G._CrLf
/*───────────────────────────────────────────────────────────────────┐
│ Hangup and load HOSTOPTS, if available │
└───────────────────────────────────────────────────────────────────*/
HANGUP
DELAY 2
LOADOPTS G._HostOpts
/*───────────────────────────────────────────────────────────────────┐
│ Disable dial in │
└───────────────────────────────────────────────────────────────────*/
SEND "ATS0=0"G._CrLf
DELAY 1
/*───────────────────────────────────────────────────────────────────┐
│ Set/Stop Logging │
└───────────────────────────────────────────────────────────────────*/
IF G._ProcLogOn <> 0 then LOGGING 1
ELSE LOGGING 0
/*───────────────────────────────────────────────────────────────────┐
│ check, whether valid cd option is set. exit if not │
└───────────────────────────────────────────────────────────────────*/
IF ZocCarrier() = "N/A" then DO
WRITELN "ERROR: CD Valid in OPTIONS SERIAL not Set."G._CrLf
SIGNAL Finito
END
/*───────────────────────────────────────────────────────────────────┐
│ Set Num of Rings │
└───────────────────────────────────────────────────────────────────*/
WRITE G._ClearScreen
SEND "ATS0="G._NumOfRings""G._CrLf
DELAY 1
/*───────────────────────────────────────────────────────────────────┐
│ Wait for Connection and Backspace from Remote │
└───────────────────────────────────────────────────────────────────*/
CALL WaitForConnect
CALL WaitForBS
/*───────────────────────────────────────────────────────────────────┐
│ Backspace received │
└───────────────────────────────────────────────────────────────────*/
CALL Welcome
CALL GetPassWord /* Set G._Authority: SUPER="S", GUEST="G", FAILURE="F" */
G._FirstMenu = 2
IF G._Test <> 0 then G._FirstMenu = 1 /* avoid time consuming menu */
DO WHILE G._Authority <> "F"
G._CurDrive = G._DriveHost /* Current drive */
G._CurDir = G._DirHost /* Current directory */
G._CurPath = G._CurDrive||G._CurDir /* Current Full Path */
G._CurFileSys = "U" /* Current file syst.: U=Unknown, H=HPFS, F=FAT */
CALL Menu
CALL Wsend '"'G._LeftBlanks'CHOICE: "'
SELECT
WHEN G._Choice = "F" then DO
CALL Wsend "Show dir (F)iles"G._CrLf
CALL ShowDir G._CurPath||"*",0
CALL CloseDelFile G._TempFile1
END
WHEN G._Choice = "?" then DO
G._FirstMenu = 2
ITERATE
END
WHEN G._Choice = "D" then DO
CALL Wsend "(D)ownload file(s) "G._CrLf
CALL DownL
CALL CloseDelFile G._TempFile1
END
WHEN G._Choice = "U" then DO
CALL Wsend "(U)pload file(s) "G._CrLf
CALL UpL
END
WHEN G._Choice = "G" then DO
CALL Wsend "(G)oodbye "
G._Authority = "F" /* HANGUP */
END
WHEN G._Authority = "S" & G._Choice = "C" then DO
CALL Wsend "(C)hange directory "
CALL ChangeDir
END
WHEN G._Authority = "S" & G._Choice = "S" then DO
CALL Wsend "(S)earch file(s) "G._CrLf
CALL SearchFile
END
WHEN G._Authority = "S" & G._Choice = "H" then DO
CALL Wsend "Shutdown (H)ost "G._CrLf
IF Ask_YN("You really want to shut down the host","N") <> 0 then DO
G._Authority = "H" /* Shut Host */
END
END
OTHERWISE DO
CALL Wsend ">"G._Choice"< is Invalid "
END
END
CALL Wsend G._CrLf
If G._Authority = "F" | G._Authority = "H" then DO
SETHOST 0
G._FirstMenu = 1
CALL Wsend "Goodbye. Thanks for Calling. "
If G._Authority = "H" then CALL Wsend "Host Closing."
CALL Wsend G._CrLF
DELAY 1
If G._Authority = "F" then DO
HANGUP
DELAY 1
END
If G._Authority = "H" then SIGNAL Finito
END
END
END
/*MAIN END*/
/*========================================================================*/
/*═════════════════════════════════════════════════════════════════════════╗
║ Procedures and Functions ║
╚═════════════════════════════════════════════════════════════════════════*/
/*═════════════════════════════════════════════════════════════════════════╗
║ ChangeDir Set G._DriveHost and G._DirHost ║
╚═════════════════════════════════════════════════════════════════════════*/
ChangeDir: Procedure Expose G.
CdValid = 1
WaitText = G._CrLf||G._LeftBlanks"Enter Drive and/or Directory to change to: "
CALL WaitForLine WaitText,1,0,0,1 /* UpCase Empty WaitTime Echo */
/*──────────────────────────────────────────────────────────────────────┐
│ Get new Drive and/or Dir │
└──────────────────────────────────────────────────────────────────────*/
IF SubStr(G._RxLastLine,2,1) = ":" then DO
G._DriveHost = Left(G._RxLastLine,2)
G._DirHost = SubStr(G._RxLastLine,3)
END
ELSE DO
G._DriveHost = G._CurDrive
G._DirHost = G._RxLastLine
END
IF Left(G._DirHost,1) == "." then DO
CdValid = 0
CALL Wsend "Going Back not allowed"G._CrLf
END
IF CdValid <> 0 then DO
IF Left(G._DirHost,1) <> "\" then G._DirHost = G._CurDir||G._DirHost
IF Right(G._DirHost,1) <> "\" then G._DirHost = G._DirHost"\"
/*───────────────────────────────────────────────────────────────────┐
│ Determine HPFS/FAT. Because fomat of dierectory listing differs │
└───────────────────────────────────────────────────────────────────*/
CALL SetFileSystem G._DriveHost
/*───────────────────────────────────────────────────────────────────┐
│ Check wether drive exists │
└───────────────────────────────────────────────────────────────────*/
IF G._CurFileSys = "U" then CdValid = 0
END
IF CdValid <> 0 then DO
/*───────────────────────────────────────────────────────────────────┐
│ Check wether directory exists │
└───────────────────────────────────────────────────────────────────*/
CD_Dir = G._DriveHost||G._DirHost
CD_Str = "dir "CD_Dir"abcdefgh.ijk>NUL"
Signal OFF Error
ADDRESS CMD CD_Str
RetCode = rc
Signal on Error Name ProgTerm
IF RetCode <> 18 & RetCode <> 0 then DO
CdValid = 0
CALL Wsend '"Path >'CD_Dir'< not valid'G._CrLf'"'
END
END
IF CdValid = 0 then DO
/*───────────────────────────────────────────────────────────────────┐
│ Not a valid path, restore original │
└───────────────────────────────────────────────────────────────────*/
G._DriveHost = G._CurDrive
G._DirHost = G._CurDir
END
G._FirstMenu = 1
RETURN
/*═════════════════════════════════════════════════════════════════════════╗
║ SetFileSystem Sets variable G._CurFileSys according to Arg(1), Drive.║
╚═════════════════════════════════════════════════════════════════════════*/
SetFileSystem: Procedure Expose G.
FsDrive = Arg(1)
/*──────────────────────────────────────────────────────────────────────┐
│ Get Drive │
└──────────────────────────────────────────────────────────────────────*/
IF SubStr(FsDrive,2,1) = ":" then FsDrive = Left(FsDrive,2)
ELSE FsDrive = G._PrgDrive
Parse UPPER VAR FsDrive FsDrive
/*──────────────────────────────────────────────────────────────────────┐
│ Check wether already known │
└──────────────────────────────────────────────────────────────────────*/
FsPos = Pos(FsDrive,G._FileSysList)
IF FsPos <> 0 then DO
G._CurFileSys = SubStr(G._FileSysList,FsPos+2,1)
RETURN
END
/*──────────────────────────────────────────────────────────────────────┐
│ Try wether able to handle file names longer than 8 (HPFS) │
└──────────────────────────────────────────────────────────────────────*/
Signal OFF Error
Address CMD '"dir 'FsDrive'\123456789>NUL"'
RetCode = rc
Signal on Error Name ProgTerm
SELECT
WHEN RetCode = 206 then G._CurFileSys = "F" /* Name too long */
WHEN RetCode = 18 then G._CurFileSys = "H" /* File not found */
WHEN RetCode = 0 then G._CurFileSys = "H" /* File found */
OTHERWISE G._CurFileSys = "U"
END
/*──────────────────────────────────────────────────────────────────────┐
│ If file system determined, add it to the list │
└──────────────────────────────────────────────────────────────────────*/
IF G._CurFileSys = "U" then CALL Wsend '"Drive >'FsDrive'< unknown'G._CrLf'"'
ELSE G._FileSysList = G._FileSysList||FsDrive||G._CurFileSys","
RETURN
/*═════════════════════════════════════════════════════════════════════════╗
║ ReadFn ARG(1) if non 0, return each line ║
║ Read a line with file name from G._TempFile1 to G._FileNameLine ║
║ and return filename ║
║ If EOF: Set G._EndOfFile1 to non 0 ║
╚═════════════════════════════════════════════════════════════════════════*/
ReadFn: Procedure Expose G.
G._EndOfFile1 = 0
DO Forever
/*───────────────────────────────────────────────────────────────────┐
│ Test for EndOfFile │
└───────────────────────────────────────────────────────────────────*/
TempFile1State = Stream(G._TempFile1,'S')
IF Left(TempFile1State,5) <> "READY" then DO
G._EndOfFile1 = 1
G._FileNameLine = ""
RETURN
END
G._FileNameLine = Linein(G._TempFile1)
/*───────────────────────────────────────────────────────────────────┐
│ Check wether it is a file name, if so LEAVE │
└───────────────────────────────────────────────────────────────────*/
IF Arg(1) = 0 then CALL GetFn
ELSE G._FileName = G._FileNameLine
IF G._FileName <> "" then LEAVE
END
RETURN
/*═════════════════════════════════════════════════════════════════════════╗
║ GetFn Check wether G._FileNameLine contains a G._FileName. ║
║ If so set it to G._FileName. Else set G._FileName to "" ║
║ ║
║ - Example of Lines in HPFS: ║
║ 0000000001111111111222222222233333333334444444444 ║
║ 1234567891234567890123456789012345678901234567890 ║
║ 3.05.94 19.11 105827 0 DOKUSP.TXT ║
║ 25.03.94 20.29 <DIR> 1236 Cmd ║
║ - Criterias for Filename in HPFS: ║
║ Column 3 must be a "." ║
║ G._FileNameLine 3rd word must not by <DIR> ║
║ ║
║ - Example of Lines in FAT: ║
║ 0000000001111111111222222222233333333334444444444 ║
║ 1234567890123456789012345678901234567890123456789 ║
║ BAT <DIR> 29.01.94 15.23 ║
║ BAT 1 <DIR> 29.01.94 15.23 ║
║ ABC 243 27.08.94 12.52 ║
║ BCD 1 243 27.08.94 13.52 ║
║ CDE TXT 243 27.08.94 14.52 ║
║ 12345678 TXT 243 27.08.94 15.52 ║
║ - Criterias for Filename in FAT: ║
║ Column 26 must be a '.' (period ║
║ Line must not contain "<DIR>" ║
║ Filename = 1st Word, FileExt is 3 letters starting in Column 10 ║
║ ║
╚═════════════════════════════════════════════════════════════════════════*/
GetFn: Procedure Expose G.
G._FileName = ""
IF G._CurFileSys = "H" then DO
/*───────────────────────────────────────────────────────────────────┐
│ This is HPFS │
└───────────────────────────────────────────────────────────────────*/
IF SubStr(G._FileNameLine,3,1) <> "." then RETURN
IF SubWord(G._FileNameLine,3,1) = "<DIR>" then RETURN
G._FileName = SubWord(G._FileNameLine,5,1)
END
ELSE IF G._CurFileSys = "F" then DO
/*───────────────────────────────────────────────────────────────────┐
│ This is FAT │
└───────────────────────────────────────────────────────────────────*/
IF SubStr(G._FileNameLine,26,1) <> "." then RETURN
IF Pos("<DIR>",G._FileNameLine) <> 0 then RETURN
G._FileName = Left(G._FileNameLine,8)
G._FileName = Strip(G._FileName)
FileExt = SubStr(G._FileNameLine,10,3)
IF FileExt <> " " then DO
FileExt = Strip(FileExt)
G._FileName = G._FileName"."FileExt
END
END
RETURN
/*═════════════════════════════════════════════════════════════════════════╗
║ Menu. Print menu and set G._Choice. G._Choice = "ERROR" if failure. ║
╚═════════════════════════════════════════════════════════════════════════*/
Menu: Procedure Expose G.
G._Choice = "ERROR"
CALL ShowMenu
WaitText = G._CrLf||G._LeftBlanks"Your Choice "
IF G._Authority = "G" then WaitText = WaitText"(F/D/U/G/?): "
ELSE WaitText = WaitText"(F/D/U/G/C/S/H/?): "
CALL WaitForLine WaitText,1,0,0,1 /* UpCase Empty WaitTime Echo */
G._Choice = G._RxLastLine
Return
/*═════════════════════════════════════════════════════════════════════════╗
║ ShowMenu, Draw the whole menu with alle menu- and info-points ║
║ G._FirstMenu > 1: Draw the whole menu with alle menu- and info-point ║
║ G._FirstMenu > 0: Draw info-point ║
╚═════════════════════════════════════════════════════════════════════════*/
ShowMenu: Procedure Expose G.
IF G._FirstMenu > 1 then DO
CALL Wsend G._ClearScreen
/* y x Text */
CALL MenuPoint 2, 10, 'F', ' Show dir (F)iles ' /* Row 1 Left */
CALL MenuPoint 5, 10, 'D', ' (D)ownload file(s) ' /* Row 2 Left */
CALL MenuPoint 8, 10, 'U', ' (U)pload file(s) ' /* Row 3 Left */
CALL MenuPoint 11, 10, 'G', ' (G)oodbye ' /* Row 4 Left */
IF G._Authority = "S" THEN DO
CALL MenuPoint 5, 45, 'C', ' (C)hange directory ' /* Row 2 Right */
CALL MenuPoint 8, 45, 'S', ' (S)earch file(s) ' /* Row 3 Right */
CALL MenuPoint 11, 45, 'H', ' Shutdown (H)ost ' /* Row 4 Right */
END
G._FirstMenu = 1
END
IF G._FirstMenu > 0 then DO
CALL Wsend G._CrLf
IF G._Authority = "S" then PathInfo = G._CurPath
ELSE PathInfo = "Standard Host Directory"
CALL InfoLine '^[[0;34;47mCurrent HostDir:^[[30m 'overlay(PathInfo,' ')
END
G._FirstMenu = 0
RETURN
/*═════════════════════════════════════════════════════════════════════════╗
║ MenuPoint. Draw one menu-point with ARG(line, col, shortcut, name) ║
╚═════════════════════════════════════════════════════════════════════════*/
MenuPoint: Procedure Expose G.
CALL Wsend '"^[['ARG(1)';'ARG(2)'H"'
CALL Wsend '"^[[1;37;47m┌───^[[0;30;47m┐"'
CALL Wsend '"^[[1;37m┌────────────────────^[[0;30;47m┐^[[40m"'
CALL Wsend '"^[['ARG(1)+1';'ARG(2)'H"'
CALL Wsend '"^[[1;37;47m│ ^[[0;34;47m'ARG(3)' ^[[30m│"'
CALL Wsend '"^[[1;37m│^[[0;30;47m'ARG(4)'│^[[40m"'
CALL Wsend '"^[['ARG(1)+2';'ARG(2)'H"'
CALL Wsend '"^[[1;37;47m└^[[0;30;47m───┘"'
CALL Wsend '"^[[1;37m└^[[0;30;47m────────────────────┘^[[40m"'
RETURN
/*═════════════════════════════════════════════════════════════════════════╗
║ InfoLine draw one info-point with ARG(col, text) ║
╚═════════════════════════════════════════════════════════════════════════*/
InfoLine: Procedure Expose G.
CALL Wsend G._CrLf
CALL Wsend '"'G._LeftBlanks'^[[1;37;47m┌──────────────────────────────────"'
CALL Wsend '"──────────────────────────^[[0;30;47m┐"'
CALL Wsend "^[[0m"G._CrLf
CALL Wsend '"'G._LeftBlanks'^[[1;37;47m│ ^[[0;30;47m'ARG(1)' ^[[30m│"'
CALL Wsend "^[[0m"G._CrLf
CALL Wsend '"'G._LeftBlanks'^[[1;37;47m└^[[0;30;47m────────────────────────"'
CALL Wsend '"────────────────────────────────────┘"'
CALL Wsend "^[[0m"G._CrLf
RETURN
/*═════════════════════════════════════════════════════════════════════════╗
║ GetPassWord Set G._Authority: "G" (Guest), "S" (Super) or "F" (Failed) ║
╚═════════════════════════════════════════════════════════════════════════*/
GetPassWord: Procedure Expose G.
G._Authority = "F"
WaitText = "Enter Password within the next "G._LogInWait" seconds: "
IF G._Test <> 0 then WaitText = WaitText" (Test) "
CALL WaitForLine WaitText,1,0,G._LogInWait,0 /* UpCase Empty WaitTime Echo */
IF G._Test <> 0 then DO
/*───────────────────────────────────────────────────────────────────┐
│ Simplified Pass word checking │
└───────────────────────────────────────────────────────────────────*/
IF G._RxLastLine = "S" then G._Authority = "S"
ELSE IF G._RxLastLine = "G" then G._Authority = "G"
END
ELSE DO
/*───────────────────────────────────────────────────────────────────┐
│ Check against Password file │
└───────────────────────────────────────────────────────────────────*/
PassWordState = Stream(G._PassWordFile,'C',"OPEN Read")
IF Left(PassWordState,5) = "READY" then DO
DO Forever
/*─────────────────────────────────────────────────────────────┐
│ Test for EndOfFile │
└─────────────────────────────────────────────────────────────*/
PassWordState = Stream(G._PassWordFile,'S')
IF Left(PassWordState,5) <> "READY" then LEAVE
/*─────────────────────────────────────────────────────────────┐
│ Read and compare line │
└─────────────────────────────────────────────────────────────*/
PassWord = Linein(G._PassWordFile)
Parse UPPER VAR PassWord PassWord
Authority = Left(PassWord,1)
IF Authority <> "S" & Authority <> "G" then ITERATE /* comment */
IF SubWord(PassWord,2) = G._RxLastLine then DO
G._Authority = Authority
LEAVE
END
END
PassWordState = Stream(G._PassWordFile,'C',"CLOSE")
END
ELSE WRITELN '"Error opening 'G._PassWordFile' for read.'G._CrLf'"'
END
WRITELN ""
IF G._Authority = "S" then CALL Wsend G._CrLf"Authority level: SUPER"G._CrLf
ELSE IF G._Authority = "G" then CALL Wsend G._CrLf"Authority level: GUEST"G._CrLf
ELSE CALL Wsend G._CrLf"Authorization failed"G._CrLf
DELAY 1
RETURN
/*═════════════════════════════════════════════════════════════════════════╗
║ Welcome. Draw welcome Text ║
╚═════════════════════════════════════════════════════════════════════════*/
Welcome: Procedure Expose G.
WelCome1 = '" ___ ___ ___ 'G._CrLf'"'
WelCome2 = '" |__ || _ | __|'G._CrLf'"'
WelCome3 = '" / /_||_|| |_ ZOC 'G._ProcName'-Script Version 'G._ProcVers''G._CrLf'"'
WelCome4 = '" |____|___|___|'G._CrLf'"'
CALL Wsend G._ClearScreen""G._CrLf""G._CrLf
CALL Wsend Welcome1
CALL Wsend Welcome2
CALL Wsend Welcome3
CALL Wsend Welcome4
CALL Wsend G._CrLf
RETURN
/*═════════════════════════════════════════════════════════════════════════╗
║ WaitForLine WaitText UpCase Empty WaitTime Echo ║
║ 1 2 3 4 5 ║
║ UpCase <> 0 converts data to upper case ║
║ Empty <> 0 waits also for empty lines ║
║ WaitTime <> 0 overrides G._MaxWait ║
║ Echo <> 0 Set Host Echo ║
║ Waits for a line of data ║
║ If Line is NoCarrier then Signal LostCarrier ║
║ If G._MaxWait is exhausted then Signal Restart ║
╚═════════════════════════════════════════════════════════════════════════*/
WaitForLine: Procedure Expose G.
WaitTime = G._MaxWait
WakeUpCounter = 0
IF Arg(4) <> 0 then WaitTime = Arg(4) /* Overrides G._MaxWait ? */
DO Forever
CurWait = WaitTime
If WaitTime > G._WakeUpTime then CurWait = G._WakeUpTime
WaitTime = WaitTime - CurWait
TIMEOUT CurWait
IF Arg(1) <> "" then CALL Wsend '"'Arg(1)'"'
CALL TestNoCarrier
IF Arg(5) <> 0 then SETHOST 1 /* Set Host Echo ? */
ELSE SETHOST 0
IF Arg(3) = 0 then GETLINE /* Wait also for empty lines ? */
ELSE WAIT G._Cr
RetCode = rc
SETHOST 0
IF RetCode = 0 then LEAVE
ELSE DO
CALL TestNoCarrier /* Restart if lost carrier */
WakeUpCounter = WakeUpCounter + 1
If WaitTime > 0 then DO
SELECT
WHEN WakeUpCounter = 3 then Nbr = "rd"
WHEN WakeUpCounter = 2 then Nbr = "nd"
WHEN WakeUpCounter = 1 then Nbr = "st"
OTHERWISE Nbr = "th"
END
CALL Wsend '"'G._Bell''G._CrLf'Please wake up! This is your 'WakeUpCounter''Nbr'"'
IF WaitTime <= (G._WakeUpTime) then DO
CALL Wsend '" and final"'
END
CALL Wsend '" Call. 'WaitTime' seconds before LOGOFF. 'G._CrLf'"'
ITERATE
END
CALL Wsend '"'G._CrLf'You are logged off because of no activity.'G._CrLf'"'
Delay 1
Signal Restart
END
END
G._RxLastLine = ZocLastLine()
IF Left(G._RxLastLine,10) = "NO CARRIER" then Signal LostCarrier
G._RxLastLine = Strip(G._RxLastLine)
IF Arg(2) <> 0 then Parse UPPER VAR G._RxLastLine G._RxLastLine /* UpCase ? */
RETURN
/*═════════════════════════════════════════════════════════════════════════╗
║ WaitForBS ║
║ Waits G._LogInWait for BackSpace from remote. ║
║ If G._LogInWait is exhausted then go to Restart ║
║ If Carrier is lost Signal LostCarrier ║
╚═════════════════════════════════════════════════════════════════════════*/
WaitForBS: Procedure Expose G.
CALL TestNoCarrier
CALL Wsend '"Hit BACKSPACE within the next 'G._LogInWait' seconds to start host ... 'G._CrLf'"'
TIMEOUT G._LogInWait
WAIT G._Bs
IF rc <> 0 then DO
CALL TestNoCarrier
Signal Restart
END
RETURN
/*═════════════════════════════════════════════════════════════════════════╗
║ WaitForConnect ║
║ Waits for Connect and subsequent CR ║
╚═════════════════════════════════════════════════════════════════════════*/
WaitForConnect: Procedure Expose G.
DO Forever
WRITELN "Waiting for call ..."
TIMEOUT 32000
/*───────────────────────────────────────────────────────────────────┐
│ Wait for Connect. │
└───────────────────────────────────────────────────────────────────*/
WAIT "CONNECT"
IF rc <> 0 then ITERATE /* keep waiting */
/*───────────────────────────────────────────────────────────────────┐
│ Wait for Connect. │
└───────────────────────────────────────────────────────────────────*/
TIMEOUT 10
WAIT G._Cr
G._RxLastLine = ZocCarrier()
IF Left(G._RxLastLine,7) = "CARRIER" then LEAVE
END
WRITELN "Remote Call received"
RETURN
/*═════════════════════════════════════════════════════════════════════════╗
║ Wsend. Write and Send. Important: Does SETHOST 0 when exiting ║
╚═════════════════════════════════════════════════════════════════════════*/
Wsend: Procedure Expose G.
IF ZOCCARRIER() = "CARRIER" then DO
SETHOST 1
SEND ARG(1)
END
SETHOST 0
WRITE ARG(1)
RETURN
/*═════════════════════════════════════════════════════════════════════════╗
║ DownL ║
╚═════════════════════════════════════════════════════════════════════════*/
DownL: Procedure Expose G.
DownLCount = 0
WaitText = "Enter Filename to download. Wildcards welcome: "
CALL WaitForLine WaitText,0,0,0,1 /* UpCase Empty WaitTime Echo */
IF G._RxLastLine = "" then DO
CALL Wsend "DownLoad cancelled"G._CrLF
RETURN
END
LoadFile = G._RxLastLine
Fn = G._CurPath||LoadFile
CALL ShowDir G._CurPath||LoadFile,0
IF FilesFound = 0 then RETURN
IF Ask_YN("You want to download this file(s)","Y") = 0 then RETURN
TempFile1State = Stream(G._TempFile1,"C","seek = 1")
OkCount = 0
ErrCount = 0
Error = 0
DO Forever
CALL ReadFn 0 /* sets G._EndOfFile1 */
IF G._EndOfFile1 <> 0 then LEAVE
/*───────────────────────────────────────────────────────────────────┐
│ If Error occured on transmission of previous File, ask wether to │
│ continue. │
└───────────────────────────────────────────────────────────────────*/
IF Error <> 0 then DO
Delay 3
IF Ask_YN("Error occured on transmission. Continue", "Y") = 0 then LEAVE
END
Fn = G._CurPath||G._FileName
/*───────────────────────────────────────────────────────────────────┐
│ Upload to remote. Turn Host Echo off immediately after. This must │
│ be done to avoid sending Garbage across the line when transfer │
│ is cancelled. │
└───────────────────────────────────────────────────────────────────*/
UPLOAD z Fn
G._RxLastLine = ZocResult()
SETHOST 0
/*───────────────────────────────────────────────────────────────────┐
│ Analyze Status of transmission │
└───────────────────────────────────────────────────────────────────*/
WRITELN "ZocResult=>"G._RxLastLine"<"
CALL Wsend '"'G._CrLf'Transmission Status for File 'Fn': "'
IF G._RxLastLine = "##OK##" then do
OkCount = OkCount + 1
CALL Wsend "Ok."
Error = 0
END
ELSE DO
Error = 1
ErrCount = ErrCount + 1
Delay 3
CALL Wsend "NOT Ok."
END
CALL Wsend G._CrLf
DownLCount = DownLCount + 1
END
CALL Wsend '"Transmission Report: ***** 'OkCount' File(s) Ok. "'
CALL Wsend '"***** 'ErrCount' File(s) NOT Ok. ***** 'G._CrLf'"'
RETURN
/*═════════════════════════════════════════════════════════════════════════╗
║ UpL ║
╚═════════════════════════════════════════════════════════════════════════*/
UpL: Procedure Expose G.
/*──────────────────────────────────────────────────────────────────────┐
│ Download from remote. Turn Host Echo off immediately after. This is │
│ to avoid sending Garbage across the line when cancel is hit. │
└──────────────────────────────────────────────────────────────────────*/
Download z G._DirRemote
G._RxLastLine = ZocResult()
SETHOST 0
/*──────────────────────────────────────────────────────────────────────┐
│ Analyze result of transmission │
└──────────────────────────────────────────────────────────────────────*/
CALL Wsend "Transmission Report: Host detected "
If G._RxLastLine = "##OK##" then DO
CALL Wsend "no Error."G._CrLf
END
ELSE DO
CALL Wsend "Error."G._CrLf
END
RETURN
/*═════════════════════════════════════════════════════════════════════════╗
║ SearchFile /AD=Directories only, /S=also subdirs ║
╚═════════════════════════════════════════════════════════════════════════*/
SearchFile: Procedure Expose G.
WaitText = G._LeftBlanks"Enter [/AD ][/S ][drive:][\dir\]filename to search for: "
CALL WaitForLine WaitText,0,1,0,1 /* UpCase Empty WaitTime Echo */
IF G._RxLastLine = "" then RETURN
Filename = G._RxLastLine
/*──────────────────────────────────────────────────────────────────────┐
│ Preceede with drive and/or parent dir if omitted │
└──────────────────────────────────────────────────────────────────────*/
IF Substr(Filename,2,1) <> ":" then DO
IF Left(Filename,1) <> "\" then DO
Filename = G._Curdrive||G._CurDir||Filename
END
ELSE Filename = G._Curdrive||Filename
END
CALL Wsend '"'G._LeftBlanks'Searching for >'Filename'<, please wait ...'G._CrLf''G._CrLf'"'
CALL ShowDir Filename,1
RETURN
/*═════════════════════════════════════════════════════════════════════════╗
║ ShowDir ARG(1)=filespec. ARG(2)=show complete list ║
║ On Exit: ║
║ If Files found: FilesFound = 1, G._TempFile1 is open. ║
║ Else FilesFound = 0. ║
╚═════════════════════════════════════════════════════════════════════════*/
ShowDir: Procedure Expose G.
SD_String = Arg(1)
CALL closedelfile G._TempFile1
CALL SetFileSystem SD_String /* Set Variable G._CurFileSys */
IF G._CurFileSys = "U" then RETURN
SD_String = "dir "SD_String">"G._TempFile1
Signal OFF Error
ADDRESS CMD SD_String
RetCode = rc
Signal on Error Name ProgTerm
IF RetCode <> 0 then DO
CALL Wsend "No Files found"G._CrLf
FilesFound = 0
RETURN
END
FilesFound = 1
/*──────────────────────────────────────────────────────────────────────┐
│ Open G._TempFile1 │
└──────────────────────────────────────────────────────────────────────*/
TempFile1State = Stream(G._TempFile1,'C',"OPEN Read")
IF Left(TempFile1State,5) <> "READY" then DO
ErrMess = "Error opening "G._TempFile1" for read"
CALL Wsend ErrMess
RETURN
END
CALL ShowList Arg(2)
RETURN
/*═════════════════════════════════════════════════════════════════════════╗
║ ShowList ARG(1) = 0: show only files, else show whole list. ║
║ Splits G._TempFile1 in groups of G._ListSize and displays. ║
║ G._TempFile1 is open when coming here ║
╚═════════════════════════════════════════════════════════════════════════*/
ShowList: Procedure Expose G.
G._EndOfFile1 = 0
TempFile2OutState = 0
TempFile2State = ""
DO Until G._EndOfFile1 <> 0
/*───────────────────────────────────────────────────────────────────┐
│ Clear and Open TempFile2 for Write │
└───────────────────────────────────────────────────────────────────*/
CALL CloseDelFile G._TempFile2
TempFile2State = Stream(G._TempFile2,'C',"OPEN Write")
IF Left(TempFile2State,5) <> "READY" then DO
ErrMess = "Error opening "G._TempFile2" for write"
CALL Wsend ErrMess
LEAVE
END
/*───────────────────────────────────────────────────────────────────┐
│ Copy a number of Lines to file TempFile2 │
└───────────────────────────────────────────────────────────────────*/
DO LineCount = 0 to G._ListSize
/*────────────────────────────────────────────────────────────────┐
│ Get a line containing a file name from G._TempFile1 │
└────────────────────────────────────────────────────────────────*/
CALL ReadFn ARG(1)
IF G._EndOfFile1 then LEAVE
/*────────────────────────────────────────────────────────────────┐
│ Skip if line in G._TempFile1 does not contain a file name │
└────────────────────────────────────────────────────────────────*/
IF G._FileNameLine = "" then DO
LineCount = LineCount - 1 /* Adjust count back if not a file */
ITERATE
END
/*────────────────────────────────────────────────────────────────┐
│ Write Line with file name to TempFile2 │
└────────────────────────────────────────────────────────────────*/
TempFile2OutState = Lineout(G._TempFile2,G._FileNameLine)
IF TempFile2OutState <> 0 then DO
ErrMess = "Error writing to "G._TempFile2
CALL Wsend ErrMess
LEAVE
END
END
IF TempFile2OutState <> 0 then LEAVE /* trouble with list file */
TempFile2State = Stream(G._TempFile2,'C',"CLOSE")
/*───────────────────────────────────────────────────────────────────┐
│ Upload TempFile2, unless it is empty │
└───────────────────────────────────────────────────────────────────*/
IF LineCount <> 0 then UPLOAD a1 G._TempFile2
IF LineCount >= G._ListSize then DO
IF Ask_YN("More","Y") = 0 then LEAVE
END
END
CALL CloseDelFile G._TempFile2
RETURN
/*═════════════════════════════════════════════════════════════════════════╗
║ Ask_YN Ask Yes/No Question. Return 1 Yes, 0 if No. ║
║ Ask_YN txt Y or N ║
║ txt: Text to Ask ║
║ Y: Default is Yes, other: Default is No ║
║ Question must be answered with Y, N, or Enter only. ║
║ Enter only returns default. ║
╚═════════════════════════════════════════════════════════════════════════*/
Ask_YN: Procedure Expose G.
AskText = G._LeftBlanks||Arg(1)
IF Arg(2) = "Y" | Arg(2) = "y" then Default = 1
ELSE Default = 0
IF Default = 1 then AskText = AskText" (Y,n) ? "
ELSE AskText = AskText" (y,N) ? "
DO Forever
CALL WaitForLine AskText,1,1,0,1 /* UpCase Empty WaitTime Echo */
IF G._RxLastLine = "" then RETURN Default
Answer = Left(G._RxLastLine,1)
IF Answer = "Y" then RETURN 1
IF Answer = "N" then RETURN 0
END
/* End Ask_YN */
/*═════════════════════════════════════════════════════════════════════════╗
║ CloseDelFile Close and delete file ║
╚═════════════════════════════════════════════════════════════════════════*/
CloseDelFile: Procedure Expose G.
FileName = Arg(1)
FState = Stream(FileName,'C',Query exists)
IF FState <> "" then DO
FState = Stream(FileName,'C',"CLOSE")
ADDRESS CMD '"del 'FileName'"'
END
RETURN
/*═════════════════════════════════════════════════════════════════════════╗
║ TestNoCarrier Restart if carrier lost ║
║ ║
╚═════════════════════════════════════════════════════════════════════════*/
TestNoCarrier: Procedure Expose G.
IF ZocCarrier() = "NO CARRIER" then DO
SETHOST 0 /* turnoff evtl. host echo */
Signal LostCarrier
END
RETURN
/*═════════════════════════════════════════════════════════════════════════╗
║ LostCarrier ║
╚═════════════════════════════════════════════════════════════════════════*/
LostCarrier:
WRITELN G._CrLf"**********Carrier lost. Restarting.**********"G._CrLf
Signal Restart
/* LostCarrier End*/
/*═════════════════════════════════════════════════════════════════════════╗
║ Restart ║
╚═════════════════════════════════════════════════════════════════════════*/
Restart:
SETHOST 0
Signal Main
/*Restart End*/
/*========================================================================*/
/*═════════════════════════════════════════════════════════════════════════╗
║ Ending Procedures ║
╚═════════════════════════════════════════════════════════════════════════*/
/*═════════════════════════════════════════════════════════════════════════╗
║ ProgTerm ║
╚═════════════════════════════════════════════════════════════════════════*/
ProgTerm:
ADDRESS ZOC
SETHOST 0
WRITELN "*** Program terminated at Line "SIGL". ***"
SIGNAL Finito
/*═════════════════════════════════════════════════════════════════════════╗
║ Common Exit ║
╚═════════════════════════════════════════════════════════════════════════*/
Finito:
ADDRESS ZOC
SETHOST 0
HANGUP
WRITELN "Trying to re-load Options "G._StdOpts
LOADOPTS G._StdOpts
IF G._ProcLogOn <> 0 then LOGGING 1
ELSE LOGGING 0
WRITELN G._ProcName"-Script Version "G._ProcVers" ended"
Exit