; HOSTMODE.KSC
;
; Utility and management functions for Kermit 95 host mode.
; Authors: F. da Cruz, C. Gianone
; Date: December 1995 - January 1996
; Updated February 1997 for OS/2
; Updated June 1997 for TAPI
; Setting of MAXUSERS fixed, December 1997.
; Recommendations of J.v.Jena jvjena@cs.tu-berlin.de incorporated, March 2000
; Corrections to _k95program and location of default host.cfg file, Apr 6, 2000
; More of same plus conversion to modern syntax, fdc, 6 July 2001.
;
; Uses of hostmode.bat:
; 
; - hostmode.bat makes the following assumptions:
;   an empty setting for the CFG variable (default) uses host.cfg
;   in the SCRIPTS subdirectory.
; 
; - A nonempty string as CFG value specifies a different subdirectory.
;   If this subdirectory does not already exist, it is created and
;   host.cfg is copied to it from the SCRIPTS subdirectory.  You can change
;   and save this configuration.
; 
; - Thus you can have different HOSTxxxx.BAT files that specify different
;   CFG values to pick up different configurations.
;
; Use of shortcuts to [scripts]/hostmode.ksc:
; 
; - Assuming the .ksc extension is registered by k95regtl,
;   create a shortcut for every needed hostmode configuration.
;   Set the work directory in the properties contextmenu of the
;   new shortcut to an existing directory. Host.cfg will be put
;   there.  If you leave the work directory unchanged you get the
;   default behavior (host.cfg in the scripts directory).
;
undef _config_changed
undef _userdb_changed
undef _userdb_locked
undef _userdb_loaded
undef _current_user
undef _current_id

if < \v(xversion) 1120 stop 1 K95 1.1.20 or later required.

asg _k95program \freplace(\v(exedir)k95.exe,/,\\)
asg _k95d_program \freplace(\v(exedir)k95d.exe,/,\\)
if eq "\v(system)" "OS/2" asg _k95program \freplace(\v(exedir)k2.exe,/,\\)

; CLS is built in now.
; def CLS write screen \27[H\27[2J

def UNLOCK {
    if exist \m(_lockfile) delete \m(_lockfile)
    undef _userdb_locked
}

def LOCK {
    if def _userdb_locked end 1
    if exist \m(_lockfile) {
	echo LOCKFILE \m(_lockfile) in use by:
	type \m(_lockfile)
	end 2
    }
    open write \m(_lockfile)
    if fail end 3
    writeln file PROPRIETOR
    if fail end 4
    close write
    if fail end 5
    def _userdb_locked 1
    end 0
}
def HOLDSCREEN echo, getc \%9 {Press Enter to continue: }, goto \%1

def MAKEVAR2 _assign \%1 \%2

def MAKEVAR {
    if = \findex(=,\%1,1) 0 end
    asg \%9 _\freplace(\%1,=,\32)
    makevar2 \%9
}

; The following code was added to accomodate the new Windows multi-user
; friendly directory layouts introduced with version 1.1.21.  We have
; check several locations for the directories that hostmode uses and
; create them in \v(appdata) if the do not exist at all.

if exist \v(common)SCRIPTS/hostmode.ksc {
   asg _hostscripts \v(common)
}

if exist \v(appdata)SCRIPTS/hostmode.ksc {
   asg _hostscripts \v(appdata)
}

if directory \v(exedir)USERS {
    asg _hostroot \v(exedir)
    forward FOUNDDIRS
}
if directory \v(startup)INCOMING {
    asg _hostroot \v(startup)
    forward FOUNDDIRS
}

if directory \v(appdata)INCOMING {
    asg _hostroot \v(appdata)
    forward FOUNDDIRS
}

cls
echo {Could not find necessary hostmode dirs, creating them...}
if not directory \v(appdata)USERS if not exist \v(appdata)USERS {
   mkdir \v(appdata)USERS
}
if not directory \v(appdata)PUBLIC if not exist \v(appdata)PUBLIC {
   mkdir \v(appdata)PUBLIC
}
if not directory \v(appdata)INCOMING if not exist \v(appdata)INCOMING {
   mkdir \v(appdata)INCOMING
}
if not directory \v(appdata)LOGS if not exist \v(appdata)LOGS {
   mkdir \v(appdata)LOGS
}
if not directory \v(appdata)TMP if not exist \v(appdata)TMP {
   mkdir \v(appdata)TMP
}

if not exist \v(appdata)USERS/hostmode.txt {
   copy \m(_hostscripts)USERS/*.TXT \v(appdata)USERS
}

if not exist \v(appdata)PUBLIC/hostuser.txt {
   copy \m(_hostscripts)PUBLIC/*.TXT \v(appdata)PUBLIC
}

echo
echo {Directories created in \v(appdata)...}
asg _hostroot \v(appdata)
holdscreen FOUNDDIRS

:FOUNDDIRS

asg _maxusers 100 ; In case there is no config file

def _haveconfig 0         ; Have not found config file yet
asg _configfile host.cfg  ; Use config file in current directory
echo STARTING...
if not exist \m(_hostroot)\m(_configfile) {
    if not exist \m(_hostscripts)scripts/host.cfg {
	ec File \m(_configfile) not found - using built-in configuration
        sleep 3
        forward NOCONFIG
    }

    if exist \m(_hostscripts)scripts/host.cfg {
        xecho COPYING \m(_hostscripts)scripts/host.cfg to \m(_hostroot)...
        copy \m(_hostscripts)scripts/host.cfg \m(_hostroot)
        if fail {
           echo FAILED
           forward NOCONFIG
        }
        echo OK
    }
}
echo Configuration file = \m(_hostroot)\m(_configfile)
open read \m(_hostroot)\m(_configfile)
if fail forward NOCONFIG
def _haveconfig 1
echo Loading configuration...
while true { read aline, if fail break, makevar \m(aline) }

:NOCONFIG
sleep 1

dcl \&u[\m(_maxusers)]
if not def _lockfile asg _lockfile \m(_usertree)/USERS.LCK

define SAVEUSERDB {
    if exist \fdef(_userbak) del \fdef(_userbak)
    rename \fdef(_userfile) \fdef(_userbak)
    if fail echo {Warning - Failure to back up user database}
    open write \fdef(_userfile)
    if fail {
	echo Failed to open \fdef(_userfile)
        holdscreen LBL_9
    }
    for \%i 1 \&u[0] 1 {
	writeln file \&u[\%i]
	if fail {
	    ec, ec Error writing record \%i to \fdef(_userfile)
	    ec Old version preserved as \fdef(_userbak)
	    break
	}
    }
    close write
    asg \%9 \v(status)
    UNLOCK
    echo
    if not = \%9 0 echo {WARNING - Failed to close \fdef(_userfile)}
    else echo {\fdef(_userfile) saved: \&u[0] records}
    undef _userdb_changed
    undef _userdb_loaded
    undef _current_user
    end \%9
}

define SAVECONFIG {
    asg \%8 \freplace(\m(_hostroot)\m(_configfile),\\,/)
    asg \%9 \freplace(\%8,.CFG,.BAK)
    if exist \%9 delete \%9
    rename \%8 \%9
    if fail echo WARNING - Failed to back up "\%8" to "\%9"
    open write \m(_hostroot)\m(_configfile)
    if fail { echo Failed to open \m(_configfile), end 1 }
    writeln file SESSIONS=\m(_sessions)
    writeln file MAXUSERS=\m(_maxusers)
    writeln file INACTIVITY=\m(_inactivity)
    writeln file LOGINTIME=\m(_logintime)
    writeln file HOSTPORT=\m(_hostport)
    writeln file COMMPORT={\m(_commport)}
    writeln file COMSPEED=\m(_comspeed)
    writeln file MODEM=\m(_modem)
    writeln file ANONOK=\m(_anonok)
    writeln file LOGGING=\m(_logging)
    writeln file DLINCOMING=\m(_dlincoming)
    writeln file MSGMAX=\m(_msgmax)
    writeln file PROTOCOL=\m(_protocol)
    writeln file XFERMODE=\m(_xfermode)
    writeln file OWNER={\m(_owner)}
    writeln file HERALD={\m(_herald)}
    writeln file PUBLIC=\m(_public)
    writeln file INCOMING=\fdef(_incoming)
    writeln file LOGDIR=\fdef(_logdir)
    writeln file USERTREE=\fdef(_usertree)
    writeln file TMPDIR=\fdef(_tmpdir)
    writeln file USERFILE=\fdef(_userfile)
    writeln file GREETING=\fdef(_greeting)
    writeln file HELPFILE=\fdef(_helpfile)
    writeln file MSGFILE=\fdef(_msgfile)
    close write
    if success def _config_changed
    else end 1
}

; SPLIT and GETFIELDS are for parsing user database records
;
def SPLIT {
    asg \%9 \findex(_,\%1)
    asg _LEFT \fbreak(\%1,_)
    asg _RIGHT \fsubstr(\%1,\%9+1)
}

def GETFIELDS {
    split {\%1}
    asg U_ID \m(_LEFT)
    split {\m(_RIGHT)}
    asg U_PW \m(_LEFT)
    split {\m(_RIGHT)}
    asg U_PR \m(_LEFT)
    split {\m(_RIGHT)}
    asg U_NM \m(_LEFT)
    split {\m(_RIGHT)}
    asg U_AD \m(_LEFT)
    split {\m(_RIGHT)}
    asg U_TP \m(_LEFT)
    split {\m(_RIGHT)}
    asg U_EM \m(_LEFT)
}

:BEGIN ; Program execution starts here...

def _priv_cd  1				; Symbolic constants.
def _priv_dos 2

                                        ; Remember startup values of these
if tapi asg _myport {tapi \v(line)}
if not def _myport asg _myport \v(line)	
asg _myspeed \v(speed)
asg _mymodem \v(modem)

set exit warning off			; Now deassign all comm devices
close

:LOOP
asg _userbak \freplace(\m(_userfile),.DAT,.BAK)
cls
echo K-95 Host Mode Management
echo
if def _userdb_locked echo * User database is locked *
else echo User database is not loaded
echo
echo { 1 - Start host mode}
echo { 2 - View configuration}
echo { 3 - Change configuration}
echo { 4 - Save configuration}
echo { 5 - Read messages from users}
echo { 6 - Leave a message for a user}
echo { 7 - View/edit current greeting message}
echo { 8 - Post a new greeting message}
echo { 9 - Manage user database}
echo {10 - Help}
echo {11 - Exit}
echo
ask \%a {Your choice: }
if not def \%a goto loop
if not num \%a {
    ec "\%a" - Not a number
    sleep 1
    goto loop
}
if > \%a 0 if not > \%a 11 forward LBL_\%a
echo "\%a" - out of range
sleep 1
goto loop

:LBL_1
cls
echo Start Host Mode...
echo
echo { 1 - Telnet}
echo { 2 - Dialup}
echo { 3 - Direct COM port}
echo { 4 - Return to main menu}
echo
ask \%a {Your choice: }
if not def \%a goto LBL_1
if not num \%a {
    ec "\%a" - not a number
    sleep 1
    goto LBL_1
}
if > \%a 0 if not > \%a 4 forward START_\%a
echo "\%a" - out of range
sleep 1
goto LBL_1

:START_1 ; Telnet
cls
echo
if def _hostport forw start_1a
echo HOSTPORT not configured.
echo Please choose "Change configuration".
holdscreen LOOP

:START_1A
echo Starting Kermit 95 mode on TCP port \m(_hostport).
getok {OK? }
if fail goto loop
if not def _config_changed forward start_1b
echo
getok {Configuration has changed - do you want to save it first? (y/n) }
if success saveconfig

:START_1B
if eq "\v(system)" "WIN32" forward S1BWIN32
if not eq "\v(system)" "OS/2" {
    echo Sorry - so far this only works for Windows 95/NT and OS/2...
    holdscreen LOOP
}
if > \m(_sessions) 1 {
    echo To start a TCP/IP host mode listener in OS/2 please follow the
    echo instructions in DOCS\MANUAL\OS2K95.HTML.
    holdscreen LOOP
}
run start \m(_k95program) \m(_hostscripts)scripts/hosttcp.ksc
goto loop

:S1BWIN32
if > \m(_sessions) 1 -
 run start -
  \m(_k95d_program) \m(_hostport) "take \m(_hostscripts)scripts/host.ksc, exit"
else run start \m(_k95program) \m(_hostscripts)scripts/hosttcp.ksc
goto loop

:START_2
cls
echo
if not eq "\m(_commport)" "" forward START_2B
echo COMMPORT not configured.
getok {Use TAPI (Windows modem device)? }
if success { asg _commport tapi, asg _modem tapi, goto start_2b }

echo
echo The following settings were made in your K-95 initialization file:
echo
echo { set modem \m(_mymodem)}
echo { set port \m(_myport)}
echo { set speed \m(_myspeed)}
echo
getok {Use them? }
if success forward START_2C

:START_2A
echo
echo Please "Change configuration" to choose or modify serial device settings.
holdscreen LOOP

:START_2B
echo Starting Kermit 95 host mode...
echo Will wait for a call on port \m(_commport).
if def _comspeed echo Speed: \m(_comspeed)
echo Modem: \m(_modem)

:START_2C
getok {OK? }
if fail goto loop
if not def _config_changed forward start_2d
echo
getok {Configuration has changed - do you want to save it first? (y/n) }
if success saveconfig

:START_2D
run start \m(_k95program) \freplace(\m(_hostscripts)scripts/hostmdm.ksc,/,\\)
goto LOOP

:START_3
cls
echo
if def \m(_commport) forward START_3C
echo COMMPORT not configured.
if equal "\v(connection)" "serial" forward START_3B
forward START_3A
:START_3B
echo
echo The following settings were made in your K-95 initialization file:
echo
if tapi echo { set port tapi \v(line)}
else echo { set port \v(line)}
echo { set speed \v(speed)}
echo
getok {Use them? }
if success forward START_3C

:START_3A
echo
echo Please "Change configuration" to choose or modify serial device settings.
holdscreen LOOP

:START_3C
if not def _config_changed forward start_3d
echo
getok {Configuration has changed - do you want to save it first? (y/n) }
if success saveconfig

:START_3D
echo
echo Using direct connection on \m(_commport) at \m(_comspeed) bps.
echo
echo Starting Kermit 95 host mode...
run start \m(_k95program) \freplace(\m(_hostscripts)scripts/hostcom.ksc,/,\\)

:START_4
goto loop

:LBL_2 ; View configuration
if = \m(_haveconfig) 0 {
    echo Can't find configuration file
    holdscreen LOOP
}
echo
echo SESSIONS=\m(_sessions)
echo MAXUSERS=\m(_maxusers)
echo INACTIVITY=\m(_inactivity)
echo HOSTPORT=\m(_hostport)
echo COMMPORT=\m(_commport)
echo COMSPEED=\m(_comspeed)
echo ANONOK=\m(_anonok)
echo LOGGING=\m(_logging)
echo DLINCOMING=\m(_dlincoming)
echo MSGMAX=\m(_msgmax)
echo PROTOCOL=\m(_protocol)
echo XFERMODE=\m(_xfermode)
echo OWNER=\m(_owner)
echo HERALD=\m(_herald)
echo PUBLIC=\m(_public)
echo INCOMING=\m(_incoming)
echo LOGDIR=\m(_logdir)
echo USERTREE=\m(_usertree)
echo TMPDIR=\m(_tmpdir)
echo USERFILE=\m(_userfile)
echo GREETING=\m(_greeting)
echo HELPFILE=\m(_helpfile)
echo MSGFILE=\m(_msgfile)
echo
clear
ask \%a Press the Enter key to return to main menu...
goto loop

:LBL_3 ; Change config
if not eq \m(_haveconfig) 0 forward getchanges
;
; Set defaults in case they don't have a config file
;
asg _sessions 1                       ; Maximum number of Telnet sessions
asg _maxusers 100                     ; Maximum number of user IDs
asg _inactivity 1200                  ; Inactivity limit (seconds)
asg _anonok 1                         ; Anonymous logins OK (0 = not OK)
asg _logging 1                        ; Logging enabled (0 = skip logging)
asg _dlincoming 0                     ; OK to download from INCOMING directory
asg _msgmax 200                       ; Longest message size (lines)
asg _protocol kermit                  ; Default file transfer protocol
asg _xfermode binary                  ; Default file transfer mode
asg _owner THE PROPRIETOR             ; Substitute your name, company name, etc
asg _herald Welcome to K-95 Host Mode ; 
asg _public   \m(_hostroot)PUBLIC     ; Directory that users can get files from
asg _incoming \m(_hostroot)INCOMING   ; Directory that users can send file to
asg _logdir   \m(_hostroot)LOGS       ; Directory for host-mode logs
asg _usertree \m(_hostroot)USERS      ; Root of user directory tree
asg _tmpdir   \m(_hostroot)TMP        ; Directory for temp files
asg _userfile \m(_usertree)/USERS.DAT ; User database file
asg _greeting \m(_usertree)/GREETING.TXT ; Message/greeting text filename
asg _helpfile \m(_usertree)/HOSTMODE.TXT ; Host-mode help file
asg _msgfile  \m(_usertree)/MESSAGES.TXT ; Messages for proprietor

:GETCHANGES

:CF0
ask \%a { Maximum TCP/IP host sessions [\m(_sessions)]: }
if not def \%a forward CFA
if not numeric \%a goto CF0
getok { SESSIONS=\%a, OK? (y/n): }
if fail goto CF0
asg _config_changed 1
asg _sessions \%a

:CFA
ask \%a { Maximum number of user IDs [\m(_maxusers)]: }
if not def \%a forward CF1
if not numeric \%a goto CFA
getok { MAXUSERS=\%a, OK? (y/n): }
if fail goto CFA
asg _config_changed 1
asg _maxusers \%a

:CF1
ask \%a { Inactivity limit, seconds [\m(_inactivity)]: }
if not def \%a forward CF2
if not numeric \%a goto CF1
getok { INACTIVITY=\%a, OK? (y/n): }
if fail goto CF1
asg _config_changed 1
asg _inactivity \%a
:CF2
ask \%a { TCP port for incoming TCP/IP connections [\m(_hostport)]: }
if not def \%a forward CF3
getok { HOSTPORT=\%a, OK? (y/n): }
if fail goto CF2
asg _config_changed 1
asg _hostport \%a
:CF3
ask \%a { Communications port for incoming dialups [\m(_commport)]: }
if not def \%a forward CF4
getok { COMMPORT=\%a, OK? (y/n): }
if fail goto CF3
asg _config_changed 1
asg _commport \%a
:CF4
ask \%a { Speed of \m(_commport) [\m(_comspeed)]: }
if not def \%a goto CF5
if < 0 \findex(:\%a:,:14400:19200:38400:28800:57600:115200:) forward CF4A
if < 0 \findex(:\%a:,:230400:1200:2400:9600:300:600:1800:4800:) forward CF4A
echo "\%a" - Unknown speed
goto CF4
:CF4A
getok { SPEED=\%a, OK? (y/n): }
if fail goto CF4
asg _config_changed 1
asg _comspeed \%a
:CF5
ask \%a { Type of modem on \m(_commport) [\m(_modem)]: }
if not def \%a forward CF6
getok { MODEM=\%a, OK? (y/n): }
if fail goto CF5
set modem type \%a
if fail {
    echo "\%a" - Unknown modem type
    goto CF5
}
asg _config_changed 1
asg _modem \%a
:CF6
ask \%a { Anonymous guest logins OK (1 = yes, 0 = no) [\m(_anonok)]: }
if not def \%a forward CF7
if not num \m(_anonok) goto CF6
getok { ANONOK=\%a, OK? (y/n): }
if fail goto CF6
asg _config_changed 1
asg _anonok \%a
:CF7
ask \%a { Maximum number of lines for a message [\m(_msgmax)]: }
if not def \%a forw CF8
if not num \m(_msgmax) goto CF7
getok { MSGMAX=\%a, OK? (y/n): }
if fail goto CF7
asg _config_changed 1
asg _msgmax \%a
:CF8
ask \%a { Default file transfer protocol [\m(_protocol)]: }
if not def \%a forw CF9
set protocol \%a
if fail {
    echo "\%a" - Bad protocol
    goto CF8
}
getok { PROTOCOL=\%a, OK? (y/n): }
if fail goto CF8
asg _config_changed 1
asg _protocol \%a
:CF9
ask \%a { Default file transfer mode (text or binary) [\m(_xfermode)]: }
if not def \%a forw CF10
set file type \%a
if fail goto CF9
getok { XFERMODE=\%a, OK? (y/n): }
if fail goto CF9
asg _config_changed 1
asg _xfermode \%a
:CF10
ask \%a { PC owner's or company's name for users to see [\m(_owner)]: }
if not def \%a forw CF11
getok { OWNER=\%a, OK? (y/n): }
if fail goto CF10
asg _config_changed 1
asg _owner \%a
:CF11
ask \%a { Main menu title [\m(_herald)]: }
if not def \%a forw CF12
getok { HERALD=\%a, OK? (y/n): }
if fail goto CF11
asg _config_changed 1
asg _herald \%a
:CF12
ask \%a { Directory readable by all users [\m(_public)]: }
if not def \%a forw CF13
getok { PUBLIC=\%a, OK? (y/n): }
if fail goto CF12
asg _config_changed 1
asg _public \%a
:CF13
ask \%a { Directory writeable by all users [\m(_incoming)]: }
if not def \%a forw CF14
getok { INCOMING=\%a, OK? (y/n): }
if fail goto CF13
asg _config_changed 1
asg _incoming \%a
:CF14
ask \%a { Directory for temporary files [\m(_tmpdir)]: }
if not def \%a forw CF15
getok { TMPDIR=\%a, OK? (y/n): }
if fail goto CF14
asg _config_changed 1
asg _tmpdir \%a
:CF15
ask \%a -
{ OK to download from INCOMING directory (1 = yes, 0 = no) [\m(_dlincoming)]: }
if not def \%a forw CF16
if not numeric \%a goto CF15
getok { DLINCOMING=\%a, OK? (y/n): }
if fail goto CF15
asg _config_changed 1
asg _dlincoming \%a
:CF16
ask \%a { Keep log files (1 = yes, 0 = no) [\m(_logging)]: }
if not def \%a forw CF17
getok { LOGGING=\%a, OK? (y/n): }
if fail goto CF16
asg _config_changed 1
asg _logging \%a
:CF17
ask \%a { Directory for log files [\m(_logdir)]: }
if not def \%a forw CF18
getok { LOGDIR=\%a, OK? (y/n): }
if fail goto CF17
asg _config_changed 1
asg _logdir \%a
:CF18
ask \%a { Root of user directory tree [\m(_usertree)]: }
if not def \%a forw CF19
getok { USERTREE=\%a, OK? (y/n): }
if fail goto CF18
asg _config_changed 1
asg _usertree \%a
:CF19
ask \%a { User database file [\m(_userfile)]: }
if not def \%a forw CF20
getok { USERFILE=\%a, OK? (y/n): }
if fail goto CF19
asg _config_changed 1
asg _userfile \%a
:CF20
ask \%a { Login message file for all users [\m(_greeting)]: }
if not def \%a forw CF21
getok { GREETING=\%a, OK? (y/n): }
if fail goto CF20
asg _config_changed 1
asg _greeting \%a
:CF21
ask \%a { File displayed when user requests help [\m(_helpfile)]: }
if not def \%a forw CF22
getok { HELPFILE=\%a, OK? (y/n): }
if fail goto CF21
asg _config_changed 1
asg _helpfile \%a
:CF22
ask \%a { File in which you receive messages from users [\m(_msgfile)]: }
if not def \%a forw CFXX
getok { MSGFILE=\%a, OK? (y/n): }
if fail goto CF22
asg _config_changed 1
asg _msgfile \%a
:CFXX
echo
clear
ask \%a Press the Enter key to return to main menu...
goto loop

:LBL_4 ; Save config
write screen Saving \m(_configfile)...
saveconfig
if success echo OK
holdscreen LOOP

:LBL_5 ; Read messages
echo
echo Sorry - this is not really a mail program.
echo Starting notepad to view the message file.
echo Use notepad to remove, copy messages, etc.
echo As yet there is no reply reply mechanism.
echo To reply, just choose "Leave message" from
echo from the main menu...
sleep 1
run notepad \freplace(\m(_msgfile),/,\\)
goto loop

:LBL_6 ; Leave message for a user
cls
echo Leave a message...
echo
:MSGTO
ask \%u {To: }
if not def \%u goto MSGTO
if dir \m(_usertree)/\%u forward SENDMESSAGE
echo "\%u" - No such user [\m(_usertree)\%u]
holdscreen LOOP

:LBL_7 ; View / edit greeting message
cls
echo Starting notepad.
echo Make any desired changes and then save the file...
sleep 1
run notepad \freplace(\m(_greeting),/,\\)
goto loop

:LBL_8 ; Post message to all users
cls
echo Post a message for all users...
echo
:MSGTO
def \%u All
forward sendmessage

:LBL_9 ; Manage user database
cls
echo User database management functions...
echo
asg \%a {Database filename: \fdef(_userfile)}
if def _userdb_loaded asg \%a \%a - Loaded
else asg \%a \%a - Not loaded
if def _userdb_changed asg \%a \%a - Changed
asg \%b {Current user:      }
if def _current_user asg \%b \%b\m(_current_id)
else asg \%b \%b(none)
echo \%a
if def _userdb_loaded echo Users:             \&u[0]
echo \%b
echo
if exist \fdef(_userfile) {
    echo { 1 - Load user database}
} else {
    echo { 1 - Create user database}
}
echo { 2 - Display user database}
echo { 3 - Look up a user / set current user}
echo { 4 - Add a new user}
echo { 5 - Remove current user}
echo { 6 - Modify current user}
echo { 7 - Save and unload user database}
echo { 8 - Remove lock}
echo { 9 - Return to main menu}
echo
ask \%a {Your choice: }
if not def \%a goto LBL_9
if not num \%a { ec "\%a" - not a number, holdscreen LBL_9 }
if > \%a 0 if not > \%a 9 forward USER_\%a
echo "\%a" - out of range
holdscreen LBL_9

:USER_1 ; Load database
if not exist \fdef(_userfile) forward USER_CREATE_DB
if not def _userdb_loaded forward USER_LOAD
echo
echo User database already loaded.
if not def _userdb_changed goto LBL_9
echo You have made changes to it.
getok {Do you want to abandon your changes? }
if success forward USER_LOAD
echo Load canceled.
holdscreen LBL_9

:USER_LOAD
lock
if fail { echo Sorry - can't lock user database., holdscreen LBL_9 }
open read \fdef(_userfile)
if fail { echo {Can't open \fdef(_userfile)}, unlock, goto loop }
asg \&u[0] 0
for \%i 1 \m(_maxusers) 1 {
    read \&u[\%i]
    if fail break
    increment \&u[0]
}
close read
def _userdb_loaded 1
ec
ec \fdef(_userfile) loaded: \&u[0] user(s).
holdscreen LBL_9

:USER_CREATE_DB ; Create database
open write \fdef(_userfile)
if fail { echo Can't create \fdef(_userfile), holdscreen LBL_9 }
close write
if fail { echo Can't close \fdef(_userfile), holdscreen LBL_9 }
asg _userdb_loaded 1
asg \&u[0] 0
echo \fdef(_userfile) created, now use "Add" to create user IDs.
holdscreen LBL_9

:USER_8
if not exist \m(_lockfile) {
    ec
    ec Lock not found.
    holdscreen LBL_9
}
dir \m(_lockfile)
echo
type \m(_lockfile)
echo
getok {OK to remove? }
if success unlock
holdscreen LBL_9

:USER_9
goto LOOP

:USER_2
if not def _userdb_loaded { ec User database not loaded, forward user_2x }
echo \&u[0] user(s) in \fdef(_userfile).
if def _userdb_changed echo Changes have not been saved.
else echo No changes have been made.
ec
for \%i 1 \&u[0] 1 { echo \%i. \&u[\%i] }
:USER_2X
holdscreen LBL_9

:USER_3 ; Look up a user
if not def _userdb_loaded {
    ec
    ec User database not loaded
    holdscreen LBL_9
}
if < \&u[0] 1 { ec, ec No users in database, holdscreen LBL_9 }
echo
echo
ask \%u {User ID or name to look up: }
asg _current_user
for \%i 1 \&u[0] 1 {
    getfields {\&u[\%i]}
    if eq "\m(U_ID)" "\%u" { asg _current_user \%i, break }
}
if not def _current_user {
    ec \%u - Not found
    holdscreen LBL_9
} else {
    ec \%u = user \m(_current_user)
}
getfields {\&u[\m(_current_user)]}
asg _current_id \m(U_ID)

ec User ID:   \m(U_ID)
ec Password:  \m(U_PW)
ec Privs:     \m(U_PR)
ec Name:      \m(U_NM)
ec Address:   \m(U_AD)
ec Phone:     \m(U_TP)
ec Email:     \m(U_EM)
holdscreen LBL_9

:USER_4 ; Add a new user
if not def _userdb_loaded { ec, ec User database not loaded, holdscr LBL_9 }
ec
ec
ask \%u {User ID: }
if not def \%u goto LBL_9
for \%i 1 \&u[0] 1 {
     split \&u[\%i]
     if eq "\%u" "\m(_LEFT)" {
	 echo User "\%u" already exists.
	 holdscr LBL_9
    }
}
:USER_PW
ask \%p {Password for \%u: }
ask \%q {Retype password: }
if not eq "\%p" "\%q" {
   echo Passwords do not match - please try again.
   goto USER_PW
}
:USER_PR
echo
echo Enter privilege level...
echo { 0 = None}
echo { 1 = Allowed to CD to any directory}
echo { 2 = Allowed to give DOS commands}
echo { 3 = 1 and 2}
echo
undef \%x
while not def \%x {
    ask \%x {Privilege level (0-2): }
}
if not numeric \%x {
    ec Please enter a digit: 0 thru 3.
    goto USER_PR
}
echo Privilege level for \%u: \%x
getok {OK? }
if fail goto USER_PR
:USER_ETC
ask \%n {User's name (optional): }
ask \%a {User's address (optional): }
ask \%t {User's phone number (optional): }
ask \%e {User's email address (optional): }
ec
ec User ID:   \%u
ec Password:  \%p
ec Privilege: \%x
ec Name:      \%n
ec Address:   \%a
ec Phone:     \%t
ec Email:     \%e
ec
getok {OK to enter? }
if fail goto LBL_9
asg \%i \&u[0]
incr \%i
ec Adding user number \%i...
asg \&u[\%i] \%u_\f.oox(\%p)_\%x_\%n_\%a_\%t_\%e_
asg \&u[0] \%i
asg _userdb_changed 1
holdscreen LBL_9

:USER_7 ; Save database
saveuserdb
holdscreen LBL_9

:USER_5 ; Remove a user
if not def _userdb_loaded { ec, ec User database not loaded, holdscr LBL_9 }
if def _current_user forward USER_REMOVE
echo No current user, please use Lookup to select a user to remove.
holdscreen LBL_9
:USER_REMOVE
echo
echo Current user is \m(_current_id):
echo \&u[\m(_current_user)]
getok {OK to remove? }
if fail {
    ec \m(_current_id) not removed
    holdscreen LBL_9
}
decrement \&u[0]
for \%i \m(_current_user) \&u[0] 1 {
     asg \&u[\%i] \&u[\%i+1]
}
echo
echo User \m(_current_id) removed.
asg _userdb_changed 1
echo You should go through the user's files yourself by hand and decide
echo what to do with them.
asg _current_id
asg _current_user
holdscreen LBL_9

:USER_6 ; Modify current user info
if def _current_user forward USER_CHANGE
echo No current user - please use Lookup to select a user.
holdscreen LBL_9
:USER_CHANGE
ec Current user:
ec
ec User ID:   \m(U_ID)
ec Password:  \m(U_PW)
ec Privilege: \m(U_PR)
ec Name:      \m(U_NM)
ec
asg \%p \m(U_PW)
getok {Change this user's password? }
if fail { echo Password not changed, forward U6_PR }
:PASS_AGAIN
ec
ask \%p {New password:    }
ask \%q {Retype password: }
if not eq "\%p" "\%q" {
    ec Passwords do not match - please try again.
    goto PASS_AGAIN
}
getok {Change \m(U_ID)'s password to "\%p"? }
if fail { echo Password not changed, forward U6_PR }
echo Password changed.
asg _userdb_changed 1
:U6_PR
asg \%x \m(U_PR)
echo \m(U_ID)'s privilege level = \m(U_PR)
getok {Change it? }
if fail { echo Privilege not changed, forward USER_XX }
:U6LOOP
echo
echo Enter privilege level...
echo { 0 = None}
echo { 1 = Allowed to CD to any directory}
echo { 2 = Allowed to give DOS commands}
echo { 3 = 1 and 2}
echo
undef \%x
while not def \%x {
    ask \%x {Privilege level (0-2): }
}
if not numeric \%x { ec Please enter a digit: 0 thru 3., goto U6LOOP }
echo Privilege level for \m(U_ID): \%x
getok {OK? }
if fail goto U6LOOP
asg _userdb_changed 1

:USER_XX
if def _userdb_changed -
asg \&u[\m(_current_user)] -
  \m(U_ID)_\f.oox(\%p)_\%x_\m(U_NM)_\m(U_AD)_\m(U_TP)_\m(U_EM)
holdscreen lbl_9

:LBL_10 ; Help
if not exist \m(_usertree)hostmode.txt {
    echo, echo "\m(_usertree)hostmode.txt" not found
    holdscreen LOOP
}
run notepad \freplace(\m(_usertree)hostmode.txt,/,\\)
goto loop

:LBL_11 ; Exit
if not def _config_changed if not def _userdb_changed forward exit
echo
if def _config_changed {
    echo Configuration is changed.
    getok {Do you want to save it? }
    if success saveconfig
}
if def _userdb_changed {
    echo User database is changed.
    getok {Do you want to save it? }
    if success saveuserdb
}
:EXIT
unlock
echo
exit

; Message writer...

:SENDMESSAGE
ask \%s {Subject: }
def \%i 0
echo Enter the message, finish by entering period (.) alone on a line:
echo
dcl \&a[200]

:MSGLOOP
incr \%i
if > \%i 200 goto MSGDONE
ask \&a[\%i] {\flpad(\%i,3,0)> }
if not eq "\&a[\%i]" "." goto MSGLOOP

:MSGDONE
asg \%n \%i
echo
getok {OK to send to \%u? (y/n): }
if fail goto loop
if eq "\%u" "All" asg \%f \m(_greeting)
else asg \%f \m(_usertree)/\%u.MSG
echo Opening \%f...
sleep 1
open append \%f
if fail { echo Can't open message file \%f, forw msgend }
writeln file Date: \v(date) \v(time)
writeln file To: \%u
writeln file From: \m(_owner)
writeln file Subject: \%s
writeln file
for \%i 1 \%n 1 { writeln file \&a[\%i] }
close write
if fail { echo Can't close message file \%f, goto msgend }

:MSGEND
dcl \&a[0]
clear
ask \%a Press the Enter key to return to main menu...
goto LOOP

; End of HOSTMODE.KSC
