1 SUB M11INT (INT.CODE%) & 2 !******************************************************************** & ! & ! M11INT & ! & ! Initializes the system and puts up the first screens & ! & ! & !******************************************************************** & ! & ! Subprogram : M11INT & ! Version : 1A & ! Programmer : John Montrym & ! Jean Fullerton & ! Releaser : & ! & ! 11 !-------------------------------------------------------------------- & ! & ! & ! C O P Y R I G H T & ! & ! & !-------------------------------------------------------------------- & ! & ! & ! Description & ! & ! & ! This subprogram performs the top-level tasks of the Smart Mailer & ! system, such as the welcome screen, and the main menu. & ! It also takes care of the Mailing List File name entry and loads & ! the system parameters into MAPPRM. & ! The argument INT.CODE% is used to instruct M11INT what to & ! do on entry. If INT.CODE% = 1% then we are being & ! called to start a session in Smart Mailer so we should put & ! up the welcome screen. If INT.CODE% = 2% then & ! we should skip the opening dialog and go straight to the & ! main menu. & ! & ! & ! M11INT returns with M11.FUNC$ set according to what was & ! typed, in response to the main menu: & ! & ! Desired function M11.FUNC$ & ! ---------------- --------- & ! & ! Update the mailing list U & ! Print (sub)list P & ! Display (sub)list D & ! Category maintenance C & ! Sublist maintenance S & ! List Processing File W & ! & ! End Smart Mailer session E & ! & ! & ! & ! Calling module: SMAIL & ! & ! & ! Assumptions: & ! & ! * SMPAR.DAT is in the same account as SMAIL.TSK and it contains & ! the system parameters. & ! & ! System Dependent Functions: & ! & ! * determining the type of terminal & ! & ! * setting up the terminal for screen work & ! & ! * all code associated with file specs & ! & !-------------------------------------------------------------------- & ! & ! Modifications: & ! & ! 19-Mar-84 Allow a default file location. The default location & ! parameter, PRM.DEFAULT.MLF.LOC$, is the last item & ! read from the parameter file. Changed line 1600. & ! Added line 1680. & ! & ! 19-Mar-84 Allow non-privileged users to specify a private & ! disk and/or their own account in the file spec for & ! the mailing list file. This fixes a bug in V 1.0A & ! which prevented non-privileged users from accessing & ! files in their own account. Subroutine 10100 was & ! changed and line 4190. & ! & ! 2-Aug-84 Changed privilege check for compatibility with V9 & ! RSTS. Smart Mailer V1.0 assumed a project number & ! of "1" meant privileged. See lines 1700, 4185 - & ! 4196, 19050 - 19055. & ! & !-------------------------------------------------------------------- & ! & ! Interface & ! & ! Common Areas: & ! & ! COMERR - Common area for error codes, tracebacks and messages & ! COMCON - System constants & ! COMVAR - System variables & ! & ! MAPMLF - MAP for the Mailing List File & ! MAPHDR - Area for the Mailing List File header record & ! MAPSEL - Area for the sublist selection & ! MAPSCR - Screen variables & ! MAPPRM - Area for system parameters & ! & ! Arguments: & ! & ! INT.CODE% - Flag to indicate whether to put up the initial & ! screen (1% = first time, 2% = subsequent time) & ! 300 !-------------------------------------------------------------------- & ! & ! Channel Assignments & ! & ! Channel Filename Map name Status at entry/exit & ! ------- ---------- -------- -------------------- & ! CH.KB% closed / open (mode 8) & ! CH.ADD% user-def MAPMLF closed / open & ! CH.PARM% SMPAR.DAT closed / closed & ! CH.SCR% SMSCR.DAT closed / open & ! & !******************************************************************** & ! & ! & ! Variables and Arrays & ! & ! & ! & ! ANS% User answer to Smart Mailer question (number) & ! ANS$ User answer to Smart Mailer question (string) & ! BASE% Offset for placement on the screen & ! DF$ Default answer & ! ERL Line where error occurred & ! ERR Set to error after error & ! F.END% Flag to indicate that the user typed 'END' or ^Z & ! HEADER.MISSING% Flag to inidicate that the Mailing List File header & ! if not there & ! I% loop variable & ! INT.CODE% M11INT argument & ! PROG.NUM% Programmer number & ! PROG.NUM$ Programmer number & ! PROJ.NUM% Project number & ! PROJ.NUM$ Project number & ! SLEN% Length of the Mailing List File header record & ! SWITCH.TO.VT52$ Command string to switch a VT100 to VT52 mode & ! T% Number to indicate the type of terminal & ! WORK$ Temporary work variable & ! 600 !******************************************************************** & ! & ! & ! Common Declarations & ! & ! & !******************************************************************** & 650 !******************************************************************** & ! & ! & ! Map Statements & ! & ! & !******************************************************************** & & 700 !-------------------------------------------------------------------- & ! & ! Subprograms & ! & ! & ! M11SCW Writes a line of text to the CRT & ! M11SCR Reads a line of text from the CRT & ! M11SCD Displays a screen full of text on the CRT & ! & ! 800 !-------------------------------------------------------------------- & ! & ! Subroutines & ! & ! & ! 11000 Reads in the printer parameters from the Parameter & ! File and transfers them to the parameter arrays & ! & ! 14800 Displays an informational message for the user & ! & ! 14900 Displays an error message and waits for the user & ! to acknowledge it & ! & !-------------------------------------------------------------------- & ! & ! Functions & ! & ! & ! 15100 FN.GET.DATA% Returns the value of the number on & ! the next data line in the parameter & ! file & ! & ! 15200 FN.GET.DATA$ Returns the string data from the & ! next line of the parameter file & ! & ! 15300 FN.TERM% Returns the type of terminal the user is & ! running from & ! & 1000 !******************************************************************** & ! & ! & ! S T A R T S U B P R O G R A M L O G I C & ! & ! & !******************************************************************** & & ON ERROR GOTO 19000 & \ ERR.CALLNAM$ = ERR.PROGNAM$ ! Save the calling subprogram & \ ERR.PROGNAM$ = "M11INT VER:01" ! Set up our name. & \ ERR.SUBNAM$ = "" & ! Set standard error trap. & ! Set up COMMON for error reporting. & & \ M11.EXIT.STATUS% = FALSE% & \ GO TO 5000 IF INT.CODE% = 2% & ! If we are continuing a session, bypass the initialization. & ! Otherwise go do the welcome stuff, first. & 1400 !-------------------------------------------------------------------- & ! & ! Initialize System & ! & !-------------------------------------------------------------------- & & WORK$ = SYS(CHR$(12%)) & \ ACT$ = '[' + NUM1$ (ASCII (MID(WORK$,6%,1%))) + ',' & + NUM1$ (ASCII (MID(WORK$,5%,1%))) + ']' & \ IF (ASCII (MID(WORK$,26%,1%)) AND 3%) = 0% & THEN DEV$ = "SY:" & ELSE DEV$ =MID(WORK$,23%,2%)+NUM1$(ASCII(MID(WORK$,25%,1%)))+':' & ! Get the device and account where this program (.TSK file) is. & ! The SMPAR.DAT file should be on the same device and account. & 1406 M11.TSK.ACCT$ = DEV$ + ACT$ & ! Set up the account of the task file. & & 1410 ESC$ = CHR$(155%) HDR.CHR$ = CHR$ (29%) ! first header record char. SUB.CHR$ = CHR$ (30%) ! first sublist record char. DELIM$ = CHR$ (31%) ! ASCII unit separator char. ! used as address field delim CNTRL.Z% = 11% ! ASCII value for control Z CNTRL.C% = 28% ! ASCII value for control C EXIT.M11% = 2% ! Code to exit from SMAIL MAIN.MENU% = 1% ! Code to return to main menu OK% = 0% ! Code for no errors FATAL.ERROR% = -1% ! Code for a fatal error WARN% = -2% ! Code for a non-fatal error TRUE% = -1% ! Logical true value FALSE% = 0% ! Logical false value TEMP% = 1% ! Temporary sublist code PERM% = 2% ! Permenant sublist code MAX.LINES% = 30% ! Max lines in sublist def CH.KB% = 1% CH.PARM% = 2% CH.SCR% = 2% CH.ADD% = 3% CH.SORTED% = 4% CH.SORT% = 5% CH.INDEX% = 6% CH.PRT% = 9% !*\ SWITCH.TO.VT52$ = CHR$(155%) + "[?2l" ! Define some constants. 1460 OPEN "KB:" AS FILE #CH.KB% & \ T% = FN.TERM% (CH.KB%) & \ on error go to 19000 & \ GO TO 8010 UNLESS (T% > 3% AND T% < 9%) & !*\ PRINT #CH.KB%, SWITCH.TO.VT52$; IF T% = 8% & \ OPEN "KB:" AS FILE #CH.KB%, MODE 8% & ! See what kind of keyboard we're talking to. & ! Go yell at user if not on a VT52, VT100 or VT200compatible terminal & ! T = 4 (VT52), 5 (VT55), 6 (VT61), 7 (VT61C), 8 (VT100, VT200). & ! Finally, reopen keyboard in simulated block mode. & & 1470 IF T% = 8% THEN HOME.UP$ = ESC$ + "[H" ERASE.EOS$ = ESC$ + "[J" ERASE.EOL$ = ESC$ + "[K" VT52% = FALSE% ELSE HOME.UP$ = ESC$ + "H" ERASE.EOS$ = ESC$ + "J" ERASE.EOL$ = ESC$ + "K" VT52% = TRUE% END IF 1500 !-------------------------------------------------------------------- & ! & ! Read in System Parameters & ! & !-------------------------------------------------------------------- & 1510 OPEN M11.TSK.ACCT$ + "SMPAR.DAT" FOR INPUT AS FILE #CH.PARM% & ! Open system Parameter File. & 1600 PRM.DEFAULT.MLF$ = FN.GET.DATA$ & \ PRM.NEW.MLF.SIZE% = FN.GET.DATA% & \ PRM.NEW.MLF.SIZE% = 2000% IF PRM.NEW.MLF.SIZE% > 2000% & & \ PRM.SCREEN.FILE$ = FN.GET.DATA$ & \ PRM.LOC.WORK.FILES$ = FN.GET.DATA$ & !* PRM.DEFAULT.MLF.LOC$ = FN.GET.DATA$ This is new (NOT IN UPD D) & !* PRM.DEFAULT.MLF.LOC$ = "SY:" This is temp for update D & ! See line 1680 & \ PRM.LABEL.TST$ = FN.GET.DATA$ & \ PRM.LABEL.EXT$ = FN.GET.DATA$ & \ PRM.LABEL.MSG$ = FN.GET.DATA$ & \ PRM.LABEL.IDR$ = FN.GET.DATA$ & \ PRM.LABEL.NUM% = FN.GET.DATA% & \ PRM.LABEL.COP% = FN.GET.DATA% & \ PRM.LABEL.LAB% = FN.GET.DATA% & \ PRM.LABEL.MAR% = FN.GET.DATA% & \ PRM.LABEL.CHR% = FN.GET.DATA% & \ PRM.LABEL.HOR% = FN.GET.DATA% & \ PRM.LABEL.LIN% = FN.GET.DATA% & \ PRM.LABEL.VER% = FN.GET.DATA% & & \ GO SUB 11000 & \ GO TO 32767 IF ERR.CODE% <> 0% & ! Read in printer parameters. & & ! Load up all the data from the Parameter File. & 1680 PRM.DEFAULT.MLF.LOC$ = FN.GET.DATA$ PRM.DEFAULT.MLF.LOC$ = "" IF PRM.DEFAULT.MLF.LOC$ = "END" ! This parameter added after V 1.0. ! Don't accept 'END' as parameter value. PRM.WILDCARD.CHR$ = EDIT$ ( FN.GET.DATA$, 2% ) ! This parameter added for V 1.1. EOF traps to 1690 1690 CLOSE #CH.PARM% & ! Close the system Parameter File. & & 1700 !-------------------------------------------------------------------- & ! & ! & ! Determine User's Privilege & ! & ! & !-------------------------------------------------------------------- & 1710 ! ******************************************************************* ! This privilege check is not useful in V9 RSTS since a project ! number of 1 no longer means 'privileged'. Any future privilege ! checks can be added here. ! ******************************************************************* 698 ! MAP (OVR) PROJ.NUM$ = 1%, FILL$ = 1% & ! ,PROG.NUM$ = 1%, FILL$ = 1% & !\ MAP (OVR) PROJ.NUM% & ! ,PROG.NUM% & 1720 ! WORK$ = SYS (CHR$( 6%) FIP - File Processor & ! + CHR$(26%) request return job status & ! + CHR$( 0%) info on current user's job & ! + CHR$( 0%) S code & ! + STRING$ (26%, 0%)) the rest is null & ! Get current job status. & ! RSTS SYS Call - see RSTS Programming Manual, section 7.2.24. & 1740 ! PROJ.NUM% = 0% & !\ PROJ.NUM$ = SEG$ (WORK$, 22%, 22%) & !\ PROG.NUM% = 0% & !\ PROG.NUM$ = SEG$ (WORK$, 21%, 21%) & !\ M11.USER.ACCT$ = "[" + NUM1$(PROJ.NUM%) +"," +NUM1$(PROG.NUM%) +"]" & !\ IF PROJ.NUM% = 1% THEN M11.USER.PRIV% = TRUE% & ! ELSE M11.USER.PRIV% = FALSE% & ! Determine if this user is privileged. & & 1800 !-------------------------------------------------------------------- & ! & ! & ! Initialize & ! & ! & !-------------------------------------------------------------------- & & SCR.NUMBER%(I%) = I% * 3% + 1% FOR I% = 0% TO 50% & ! Set up relative screen numbers. & 2000 !-------------------------------------------------------------------- & ! & ! & ! Welcome Screen & ! & ! & !-------------------------------------------------------------------- & 2020 OPEN PRM.SCREEN.FILE$ FOR INPUT AS FILE #CH.SCR% & ,ORGANIZATION RELATIVE FIXED & ,RECORDSIZE 510% & ,ACCESS READ & ,ALLOW READ & 2050 CALL M11SCD (SCR.WELCOME%) & \ M11.MSG$ = "Version 1.1" & \ CALL M11SCW (M11.MSG$, 9%, 31%) & \ M11.MSG$ = "Copyright 1983" & ! CALL M11SCW (M11.MSG$, 10%, 29%) & \ M11.MSG$ = "by Digital Equipment Corporation" & ! CALL M11SCW (M11.MSG$, 11%, 21%) & ! Show the welcome sceen. & ! Put the copyright notice in the object code. & 2070 CALL M11SCR (ANS$, 17%, 65%, 1%, "N", "Y", F.END%) & \ IF F.END% THEN M11.FUNC$ = "E" & \ GO TO 9000 & ! Get the answer to the welcome screen. & ! END sends us out. & 2090 GO TO 4000 IF ANS$ = "N" & \ GO TO 2070 UNLESS ANS$ = "Y" OR ANS$ = "?" & ! Get user's reply. & ! It must be "Y", "N", or "?". & & 2100 !-------------------------------------------------------------------- & ! & ! & ! Show Help Screens & ! & ! & !-------------------------------------------------------------------- & & CALL M11SCD (SCR.HLP.0A%) & \ CALL M11SCR (ANS$, 24%, 72%, 4%, "", "A", F.END%) & \ GO TO 4000 UNLESS SEG$ (ANS$, 1%, 1%) = "M" & ! Show help screen #1. & ! Get user's answer. Go get mailing list name if 'END'. & ! Continue with help if 'MORE'. & 2180 CALL M11SCD (SCR.HLP.0B%) & \ CALL M11SCR (ANS$, 24%, 72%, 4%, "", "A", F.END%) & \ GO TO 4000 UNLESS SEG$ (ANS$, 1%, 1%) = "M" & ! Show help screen #2. & ! Again, get user's response. Get out of help if it's 'END'. & ! Continue if 'MORE'. & 2250 CALL M11SCD (SCR.HLP.0C%) & \ M11.MSG$ = "" & \ GO SUB 14900 & ! Show 3rd help screen. & ! Get response, 'END' exits help. Continue if "MORE". & & 4000 !-------------------------------------------------------------------- & ! & ! & ! Get Mailing List Name & ! & ! & !-------------------------------------------------------------------- & 4050 CALL M11SCD (SCR.ML.NAME%) & ! Put up the screen to enter the mailing list name. & 4080 HEADER.MISSING% = FALSE% & \ CALL M11SCR (M11.MAIL.FILE$,13%,43%,30%, PRM.DEFAULT.MLF$, "A", F.END%) & \ IF F.END% THEN & IF INT.CODE% = 1% & THEN M11.FUNC$ = "E" & \ GO TO 9000 & ELSE GO TO 5000 & ! Get the filename. If user says 'END', we exit Smart Mailer & ! if we just got in. If we got to this function from the & ! main menu, however, simply go back to the main menu. & 4100 IF SEG$ (M11.MAIL.FILE$, 1%, 1%) = "?" & OR M11.MAIL.FILE$ = "HELP" & OR M11.MAIL.FILE$ = "" THEN & CALL M11SCD (SCR.HLP.1%) & \ M11.MSG$ = "When through reading screen ..." & \ GO SUB 14900 & \ GO TO 4000 & ! Give help when requested, or if given a null name. & 4180 M11.MAIL.FILE$ = EDIT$ (M11.MAIL.FILE$, 32%) & \ M11.MAIL.FILE$ = TRM$ (M11.MAIL.FILE$) + ".MLF" & IF POS (M11.MAIL.FILE$, ".", 1%) = 0% & \ CALL M11SCW (M11.MAIL.FILE$, 13%,43%) & !*M11.MAIL.FILE$ = TRM$(PRM.DEFAULT.MLF.LOC$) + TRM$(M11.MAIL.FILE$) & !* IF POS (M11.MAIL.FILE$, ":", 1%) = 0% & \ GO SUB 10100 & \ CLOSE #CH.ADD% & ! Fabricate the file name. Close old address file. & ! Get the device and account of the Mail File. & 4182 M11.SUBLIST.CODE% = 0% & \ M11.LAST.LINE% = 0% & \ SEL.ALL$ = "" & ! Initialize common area to indicate no sublists defined yet. & 4185 WORK$ = FN.DROP.PRIV$ & \ OPEN M11.MAIL.FILE$ FOR INPUT AS FILE #CH.ADD% & ,ORGANIZATION INDEXED VARIABLE & ,ACCESS MODIFY & ,ALLOW MODIFY & ,BUCKETSIZE 2% & ,RECORDSIZE 350% & ,MAP MAPMLF & ,PRIMARY KEY MLF.KEY0$ NODUPLICATES & ,ALTERNATE KEY MLF.KEY1$ DUPLICATES CHANGES & & \ WORK$ = FN.REGAIN.PRIV$ & & ! Drop temporary privileges and attempt to open file. A protection & ! violation error traps to line 4195. If file does not exist, error & ! traps to 4300. If file exists, but the header record doesn't, & ! error traps to 4300 with HEADER.MISSING% set. & ! Any other file error traps to 4200 -- illegal file. & 4190 GET #CH.ADD%, KEY #0% EQ HDR.CHR$ + "000000000000001" & \ MOVE FROM #CH.ADD%, HDR.ALL$ = RECOUNT & \ UNLOCK #CH.ADD% & \ GO TO 5000 & ! Get the header record, load up the parameters, free the bucket & ! Go put up main menu. & 4195 WORK$ = FN.REGAIN.PRIV$ OPEN M11.MAIL.FILE$ FOR INPUT AS FILE #CH.ADD% & ,ORGANIZATION INDEXED VARIABLE & ,ACCESS MODIFY & ,ALLOW MODIFY & ,BUCKETSIZE 2% & ,RECORDSIZE 350% & ,MAP MAPMLF & ,PRIMARY KEY MLF.KEY0$ NODUPLICATES & ,ALTERNATE KEY MLF.KEY1$ DUPLICATES CHANGES ! The file could not be opened without temporary privilege. Regain ! temporary privileges and open file so program can get the header ! record. 4196 GET #CH.ADD%, KEY #0% EQ HDR.CHR$ + "000000000000001" & \ MOVE FROM #CH.ADD%, HDR.ALL$ = RECOUNT & \ UNLOCK #CH.ADD% & \ GO TO 4220 IF HDR.PUBLIC.MAIL.LIST$ <> "Y" & AND ( MAIL.FILE.ACCT$ <> M11.USER.ACCT$ AND & MAIL.FILE.ACCT$ <> DEF.ACCT$ ) & \ GO TO 5000 & ! Get the header record, load up the parameters, free the bucket & ! The user is non-privileged, so deny access unless the mailing & ! list is public, or is located in the default account. 4200 M11.MSG$ = "Problem opening that file (bad filespec?) try again" & \ CALL M11SCW (M11.MSG$ + BEL, 24%, 1%) & \ GO TO 4080 & ! Tell about bad filespec, give user another chance. & 4220 M11.MSG$ = "You may not use a restricted file in another account." & \ CALL M11SCW (M11.MSG$ + BEL, 24%, 1%) & \ CLOSE #CH.ADD% & \ HDR.ALL$ = "" & \ GO TO 4080 & ! The user did not have access to this file. Go back for another & ! filespec. & 4300 !-------------------------------------------------------------------- & ! & ! Create new Mailing List File & ! & !-------------------------------------------------------------------- & & GO TO 4320 IF HEADER.MISSING% & \ CALL M11SCD (SCR.NEW.ML%) & ! Put up screen asking if user REALLY wants to create a new file. & 4311 CALL M11SCR (ANS$, 14%, 60%, 3%, "", "A", F.END%) & \ GO TO 4000 IF F.END% & \ GO TO 4320 UNLESS SEG$ (ANS$, 1%, 1%) = "?" & \ M11.MSG$ = "Type END to go back; press RETURN to create a new file." & \ CALL M11SCW (M11.MSG$, 24%, 1%) & \ GO TO 4311 & ! Allow user to abort creation of the new file. & 4320 HDR.SYS.DEF.PRIME.ID$ = "1" ! Flag set if system is to & ! supply a primary ID. & \ HDR.SYS.DEF.ALT.ID$ = "Y" ! Flag set if system is to & ! generate an alternate ID. & \ HDR.LAST.ADDR.DEF$ = "Y" ! Flag set if system is to & ! default address to last one & ! entered. & \ HDR.LAST.NAME.MIX$ = "6" ! Define alternate ID mix & \ HDR.FIRST.NAME.MIX$ = "4" & \ HDR.LAST.NAME.MIX% = 6% & \ HDR.FIRST.NAME.MIX% = 4% & \ HDR.COUNTRY$ = "A" ! Default country is US. & \ CHECK$ = "Y" ! therefore, check codes & ! Initialize Mailing List parameters. & ! Null out alternate ID. & 4350 CALL M11SCD (SCR.MLPARMS%) & \ CALL M11SCW ("(The file header is missing)", 24%, 1%) & IF HEADER.MISSING% & \ CALL M11SCW (HDR.SYS.DEF.PRIME.ID$, 3%, 60%) & \ CALL M11SCW (HDR.SYS.DEF.ALT.ID$, 8%, 60%) & \ CALL M11SCW (HDR.LAST.NAME.MIX$, 10%, 60%) & \ CALL M11SCW (HDR.FIRST.NAME.MIX$, 10%, 65%) & \ CALL M11SCW (HDR.LAST.ADDR.DEF$, 12%, 60%) & \ CALL M11SCW (CHECK$, 14%, 60%) & ! Show initial values of these parameters. & 4400 CALL M11SCR (ANS$, 22%, 41%, 1%, "", "N", F.END%) & \ GO TO 4000 IF F.END% & \ GO TO 4500 IF ANS$ = "" & \ GO TO 4405 UNLESS ANS$ = "?" & ! Get the user's selection. Move back if it's 'END'. & 4402 CALL M11SCD (SCR.HLP.3%) & \ M11.MSG$ = "" & \ GO SUB 14900 & \ GO TO 4350 & ! Supply help if necessary. & 4405 ANS% = VAL (ANS$) & \ GO TO 4400 IF ANS% < 1% OR ANS% > 5% & \ ON ANS% GO TO 4410, 4420, 4430, 4440, 4450 & ! Go change the one selected. & 4410 CALL M11SCR (ANS$, 3%, 60%, 1%, HDR.SYS.DEF.PRIME.ID$,"A", F.END%) GO TO 4400 IF F.END% GO TO 4402 IF ANS$ = "?" IF POS ( "123", ANS$, 1% ) = 0% THEN M11.MSG$ = "Primary ID Type must be 1, 2, or 3." CALL M11SCW (M11.MSG$, 24%, 1% ) GOTO 4410 END IF HDR.SYS.DEF.PRIME.ID$ = ANS$ GO TO 4400 ! Get system defined Primary ID flag. (1 = system defined consecutive ! numbers, 2 = system defined address hash, 3 = user defined. ) 4420 CALL M11SCR (ANS$, 8%, 60%, 1%, HDR.SYS.DEF.ALT.ID$, "Y", F.END%) & \ GO TO 4400 IF F.END% & \ GO TO 4402 IF ANS$ = "?" & \ HDR.SYS.DEF.ALT.ID$ = ANS$ & \ CALL M11SCW (ERASE.EOL$, 10%, 60%) IF ANS$ = "N" & \ GO TO 4400 & ! Get Y/N system defined Alternate ID flag. & 4430 CALL M11SCR (ANS$, 10%, 60%, 2%, HDR.LAST.NAME.MIX$, "I", F.END%) & \ GO TO 4400 IF F.END% & \ GO TO 4439 IF ANS$ = "?" & \ HDR.LAST.NAME.MIX% = VAL (ANS$) & & \ CALL M11SCR (ANS$, 10%, 65%, 2%, HDR.FIRST.NAME.MIX$,"I", F.END%) & \ GO TO 4400 IF F.END% & \ GO TO 4439 IF ANS$ = "?" & \ HDR.FIRST.NAME.MIX% = VAL (ANS$) & & \ GO TO 4400 & UNLESS HDR.LAST.NAME.MIX% > 10% & OR HDR.FIRST.NAME.MIX% > 10% & OR HDR.LAST.NAME.MIX% + HDR.FIRST.NAME.MIX% <> 10% & ! Get mix of name characters for alternate ID. & ! Continue if the numbers are ok. & 4439 M11.MSG$ = "Both numbers must be between 0 and 10, and add to 10." & \ CALL M11SCW (M11.MSG$, 24%, 1%) & \ GO TO 4430 & ! Provide help if requested, or if wrong answer(s) given. & 4440 CALL M11SCR (ANS$, 12%, 60%, 1%, HDR.LAST.ADDR.DEF$, "Y", F.END%) & \ GO TO 4400 IF F.END% & \ GO TO 4402 IF ANS$ = "?" & \ HDR.LAST.ADDR.DEF$ = ANS$ & \ GO TO 4400 & ! Get Y/N 'default to last address' flag. & 4450 CALL M11SCR (ANS$, 14%, 60%, 1%, CHECK$, "Y", F.END%) & \ GO TO 4400 IF F.END% & \ GO TO 4402 IF ANS$ = "?" & \ CHECK$ = ANS$ & \ HDR.COUNTRY$ = " " IF CHECK$ = "N" & \ HDR.COUNTRY$ = "A" IF CHECK$ = "Y" & \ GO TO 4400 & ! Get Y/N to check the state and zip codes. & ! If answer is Yes, then call country US ('A'), & ! otherwise, leave country blank (and don't check the codes.) & 4500 !-------------------------------------------------------------------- & ! & ! & ! Open New Mailing List File & ! & ! & !-------------------------------------------------------------------- & 4520 GO TO 4600 IF HEADER.MISSING% & ! Bypass creating the file, if it is already there. & 4580 WORK$ = FN.DROP.PRIV$ & \ OPEN M11.MAIL.FILE$ FOR OUTPUT AS FILE #CH.ADD% & ,ORGANIZATION INDEXED VARIABLE & ,ACCESS MODIFY & ,ALLOW MODIFY & ,FILESIZE PRM.NEW.MLF.SIZE% & ,BUCKETSIZE 2% & ,RECORDSIZE 350% & ,MAP MAPMLF & ,PRIMARY KEY MLF.KEY0$ NODUPLICATES & ,ALTERNATE KEY MLF.KEY1$ DUPLICATES CHANGES & \ WORK$ = FN.REGAIN.PRIV$ & \ GO TO 4600 & ! Temporarily drop privilege to deny access of files to non- & ! privileged users. Open the new file. & ! Regain privilege. & ! A filesize of 1200 blocks is designed to hold about 2000 addresses. & 4590 M11.MSG$ = "You may not create a file in another account." & \ GO SUB 14900 \ WORK$ = FN.REGAIN.PRIV$ & \ GO TO 4050 & ! The user did not have access to this file. Go back for another & ! filespec. & 4595 M11.MSG$ = "Pack on specified device is private." & \ CALL M11SCW (M11.MSG$ + BEL, 24%, 1%) & \ SLEEP 3% & \ WORK$ = FN.REGAIN.PRIV$ & \ GO TO 4050 & ! The account specified did not exist on the private pack. & ! Go back for another filespec. & & 4600 !-------------------------------------------------------------------- & ! & ! & ! Category Initialization Screen & ! & ! & !-------------------------------------------------------------------- & & 4602 FOR I% = 0% TO 10% & \ HDR.CAT.PROMPT$(I%) = "undefined" & \ HDR.CAT.TYPE$(I%) = "A" & \ NEXT I% & ! Initialize the category labels and types. & 4610 CALL M11SCD (SCR.CAT.INIT%) & \ BASE% = 7% & \ FOR I% = 1% TO 6% & \ CALL M11SCW (HDR.CAT.PROMPT$(I%), BASE%+I%, 25%) & \ CALL M11SCW (HDR.CAT.TYPE$(I%), BASE%+I%, 41%) & \ NEXT I% & ! Put up the category definition screen. & 4615 FOR I% = 1% TO 6% & \ DF$ = HDR.CAT.PROMPT$(I%) & ! For each category ..... & 4620 CALL M11SCR (ANS$, BASE%+I%, 25%, 10%, DF$, "a", F.END%) & \ GO TO 4615 IF F.END% & \ GO TO 4690 IF ANS$ = "?" & \ IF ANS$ = "" THEN & M11.MSG$ = "You must give this category a name." & \ CALL M11SCW (M11.MSG$, 24%, 1%) & \ GO TO 4620 & ! Get the user's category name. & ! Don't allow blank names. & 4640 HDR.CAT.PROMPT$(I%) = ANS$ & \ DF$ = HDR.CAT.TYPE$(I%) & ! Assign the name to this category. & 4680 CALL M11SCR (ANS$, BASE% + I%, 41%, 1%, DF$, "A", F.END%) & \ GO TO 4610 IF F.END% & \ IF POS ("ADNYC", ANS$, 1%) = 0% OR ANS$ = "" THEN & M11.MSG$ = "The type must be either 'A', 'D', 'N', 'Y' or 'C'." & \ CALL M11SCW (M11.MSG$, 24%, 1%) & \ GO TO 4680 & ! Get the type. It must be valid. If 'END', go abort this & ! mailing list. & 4685 HDR.CAT.TYPE$(I%) = ANS$ & \ GO TO 4700 & ! Set the category type. & 4690 CALL M11SCD (SCR.HLP.4%) & \ M11.MSG$ = "When through reading screen ..." & \ GO SUB 14900 & \ GO TO 4610 & ! Show help screen. & 4700 NEXT I% & ! Loop through each category. & 4800 HDR.KEY0$ = HDR.CHR$ + "000000000000001" & \ HDR.KEY1$ = STRING$(10%,0%) & !-HDR.SYS.DEF.PRIME.ID$ = user defined & !-HDR.SYS.DEF.ALT.ID$ = user defined & !-HDR.LAST.ADDR.DEF$ = user defined & \ HDR.DATE.FORMAT$ = "1" & \ HDR.NEXT.PRIME.ID$ = " 1" & !-HDR.LAST.NAME.MIX% = user defined & !-HDR.FIRST.NAME.MIX% = user defined & \ HDR.PACK.ADDRS$ = "Y" & !-HDR.COUNTRY$ = user defined & \ HDR.FUTURE$ = " " ! set future parameters blank & \ HDR.PUBLIC.MAIL.LIST$ = "N" ! defaults to private file & \ HDR.FIELD.LEN%(0%) = 0% & \ HDR.FIELD.LEN%(1%) = 16% ! primary ID & \ HDR.FIELD.LEN%(2%) = 10% ! alternate ID & \ HDR.FIELD.LEN%(3%) = 4% ! counter string length & \ HDR.FIELD.LEN%(4%) = 30% ! name & \ HDR.FIELD.LEN%(5%) = 30% ! address line 1 & \ HDR.FIELD.LEN%(6%) = 30% ! address line 2 & \ HDR.FIELD.LEN%(7%) = 30% ! address line 3 & \ HDR.FIELD.LEN%(8%) = 30% ! city/town & \ HDR.FIELD.LEN%(9%) = 12% ! state/country & \ HDR.FIELD.LEN%(10%) = 10% ! zip code & \ HDR.FIELD.LEN%(11%) = 10% ! categories & \ HDR.FIELD.LEN%(12%) = 10% & \ HDR.FIELD.LEN%(13%) = 10% & \ HDR.FIELD.LEN%(14%) = 10% & \ HDR.FIELD.LEN%(15%) = 10% & \ HDR.FIELD.LEN%(16%) = 10% & \ HDR.FIELD.LEN%(17%) = 10% ! future & \ HDR.FIELD.LEN%(18%) = 65% ! comment & \ HDR.FIELD.LEN%(19%) = 0% & \ HDR.FIELD.LEN%(20%) = 0% & ! Fill in header field length (in bytes). & 4900 MOVE TO #CH.ADD%, HDR.ALL$ & \ SLEN% = LEN (HDR.ALL$) & \ PUT #CH.ADD%, COUNT SLEN% & ! Write out the parameter record. & 4920 M11.MSG$ = "Finished creating Mailing List File called " + M11.MAIL.FILE$ & \ GO SUB 14800 & \ SLEEP 2% & ! Inform the user that file is created. & & & 5000 !-------------------------------------------------------------------- & ! & ! & ! Main Menu & ! & ! & !-------------------------------------------------------------------- & 5050 CLOSE #CH.KB% & ! The channel may have been closed to allow immediate ^C. & 5060 OPEN "KB:" AS FILE #CH.KB%, MODE 8% & ! WORK$ = SYS (CHR$(11%) + CHR$(CH.KB%)) & ! But, it may also be open. SO, close it, flush buffer, and reopen. & 5100 CALL M11SCD (SCR.MAIN.MENU%) & ! Display Main Menu. & 5120 CALL M11SCR (ANS$, 22%, 40%, 1%, "U", "A", F.END%) & \ IF F.END% & OR SEG$ (ANS$, 1%, 2%) = "EX" THEN & M11.FUNC$ = "E" & \ GO TO 9000 & ! Get user's Main Menu choice. & ! If "END", exit with return flag set. & 5150 GO TO 5120 IF ANS$ = "" & \ GO TO 6000 IF ANS$ = "?" & \ GO TO 5120 IF POS ("UPDCSTWR", ANS$, 1%) = 0% & \ M11.FUNC$ = ANS$ & \ GO TO 4000 IF M11.FUNC$ = "T" & \ GO TO 9000 & ! Go offer help if it was requested. Reject invalid commands. & ! If user typed "T", we handle within this module, otherwise, & ! return to caller with user's menu response in M11.FUNC$. & & 6000 !-------------------------------------------------------------------- & ! & ! & ! Help Messages & ! & ! & !-------------------------------------------------------------------- & 6100 CALL M11SCD (SCR.HLP.5%) & ! Show help screen for main menu. & 6300 M11.MSG$ = "" & \ GO SUB 14900 & \ GO TO 5000 & ! Wait for user to finish reading help information. & ! Then go back to Main Menu (regardless of response). & 8000 !-------------------------------------------------------------------- & ! & ! & ! Anticipated Error Handling & ! & ! & !-------------------------------------------------------------------- & & 8010 PRINT #CH.KB% & \ PRINT #CH.KB%, "Smart Mailer will only run on a video terminal." & \ PRINT #CH.KB% & \ WORK$ = SYS (CHR$(9%)) & ! Tell user to find a VT52. & & 9000 !******************************************************************** & ! & ! & ! E N D O F P R O C E S S I N G & ! & ! & !******************************************************************** & 9100 ERR.PROGNAM$ = ERR.CALLNAM$ & \ ERR.SUBNAM$ = "" & ! Restore the caller's name as the current program. & 9900 GOTO 32767 & ! Go to the end of the subprogram. & 10000 !******************************************************************** & ! & ! & ! S U B R O U T I N E S L O C A L T O & ! & ! T H I S S U B P R O G R A M & ! & ! & !******************************************************************** 10100 !******************************************************************** & ! & ! & ! & ! Determine Device and Account for Mail File & ! & ! & ! & !******************************************************************** & & P1% = POS(PRM.DEFAULT.MLF.LOC$,":",1%) P2% = POS(PRM.DEFAULT.MLF.LOC$,"]",1%) IF P2% <> 0% THEN DEF.ACCT$ = SEG$(PRM.DEFAULT.MLF.LOC$, P1%+1%, P2%) ELSE DEF.ACCT$ = M11.USER.ACCT$ END IF ! ! Determine the default account for mailing list files. ! P1% = POS(M11.MAIL.FILE$,":",1%) P2% = POS(M11.MAIL.FILE$,"]",1%) IF P1% = 0% AND P2% = 0% THEN M11.MAIL.FILE$ = TRM$(PRM.DEFAULT.MLF.LOC$) + M11.MAIL.FILE$ MAIL.FILE.ACCT$ = DEF.ACCT$ END IF ! ! If no device and no account were specified add the ! default location to the file spec. ! The mailing list account is the default account ! MAIL.FILE.ACCT$ = SEG$(M11.MAIL.FILE$, P1%+1%, P2%) IF P2% <> 0% ! ! The mailing list account was specified ! IF P1% <> 0% AND P2% = 0% THEN LENGTH% = LEN(M11.MAIL.FILE$) M11.MAIL.FILE$ = SEG$(M11.MAIL.FILE$,1%,P1%) & + M11.USER.ACCT$ & + SEG$(M11.MAIL.FILE$, P1%+1%, LENGTH%) MAIL.FILE.ACCT$ = M11.USER.ACCT$ END IF ! If a device was specified but not the account number, make the user's ! account part of the file spec. This overrides any account number ! associated with a logical device name. This is a security measure to ! prevent unauthorized access through use of a logical that includes ! an account number. Logical device names are o.k. ! RETURN 11000 !******************************************************************** & ! & ! Load the printer parameter arrays & ! & ! input: (from M11PAR.DAT) & ! & ! output: PRM.PRT.- & ! & ! local: COLON% position of the colon in the printer string & ! COMMA position of a comma in the printer string & ! J% loop index & ! J$ string representation of loop index & ! K% loop index & ! NAME$ printer name & ! PRINTER$ printer parameter string from parameter file & ! START% position variable & !-------------------------------------------------------------------- & & 11100 FOR J% = 0% TO 4% ! For each possible printer & & \ J$ = STR$ (J%+1%) & \ PRINTER$ = FN.GET.DATA$ & ! Get printer parameter line from Parameter File. & & 11400 ERR.MSG$ = "First printer must be an actual device." & \ IF SEG$ (PRINTER$, 1%, 2%) = "NL" & OR SEG$ (PRINTER$, 1%, 2%) = "nl" & THEN PRM.PRT.DEV$(J%) = "NL:" & \ IF J% = 0% THEN GO TO 11900 & ELSE GO TO 11700 & ! Pass any null devices, unless it is the first one. & ! In that case, it is an error. & 11420 ERR.MSG$ = "Too few printer parameters on line" & \ START% = 1% & \ FOR K% = 1% TO 4% & \ COMMA% = POS (PRINTER$, ",", START%) & \ GO TO 11900 IF COMMA% = 0% & \ START% = COMMA% + 1% & \ NEXT K% & ! Check for 4 commas (i.e., all 5 parameters) & 11440 NAME$ = SEG$ (PRINTER$, START%, LEN (PRINTER$)) & \ NAME$ = EDIT$ (NAME$, 12%) & \ NAME$ = "Printing device " + J$ IF LEN (NAME$) = 0% & \ PRM.PRT.NAM$(J%) = NAME$ & ! Extract the name of the printer from the end of the line. & ! Give it a default name if the name is null. & 11500 PRINTER$ = EDIT$ (PRINTER$, 38%) & ! Compress the rest of the line, and change to upper case. & 11520 ERR.MSG$ = "Invalid device for printer " + J$ & \ COMMA% = POS (PRINTER$, ",", 1%) & \ COLON% = COMMA% - 1% & \ GO TO 11900 IF COMMA% < 4% & \ GO TO 11900 IF SEG$ (PRINTER$, COLON%, COLON%) <> ":" & \ PRM.PRT.DEV$(J%) = SEG$ (PRINTER$, 1%, COLON%) & ! Check and then extract the printer device name. & 11540 ERR.MSG$ = "Invalid printer queable code, must be Q or N" & \ START% = COMMA% + 1% & \ COMMA% = POS (PRINTER$, ",", START%) & \ GO TO 11900 IF COMMA% = START% & \ PRM.PRT.COD$(J%) = SEG$ (PRINTER$, START%, COMMA%-1%) & \ GO TO 11900 IF PRM.PRT.COD$(J%) <> "Q" & AND PRM.PRT.COD$(J%) <> "N" & ! Extract and check the printer queable code. & 11560 ERR.MSG$ = "Invalid printer line length" & \ START% = COMMA% + 1% & \ COMMA% = POS (PRINTER$, ",", START%) & \ GO TO 11900 IF COMMA% = START% & \ PRM.PRT.LEN%(J%) = VAL (SEG$ (PRINTER$, START%, COMMA%-1%)) & \ GO TO 11900 IF PRM.PRT.LEN%(J%) <= 0% & ! Extract and check the printer line length. & 11580 ERR.MSG$ = "Invalid printer type, must be F or V" & \ START% = COMMA% + 1% & \ COMMA% = POS (PRINTER$, ",", START%) & \ GO TO 11900 IF COMMA% = START% & \ PRM.PRT.TYP$(J%) = SEG$ (PRINTER$, START%, COMMA%-1%) & \ GO TO 11900 IF PRM.PRT.TYP$(J%) <> "F" & AND PRM.PRT.TYP$(J%) <> "V" & ! Extract and check the printer type. & 11700 NEXT J% & ! Do next printer. & 11800 ERR.MSG$ = "" & \ RETURN & & 11900 ERR.CODE% = FATAL.ERROR% & \ RETURN & ! Something is wrong with the printer parameters, tell user and stop. & & 15000 !******************************************************************** & ! & ! & ! F U N C T I O N S L O C A L T O & ! & ! T H I S S U B P R O G R A M & ! & ! & !******************************************************************** & & 15100 !******************************************************************** & ! & ! & ! FN.GET.DATA% & ! & ! Gets numeric data item from next line of input & ! parameter file. & ! & ! & !******************************************************************** & 15110 DEF FN.GET.DATA% & 15115 INPUT LINE #CH.PARM%, WORK$ & \ COMMENT% = POS (WORK$, "!", 1%) & \ IF COMMENT% > 0% THEN WORK$ = SEG$ (WORK$, 1%, COMMENT%-1%) & ! Strip away the comment, if any. & 15120 WORK$ = EDIT$ (WORK$, 2% + 4% + 32% ) & ! Remove extraneous characters. & 15130 FN.GET.DATA% = VAL (WORK$) & \ FNEND & ! Set the numeric value of our function, return. & & 15200 !******************************************************************** & ! & ! & ! FN.GET.DATA$ & ! & ! Gets data string from next line of input file & ! & ! & !******************************************************************** & 15210 DEF FN.GET.DATA$ & 15215 INPUT LINE #CH.PARM%, WORK$ & \ COMMENT% = POS (WORK$, "!", 1%) & \ IF COMMENT% > 0% THEN WORK$ = SEG$ (WORK$, 1%, COMMENT% -1%) & ! Strip away the comment, if any. & 15220 WORK$ = EDIT$ (WORK$, 140%) & ! Remove leading and trailing space/tabs, remove extraneous char.s & 15230 FN.GET.DATA$ = WORK$ & \ FNEND & ! Set the string value of our function, return. & & 19000 !******************************************************************** & ! & ! & ! S T A N D A R D E R R O R H A N D L I N G & ! & ! & !******************************************************************** & 19010 GO TO 19990 IF ERN$ <> SEG$ (ERR.PROGNAM$, 1%, 6%) & ! Only tracing back an error from another subprogram & 19020 RESUME 4190 IF ERL = 4190 AND ERR = 154 & \ RESUME 4196 IF ERL = 4196 AND ERR = 154 & \ RESUME 1510 IF ERL = 1510 AND ERR = 138 & \ RESUME 5060 IF ERL = 5050 AND ERR = 9 & ! If bucket locked, then try again. & ! If file is locked, then try again. 19040 RESUME 1690 IF ERL = 1680 AND ERR = 11% ! Must trap for end of file since V1.1 has more parameters than V1.0 ! and the user may have an old parameter file. 19050 IF ERL = 4185 OR ERL = 4190 THEN & HEADER.MISSING% = TRUE% IF ERR = 155 & \ RESUME 4300 IF ERR = 155 OR ERR = 5 & \ RESUME 4195 IF ERR = 10 & \ RESUME 4200 & ! Line 4185 tried to open file after dropping privilege. & ! If we have trouble opening the file or getting the header & ! record, set HEADER.MISSING% if it's the latter. In either & ! case, resume at the trouble spot. If it's a protection & ! violatation (non-privileged user), resume at 4220. Any & ! other problem will abort. & 19055 IF ERL = 4195 OR ERL = 4196 THEN & HEADER.MISSING% = TRUE% IF ERR = 155 & \ RESUME 4300 IF ERR = 155 OR ERR = 5 & \ RESUME 4200 & ! If we have trouble opening the file or getting the header & ! record, set HEADER.MISSING% if it's the latter. In either & ! case, resume at the trouble spot. Any other problem will abort. & 19060 IF ERL = 4580 & THEN RESUME 4590 IF ERR = 10 & \ RESUME 4595 IF ERR = 24 & ! If a non-privileged user tried to open a file in another account, & ! or the pack for the specified device is private, then go back & ! and complain. & 19100 RESUME 11900 IF ERL = 11560 & ! Handle anticipated errors. & 19800 ERR.MSG$ = "Unexpected fatal error" & \ ERR.MSG$ = "Problem accessing the Parameter File (not there?)" & IF ERL = 1510 & \ ERR.MSG$ = "Problem accessing the Screen File (not there?)" & IF ERL = 2020 & \ ERR.MSG$ = "Problem reading Parameter File (wrong order?)" & IF ERL = 15130 & \ ERR.MSG$ = "System files have the wrong protection code." & IF ERR = 10 & ! Define error messages for known (but unexpected) errors. & & 19850 ERR.ERL% = ERL & \ ERR.ERR% = ERR & \ ERR.CODE% = FATAL.ERROR% & ! On a fatal error, call the standard error handler. & 19990 ON ERROR GO BACK & ! Return to calling program for fatal error processing. & 32767 SUBEND