Trailing-Edge
-
PDP-10 Archives
-
cuspmar86binsrc_1of2_bb-x128b-sb
-
10,7/acct/newact.mac
There are 2 other files named newact.mac in the archive. Click here to see a list.
TITLE NEWACT--CONVERT A VERSION 4 ACCT.SYS TO A VERSION 6 ACTDAE.SYS
SUBTTL Tarl/TARL/LWS/TL/RCB 3-Dec-85
SALL ;CLEAN LISTINGS
.DIRECT FLBLST ;EVEN CLEANER
SEARCH ACTPRM
MODULE (NEWACT)
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1985,1986. ALL RIGHTS RESERVED.
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE INCLUSION
;OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER COPIES THEREOF
;MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON. NO
;TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY TRANSFERRED.
;
;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
;AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.
;
;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1986.
ALL RIGHTS RESERVED.
\;END COPYRIGHT MACRO
NEAVER==1 ;VERSION NUMBER
NEAEDT==7 ;EDIT NUMBER
NEAWHO==0 ;WHO EDITED LAST
NEAMIN==0 ;MINOR VERSION NUMBER
NEAACV==<VRSN. (NEA)>
.ORG 137
EXP NEAACV ;VERSION
.ORG
SUBTTL Table of contents
; TABLE OF CONTENTS FOR NEWACT
;
;
; SECTION PAGE
; 1. Table of contents......................................... 2
; 2. Revision History.......................................... 3
; 3. General information....................................... 4
; 4. Assembly parameters....................................... 5
; 5. Definitions............................................... 6
; 6. Basic conversion table.................................... 7
; 7. Main program.............................................. 8
; 8. Initialization............................................ 9
; 9. Lookup the input files.................................... 10
; 10. Initialize the USERS.TXT index............................ 11
; 11. Insert USERS.TXT index entries............................ 12
; 12. Main conversion loop...................................... 13
; 13. Final cleanup............................................. 14
; 14. Read an entry from ACCT.SYS............................... 15
; 15. Read an entry from AUXACC.SYS............................. 16
; 16. Convert an entry.......................................... 17
; 17. Convert a username........................................ 18
; 18. Convert a password........................................ 19
; 19. Convert core limits....................................... 20
; 20. Convert program-to-run.................................... 21
; 21. Convert expiration date................................... 22
; 22. Convert AUXACC data....................................... 23
; 23. Format a PPN for display.................................. 24
; 24. Find the length of a SIXBIT string........................ 25
; 25. Random hiseg data......................................... 26
; 26. Impure (lowseg) data...................................... 27
SUBTTL Revision History
; 1) Create NEWACT. /TARL
;
; 2) Add defaults when converting "program-to-run" so they'll
; be displayed the same as when created by new REACT.
; QAR #868019 5-Apr-85 /LWS
;
; 3) Converts ACCT.SYS and AUXACC.SYS to RMS ACCT.ACT /TL
;
; 4) New accounting file name is now SYS:ACTDAE.SYS, managed
; by RMS. /LWS
;
; 5) Get rid of VERSET. ACTRMS must be loaded first. /LWS
;
; 6) DO COPYRIGHTS. 15-AUG-85 /LEO
;
; 7) Upgrade from version 5 (already obsolete) to version 6. /RCB
;
;
;End of revision history
SUBTTL General information
COMMENT `
The following information describes how to customize NEWACT for any possible
changes to the formats of ACCT.SYS and AUXACC.SYS for your site, or for use
of .ACCUS or the old 'charge number'.
First, make sure that ACTSYM is up-to-date with respect to your changes. In
particular, be sure that .ACLEN accurately reflects the length of a profile
entry. Then, be sure that you update the AEPROF macro in ACTSYM to define
words for your entries in the new profile format.
If you have used some form of password encryption in the past, you will want to
set NCRYPT accordingly. You may also need to modify ACTCUS to include your
encryption algorithm, if you wrote your own.
Next, add your profile entries to CNDTAB, so that the fields from ACCT.SYS will
be preserved in ACTDAE.SYS. Then, for any of your entries which require no
translation, add them to the table of fixed byte pointers (XFRBPT). For any
entries which do require translation, add calls your conversion routines to
CNVSPC.
Also, if you want the users' names to be something a bit more readable than
the old 12-character restriction, you can define a USERS.TXT file. This is
entirely optional, and NEWACT will be quite happy if no USERS.TXT exists.
If you should desire this, the official format of USERS.TXT is as follows:
<structure>:[ppn],<user-name>
on each line. In fact, NEWACT considers the structure name to be optional,
and will allow comments and blank lines in the file. The user-name can
be any ASCII text without control-characters, up to 39 characters in length.
No spaces are allowed between the ppn and the comma separating it from the
username. Any spaces after that comma are considered part of the username.
It is not necessary that every PPN in ACCT.SYS have an entry in USERS.TXT.
(As a historical footnote, the reason that USERS.TXT has a structure in it
is due to a mail system which was used in-house at DEC, but which was never
made suitable for general distribution. This structure was where the user's
mail file resided.)
Even if you use no site-specific fields in ACCT.SYS, you may want to examine
the available assembly parameters. The security features made availble with
this release of the accounting system are a considerable improvement over what
has been previously available.
Finally, note that NEWACT looks for all files on DSK:. If your PPN has read
privileges to the system files, a simple manipulation of your search list with
SETSRC or PATH will suffice to include the system area in your DSK: definition,
should that be desired.
`
SUBTTL Assembly parameters
ND FTISWS,0
IFN FTISWS,<
.ACLEN==20 ;JUNKY OLD WORDS (OBSOLETE)
ND NCRYPT,2
>
ND NCRYPT,0 ;0 - OLD ACCT.SYS IS NOT ENCRYPTED
;1 - OLD ACCT.SYS IS ENCRYPTED BY CUSTOMER ALG 1 (#5)
;2 - OLD ACCT.SYS IS ENCRYPTED BY CUSTOMER ALG 2 (#6)
;DEFINITIONS FOR NEW VALUES IN PROFILE
ND CTXMXC,4 ;MAXIMUM NUMBER OF CONTEXTS
ND CTXMXP,^D1000 ;MAXIMUM NUMBER OF IDLE CONTEXT PAGES
ND PIDMAX,2 ;MAXIMUM NUMBER OF PIDS
ND PSWLEN,0 ;MINIMUM ALLOWABLE PASSWORD LENGTH
ND PSWCHG,0 ;DEMAND PASSWORD CHANGE ON NEXT LOGIN IF NON-ZERO
ND PSWINT,0 ;NON-ZERO IS MAXIMUM NUMBER OF DAYS BETWEEN PSW CHANGES
ND SETPCP,0 ;DISALLOW USER-ORIGINATED PASSWORD CHANGES IF NON-ZERO
SUBTTL Definitions
;PDL length
PDLLEN==200 ;MIGHT BE LONG ENOUGH
;Dummy for ACTRMS
UGAUX%==:.RETF ;SATISFY GLOBAL REQUIREMENTS
;Macro to define byte pointer pairs: old location:new location
DEFINE FROMTO(F.OFF,F.MASK,T.OFF,T.MASK),<
IFN F.MASK,<POINTR(ACCT+F.OFF,F.MASK)>
IFE F.MASK,<POINT 36,ACCT+F.OFF,35>
XLIST
IFN T.MASK,<POINTR(PROFIL+T.OFF,T.MASK)>
IFE T.MASK,<POINT 36,PROFIL+T.OFF,35>
LIST
>;END DEFINE FROMTO
DEFINE NEWDEF(F.DEF,T.OFF,T.MASK),<
IFN F.DEF,<
POINT 36,[F.DEF],35
XLIST
IFN T.MASK,<POINTR(PROFIL+T.OFF,T.MASK)>
IFE T.MASK,<POINT 36,PROFIL+T.OFF,35>
LIST
>>;END DEFINE NEWDEF
SUBTTL Basic conversion table
;Byte pointers for quantities which can be simply transferred.
XFRBPT:
FROMTO( .ACPPN, , .AEPPN, ,) ;PPN
FROMTO( .ACPRV, , .AEPRV, ,) ;PRIMARY PRIV WORD
FROMTO( .ACLIT, , .AELGT, ,) ;LOGIN TIMES
FROMTO( .ACCIP, AC.SND, .AEIPC, AE.SND) ;IPCF SEND QUOTA
FROMTO( .ACCIP, AC.RCV, .AEIPC, AE.RCV) ;IPCF RECEIVE QUOTA
NEWDEF( PIDMAX, .AEIPC, AE.PID) ;IPCF MAX NUMBER OF PIDS
FROMTO( .ACPRO, AC.WDT, .AEWCH, JW.WDY) ;WATCH DAYTIME
FROMTO( .ACPRO, AC.WRT, .AEWCH, JW.WRN) ; RUNTIME
FROMTO( .ACPRO, AC.WWA, .AEWCH, JW.WWT) ; WAIT
FROMTO( .ACPRO, AC.RED, .AEWCH, JW.WDR) ; READ
FROMTO( .ACPRO, AC.WRI, .AEWCH, JW.WDW) ; WRITES
FROMTO( .ACPRO, AC.WVR, .AEWCH, JW.WVR) ; VERSION
FROMTO( .ACPRO, AC.WMT, .AEWCH, JW.WMT) ; MAGTAPE
FROMTO( .ACPRO, AC.WFL, .AEWCH, JW.WFI) ; FILE
FROMTO( .ACPRO, AC.CDR, .AESPL, JS.PCR) ;SPOOL CDR
FROMTO( .ACPRO, AC.CDP, .AESPL, JS.PCP) ; CDP
FROMTO( .ACPRO, AC.PTP, .AESPL, JS.PPT) ; PTP
FROMTO( .ACPRO, AC.PLT, .AESPL, JS.PPL) ; PLOT
FROMTO( .ACPRO, AC.LPT, .AESPL, JS.PLP) ; LPT
FROMTO( .ACPRO, AC.OPR, .AEPRX, JP.OPR) ;OPR PRIVS
FROMTO( .ACPRO, AC.RMK, .AEREQ, AE.RMK) ;REQUIRE REMARK
FROMTO( .ACPRO, AC.ACT, .AEREQ, AE.ACT) ; ACCOUNT
FROMTO( .ACPRO, AC.NRT, .AEREQ, AE.NRT) ; NAME UNDER TIMESHARING
FROMTO( .ACPRO, AC.NRB, .AEREQ, AE.NRB) ; NAME UNDER BATCH
FROMTO( .ACPRO, AC.PRT, .AEREQ, AE.PRT) ; PASSWORD UNDER TIMESHARING
FROMTO( .ACPRO, AC.PRB, .AEREQ, AE.PRB) ; PASSWORD UNDER BATCH
NEWDEF( SETPCP, .AEREQ, AE.PCP) ; PROHIBIT PASSWORD CHANGING
NEWDEF( PSWLEN, .AEREQ, AE.PWL) ; MINIMUM PASSWORD LENGTH
NEWDEF( PSWINT, .AEREQ, AE.PCI) ; PASSWORD CHANGE INTERVAL
FROMTO( .ACPRO, AC.LOC, .AEACC, AE.LOC) ;LOGIN LOCAL
FROMTO( .ACPRO, AC.ROP, .AEACC, AE.ROP) ; REMOTE OPERATOR
FROMTO( .ACPRO, AC.DST, .AEACC, AE.DST) ; DATA SET
FROMTO( .ACPRO, AC.RMT, .AEACC, AE.RMT) ; REMOTE
FROMTO( .ACPRO, AC.BAT, .AEACC, AE.BAT) ; BATCH
FROMTO( .ACPRO, AC.SBJ, .AEACC, AE.SBJ) ; BATCH SUB JOB
FROMTO( .ACPRO, AC.RMT, .AEACC, AE.FAL) ; FILE ACCESS
FROMTO( .ACPRO, AC.RMT, .AEACC, AE.CDR) ; PHYSICAL CARD READER
FROMTO( .ACESE, AC.SCD, .AESCD, AE.SCD) ;SCHEDULAR TYPE
FROMTO( .ACESE, AC.EDQ, .AEENQ, ,) ;ENQ/DEQ QUOTA
NEWDEF( CTXMXC, .AECTX, AE.CNQ) ;MAXIMUM NUMBER OF CONTEXTS
NEWDEF( CTXMXP, .AECTX, AE.CPQ) ;MAX NUMBER OF IDLE CONTEXT PAGES
;Customer stuff and obsolete stuff
FROMTO( .ACCUS, , .AECUS, ,) ;CUSTOMER PROFILE WORD.
;FROMTO(.ACCNO, , .AECU2, ,) ;CHARGE NUMBER. OBSOLETE.
EXP 0 ;END OF TABLE.
SUBTTL Main program
NEWACT: JFCL ;IGNORE CCL ENTRY
RESET ;CLEAR THE WORLD'S STATUS
MOVE P,PDLPTR ;GET POINTER TO PUSH DOWN LIST
MOVEI S1,IB.SZ ;SIZE OF IB
MOVEI S2,IB ;POINTER TO INITIALIZATION BLOCK
$CALL I%INIT ;INITIALIZE
PUSHJ P,INITIA ;SETUP INITIAL DATA AND OVERHEAD
PUSHJ P,CONVRT ;CONVERT THE VARIOUS PROFILES
PUSHJ P,FINISH ;CLEAN UP
DIEBAD: EXIT ;DONE
SUBTTL Initialization
INITIA: MOVEI S1,'NEA' ;MODULE PREFIX
SETZ S2, ;NO ERROR PROCESSOR
PUSHJ P,A$ERRI## ;SETUP THE ERROR MODULE
PUSHJ P,INITIO## ;WARM UP ACTRMS
SETZM ZERMEM ;CLEAR A WORD
MOVE S1,[ZERMEM,,ZERMEM+1] ;XFER VECTOR
BLT S1,ZEREND ;FINISH CLEARING VOLATILE MEMORY
PUSHJ P,FNDIFL ;FIND AND CHECK THE INPUT FILES
PUSHJ P,ACCYNK ;YANK IN AN ACCT.SYS ENTRY
SKIPT ;THERE'D BETTER BE ONE
FATAL (NEA,<No entries found in ACCT.SYS>,,DIEBAD)
PUSHJ P,AUXYNK ;YANK IN AN AUXACC.SYS ENTRY
SKIPT ;NEED AT LEAST ONE
FATAL (NEX,<No entries found in AUXACC.SYS>,,DIEBAD)
PUSHJ P,USRINI ;DEAL WITH USERS.TXT
$TEXT (<-1,,OUTFIL>,<DSK:^W/[ACTFIL]/.SYS^0>) ;MAKE OUTPUT FILE NAME
MOVEI S1,OUTFIL ;POINT TO FILE SPEC
MOVEI S2,1 ;WRITE ACCESS
PUSHJ P,OPNA## ;OPEN AS THE PRIMARY FILE
JUMPF INIT.F ;REPORT FAILURES BELOW
MOVEI S1,1 ;OPTION TYPE ONE
MOVEI S2,1 ;SET THE LOAD FLAG
PUSHJ P,OPTA## ;THIS IS THE INITIAL LOAD
MOVEI S1,4 ;OPTION NUMBER
PUSHJ P,OPTA## ;GET RETURNED FILESPEC BLOCK
MOVSI S1,FDXSIZ ;BLOCK LENGTH
MOVEM S1,(S2) ;SET FOR GLXFIL
INFO (WTF,<Writing to file ^F/(S2)/>) ;SAY WHERE THIS IS GOING
SETOM PRODEF+.AEMAP ;START OUT TO DEFAULT
MOVE S1,[PRODEF+.AEMAP,,PRODEF+.AEMAP+1] ;BLT XFER WORD
BLT S1,PRODEF+.AEMAP+.AMPLW-1 ;SETUP TO DEFAULT EVERYTHING
MOVSI P1,-.AEMIN ;AOBJN POINTER TO CHGTAB
MOVEI T1,PRODEF ;CURRENT PROFILE
SETZ T3, ;GOING TO CLEAR THE BITS
INIT.1: HRRZ T2,P1 ;GET JUST THE OFFSET
MOVX T4,PD.CND!PD.UNP ;CAN-NOT-DEFAULT OR USER-CHANGEABLE
TDNE T4,CHGTAB##(P1) ;IS IT ON FOR THIS OFFSET?
PUSHJ P,A$BMAP## ;YES, CLEAR THE 'DEFAULTED' BIT
AOBJN P1,INIT.1 ;LOOP OVER ALL PROFILE ENTRIES
MOVSI P1,-CNDLEN ;TABLE INDEXER FOR ACCT.SYS ENTRIES
INIT.2: MOVE T2,CNDTAB(P1) ;GET NEXT NON-DEFAULTED ENTRY
PUSHJ P,A$BMAP## ;CLEAR ITS DEFAULT BIT
AOBJN P1,INIT.2 ;DEAL WITH EXPLICIT VALUES IN OLD FILE
GETPPN S1, ;GET OUR PPN
JFCL ;WHO WOULD PUT THIS THING IN PRVTAB?
MOVEM S1,PRODEF+.AEPAP ;PROFILE ALTERATION PPN
$CALL I%NOW ;GET THE CURRENT UDT
MOVEM S1,PRODEF+.AETIM ;SET AS PROFILE CHANGE TIME
MOVE S1,[6,,.AEMIN] ;VERSION AND INITIAL LENGTH
MOVEM S1,PRODEF+.AEVRS ;SETUP OVERHEAD WORD
POPJ P, ;DONE SETTING UP
INIT.F: MOVEI S1,2 ;LAST FAB ERROR
PUSHJ P,OPTA## ;GET THE RMS ERROR CODE
FATAL (RIE,<RMS initialization error; code is ^O/S1/>,,DIEBAD)
CNDTAB: EXP .AEPRV,.AEPRX,.AECOR,.AEIPC,.AESPL,.AEACC,.AEREQ,.AEPGR
EXP .AESCD,.AEENQ,.AECTX,.AEEXP
; EXP .AECUS
CNDLEN==.-CNDTAB
SUBTTL Lookup the input files
FNDIFL: MOVEI S1,FOB.MZ ;FOB SIZE
MOVEI S2,ACCFOB ;FOB FOR ACCT.SYS
$CALL F%IOPN ;LOOKUP THE FILE
SKIPT ;DID IT WIN?
FATAL (CRA,<Can't read ACCT.SYS; error is ^E/S1/>,,DIEBAD)
MOVEM S1,ACCIFN ;SAVE IFN FOR READING
MOVEI S1,FOB.MZ ;FOB SIZE
MOVEI S2,AUXFOB ;FOB FOR AUXACC.SYS
$CALL F%IOPN ;LOOKUP THE FILE
SKIPT ;MAKE SURE IT WINS
FATAL (CRX,<Can't read AUXACC.SYS; error is ^E/S1/>,,DIEBAD)
MOVEM S1,AUXIFN ;SAVE IFN FOR READING
MOVE S1,ACCIFN ;READ ACCT.SYS
$CALL F%IBYT ;ONE (FIRST) WORD
SKIPT ;BETTER BE THERE
FATAL (ERA,<Error reading ACCT.SYS; error is ^E/S1/>,,DIEBAD)
IFN FTISWS,<
TXZN S2,1B0 ;CHECK THE ENCRYPTION FLAG
TDZA S1,S1 ;OFF
SETO S1, ;OR ON
MOVEM S1,CPTFLG ;REMEMBER IT FOR LATER
> ;END OF FTISWS
CAMN S2,ACCVWD ;QUICK CHECK AGAINST EXPECTED VALUE
JRST FNDI.1 ;GOT IT, DON'T CHECK FIELDS
LOAD S1,S2,AC.VRS ;NO, GET VERSION FIELD
CAIE S1,.ACCVN ;IS IT WHAT WE EXPECTED?
FATAL (WVA,<Wrong version of ACCT.SYS; expected ^O/[.ACCVN]/ but ^O/S1/ was found>,,DIEBAD)
LOAD S1,S2,AC.LEN ;YES, GET LENGTH FIELD
CAIE S1,.ACLEN ;MAKE SURE IT'S WHAT WE EXPECTED
FATAL (BSA,<Bad size entry in ACCT.SYS; expected ^O/[.ACLEN]/ but ^O/S1/ was found>,,DIEBAD)
FNDI.1: MOVE S1,ACCIFN ;HANDLE FOR ACCT.SYS
MOVEI S2,FI.SIZ ;FILE-INFO SIZE REQUEST
$CALL F%INFO ;ASK GLXFIL FOR RIBSIZ
SKIPT ;I HOPE IT WORKED
FATAL (UGE,<Unexpected GLXLIB error: ^E/S1/>,,DIEBAD)
IDIVI S1,.ACLEN ;CONVERT TO NUMBER OF ENTRIES
CAIE S2,1 ;IS THE REMAINDER WHAT WE EXPECT?
WARN (ILA,<Incorrect length of ACCT.SYS; proceeding>)
MOVEM S1,ACCNUM ;STORE AS COUNT OF ACCT.SYS ENTRIES
MOVE S1,AUXIFN ;HANDLE FOR AUXACC.SYS
$CALL F%IBYT ;READ FORMAT WORD
SKIPT ;I HOPE IT WORKED
FATAL (ERX,<Error reading AUXACC.SYS; error is ^E/S1/>,,DIEBAD)
SKIPE S2 ;CHECK FORMAT/VERSION WORD
FATAL (UVX,<Unknown version of AUXACC.SYS; expected 0 but ^O/S2/ was found>,,DIEBAD)
MOVE S1,ACCIFN ;GET HANDLE FOR ACCT.SYS
SETO S2, ;WANT REAL FILESPEC
$CALL F%FD ;GET AN FD FOR IT
INFO (RAF,<Reading ACCT information from ^F/(S1)/>)
MOVE S1,AUXIFN ;GET HANDLE FOR AUXACC.SYS
SETO S2, ;WANT REAL FILESPEC
$CALL F%FD ;GET AN FD FOR IT
INFO (RXF,<Reading AUXACC information from ^F/(S1)/>)
POPJ P, ;DONE
SUBTTL Initialize the USERS.TXT index
USRINI: MOVEI S1,FOB.MZ ;SIZE OF FOB
MOVEI S2,USRFOB ;FOB FOR USERS.TXT
$CALL F%IOPN ;TRY TO READ THE FILE
JUMPT USRI.0 ;CONTINUE IF LOOKUP SUCCEEDS
CAXN S1,ERFNF$ ;NO SUCH FILE?
$RETT ;PROCEED WITHOUT IT QUIETLY
WARN (CRU,<Can't read USERS.TXT; error is ^E/S1/; proceeding>,,.RETF)
USRI.0: MOVEM S1,USRIFN ;SAVE FILE HANDLE
SETO S2, ;WANT REAL FILESPEC
$CALL F%FD ;GET IT
INFO (BUI,<Building USERS.TXT index from ^F/(S1)/>)
USRI.1: MOVE S1,USRIFN ;RECOVER IFN
$CALL F%IBYT ;GET FIRST BYTE FROM THE LINE
JUMPF USRI.7 ;EOF?
CAIE S2,";" ;IS IT A COMMENT INTRODUCER?
CAIN S2,"!" ;OF EITHER KIND?
JRST USRI.5 ;YES, SKIP THIS LINE
CAIGE S2," " ;OR A CONTROL CHARACTER?
JRST USRI.1 ;YES, WAIT FOR A REAL CHARACTER
CAIA ;NO, START LOOKING FOR A PPN
USRI.2: $CALL F%IBYT ;GET ANOTHER CHARACTER ON THE LINE
SKIPT ;GET IT OK?
FATAL (UUE,<Unexpected USERS.TXT error: ^E/S1/>,,USRI.7)
CAIGE S2," " ;CONTROL CHARACTER?
JRST USRI.1 ;YES, ASSUME END OF LINE
CAIE S2,"[" ;START OF PPN?
JRST USRI.2 ;NO, KEEP LOOKING
PUSHJ P,USRI.4 ;YES, GET PROJECT NUMBER
JUMPF USRI.3 ;ERROR ALREADY GIVEN
CAIE S2,"," ;TERMINATOR OK?
FATAL (SEU,<Syntax error in USERS.TXT>,,USRI.7)
MOVSM T1,USRPPN ;YES, SAVE PRJNUM
PUSHJ P,USRI.4 ;GET PRGNUM
JUMPF USRI.3 ;ERROR ALREADY GIVEN
CAIE S2,"]" ;TERMINATOR OK?
FATAL (SEU,<Syntax error in USERS.TXT>,,USRI.7)
HRRM T1,USRPPN ;YES, SAVE PRGNUM
MOVE S1,USRPPN ;GET PPN JUST PARSED
PUSHJ P,A$CKPP## ;TEST IF IT'S RESERVED
JUMPF USRI.3 ;YES, DON'T BOTHER WITH IT
MOVE S1,USRIFN ;GET FILE HANDLE AGAIN
$CALL F%IBYT ;GET NEXT CHARACTER
SKIPF ;IT BETTER SUCCEED
CAIE S2,"," ;AND LOOK RIGHT
FATAL (SEU,<Syntax error in USERS.TXT>,,USRI.7)
SETZM FIXNAM ;CLEAR OUT OUR BLOCK
MOVE S2,[FIXNAM,,FIXNAM+1] ;XFER WORD
BLT S2,FIXNAM+.AANLW-1 ;CLEAR ALL OF IT
MOVE T1,[POINT 8,FIXNAM] ;STORAGE POINTER
MOVEI T2,.AANLC ;CHARACTER LIMIT
PUSHJ P,USRI.8 ;GET THE NAME
SKIPN FIXNAM ;ANYTHING THERE?
JRST USRI.1 ;NO, FORGET IT
MOVEI S1,FIXNAM ;YES, POINT TO IT
PUSHJ P,A$CKNM## ;SEE IF NAME IS RESERVED
JUMPF USRI.1 ;DON'T BOTHER WITH IT IF SO
IBP T1 ;OK, SKIP PAST A NULL
HRRZI S2,1-FIXNAM(T1) ;GET TOTAL WORD LENGTH OF STRING
PUSHJ P,TREINS ;STICK INTO THE TREE
JRST USRI.1 ;GO UNTIL EOF
USRI.3: MOVE S1,USRIFN ;RECOVER FILE HANDLE
USRI.5: $CALL F%IBYT ;EAT ANOTHER CHARACTER
SKIPT ;EOF NOT ALLOWED HERE
FATAL (SEU,<Syntax error in USERS.TXT>,,USRI.7)
CAIL S2," " ;CONTROL CHARACTER?
JRST USRI.5 ;NO, KEEP LOOKING
JRST USRI.1 ;YES, START ANOTHER LINE
USRI.4: SETZ T1, ;PLACE TO GET OCTAL NUMBER
USRI.6: $CALL F%IBYT ;GET ANOTHER CHARACTER
SKIPT ;BETTER WORK
WARN (BPU,<Bad PPN in USERS.TXT ignored>,,.RETF)
CAIL S2,"0" ;IS IT AN OCTAL DIGIT?
CAILE S2,"7" ;CHECK
$RETT ;NO, WE'RE DONE HERE
LSH T1,3 ;YES, SHIFT NUMBER OVER
TRO T1,-"0"(S2) ;INCLUDE THE DIGIT
TLNN T1,-1 ;RANGE TEST
JRST USRI.6 ;STILL OK SO LOOP
WARN (BPU,<Bad PPN in USERS.TXT ignored>,,.RETF)
USRI.8: $CALL F%IBYT ;GET NEXT CHARACTER OF NAME
$RETIF ;QUIT AT EOF
CAIGE S2," " ;STILL A PRINTING CHARACTER?
$RETT ;NO, WE'RE DONE
CAIL S2,"a" ;YES, IS IT LOWER CASE
CAILE S2,"z" ; ?
CAIA ;NO
TRZ S2,40 ;YES, RAISE CAISE
IDPB S2,T1 ;STUFF INTO BLOCK
SOJG T2,USRI.8 ;LOOP AS LONG AS WE HAVE ROOM
USRI.7: SKIPN S1,USRLIS ;DID WE BUILD AN INDEX?
POPJ P, ;NO, IGNORE THINGS HERE
$CALL L%FIRST ;YES, GET ITS FIRST ENTRY
SKIPF ;IF NO FIRST,
CAME S2,USRMNA ;OR INDEX IS INCONSISTENT,
FATAL (CBI,<Can't build index for USERS.TXT, proceeding without it after all>,,USRI.9)
INFO (UIB,<USERS.TXT index has been built>)
$RETT ;WE WIN
USRI.9: MOVE S1,USRLIS ;GET LIST HANDLE
SETZM USRLIS ;INVALIDATE IT FOR SEARCHERS
PJRST L%DLST ;DELETE THE ENTIRE LIST
SUBTTL Insert USERS.TXT index entries
TREINS: ADDI S2,2 ;ADJUST BY OUR OVERHEAD
MOVEM S2,USRLEN ;SAVE TEXT BLOCK LENGTH
SKIPN USRLIS ;IS THIS THE FIRST ENTRY?
JRST TREI.1 ;YES, GO CREATE THE LIST
MOVE S1,USRPPN ;GET INCOMING PPN
CAMGE S1,USRMIN ;IS THIS A NEW MINIMUM?
JRST TREI.2 ;YES, INSERT AT THE BEGINNING
CAMLE S1,USRMAX ;IS THIS A NEW MAXIMUM?
JRST TREI.3 ;YES, INSERT AT THE TAIL
MOVE T1,USRHED ;NO, START AT THE ROOT AND TRUDGE ALONG
TREI.4: MOVE S1,USRPPN ;GET INCOMING PPN AGAIN
CAMN S1,0(T1) ;IS THIS A DUPLICATE?
WARN (DED,<Duplicate entry for ^U/USRPPN/ discarded>,,.RETF)
CAML S1,0(T1) ;PREDECESSOR?
JRST TREI.5 ;NO, SUCCESSOR
HLRZ S2,1(T1) ;YES, GET PREDECESSOR LINK
JUMPE S2,TREI.7 ;TIME TO INSERT IF NO LEFT SON
MOVE T1,S2 ;ADJUST CURRENT NODE
JRST TREI.4 ;KEEP SEARCHING & SORTING
TREI.7: MOVEI T2,L%CBFR ;CREATE BEFORE CURRENT ENTRY
PUSHJ P,TREI.6 ;COPY DATA TO THIS NEW BLOCK
HRLM S2,1(T1) ;ADJUST LEFT-SON POINTER
$RETT ;BINGO
TREI.6: MOVE S1,USRLIS ;GET LIST HANDLE
MOVE S2,T1 ;COPY NODE POINTER
$CALL L%APOS ;POSITION BY ADDRESS
SKIPT ;BETTER BE OK
$STOP (ICE,<Index consistency error>)
TREI.9: MOVE S2,USRLEN ;GET DESIRED BLOCK LENGTH
PUSHJ P,(T2) ;LINK IN REQUIRED DIRECTION
MOVE S1,USRPPN ;GET INCOMING PPN
MOVEM S1,0(S2) ;SET IN BLOCK
MOVEI S1,2(S2) ;WHERE THE TEXT WILL GO
HRLI S1,FIXNAM ;WHENCE IT COMES
MOVE T2,USRLEN ;TEXT LENGTH
ADDI T2,-1(S2) ;END OF BLT
BLT S1,(T2) ;COPY THE TEXT
POPJ P, ;RETURN TO LINK INTO TREE
TREI.5: HRRZ S2,1(T1) ;GET RIGHT SON POINTER
JUMPE S2,TREI.8 ;TIME TO INSERT IF NO RIGHT SON
MOVE T1,S2 ;ADJUST CURRENT NODE
JRST TREI.4 ;AND KEEP LOOKING FOR A SPOT
TREI.8: MOVEI T2,L%CENT ;LINK AFTER CURRENT ENTRY
PUSHJ P,TREI.6 ;COPY DATA TO THIS NEW BLOCK
HRRM S2,1(T1) ;UPDATE RIGHT-SON POINTER
$RETT ;BINGO
TREI.1: $CALL L%CLST ;CREATE A NEW LIST
MOVEM S1,USRLIS ;SAVE HANDLE
MOVEI T2,L%CENT ;CREATE AFTER NIL
PUSHJ P,TREI.9 ;MAKE AN ENTRY AND COPY DATA TO IT
MOVEM S2,USRMNA ;MIN ADDRESS
MOVEM S2,USRMXA ;MAX ADDRESS
MOVEM S2,USRHED ;ROOT OF TREE
MOVE S1,USRPPN ;PPN JUST INSERTED
MOVEM S1,USRMIN ;IS LEAST
MOVEM S1,USRMAX ;AND LARGEST
$RETT ;BINGO
TREI.2: MOVE T1,USRMNA ;ADDRESS OF OLD MINIMUM
PUSHJ P,TREI.7 ;LINK IN A PREDECESSOR
MOVE S1,USRPPN ;INCOMING PPN
MOVEM S1,USRMIN ;IS NEW MIN PPN
MOVEM S2,USRMNA ;NEW MINIMUM'S ADDRESS
POPJ P, ;AND RETURN
TREI.3: MOVE T1,USRMXA ;ADDRESS OF OLD MAXIMUM
PUSHJ P,TREI.8 ;LINK IN A SUCCESSOR
MOVE S1,USRPPN ;INCOMING PPN
MOVEM S1,USRMAX ;IS NEW MAX PPN
MOVEM S2,USRMXA ;NEW MAXIMUM'S ADDRESS
POPJ P, ;AND RETURN
SUBTTL Main conversion loop
CONVRT: MOVE S1,[PRODEF,,PROFIL] ;XFER WORD
BLT S1,PROFIL+.AEMAX-1 ;INITIALIZE FROM THE DEFAULT PROFILE
SKIPN S1,AUXPPN ;GET PPN OF AUXACC ENTRY
JRST CONV.1 ;THERE IS NONE
SKIPN S2,ACCT+.ACPPN ;IS THERE AN ACCT.SYS ENTRY?
JRST CONV.0 ;NO, SO WE WANT TO DO AUXACC
CAML S1,S2 ;IS IT TIME TO SPLICE IN AUXACC?
JRST CONV.1 ;NO, DON'T BOTHER ME
CONV.0: MOVEM S1,PPN ;YES, SAVE WHAT WE'RE DOING
MOVEM S1,PROFIL+.AEPPN ;SET IN MAIN PROFILE
MOVX S2,AE.FIO ;POSSIBLE FILES-ONLY PPN
TRC S1,-1 ;CHANGE ITS FORM
TRCE S1,-1 ;IS IT OF THE FORM [*,%]?
IORM S2,PROFIL+.AEACC ;NO, DON'T ALLOW IT TO LOG IN
SETOM AUXFLG ;THIS IS FOR AUXACC
PUSHJ P,CNVSPC ;ONLY CONVERT THE SPECIAL ENTRY FORMS
JRST CONV.2 ;GO INSERT THE NEW ENTRY
CONV.1: SETZM AUXFLG ;FLAG A REAL USER ACCOUNT
MOVE S1,ACCT+.ACPPN ;GET PROFILE'S PPN
MOVEM S1,PPN ;SAVE FOR THOSE WHO CARE
PUSHJ P,CNVDAT ;CONVERT THE PROFILE
CONV.2: MOVEI S1,PROFIL ;POINT TO THE ENTRY WE WANT TO ADD
PUSHJ P,PUTA## ;INSERT IT INTO THE FILE
JUMPT CONV.3 ;CONTINUE ON SUCCESS
MOVEI S1,3 ;LAST RAB ERROR
PUSHJ P,OPTA## ;GET RMS CODE
CAIE S1,ER$DUP## ;IS IT A DUPLICATE KEY?
JRST CONV.4 ;NO, DON'T TRY TO MAKE THINGS WORSE
SETZM FIXNAM ;CLEAR NAME WORD
MOVE S1,[FIXNAM,,FIXNAM+1] ;XFER WORD
BLT S1,FIXNAM+.AANLW+1 ;CLEAR ENTIRE BLOCK
SKIPN PROFIL+.AENAM ;HAVE A PREVIOUS NAME?
JRST CONV.6 ;NO, DO SHORT NAME
$TEXT (<POINT 8,FIXNAM,-1>,<^Q/NAMPTR/-^O/PPN,LHMASK/,^O/PPN,RHMASK/^0>) ;YES, CREATE A FIXED-UP NAME
JRST CONV.7 ;SKIP SHORT NAME
CONV.6: MOVE S1,PPN ;GET THE PPN
PUSHJ P,A$CKPP## ;GENERATE SOME TEXT
$TEXT (<POINT 8,FIXNAM,-1>,<^T/(S1)/^0>) ;GENERATE DEFAULT NAME
CONV.7: MOVEI S1,377_4 ;MASK FOR LOW-ORDER BYTE
TDNE S1,FIXNAM+.AANLW-1 ;DID IT FIT?
JRST CONV.4 ;NO, GIVE UP
MOVE S1,[FIXNAM,,PROFIL+.AENAM] ;XFER WORD
BLT S1,PROFIL+.AENAM+.AANLW-1 ;MOVE THE NEW NAME
MOVEI S1,PROFIL ;POINT TO OUR PROPOSED RECORD
PUSHJ P,PUTA## ;TRY IT AGAIN
JUMPT CONV.3 ;FINE IF IT WORKED
CONV.4: MOVEI S1,3 ;GIVE UP
PUSHJ P,OPTA## ;GET LAST RMS ERROR CODE
AOS FAICNT ;COUNT OUR FAILURES
FATAL (EWF,<Error writing output file for ^U/PPN/; RMS error is ^O/S1/>,,CONV.5)
CONV.3: PUSHJ P,CVTPPF ;FORMAT THE PPN
$TEXT (,< ^T/(S1)/ ^Q/NAMPTR/>) ;DISPLAY SOMETHING
AOS COUNT ;NOTE WE CONVERTED ANOTHER SUCCESSFULLY
CONV.5: MOVE S1,PPN ;GET THE NEW PPN
CAML S1,AUXPPN ;DID WE USE UP OUR AUXACC ENTRY?
PUSHJ P,AUXYNK ;YES, GET THE NEXT ONE
MOVE S1,PPN ;GET THE PPN WE'RE INSERTING AGAIN
CAML S1,ACCT+.ACPPN ;DID WE USE UP OUR ACCT.SYS ENTRY?
PUSHJ P,ACCYNK ;YES, FETCH THE NEXT
SKIPN AUXPPN ;IF NO MORE AUXACC,
SKIPE ACCT+.ACPPN ;AND NO MORE ACCT.SYS
JRST CONVRT ;(NO, KEEP CONVERTING)
POPJ P, ;THEN WE'VE FINISHED CONVERTING
SUBTTL Final cleanup
FINISH: PUSHJ P,CLSA## ;CLOSE THE OUTPUT FILE
JUMPF FINI.1 ;LAST CHANCE TO CARE ABOUT ERRORS
MOVE S1,ACCIFN ;POINT TO ACCT.SYS
$CALL F%REL ;RELEASE THE CHANNEL
MOVE S1,AUXIFN ;POINT TO AUXACC.SYS
$CALL F%REL ;RELEASE THE CHANNEL
SKIPE S1,USRIFN ;IF WE HAD A USERS.TXT,
$CALL F%REL ;GET RID OF ITS CHANNEL
SETZM ACCIFN ;CLEAR OUT THE IFNS
SETZM AUXIFN ;FOR NEATNESS'S SAKE
SETZM USRIFN ;BECAUSE IT LOOKS BETTER
SKIPE S1,USRLIS ;IF WE MADE A LINKED LIST,
$CALL L%DLST ;DESTROY IT
SETZM USRLIS ;FORGET THE LIST HANDLE
MOVE S1,COUNT ;GET OUR SUCCESS COUNT
MOVEI T1,[ITEXT (<^D/COUNT/ entries converted>)] ;ASSUME SEVERAL
CAIN S1,1 ;CORRECT?
MOVEI T1,[ITEXT (<One entry converted>)] ;ONLY ONE
SKIPN S1 ;FINAL CHECK
MOVEI T1,[ITEXT (<No entries converted>)] ;HOW CAN THIS HAPPEN?
MOVE S1,FAICNT ;GET OUR FAILURE COUNT
MOVEI T2,[ITEXT (<; there were ^D/FAICNT/ failures>)] ;ASSUME SOME
CAIN S1,1 ;CORRECT?
MOVEI T2,[ITEXT (<; there was one failure>)] ;A BETTER SITUATION
SKIPN S1 ;FINAL CHECK
MOVEI T2,[ITEXT (<>)] ;BEST OF ALL
INFO (SUM,<^I/(T1)/^I/(T2)/>) ;GIVE A SUMMARY
PJRST M%CLNC ;RETURN AFTER CLEANING CORE
FINI.1: MOVEI S1,2 ;LAST FAB ERROR
PUSHJ P,OPTA## ;ASK RMS
FATAL (ECO,<Error closing output file, RMS status is ^O/S1/>,,DIEBAD)
SUBTTL Read an entry from ACCT.SYS
ACCYNK: MOVE S1,ACCIFN ;GET OUR FILE HANDLE
MOVSI T1,-.ACLEN ;POINTER TO FILL UP A BLOCK
ACCY.1: $CALL F%IBYT ;GET A WORD FROM THE FILE
JUMPF ACCY.2 ;CHECK IF EOF OR OTHER ERROR
MOVEM S2,ACCT(T1) ;STORE PROFILE WORD
AOBJN T1,ACCY.1 ;GET AN ENTIRE PROFILE INTO THE BLOCK
SKIPN ACCT+.ACPPN ;IS THIS A VALID ENTRY?
JRST ACCYNK ;NO, TRY AGAIN
$RETT ;YES, RETURN IT
ACCY.2: CAIN S1,EREOF$ ;IF EOF RETURNED,
TRNE T1,-1 ;AT THE START OF A PROFILE,
FATAL (AFE,<ACCT.SYS file error: ^E/S1/>,,.+1) ;NO, COMPLAIN
SETZM ACCT+.ACPPN ;NOTE THE EOF
$RETF ;AND RETURN
SUBTTL Read an entry from AUXACC.SYS
AUXYNK: MOVE S1,AUXIFN ;GET FILE HANDLE FOR AUXACC.SYS
$CALL F%IBYT ;READ START OF NEXT BLOCK
JUMPF AUXY.F ;CHECK FAILURE FOR EOF
AOSE S2 ;IS IT THE EXPECTED FLAG?
FATAL (JIF,<Junk in AUXACC.SYS file>,,AUXY.Z) ;NO, GIVE UP
$CALL F%IBYT ;YES, GET 'LENGTH' WORD
JUMPF AUXY.X ;REQUIRED
MOVEI T1,(S2) ;COPY IT
IDIVI T1,5 ;SEE HOW MANY SUB-ENTRIES
CAIE T2,1 ;MAKE SURE THE FORMAT IS VALID
FATAL (FEX,<Format error in AUXACC.SYS>,,AUXY.Z) ;NO, GIVE UP
MOVNI S2,-1(S2) ;GET MINUS LENGTH OF REAL AUXACC STUFF
HRLZM S2,AUXLEN ;STORE FOR LATER A$EBLK CALL
SETZM AUXBLK ;CLEAR THE BUFFER
MOVE T2,[AUXBLK,,AUXBLK+1] ;XFER WORD
BLT T2,AUXBLK+.AUMAX-1 ;SPREAD THE ZEROS AROUND A LITTLE
$CALL F%IBYT ;GET THE PPN OF THIS ENTRY
MOVEM S2,AUXPPN ;SAVE FOR LATER
JUMPF AUXY.X ;REQUIRED
MOVEI T2,AUXBLK ;POINT TO THE BLOCK WE'RE GOING TO FILL
AUXY.1: SOJL T1,AUXY.2 ;CHECK USEFULNESS AT END OF ENTRY
$CALL F%IBYT ;GET NEXT STRUCTURE
JUMPF AUXY.X ;REQUIRED
MOVEM S2,.AUSTR(T2) ;SAVE AWAY
$CALL F%IBYT ;GET ITS RESERVED QUOTA
JUMPF AUXY.X ;REQUIRED
MOVEM S2,.AURES(T2) ;SAVE IT
$CALL F%IBYT ;GET ITS FCFS QUOTA
JUMPF AUXY.X ;REQUIRED
MOVEM S2,.AULIN(T2) ;SAVE THAT
$CALL F%IBYT ;GET LOGGED-OUT QUOTA
JUMPF AUXY.X ;REQUIRED
MOVEM S2,.AUOUT(T2) ;SAVE AWAY
$CALL F%IBYT ;GET THE STATUS BITS
JUMPF AUXY.X ;REQUIRED
MOVEM S2,.AUBIT(T2) ;SAVE IT
ADDI T2,.AULEN ;UPDATE SUB-BLOCK POINTER
JRST AUXY.1 ;LOOP OVER ALL SUB-BLOCKS FOR THIS ENTRY
AUXY.2: SKIPN AUXPPN ;DID WE CARE AFTER ALL?
JRST AUXYNK ;NO, TRY AGAIN
$RETT ;YES, RETURN THE BLOCK
AUXY.F: CAIN S1,EREOF$ ;WAS IT THE EXPECTED EOF?
JRST AUXY.Z ;YES, JUST GIVE UP
AUXY.X: CAIE S1,EREOF$ ;PREMATURE EOF?
FATAL (UXE,<Unexpected AUXACC.SYS error: ^E/S1/>,,AUXY.Z)
FATAL (PEX,<Premature end of AUXACC.SYS>,,AUXY.Z)
AUXY.Z: SETZM AUXPPN ;NO MORE ENTRIES
$RETF ;RETURN
SUBTTL Convert an entry
CNVDAT: MOVEI T4,XFRBPT ;GET POINTER TO TRANSFER BPT'S
CNVD.1: SKIPN 0(T4) ;CHECK FOR END OF LIST
JRST CNVSPC ;DONE, NOW DO NON-SIMPLE TASKS.
LDB T1,0(T4) ;GET OLD VALUE
DPB T1,1(T4) ;STORE IN NEW PLACE
ADDI T4,2 ;POINT TO NEXT SERIES OF BPT'S
JRST CNVD.1
;HERE TO DO THE NON-TRIVIAL CONVERSIONS
CNVSPC: PUSHJ P,CNVNAM ;CONVERT THE NAME
PUSHJ P,CNVPSW ;CONVERT THE PASSWORD
PUSHJ P,CNVCOR ;CONVERT THE CORE LIMITS
PUSHJ P,CNVPGR ;CONVERT THE PROGRAM-TO-RUN
PUSHJ P,CNVEXP ;CONVERT THE EXPIRATION DATE
PUSHJ P,CNVAUX ;CONVERT THE AUXACC DATA (IF ANY)
; PUSHJ P,CNVCUS ;MAYBE CONVERT CUSTOMER DATA
POPJ P, ;DONE
SUBTTL Convert a username
CNVNAM: MOVE S1,PPN ;GET THE PPN WE'RE CONVERTING
PUSHJ P,A$CKPP## ;CHECK IF RESERVED AND GET A NAME
JUMPF CNVNMR ;RESERVED NAMES NEED LOOK NO FURTHER
MOVEM S1,NAMTXT ;NOT RESERVED, SAVE THE TEXT ADDRESS
CNVNM1: SKIPN S1,USRLIS ;IS THERE AN INDEX FOR USERS.TXT?
JRST CNVNM4 ;NO, DON'T TRY TO USE IT
MOVE S2,PPN ;YES, GET CURRENT PPN AGAIN
CAMN S2,USRMIN ;IS THIS THE NEXT ENTRY TO USE?
JRST CNVNMF ;YES, GO GET A NAME FROM THE FILE
CAML S2,USRMIN ;DID WE SKIP ONE BY?
JRST CNVNMG ;YES, GO FLUSH IT
CNVNM4: SKIPE AUXFLG ;NO USERS.TXT, SHOULD WE CHECK ACCT.SYS?
JRST CNVNM2 ;NO, SKIP THIS
MOVE S2,[POINT 6,ACCT+.ACNM1] ;SOURCE POINTER
PUSHJ P,SIXLEN ;SETUP FOR SIXBIT TO ASCII CONVERSION
MOVE T3,[POINT 8,PROFIL+.AENAM] ;DESTINATION POINTER
JUMPN S1,CNVNM5 ;GO DO IT IF NON-NULL NAME
HRRZ T2,PPN ;GET THE PRGNUM
CAIE T2,-2 ;ONLY ALLOW BLANK NAME FOR [*,#]
JRST CNVNM2 ;NO, USE DEFAULT STRING
SETZ T2, ;YES, RESET TO USE NO BYTES
CNVNM5: EXTEND S1,[EXP <MOVSO 40>,0] ;STRING TRANSLATION
CNVNM2: $TEXT (<POINT 8,PROFIL+.AENAM,-1>,<^T/@NAMTXT/^0>) ;OR STRING MOVING
CNVNM3: MOVEI S1,PROFIL+.AENAM ;POINT TO NAME IN QUESTION
PUSHJ P,A$CKNM## ;TEST IF IT'S RESERVED
$RETIT ;WIN IF IT ISN'T
SETZM PROFIL+.AENAM ;CLEAR START OF NAME
MOVE S1,[PROFIL+.AENAM,,PROFIL+.AENAM+1] ;XFER WORD
BLT S1,PROFIL+.AENAM+.AANLW-1 ;CLEAR REST OF NAME IN PROFILE
JRST CNVNM2 ;USE THE DEFAULT TEXT
CNVNMR: $TEXT (<POINT 8,PROFIL+.AENAM,-1>,<^T/(S1)/^0>) ;JUST USE THIS NAME
POPJ P, ;IT'S GOOD IF RESERVED TO US
CNVNMG: WARN (UES,<USERS.TXT entry for ^U/USRMIN/ wasn't referenced>)
PUSHJ P,CNVNMD ;DELETE THE USELESS NAME
JRST CNVNM1 ;TRY AGAIN TO GET A NAME
CNVNMD: MOVE S1,USRLIS ;WHICH LIST ARE WE TALKING ABOUT
$CALL L%DENT ;DELETE THE CURRENT ENTRY
MOVE S1,USRLIS ;GET LIST HANDLE AGAIN (JUST IN CASE)
$CALL L%FIRST ;MAKE SURE WE HAVE A 'CURRENT' ENTRY
JUMPF CNVNME ;END OF LINKED LIST
MOVE S1,0(S2) ;GET THE PPN
MOVEM S1,USRMIN ;SAVE FOR COMPARISONS
MOVEM S2,USRMNA ;DATA ADDRESS (FOR THOSE WHO CARE)
$RETT ;RETURN WITH A NEW LIST FRONT
CNVNME: MOVE S1,USRLIS ;GET HANDLE AGAIN
$CALL L%DLST ;DELETE THE LIST ITSELF
SETZM USRLIS ;HANDLE NO LONGER VALID
$RETF ;NO MORE NAMES TO BE FOUND HERE
CNVNMF: $CALL L%SIZE ;GET ENTRY'S DATA LENGTH IN WORDS
MOVEI S1,PROFIL+.AENAM-1-2(S2) ;FORM END ADDRESS OF BLT
MOVE S2,USRMNA ;GET ADDRESS OF ENTRY
MOVSI S2,2(S2) ;SOURCE FROM NAME PORTION THEREOF
HRRI S2,PROFIL+.AENAM ;DESTINATION IS THE PROFILE
BLT S2,(S1) ;MOVE THE NAME
PJRST CNVNMD ;DELETE THIS USED ENTRY AND RETURN
SUBTTL Convert a password
CNVPSW: SETZM PSWBLK ;MAKE SURE THE BLOCK STARTS OFF NULL
MOVE S1,[PSWBLK,,PSWBLK+1] ;XFER WORD
BLT S1,PSWBLK+.APWLW-1 ;CLEAR OUT THE ENTIRE BLOCK
SKIPE AUXFLG ;IF THIS IS FOR AUXACC,
JRST CNVPS1 ;DON'T FETCH FROM PROFILE
MOVE S1,ACCT+.ACPSW ;GET THE PASSWORD
IFN NCRYPT!FTISWS,<
IFN FTISWS,<
SKIPE CPTFLG ;ARE WE ENCRYPTING?
>
JRST CNVPS2 ;YES, GO DEAL WITH ENCRYPTION
> ;END IF IFN NCRYPT
MOVEM S1,PSWSIX ;STORE SIXBIT TEXT FOR CONVERSION
MOVE S2,[POINT 6,PSWSIX] ;POINT TO PASSWORD SOURCE
PUSHJ P,SIXLEN ;SETUP FOR MOVSO
MOVE T3,[POINT 8,PSWBLK] ;WHERE TO STORE THE EXPANDED TEXT
EXTEND S1,[EXP <MOVSO 40>,0] ;CONVERT SIXBIT TO 8-BIT ASCII
JFCL ;SHOULD ALWAYS SKIP
CNVPS1: MOVEI S1,PSWBLK ;PASSWORD TEXT
MOVEI S2,PROFIL ;THE PROFILE WE'RE CREATING
PUSHJ P,SETPSW## ;STORE AN ENCRYPTED PASSWORD
JUMPT CNVPS3 ;CONTINUE IF WON
MOVE S1,CURALG## ;GET FAILING ALGORITHM
WARN (EAF,<Encryption algorithm ^O/S1/ failed for ^Q/NAMPTR/ ^U/PPN/>) ;COMPLAIN OF FAILURE
SKIPN PSWBLK ;WAS THERE ANYTHING TO ENCRYPT?
JRST CNVPS3 ;YES, GIVE UP
SETZM PSWBLK ;CLEAR WORD OF BLOCK
MOVE S1,[PSWBLK,,PSWBLK+1] ;XFER VECTOR
BLT S1,PSWBLK+.APWLW-1 ;CLEAR WHOLE BLOCK
JRST CNVPS1 ;TRY AGAIN
IFN NCRYPT!FTISWS,<
CNVPS2: MOVEM S1,PSWBLK ;SAVE ENCRYPTED WORD IN BLOCK
MOVEI T1,PROFIL ;PROFILE WE'RE CREATING
MOVE T2,[-4,,.AEPSW] ;LENGTH AND OFFSET OF EXTENSIBLE BLOCK
MOVEI T3,PSWBLK ;WHERE WE STORED IT
SETO T4, ;WE ALREADY CLEARED THE BIT
PUSHJ P,A$EBLK## ;STUFF THE ALREADY ENCRYPTED PASSWORD IN
MOVEI S1,NCRYPT+4 ;CONVERT 'CUSTOMER' INDEX TO 'DEC' INDEX
STORE S1,PROFIL+.AEFLG,AE.PWE ;SAVE WHICH ALGORITHM WAS USED
> ;END OF IFN NCRYPT
CNVPS3:
IFN PSWCHG,<
SKIPN AUXFLG ;IF FOR A REAL PPN,
SETOM PROFIL+.AEPCT ;REQUIRE A PASSWORD CHANGE AT NEXT LOGIN
>
POPJ P, ;DONE HERE
SUBTTL Convert core limits
CNVCOR: SKIPE AUXFLG ;IF FOR AUXACC,
POPJ P, ;CAN'T DO IT
LOAD S1,ACCT+.ACCIP,AC.NPP ;GET PHYSICAL LIMIT
SKIPE S1 ;IF RESTRICTED,
AOS S1 ;CONVERT TO REAL PAGE LIMIT
STORE S1,PROFIL+.AECOR,AE.NPP ;SET PHYSICAL LIMIT
LOAD S1,ACCT+.ACCIP,AC.NVP ;GET VIRTUAL LIMIT
SKIPE S1 ;IF RESTRICTED,
AOS S1 ;CONVERT TO REAL PAGE LIMIT
STORE S1,PROFIL+.AECOR,AE.NVP ;SET VIRTUAL LIMIT
POPJ P, ;DONE
SUBTTL Convert program-to-run
CNVPGR: SKIPN AUXFLG ;MUST BE A REAL PROFILE,
SKIPN S1,ACCT+.ACPGM ;WITH A REAL PROGRAM-TO-RUN
POPJ P, ;ELSE CAN DO NOTHING
MOVEM S1,PGRBLK+.FDNAM-.FDFIL ;SET NAME IN BLOCK
SKIPN S1,ACCT+.ACDEV ;GET DEVICE FOR PROGRAM IF GIVEN
MOVSI S1,'SYS' ;USE SYS: OTHERWISE
MOVEM S1,PGRBLK+.FDSTR-.FDFIL ;SET DEVICE IN BLOCK
MOVE S1,ACCT+.ACDIR ;GET PPN FOR PROGRAM
MOVEM S1,PGRBLK+.FDPPN-.FDFIL ;SET PPN IN BLOCK
MOVEI T1,PROFIL ;THE PROFILE TO AFFECT
MOVE T2,[.FDFIL-.FDPPN-1,,.AEPGR] ;LENGTH AND OFFSET TO INSERT
MOVEI T3,PGRBLK ;WHERE WE STORED IT
SETO T4, ;WE ALREADY CLEARED THE BIT
PUSHJ P,A$EBLK## ;INSERT THE PROGGIE INTO THE PROFILE
POPJ P, ;DONE HERE
SUBTTL Convert expiration date
CNVEXP: SKIPE S2,AUXFLG ;MUST BE FOR A REAL PROFILE
POPJ P, ;CAN DO NOTHING FOR AUXACC
LOAD S1,ACCT+.ACESE,AC.EXP ;GET OLD EXPIRATION DATE
CAIN S1,-1 ;IF 'NEVER'
SOJA S2,CNVEX1 ;PROPAGATE THE 'NEVER'
MOVEI T1,(S1) ;ELSE, COPY 15-BIT DATE FOR HACKING
IDIVI T1,^D<31*12> ;SEPARATE YEAR
IDIVI T2,^D31 ;THEN MONTHS AND DAYS
MOVEI S1,1(T3) ;GET ACTUAL DAYS AS A BASE
MOVEI S2,^D1964(T1) ;GET REAL YEAR FOR CALCULATIONS
CAIGE T2,2 ;JAN OR FEB?
SOSA S2 ;YES, DECREMENT YEAR
CAIA ;NO, DON'T HIT MONTHS YET
ADDI T2,^D12 ;YES, OFFSET FOR LEAP YEAR HACKERY
ADDI T2,2 ;MAKE +1 OFFSET FROM -1
IMULI T2,^D153 ;INTEGER MULTIPLY MONTH BY (153/5)
IDIVI T2,5 ; TO GET CUMULATIVE MONTH TOTAL
ADDI S1,(T2) ;GET DAYS THIS YEAR
MOVEI T1,(S2) ;COPY YEAR FOR CONVERSION
IMULI S2,^D365 ;GET BASIC COUNT OF DAYS FOR YEAR
IDIVI T1,4 ;GET COUNT OF POSSIBLE LEAP YEARS
ADDI S2,(T1) ;THESE MADE EXTRA DAYS
IDIVI T1,^D25 ;CONVERT TO CENTURIES
SUBI S2,(T1) ;THESE DIDN'T HAVE LEAP DAYS
IDIVI T1,4 ;GET QUADRACENTURIES
ADDI S2,(T1) ;BUT THESE WERE LEAP YEARS AFTER ALL
ADDI S2,(S1) ;ADD COUNT FOR DAYS THIS YEAR
SUB S2,[^D679004] ;MAKE DAY 0=17-NOV-1858
TLNE S2,-1 ;OVERFLOW?
SETO S2, ;YES, MAKE IT 'NEVER' AFTER ALL
HRLOS S2 ;GO TO END OF SPECIFIED DAY
CNVEX1: MOVEM S2,PROFIL+.AEEXP ;SAVE EXPIRATION DATE AWAY
POPJ P, ;DONE HERE
SUBTTL Convert AUXACC data
CNVAUX: MOVE S1,PPN ;GET PPN WE'RE CONVERTING
CAME S1,AUXPPN ;DOES IT HAVE AN AUXACC ENTRY?
POPJ P, ;NOTHING WE CAN DO IF NOT
MOVEI T1,PROFIL ;WHICH PROFILE WE'RE DOING
MOVE T2,AUXLEN ;MINUS BLOCK LENGTH IN LH
HRRI T2,.AEAUX ;PROFILE OFFSET IN RH
MOVEI T3,AUXBLK ;WHERE WE STORED THE DATA
SETZ T4, ;CLEAR THE 'DEFAULTED' BIT
PJRST A$EBLK## ;STUFF INTO THE PROFILE AND RETURN
SUBTTL Format a PPN for display
CVTPPF: PUSHJ P,.SAVE2 ;SAVE P1 AND P2
MOVEI P1,[ITEXT (<^O6R /S1/>)]
MOVEI P2,[ITEXT (<^O6L /S2/>)]
HLRZ S1,PPN ;GET PROJECT NUMBER
HRRZ S2,PPN ;AND PROGRAMMER NUMBER
CAIN S1,-1 ;DEFAULT PROJECT?
MOVEI P1,[ITEXT (< %>)] ;YES
CAIN S2,-1 ;DEFAULT PROGRAMMER?
MOVEI P2,[ITEXT (<% >)] ;YES
CAIN S2,-2 ;WILD PROGRAMMER?
MOVEI P2,[ITEXT (<# >)] ;YES
$TEXT (<-1,,PPNTXT>,<^I/(P1)/,^I/(P2)/^0>)
MOVEI S1,PPNTXT ;POINT TO TEXT
POPJ P, ;AND RETURN
SUBTTL Find the length of a SIXBIT string
SIXLEN: SKIPN 0(S2) ;MAKE SURE
SKIPE S1,1(S2) ;THAT SOMETHING'S THERE
CAIA ;IT IS
JRST SIXL.1 ;NO, JUST RETURN THE ZERO
SKIPN T1,1(S2) ;CHECK LENGTH OF SECOND WORD
MOVE T1,0(S2) ;UNLESS ONLY ONE WORD IN LENGTH
SKIPE S1,1(S2) ;OFFSET LENGTH BY FIRST WORD
MOVEI S1,6 ;IF PRESENT
MOVN T2,T1 ;SHUFFLE SOME BITS
AND T1,T2 ;FIND LAST BIT IN TRAILING WORD
JFFO T1,.+1 ;GET ITS BIT NUMBER
IDIVI T2,6 ;THEN ITS SIXBIT CHARACTER OFFSET
ADDI S1,1(T2) ;TOTAL, CORRECTING FOR 0 VS 1 ORIGIN
SIXL.1: SETZB T1,T4 ;DON'T CONFUSE THE MICROCODE
MOVEI T2,(S1) ;TARGET IS AT LEAST AS LARGE AS SOURCE
POPJ P, ;ALL BUT T3 NOW SETUP
SUBTTL Random hiseg data
PDLPTR: IOWD PDLLEN,PDL ;STACK BASE
NAMPTR: POINT 8,PROFIL+.AENAM ;POINTER TO CONFUSE ITEXT MACRO
ACCVWD: 4,,.ACLEN ;OUR EXPECTED FORMAT WORD OF ACCT.SYS
IB: $BUILD (IB.SZ) ;BUILD A LIBRARY INITIALIZATION BLOCK
$SET (IB.PRG,,%%.MOD) ;PROGRAM NAME
$SET (IB.FLG,IB.NPF,1) ;WE WANT TO USE UP MEMORY
$EOB ;DEFAULT THE REST
ACCFDB: $BUILD (FDXSIZ) ;FD FOR ACCT.SYS
$SET (.FDLEN,FD.LEN,FDXSIZ) ;REMEMBER SIZE OF BLOCK
$SET (.FDSTR,,'DSK ') ;DEVICE DSK:
$SET (.FDNAM,,'ACCT ') ;NAME ACCT
$SET (.FDEXT,,'SYS ') ;EXTENSION .SYS
$EOB
ACCFOB: $BUILD (FOB.MZ) ;SMALL FOB
$SET (FOB.FD,,ACCFDB) ;POINT TO FD
$SET (FOB.CW,FB.BSZ,^D36) ;FULLWORD BYTE SIZE
$EOB
AUXFDB: $BUILD (FDXSIZ) ;AUXACC.SYS FD
$SET (.FDLEN,FD.LEN,FDXSIZ) ;REMEMBER SIZE OF BLOCK
$SET (.FDSTR,,'DSK ') ;DEVICE DSK:
$SET (.FDNAM,,'AUXACC') ;NAME AUXACC
$SET (.FDEXT,,'SYS ') ;EXTENSION .SYS
$EOB
AUXFOB: $BUILD (FOB.MZ) ;SMALL FOB
$SET (FOB.FD,,AUXFDB) ;POINT TO FD
$SET (FOB.CW,FB.BSZ,^D36) ;FULLWORD BYTE SIZE
$EOB
USRFDB: $BUILD (FDXSIZ) ;USERS.TXT FD
$SET (.FDLEN,FD.LEN,FDXSIZ) ;LENGTH OF FD
$SET (.FDSTR,,'DSK ') ;DEVICE DSK:
$SET (.FDNAM,,'USERS ') ;NAME USERS
$SET (.FDEXT,,'TXT ') ;EXTENSION .TXT
$EOB
USRFOB: $BUILD (FOB.MZ) ;SMALL FOB
$SET (FOB.FD,,USRFDB) ;POINT TO FD
$SET (FOB.CW,FB.LSN,1) ;NOTICE (& IGNORE) LSN'S
$SET (FOB.CW,FB.BSZ,^D7) ;BYTE SIZE (TEXT, OF COURSE)
$EOB
SUBTTL Impure (lowseg) data
RELOC 0
ZERMEM:! ;START OF ZEROABLE DATA
PRODEF: BLOCK .AEMAX ;DEFAULT (BASE) PROFILE
PROFIL: BLOCK .AEMAX ;WORKING PROFILE
ACCT: BLOCK .ACLEN ;VERSION 4 PROFILE TO CONVERT
COUNT: BLOCK 1 ;COUNT OF SUCCESSFUL CONVERSIONS
FAICNT: BLOCK 1 ;COUNT OF UNRECOVERED RMS FAILURES
ACCNUM: BLOCK 1 ;NUMBER OF ENTRIES PRESUMED IN ACCT.SYS
AUXLEN: BLOCK 1 ;AOBJN LH FOR .AEAUX
AUXBLK: BLOCK .AUMAX ;SPACE FOR AN AUXACC ENTRY
AUXPPN: BLOCK 1 ;THE PPN FROM THE AUXACC ENTRY
PPN: BLOCK 1 ;OUR CURRENT WORKING PPN
AUXFLG: BLOCK 1 ;FLAG FOR WHETHER CONVERTEE IS A USER
PSWSIX: BLOCK 2 ;SPACE FOR A SIXBIT PASSWORD SOURCE
PSWBLK: BLOCK .APWLW ;SPACE FOR AN 8-BIT PASSWORD
FIXNAM: BLOCK .AANLW+2 ;SPACE TO FIX UP A USERNAME
PGRBLK: BLOCK .FDPPN-.FDFIL+1 ;SPACE FOR A PROGRAM-TO-RUN BLOCK
ACCIFN: BLOCK 1 ;IFN FOR ACCT.SYS
AUXIFN: BLOCK 1 ;IFN FOR AUXACC.SYS
USRIFN: BLOCK 1 ;IFN FOR USERS.TXT
USRLIS: BLOCK 1 ;LIST HANDLE FOR USERS.TXT DATA
USRMIN: BLOCK 1 ;LEAST PPN IN USERS.TXT
USRMNA: BLOCK 1 ;ADDRESS OF ENTRY DESCRIBING USRMIN
USRMAX: BLOCK 1 ;LARGEST PPN IN USERS.TXT
USRMXA: BLOCK 1 ;ADDRESS OF ENTRY FOR USRMAX
USRHED: BLOCK 1 ;ROOT OF TREE WHILE BUILDING USRLIS
USRPPN: BLOCK 1 ;THE CURRENT PPN FROM USERS.TXT
USRLEN: BLOCK 1 ;LENGTH OF ENTRY TO CREATE IN TREINS
NAMTXT: BLOCK 1 ;TEMP. WHILE ASSIGNING USERNAMES
OUTFIL: BLOCK ^D<7*8+3+7*2+1>/5+1 ;SPACE FOR ASCIZ FILESPEC
PPNTXT: BLOCK 4 ;FORMATTED PPN FOR DISPLAY
ZEREND==.-1 ;LAST ZEROABLE WORD WAS ABOVE
PDL: BLOCK PDLLEN ;OUR STACK
RELOC ;BACK TO HISEG FOR LITERALS
END NEWACT