@X @~
~V7 56 2 -5
~D10
~H                    MUSS
~
~
~D10
~H             LIB111
~D10
~MMANCHESTER UNIVERSITY  -  CONFIDENTIAL
~
~
                                                           ISSUE 11~
~V9 -1
~P
~V9 1
~YLIB111
~S1~M~OLIB IMPLEMENTATION DESCRIPTION~
~S1~M~OSection 11  Version 1~
~S1~OSection 11.1 User Management Utilities~
~S1~O1. General Description~
~BThis module provides a set of utilities for user
management and resource allocation.
~S1~O2. Interfaces~
~
Library procedures~
   NEW.USER (SOURCE1, SOURCE2)~
   DELETE.USER (SOURCE)~
   SET.ACCOUNT (SOURCE1, SOURCE2, SOURCE3)~
   LIST.ACCOUNTS (DEPTH, DEST)~
~S1~O3. Implementation~
~S1~O3.1 Outline of Operation~
~BThe operation of the procedures in this module is
straightforward.~
~S1~O3.2 Data Structures~
~BNone.~
~S1~O3.3 Special Notes~
~BNone.~
~Y
~V9 -1
~P
~V9 -1
~D15
~HFLOWCHARTS
~
~
~H                LIB111
~V9 -1
~F
@TITLE LIB11(1,7)
@COL 1S-2R-3R-4R-5R-6F
@FLOW 1-2-3-4-5-6
@BOX 1.0
USER MANAGEMENT LIBRARY
@BOX 4.0
PROCEDURES IN MODULE:
   1 NEW USER
   2 DELETE USER
   3 SET ACCOUNT
   4 LIST ACCOUNT
   5 READ PARAMS
@BOX 6.0
END
@BOX 1.1
#LIB11/1
MODULE (NEW.USER, DELETE.USER, SET.ACCOUNT, LIST.ACCOUNTS);
@BOX 3.1
TYPE CAT.USER.ENT IS
   LOGICAL64 UNAME, PASSWD
   LOGICAL8 LEVEL, FILLER1, FILLER2, FILLER3
   INTEGER [SYS17.NO.OF.USER.PARAMS] USER.PARAMS;
LITERAL / INTEGER MAP.SEG.1 = 1, READ.INCOMES = 0, READ.BALANCES = 1;
LITERAL / LOGICAL64 TERMINATOR = "@";
LITERAL / ADDR [LOGICAL8] NIL = ;
@BOX 4.1
*CODE 1;
LSPEC NEW.USER (ADDR [LOGICAL8], ADDR [LOGICAL8]);
LSPEC DELETE.USER (ADDR [LOGICAL8]);
LSPEC SET.ACCOUNT (ADDR [LOGICAL8], ADDR [LOGICAL8], ADDR [LOGICAL8]);
LSPEC LIST.ACCOUNTS (LOGICAL8, ADDR [LOGICAL8]);
PSPEC READ.PARAMS (INTEGER, ADDR [INTEGER], ADDR [LOGICAL8]);
   #LIB11.1
   #LIB11.2
   #LIB11.3
   #LIB11.4
   #LIB11.5
@BOX 6.1
*END
@END
@TITLE LIB11/1(1,11)
@COL 1S-2R-3R-4R
@FLOW 1-2-3-4
@BOX 1.0
OTHER MODULES REFERENCED
@BOX 4.0
SYS14 VIRTUAL STORE MANAGEMENT
SYS17 USER MANAGER
@BOX 1.1
::EXTERNAL ENVIRONMENT
@BOX 2.1
@BOX 4.1
IMPORT LITERAL SYS17.NO.OF.RESOURCES,
   SYS17.NO.OF.USER.PARAMS, SYS17.NO.OF.CONSUMABLES, SYS17.NO.OF.REUSABLES;
IMPORT LITERAL ADDR SYS14.SEG.SIZE;
LSPEC CREATE.USER (LOGICAL64);
LSPEC ERASE.USER (LOGICAL64);
LSPEC FIND.U (LOGICAL64, LOGICAL64);
LSPEC CATALOGUE.USERS ();
LSPEC NEWPASSWORD (LOGICAL64, LOGICAL64);
LSPEC SET.USER.PARAM (LOGICAL64, INTEGER, INTEGER);
LSPEC MAP (INTEGER, INTEGER, INTEGER);
LSPEC CAPTION (ADDR [LOGICAL8]);
LSPEC PROMPT (ADDR [LOGICAL8]);
LSPEC IN.NAME () / LOGICAL64;
LSPEC NEXT.CH () / INTEGER;
LSPEC IN.CH () / INTEGER;
LSPEC OUT.FN (ADDR [LOGICAL8]);
LSPEC OUT.CH (INTEGER);
LSPEC BREAK.OUTPUT (INTEGER);
LSPEC NEW.LINES (INTEGER);
LSPEC OUT.NAME (LOGICAL64);
LSPEC SPACES (INTEGER);
LSPEC IN.I () / ADDR;
LSPEC OUT.I (INTEGER32, INTEGER);
LSPEC CURRENT.INPUT () / INTEGER;
LSPEC CURRENT.OUTPUT () / INTEGER;
LSPEC DEFINE.INPUT (INTEGER, ADDR [LOGICAL8], INTEGER32) / INTEGER;
LSPEC DEFINE.OUTPUT (INTEGER, ADDR [LOGICAL8], INTEGER32, INTEGER32) / INTEGER;
LSPEC SELECT.INPUT (INTEGER);
LSPEC SELECT.OUTPUT (INTEGER);
LSPEC END.INPUT (INTEGER, INTEGER);
LSPEC END.OUTPUT (INTEGER, INTEGER);
ADDR PW0, PW1, PW2, PW3, PW4, PW5, PW6;
LOGICAL64 PWW1, PWW2;
@END
@TITLE LIB11.1(1,7)
@COL 1S-2R-8R-9R-4T-6R-7T-10T-12R
@COL 15R-13F
@FLOW 1-2-8-9-4NO-6-7OK-10NO-12-4
@FLOW 4YES-15-13
@FLOW 7FAULT-15
@FLOW 10YES-15
@ROW 12-15

@BOX 1.0
NEW USER (SOURCE1,SOURCE2)
@BOX 2.0
READ IN INCOMES
[LIB11.5]
@BOX 4.0
READ IN USER NAME?
@BOX 6.0
CREATE USER
@BOX 7.0
CREATION FAILED?
@BOX 8.0
SET UP NEW STREAM IF NECESSARY
@BOX 9.0
SELECT INPUT STREAM
@BOX 10.0
PASSWORD AVAILABLE?
@BOX 12.0
SET PASSWORD
@BOX 13.0
END
@BOX 15.0
SELECT ORIGINAL INPUT STREAM
@BOX 1.1
PROC NEW.USER (SOURCE1, SOURCE2);
INTEGER I, TEMP, CHAR, CURR.STR.NO, PREV.STR.NO, SAVED.PW0;
INTEGER [SYS17.NO.OF.RESOURCES] INCOME;
LOGICAL64 UNAME, PASSWD;
@BOX 2.1
READ.PARAMS (READ.INCOMES, ^INCOME, SOURCE1);
@BOX 4.1
PROMPT (%"USERNAME? ");
IF IN.NAME () => UNAME = TERMINATOR
@BOX 6.1
-1 => I;
CREATE.USER (UNAME);
WHILE PW0 = 0 AND 1 +> I < SYS17.NO.OF.RESOURCES DO
   IF INCOME [I] => TEMP = -1 THEN
      0 => TEMP;
   FI
   SET.USER.PARAM (UNAME, I + SYS17.NO.OF.CONSUMABLES, TEMP);
   IF  I < SYS17.NO.OF.CONSUMABLES AND PW0 = 0 THEN
      SET.USER.PARAM (UNAME, I, TEMP);
   FI
OD
@BOX 7.1
IF PW0 /= 0
@BOX 8.1
CURRENT.INPUT () => PREV.STR.NO;
IF SOURCE2 /= NIL THEN
   DEFINE.INPUT (-1, SOURCE2, 0) => CURR.STR.NO;
ELSE
   PREV.STR.NO => CURR.STR.NO;
FI
@BOX 9.1
SELECT.INPUT (CURR.STR.NO);
@BOX 10.1
OUT.NAME (UNAME);
CAPTION (%" CREATED");
NEW.LINES (1);
PROMPT (%"PASSWORD? ");
IF IN.NAME () => PASSWD = TERMINATOR
@BOX 12.1
NEW.PASSWORD (PASSWD, UNAME);
@BOX 13.1
END
@BOX 15.1
PW0 => SAVED.PW0;
IF CURR.STR.NO /=  PREV.STR.NO THEN
   SELECT.INPUT (PREV.STR.NO);
   END.INPUT (CURR.STR.NO, 0);
FI
SAVED.PW0 => PW0;
@END
@TITLE LIB11.2(1,7)
@COL 1S-3R-4R-5T-6T-7R-11R-12F
@FLOW 1-3-4-5NO-6NO-7-5
@FLOW 5YES-11-12
@FLOW 6YES-11
@BOX 1.0
DELETE USER (SOURCE)
@BOX 3.0
SET UP NEW STREAM IF NECESSARY
@BOX 4.0
SELECT NEW STREAM
@BOX 5.0
READ USERNAME,
CHECK FOR TERMINATOR?
@BOX 6.0
NOT ABLE TO ERASE THE USER?
@BOX 7.0
OUTPUT USERNAME OF ERASED USER
@BOX 11.0
SELECT ORIGINAL STREAM IF NECESSARY
@BOX 12.0
END
@BOX 1.1
PROC DELETE.USER (SOURCE);
INTEGER CURR.STR.NO, PREV.STR.NO, SAVED.PW0;
LOGICAL64 USERNAME;
@BOX 3.1
CURRENT.INPUT () => PREV.STR.NO;
IF SOURCE /= NIL THEN
   DEFINE.INPUT (-1, SOURCE, 0) => CURR.STR.NO;
ELSE
   PREV.STR.NO => CURR.STR.NO;
FI
@BOX 4.1
SELECT.INPUT (CURR.STR.NO);
PROMPT (%"USERNAME? ");
@BOX 5.1
IF IN.NAME () => USERNAME = TERMINATOR
@BOX 6.1
ERASE.USER (USERNAME);
IF PW0 /= 0
@BOX 7.1
OUT.NAME (USERNAME);
CAPTION (%" DELETED");
NEW.LINES (1);
@BOX 11.1
PW0 => SAVED.PW0;
IF CURR.STR.NO /=  PREV.STR.NO THEN
   SELECT.INPUT (PREV.STR.NO);
   END.INPUT (CURR.STR.NO, 0);
FI
SAVED.PW0 => PW0;
@BOX 12.1
END
@END
@TITLE LIB11.3(1,7)
@COL 1S-2R-10R-11R-12R-3T-5R-6T-13R-14R-9F
@FLOW 1-2-10-11-12-3OK-5-6NO-13-3
@FLOW 3TERMINATOR-14-9
@FLOW 6YES-14
@BOX 1.0
SET ACCOUNT (SOURCE1, SOURCE2, SOURCE3)
@BOX 2.0
READ USER INCOMES
[LIB11.5]
@BOX 3.0
READ USERNAME AND CHECK FOR TERMINATOR?
@BOX 5.0
SET BALANCES
@BOX 6.0
FAULT?
@BOX 9.0
END
@BOX 10.0
READ USER BALANCES
[LIB11.5]
@BOX 11.0
SET UP NEW STREAM IF NECESSARY
@BOX 12.0
SELECT INPUT STREAM
@BOX 13.0
OUTPUT USERNAME
@BOX 14.0
SELECT ORIGINAL INPUT STREAM
@BOX 1.1
PROC SET.ACCOUNT (SOURCE1, SOURCE2, SOURCE3);
INTEGER [SYS17.NO.OF.RESOURCES] INCOMES;
INTEGER [SYS17.NO.OF.CONSUMABLES] BALANCES;
INTEGER I, CURR.STR.NO, PREV.STR.NO, SAVED.PW0;
LOGICAL64 UNAME;
@BOX 2.1
READ.PARAMS (READ.INCOMES, ^INCOMES, SOURCE1);
@BOX 3.1
IF IN.NAME () => UNAME = TERMINATOR
@BOX 5.1
-1 => I;
WHILE PW0 = 0 AND 1 +> I < SYS17.NO.OF.RESOURCES DO
   IF INCOMES [I] /= -1 THEN
      SET.USER.PARAM (UNAME, I + SYS17.NO.OF.CONSUMABLES, INCOMES [I]);
   FI
OD
-1 => I;
WHILE PW0 = 0 AND 1 +> I < SYS17.NO.OF.CONSUMABLES DO
   IF BALANCES [I] /= -1 THEN
      SET.USER.PARAM (UNAME, I, BALANCES [I]);
   FI
OD
@BOX 6.1
IF PW0 /= 0
@BOX 9.1
END
@BOX 10.1
READ.PARAMS (READ.BALANCES, ^BALANCES, SOURCE2);
@BOX 11.1
CURRENT.INPUT () => PREV.STR.NO;
IF SOURCE3 /=  NIL THEN
   DEFINE.INPUT (-1, SOURCE3, 0) => CURR.STR.NO;
ELSE
   PREV.STR.NO => CURR.STR.NO;
FI
@BOX 12.1
SELECT.INPUT (CURR.STR.NO);
PROMPT (%"USERNAME? ");
@BOX 13.1
OUT.NAME (UNAME);
CAPTION (%" ACCOUNTS SET");
NEW.LINES (1);
@BOX 14.1
PW0 => SAVED.PW0;
IF CURR.STR.NO /= PREV.STR.NO THEN
   SELECT.INPUT (PREV.STR.NO);
   END.INPUT (CURR.STR.NO, 0);
FI
SAVED.PW0 => PW0;
@END
@TITLE LIB11.4(1,7)

@COL 1S-2R-3R-4R-7R-9T-10R-11F
@FLOW 1-2-3-4-7-9NO-10-11
@FLOW 9YES-7
@BOX 1.0
LIST ACCOUNTS (DEPTH, DEST)
@BOX 2.0
SET UP OUTPUT STREAM
@BOX 3.0
GET USER CATALOGUE
@BOX 4.0
OUTPUT HEADINGS
@BOX 7.0
WRITE OUT USER ACCOUNTS
#LIB11.4.1
@BOX 9.0
MORE USER?
@BOX 10.0
RESELECT ORIGINAL OUTPUT STREAM
@BOX 11.0
END
@BOX 1.1
PROC LIST.ACCOUNTS (DEPTH, DEST);
ADDR [CAT.USER.ENT] USER;
INTEGER USER.NO, OUT.STR.NO, PREV.STR.NO, SUBORDS.USED, J, NO.USERS,
   USER.UID, FIRST.REUSABLE;
@BOX 2.1
CURRENT.OUTPUT () => PREV.STR.NO;
IF DEST /= NIL THEN
   DEFINE.OUTPUT (-1, DEST , 0, 0) => OUT.STR.NO;
ELSE
   PREV.STR.NO => OUT.STR.NO;
FI
@BOX 3.1
SELECT.OUTPUT (OUT.STR.NO);
CATALOGUE.USERS ();
PW1 => NO.USERS;
MAP (PW2, MAP.SEG.1, 0);
MAKE (CAT.USER.ENT, NO.USERS, SYS14.SEG.SIZE * PW6) => USER;
IF DEPTH = 0 OR DEPTH = "0" THEN
   "S" => DEPTH;
FI
0 => USER.NO;
@BOX 4.1
OUT.FN (%"  ACCOUNTS");
NEW.LINES (1);
CAPTION (%"USERNAME  L     CPU.BAL     CPU.INC   MAX.FILES");
CAPTION (%"   MAX.F.STORE  SUBS    MAX.SUBS");
NEW.LINES (1);
@BOX 7.1
::WRITE OUT ACCOUNTS
#LIB11.4.1
@BOX 9.1
IF 1 +> USER.NO < NO.USERS
@BOX 10.1
NEW.LINES (1);
IF PREV.STR.NO /= OUT.STR.NO THEN
   SELECT.OUTPUT (PREV.STR.NO);
   END.OUTPUT (OUT.STR.NO, 0);
FI
@BOX 11.1
END
@END
@TITLE LIB11.4.1(1,7)
@COL 1S-2T-3R-4R-5R-6R-7R-8F
@FLOW 1-2NO-3-4-5-6-7-8
@FLOW 2YES-8
@BOX 1.0
WRITE OUT ACCOUNTS
@BOX 2.0
THIS USER'S ACCOUNTS NOT REQUIRED?
@BOX 3.0
OUTPUT USERNAME AND LEVEL
@BOX 4.0
OUTPUT "CPU TIME ACCOUNTS"
@BOX 5.0
OUTPUT "FILES ACCOUNTS"
@BOX 6.0
OUTPUT "FILE STORE ACCOUNTS"
@BOX 7.0
OUTPUT "SUBORDS ACCOUNTS"
@BOX 8.0
END
@BOX 1.1
::WRITE OUT ACCOUNTS
@BOX 2.1
IF DEPTH = "S" AND LEVEL OF USER^ [USER.NO] > 1
@BOX 3.1
SELECT USER^ [USER.NO];
NEW.LINES (1);
OUTNAME (UNAME);
OUT.I (LEVEL, 2);
@BOX 4.1
OUT.I (USER.PARAMS [1], 11);
OUT.I (USER.PARAMS [SYS17.NO.OF.CONSUMABLES + 1], 11);
@BOX 5.1
SYS17.NO.OF.CONSUMABLES * 2 => FIRST.REUSABLE;
OUT.I (USER.PARAMS [FIRST.REUSABLE], 11);
@BOX 6.1
OUT.I (USER.PARAMS [FIRST.REUSABLE + 1], 13);
@BOX 7.1
0 => SUBORDS.USED;
USER.NO => J;
WHILE 1 +> J < NO.USERS AND LEVEL OF USER^ [J] /= LEVEL DO
   IF LEVEL OF USER^ [J] = LEVEL + 1 THEN
      1 +> SUBORDS.USED;
   FI
OD
OUT.I (SUBORDS.USED, 5);
OUT.I (USER.PARAMS [FIRST.REUSABLE + 2], 11);
@BOX 8.1
::END OF  WRITE OUT ACCOUNTS
@END

@TITLE LIB11.5(1,7)

@COL 1S-3R-4R-15R-5R-6R-7R-8T-9R-10R-11T-12R-14F
@COL 16R
@ROW 9-16
@FLOW 1-3-4-15-5-6-7-8NO-9-10-11NO-12-14
@FLOW 8YES-16-10
@FLOW 11YES-6
@BOX 1.0
READ PARAMETERS (INIT CAPTION SWITCH, VALUES, SOURCE)
@BOX 3.0
SET UP INPUT STREAM IF NECESSARY
@BOX 4.0
SELECT NEW INPUT STREAM
@BOX 5.0
FIND NUMBER OF INPUT ELEMENTS
@BOX 6.0
PROMPT FOR INPUT
@BOX 7.0
READ NEXT NON SPACE CHARACTER
@BOX 8.0
CHARACTER IS A TERMINATOR?
@BOX 9.0
READ IN NEXT PARAMETER
@BOX 10.0
SKIP TO START OF NEXT PARAMETER LINE
@BOX 11.0
ANY MORE USERS?
@BOX 12.0
RESET TO ORIGINAL INPUT STREAM, IF NECESSARY
@BOX 14.0
END
@BOX 15.0
OUTPUT THE INITIAL HEADING
@BOX 16.0
FILL IN REST OF THE VALUES WITH -1
@BOX 1.1
PROC READ.PARAMS (INIT.CAP.SWITCH, VALUES, SOURCE);
INTEGER PREV.STR.NO, CURR.STR.NO, VAL.NO, CHAR, NO.OF.VALS;
::MONITORING DATAVECS
#LIB11.5.1
@BOX 3.1
CURRENT.INPUT () => PREV.STR.NO;
IF SOURCE /= NIL THEN
   DEFINE.INPUT (-1, SOURCE, 0) => CURR.STR.NO;
ELSE
   PREV.STR.NO => CURR.STR.NO;
FI
@BOX 4.1
SELECT.INPUT (CURR.STR.NO);
@BOX 5.1
0 => VAL.NO;
SIZE (VALUES) => NO.OF.VALS;
::TEMP OUTPUT RESOURCE TO BE REMOVED ALTOGETHER IN THE NEXT ISSUE
::TEMP SKIP OVER OUTPUT
-1 => VALUES^ [VAL.NO];
1 => VAL.NO;
::END OF TEMP
@BOX 6.1
PROMPT (PROMPT.PTR [VAL.NO]);
@BOX 7.1
WHILE NEXT.CH () => CHAR =< " " /= "$L" DO
   IN.CH ();
OD
@BOX 8.1
IF CHAR = TERMINATOR
@BOX 9.1
IF CHAR = "$L" OR CHAR =< "0" OR CHAR >= "9" THEN
   -1 => VALUES^ [VAL.NO];
ELSE
   IN.I () => VALUES^ [VAL.NO];
FI
@BOX 10.1
WHILE NEXT.CH () /= "$L" DO
   IN.CH ();
OD
IN.CH ();
@BOX 11.1
IF 1 +> VAL.NO < NO.OF.VALS
@BOX 12.1
IF CURR.STR.NO /= PREV.STR.NO THEN
   SELECT.INPUT (PREV.STR.NO);
   END.INPUT (CURR.STR.NO, 0);
FI
@BOX 14.1
END
@BOX 15.1
IF INIT.CAP.SWITCH = READ.INCOMES THEN
   CAPTION (%"ENTER INCOMES/MAXIMA$L");
ELSE
   CAPTION (%"ENTER BALANCES FOR CONSUMABLES$L");
FI
BREAK.OUTPUT (-1);
@BOX 16.1
WHILE VAL.NO < NO.OF.VALS DO
   -1 => VALUES^ [VAL.NO];
   1 +> VAL.NO;
OD
@END
@TITLE LIB11.5.1(1,7)

@COL 1S-2R-3R-4R
@FLOW 1-2-3-4
@BOX 1.0
MONITORING DATAVECS
@BOX 4.0
DATAVECS
@BOX 1.1
::MONITORING DATAVECS
@BOX 4.1
::TEMP OUTPUT TO BE REMOVED ALTOGETHER IN THE NEXT ISSUE
DATAVEC OUTPUT.PR (LOGICAL8)
   "OUTPUT "
END
::END OF TEMP
DATAVEC CPU.PR (LOGICAL8)
   "CPU TIME "
END
DATAVEC NO.OF.FILES.PR (LOGICAL8)
   "NO OF FILES "
END
DATAVEC FILE.STORE.PR (LOGICAL8)
   "FILE STORE "
END
DATAVEC SUBORD.PR (LOGICAL8)
   "SUBORDS "
END
DATAVEC PROMPT.PTR (ADDR [LOGICAL8])
   OUTPUT.PR CPU.PR NO.OF.FILES.PR
   FILE.STORE.PR SUBORD.PR
END
@END


