Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_SRC_3_19910112
-
utilities/acj.mid
There are no other files named acj.mid in the archive.
;<UTILITIES>ACJ.MID.133, 27-Apr-83 00:58:28, Edit by MRC
TITLE ACJ
SUBTTL Definitions
; Stanford SCORE Access Control Job for TOPS-20 release 5
; Mark Crispin, SU-SCORE
; Access Control Job features:
; 1. Disallow OPERATOR logins/attach if not on CTY or a PTY controlled by
; OPERATOR.
; 2. Disallow login/attach if frozen or root-directory subdirectory.
; 3. Record CRDIR% that sets capabilities, disallow CRDIR% of non files-only
; subdirectory.
; 4. Log capabilities enabling
; 5. Downtime queue management, catch HSYS% and update downtime queue as
; appropriate.
; 6. If FTSETSPD, disallow setting speed on non-dialup terminals if not
; WHEEL or OPERATOR (for when the front end was flaking out).
; 7. Disallow creating more than MAXFRK forks.
; 8. ACCESS and CONNECT to non-PS: structures works if PS: user group matches.
; 9. If FTSUBDIR, ACCESS and CONNECT work to one's subdirectories (now done in
; the system).
; 10. Disallow CRJOB% if not WHEEL or OPERATOR.
; 11. Record logout information for FINGER.
; 12. Record entry into MDDT on console.
; 13. Disallow CTY: assign
; Assembly parameters
IFNDEF ACJVER,ACJVER==5 ; version
IFNDEF FTSETSPD,FTSETSPD==0 ; non-zero if to disallow setting speeds
IFNDEF FTSUBDIR,FTSUBDIR==0 ; non-zero if to handle subdirectory connect
IFNDEF MAXFRK,MAXFRK==10. ; maximum number of forks any one job may have
IFNDEF PDLLEN,PDLLEN==20 ; length of stack
IFNDEF RCVLEN,RCVLEN==100 ; length of RCVOK% argument block
IFNDEF USRLEN,USRLEN==10 ; length of user name string
IFNDEF HSYLEN,HSYLEN==18. ; two date/time words plus 16 string words
IFNDEF GTDLEN,GTDLEN==.CDDFE ; size of GTDIR% value block
IFNDEF GRPLEN,GRPLEN==100. ; maximum number of groups we handle
; AC's
A=1 ? B=2 ? C=3 ? D=4 ; JSYS arguments, temporaries
E=5 ? F=6 ? G=7 ; other temporaries
P=17 ; stack pointer (used in ERCAL)
IFNDEF STAT%,STAT%=JSYS 745
IFNDEF TCP%TV,TCP%TV==<100,,0>
IFNDEF TCP%NT,TCP%NT==<40,,0>
.INSRT MRC:<FINGER>FNGDEF.MID
; Macros
DEFINE TMSG STRING
HRROI A,[ASCIZ\!STRING!\]
PSOUT%
TERMIN
DEFINE LOGMSG STRING
CALL TIMSMP
TMSG [ ACJ: STRING]
TERMIN
DEFINE INS ?VALUE,MASK
<.DPB VALUE,<.BP MASK>> TERMIN
SUBTTL Data area
.DECSAV ; absolute assembly, produce an .EXE file
CORBEG==.
PDL: BLOCK PDLLEN ; stack
RCVBLK: BLOCK RCVLEN ; RCVOK% argument block
USRNAM: BLOCK USRLEN ; user name string
IFN FTSUBDIR,[
DIRNAM: BLOCK <2*USRLEN>+1 ; directory name string
];IFN FTSUBDIR
HSYTAB: BLOCK HSYLEN ; HSYS% block
HSYTB1: BLOCK HSYLEN ; auxillary readin block
DWNJFI: BLOCK 1 ; downtime queue input JFN
DWNJFO: BLOCK 1 ; downtime queue output JFN
HSYDNP: BLOCK 1 ; non-zero means HSYS% needs to be done
FNGJFN: BLOCK 1 ; JFN of FINGER file
GTJBLK: BLOCK .JIMAX+1 ; GETJI% readin area
MYUSRN: BLOCK 1 ; save of my user number
MYJOBN: BLOCK 1 ; save of my job number
OPRNUM: BLOCK 1 ; user number of OPERATOR
CTYNUM: BLOCK 1 ; TTY number of CTY
CTYDEV: BLOCK 1 ; CTY's device designator
NVTMIN: BLOCK 1 ; lowest NVT number
NVTMAX: BLOCK 1 ; highest NVT number
TVTMIN: BLOCK 1 ; lowest TVT number
TVTMAX: BLOCK 1 ; highest TVT number
PNVMIN: BLOCK 1 ; lowest PNV number
PNVMAX: BLOCK 1 ; highest PNV number
$NVTPU: BLOCK 1 ; NVTPUP table
$PUPFP: BLOCK 1 ; PUPFPT table
$PUPBU: BLOCK 1 ; PUPBUF table
PUPBUF: BLOCK 1 ; address of Pup free storage
; These blocks are +1 since they begin with a count word
GTDBLK: BLOCK GTDLEN+1 ; GTDIR% value block
USRGRP: BLOCK GRPLEN+1 ; user group list for user doing connect
DIRGRP: BLOCK GRPLEN+1 ; directory group list for dir to connect to
COREND==.-1
PAT..: ; patch area
LOC <.\777>+1 ; move to a page boundary
; Name of the downtime queue
DWNQUE: ASCIZ/SYSTEM:DOWNTIME.QUEUE/
SUBTTL Start of program
; Entry vector
EVEC: JRST ACJ ; START
JRST ACJ ; REENTER
<INS ACJVER,VI%MAJ>\<INS .FVERS,VI%EDN> ; version
EVECL==.-EVEC
ACJ: RESET% ; clean up I/O, etc.
MOVE [CORBEG,,CORBEG+1] ; init data area
SETZM CORBEG
BLT COREND
MOVE P,[PDL(-PDLLEN)] ; init stack
MOVEI A,.FHSLF ; get my capabilities
RPCAP%
TRNN B,SC%WHL\SC%OPR ; wizard?
JRST [ LOGMSG [WHEEL or OPERATOR capability required
]
HALTF%
JRST ACJ]
MOVE B,C ; enable all capabilities
EPCAP%
ERCAL FATAL
MOVEI A,.SFMS0 ; enable all system alerts
MOVEI B,1
SMON%
ERCAL FATAL
GJINF% ; get my user and job number
MOVEM A,MYUSRN
MOVEM C,MYJOBN
SETZB A,C ; get OPERATOR's user number
HRROI B,[ASCIZ/OPERATOR/]
RCUSR%
ERCAL FATAL
MOVEM C,OPRNUM ; save for later
HRROI A,[ASCIZ/CTY/] ; get CTY line number
STDEV%
ERCAL FATAL
MOVEM B,CTYDEV ; save in device format for ASND% check
HRRZM B,CTYNUM ; save for OPERATOR login check
HRLOI 377777 ; assume no ARPANET
MOVEM NVTMIN
MOVEM NVTMAX
MOVEM TVTMIN
MOVEM TVTMAX
MOVEM PNVMIN
MOVEM PNVMAX
MOVEI A,.GTNSZ ; get NCP data
GTNCP%
ERJMP CHKTVT ; no ARPANET here
HRRZM C,NVTMIN ; set first NVT
HLRO B,C ; -number of NVTs
SUB C,B ; 1+first NVT number
HRRZM C,NVTMAX
CHKTVT: MOVSI A,(TCP%NT) ; get TVT function
STAT%
ERJMP CHKPNV ; no TCP here
HRRZM B,TVTMIN ; set first TVT
HLRO C,B ; -number of TVTs
SUB B,C ; 1+last TVT number
HRRZM B,TVTMAX
CHKPNV: MOVE A,[SIXBIT/PUPPAR/]
SYSGT% ; get -nbr,,1st Pup NVT
JUMPE B,HOOKUP ; forget if no such table
HRRZM A,PNVMIN ; save TTY nbr of 1st Pup NVT
HLRE D,A
SUBI A,1(D)
HRRZM A,PNVMAX ; and TTY nbr of last Pup NVT
MOVEI A,(B) ; get GETAB table nbr
HRLI A,1 ; next item in table
GETAB%
ERJMP HOOKUP
MOVEM A,PUPBUF ; addr of Pup free storage (in monitor space)
MOVE A,[SIXBIT/NVTPUP/]
SYSGT%
ERCAL FATAL
MOVEM B,$NVTPUP
MOVE A,[SIXBIT/PUPFPT/]
SYSGT%
ERCAL FATAL
MOVEM B,$PUPFPT
MOVE A,[SIXBIT/PUPBUF/]
SYSGT%
ERCAL FATAL
MOVEM B,$PUPBUF
; JRST HOOKUP
; Now wire in the ACJ hooks we want
HOOKUP: MOVEI A,.SFSOK
MOVE B,[SF%EOK\SF%DOK\.GOASD]; catch ASND%
SMON%
ERCAL FATAL
MOVE B,[SF%EOK\SF%DOK\.GOOAD]; catch assign due to OPENF%
SMON%
ERCAL FATAL
MOVEI A,.SFSOK
MOVE B,[SF%EOK\SF%DOK\.GOCJB]; catch CRJOB%
SMON%
ERCAL FATAL
MOVE B,[SF%EOK\SF%DOK\.GOLOG]; catch logins
SMON%
ERCAL FATAL
MOVE B,[SF%EOK\SF%DOK\.GOCFK]; catch CFORK%
SMON%
ERCAL FATAL
IFN FTSETSPD,[
MOVE B,[SF%EOK\SF%DOK\.GOTBR]; catch setting terminal speed
SMON%
ERCAL FATAL
];IFN FTSETSPD
MOVE B,[SF%EOK\SF%DOK\.GOLGO]; catch logout
SMON%
ERCAL FATAL
MOVE B,[SF%EOK\SF%DOK\.GOCRD]; catch CRDIR%
SMON%
ERCAL FATAL
MOVE B,[SF%EOK\SF%DOK\.GOMDD]; catch MDDT%
SMON%
ERCAL FATAL
MOVE B,[SF%EOK\.GOACC] ; access to directory w/o other rights
SMON%
ERCAL FATAL
MOVE B,[SF%EOK\SF%DOK\.GOATJ]; catch ATACH%
SMON%
ERCAL FATAL
MOVE B,[SF%EOK\SF%DOK\.GOHSY]; catch HSYS% for Stanford HSYS% queueing
SMON%
ERJMP [LOGMSG [Unable to enable HSYS% hook
]
MOVEI A,.SFSOK ; restore A clobbered by LOGMSG
JRST .+1]
MOVEI A,.FHSLF ; stick us onto queue 0
MOVEI B,1
SPRIW%
ERCAL FATAL
; Set cease from the downtime queue and update downtime queue
MOVSI A,(GJ%FOU\GJ%OLD\GJ%SHT); get a handle on the downtime queue
HRROI B,DWNQUE
GTJFN%
ERJMP MAPFNG ; no queue, map FINGER file
HRRZM A,DWNJFO ; stask JFN away
MOVE B,[<INS 36.,OF%BSZ>\OF%WR\OF%RTD]
OPENF%
ERCAL FATAL
MOVSI A,(GJ%OLD\GJ%SHT) ; get read JFN on downtime queue
HRROI B,DWNQUE
GTJFN%
ERCAL FATAL
HRRZM A,DWNJFI ; stash the JFN away
MOVE B,[<INS 36.,OF%BSZ>\OF%RD]
OPENF% ; open the file
ERCAL FATAL
SETOM HSYDNP ; flag an HSYS% needs to be done
ACJ1: MOVE A,DWNJFI ; get the JFN back
MOVE B,[444400,,HSYTAB] ; get a record
MOVNI C,HSYLEN
SIN%
ERJMP ACJ2 ; end of file, no HSYS% to do
GTAD% ; verify that the time is reasonable
CAML A,HSYTAB
JRST ACJ1 ; it isn't, try next time
MOVE A,DWNJFO ; write the record back
MOVE B,[444400,,HSYTAB]
MOVNI C,HSYLEN
SOUT%
ERCAL FATAL
SKIPN HSYDNP ; does an HSYS% need to be done?
JRST ACJ1 ; no, next record
SETZM HSYDNP ; flag that we're doing it now
DMOVE A,HSYTAB ; get time down/time up
MOVEI C,HSYTAB+2 ; pointer to string
HSYS% ; set the new cease
ERCAL FATAL
LOGMSG [System shutdown set for ]
MOVEI A,.PRIOU ; output shutdown time
MOVE B,HSYTAB
SETZ C,
ODTIM%
ERCAL FATAL
SKIPN B,HSYTAB+1 ; until time known?
JRST ACJ10 ; no
TMSG [ until ]
MOVEI A,.PRIOU ; output until time
ODTIM%
ERCAL FATAL
ACJ10: SKIPN HSYTAB+2 ; is there a reason?
JRST ACJ1 ; no, don't try to output it
TMSG [ for ]
HRROI A,HSYTAB+2 ; pointer to reason string
PSOUT%
TMSG [
]
JRST ACJ1
ACJ2: SETZM HSYDNP ; clear the flag (probably unnecessary)
MOVE A,DWNJFI ; flush the files
HRLI A,(CO%NRJ) ; don't flush the JFN
CLOSF%
ERCAL FATAL
HRLI A,(DF%EXP) ; delete and expunge the old file
DELF%
ERJMP .+1 ; don't terribly care
MOVE A,DWNJFO
CLOSF%
ERCAL FATAL
; JRST MAPFNG ; now enter the main program loop
; Map in the FINGER data base
MAPFNG: MOVSI A,(GJ%OLD\GJ%SHT)
HRROI B,[ASCIZ/FINGER:FINGER.BIN/]
GTJFN%
ERJMP LOOP ; no FINGER file, don't care
MOVEM A,FNGJFN ; save JFN of FINGER file
MOVEI B,OF%RD\OF%WR\OF%THW
OPENF%
ERCAL FATAL ; can't get the FINGER file
HRLZS A
HRRI A,BLDPAG
DMOVE B,[.FHSLF,,BLDPAG
PM%CNT\PM%RD\PM%WR\PM%PLD\<HSTPAG-BLDPAG>]
PMAP%
ERCAL FATAL
SETOM FNGLOK ; in case file locked by previous load
ERJMP LOOP
; JRST LOOP
SUBTTL Here's the main program loop
LOOP: MOVEI A,RCVBLK ; get a request
MOVEI B,RCVLEN
RCVOK%
ERCAL FATAL
HRRZ B,RCVBLK+.RCFCJ ; get job number of requestor
SKIPE B ; SYSJOB?
CAMN B,MYJOBN ; or me?
JRST GRANT ; this shouldn't be necessary, but it's a bug
HLLZ B,MYUSRN ; get USRLH code
XOR B,RCVBLK+.RCUNO ; get user number
SKIPN B ; unlogged in user?
SETZM RCVBLK+.RCUNO ; yes, make it easier for routines below
HLRZ B,RCVBLK+.RCFCJ ; check function code
CAIN B,.GOLOG ; login?
JRST LOGCHK ; yes, check for valid login
CAIN B,.GOATJ ; attach?
JRST ATTCHK ; yes, similar to login check
CAIN B,.GOLGO ; logout?
JRST LGOLOG ; yes, record it
CAIN B,.GOACC ; connect or access?
JRST ACCCHK ; yes, check non-PS: user groups
CAIN B,.GOHSY ; system shutdown request?
JRST HSYQUE ; yes, mung the downtime queue
IFN FTSETSPD,[
CAIN B,.GOTBR ; setting terminal speed?
JRST SETSPD ; yes, log and maybe check it
];IFN FTSETSPD
CAIN B,.GOCFK ; create fork?
JRST CFKCHK ; yes, check for less than MAXFRK forks
CAIN B,.GOCAP ; enable capabilities?
JRST CAPCHK ; see if god capabilities being set
CAIN B,.GOCRD ; create directory?
JRST CRDCHK ; see if capabilities being set
CAIN B,.GOMDD ; enter MDDT%?
JRST MDDCHK ; yes, log it
CAIE B,.GOASD ; device assign?
CAIN B,.GOOAD ; assign due to OPENF%?
JRST ASDCHK ; yes, check it
CAIN B,.GOCJB ; create job?
JRST WOPR ; only let WHEEL or OPERATOR do it
MOVE B ; save function code over LOGMSG
LOGMSG [Unknown access function code ]
MOVEI A,.PRIOU ; output the function code
MOVE B,
MOVEI C,8. ; in octal
NOUT%
ERCAL FATAL
JRST GRANT
SUBTTL Downtime queue munger
; First, get the HSYS% arguments
HSYQUE: LOGMSG [System shutdown set]
CALL LOGUSR
MOVSI B,-HSYLEN ; get this many table words
HSYQU0: MOVEI A,.DWNTI ; from the DWNTIM table
HRLI A,(B)
GETAB%
ERCAL FATAL
MOVEM A,HSYTAB(B) ; to my HSYTAB table
AOBJN B,HSYQU0
GTAD% ; get the current date/time
MOVE A ; store it away someplace "safe"
SKIPN HSYTAB ; always paw over the queue on a cancel
JRST HSYQU1
ADDI A,3*5*60. ; fuzz up a few minutes or so
CAML A,HSYTAB ; is it a very soon downtime?
JRST GRANT ; yes, punt the queue
HSYQU1: MOVSI A,(GJ%FOU\GJ%OLD\GJ%SHT); get a handle on the downtime queue
HRROI B,DWNQUE
GTJFN%
ERJMP NEWQUE
HRRZM A,DWNJFO ; stask JFN away
MOVE B,[<INS 36.,OF%BSZ>\OF%WR\OF%RTD]
OPENF%
ERJMP [MOVE A,DWNJFO ; some cretin is trying to screw us
RLJFN%
ERJMP GRANT
LOGMSG [Cannot open downtime queue
]
JRST GRANT]
MOVSI A,(GJ%OLD\GJ%SHT) ; get read JFN on file
HRROI B,DWNQUE
GTJFN%
ERCAL FATAL ; bullshit; we have the file open!
HRRZM A,DWNJFI
MOVE B,[<INS 36.,OF%BSZ>\OF%RD]
OPENF%
ERCAL FATAL
SKIPN HSYTAB ; is this a new shutdown request?
JRST HSYCAN ; no, a cancellation - process it
SETOM HSYDNP ; flag an HSYS% needs to be done
; JRST HSYFFR
; Drops in from previous page
HSYFFR: MOVE A,DWNJFI ; search for the first record after this cease
MOVE B,[444400,,HSYTB1]
MOVNI C,HSYLEN
SIN%
ERJMP [MOVE A,DWNJFO ; none, insert new record here
MOVE B,[444400,,HSYTAB]
MOVNI C,HSYLEN
SOUT%
ERCAL FATAL
JRST HSYXIT] ; and leave
CAML HSYTB1 ; is this time valid?
JRST HSYFFR ; bad time, flush this record
MOVE A,HSYTB1 ; is this time before the new time?
CAMG A,HSYTAB
JRST [ MOVE A,DWNJFO ; no, write record out
MOVE B,[444400,,HSYTB1]
MOVNI C,HSYLEN
SOUT%
ERCAL FATAL
SKIPN HSYDNP ; does an HSYS% need to be done?
JRST HSYFFR ; no, flush
SETZM HSYDNP ; doesn't need to be done any more
DMOVE A,HSYTB1 ; get time down/time up
MOVEI C,HSYTB1+2; pointer to string
HSYS% ; set the new cease
ERCAL FATAL
JRST HSYFFR] ; and continue scan
MOVE A,DWNJFO ; yes, insert new record here
MOVE B,[444400,,HSYTAB]
MOVNI C,HSYLEN
SOUT%
ERCAL FATAL
HSYCOP: MOVE B,[444400,,HSYTB1] ; and continue copying the rest of the file
MOVNI C,HSYLEN
SOUT%
ERCAL FATAL
MOVE A,DWNJFI ; get yet another record
MOVE B,[444400,,HSYTB1]
MOVNI C,HSYLEN
SIN%
ERJMP HSYXIT ; end of file, all done
MOVE A,DWNJFO ; still more, get output JFN and continue
JRST HSYCOP
; Cancel the top request of the queue
HSYCAN: MOVE A,DWNJFI ; flush the first record
MOVE B,[444400,,HSYTAB]
MOVNI C,HSYLEN
SIN%
ERJMP HSYXIT ; file probably empty somehow
HSYCN0: MOVE B,[444400,,HSYTAB] ; get new downtime request
MOVNI C,HSYLEN
SIN%
ERJMP HSYXIT ; at end, punt
GTAD% ; verify that this new time is in the future
CAML A,HSYTAB
JRST HSYCN0 ; bad time, flush this record
DMOVE A,HSYTAB ; get time down/time up
MOVEI C,HSYTAB+2 ; pointer to string
HSYS% ; set the new cease
ERCAL FATAL
HSYCN1: MOVE A,DWNJFO ; write record out, repeat for each record
MOVE B,[444400,,HSYTAB] ; (probably should check for invalid date/time
MOVNI C,HSYLEN ; here too, but since it's "impossible" I
SOUT% ; didn't want to bother. Up above is to
ERCAL FATAL ; prevent a cancel bringing down the system!)
MOVE A,DWNJFI ; get back input JFN
MOVE B,[444400,,HSYTAB] ; read next record
MOVNI C,HSYLEN
SIN%
ERJMP HSYXIT ; at end, punt
JRST HSYCN1 ; loop back for next record
; Create a new downtime queue
NEWQUE: SKIPN HSYTAB ; is this a cease request?
JRST GRANT ; a cancellation and no file, go away
MOVSI A,(GJ%FOU\GJ%NEW\GJ%SHT); no queue, make one
HRROI B,DWNQUE
GTJFN%
ERCAL FATAL ; something is horribly wrong!!
HRRZM A,DWNJFO ; stask JFN away
MOVE B,[<INS 36.,OF%BSZ>\OF%WR\OF%RTD]
OPENF%
ERJMP [MOVE A,DWNJFO ; uh oh. Looks like we got reamed
RLJFN%
ERJMP GRANT
LOGMSG [Cannot create downtime queue
]
JRST GRANT]
MOVE B,[444400,,HSYTAB] ; write the request out
MOVNI C,HSYLEN
SOUT%
ERCAL FATAL
CLOSF% ; close off the file
ERCAL FATAL
JRST GRANT ; grant the request
; Here when downtime queue munging done. Flush the JFNs and exit
HSYXIT: MOVE A,DWNJFI ; flush the files
HRLI A,(CO%NRJ) ; don't flush the JFN
CLOSF%
ERCAL FATAL
HRLI A,(DF%EXP) ; delete and expunge the old file
DELF%
ERJMP .+1
MOVE A,DWNJFO
CLOSF%
ERCAL FATAL
JRST GRANT ; grant the request
SUBTTL Consider terminal speed set request
IFN FTSETSPD,[
SETSPD: MOVE A,RCVBLK+.RCTER ; get controlling terminal
MOVE B,RCVBLK+.RCARA ; compare against terminal user is setting
MOVE D,RCVBLK+.RCARA ; get pointer to argument block
CAME A,.GELIN(D) ; is user setting own terminal?
JRST SETSP1 ; no, must access control
TRO A,.TTDES ; convert to a terminal designator
MOVEI B,.MORSP ; return terminal speed information
MTOPR%
ERJMP GRANT ; dunno
TLNE B,(MO%RMT) ; is it a remote line?
JRST GRANT ; yes, allow it silently
SETSP1: LOGMSG [Set speed of line ]
MOVEI A,.PRIOU
HRRZ B,.GELIN(D) ; get line number
MOVEI C,8.
NOUT%
ERCAL FATAL
CAMN B,RCVBLK+.RCTER ; same line?
JRST SETSP2 ; yes, flush this part of msg
TMSG [ from line ]
MOVEI A,.PRIOU ; output user's line number
MOVE B,RCVBLK+.RCTER ; note C still set up from NOUT above
NOUT%
ERCAL FATAL
SETSP2: TMSG [ to ]
MOVEI A,.PRIOU
HLRZ B,.GESPD(D) ; input speed
MOVEI C,10.
NOUT%
ERCAL FATAL
MOVEI B,"/
BOUT%
ERCAL FATAL
HRRZ B,.GESPD(D) ; output speed
NOUT%
ERCAL FATAL
CALL LOGUSR ; output user name
JRST WOPR ; only let WOPR do this
];IFN FTSETSPD
SUBTTL Check for subdirectory or non-PS: user group match
ACCCHK:
IFN FTSUBDIR,[
HRROI A,USRNAM ; translate user name to string to USRNAM
SKIPN B,RCVBLK+.RCUNO
JRST DENY ; unlogged in?
DIRST%
ERCAL FATAL
HRROI A,DIRNAM ; translate directory name to string in DIRNAM
MOVE B,RCVBLK+.RCARA ; get pointer to arguments
SKIPN B,.GOAC1(B)
JRST DENY ; unlogged in?
DIRST%
ERJMP DENY ; deny if can't get at it
DMOVE A,[440700,,USRNAM
440700,,DIRNAM]
FNDOPN: ILDB C,B ; try to find open broket
JUMPE C,DENY ; just paranoia, but...
CAIE C,"<
JRST FNDOPN
CHKMAT: ILDB C,A ; get char from user name
ILDB D,B ; and from directory name
JUMPE D,DENY ; more paranoia...
CAIN C,(D) ; a match?
JRST CHKMAT ; still possible...
JUMPN C,CHKGRP ; if user not a substring, then try groups
CAIN D,". ; look like subdirectory?
JRST GRANT ; yes, let user win
; Note: this introduces a bug - FOO can connect to <FOO.BAR> on a foreign
; structure. I'll worry about it if I ever have a foreign structure. A
; much more obvious bug would be allowing close brocket as well as dot,
; which would completely defeat foreign structures!!
];IFN FTSUBDIR
; Not a subdirectory. Let's see if there is a user group match
CHKGRP: MOVE B,.GOAC1(B) ; get directory number wants to connect to
DMOVE A,[GRPLEN ? GTDLEN]; set up size of blocks
MOVEM A,USRGRP ; user group lists
MOVEM A,DIRGRP ; and directory group list
MOVEM B,GTDBLK ; GTDIR% BLOCK
MOVEI A,USRGRP ; return user groups for user
MOVEM A,GTDBLK+.CDUGP
SETZB A,GTDBLK+.CDDGP ; not directory groups, also clear RCDIR% flags
SKIPN B,RCVBLK+.RCUNO ; get her user number
JRST DENY ; unlogged in?
RCDIR% ; convert to directory number
ERCAL FATAL
MOVE A,C ; get directory number from C
MOVEI B,GTDBLK ; GTDIR% argument block
SETZ C, ; no password
GTDIR% ; get this user's almost everything
ERCAL FATAL
MOVEI A,DIRGRP ; now get directory groups for directory user
MOVEM A,GTDBLK+.CDDGP ; wants to connect to
SETZM GTDBLK+.CDUGP ; not user groups
MOVE A,RCVBLK+.RCARA ; get directory number she wants to connect to
MOVE A,.GOAC1(A)
MOVEI B,GTDBLK
SETZ C,
GTDIR% ; get the information
ERJMP DENY ; if I can't get at, tough
MOVEI A,DP%CN_6 ; is connecting to directory w/o psw allowed?
TDNN A,GTDBLK+.CDDPT
JRST DENY ; too bad
SOSLE A,USRGRP ; get user group list count
SOSG B,DIRGRP ; ditto for directory group
JRST DENY ; user or directory not in any groups
HRLOI A,-1(A) ; form AOBJN pointers to lists
EQVI A,USRGRP+1
HRLOI B,-1(B)
EQVI B,DIRGRP+1
USGLUP: MOVE (A) ; get a group this user is in
MOVE C,B ; see if there is a directory group match
DRGLUP: CAMN (C) ; match?
JRST GRANT ; user wins
AOBJN C,DRGLUP ; try next directory
AOBJN A,USGLUP ; no groups match, try next user group
JRST DENY ; no match at all
SUBTTL Extra login/attach validation
; Attach check just sets up the user and terminal numbers of the desired
; job for the login check routine to use (note that the job number is not
; set up!).
ATTCHK: SKIPN RCVBLK+.RCUNO ; is user logged in?
JRST ATTCH0 ; no, don't do WOPR check
MOVEI A,SC%WHL\SC%OPR ; WOPR can do any kind of attach
TDNE A,RCVBLK+.RCCAP ; WOPR?
JRST GRANT
ATTCH0: MOVE A,RCVBLK+.RCARA ; get pointer to arguments
SKIPE B,.GOTJB(A) ; get user#
HLL B,MYUSRN ; make sure a valid user number
MOVEM B,.GELUN(A) ; set up into .GELUN for login check
MOVE B,.GOTTY(A) ; get TTY # in B
MOVEM B,RCVBLK+.RCTER ; set up as the TTY to check
; JRST LOGCHK ; fall into login check routine
LOGCHK: SETZ A, ; no input flags
MOVE B,RCVBLK+.RCARA ; get pointer to arguments
MOVE B,.GELUN(B) ; get user number user wants to log in under
RCDIR% ; get dir info, dir # in C
ERJMP GRANT ; let LOGIN% barf on the user
TRNE A,CD%NVD\CD%RTD ; frozen?
JRST DENY ; loser
MOVE A,RCVBLK+.RCTER ; get terminal number
MOVE B,RCVBLK+.RCARA ; and user number user wants
MOVE B,.GELUN(B)
CAMN A,CTYNUM ; logging in on the CTY?
JRST [ CAMN B,OPRNUM ; operator may log in on the CTY
JRST GRANT
MOVE A,C ; get directory number from RCDIR%
MOVEI B,GTDBLK ; else user must have WHEEL or OPERATOR
SETZ C, ; no passwords, please
GTDIR%
ERCAL FATAL
MOVE GTDBLK+.CDPRV; fool WOPR
MOVEM RCVBLK+.RCCAP
JRST WOPR]
CAME B,OPRNUM ; trying to become OPERATOR?
JRST GRANT
HRRZ A,RCVBLK+.RCFCJ ; potential OPERATOR's job number
HRROI B,A ; put answer in A
MOVEI C,.JICPJ ; get job number of PTY mother
GETJI%
ERJMP GRANT
JUMPL A,DENY ; not on a PTY, lose
HRROI B,A ; on a PTY, get user number of PTY owner
MOVEI C,.JIUNO
GETJI%
ERJMP GRANT
CAME A,OPRNUM ; does this PTY belong to OPERATOR?
JRST DENY
JRST GRANT ; looks okay, allow it
SUBTTL Logout logging
LGOLOG: MOVE FNGSIG ; get the header word
ERJMP LGOCLB ; FINGER file zonked, ignore
CAME ['FINGER] ; is it SIXBIT/FINGER/?
JRST LGOCLB ; file clobbered
AOSN FNGLOK ; yes, try to lock it
JRST LGOLG0 ; got the lock
GTAD% ; file locked, check time now
SUBI A,10.*3 ; minus 10 seconds in the past
CAMGE A,FNGTIM ; was file locked more than 10 seconds ago?
JRST [ LOGMSG [FINGER file locked, logout ignored
]
JRST GRANT] ; unable to lock file
LOGMSG [FINGER file locked spuriously, ignoring lock
]
LGOLG0: MOVE A,RCVBLK+.RCARA ; get pointer to arguments
SKIPGE A,.GERLG(A) ; job number being logged out or -1
HRRZ A,RCVBLK+.RCFCJ ; our own job getting zapped
MOVE B,[-<.JIMAX+1>,,GTJBLK]; get the job's everything
MOVEI C,0
GETJI%
ERJMP LGOUNL ; job vanished or something
AOSN GTJBLK+.JIBAT ; is job controlled by batch?
JRST LGOUNL ; yes, don't record it
DMOVE E,GTJBLK+.JITNO ; TTY number in E, user number in F
SKIPN B,F ; get user number in B
JRST LGOUNL ; if unlogged in job, forget it
HRROI A,USRNAM ; make username string
DIRST%
ERJMP LGOUNL ; ???
MOVE A,FNGINF ; pointer to user lookup area
ERJMP LGOCUL
HRROI B,USRNAM ; user name of this person
TBLUK% ; find user
ERJMP LGOUNL ; user not in database
TLNN B,(TL%EXM) ; exact match?
JRST LGOUNL ; forget it
HRRZ G,(A) ; address of user info
GTAD% ; time now
MOVEM A,DIED(G) ; save time if possible
ERJMP LGOCUL ; file messed up or something
MOVEM A,FNGTIM ; set the last writer time as well
MOVE A,MYUSRN ; as well as last writer user
MOVEM A,FNGAUT
SKIPGE B,E ; terminal number
JRST LGOLG1 ; detached, don't check for NVT
CAML B,NVTMIN ; is it an NVT?
CAML B,NVTMAX
JRST LGOLG2
MOVEI A,.GTNNI ; get NVT line status
MOVEI C,E ; destination
HRROI D,.NCFHS ; get foreign host
GTNCP%
ERJMP LGOLG1 ; maybe logged out
LGOLGH: MOVE B,E
JRST LGOLG1
LGOLG2: CAML B,TVTMIN ; is it a TVT?
CAML B,TVTMAX
JRST LGOLG3
MOVE E,B ; save TTY # in case error
MOVSI A,(TCP%TV) ; argument is TVT
HRR A,B ; TVT number
HRROI B,7 ; want host number (should be a symbolic name)
HRROI C,E ; location of last logout
STAT%
ERJMP LGOLGH
JRST LGOLGH
LGOLG3: CAML B,PNVMIN ; is it a Pup NVT?
CAMLE B,PNVMAX
JRST LGOLG1 ; out of range to be a PNV
MOVE E,B
SUB B,PNVMIN
MOVS A,B
HRR A,$NVTPUP ; get its TTYPUP word
GETAB%
ERJMP LGOLGH
JUMPE A,LGOLGH ; must have just disconnected
MOVSS A
HRR A,$PUPFPT
GETAB% ; get foreign port addr (in monitor space)
ERJMP LGOLGH
JUMPE A,LGOLGH
SUB A,PUPBUF ; get offset from start of Pup free storage
MOVSI A,1(A) ; really want 2nd word
HRR A,$PUPBUF
GETAB% ; get foreign host name
ERJMP LGOLGH
MOVE B,A
TLO B,400000 ; flag so FINGER knows its an Ethernet host
LGOLG1: MOVEM B,R.I.P.(G) ; location of last logout
ERJMP LGOCUL
LGOUNL: SETOM FNGLOK ; now unlock the database
HRLZ A,FNGJFN ; JFN of FINGER file
HRRI A,BLDPAG
MOVE B,[UF%NOW\<HSTPAG-BLDPAG>]; update it all
UFPGS%
ERJMP GRANT
JRST GRANT
LGOCUL: SETOM FNGLOK ; unlock clobbered file
LGOCLB: LOGMSG [FINGER file apparently clobbered, ignoring logout
]
JRST GRANT
SUBTTL CRDIR%, MDDT%, EPCAP%
; CRDIR% check - see if capabilities being set
CRDCHK: MOVE A,RCVBLK+.RCARA ; get pointer to arguments
MOVE B,1(A) ; get bits in AC2 for CRDIR%
TLNN B,(CD%PRV) ; setting privileges?
JRST CRDCH2 ; don't bother logging
MOVE D,2(A) ; get directory number
LOGMSG [Create directory ]
SKIPN B,D
JRST [ TMSG [(new)]
JRST CRDCH1]
MOVEI A,.PRIOU ; try to output directory
DIRST%
JRST [ TMSG [(unknown?)]
JRST CRDCH1]
CRDCH1: TMSG [ with privileges]
CALL LOGUSR
MOVE A,RCVBLK+.RCARA ; get pointer to arguments
CRDCH2: MOVE B,3(A) ; get mode bits
TLNE B,(CD%DIR) ; FILES-ONLY?
JRST GRANT ; yes, allow
SKIPN 2(A) ; not files only, new directory?
JRST WOPR ; yes, require WOPR
MOVE B,1(A) ; get bits in AC2 for CRDIR%
TLNN B,(CD%MOD) ; old directory, setting mode?
JRST GRANT ; no, allow
JRST WOPR ; yes, allow only if WOPR
; MDDT% check - log it on the console
MDDCHK: LOGMSG [Entry into monitor DDT]
CALL LOGUSR
JRST WOPR ; redundant but oh well
; EPCAP% check - see if god privileges and if so log
CAPCHK: MOVE A,RCVBLK+.RCARA ; get pointer to arguments
MOVE A,.GENCP(A) ; get new capabilities user wants
ANDCM A,RCVBLK+.RCCAP ; not interested in ones she already has
SKIPE B,RCVBLK+.RCUNO ; not interested in unlogged in jobs (FTPSER!)
TRNN A,SC%WHL\SC%OPR ; becoming a WHEEL or OPERATOR?
JRST GRANT ; no, not interested in other bits
CAMN B,OPRNUM ; not interested in OPERATOR jobs either
JRST GRANT
LOGMSG [Enable capabilities]
CALL LOGUSR
JRST GRANT
SUBTTL ASND%, CFORK% & grant/deny exits
; ASND% check - disallow access to CTY unless WOPR
ASDCHK: MOVE A,RCVBLK+.RCARA ; get pointer to arguments
MOVE A,.GEADD(A) ; get device designator she wants
CAMN A,CTYDEV ; CTY:?
JRST WOPR ; yes, disallow unless WOPR
JRST GRANT ; otherwise allow
; CFORK% check - limit # of user forks to something reasonable
CFKCHK: MOVE A,RCVBLK+.RCARA ; get pointer to arguments
MOVE A,.GEFCT(A) ; get number of forks she is using
CAIG A,MAXFRK ; too many?
JRST GRANT ; no - allow
; JRST WOPR ; yes - allow only if WHEEL or OPERATOR
; Entry to allow if WHEEL or OPERATOR
WOPR: MOVEI A,SC%WHL\SC%OPR ; let WHEEL or OPERATOR win
TDNE A,RCVBLK+.RCCAP
GRANT: TDZA B,B ; grant the request
DENY: MOVEI B,400000 ; deny the request
MOVE A,RCVBLK+.RCRQN ; grant the request
SETZ C, ; no string for now
GIVOK%
ERCAL FATAL
JRST LOOP
SUBTTL Fatal errors come here
FATAL: LOGMSG []
MOVEI A,.PRIOU ; display last error
HRLOI B,.FHSLF
SETZ C,
ERSTR%
ERJMP .+2
ERJMP .+1
TMSG [, JSYS at PC=]
POP P,F
MOVEI F,-2(F) ; point PC at actual location of the JSYS
; Clever symbol table lookup routine. For details, read "Introduction to
; DECsystem-20 Assembly Language Programming", by Ralph Gorin, published by
; Digital Press.
SETZB C,E ; no current program name or best symbol
MOVE D,116 ; .JBSYM
HLRO A,D
SUB D,A ; -count,,ending address +1
SYMLUP: LDB A,[400400,,-2(D)] ; symbol type
JUMPE A,NXTSYM ; program names are uninteresting
CAILE A,2 ; 0=prog name, 1=global, 2=local
JRST NXTSYM ; none of the kind we want
MOVE A,-1(D) ; value of the symbol
CAMN A,F ; exact match?
JRST [ MOVE E,D ; yes, select it
JRST FNDSYM]
CAML A,F ; smaller than value sought?
JRST NXTSYM ; too large
SKIPE B,E ; get best one so far if there is one
CAML A,-1(B) ; compare to previous best
MOVE E,D ; current symbol is best match so far
NXTSYM: ADD D,[2000000-2] ; add 2 in the left, sub 2 in the right
JUMPL D,SYMLUP ; loop unless control count is exhausted
SKIPN D,E ; did we find anything helpful?
JRST FATAL1
; JRST FNDSYM
; Found an entry that looks close. See if it really is and if so use it
FNDSYM: MOVE A,F ; desired value
SUB A,-1(D) ; less symbol's value = offset
CAIL A,200 ; is offset small enough?
JRST FATAL1 ; no, not a good enough match
MOVE D,E ; get the symbol's address
MOVE A,-2(D) ; symbol name
TLZ A,740000 ; clear flags
CALL SQZTYO ; print symbol name
MOVE B,F ; get desired value
SUB B,-1(D) ; less this symbol's value
JUMPE B,FATAL2 ; if no offset, don't print "+0"
MOVEI A,"+ ; add + to the output line
PBOUT%
CAIA
FATAL1: MOVE B,F ; here if PC must be in octal
MOVEI A,.PRIOU ; and copy numeric offset to output
MOVEI C,8.
NOUT%
ERJMP .+1
FATAL2: SKIPE MYJOBN ; attempt to recover if job 0
HALTF%
RESET% ; deACJify
MOVEI A,.SNPSY ; see if there is another ACJ around
DMOVE B,[.RSQZ 0,ACJFN
.RSQZ 0,STG]
SNOOP%
JRST [ LOGMSG [Can't get address of ACJFN
]
HALTF%
JRST ACJ]
MOVEI A,(B) ; address of ACJFN in A
HRLI A,1 ; transfer one word
MOVEI B,D ; into D
PEEK%
JRST [ LOGMSG [Can't PEEK% in ACJFN
]
HALTF%
JRST ACJ]
JUMPE D,[TMSG [ - Restarting ACJ
]
JRST ACJ]
LOGMSG [Another ACJ is running as system fork ]
MOVEI A,.PRIOU
MOVEI B,(D)
MOVEI C,8.
NOUT%
ERJMP .+1
TMSG [
]
HALTF%
JRST ACJ
SUBTTL Subroutines
; Convert a 32-bit quantity in A from squoze to ASCII
SQZTYO: IDIVI A,50 ; divide by 50
PUSH P,B ; save remainder, a character
SKIPE A ; if A is now zero, unwind the stack
CALL SQZTYO ; call self again, reduce A
POP P,A ; get character
ADJBP A,[350700,,[ASCII/ 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.$%/]]
LDB A,A ; convert squoze code to ASCII
PBOUT%
RET
; Output user name of requester
LOGUSR: TMSG [ by job ]
MOVEI A,.PRIOU
HRRZ B,RCVBLK+.RCFCJ ; job number
MOVEI C,10. ; output in decimal
NOUT%
ERCAL FATAL
TMSG [, user ]
MOVEI A,.PRIOU
SKIPN B,RCVBLK+.RCUNO ; from user number in block
JRST [ TMSG [not logged in user]
JRST LOGUS1]
DIRST%
ERJMP [TMSG [???]
JRST LOGUS1]
LOGUS1: TMSG [, program ]
HRRZ A,RCVBLK+.RCFCJ ; get program name for this job
MOVE B,[-1,,GTJBLK+.JIPNM]
MOVEI C,.JIPNM
GETJI%
SETZM GTJBLK+.JIPNM
MOVE B,GTJBLK+.JIPNM ; get job name in B for output
SIXOUT: SETZ A, ; canonical SIXBIT output routine
LSHC A,6
ADDI A,"A-'A
PBOUT% ; wasteful of jsi, but...
JUMPN B,SIXOUT
TMSG [, TTY]
MOVEI A,.PRIOU
MOVE B,RCVBLK+.RCTER ; get terminal number
MOVEI C,8. ; output in octal
NOUT%
ERCAL FATAL
CAML B,NVTMIN ; is it an NVT?
CAML B,NVTMAX
JRST LOGUS3
MOVEI A,.GTNNI ; get NVT line status
MOVEI C,E ; destination
HRROI D,.NCFHS ; get foreign host
GTNCP%
ERJMP LOGUS3
TMSG [, ]
MOVEI A,.PRIOU ; output host name
MOVE B,E ; host number from E
MOVEI C,^D8 ; in case have to go by numbers
CVHST%
NOUT%
ERJMP .+1
LOGUS3: TMSG [
]
RET
TIMSMP: MOVEI A,.PRIOU
RFPOS% ; get cursor position
ERJMP TIMSM1
TRNN B,-1
JRST TIMSM1
TMSG [
]
TIMSM1: MOVEI A,.PRIOU
SETO B,
SETZ C,
ODTIM%
ERJMP .+1
RET
...LIT: CONSTANTS
END EVECL,,EVEC