Google
 

Trailing-Edge - PDP-10 Archives - bb-d868c-bm_tops20_v4_2020_distr - 4-sources/ulist.mac
There are 21 other files named ulist.mac in the archive. Click here to see a list.
;<4.UTILITIES>ULIST.MAC.25,  3-Jan-80 15:27:53, EDIT BY R.ACE
;UPDATE COPYRIGHT DATE
;<4.UTILITIES>ULIST.MAC.24, 12-Mar-79 14:25:52, EDIT BY KONEN
;UPDATE COPYRIGHT FOR RELEASE 4
;<4.UTILITIES>ULIST.MAC.23, 23-Jan-79 16:22:13, Edit by KONEN
;UPDATE VERSION NUMBER FOR RELEASE 4
;<4.UTILITIES>ULIST.MAC.22,  13-APR-78 14:22:52 EDIT BY COWER
;TCO 1902 - INFO ON MORE THAN ONE STRUCTURE IN SESSION



;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1976,1977,1978,1979,1980 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.

TITLE ULIST  LIST USER DIRECTORY
	SEARCH MONSYM, MACSYM
	.REQUIRE SYS:MACREL
	SALL
	IFNDEF .PSECT,<
	.DIRECT .XTABM>

; VERSION NUMBER DEFINITIONS

VMAJOR==4		;MAJOR VERSION OF ULIST
VMINOR==0		;MINOR VERSION NUMBER
VEDIT==10		;EDIT NUMBER
VWHO==0			;GROUP WHO LAST EDITED PROGRAM (0=DEC DEVELOPMENT)

VULIST== <VWHO>B2+<VMAJOR>B11+<VMINOR>B17+VEDIT

F=0		;FLAG AC
A=1
B=2
C=3
D=4
E=5
NC=6
T1=7
T2=10
T3=11
BP=12
CH=13
CX=16
P=17

COLWID==^D32			;COLUMN WIDTH FOR MINI LISTING
NARCOL==^D72/COLWID		;NUMBER OF COLUMNS ON NARROW LISTING
WIDCOL==^D132/COLWID		;NUMBER OF COLUMNS ON WIDE LISTING

NCHPW==5		;NUMBER OF ASCII CHARACTERS PER WORD
MAXUSR==20000		;MAXIMUM USER NUMBER+1
PAGLEN==^D56		;LINES WRITTEN ON A PAGE
COMFRE==50		;FREE SPACE AFTER COMMAND TABLE
GRPLSZ==17000		;SIZE OF MASTER GROUP BIT MAP
NGPUSR==10		;ESTIMATED AVERAGE # OF GROUPS/USER
GRPSIZ==1000		;SIZE OF GROUP BLOCKS
GBFSIZ==^D12/5+1	;SIZE OF GROUP BUFFER FOR OUTPUT
BUFSIZ==200		;SIZE OF INPUT TEXT BUFFER
ATMSIZ==200		;SIZE OF ATOM BUFFER
GJFSIZ==.GJRTY+2	;SIZE OF GTJFN BLOCK FOR COMND JSYS

C.FF==14		;FORMFEED

NAMPAG==100000			;PAGE FOR NAME STRING STORAGE
NAMPTR==200000			;POINTERS TO THE NAME STRINGS

TEMPS==NAMPTR			;START OF PAGES TO BE ZEROED
 UGRTAB==NAMPTR+MAXUSR		;USER GROUP POINTERS
 DGRTAB==UGRTAB+MAXUSR		;DIRECTORY GROUP POINTERS
 ORDRTB=DGRTAB+MAXUSR		;TABLE OF INDECES INTO OTHER TABLES, SORTED
 PRVTAB==ORDRTB+MAXUSR		;TABLE OF PRIVILEGE BITS
 TYPTAB==PRVTAB+MAXUSR		;TABLE OF USER TYPE BITS
 DGLTAB==TYPTAB+MAXUSR		;TABLE OF DIR GROUP LISTS
 UGLTAB==DGLTAB+NGPUSR*MAXUSR	;TABLE OF USER GROUP LISTS
ETEMPS==UGLTAB+NGPUSR*MAXUSR-1	;END OF ZEROED AREA

USERLH==500000			;LEFT HALF OF A USER NUMBER
SUBTTL	MACRO DEFINITIONS

; FUNCTION DESCRIPTOR BLOCK FOR COMND JSYS

DEFINE CMFDB (TYPE,FLAGS,DATA,HELP,DEFLT,LST)
<	..XX== < FLD(TYPE,CM%FNC) + FLAGS + LST >
  IFNB <HELP>,< ..XX== ..XX+CM%HPP >
  IFNB <DEFLT>,< ..XX== ..XX+CM%DPP >
	..XX
  IFNB <DATA>,<DATA>
  IFB <DATA>,<0>
  IFNB <HELP>, <POINT 7,[ASCIZ\HELP\] >
  IFB <HELP>,  <0>
  IFNB <DEFLT>, <POINT 7,DEFLT >
  IFB <DEFLT>, <0>
>

DEFINE TXT(TEXT) <POINT 7,[ASCIZ\TEXT\]>
;FLAGS

R.PASS==4		;PASSWORDS WANTED IF ONE
R.WIDE==10		;WIDE PAPER IF ONE
R.DGRP==20		;DIRECTORY GROUP LISTING IF ONE.
R.LIN2==100		;SECOND LINE NEEDED IN NARROW LISTING
R.DGM==200		;GROUP HAS A MEMBER
R.LPT==400		;USER ASKED FOR OUTPUT TO LPT VIA LPT CMD
R.ALPH==1000		;ALPHABETIC LISTING
R.NUM==2000		;NUMERIC LISTING
R.MINI==4000		;MINI LISTING
R.COLL==10000		;HAVE COLLECTED AND SORTED NAMES

;FLAGS TO BE CLEARED AFTER COMMAND COMPLETION

F.CLR==R.PASS+R.DGRP+R.LPT+R.ALPH+R.NUM+R.MINI

;FLAGS TO BE DEFAULTED ON

F.DEF==R.WIDE
;PROGRAM ENTRY VECTOR

ENTVEC:	JRST START		;STARTING LOCATION
	JRST START		;REENTER LOCATION
	VULIST			;VERSION NUMBER

ENTRY START

START:	RESET
	SETZ F,			;INIT FLAGS
	HRROI A,DIRBUF		;POINT TO DIR NAME
	MOVEM A,STRPTR		;INIT STRUCURE PNTR
RESTRT:	MOVE P,PDP
	TRZ F,F.CLR		;RESET FLAGS
	TRO F,F.DEF		;SET DEFAULT FLAGS
	SETOM OUTFIL
	MOVEI A,400000
	RPCAP
	TRNN B,600000		;WHEEL OR OPER?
	JRST NOCANDO
	MOVEM C,OLDCAP		;WILL RESTORE TO THESE CAPS ON EXIT
	MOVEM B,C
	EPCAP
	HRROI A,-1
	CLOSF
	 JSHLT			;UNEXPECTED ERROR
SUBTTL	COMMAND PARSER AND DISPATCH

	HRROI A,PROMPT		;GET POINTER TO PROMPT STRING
	MOVEM A,CMDBLK+.CMRTY	;PUT RE-TYPE PROMPT POINTER IN STATE BLOCK
	HRROI A,BUFFER		;GET POINTER TO INPUT TEXT BUFFER
	MOVEM A,CMDBLK+.CMPTR	;SAVE POINTER TO COMMAND STRING
	MOVEM A,CMDBLK+.CMBFP	;SAVE POINTER TO START-OF-BUFFER
	MOVE A,[.PRIIN,,.PRIOU] ;GET PRIMARY INPUT,, OUTPUT JFN'S
	MOVEM A,CMDBLK+.CMIOJ	;SAVE PRIMARY JFN'S
	MOVEI A,PARSE1		;GET RE-PARSE ADDRESS
	MOVEM A,CMDBLK+.CMFLG	;SAVE RE-PARSE ADDRESS
	SETZM CMDBLK+.CMINC	;INITIALIZE # OF CHARACTERS AFTER POINTER
	MOVEI A,BUFSIZ*NCHPW	;GET # OF CHARACTERS IN BUFFER AREA
	MOVEM A,CMDBLK+.CMCNT	;SAVE INITIAL # OF FREE CHARACTER POSITIONS
	HRROI A,ATMBFR		;GET POINTER TO ATOM BUFFER
	MOVEM A,CMDBLK+.CMABP	;SAVE POINTER TO LAST ATOM INPUT
	MOVEI A,ATMSIZ*NCHPW	;GET # OF CHARACTERS IN ATOM BUFFER
	MOVEM A,CMDBLK+.CMABC	;SAVE COUNT OF SPACE LEFT IN ATOM BUFFER
PARSE:
COMMAN:	MOVEI A,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI B,[CMFDB (.CMINI)] ;GET FUNCTION DESCRIPTOR BLOCK
	COMND			;INITIALIZE COMMAND SCANNER JSYS

PARSE1:	MOVE A,[GJFBLK,,GJFBLK+1] ;SET UP TO CLEAR GTJFN BLOCK
	SETZM GJFBLK		;CLEAR FIRST WORD OF BLOCK
	BLT A,GJFBLK+GJFSIZ-1	;CLEAR GTJFN BLOCK

	MOVEI A,GJFBLK		;GET ADDRESS OF GTJFN BLOCK
	MOVEM A,CMDBLK+.CMGJB	;STORE POINTER TO GTJFN BLOCK
	MOVEI A,CMDBLK		;GET POINTER TO COMMAND STATE BLOCK
	MOVEI B,[CMFDB (.CMKEY,,COMTB1)] ;GET FUNCTION BLOCK
	COMND			;DO INITIAL PARSE
	TXNN A,CM%NOP		;VALID COMMAND ENTERED ?
	JRST PARSE5		;YES, GO DISPATCH TO PROCESSING ROUTINE
	CALL TSTCOL		;GO SEE IF CRLF NEEDED
	TMSG <? ULIST: No such ULIST command as ">
	MOVE A,CMDBLK+.CMABP	;GET POINTER TO ATOM BUFFER
	PSOUT			;OUTPUT STRING ENTERED BY USER
	TMSG <"
>				;OUTPUT END-OF-MESSAGE
	JRST PARSE		;GO TRY TO GET A COMMAND AGAIN

PARSE5:	HRRZ A,(B)		;GET DISPATCH ADDRESS
	CALL (A)		;PERFORM REQUESTED FUNCTION
	JRST PARSE		;GO PARSE NEXT COMMAND
TYPCOM:	PSOUT
	JRST COMMAN

CRLFM:	ASCIZ /
/
NOLPT:	HRROI A,[ASCIZ /
? LPT: is not available. Use an OUTPUT command.
/]
	JRST TYPCOM
;USED TO SPECIFY STR OTHER THAN DEFAULT

.STR:	STKVAR <STRDV>
	SETZM	STRDEV		;TCO 1902
	TRZ	F,R.COLL	;TCO 1902
	HRROI A,DIRBUF		;INIT POINTER
	MOVEM A,STRPTR
	MOVEI A,CMDBLK		;COMND INFO
	MOVEI B,[CMFDB (.CMNOI,,<TXT(TO USE)>)]
	COMND
	MOVEI B,[CMFDB (.CMDEV,CM%SDH,,<STRUCTURE NAME>,<[ASCIZ "DSK"]>)]
	COMND
	TXNE A,CM%NOP		;LOSAGE?
	JRST [	TMSG <?Invalid structure name given
>
		RET]
	MOVEM B,STRDV		;SAVE DESIGNATOR A WHILE
	MOVEI B,[CMFDB (.CMCFM)]
	COMND
	TXNE A,CM%NOP
	CALLRET COMER1
	MOVE A,STRDV		;GET DEVICE DESIGNAORT
	DVCHR
	LDB A,[POINTR B,DV%TYP]
	CAIE A,.DVDSK		;GRNTEE DISK
	 JRST [	TMSG <?Invalid structure name given
>
		RET]
	MOVE B,STRDV		;DEVICE DESIGNATOR
	MOVE A,STRPTR		;GET PNTR
	DEVST			;GET STRING
	 JRST [	JSERR
		RET]
	MOVEI B,":"		;TERMINATE WITH COLON
	IDPB B,A		;...
	MOVEM A,STRPTR		;UPDATE PNTR
	RET			;GET NEXT COMMAND
.BEGIN:	MOVEI A,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI B,[CMFDB (.CMNOI,,<TXT(LISTING)>)]
	COMND			;PARSE NOISE FIELD
	MOVEI B,[CMFDB (.CMCFM)] ;GET CONFIRM FUNCTION BLOCK
	COMND			;WAIT FOR CONFIRMATION
	TXNE A,CM%NOP		;GARBAGE AT END-OF-COMMAND ?
	CALLRET COMER1		;YES, ISSUE ERROR MESSAGE
	SKIPL OUTFIL		;OUTPUT GET SPECIFIED?
	JRST GO1		;YES.
	MOVSI A,400001		;NO. TRY THE TTY OR LPT.
	HRROI B,[ASCIZ /TTY:USERS.TXT;P770000/]	;TTY IS THE DEFAULT UNLESS
	TRNE F,R.LPT		; PRINT COMMAND WAS TYPED.
	HRROI B,[ASCIZ /LPT:USERS.TXT;P770000/]	; ..
	GTJFN			; ..
	  JRST NOLPT		;NO SUCH BEAST
	HRRZM A,OUTFIL		;GOT ITS NAME
	MOVE B,[070000,,100000]	;OPEN FOR ASCII OUTPUT
	OPENF			; ..
	  JRST NOLPT		;NOT AVAIL?
GO1:	TRNN F,R.PASS		;PASSWORDS BEING LISTED?
	JRST NOPASS		;NO.
FINK:	MOVEI A,-1		;YES. DEFAULT DESIGNATOR FOR LOG TTY.
	MOVEM A,LOGDES		;STORE IT.
	MOVE A,['LOGDES']	;SEE IF THE GETAB IS THERE FOR LOG TTY
	SYSGT			; TRY IT
	TRNN B,-1		;IF TABLE NUMBER ZERO,
	JRST FINK1		;NOT THERE. USE DEFAULT
	MOVSI A,1		;OK. USE ERROR TTY (ENTRY 1 OF TABLE)
	HRR A,B			;PLUG IN TABLE NUMBER
	GETAB			;GET THE DESIGNATOR
	  JRST FINK1		;NOT THERE?
	CAIGE A,400000		;OR OTHER BAD DESIGNATOR
	JRST FINK1		;NO GOOD. USE DEFAULT
	MOVEM A,LOGDES		;OK. STORE IT.
FINK1:	MOVE A,LOGDES		;GET TTY TO TYPE FINK MSG ON
	DOBE			;WAIT FOR IT.
	HRROI B,[ASCIZ /
* * * ULIST with passwords by /]
	MOVEI C,0
	SOUT
	GJINF
	PUSH P,C
	MOVE B,A		;LOGIN DIRECTORY NUMBER
	HRROI A,COMWRD
	DIRST
	  SETZM COMWRD
	MOVE A,LOGDES
	HRROI B,COMWRD
	MOVEI C,0
	SOUT
	HRROI B,[ASCIZ / job /]
	SOUT
	POP P,B
	MOVEI C,12
	NOUT
	  JFCL
	HRROI B,CRLFM
	MOVEI C,0
	SOUT
NOPASS:	PUSHJ P,COLECT		;GET DATA IF NOT DONE ALREADY
	TRNN F,R.ALPH!R.MINI!R.NUM!R.DGRP	;ANY LISTING ASKED FOR?
	TRO F,R.NUM		;NO. DEFAULT IS NUMERIC
	TRNE F,R.DGRP		;PRODUCE LISTINGS REQUESTED
	PUSHJ P,DIRGRP		;DIRECTORY GROUPS LISTING ASKED FOR
	TRNE F,R.ALPH
	PUSHJ P,ALPHA
	TRNE F,R.NUM
	PUSHJ P,NUMRIC
	TRNE F,R.MINI
	PUSHJ P,MINI
DONE:	SETO A,
	CLOSF
	 JSHLT			;UNEXPECTED FATAL ERROR
	SETOM OUTFIL		;NO OUTPUT FILE OPEN
	MOVEI A,400000
	MOVE B,OLDCAP		;RESET TO CAPABILITIES
	MOVE C,B		;SET ON ENTRY
	EPCAP			; ..
	JRST RESTRT		;RESTART IN CASE WANT MORE.

.HELP:	MOVEI A,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI B,[CMFDB (.CMCFM)] ;GET FUNCTION BLOCK FOR CONFIRM
	COMND			;WAIT FOR END-OF-COMMAND
	TXNE A,CM%NOP		;GARBAGE AT END-OF-COMMAND ?
	CALLRET COMER1		;YES, ISSUE ERROR MESSAGE
	HRROI A,HLPTXT
	PSOUT
	JRST PARSE		;GO DO NEXT COMMAND

NUMRIC:	SETZM USERNO		;NUMERIC LISTING. START AT USER 0
	SETZM LINENO		;AND START OF PAPER
	SETZM PAGENO		; ..
NUMERL:	PUSHJ P,DUMP
	 JFCL
	AOS A,USERNO
	CAIGE A,MAXUSR
	JRST NUMERL
	PUSHJ P,FORM		;END THE PAGE
	POPJ P,0		;RETURN FROM NUMERIC.
;COMMAND TABLES

DEFINE COMS <
CC (<ALPHABETIC>,.ALPHA)
CC (<BEGIN>,.BEGIN)
CC (<DIRECTORY>,.DIR)
CC (<EXIT>,.EXIT)
CC (<HELP>,.HELP)
CC (<INCLUDE>,.INCLU)
CC (<MINI>,.MINI)
CC (<NARROW>,.NARRO)
CC (<NUMERIC>,.NUMER)
CC (<OMIT>,.OMIT)
CC (<OUTPUT>,.OUTPT)
CC (<PRINT>,.PRINT)
CC (<STRUCTURE>,<.STR>)
CC (<WIDE>,.WIDE)
>

COMTB1:	NCOMS-1 ,, COMFRE
	DEFINE CC (WORD,TAG,HELP)<
	[ASCIZ /WORD/],,TAG>

	COMS
NCOMS==.-COMTB1

FRECOM:	BLOCK COMFRE-NCOMS
.NUMER:	MOVEI A,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI B,[CMFDB (.CMNOI,,<TXT(LIST OF USERS)>)]
	COMND			;PARSE NOISE FIELD
	MOVEI B,[CMFDB (.CMCFM)] ;GET FUNCTION BLOCK FOR CONFIRMATION
	COMND			;WAIT FOR END-OF-COMMAND
	TXNE A,CM%NOP		;GARBAGE AT END-OF-COMMAND ?
	CALLRET COMER1		;YES, ISSUE ERROR MESSAGE
	TRO F,R.NUM
	JRST PARSE		;GO GET NEXT COMMAND
.ALPHA:	MOVEI A,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI B,[CMFDB (.CMNOI,,<TXT(LIST OF USERS)>)]
	COMND			;PARSE NOISE FIELD
	MOVEI B,[CMFDB (.CMCFM)] ;GET FUNCTION BLOCK FOR CONFIRMATION
	COMND			;WAIT FOR END-OF-COMMAND
	TXNE A,CM%NOP		;GARBAGE AT END-OF-COMMAND ?
	CALLRET COMER1		;YES, ISSUE ERROR MESSAGE
	TRO F,R.ALPH
	JRST PARSE		;GO GET NEXT COMMAND


.DIR:	MOVEI A,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI B,[CMFDB (.CMNOI,,<TXT(GROUP LISTING)>)]
	COMND			;PARSE NOISE FIELD
	MOVEI B,[CMFDB (.CMCFM)] ;GET FUNCTION BLOCK FOR CONFIRMATION
	COMND			;WAIT FOR END-OF-COMMAND
	TXNE A,CM%NOP		;GARBAGE AT END-OF-COMMAND ?
	CALLRET COMER1		;YES, ISSUE ERROR MESSAGE
	TRO F,R.DGRP
	JRST PARSE

.NARRO:	TRZA F,R.WIDE
.WIDE:	TRO F,R.WIDE
	MOVEI A,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI B,[CMFDB (.CMNOI,,<TXT(PAPER FORMAT)>)]
	COMND			;PARSE NOISE FIELD
	MOVEI B,[CMFDB (.CMCFM)] ;GET FUNCTION BLOCK FOR CONFIRMATION
	COMND			;WAIT FOR END-OF-COMMAND
	TXNE A,CM%NOP		;GARBAGE AT END-OF-COMMAND ?
	CALLRET COMER1		;YES, ISSUE ERROR MESSAGE
	JRST PARSE

.INCLU:	TRO F,R.PASS
	MOVEI A,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI B,[CMFDB (.CMNOI,,<TXT(PASSWORDS IN LISTING)>)]
	COMND			;PARSE NOISE
	MOVEI B,[CMFDB (.CMCFM)] ;GET FUNCTION BLOCK FOR CONFIRM
	COMND			;CONFIRM COMMAND
	TXNE A,CM%NOP		;GARBAGE AT END-OF-COMMAND ?
	CALLRET COMER1		;YES, ISSUE ERROR MESSAGE
	JRST PARSE		;GO PARSE NEXT COMMAND
.OMIT:	TRZ F,R.PASS
	MOVEI A,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI B,[CMFDB (.CMNOI,,<TXT(PASSWORDS FROM LISTING)>)]
	COMND			;PARSE NOISE
	MOVEI B,[CMFDB (.CMCFM)] ;GET FUNCTION BLOCK FOR CONFIRM
	COMND			;CONFIRM COMMAND
	TXNE A,CM%NOP		;GARBAGE AT END-OF-COMMAND ?
	CALLRET COMER1		;YES, ISSUE ERROR MESSAGE
	JRST PARSE

.MINI:	MOVEI A,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI B,[CMFDB (.CMNOI,,<TXT(LISTING FORMAT)>)]
	COMND			;PARSE NOISE
	MOVEI B,[CMFDB (.CMCFM)] ;GET FUNCTION BLOCK FOR END-OF-COMMAND
	COMND			;CONFIRM
	TXNE A,CM%NOP		;GARBAGE AT END-OF-COMMAND ?
	CALLRET COMER1		;YES, ISSUE ERROR MESSAGE
	TRO F,R.MINI
	JRST PARSE		;GO PARSE NEXT COMMAND
.PRINT:	MOVEI A,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI B,[CMFDB (.CMNOI,,<TXT(LISTING ON PRINTER)>)]
	COMND			;PARSE NOISE FIELD
	MOVEI B,[CMFDB (.CMCFM)] ;GET CONFIRM FUNCTION BLOCK
	COMND			;PARSE END-OF-COMMAND
	TXNE A,CM%NOP		;GARBAGE AT END-OF-COMMAND ?
	CALLRET COMER1		;YES, ISSUE ERROR MESSAGE
	TRO F,R.LPT		;OUTPUT TO LINEPRINTER
	JRST COMMAN
.EXIT:	MOVEI A,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI B,[CMFDB (.CMNOI,,<TXT(TO MONITOR)>)]
	COMND			;PARSE NOISE FIELD
	MOVEI B,[CMFDB (.CMCFM)] ;GET CONFIRM FUNCTION BLOCK
	COMND			;WAIT FOR END-OF-COMMAND
	TXNE A,CM%NOP		;GARBAGE AT END-OF-COMMAND ?
	CALLRET COMER1		;YES, ISSUE ERROR MESSAGE
	HALTF			;TO THE EXEC
	JRST RESTRT		;IN CASE OF CONTINUE
ALPHA:	SETZM LINENO
	SETZM PAGENO		;CLEAR FORMAT COUNTERS
	MOVEI A,DUMP		;STANDARD OUTPUT ROUTINE
	MOVEM A,DMPADR		; FOR DISPATCH
	PUSHJ P,ALFDMP		;ALPHABETIZE AND THEN DUMP
	PUSHJ P,FORM		;END THE PAGE
	POPJ P,0		;END OF ALPHA ROUTINE
;MINI LISTING MAKER

MINI:	MOVEI A,NARCOL		;COLUMNS IF NARROW
	TRNE F,R.WIDE		;WIDE PAPER?
	MOVEI A,WIDCOL		;YES.
	MOVEM A,MAXCOL
	MOVEI A,1		;START AT USER NUMBER 1
	MOVEM A,PAGBAS
MINI04:	SETZM LINENO
	MOVE A,OUTFIL		;JFN TO USE
	HRROI B,[ASCIZ "    List of structure: "]
	MOVEI C,0
	SOUT
	MOVE B,STRDEV		;DEVICE DESIGNATOR
	DEVST			;TELL WHICH STR
	 JSERR
	MOVEI B,11
	BOUT			;TAB OVER
	SETO B,			;CURRENT DATE/TIME
	MOVSI C,322401
	ODTIM			;TO LISTING
	HRROI B,CRLFM
	MOVEI C,0
	SOUT
	HRROI B,CRLFM		;LEAVE A BLANK LINE
	SOUT
MINI03:	SETZM COLUMN
	SETZM LINPOS		;CLEAR LINE POSITION
MINI02:	MOVEI A,PAGLEN		;COMPUTE CURRENT USER NUMBER
	IMUL A,COLUMN
	ADD A,LINENO
	ADD A,PAGBAS
	MOVEM A,USERNO
	CAMLE A,TOPUSR		;OVER THE TOP?
	JRST MINEOL		;YES
	MOVE A,OUTFIL		;NO. OUTPUT THE NUMBER
	HRRZ B,USERNO
	MOVX C,NO%LFL+<FLD (5,NO%COL)>+8 ;IN 5 COL OCTAL
	NOUT
	  JFCL
	MOVEI B,40		;SPACE ONE
	BOUT
	MOVEI B,6		;ACCOUNT FOR SPACE USED BY NUMBER
	ADDM B,LINPOS
	HRRZ B,USERNO		;GET NAME STRING
	MOVE D,NAMPTR(B)
	HRLI D,(<POINT 7,0>)	;POINTER TO NAME
MINI06:	ILDB B,D		;GET A CHAR OF NAME
	JUMPE B,MINI07		;QUITS ON NULL
	BOUT			;OUTPUT CHAR
	AOS LINPOS		;COUNT LINE POSITION
	JRST MINI06		;LOOP FOR ALL CHARS OF NAME

MINI07:	MOVE C,COLUMN		;CURRENT COLUMN NUMBER
	ADDI C,1		;COMPUTE DISTANCE TO NEXT COLUMN START
	IMULI C,COLWID
	SUB C,LINPOS
MINI05:	MOVEI B,40
	BOUT
	AOS LINPOS
	SOJG C,MINI05		;FILL COLUMN WITH SPACES
	; ..
MINI01:	AOS A,COLUMN		;FILLED COLUMN?
	CAMGE A,MAXCOL		; ..
	JRST MINI02		;NO
MINEOL:	HRROI B,CRLFM		;YES. TERMINATE THE LINE
	MOVE A,OUTFIL
	MOVEI C,0
	SOUT
	AOS LINENO		;COUNT LINES ON PAGE
	MOVE A,LINENO		;SEE IF THROUGH
	ADD A,PAGBAS		;NUMBER WE WOULD NOW BE UP TO
	CAMLE A,TOPUSR		;TOO HIGH?
	JRST MINEND		;YES.
	MOVE A,LINENO		;NO. SEE IF PAGE FULL
	CAIGE A,PAGLEN		; ..
	JRST MINI03		;NO.
MINEND:	PUSHJ P,FORM		;YES. FORMFEED.
	MOVEI A,PAGLEN
	IMUL A,MAXCOL
	ADDB A,PAGBAS
	CAMG A,TOPUSR
	JRST MINI04
	POPJ P,0
;ROUTINE TO DUMP ONE DIRECTORY
; CURSTR/ CURRENT STRUCTURE UNIQUE CODE
; USERNO/ DIRECTORY NUMBER

DUMP:	TRZ F,R.LIN2		;ASSUME NO SECOND LINE ON NARROW FORM
	SKIPLE LINENO
	JRST S1
	AOS PAGENO
	MOVE A,OUTFIL
	MOVEI B,C.FF
	BOUT
	MOVEI A,PAGLEN-3	;LEAVE OFF HEADING IN COUNT
	MOVEM A,LINENO		;INITIALIZE PAGE LENGTH COUNTDOWN
	HRROI B,[ASCIZ /Name,Password,Account/]	;IF PASSWORD LISTED
	TRNN F,R.PASS
	HRROI B,[ASCIZ /Name,Account/]	;IF NO PASSWORD.
	MOVE A,OUTFIL
	MOVEI C,0
	SOUT
	HRROI B,[ASCIZ /	(Structure: /]
	SOUT
	MOVE B,STRDEV
	DEVST
	 JFCL
	HRROI B,[ASCIZ /)	/]
	MOVEI C,0
	SOUT
	SETO B,			;CURRENT DATE
	MOVSI C,200401
	ODTIM			;DATE STAMP THE LISTING
	HRROI B,[ASCIZ /	Page /]
	MOVEI C,0
	SOUT
	MOVE B,PAGENO		;LIST PAGE NUMBER
	MOVEI C,^D10		;IN DECIMAL
	NOUT
	  JFCL
	PUSHJ P,LCRLF		;EOL (LOADS A, CLEARS C.)
	HRROI B,[ASCIZ /  Dir-#   Privileges  Login-Quota Logout-Quota User-Groups  Dir-Groups /]
	SOUT			;OUTPUT FIRST 5 HEADINGS
	TRNN F,R.WIDE		;IF NARROW FORMAT,
	PUSHJ P,LCRLF		;OUTPUT A LINEFEED HERE
	MOVEI B,"("		;IF NARROW
	TRNE F,R.WIDE
	MOVEI B," "		;IF WIDE
	BOUT
	HRROI B,[ASCIZ /   Modes     Def-File-Pro   Dir-Prot   Def-File-Ret /]
	SOUT
	MOVEI B,")"
	TRNN F,R.WIDE
	BOUT
	PUSHJ P,LCRLF
	PUSHJ P,LCRLF
S1:	HRRZ A,USERNO		;GET DIR NO.
	SKIPN B,NAMPTR(A)	;SEE IF ANY
	RET			;NO NAME - SKIP UT
	TLO B,-1		;FORM PNTR
	MOVE A,OUTFIL
	MOVEI C,0
	SOUT
	MOVE A,[UGROUP,,UGROUP+1];GET SOURCE, DESTINATION
	SETZM UGROUP		;CLEAR FIRST WORD OF BLOCK
	BLT A,UGROUP+GRPSIZ-1	;CLEAR REMAINDER OF USER GROUP BLOCK
	MOVE A,[DGROUP,,DGROUP+1] ;GET SOURCE,, DESTINATION
	SETZM DGROUP		;CLEAR FIRST WORD OF BLOCK
	BLT A,DGROUP+GRPSIZ-1	;CLEAR REMAINDER OF DIR GROUP BLOCK
	MOVEI A,UGROUP		;GET ADR OF USER GROUP BLOCK
	MOVEM A,STRBF+.CDUGP	;STORE ADR OF BLOCK FOR GTDIR
	MOVEI A,DGROUP		;GET ADR OF DIR GROUP BLOCK
	MOVEM A,STRBF+.CDDGP	;STORE ADR OF BLOCK FOR GTDIR
	MOVEI A,GRPSIZ		;GET SIZE OF USER AND DIR GROUP BLOCKS
	MOVEM A,UGROUP		;STORE SIZE IN BLOCK
	MOVEM A,DGROUP		;STORE SIZE IN DIR GROUP BLOCK
	HRRI A,ACTBUF		;ADDRESS OF DEFAULT ACCOUNT BUFFER
	HRLI A,(<POINT 7,>)	;MAKE IT A BYTE POINTER
	MOVEM A,STRBF+.CDDAC	;STORE IN BLOCK FOR GTDIR
	HRRZ A,USERNO
	HRL A,CURSTR		;STR #
	MOVEI C,20
	MOVEM C,STRBF+.CDLEN	;COUNT 20 WORDS
	MOVEI B,STRBF
	HRROI C,STRBF+STRPSW
	GTDIR
	 ERJMP CPOPJ
	SETZ C,
	MOVE A,OUTFIL
	TRNN F,R.PASS		;WANT PASSWORDS LISTED?
	JRST S11		;NO.
	MOVEI B,","
	BOUT
	HRROI B,STRBF+STRPSW
	SOUT			;OUTPUT THE PASSWORD
S11:	HRRI A,ACTBUF		;PLACE WHERE DEFAULT ACCT WAS PUT
	HRLI A,(<POINT 7,>)	;MAKE IT A BYTE POINTER
	ILDB B,A		;GET FIRST CHARACTER OF ACCT
	JUMPE B,S12		;IS THERE A DEFAULT ACCOUNT?
	MOVEI B,","		;YES, PRINT IT OUT
	MOVE A,OUTFIL
	BOUT
	HRROI B,ACTBUF
	SETZ C,			;STOP ON NULL
	SOUT			;PRINT THE ACCOUNT
S12:	TRNE F,R.WIDE		;WIDE PAPER?
	JRST S11A		;YES. NO EXTRA FIDDLING
	MOVSI C,-NORDR2		;NARROW. SEE IF SECOND LINE NEEDED
	ADD C,[NORDR1,,NORDR1]	;POINT TO SECOND LINE DATA
LN2QL:	MOVE A,ORDERT(C)
	MOVE A,STRBF(A)		;GET USER DIR DATUM
	CAME A,DEFLTT(C)	;DIFFERENT FROM DEFAULT?
	TROA F,R.LIN2		;YES. NEED SECOND LINE.
	AOBJN C,LN2QL		;SEARCH FOR ANY DIFFERENCES.
S11A:	PUSHJ P,LCRLF
	MOVSI E,-NORDR2		;MAX NUMBER OF OCTAL DATA TO OUTPUT
	MOVEI B," "
	BOUT
	BOUT
S3:	MOVE A,OUTFIL		;WHERE TO WRITE
	MOVE C,ORDERT(E)	;GET THE DRIVING INFO
	HRRZ B,C		;GET OFFSET TO DATA
	CAIN B,.CDUGP		;DOING USER GROUPS ?
	JRST S3A		;YES, GO OUTPUT THE GROUPS
	CAIN B,.CDDGP		;  OR DIR GROUPS ?
	JRST S3B		;YES, GO OUTPUT THE GROUPS
	HRRI C,10		;OCTAL PRINT RADIX
	CAIE B,.CDLIQ		;QUOTAS SHOULD BE
	CAIN B,.CDLOQ		;PRINTED IN DECIMAL
	HRRI C,^D10
	MOVE B,STRBF(B)		;NO, GET THE DATA
	SKIPN B			;IS DATUM ZERO?
	TLZ C,(1B3)		;YES, NO LEADING ZEROES
	NOUT			;OUTPUT THE NUMBER
	  JFCL
	JRST S3B		;GO SEE IF WIDE OR NARROW LISTING
S3A:	CALL GRPOUT		;GO OUTPUT THE GROUP
S3B:	TRNE F,R.WIDE		;WIDE OR NARROW?
	JRST NOBRK		;WIDE. PROCEED
	MOVEI B,0(E)		;NARROW. END OF LINE 1 YET?
	CAIE B,NORDR1-1		; ..
	JRST NOBRK		;NO
	TRNN F,R.LIN2		;YES. SECOND LINE NEEDED?
	JRST NOLIN2		;NO. DONE THIS USER.
	PUSHJ P,LCRLF		;YES. PRINT AND COUNT EOL
	MOVEI B,"("		;FLAG SECOND LINE WITH PARENS
	JRST S3C
NOBRK:	MOVEI B," "
S3C:	BOUT
	AOBJN E,S3
	MOVEI B,")"		;CLOSE OFF LINE 2 IF NEEDED
	TRZE F,R.LIN2		; ..
	BOUT			; ..
NOLIN2:	PUSHJ P,LCRLF
CPOPJ1:	AOS 0(P)
CPOPJ:	POPJ P,0
; ROUTINE TO OUTPUT THE USER AND DIRECTORY GROUPS
;
;		CALL GRPOUT
; RETURNS +1	ALWAYS


GRPOUT:	STKVAR <UGRADR,DGRADR>;	;ALLOCATE TEMPORARY STORAGE
	SETZM UGRADR		;INITIALIZE NEXT ADR
	SETZM DGRADR		;INITIALIZE NEXT DIR GROUP ADR
	MOVE T1,STRBF+.CDUGP	;GET ADR OF USER GROUP BLOCK
	HRRZ T2,(T1)		;GET SIZE OF BLOCK
	CAIG T2,1		;AT LEAST ONE GROUP TO DO ?
	JRST GRPOU0		;NO, GO CHECK DIR GROUPS
	ADDI T1,1		;POINT TO FIRST GROUP #
	MOVEM T1,UGRADR		;SAVE ADR OF FIRST USER GROUP
GRPOU0:	MOVE T1,STRBF+.CDDGP	;GET ADR OF DIR GROUP BLOCK
	HRRZ T2,(T1)		;GET SIZE OF DIR GROUP BLOCK
	CAIG T2,1		;AT LEAST ONE GROUP TO DO ?
	JRST GRPOU1		;NO, DO NOT STORE ADR
	ADDI T1,1		;POINT TO FIRST GROUP #
	MOVEM T1,DGRADR		;SAVE DIR GROUP # ADDRESS

GRPOU1:	MOVE T1,UGRADR		;GET ADR OF USER GROUP #
	JUMPE T1,[ HRROI B,[ASCIZ/            /]
		   SETZM C
		   SOUT
		   JRST GRPOU2 ] ;GO SEE IF ANY DIR GROUPS REMAIN
	CALL GRPLIN		;OUTPUT A LINE OF USER GROUPS
	 SETZM T1		;INDICATE ALL USER GROUPS OUTPUT
	MOVEM T1,UGRADR		;SAVE ADR OF USER GROUPS
	MOVEI B," "		;GET A SPACE
	BOUT			;OUTPUT THE SPACE
GRPOU2:	MOVE T1,DGRADR		;GET ADR OF DIR GROUP #
	JUMPE T1,[ HRROI B,[ASCIZ/           /]
		   SETZM C
		   SOUT
		   JRST GRPOU3]	;IF NO DIR GROUPS LEFT, SEE IF DONE
	CALL GRPLIN		;GO OUTPUT LINE OF DIR GROUP #'S
	 SETZM T1		;INDICATE ALL DIR GROUPS OUTPUT
	MOVEM T1,DGRADR		;SAVE ADR OF NEXT DIR GROUP #

GRPOU3:	SKIPN UGRADR		;MORE USER GROUPS TO DO ?
	SKIPE DGRADR		;MORE DIRECTORY GROUPS TO DO ?
	JRST GRPOU4		;YES, GO OUTPUT A CRLF AND SPACING
	RET			;RETURN TOW WHENCE WE CAME ...
GRPOU4:	CALL LCRLF		;GO TO NEXT LINE
	MOVE A,OUTFIL
	HRROI B,[ASCIZ/					       /]
	SETZM C			;TERMINATE ON NULL
	SOUT			;OUTPUT THE CRLF AND SPACING
	JRST GRPOU1		;GO OUTPUT NEXT LINE OF USER AND DIR GROUPS
; ROUTINE TO OUTPUT ONE LINE OF A GROUP LIST.  GROUPS ARE OUTPUT
;  UNTIL THE END OF THE GROUP LIST, OR UNTIL THE NEXT GROUP WOULD
;  OVERFLOW 12 COLUMNS FROM THE FIRST GROUP OUTPUT ON THE LINE.
;
; ACCEPTS IN T1/	ADR OF FIRST GROUP TO OUTPUT
;			CALL GRPLIN
;			  END-OF-LIST
;			MORE GROUPS TO OUTPUT
; CLOBBERS T2, T3
; RETURNS ADR OF LAST GROUP # OUTPUT IN T1

GRPLIN:	STKVAR <COLS>;		;ALLOCATE TEMP STORAGE
	SETZM COLS		;INITIALIZE COLUMN COUNTER
	MOVE A,[GRPBUF,,GRPBUF+1] ;GET SOURCE,,DESTINATION
	SETZM GRPBUF		;CLEAR FIRST WORD OF BUFFER
	BLT A,GRPBUF+GBFSIZ-1	;CLEAR REMAINDER OF BUFFER
	HRROI A,GRPBUF		;GET POINTER TO GROUP BUFFER
	MOVEI C,^D10		;USE DECIMAL RADIX
GRPLN1:	SKIPN B,(T1)		;MORE GROUPS ?
	JRST GRPLN3		;NO, OUTPUT BUFFER AND RETURN
	MOVE T2,B		;COPY GROUP #
	SETZM D			;INITIALIZE COLUMN COUNTER
GRPLN2:	IDIVI T2,^D10		;COMPUTE # OF DIGITS
	ADDI D,1		;INCREMENT # OF COLUMNS IN #
	JUMPN T2,GRPLN2		;SEE IF MORE COLUMNS
	ADD D,COLS		;COMPUTE TOTAL # OF COLUMNS
	CAILE D,^D10		;ENOUGH COLUMNS LEFT ?
	JRST GRPLN4		;NO, OUTPUT BUFFER AND RETURN
	MOVEM D,COLS		;YES, UPDATE COLUMN TOTAL
	NOUT			;OUTPUT THE GROUP NUMBER
	 JSERR			;UNEXPECTED ERROR
	MOVEI B,","		;GET DELIMITER
	SKIPE 1(T1)		;IS THERE ANOTHER GROUP TO OUTPUT ?
	BOUT			;YES, OUTPUT DELIMITER
	SKIPE 1(T1)		;ANOTHER GROUP TO OUTPUT ?
	AOS COLS		;YES, INCREMENT COLUMN COUNT FOR ","
	AOJA T1,GRPLN1		;GO DO NEXT GROUP NUMBER

; HERE WHEN BUFFER FULL

GRPLN3:	TDZA D,D		;MARK THAT NO GROUPS ARE LEFT
GRPLN4:	SETOM D			;MARK THAT GROUPS ARE LEFT
	MOVE A,OUTFIL		;GET OUTPUT JFN
	MOVEI B," "		;GET A SPACE
	MOVEI C,^D11		;GET # OF COLUMNS TO OUTPUT
	SUB C,COLS		;COMPUTE # OF COLUMNS LEFT
	JUMPE C,GRPLN6		;NONE LEFT, OUTPUT GROUPS
GRPLN5:	BOUT			;OUTPUT A SPACE
	SOJG C,GRPLN5		;GO OUTPUT REMAINING SPACES
GRPLN6:	HRROI B,GRPBUF		;GET POINTER TO GROUPS
	SETZM C			;TERMINATE ON NULL
	SOUT			;OUTPUT THE GROUPS
	JUMPE D,R		;RETURN IF NO MORE GROUPS
	RETSKP			;SKIP RETURN IF GROUPS LEFT
;SUBR TO COLLECT THE NAMES AND DIRECTORY GROUP INFO

COLECT:	STKVAR <LSTDGP,LSTUGP,DIRJFN>;	;ALLOCATE TEMPORARY STORAGE
	TRNE F,R.COLL		;ALREADY GOT DATA?
	RET			;YES. RETURN
	MOVE A,[GRPLST,,GRPLST+1] ;GET SOURCE,,DESTINATION
	SETZM GRPLST		;CLEAR FIRST WORD OF MASTER GROUP LIST
	BLT A,GRPLST+GRPLSZ-1	;CLEAR REMAINDER OF MASTER GROUP LIST
	MOVEI A,DGLTAB		;GET ADR OF DIR GROUP LIST TABLE
	MOVEM A,LSTDGP		;INITIALIZE NEXT FREE CELL IN TABLE
	MOVEI A,UGLTAB		;GET ADR OF USER GROUP LIST TABLE
	MOVEM A,LSTUGP		;INITIALIZE NEXT FREE CELL IN TABLE
	SETZM TOPUSR		;CLEAR HIGHEST USER NUMBER
	MOVE A,STRPTR		;GET POINTER TO STR NAME
	HRROI B,[ASCIZ /<*>/]	;T2/ POINTER TO SOURCE
	SETZ C,			;T3/ STOP ON NULL
	SOUT			;APPEND <*> TO STR:
	MOVX A,RC%EMO!RC%AWL	;T2/ EXACT MATCH, ALLOW WILD CARDS
	HRROI B,DIRBUF		;POINT TO STR:<*>
	RCDIR			;GET FIRST DIRECTORY
	 ERJMP [ TMSG <
?Failed to get first directory>
		JSERR
		RET]
	TXNE A,RC%NOM!RC%AMB!RC%NMD ;ANY ERRORS?
	JRST [	TMSG <
?Failed to get first directory>
		RET]
	MOVEM C,USERNO		;NO. SAVE DIRECTORY NUMBER
	HRROI A,STRBF		;A/ POINTER TO DESTINATION
	MOVE B,USERNO		;B/ DIRECTORY NUMBER
	DIRST			;WRITE DIRECTORY NAME IN STRBF
	 JFCL
	SETZM CURSTR		;NONE YET
	SETZ NC,		;START USER SCAN AT 0, NO GRPS SEEN
	SETZM TEMPS		;ACQUIRE AND CLEAR FRESH STORAGE
	MOVE A,[TEMPS,,TEMPS+1]
	BLT A,ETEMPS		; ..
	MOVEI E,NAMPAG		;E HOLDS CURRENT STRING FREE ADDR
	MOVE C,USERNO		;C/ DIRECTORY NUMBER
	SKIPN STRDEV		;SET STR YET?
	CALL SETSTR		;NO - SET IT UP NOW

;LOOP THROUGH ALL DIRECTORIES, GATHERING DATA

COLL1:	HRRZ B,USERNO		;DIR # RHS ONLY
	CAMLE B,TOPUSR
	HRRZM B,TOPUSR		;SAVE HIGHEST SO FAR
	MOVE A,E		;POINT TO NEXT AVAILABLE POSITION IN NAMPAG
	HRLI A,(<POINT 7,0>)
	MOVE B,USERNO		;B/ DIRECTORY NUMBER
	DIRST			;WRITE DIRECTORY NAME
	 JFCL
	HRRZ B,USERNO		;GET DIRECTORY NUMBER
	MOVEM E,NAMPTR(B)	;STORE ADDRESS OF THIS DIRECTORY'S NAME
	IBP A			;ADVANCE OVER NULL
	MOVEI E,1(A)		;AND NEXT AVAILABLE CELL TO E
	MOVE A,LSTUGP		;GET ADR OF USER GROUP LIST
	MOVEM A,STRBF+.CDUGP	;SET UP TO GET USER GROUPS
	MOVEI C,-UGLTAB(A)	;COMPUTE # OF WORDS USED ALREADY
	MOVEI B,NGPUSR*MAXUSR	;GET # OF WORDS IN TABLE
	SUB B,C			;COMPUTE # OF WORDS LEFT
	MOVEM B,(A)		;STORE # OF WORDS IN LIST
	MOVE A,LSTDGP		;GET ADR OF USER GROUP LIST
	MOVEM A,STRBF+.CDDGP	;SET UP TO GET USER GROUPS
	MOVEI C,-DGLTAB(A)	;COMPUTE # OF WORDS USED ALREADY
	MOVEI B,NGPUSR*MAXUSR	;GET # OF WORDS IN TABLE
	SUB B,C			;COMPUTE # OF WORDS LEFT
	MOVEM B,(A)		;STORE # OF WORDS IN LIST
	SETZM STRBF+.CDLEN	;ZERO COUNT WORD
	MOVE A,USERNO		;NOW GET THE DIRECTORY DATA
	MOVEI B,STRBF		;WHERE TO HOLD IT FOR A MOMENT
	HRROI C,STRBF+STRPSW	;PLACE FOR PASSWORD (NOT NEEDED)
	GTDIR
	 ERJMP [TMSG <?GTDIR Failed for - >
		HRRZ B,USERNO
		HRRO A,NAMPTR(B)
		PSOUT
		JSERR
		JRST COLN1]	;REPORT FAILURE AND PROCEED
	MOVE B,STRBF+.CDUGP		;USER GROUP POINTER
	MOVEM B,UGRTAB(A)	;STORE IT
	MOVE B,(B)		;GET # OF GROUPS IN LIST
	ADDM B,LSTUGP		;COMPUTE NEXT FREE CELL IN TABLE
	MOVE B,STRBF+.CDDGP		;DIR GROUP POINTER
	MOVEM B,DGRTAB(A)	;STORE THEM TOO
	MOVE B,(B)		;GET # OF GROUPS IN LIST
	ADDM B,LSTDGP		;COMPUTE NEXT FREE CELL IN TABLE
	MOVE A,STRBF+.CDUGP	;GET ADR OF USR GROUP LIST
	CALL MSKGRP		;GO ADD TO MASTER GROUP LIST
	MOVE A,STRBF+.CDDGP	;GET ADR OF DIR GROUP LIST
	CALL MSKGRP		;GO ADD TO MASTER GROUP LIST
	MOVE A,USERNO		;GET USER NUMBER AGAIN
	MOVE B,STRBF+.CDPRV		;WHEEL, OPER, CONFI BITS
	MOVEM B,PRVTAB(A)	;STORE
	MOVE B,STRBF+.CDMOD		;FILES ONLY, ETC.
	MOVEM B,TYPTAB(A)	; ..

;HERE TO STEP TO NEXT DIRECTORY

COLN1:	MOVX A,RC%EMO!RC%AWL!RC%STP ;A/ NO RECOGNTION, ALLOW WILD CARDS, STEP
	HRROI B,DIRBUF		;B/ POINT TO STR:<*>
	MOVE C,USERNO		;C/ DIRECTORY NUMBER FROM LAST CALL
	RCDIR			;GET NEXT DIRECTORY NUMBER
	 ERJMP [ TMSG <
?Failed to get next directory>
		JSERR
		JRST COLN2]
	TXNE A,RC%NOM!RC%AMB	;ANY ERRORS?
	JRST [	TMSG <
?Failed to get next directory>
		JRST COLN2]
	TXNE A,RC%NMD		;NO MORE DIRECTORIES?
	JRST COLN2		;YES. DONE
	MOVEM C,USERNO		;GOT ONE. SAVE DIRECTORY NUMBER
	JRST COLL1		;GO GET THIS DIRECTORY'S DATA

;HERE WHEN ALL DIRECTORIES HAVE BEEN LOOKED AT

COLN2:	PUSHJ P,SORT		;MAKE THE SORTED INDEX POINTERS
	PUSHJ P,GDFLT		;GET DIRECTORY DEFAULTS
	TRO F,R.COLL		;NOW HAVE ALL THE DATA
	TMSG < Done

>
	RET			;ALL DONE
;ROUTINE TO SET DEFAULT DIR VALUES

GDFLT:	MOVEI A,0		;GET DIR #0
	SETZM STRBF+.CDLEN	;ZERO COUNT WORD
	MOVEI B,STRBF		;TEMP BUFFER
	HRROI C,STRBF+STRPSW	;TEMP 
	SETZM STRBF+.CDUGP	;NO DEFAULTS
	SETZM STRBF+.CDDGP
	GTDIR
	 ERJMP [JSHLT]		;FATAL ERROR
	MOVSI C,-NORDR2		;INIT COUNTER
	AOBJN C,.+1		;SKIP FIRST ITEM (DIRNUM)
GDFLT1:	HRRZ B,ORDERT(C)	;OFFSET INTO TABLE
	MOVE A,STRBF(B)		;GET ITEM
	MOVEM A,DEFLTT(C)	;STORE INTO DEFAULT TABLE
	AOBJN C,GDFLT1		;LOOP TILL DONE
	RET			;RETURN

;ROUTINE TO SETUP CURRENT STR
; C/ DIRECTORY NUMBER
; STRBF/ DIRECTORY NAME STRING

SETSTR:	HLRZM C,CURSTR		;REMEMBER STR UNIQUE CODE
	HRROI A,STRBF		;POINT TO NAME STRING
	STDEV			;GET DEVICE DESIGNATOR
	 JSHLT
	MOVEM B,STRDEV		;SAVE IT
	RET			;RETURN
; ROUTINE TO TURN ON THE BITS IN THE MASTER GROUP LIST CORRESPONDING
; TO THE GROUPS IN A GROUP LIST.
;
; ACCEPTS IN A/	ADDRESS OF GROUP LIST
;
;		CALL MSKGRP
; RETURNS +1	ALWAYS
;
; CLOBBERS A,B,C, T1

MSKGRP:	JUMPE A,R		;RETURN IF NO LIST GIVEN
	ADDI A,1		;POINT TO FIRST GROUP IN LIST

MSKGP1:	MOVE B,(A)		;GET A GROUP FROM THE LIST
	JUMPE B,R		;RETURN IF END-OF-LIST
	IDIVI B,^D36		;COMPUTE WORD OFFSET, BIT POSITION
	CAIL B,GRPLSZ		;WILL THIS FIT IN THE TABLE?
	JRST [	PUSH P,A	;NO
		HRROI A,[ASCIZ/
? GROUP NUMBER OUT OF RANGE, SKIPPED.
/]
		PSOUT
		POP P,A
		AOJA A,MSKGP1]
	ADDI B,GRPLST		;COMPUTE ADR OF WORD CONTAINING THE BIT
	MOVX T1,.MINFI		;GET A LEFT-JUSTIFIED BIT
	MOVN C,C		;SHIFT IN CORRECT DIRECTION
	LSH T1,0(C)		;POSITION MASK IN CORRECT POSITION
	IORM T1,(B)		;MARK THE BIT IN MASTER LIST
	AOJA A,MSKGP1		;GO CHECK NEXT GROUP IN LIST


LCRLF:	MOVE A,OUTFIL
	HRROI B,CRLFM
	MOVEI C,0
	SOUT
	SOS LINENO
	POPJ P,0

NOCANDO:
	HRROI A,[ASCIZ /
? ULIST: Not privileged to read system files.
/]
	PSOUT
	HALTF
	JRST DONE

FORM:	MOVE A,OUTFIL
	MOVEI B,C.FF
	BOUT
	POPJ P,0
SORT:	SETOM USERNO		;NO PREVIOUS DUMP
	SETZM SORTP		;AND FIRST CELL IN SORTED BLOCK
ALPHA1:	MOVEI T1,0		;START TESTING AT ZERO
ALPL1:	SKIPE NAMPTR(T1)	;FIND SOMEBODY, ANYBODY AT ALL
	JRST ALPHA2		;GOT ONE.
	CAIGE T1,MAXUSR-1	;ANYONE EXIST?
	AOJA T1,ALPL1		;MAYBE
	POPJ P,0		;NO. IMPOSSIBLE. DONE.

ALPHA2:	SKIPGE USERNO		;FIRST PASS?
	JRST ALPHA3		;YES. THIS T1 IS BEST SO FAR
	MOVE A,NAMPTR(T1)	;NO. GET NAME STRING ADR FOR CHECK
ALP2A:	MOVE B,USERNO		;COMPARE WITH PREVIOUS
	MOVE B,NAMPTR(B)	; ..
	PUSHJ P,STCAML		;SKIP IF STRING(A) LESS THAN STRING (B)
	  JRST ALPHA3		;B .GE. A
ALP2B:	CAML T1,TOPUSR		;RUN THRU THEM ALL?
	POPJ P,0		;YES. NONE AFTER PREVIOUS. DONE.
	SKIPE A,NAMPTR+1(T1)	;NEXT T1 IN USE?
	AOJA T1,ALPHA2		;YES. GO CHECK IT
	AOJA T1,ALP2B		;NO. LOOK FURTHER.

ALPHA3:	MOVEI T2,0		;START SECOND CHECK AT ZERO TOO
	SKIPN NAMPTR(T2)	;THIS USER EXIST?
	AOJA T2,.-1		;NO. FIND ONE. MUST BE ONE, WAS ABOVE.
ALP3A:	SKIPGE USERNO		;ANY PREVIOUS?
	JRST ALPHA4		;NO.
	MOVE A,NAMPTR(T2)	;YES. COMPARE T2 WITH PREVIOUS
ALP3B:	MOVE B,USERNO		; ..
	MOVE B,NAMPTR(B)	; ..
	PUSHJ P,STCAML		;SKIP IF T2 BEFORE OLD
	  JRST ALPHA4		;T2 AFTER OLD. IT'S A CANDIDATE
ALPHA6:	CAML T2,TOPUSR		;T2 NOT A CANDIDATE. AT END?
	JRST ALPHA7		;YES. BEST GUY POSSIBLE IS IN T1
	SKIPN A,NAMPTR+1(T2)	;NOT AT END. TRY ANOTHER.
	AOJA T2,ALPHA6		;THAT ONE NOT IN USE. SKIP IT.
	AOJA T2,ALP3A		;OK, TRY THIS ONE.

ALPHA4:	MOVE A,NAMPTR(T1)	;COMPARE THE TWO TEST NAMES
	MOVE B,NAMPTR(T2)	; ..
	PUSHJ P,STCAML		;SKIP IF T1 BEFORE T2
	  MOVE T1,T2		;T2 WAS FIRST. MOVE TO BEST SO FAR.
	JRST ALPHA6		;BEST IS IN T1. TRY ANOTHER T2.

ALPHA7:	HRRZM T1,USERNO		;THIS IS BEST GUY.
	MOVE T2,SORTP		;POINTER INTO SORTED BLOCK
	HRRZM T1,ORDRTB(T2)	;STORE ANSWER
	AOS SORTP		;PREPARE FOR NEXT ONE
	JRST ALPHA1		;AND START ALL OVER FOR ANOTHER ONE.
DIRGRP:	PUSHJ P,COLECT		;GET THE NAMES, USER AND DIR GRPS
	MOVE A,OUTFIL		;TITLE PAGE
	MOVEI C,0
	HRROI B,[ASCIZ /


	     USER and DIRECTORY groups on structure: /]
	SOUT
	MOVE B,STRDEV		;DEVICE DESIGNATOR
	DEVST			;LIST STR NAME
	 JSERR
	HRROI B,[ASCIZ /

		/]
	MOVEI C,0
	SOUT			;NEXT LINE
	SETO B,			;CURRENT DATE
	MOVSI C,322401		;PRINT DATE ONLY
	ODTIM
	PUSHJ P,LCRLF
	HRROI B,[ASCIZ /


The following groups are in use:

/]
	SOUT

	SETZB D,LASTGP		;INITIALIZE HIGHEST GROUP #
	MOVEI T1,GRPLST		;GET ADR OF MASTER GROUP LIST
DIRGL1:	MOVE T2,(T1)		;GET A WORD FROM LIST
DIRGL2:	JFFO T2,DIRGL5		;COUNT BITS
	 JRST DIRG10		;NO BITS IN THIS WORD, DO NEXT WORD
DIRGL5:	TDZ T2,BITTAB(T3)	;CLEAR BIT JUST FOUND
	MOVE B,T1		;GET ADDRESS OF THIS WORD
	SUBI B,GRPLST		;COMPUTE OFFSET INTO TABLE
	IMULI B,^D36		;COMPUTE POSITION OF FIRST BIT + 1
	ADDI B,(T3)		;ADD POSITION OF BIT IN THIS WORD
	CAMLE B,LASTGP		;FOUND A NEW HIGHEST GROUP # ?
	MOVEM B,LASTGP		;YES, STORE NEW HIGHEST GROUP #
	MOVEI C,^D10		;GET DECIMAL RADIX
	NOUT			;OUTPUT THE GROUP NUMBER
	 JSERR			;UNEXPECTED ERROR
	MOVEI B,.CHTAB		;TYPE A TAB
	BOUT
	AOS D			;SEE IF CRLF NEEDED
	CAIGE D,^D9
	JRST DIRGL2		;NO
	CALL LCRLF		;YES, TYPE CRLF
	SETZ D,			;INITIALIZE COUNT
	JRST DIRGL2		;GO DO NEXT BIT IN THIS WORD
DIRG10:	CAIGE T1,GRPLST+GRPLSZ-1 ;DONE ALL WORDS IN TABLE YET ?
	AOJA T1,DIRGL1		;NO, GO DO NEXT WORD IN TABLE

	HRROI B,[ASCIZ /

The highest directory in use is number: /]
	MOVEI C,0
	SOUT
	MOVE B,TOPUSR		;GET HIGHEST DIR NUMBER
	MOVEI C,10
	NOUT
	  JFCL
	HRROI B,[ASCIZ /

The first free directory number is: /]
	MOVEI C,0
	SOUT
	SETZ B,			;INIT TO ZERO
	MOVEI E,20		;START AT DIR #20
LOWHL:	SKIPN NAMPTR(E)		;LOOK FOR UNUSED
	JRST [	MOVE B,E	;USE THIS
		JRST LOWH1]
	CAMGE E,TOPUSR		;CHECK IF DONE
	AOJA E,LOWHL		;LOOP
LOWH1:	JUMPE B,[HRROI B,[ASCIZ "None available"]
		 SETZ C,
		 SOUT
		 JRST LOWH2]
	MOVEI C,10
	NOUT
	  JFCL
LOWH2:	HRROI B,CRLFM
	MOVEI C,0
	SOUT
	MOVEI B,C.FF		;NEW PAGE
	BOUT			; ..
	MOVEI A,1		;START WITH GROUP NUMBER 1
	MOVEM A,GROUPN		;SAVE INITIAL GROUP NUMBER
DIRDL1:	TRZ F,R.DGM		;INITIALIZE TO NO MEMBERS OF GROUP
	MOVEI A,DIRDA		;WHERE TO GO FOR DUMP TEST AND DUMP
	MOVEM A,DMPADR		;AS ALPHABETIZING PROCEEDS
	PUSHJ P,ALFDMP		;SCAN USERS
	JRST DIRDB		;YES.
GNOUT:	MOVE A,OUTFIL		;HANDY SETUP OF A. OUTPUT GRP NUMBER
	MOVE B,GROUPN
	MOVE C,[120002,,12]
	NOUT
	  JFCL
	POPJ P,0

GNOUTE:	PUSHJ P,GNOUT		;OUTPUT GROUP NUMBER AND
	JRST LCRLF		; EOL, RETURN WITH A/OUTFIL, C/0

DGNAME:	MOVE A,OUTFIL
	HRROI B,[ASCIZ /, /]
	MOVEI C,0
	TRNE F,R.DGM		;IF NOT FIRST,
	SOUT			;OUTPUT A COMMA AND A SPACE
	MOVEI A,2		;AND COUNT THOSE POSITIONS
	TROE F,R.DGM		;UNLESS FIRST TIME THRU (FLAG NOT FIRST)
	ADDM A,COLUMN		;UPDATE COLUMN COUNTER
DGNM1:	HRROI A,STRBF		;SCRATCH STORAGE
	HRRO B,NAMPTR(E)	;NAME TO TYPE OUT
	MOVEI C,1000		;LENGTH OF STRING
	MOVEI D,0		;TERMINATES ON A NULL
	SOUT
	MOVNS C			;COMPUTE STRING LENGTH
	ADDI C,1000		;GET CHARACTERS IN NAME
	ADDB C,COLUMN		;UPDATE COLUMN COUNT
	TRNN F,R.WIDE		;WIDE OR NARROW PAPER?
	 JRST [	CAIGE C,^D70	;WOULD IT OVERFLOW?
		JRST DGNGO	;NO. GO OUTPUT IT
		JRST DGNCR]	;YES. DO AN EOL AND RETRY.
	CAIGE C,^D130		;WOULD IT OVERFLOW WIDE PAPER?
	JRST DGNGO		;NO, IT FITS
DGNCR:	PUSHJ P,LCRLF		;OUTPUT NEW LINE
	SETZM COLUMN		;CLEAR COLUMN COUNTER
	JRST DGNM1		;AND TRY AGAIN

DGNGO:	MOVE A,OUTFIL		;OUTPUT THE NAME AT LAST
	MOVEI C,0		;INDEFINITE STRING
	HRRO B,NAMPTR(E)	;POINT TO NAME STRING
	SOUT			;OUTPUT IT
	POPJ P,0		;AND RETURN
DIRDB:	TRZ F,R.DGM		;NOW DO THE USERS OF THE GROUP.
	MOVEI A,DIRUA		;ROUTINE TO TEST USER GROUP AND DUMP
	MOVEM A,DMPADR		; ..
	PUSHJ P,ALFDMP		;ALPHABETIZE, DUMP IF IN GRP
	JRST DIRDC		;YES.

DIRDC:	MOVE A,GROUPN		;GET CURRENT GROUP
	CALL GETNGP		;GET NEXT GROUP NUMBER
	 JRST DIRDC0		;NO MORE
	MOVEM A,GROUPN		;SAVE NEW GROUP NUMBER
	JRST DIRDL1		;LOOP BACK FOR THIS GROUP

DIRDC0:	MOVEI A,BITDMP		;FOLLOWING ALL USE BIT TEST DUMP ROUTINE
	MOVEM A,DMPADR		; SO SAVE DISPATCH ADDRESS
	MOVE A,OUTFIL		;SPACE TO NEW PAGE
	MOVEI B,C.FF		; ..
	BOUT			; ..
	MOVEI T1,PRVTAB		;FIRST OF TWO TABLES WITH BITS
DIRDC1:	MOVEM T1,BITTBA		;TABLE ADDRESS
	MOVSI T1,(1B0)		;BIT TO TEST, START AT LEFT.
	MOVEM T1,BIT		; ..
BITDL:	MOVSI T2,-MAXUSR		;CHECK ALL USERS FOR CURRENT BIT
	HRR T2,BITTBA		;IN RIGHT TABLE
	MOVE T1,BIT		;BIT TO LOOK FOR
	TDNE T1,0(T2)		;THIS USER HAVE BIT?
	JRST DIRDC2		;YES.
	AOBJN T2,.-2		;NO. DOES ANYONE HAVE IT?
	JRST DIRDCN		;NO. NO OUTPUT FOR THIS BIT.
DIRDC2:	MOVEI B,0		;CLEAR TEXT POINTER
	MOVSI E,-NBITN		;COUNTER THRU BITS WITH TEXT
DDC2L:	LSH E,1			;DOUBLE INDEX
	MOVE T1,BITT2(E)	;BIT IN TABLE
	MOVE T2,BITT2+1(E)	;AND TABLE TO CHECK IN
	ASH E,-1		;GET AOBJN POINTER BACK (INCL SIGN)
	CAMN T1,BIT		;IS THIS THE ONE WE FOUND?
	CAME T2,BITTBA		;AND IN RIGHT TABLE?
	SKIPA			;NO.
	HRRO B,BITT1(E)		;YES. GET THE MESSAGE.
	AOBJN E,DDC2L		;TRY TO FIND THE MESSAGE.
	MOVE A,OUTFIL		;SET UP FOR I/O
	MOVEI C,0		; ..
	JUMPN B,[	SOUT
			JRST DIRDC3]
	HRROI B,[ASCIZ /

The following users have /]
	SOUT
	MOVE T1,BITTBA		;WHICH KIND OF BIT?
	HRROI B,[ASCIZ /privilege bit /]
	CAIE T1,PRVTAB
	HRROI B,[ASCIZ /user type bit /]
	SOUT			;DESCRIBE BIT WHICH HAS NO MESSAGE
	MOVE T1,BIT		;GET BIT NUMBER
	JFFO T1,.+1
	MOVEI B,(T2)
	MOVEI C,12		;IN DECIMAL
	NOUT
	  JFCL
	HRROI B,[ASCIZ /

/]
	MOVEI C,0
	SOUT
DIRDC3:	SETZM COLUMN		;START OF A LINE AFTER FOLLOWING TEXTS
	TRZ F,R.DGM		;FOR THE COMMA FIDDLER
	PUSHJ P,ALFDMP		;AND DUMP CLASS MEMBERS IN SORTED ORDER
DIRDCN:	MOVE E,BIT		;NEXT BIT IN MEMORY CELL
	LSH E,-1
	MOVEM E,BIT		; ..
	JUMPN E,BITDL		;LOOP IF MORE.
	MOVEI T1,TYPTAB		;FINISHED ONE TABLE. DONE BOTH?
	CAME T1,BITTBA		; ..
	JRST DIRDC1		;NO. TRY BITS IN TYPTAB TOO
	PUSHJ P,LCRLF		;LIST A COUPLE BLANK LINES
	PUSHJ P,LCRLF
	POPJ P,0		;DONE WITH DIR GRP LISTING

ALFDMP:	SETZB T1,SORTP		;START WITH FIRST SORTED INDEX
ALFDL1:	SKIPN T1,ORDRTB(T1)	;GET NEXT GUY ALPHABETICALLY
	POPJ P,0		;RAN OUT.
	MOVEM T1,USERNO		;STORE TO DRIVE DUMPERS
	PUSHJ P,@DMPADR		;DUMP OR TEST AND DUMP
	  JFCL
	AOS T1,SORTP		;UP TO NEXT ONE
	CAIGE T1,MAXUSR		;DONE ALL DIRECTORIES ?
	JRST ALFDL1		;NO. TRY THIS ONE
	POPJ P,0		;YES. END OF LINE.


;ROUTINE TO GET NEXT GROUP NUMBER
;ACCEPTS IN A/	CURRENT GROUP NUMBER
;RETURNS +1:	NO MORE GROUPS
;	 +2:	A/	NEXT GROUP NUMBER

GETNGP:	IDIVI A,^D36		;GET BIT NUMBER AND INDEX INTO TABLE
	MOVX C,.MINFI		;GET BIT POSITION
	MOVNS B
	ASH C,0(B)		;GET MASK OF BITS NOT WANTED
	MOVE T1,GRPLST(A)	;GET WORD FROM GROUP TABLE
	TDZ T1,C		;TURN OFF UNWANTED BITS
GETNG0:	JFFO T1,GETNG1		;ANY MORE BITS IN THIS WORD?
GETNG2:	AOS A			;STEP TO NEXT WORD IN TABLE
	CAIL A,GRPLSZ		;REACHED END?
	RET			;YES, NONE FOUND
	SKIPN T1,GRPLST(A)	;NO, ANY BITS ON IN THIS WORD?
	JRST GETNG2		;NO, GO TO NEXT WORD
	JRST GETNG0		;YES, GO RETURN THE GROUP NUMBER

GETNG1:	IMULI A,^D36		;YES, GO RETURN THIS NUMBER
	ADD A,T2
	RETSKP
DIRDA:	MOVE E,USERNO		;DRIVER OF DUMP ROUTINE IS USER NUMBER
	MOVE T3,GROUPN		;GET CURRENT GROUP NUMBER
	SKIPN T1,DGRTAB(E)	;GET ADDRESS OF GROUP LIST FOR DIRECTORY
	RET			;NO GROUPS FOR THIS DIRECTORY
	MOVE T2,(T1)		;GET LENGTH OF GROUP LIST
DIRDA0:	ADDI T1,1		;INCREMENT POINTER
	SOJLE T2,R		;IF END-OF-LIST, RETURN NOT-IN-GROUP
	CAME T3,(T1)		;THIS DIR IN THIS GROUP ?
	JRST DIRDA0		;NO, GO CHECK NEXT GROUP IN LIST
	TRNE F,R.DGM		;YES, FIRST ONE?
	JRST DIRDA1		;NO.
	PUSHJ P,LCRLF
	HRROI B,[ASCIZ /

The following directories are in group /]
	SOUT
	PUSHJ P,GNOUTE
	PUSHJ P,LCRLF
	SETZM COLUMN
DIRDA1:	PUSHJ P,DGNAME
	JRST CPOPJ1

DIRUA:	MOVE E,USERNO		;DRIVER OF DUMP ROUTINE IS USER NUMBER
	MOVE T3,GROUPN		;GET CURRENT GROUP NUMBER
	SKIPN T1,UGRTAB(E)	;GET ADDRESS OF GROUP LIST FOR DIRECTORY
	RET			;NO GROUPS FOR THIS DIRECTORY
	MOVE T2,(T1)		;GET LENGTH OF GROUP LIST
DIRUA0:	ADDI T1,1		;INCREMENT POINTER
	SOJLE T2,R		;IF END-OF-LIST, RETURN NOT-IN-GROUP
	CAME T3,(T1)		;THIS DIR IN THIS GROUP ?
	JRST DIRUA0		;NO, GO CHECK NEXT GROUP IN LIST
	TRNE F,R.DGM		;FOUND A USER. FIRST?
	JRST DIRUA1		;NO
	PUSHJ P,LCRLF		;YES. HEAD THE USER GROUP.
	HRROI B,[ASCIZ /

The following users have access to group /]
	SOUT
	PUSHJ P,GNOUTE		;TYPE THE NUMBER
	PUSHJ P,LCRLF		;BLANK LINE
	SETZM COLUMN		;CLEAR COLUMN COUNTER
DIRUA1:	PUSHJ P,DGNAME		;LIST THE USER NAME
	JRST CPOPJ1		;AND SEE WHO ELSE THERE IS
BITDMP:	MOVE E,USERNO		;GET USER NUMBER
	MOVE T1,BITTBA		;AND LOCATION IN TABLE
	ADDI T1,0(E)		; ..
	MOVE A,BIT		;AND PRIV BIT TO CHECK
	TDNE A,0(T1)		;IS IT ON?
	PUSHJ P,DGNAME		;YES. TYPE IT.
	POPJ P,0		;END OF BITDMP

BITT1:	[ASCIZ /

The following users are WHEELS:

/]
	[ASCIZ /

The following users are OPERATORS:

/]
	[ASCIZ /

The following users have CONFIDENTIAL INFORMATION ACCESS:

/]
	[ASCIZ /

The following users have MAINTENANCE ACCESS:

/]
	[ASCIZ /

The following users have IPCF privilege:

/]
	[ASCIZ /

The following users have ENQ-DEQ privilege:

/]
	[ASCIZ /

The following directories are FILES-ONLY:

/]
	[ASCIZ /

The following may use ALPHANUMERIC ACCOUNTS:

/]
	[ASCIZ /

The following users always see LOGIN message:

/]
NBITN==.-BITT1
BITT2:	EXP SC%WHL,PRVTAB
	EXP SC%OPR,PRVTAB
	EXP SC%CNF,PRVTAB
	EXP SC%MNT,PRVTAB
	EXP SC%IPC,PRVTAB
	EXP SC%ENQ,PRVTAB
	EXP 1B0,TYPTAB
	EXP 1B1,TYPTAB
	EXP 1B2,TYPTAB

;XWD NOUT FLAGS FOR LH C,  INDEX INTO DIR BLK
ORDERT:	XWD 500005,.CDNUM	;DIRECTORY NUMBER
	XWD 500014,.CDPRV	;PRIVILEGES
	XWD 500014,.CDLIQ	;LOGIN QUOTA
	XWD 500014,.CDLOQ	;LOGOUT QUOTA
	XWD 540014,.CDUGP	;USR GRPS
	XWD 540014,.CDDGP	;DIR GRPS
NORDR1==.-ORDERT	;NUMBER ALWAYS PRINTED EVEN ON NARROW FORM.
;BELOW HERE PRINTED ONLY IF NON-STD IN NARROW FORM.
	XWD 500014,.CDMOD	;USER TYPE
	XWD 500014,.CDFPT	;DEFAULT FILE PROT
	XWD 500014,.CDDPT	;DIR PROT
	XWD 500014,.CDRET	;DEF FILE RETENTION
NORDR2==.-ORDERT

DEFLTT: EXP -1			;DEFAULT VALUES OF ABOVE
	BLOCK NORDR2-1		;IN THE SAME ORDER
.OUTPT:	TRZ F,R.LPT
	MOVEI A,CMDBLK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI B,[CMFDB (.CMNOI,,<TXT(TO FILE)>)]
	COMND			;PARSE NOISE FIELD
	MOVE D,[GJFBLK,,GJFBLK+1] ;SET UP TO CLEAR GTJFN BLOCK
	SETZM GJFBLK		;CLEAR FIRST WORD OF BLOCK
	BLT D,GJFBLK+GJFSIZ-1	;CLEAR GTJFN BLOCK FOR COMND JSYS
	HRROI D,[ASCIZ/USERS/]	;GET DEFAULT FILENAME
	MOVEM D,GJFBLK+.GJNAM	;SAVE DEFUALT FILENAME
	HRROI D,[ASCIZ/TXT/]	;GET DEFAULT FILE TYPE POINTER
	MOVEM D,GJFBLK+.GJEXT	;SAVE DEFAULT FILE TYPE
	HRROI D,[ASCIZ/770000/]	;GET DEFAULT PROTECTION
	MOVEM D,GJFBLK+.GJPRO	;SAVE DEFAULT PROTECTION
	MOVX D,GJ%FOU		;FOR OUTPUT USE
	MOVEM D,GJFBLK+.GJGEN	;GET NEXT HIGHEST GENERATION
	MOVEI B,[CMFDB (.CMFIL)] ;GET FUNCTION BLOCK FOR OUTPUT FILE
	COMND			;GO PARSE FILE NAME
	TXNN A,CM%NOP		;NAME PARSED OK ?
	JRST .OUTP1		;YES, GO SAVE JFN
	CALL TSTCOL		;NO, SEE IF CRLF NEEDED
	TMSG <? ULIST: Invalid file specification
>				;OUTPUT MESSAGE
	RET			;RETURN
.OUTP1:	MOVEM B,OUTFIL
	MOVEI B,[CMFDB (.CMCFM)] ;GET CONFIRM FUNCTION BLOCK
	COMND			;WAIT FOR END-OF-COMMAND
	TXNE A,CM%NOP		;GARBAGE AT END-OF-COMMAND ?
	CALLRET COMER1		;YES, ISSUE ERROR MESSAGE
	MOVE A,OUTFIL		;GET JFN OF OUTPUT FILE
	MOVSI B,7B23
	HRRI B,101000
	OPENF
	 JRST .OUTP2
	JRST PARSE

.OUTP2:	SKIPL A,OUTFIL
	RLJFN
	  JFCL
	SETOM OUTFIL
	CALL TSTCOL		;SEE IF CRLF NEEDED
	TMSG <? ULIST: Cannot OPEN specified file
>				;OUTPUT ERROR MESSAGE
	RET			;RETURN TO PARSER

STCAML:	HRLI A,440700
	HRLI B,440700		;MAKE TWO STRING POINTERS
STCMLL:	ILDB C,A
	ILDB D,B		;GET TWO CHARACTERS
	CAMGE C,D		;TO A DIFFERENCE WITH A LOWER?
	JRST CPOPJ1		;YES. SKIP RETURN
	CAME C,D		;B LOWER?
	POPJ P,0		;YES. NON-SKIP RETURN
	JUMPN C,STCMLL		;SAME. LOOP UNLESS BOTH NULLS.
	JRST CPOPJ1		;END ON MATCHING NULLS.
SUBTTL	COMMAND ERROR SUBROUTINES

; INVALID END-OF-COMMAND

COMER1:	CALL TSTCOL		;TEST COLUMN POSITION
	TMSG <? ULIST: Garbage at end-of-command
>				;OUTPUT ERROR MESSAGE
	RET			;RETURN TO WHENCE WE CAME ...


; SUBROUTINE TO TEST COLUMN POSITION AND OUTPUT CRLF IF NEEDED

TSTCOL:	movei A,.priou		;get primary output designator
	rfpos			;read file position
	hrrz B,B		;keep just the column position
	JUMPE B,R		;IF AT COLUMN 1 DO NOT OUTPUT CRLF
	tmsg <
>				;no, output a crlf
	RET			;RETURN
HLPTXT:	ASCIZ	"
Commands are:

ALPHABETIC (LIST OF USERS)
BEGIN (LISTING)			[Starts outputting the listing]
DIRECTORY (GROUP LISTING)
EXIT (TO MONITOR)
HELP
INCLUDE (PASSWORDS IN LISTING)
MINI (LISTING FORMAT)		[Name & Directory number only]
NARROW (PAPER FORMAT)
NUMERIC (LIST OF USERS)
OMIT (PASSWORDS FROM LISTING)
OUTPUT (TO FILE) FILE-SPEC
PRINT (LISTING ON PRINTER)
STRUCTURE (TO USE) STR-NAME
WIDE (PAPER FORMAT)

Assumed are: NUMERIC, WIDE, OMIT, and output to TTY:
"
PROMPT:	ASCIZ /ULIST>/
BITTAB:	REPEAT ^D36,<	EXP 1B<.-BITTAB>>
FCOCB:	BYTE (2)1,1,1,1,1,1,1,2,1,2,2,1,2,2,1,1,1,1
FCOCC:	BYTE (2)1,1,1,1,1,1,1,1,1,1,1,1,1,2

PDP:	IOWD 200,PDL
PDL:	BLOCK 200

STRBF:	BLOCK 60
	STRPSW==30		;PLACE TO PUT PASSWORD IN STRBF

COMWRD:	BLOCK 10		;STORAGE FOR COMMAND WORD
ECMWRD==.-1
BP0:	XWD 010700,COMWRD-1	;POINTER WHICH IDPB'S TO FIRST CHAR
				; OF COMMAND WORD STORAGE
COMX:	BLOCK 1		;COMMAND INDEX
USERNO:	BLOCK 1		;DIRECTORY NUMBER
TOPUSR:	BLOCK 1		;HIGHEST USER IN USE
PAGBAS:	BLOCK 1		;FIRST USER NUMBER ON PAGE IN MINILIST
MAXCOL:	BLOCK 1		;COLUMNS PER LINE OF PAPER
LINENO:	BLOCK 1		;LENGTH OF PAGE COUNTER
DMPADR:	BLOCK 1		;DISPATCH FOR DUMP ROUTINE
PAGENO:	BLOCK 1		;PAGE COUNTER
OLDCAP:	BLOCK 1		;CAPABILITIES ON ENTRY
OUTFIL:	BLOCK 1		;OUTPUT JFN
GROUPS:	BLOCK 1		;OR OF ALL GROUP BITS IN SYSTEM
LASTGP:	BLOCK 1		;HIGHEST G$OUP NUMBER IN USE
GROUPN:	BLOCK 1		;GROUP NUMBER CURRENTLY CONSIDERING
COLUMN:	BLOCK 1		;COLUMN ON OUTPUT PAGE FOR GROUP ROUTINE
LINPOS:	BLOCK 1		;CHARACTER POSITION ON CURRENT LINE
COMCHC:	BLOCK 1		;COUNT OF CHARS IN COMMAND WORD
SORTP:	BLOCK 1		;POINTER TO SORTED USER BLOCK
UGROUP:	BLOCK GRPSIZ+1+1  ;USER GROUP BLOCK
DGROUP:	BLOCK GRPSIZ+1+1  ;DIR GROUP BLOCK
ACTBUF:	BLOCK 11	;BUFFER FOR DEFAULT DIRECTORY ACCOUNT
BIT:	BLOCK 1		;BIT TO TEST IN PRIV WORD IN BITDMP
BITTBA:	BLOCK 1		;WHICH BIT TABLE BEING CHECKED
LOGDES:	BLOCK 1		;TTY FOR ERROR MESSAGES
CURSTR:	BLOCK 1		;CURRENT STRUCTURE
STRDEV: BLOCK 1		;DEVICE DESIGNATOR FOR STR
DIRBUF:	BLOCK 20	;NAME STRING FOR <ROOT-DIRECTORY>
STRPTR:	BLOCK 1		;PNTR TO DIRBUF
GRPBUF:	BLOCK GBFSIZ	;BUFFER FOR OUTPUTTING GROUPS
GRPLST:	BLOCK GRPLSZ	;LIST OF ALL GROUPS IN USE ON SYSTEM
CMDBLK:	BLOCK .CMGJB+5		;COMMAND STATE BLOCK FOR COMND JSYS
ATMBFR:	BLOCK ATMSIZ		;ATOM BUFFER
BUFFER:	BLOCK BUFSIZ		;INPUT TEXT BUFFER
GJFBLK:	BLOCK GJFSIZ		;GTJFN BLOCK FOR COMND JSYS

PATCH:	BLOCK 400

	END <3,,ENTVEC>