10 !---------------------------------------------------------------------! ! ! ! ACMAN V03.01 ! ! DYNAMIC SYSTEM ACCOUNT MANAGER ! ! BY RUSS SCHWARTZ ! ! NATIONWIDE MUTUAL INSURANCE COMPANY ! ! NOVEMBER, 1979 ! ! ! !---------------------------------------------------------------------! 13 !*********************************************************************! ! ! ! D I S C L A I M E R ! ! ! !*********************************************************************! ! ! ! THIS SOFTWARE IS PROPERTY OF NATIONWIDE MUTUAL INSURANCE ! ! COMPANY. NO WARRANTY, EXPRESS OR IMPLIED, IS MADE CON- ! ! CERNING THE ACCURACY OR RELIABILITY OF THIS SOFTWARE. ! ! THUS THE OWNER ASSUMES NO RESPONSIBILITY FOR THE SUPPORT ! ! OR MAINTENANCE OF THIS SOFTWARE ON ANY SYSTEM. ! ! ! !*********************************************************************! 15 !---------------------------------------------------------------------! ! ! ! "ACMAN" IS THE ACCOUNT MANAGER PROGRAM. IT ATTEMPTS TO ! ! ACCESS THE WORKFILES AND INITIALIZE THEM. IF NOT FOUND, ! ! THEY ARE CREATED. DATA FROM THE "$ACCT.SYS" FILE ARE ! ! READ IN AND SORTED BY ACCOUNT NUMBER, IF NECESSARY. THE ! ! PROGRAM THEN DECLARES THE JOB A RECEIVER AND WAITS FOR ! ! THE FIRST REQUEST. ! ! ! ! THE PROGRAM PROCESSES REQUESTS TO: CREATE AND DELETE ! ! ACCOUNTS; CHANGE PASSWORDS, QUOTAS AND NAMES; VERIFY ! ! ACCOUNTING DATA; UPDATE "$ACCT.SYS"; CREATE ALL ACCOUNTS ! ! ON A DESIGNATED DISK; DUMP A FORMATTED COPY OF "$ACCT.SYS" ! ! TO THE LINE PRINTER; CHANGE "ACMAN"'S CONSOLE; AND ! ! TERMINATE ACCOUNT MANAGEMENT. ! ! ! !---------------------------------------------------------------------! 20 ! EDIT DATE MODIFICATION ! ---- ---- ------------ ! 01 28-NOV-79 RE-WRITTEN FOR VERSION 4. 30 ! VARIABLE NAME DESCRIPTION ! ------------- ----------- 40 ! FUNCTION DESCRIPTION ! -------- ----------- 50 ! SUBROUTINE DESCRIPTION ! ---------- ----------- 58 ! S E T U P P A R A M E T E R S ! ----------------------------------- 60 EXTEND \ DIM #1%, LINK%(400%), INUSE%(400%) \ DIM #2%, ACCT.SYS$(400%) = 64% \ DIM DISK$(1%) ! PROGRAM WRITTEN IN EXTEND MODE. ! DIMENSION STATEMENTS. 65 VERSION$ = "V03.01" \ LIBR$ = "[1,2]" \ ACCT.MAX% = 400% \ BUFLEN% = 84% \ LOGNAM$ = "ACMAN " \ MESMAX% = 10% \ PRIORITY% = -8% \ BURST% = 6% ! SET UP PARAMETERS. 66 TEST% = 0% ! SWITCH TO INDICATE TEST MODE. ! WHEN ON, DISABLES SYS() CALLS WHICH MAKE CHANGES. 68 COMMA$ = " , , , , ," + SPACE$(34%) ! BLANK $ACCT.SYS ENTRY. 70 READ DISK$(INDEX%) FOR INDEX% = 0% TO 1% 72 DATA SY:, SY: 900 !!! RESERVED LINE !!! 990 !---------------------------------------------------------------------! ! ! ! I N I T I A L I Z A T I O N S E C T I O N ! ! ! !---------------------------------------------------------------------! 1000 ON ERROR GO TO 32000 \ Z$ = SYS(CHR$(6%) + CHR$(-7%)) \ Z$ = SYS(CHR$(6%) + CHR$(-13%) + STRING$(2%, 255%) + CHR$(PRIORITY%) + CHR$(255%) + CHR$(BURST%) + STRING$(23%, 0%)) \ Z$ = SYS(CHR$(6%) + CHR$(-22%)) \ HEAD$ = "ACMAN " + VERSION$ + SPACE$(2%) + RIGHT(SYS(CHR$(6%) + CHR$(9%)), 3%) \ PRINT STRING$(6%, 10%) + HEAD$ + CHR$(10%) \ PRINT "Dynamic System Account Manager" + CHR$(10%) ! SET UP ERROR TRAP. ! CTRL/C TRAP ENABLE. ! PRINT A HEADER. 1005 ! A C C E S S W O R K F I L E S ! ----------------------------------- 1010 DETACH%, EXIST%, EXEC%, DONE%, FATAL% = 0% \ OPER$ = CHR$(0%) \ FOR INDEX% = 0% TO 1% \ WORK$ = DISK$(INDEX%) + LIBR$ + "ACMAN" + NUM1$(INDEX%) + ".WRK" \ EXIST% = 0% \ OPEN WORK$ FOR INPUT AS FILE INDEX% + 1% \ EXIST% = -1% ! SEE IF THE WORK FILES ARE THERE. ! ACCESS THEM IF THEY ARE. 1020 OPEN WORK$ FOR OUTPUT AS FILE INDEX% + 1% UNLESS EXIST% ! CREATE EACH MISSING WORKFILE. 1030 FATAL% = ((STATUS AND 1024%) <> 0%) \ NEXT INDEX% \ PRINT TAB(5%); "?Can't write to work file(s)" IF FATAL% \ GO TO 1300 IF FATAL% ! IF WE DON'T HAVE WRITE ACCESS, WE'RE PROBABLY ALREADY ! RUNNING ELSEWHERE, SO TERMINATE. 1032 ! S E T U P W O R K B U F F E R ! -------------------------------------- 1035 OPEN "NL:ACMAN.WRK" AS FILE 11%, RECORDSIZE 64% \ FIELD #11%, 64% AS WBUFF$ \ LSET WBUFF$ = STRING$(64%,0%) \ FIELD #11%, 3% AS ZPROJ$, 3% AS JUNK$, 3% AS ZPROG$, 2% AS JUNK$, 6% AS ZPASWRD$, 1% AS JUNK$, 5% AS ZQUOTA$, 2% AS JUNK$, 3% AS ZCLUSTR$, 2% AS JUNK$, 32% AS ZNAME$, 2% AS JUNK$ ! SET UP WORK BUFFER FOR SPLITTING UP $ACCT.SYS DATA. 1039 ! S E T UP R E Q U E S T B U F F E R ! ------------------------------------------- 1040 OPEN "NL:ACMAN.CMD" AS FILE 12%, RECORDSIZE BUFLEN% \ FIELD #12%, BUFLEN% AS PARM$ \ FIELD #12%, 1% AS KB$, 1% AS CMD$, 2% AS PPN$, 4% AS PASWRD$, 2% AS QUOTA$, 2% AS CLUSTR$, 4% AS DEV$, 4% AS RES$, 64% AS ANAME$ \ LSET PARM$ = STRING$(BUFLEN%, 0%) ! SET UP THE REQUEST BUFFER. 1042 ! I N I T W O R K F I L E S & D E T A C H ! --------------------------------------------------- 1045 LINK%(INDEX%) = INDEX% FOR INDEX% = ACCT.MAX% TO 0% STEP -1% \ INUSE%(INDEX%) = 0% FOR INDEX% = ACCT.MAX% TO 0% STEP -1% \ Z% = FNERASE%(LIBR$ + "ACMAN.LOG") ! INITIALIZE WORK FILE ARRAYS. ! GET RID OF THE OLD LOG FILE. 1050 PRINT "Detaching..." + STRING$(6%, 10%) \ Z$ = SYS(CHR$(6%) + CHR$(7%)) \ DETACH% = -1% \ Z% = FNLOG%(HEAD$) ! TELL THEM WE'RE DETACHING. ! DETACH & SET DETACH INDICATOR. ! PRINT THE HEADER IN THE LOG. 1055 ! R E A D $ A C C T . S Y S ! ---------------------------- 1060 OPEN "$ACCT.SYS" FOR INPUT AS FILE 4% ! ACCESS THE "ACCT.SYS" FILE. 1070 DONE% = 0% \ INDEX% = 1% \ WHILE NOT (DONE%) AND INDEX% <= ACCT.MAX% \ INPUT LINE #4%, ACCT.SYS$(INDEX%) \ LINK%(0%) = INDEX% \ INUSE%(INDEX%) = -1% \ INDEX% = INDEX% + 1% 1080 NEXT \ CLOSE 4% \ ERRTXT$ = "?Work files too small -- Redimension" \ FATAL% = NOT (DONE%) \ Z% = FNSEND%(ERRTXT$) + FNLOG%(ERRTXT$) IF FATAL% \ GO TO 1300 IF FATAL% ! READ IN THE ACCT.SYS DATA ! UNTIL ALLREAD IN OR WORK FILES FULL. ! FATAL ERROR IF WORK FILES FILL UP. 1090 Z% = FNERASE%("$ACCT.BKP") \ NAME "$ACCT.SYS" AS "ACCT.BKP" ! GET RID OF OLD ACCT.SYS BACKUP. ! MAKE CURRENT ACCT.SYS THE NEW BACKUP. 1095 ! C H E C K S O R T R E Q U I R E M E N T S ! ----------------------------------------------- 1100 SORT% = 0% \ SORT% = -1% IF FNPGET(INDEX%) > FNPGET(INDEX% + 1%) FOR INDEX% = 1% TO LINK%(0%) - 1% \ Z% = FNLOG%("%Accounts need sorting") IF SORT% \ GO TO 1130 UNLESS SORT% ! SEE IF ANY ACCOUNTS ARE OUT OF ORDER. ! IF SO, THEN SORT THEM. 1110 SORT% = -1% \ WHILE SORT% \ SORT% = 0% \ FOR INDEX% = 1% TO LINK%(0%) - 1% \ GO TO 1120 UNLESS FNPGET(INDEX%) > FNPGET(INDEX% + 1%) \ SORT% = -1% \ TEMP% = LINK%(INDEX%) \ LINK%(INDEX%) = LINK%(INDEX% + 1%) \ LINK%(INDEX% + 1%) = TEMP% 1120 NEXT INDEX% \ NEXT ! BUBBLE-SORT THE LINKS. 1125 ! D E C L A R E R E C E I V E R ! -------------------------------- 1130 Z$ = SYS(CHR$(6%) + CHR$(22%) + STRING$(38%, 0%)) \ ARG$ = CHR$(6%) + CHR$(22%) + CHR$(1%) + CHR$(0%) + LOGNAM$ + STRING$(11%, 0%) + CHR$(3%) + CVT%$(SWAP%(BUFLEN%)) + CHR$(MESMAX%) + STRING$(15%, 0%) \ Z$ = SYS(ARG$) ! REMOVE THIS JOB AS A RECEIVER. ! DECLARE THIS JOB AS A RECEIVER: ! LOCAL SENDERS ONLY. ! PRIVILEGED SENDERS ONLY. 1140 TEXT$ = "Put on-line at " + TIME$(0%) + " on " + DATE$(0%) \ Z% = FNSEND%(TEXT$) + FNLOG%(TEXT$) ! LET EVERYBODY KNOW WE'RE READY TO RECEIVE REQUESTS. 1145 !---------------------------------------------------------------------! ! ! ! E X E C U T I V E S E C T I O N ! ! ! !---------------------------------------------------------------------! 1200 EXEC% = -1% \ ARG$ = STRING$(6%, 0%) + CHR$(12%) + CHR$(0%) + CVT%$(SWAP%(BUFLEN%)) + STRING$(26%, 0%) \ RCV.NOW$ = CHR$(6%) + CHR$(22%) + CHR$(2%) + CHR$(2%) + ARG$ \ RCV.LATER$ = CHR$(6%) + CHR$(22%) + CHR$(2%) + CHR$(3%) + ARG$ ! GENERATE MESSAGE-RECEIVE CALLS. ! RCV.NOW$ = RECEIVE WITH NO SLEEP. ! RCV.LATER$ = RECEIVE WITH INDEFINITE SLEEP. 1210 GOSUB 3200 ! GENERATE NEW $ACCT.SYS IMMEDIATELY. 1220 WHILE EXEC% \ DONE% = 0% \ WHILE NOT DONE% \ MSG$ = SYS(RCV.NOW$) \ DONE% = -1% 1225 MSG$ = SYS(RCV.LATER$) UNLESS DONE% 1230 NEXT \ XPROJ$ = NUM1$(ASCII(RIGHT(PPN$, 2%))) \ XPROG$ = NUM1$(ASCII(PPN$)) \ XDEV$ = LEFT(DEV$, 2%) \ XDEV$ = XDEV$ + NUM1$(ASCII(MID(DEV$, 3%, 1%))) UNLESS ASCII(MID(DEV$, 4%, 1%)) = 0% \ XDEV$ = XDEV$ + ":" \ XPASWRD$ = RAD$(SWAP%(CVT$%(LEFT(PASWRD$, 2%)))) + RAD$(SWAP%(CVT$%(RIGHT(PASWRD$, 3%)))) \ XQUOTA$ = NUM1$(256. * ASCII(RIGHT(QUOTA$, 2%)) + ASCII(QUOTA$)) \ XCLUSTR$ = NUM1$(SWAP%(CVT$%(CLUSTR$))) \ LSET WBUFF$ = COMMA$ \ ON ASCII(CMD$) + 1% GOSUB 2000, 2200, 2400, 2600, 2800, 3000, 3200, 3400, 3600, 3800, 4000, 4200, 4400, 4600, 4800 \ LSET PARM$ = STRING$(BUFLEN%, 0%) \ NEXT ! WHILE EXECUTE FLAG IS ON. ! RECEIVE A MESSAGE (ONE WAY OR ANOTHER). ! TRANSLATE ALL THE PARAMETERS (THEY'RE USED AS-IS ! IN SYS() CALLS). ! GO EXECUTE THE REQUEST. ! CLEAR OUT THE REQUEST BUFFER WHEN DONE. ! LINE NUMBER COMMAND ! ----------- ------- ! 2000 OFF[LINE] ! 2200 CRE[ATE] OR ENT[ER] ! 2400 DEL[ETE] ! 2600 QUO[TA] ! 2800 CHA[NGE] OR PAS[SWORD] ! 3000 NAM[E] ! 3200 SAV[E] ! 3400 VER[IFY] ! 3600 STA[NDARD] OR REB[UILD] ! 3800 CON[SOLE] OR [OPE]RATOR ! 4000 DUM[P] ! 4200 ! 4400 ! 4600 ! 4800 1290 !---------------------------------------------------------------------! ! ! ! T E R M I N A T I O N S E C T I O N ! ! ! !---------------------------------------------------------------------! 1300 ERRTXT$ = "?Terminating abnormally" \ Z% = FNSEND%(ERRTXT$) + FNLOG%(ERRTXT$) IF FATAL% AND DETACH% \ ERRTXT$ = "Taken off-line at " + TIME$(0%) + " on " + DATE$(0%) \ Z% = FNSEND%(ERRTXT$) + FNLOG%(ERRTXT$) ! SEND ABEND MESSAGE. ! SEND OFF-LINE MESSAGE IN ALL CASES. 1310 CLOSE CHNL% FOR CHNL% = 1% TO 12% \ Z$ = SYS(CHR$(6%) + CHR$(22%) + STRING$(38%, 0%)) \ JOB% = ASCII(SYS(CHR$(6%) + CHR$(9%))) / 2% \ Z$ = SYS(CHR$(6%) + CHR$(8%) + CHR$(JOB%) + STRING$(24%, 0%) + CHR$(255%) + STRING$(2%, 0%)) IF DETACH% \ GO TO 32767 ! CLOSE ALL CHANNELS. ! REMOVE RECEIVER. ! KILL JOB IF DETACHED. ! "END" IF ATTACHED. 1990 !---------------------------------------------------------------------! ! ! ! R E Q U E S T P R O C E S S I N G ! ! ! !---------------------------------------------------------------------! 1995 ! T E R M I N A T E M A N A G E R ( O F F L I N E ) ! ------------------------------------------------------- 2000 EXEC% = 0% \ TEXT$ = "Requested off-line" \ Z% = FNSEND%(TEXT$) + FNLOG%(TEXT$) \ RETURN ! SET SHUT-DOWN FLAG. ! TERMINATE ACCOUNT MANAGER. 2195 ! C R E A T E N E W A C C O U N T ( C R E , E N T ) ! ---------------------------------------------------------- 2200 DONE% = 0% \ Z$ = SYS(CHR$(6%) + STRING$(5%, 0%) + PPN$ + PASWRD$ + QUOTA$ + STRING$(8%, 0%) + DEV$ + CLUSTR$ + STRING$(2%, 0%)) UNLESS TEST% \ TEXT$ = "Created " + XDEV$ + "[" + XPROJ$ + "," + XPROG$ + "]" \ Z% = FNSEND%(TEXT$) \ TEXT$ = TEXT$ + ",paswrd=" + XPASWRD$ + ",quota=" + XQUOTA$ + ",clustr=" + XCLUSTR$ + "," \ Z% = FNLOG%(TEXT$) + FNLOG%(" name=" + ANAME$) \ DONE% = -1% ! CREATE THE ACCOUNT UNLESS IN TEST MODE. ! LET THEM KNOW WE CREATED IT. 2210 TEXT$ = ERRTXT$ + " -- Can't create " + XDEV$ + "[" + XPROJ$ + "," + XPROG$ + "]" \ Z% = FNSEND%(TEXT$) + FNLOG%(TEXT$) UNLESS DONE% \ GO TO 2250 IF NOT(DONE%) OR (XDEV$ <> "SY:") ! WARN THEM IF WE BOMBED ON THE CREATE. ! SKIP UPDATING $ACCT.SYS IF WE BOMBED, OR NOT SYSTEM DISKS. 2220 POINT% = FNSRCH%(INT(VAL(XPROJ$)), INT(VAL(XPROG$)), 0%) \ GO TO 2250 UNLESS POINT% \ LINK%(0%) = LINK%(0%) + 1% \ FREE% = 1% \ FREE% = FREE% + 1% UNTIL (INUSE%(FREE%) = 0%) \ INUSE%(FREE%) = -1% \ LINK%(LINK%(0%)) = FREE% IF POINT% < 0% \ LINK%(INDEX%) = LINK%(INDEX% - 1%) FOR INDEX% = LINK%(0%) TO POINT% + 1% STEP -1% IF POINT% > 0% \ LINK%(POINT%) = FREE% IF POINT% > 0% ! SEARCH FOR THE NEW ENTRY LOCATION. ! INCREMENT ENTRY COUNT. ! MOVE ALL THE LINKS TO MAKE ROOM. ! FIND A FREE ENTRY SLOT. ! ALLOCATE IT. 2240 RSET ZPROJ$ = XPROJ$ \ RSET ZPROG$ = XPROG$ \ LSET ZPASWRD$ = XPASWRD$ \ RSET ZQUOTA$ = XQUOTA$ \ RSET ZCLUSTR$ = XCLUSTR$ \ LSET ZNAME$ = ANAME$ \ ACCT.SYS$(FREE%) = WBUFF$ + CHR$(0%) \ GOSUB 3200 ! SET UP THE NEW ENTRY. ! STORE IT AWAY. ! UPDATE $ACCT.SYS 2250 RETURN ! SUBROUTINE TO CREATE A NEW ACCOUNT. 2395 ! D E L E T E A C C O U N T ( D E L ) ! ----------------------------------------- 2400 DONE% = 0% \ Z$ = SYS(CHR$(6%) + CHR$(1%) + STRING$(4%, 0%) + PPN$ + STRING$(14%, 0%) + DEV$ + STRING$(4%, 0%)) UNLESS TEST% \ TEXT$ = "Deleted " + XDEV$ + "[" + XPROJ$ + "," + XPROG$ + "]" \ Z% = FNSEND%(TEXT$) + FNLOG%(TEXT$) \ DONE% = -1% ! DELETE THE ACCOUNT UNLESS IN TEST MODE. ! LET THEM KNOW WE CREATED IT. 2410 TEXT$ = ERRTXT$ + " -- ?Can't delete " + XDEV$ + "[" + XPROJ$ + "," + XPROG$ + "]" \ Z% = FNSEND%(TEXT$) + FNLOG%(TEXT$) UNLESS DONE% \ GO TO 2450 IF NOT(DONE%) OR (XDEV$ <> "SY:") ! WARN THEM IF WE BOMBED ON THE DELETE. ! SKIP UPDATING $ACCT.SYS IF WE BOMBED, OR NOT SYSTEM DISKS. 2420 POINT% = FNSRCH%(INT(VAL(XPROJ$)), INT(VAL(XPROG$)), -1%) \ GO TO 2450 UNLESS POINT% \ INUSE%(LINK%(POINT%)) = 0% \ LINK%(0%) = LINK%(0%) - 1% \ LINK%(INDEX%) = LINK%(INDEX% + 1%) FOR INDEX% = POINT% TO LINK%(0%) \ GOSUB 3200 ! SEARCH FOR THE ENTRY & FREE IT. ! DECREMENT ENTRY-COUNT. ! MOVE LINKS TO CLOSE UP GAP. ! UPDATE $ACCT.SYS 2450 RETURN ! SUBROUTINE TO DELETE ACCOUNT. 2595 ! C H A N G E Q U O T A ( Q U O ) ! ------------------------------------- 2600 DONE% = 0% \ Z$ = SYS(CHR$(6%) + CHR$(8%) + STRING$(4%, 0%) + PPN$ + STRING$(4%, 0%) + QUOTA$ + STRING$(6%, 0%) + CHR$(255%) + CHR$(0%) + DEV$ + STRING$(4%, 0%)) UNLESS TEST% \ TEXT$ = "Changed quota " + XDEV$ + "[" + XPROJ$ + "," + XPROG$ + "]" \ Z% = FNSEND%(TEXT$) \ TEXT$ = TEXT$ + ",quota=" + XQUOTA$ \ Z% = FNLOG%(TEXT$) \ DONE% = -1% ! CHANGE THE QUOTA UNLESS IN TEST MODE. ! LET THEM KNOW WE CHANGED IT. 2610 TEXT$ = ERRTXT$ + " -- ?Can't change quota " + XDEV$ + "[" + XPROJ$ + "," + XPROG$ + "]" \ Z% = FNSEND%(TEXT$) + FNLOG%(TEXT$) UNLESS DONE% \ GO TO 2650 IF NOT(DONE%) OR (XDEV$ <> "SY:") ! WARN THEM IF WE BOMBED ON THE CHANGE. ! SKIP UPDATING $ACCT.SYS IF WE BOMBED, OR NOT SYSTEM DISKS. 2620 POINT% = FNSRCH%(INT(VAL(XPROJ$)), INT(VAL(XPROG$)), -1%) \ GO TO 2650 UNLESS POINT% \ LSET WBUFF$ = ACCT.SYS$(LINK%(POINT%)) \ RSET ZQUOTA$ = XQUOTA$ \ ACCT.SYS$(LINK%(POINT%)) = WBUFF$ + CHR$(0%) \ GOSUB 3200 ! GET THE ENTRY. ! STORE NEW QUOTA VALUE. ! REPLACE THE ENTRY & UPDATE $ACCT.SYS 2650 RETURN ! SUBROUTINE TO CHANGE A QUOTA. 2795 ! C H A N G E P A S S W O R D ( C H A , P A S ) ! --------------------------------------------------- 2800 DONE% = 0% \ Z$ = SYS(CHR$(6%) + CHR$(8%) + STRING$(4%, 0%) + PPN$ + PASWRD$ + STRING$(10%, 0%) + DEV$ + STRING$(4%, 0%)) UNLESS TEST% \ TEXT$ = "Changed password " + XDEV$ + "[" + XPROJ$ + "," + XPROG$ + "]" \ Z% = FNSEND%(TEXT$) \ Z% = FNLOG%(TEXT$ + ",paswrd=" + XPASWRD$) \ DONE% = -1% ! CHANGE THE PASSWORD UNLESS IN TEST MODE. ! LET THEM KNOW WE DID IT. 2810 TEXT$ = ERRTXT$ + " -- ?Can't change password " + XDEV$ + "[" + XPROJ$ + "," + XPROG$ + "]" \ Z% = FNSEND%(TEXT$) + FNLOG%(TEXT$) UNLESS DONE% \ GO TO 2850 IF NOT(DONE%) OR (XDEV$ <> "SY:") ! WARN THEM IF WE BOMBED ON THE CHANGE. ! SKIP UPDATING $ACCT.SYS IF WE BOMBED OR NOT SYSTEM DISKS. 2820 POINT% = FNSRCH%(INT(VAL(XPROJ$)), INT(VAL(XPROG$)), -1%) \ GO TO 2850 UNLESS POINT% \ LSET WBUFF$ = ACCT.SYS$(LINK%(POINT%)) \ LSET ZPASWRD$ = XPASWRD$ \ ACCT.SYS$(POINT%) = WBUFF$ \ GOSUB 3200 ! SEARCH FOR THE ENTRY. ! GET ITS DATA. ! REPLACE PASWORD AND STORE IT BACK. ! UPDATE $ACCT.SYS 2850 RETURN ! SUBROUTINE TO CHANGE A PASSWORD. 2995 ! C H A N G E A C C O U N T N A M E ( N A M E ) ! ------------------------------------------------------ 3000 POINT% = FNSRCH%(INT(VAL(XPROJ$)), INT(VAL(XPROG$)), -1%) \ GO TO 3050 UNLESS POINT% \ LSET WBUFF$ = ACCT.SYS$(LINK%(POINT%)) \ LSET ZNAME$ = ANAME$ \ ACCT.SYS$(LINK%(POINT%)) = WBUFF$ + CHR$(0%) \ TEXT$ = "Changed name " + XDEV$ + "[" + XPROJ$ + "," + XPROG$ + "]" \ Z% = FNSEND%(TEXT$) + FNLOG%(TEXT$ + ",NAME=" + ANAME$) \ GOSUB 3200 ! GET THE OLD ENTRY. ! STORE NEW NAME & REPLACE THE ENTRY. ! UPDATE $ACCT.SYS NO MATTER WHAT THE DISK. 3050 RETURN ! SUBROUTINE TO CHANGE AN ACCOUNT NAME. 3195 ! G E N E R A T E $ A C C T . S Y S ( S A V ) ! ------------------------------------------------- 3200 Z% = FNERASE%("$ACCT.NEW") \ NO.WRITE% = -1% \ WHILE NO.WRITE% \ CLOSE 4% \ OPEN DISK$(0%) + "$ACCT.NEW" FOR OUTPUT AS FILE 4% \ NO.WRITE% = ((STATUS AND 1024%) <> 0%) \ NEXT ! ATTEMPT TO CREATE NEW $ACCT.SYS UNDER A PSEUDONYM. 3210 PRINT #4%, ACCT.SYS$(LINK%(INDEX%)); FOR INDEX% = 1% TO LINK%(0%) 3220 CLOSE 4% \ Z% = FNERASE%("$ACCT.SYS") \ NAME "$ACCT.NEW" AS "ACCT.SYS" \ TEXT$ = "Saved $ACCT.SYS" \ Z% = FNSEND%(TEXT$) + FNLOG%(TEXT$) IF ASCII(CMD$) = 6% ! WIP OUT OLD $ACCT.SYS ! RENAME NEW ONE. ! SEND THEM A MESSAGE IF THIS WAS A "SAVE". 3230 RETURN ! SUBROUTINE TO GENERATE NEW $ACCT.SYS 3395 ! V E R I F Y A C C O U N T I N G D A T A ( V E R ) ! ---------------------------------------------------------- 3400 DONE% = 0% \ SCAN$ = SYS(CHR$(6%) + CHR$(14%) + STRING$(4%, 0%) + PPN$ + STRING$(14%, 0%) + DEV$ + STRING$(4%, 0%)) \ DONE% = -1% ! LOOK UP THE ACCOUNTING DATA. 3410 TEXT$ = ERRTXT$ + " -- ?Can't verify account" \ Z% = FNSEND%(TEXT$) + FNLOG%(TEXT$) UNLESS DONE% \ GO TO 3450 UNLESS DONE% ! WARN THEM IF WE BOMBED ON THE LOOK-UP. 3420 POINT% = FNSRCH%(INT(VAL(XPROJ$)), INT(VAL(XPROG$)), -1%) \ LSET WBUFF$ = ACCT.SYS$(LINK%(POINT%)) \ Z% = FNSEND%(ZNAME$) \ Z$ = SYS(CHR$(6%) + CHR$(-5%) + KB$ + " ACCT DISK" + CHR$(13%) + CHR$(10%)) \ Z$ = SYS(CHR$(6%) + CHR$(-5%) + KB$ + "QUOTA " + SPACE$(5% - LEN(ZQUOTA$)) + ZQUOTA$ + " " + NUM1$(256. * ASCII(MID(SCAN$, 28%,1%)) + ASCII(MID(SCAN$,27%, 1%))) + CHR$(13%) + CHR$(10%)) \ Z$ = SYS(CHR$(6%) + CHR$(-5%) + KB$ + "CLUSTR " + SPACE$(2% - LEN(ZCLUSTR$)) + ZCLUSTR$ + " " + NUM1$(SWAP%(CVT$%(MID(SCAN$, 29%, 2%)))) + CHR$(13%) + CHR$(10%)) \ Z$ = SYS(CHR$(6%) + CHR$(-5%) + KB$ + "PASWRD " + SPACE$(6% - LEN(ZPASWRD$)) + ZPASWRD$ + " " + RAD$(SWAP%(CVT$%(MID(SCAN$, 9%, 2%)))) + RAD$(SWAP%(CVT$%(MID(SCAN$, 11%, 2%))))) \ SLEEP (10%) \ Z$ = SYS(CHR$(6%) + CHR$(-5%) + KB$ + CHR$(13%) + STRING$(30%, 35%) + CHR$(13%) + STRING$(30%, 72%) + CHR$(13%) + STRING$(30%, 73%) + CHR$(13%) + STRING$(2%, 10%)) \ Z% = FNLOG%("VERIFIED " + XDEV$ + "[" + XPROJ$ + "," + XPROG$ + "]") ! SEND THEM THE DATA, GIVING THEM A CHANCE ! TO READ THE PASSWORD BEFORE WE WIPE IT OUT. 3450 RETURN ! SUBROUTINE TO VERIFY ACCOUNTS. 3595 ! C R E A T E A L L A C C O U N T S ( S T A , R E B ) ! ------------------------------------------------------------ 3600 FOR INDEX% = 1% TO LINK%(0%) \ DONE% = 0% \ LSET WBUFF$ = ACCT.SYS$(LINK%(INDEX%)) \ ARG$ = "SY:" + "[" + ZPROJ$ + "," + ZPROG$ + "]" + ZPASWRD$ + "/SIZE:" + ZQUOTA$ + "/CLUSTER:" + ZCLUSTR$ \ SCAN$ = SYS(CHR$(6%) + CHR$(-10%) + ARG$) \ ARG$ = CHR$(6%) + STRING$(5%, 0%) + MID(SCAN$, 5%, 2%) + MID(SCAN$, 7%, 4%) + MID(SCAN$, 13%, 2%) + STRING$(8%, 0%) + DEV$ + MID(SCAN$, 15%, 2%) + STRING$(2%, 0%) \ Z$ = SYS(ARG$) UNLESS TEST% \ DONE% = -1% ! CREATE EACH ACCOUNT. 3610 TEXT$ = ERRTXT$ + "?Can't create " + XDEV$ + "[" + ZPROJ$ + "," + ZPROG$ + "]" \ Z% = FNSEND%(TEXT$) + FNLOG%(TEXT$) UNLESS DONE% \ NEXT INDEX% ! TELL THEM IF WE BOMBED ON THE CREATE. 3620 TEXT$ = "Rebuilt " + XDEV$ \ Z% = FNSEND%(TEXT$) + FNLOG%(TEXT$) ! LET THEM KNOW WE FINISHED. 3650 RETURN ! SUBROUTINE TO CREATE ALL ACCOUNTS. 3795 ! C H A N G E O P E R . C O N S O L E ( C O N , O P E ) ! -------------------------------------------------------------- 3800 TEXT$ = "Console changed from KB" + NUM1$(ASCII(OPER$)) + ": to KB" + NUM1$(ASCII(RES$)) + ":" \ Z% = FNSEND%(TEXT$) \ OPER$ = LEFT(RES$, 1%) \ Z% = FNSEND%(TEXT$) \ Z% = FNLOG%(TEXT$) \ RETURN 3995 ! D U M P $ A C C T . S Y S ( D U M ) ! ----------------------------------------- 4000 OPEN "LP:ACMAN.OUT" FOR OUTPUT AS FILE 9% \ IF XPASWRD$ = "YES" THEN Z$ = "PASWRD " ELSE Z$ = "" ! ACCESS THE LINE PRINTER FOR THE DUMP. ! SET UP APPROPRIATE PART OF HEADER. 4010 FOR INDEX% = 1% TO LINK%(0%) \ LSET WBUFF$ = ACCT.SYS$(LINK%(INDEX%)) ! EXTRACT THE DATA. 4020 PRINT #9%, CHR$(12%) +"Dump of $ACCT.SYS at " + TIME$(0%) + " on " + DATE$(0%) + CHR$(13%) + STRING$(2%, 10%) + " ACCOUNT " + Z$ + "QUOTA CLU NAME" + CHR$(10%) IF INT((INDEX% - 1%) / 50.) = (INDEX% - 1%) / 50. \ PRINT #9%, "[" + ZPROJ$ + "," + ZPROG$ + "] "; \ PRINT #9%, ZPASWRD$ + " "; IF XPASWRD$ = "YES" \ PRINT #9%, ZQUOTA$ + " " + ZCLUSTR$ + " " + ZNAME$ ! PRINT A HEADER WHEN NECESSARY. ! PRINT THE DATA, INCLUDING PASSWORDS IF DESIRED. 4030 NEXT INDEX% \ TEXT$ = "Dumped $ACCT.SYS to line printer" \ Z% = FNSEND%(TEXT$) + FNLOG%(TEXT$) ! NEXT ACCOUNT. ! LET THEM KNOW WE DID IT. 4040 CLOSE 9% \ RETURN ! SUBROUTINE TO DUMP $ACCT.SYS TO LINE PRINTER. 4195 ! R E S E R V E D F O R E X P A N S I O N ! --------------------------------------------- 4200 Z% = FNSEND%("?Unimplemented command") \ RETURN 4400 Z% = FNSEND%("?Unimplemented command") \ RETURN 4600 Z% = FNSEND%("?Unimplemented command") \ RETURN 4800 Z% = FNSEND%("?Unimplemented command") \ RETURN 17990 !---------------------------------------------------------------------! ! ! ! F U N C T I O N S ! ! ! !---------------------------------------------------------------------! 18000 DEF FNSEND%(TEXT$) \ ARG$ = CHR$(13%) + CHR$(10%) + "ACMAN: " + TEXT$ + CHR$(13%) + CHR$(10%) \ Z$ = SYS(CHR$(6%) + CHR$(-5%) + KB$ + ARG$) \ Z$ = SYS(CHR$(6%) + CHR$(-5%) + OPER$ + ARG$) UNLESS KB$ = OPER$ \ FNEND ! FUNCTION TO SEND A MESSAGE. ! SEND TO BOTH REQUESTOR AND OPERATOR UNLESS THEY'RE THE SAME. 18100 DEF FNLOG%(TEXT$) \ NO.WRITE% = -1% \ WHILE NO.WRITE% \ CLOSE 5% \ OPEN LIBR$ + "ACMAN.LOG" AS FILE 5%, MODE 2% \ NO.WRITE% = ((STATUS AND 1024%) <> 0%) \ NEXT \ PRINT #5%, DATE$(0%) + " " + TIME$(0%) + " " + TEXT$ \ CLOSE 5% \ FNEND ! FUNCTION TO LOG A MESSAGE. 18200 DEF FNPPN(PROJ%, PROG%) = (1000. * PROJ%) + PROG% ! CONVERT A PPN TO A FLOATING POINT NUMBER. 18300 DEF FNERASE%(ARG$) \ ZSCAN$ = SYS(CHR$(6%) + CHR$(-10%) + ARG$) \ ZDIR$ = SYS(CHR$(6%) + CHR$(17%) + STRING$(2%, 255%) + RIGHT(ZSCAN$, 5%)) \ OPEN ARG$ AS FILE 6% \ FIELD #6%, BUFSIZ(6%) AS ZBUFF$ \ LSET ZBUFF$ = STRING$(BUFSIZ(6%), 0%) \ PUT #6% FOR ZINDEX% = 1% TO SWAP%(CVT$%(MID(ZDIR$, 13%, 2%))) \ CLOSE 6% \ KILL ARG$ 18310 FNEND ! FUNCTION TO ERASE A FILE. ! ALL ERRORS CAUSE AN ABORT OF THE FUNCTION. 18400 DEF FNPGET(TEMP%) \ LSET WBUFF$ = ACCT.SYS$(LINK%(TEMP%)) + CHR$(0%) \ FNPGET = (1000. * VAL(ZPROJ$)) + VAL(ZPROG$) \ FNEND ! FUNCTION TO TURN AN ACCT.SYS PPN ENTRY NUMERIC ! FOR COMPARISON PURPOSES. 18500 DEF FNSRCH%(PROJ%, PROG%, TEMP%) \ INDEX% = 1% \ FLAG% = 0% \ PPN = FNPPN(PROJ%, PROG%) \ WHILE FNPGET(INDEX%) < PPN AND INDEX% < LINK%(0%) \ INDEX% = INDEX% + 1% \ NEXT \ FLAG% = INDEX% IF (TEMP% = -1%) AND (FNPGET(INDEX%) = PPN) \ FLAG% = INDEX% IF (TEMP% = 0%) AND (FNPGET(INDEX%) > PPN) \ FLAG% = -1% * INDEX% IF (TEMP% = 0%) AND (INDEX% = LINK%(0%) AND FNPGET(INDEX%) < PPN) \ FNSRCH% = FLAG% \ Z% = FNSEND%("FNSRCH% = " + NUM1$(FLAG%)) IF TEST% \ ERRTXT$ = "?Inconsistency in $ACCT.SYS" \ Z% = FNSEND%(ERRTXT$) + FNLOG%(ERRTXT$) UNLESS FLAG% \ EXEC% = 0% UNLESS FLAG% \ FNEND ! FUNCTION TO FIND AN ENTRY IN $ACCT.SYS ! DATA PASSED: ! TEMP% = 0% MAKE SURE PPN ISN'T THERE. ! TEMP% = -1% MAKE SURE IT IS THERE. ! PROJ%, PROG% PPN IN QUESTION. ! DATA RETURNED: ! FNSRCH% = 0% UNSUCCESSFUL SEARCH. ! FNSRCH% = N% LOCATION OR INSERT POINT OF PPN. ! WARNS USER/OPERATOR WHEN $ACCT.SYS DISAGREES WITH SYSTEM. ! SETS SHUT-DOWN FLAG IF THIS OCCURS. 31990 !---------------------------------------------------------------------! ! ! ! E R R O R H A N D L I N G ! ! ! !---------------------------------------------------------------------! 32000 ERRTXT$ = RIGHT(SYS(CHR$(6%) + CHR$(9%) + CHR$(ERR)), 3%) ! GENERATE ERROR TEXT. 32020 IF ERR = 5% AND ERL = 1010% THEN RESUME 1020 ! WORK FILE(S) MISSING. 32030 IF ERR = 5% AND ERL = 1060% THEN ERRTXT$ = "?ACCT.SYS is missing" \ Z% = FNSEND%(ERRTXT$) + FNLOG%(ERRTXT$) \ FATAL% = -1% \ RESUME 1300 ! CAN'T FIND $ACCT.SYS 32040 IF ERR = 11% AND ERL = 1070% THEN DONE% = -1% \ RESUME 1080 ! END OF $ACCT.SYS REACHED. 32050 IF ERR = 5% AND ERL = 1220% THEN RESUME 1225 ! NO MESSAGE IMMEDIATELY AVAILABLE, SO WAIT. 32060 IF ERL = 18300% THEN RESUME 18310 ! ERRORS IN ERASING A FILE. 32070 IF ERR = 5% AND ERL = 1225% THEN RESUME 1230 ! WE WOKE UP FROM WAIT, SO ONE'S READY. 32080 IF ERL = 2200% THEN RESUME 2210 ! ACCOUNT CREATION ERRORS. 32090 IF ERL = 2400% THEN RESUME 2410 ! ACCOUNT DETION ERRORS. 32100 RESUME 2810 IF ERL = 2800 ! PASSWORD CHANGING ERRORS. 32110 RESUME 2610 IF ERL = 2600% ! QUOTA-CHANGING ERRORS. 32120 RESUME 3410 IF ERL = 3400% ! ACCOUNT VERIFICATION ERRORS. 32130 RESUME 3610 IF (ERL = 3600%) AND (ERR = 2% OR ERR = 16% OR ERR = 10% OR ERR = 3%) \ TEXT$ = ERRTXT$ + " -- ?Aborting rebuild of " + XDEV$ \ Z% = FNSEND%(TEXT$) + FNLOG%(TEXT$) \ RESUME 3650 ! IF ACCOUNT DEPENDENT ERROR, THEN SKIP. ! IF DISK DEPENDENT ERROR, THEN ABORT. 32140 IF ERL >= 4000% AND ERL <= 4030% THEN Z% = FNSEND%("?Line printer hung/not available -- aborting request") \ RESUME 4040 ! ANY LINE PRINTER ERROR ON A DUMP IS FATAL. 32150 IF ERL = 1130% AND ERR = 4% THEN ERRTXT$ = "?No room in receiver table" \ Z% = FNSEND%(ERRTXT$) + FNLOG%(ERRTXT$) \ FATAL% = -1% \ RESUME 1300 ! NO ROOM IN RECEIVER TABLE. 32160 IF ERL = 1130% AND (ERR = 3% OR ERR = 16%) THEN ERRTXT$ = "?Duplicate receiver ID" \ Z% = FNSEND%(ERRTXT$) + FNLOG%(ERRTXT$) \ FATAL% = -1% \ RESUME 1300 ! DUPLICATE RECEIVER ID'S. 32760 PRINT TAB(5%); ERRTXT$ + " at line"; ERL \ PRINT TAB(5%); "?Program malfunction at line"; ERL \ RESUME 32766 ! UNEXPECTED ERRORS. 32766 CLOSE CHNL% FOR CHNL% = 1% TO 12% 32767 END