mirror of
https://github.com/PDP-10/its.git
synced 2026-04-26 20:27:13 +00:00
10446 lines
288 KiB
Plaintext
10446 lines
288 KiB
Plaintext
; -*- MIDAS -*-
|
||
|
||
.symtab 3537.,7942.
|
||
|
||
.lstoff
|
||
ifndef $$pand,[
|
||
if1 [
|
||
define getpnd
|
||
.tag retry
|
||
printx /Is this to be a PANDA? /
|
||
.ttymac foo
|
||
irpnc 0,1,1,bar,,foo
|
||
ifse bar,Y,[$$pand==1]
|
||
ifse bar,y,[$$pand==1]
|
||
ifse bar,N,[$$pand==0]
|
||
ifse bar,n,[$$pand==0]
|
||
termin
|
||
termin
|
||
ifndef $$pand,[printx /
|
||
Answer Yes or No.
|
||
/
|
||
.go retry]
|
||
|
||
ifn $$pand,[ .ofnm1==sixbit /PANDA/ ? .ofnm2==sixbit /BIN/]
|
||
ife $$pand,[ .ofnm1==sixbit /PWORD/ ? .ofnm2==sixbit /BIN/]
|
||
|
||
termin
|
||
|
||
getpnd
|
||
|
||
expunge getpnd
|
||
];end IF1
|
||
];end IFNDEF $$PAND,
|
||
|
||
ifndef $$DBUG,$$DBUG==0 ;debuggin? Don't hack real thing!
|
||
|
||
ife $$PAND,title PWORD -- Passwords for ITS
|
||
ifn $$PAND,title PANDA -- Password Manipulations
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;;;
|
||
;;;
|
||
;;; Conventions to be rigidly adhered to!!!!!!!!
|
||
;;; Under penalty of bugs and hassles!!!
|
||
;;;
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;;;
|
||
;;; 1) Do not use ERROR lightly. It is for true internal errors, and
|
||
;;; will write crash files!
|
||
;;; 2) Put all conventions to be rigidly adhered to here!
|
||
;;; 3) Document all that you do!
|
||
;;; 4) Do more than that, TELL me all that you do. I.e. :BUG PWORD
|
||
;;; 7) I'd prefer to make whatever changes myself, on grounds that I know
|
||
;;; more of what is involved. At least, make an attempt to ask me first!
|
||
;;; 8) Make no patches to the binary without also modifying the source and
|
||
;;; doing :BUG PWORD ....
|
||
;;; 9) All typeout of strings is done by the TYPE macro. The first argument
|
||
;;; is the channel on which it should be output. Use DSPC if ^P codes are
|
||
;;; to be included, otherwise TYOC should be used, if output is to the
|
||
;;; TTY.
|
||
;;; 10) ECHOCH is for echoing the character contained in CH .... $ECHO is for
|
||
;;; "echoing" arbitrary characters, it takes a character
|
||
;;; as an argument. $ECHO ["A] will "echo" an "A". It echos tab, LF
|
||
;;; and backspace as uparrow-frobby, and on sail-able TTY's it uses ^KA
|
||
;;; type stuff.
|
||
;;; 12) Any code which deigns to type out on it's own (as opposed to the
|
||
;;; TYPE etc. macros, which do this on their own) should refrain from
|
||
;;; doing so if TTYFLG is non-zero. This indicates an output reset
|
||
;;; is in progress, and all output should be flushed until something
|
||
;;; of the nature of a prompt occurs, which should zero TTYFLG and then
|
||
;;; type out.
|
||
;;; 13) Do not use DSKLOS for OPEN's that can fail letigimately.
|
||
;;; It generates crash files. Use FILOSS <filename block>
|
||
;;; 14) All interrupt routines *MUST* save UUO and UUOH if they use any
|
||
;;; user UUO's. The same is true of any UUO's that call UUO's
|
||
;;; recursively. Also, UUOAC. They should use the UUOPSH or UUOPOP
|
||
;;; macros.
|
||
;;; 15) Any UUO's that may use AC's in effective address calculations
|
||
;;; move tt,(sp) ? move t,-1(sp) to recover their original contents
|
||
;;; the AC field may be saved in UUOAC
|
||
;;; 16) 17 (SP) cannot be used as the data address of a UUO. (obviously)
|
||
;;; 17) UUO's clobber no AC's
|
||
;;;
|
||
;;;
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
||
|
||
SUBTTL Basic Definitions
|
||
|
||
x=:0 ;super temporary
|
||
a=:1
|
||
b=:2
|
||
c=:3
|
||
d=:4
|
||
e=:5
|
||
|
||
t=:7 ;temporary arithmetic register
|
||
tt=:10 ;temporary arithmetic register, T+1
|
||
ch=:11 ;Character being manipulated.
|
||
count=:12 ;count into string being manipulated
|
||
bp=:13 ;byte pointer into string being read
|
||
ct=:14 ;count of characters read in this part
|
||
;of the reader. If it goes negative,
|
||
;the reader will fail-return
|
||
;when this happens, the caller should
|
||
;consider itself to have gotten a rubout,
|
||
;rubbing out it's terminating character.
|
||
sp=:17
|
||
|
||
lodc==1 ;channel to load DDT from
|
||
dspc==2 ;TTY out channel, display mode
|
||
tyic==3 ;TTY input channel, 12-bit input
|
||
tyoc==4 ;TTY out channel, non-display
|
||
lsrc==5 ;channel for LSRTNS
|
||
pwdc==6 ;channel for maping in pword database
|
||
dski==7 ;channel for disk input
|
||
hstc==10 ;channel for NETWRK to use for HOSTS3 table
|
||
dsko==14 ;channel to do mail output on
|
||
logc==15 ;channel for log file output
|
||
tlnc==16 ;USR device channel for STY owner
|
||
usrc==17 ;USR device channel
|
||
|
||
|
||
c.op==42 ;opcode for .OPER's
|
||
;;; random data area lengths
|
||
|
||
pdllen==100. ;large pdl
|
||
msgbfl==1400*5 ;>2 * # of chars on VT52 screen! (79. x 24.)
|
||
cargmx==3 ;maximum control arguments.
|
||
cargct==10 ;must be greater than the most # of
|
||
;control arguments known to any command
|
||
|
||
buflen==100 ;buffer for reading from disk
|
||
luckln==100 ;# of spaces to reserve for friendly sites
|
||
loseln==20 ;# of spaces to reserve for unfriendly sites
|
||
|
||
.purpg==13 ;first pure page
|
||
|
||
cnt==%CLBTW,,0 ;control
|
||
cnti==%CLBIT,,0 ;control immediate
|
||
argi==%CLIMM,,0 ;immediate argument
|
||
val==%CLOUT,,0 ;value return
|
||
errret==%CLERR,,0 ;error return
|
||
|
||
DEFINE SYSCAL A,B,C=<calerr>
|
||
.CALL [SETZ ? SIXBIT/A/ ? B ? setz+errret+c] TERMIN
|
||
|
||
define .pure
|
||
ifn .pure.,.err Two .PURE's without a corresponding .UPURE
|
||
.pure.==-1
|
||
..unpr==.
|
||
loc ..pure
|
||
termin
|
||
|
||
define .upure
|
||
ife .pure.,.err Two .UPURE's without a correspponding .PURE
|
||
.pure.==0
|
||
..pure==.
|
||
loc ..unpr
|
||
termin
|
||
|
||
|
||
..unpr==100
|
||
..pure==2000*.purpg
|
||
.pure.==0 ; initially allocating impure
|
||
|
||
;; Macro to check for overlap of pure and impure
|
||
define .perch
|
||
define .pch. xx,yy,zz
|
||
printc \
|
||
Impure storage from 0 to yy
|
||
Pure storage from xx to zz
|
||
\
|
||
termin
|
||
.pch. \.purpg*2000,\..unpr,\..pure
|
||
ifl .purpg*2000-..unpr,.err UNPURE overlaps with PURE
|
||
termin
|
||
|
||
define norm7 c ;normallize a 7-bit byte pointer
|
||
skipge c
|
||
sub c,[430000,,1]
|
||
termin
|
||
|
||
define decbp c ;decrement byte pointer
|
||
add c,[70000,,] ;back up the byte pointer
|
||
skipge c ;did we cross a word boundary?
|
||
sub c,[430000,,1] ;then fix it
|
||
termin
|
||
|
||
define decbp6 c ;decrement byte pointer
|
||
add c,[60000,,] ;back up the byte pointer
|
||
skipge c ;did we cross a word boundary?
|
||
sub c,[440000,,1] ;then fix it
|
||
termin
|
||
|
||
;;; This macro takes two arguments, the first is a starting location in
|
||
;;; memory, and the second is a # of characters after that.
|
||
;;; It returns the BP that you'd get after that # of IDPB's into that buffer
|
||
define bpend buf,ln
|
||
<<000700+<<<<5-<ln-<ln/5>*5>>*7>+1>_14>>,,<buf+<ln/5>>> termin
|
||
|
||
define upper chr ;uppercase a character
|
||
cail chr,141 ;lower "a"
|
||
caile chr,172 ;lower "z"
|
||
caia ;if got here, it's not lower a-z, skip
|
||
subi chr,40 ;convert case
|
||
termin
|
||
|
||
define type chan=tyoc,&STRING
|
||
output chan,[asciz string]
|
||
termin
|
||
|
||
define ask &string
|
||
askusr [asciz string]
|
||
termin
|
||
|
||
;; WRITE clobbers X, writes string to bp
|
||
define write bp,&string
|
||
move x,[440700,,[asciz string]]
|
||
copy x,bp
|
||
termin
|
||
|
||
define tyobpi bp,ch
|
||
movei x,ch
|
||
idpb x,bp
|
||
termin
|
||
|
||
define do stuff,else,\label
|
||
define ddoo exit
|
||
jrst [stuff
|
||
jrst label]
|
||
!else!
|
||
|
||
label::
|
||
termin
|
||
|
||
ddoo <jrst label>
|
||
|
||
termin
|
||
|
||
pjrst==jrst ;for pushj sp, ? popj sp, sequences.
|
||
call=pushj sp,
|
||
ret=popj sp,
|
||
|
||
;;; macros to evaluate system symbols and locations
|
||
|
||
define seval a,b ;get value of symbol B in A
|
||
move a,[squoze 0,/b/]
|
||
.eval a,
|
||
loss
|
||
termin
|
||
|
||
define eval a,b
|
||
seval a,b
|
||
hrl a,a ;move to left
|
||
hrri a,a ;destination is a
|
||
.getloc a, ;get it into a
|
||
termin ;done!
|
||
|
||
define save objs
|
||
irp x,,[objs]
|
||
push sp,x
|
||
termin
|
||
termin
|
||
|
||
define restore objs
|
||
irp x,,[objs]
|
||
pop sp,x
|
||
termin
|
||
|
||
termin
|
||
|
||
%TCCOM==400000 ;Comm mode bit in %TCCOM
|
||
|
||
;;; definitions of data-structures in command table.
|
||
|
||
; CO <=> Command Option
|
||
%CO==:1,,525252 ;bit mask for %CO bit-typeout
|
||
%COJCL==:400000 ;says command accepts JCL
|
||
%COTOP==:200000 ;Says is a topic, not a command
|
||
%COOPT==:100000 ;says that the %COARG argument is optional
|
||
%COARG==:040000 ;says that the first word of JCL is 6bit
|
||
%COCRG==:020000 ;says that this command expects control
|
||
;arguments
|
||
%CONLS==:010000 ;says don't list this among the commands.
|
||
;useful for establishing aliases among
|
||
;commands.
|
||
%COFIL==:004000 ;Says this command may use ^X or ^Y
|
||
%COSND==:002000 ;Says this command needs :SEND type rubout
|
||
;hackery, including updating SNAPTR
|
||
|
||
;Command table entry format
|
||
CM$NAM==:0 ; SIXBIT /NAME/
|
||
CM$RTN==:1 ; Routine to run
|
||
CM$FLG==:2
|
||
CM$OPT==:3 ; AOBJN ptr to OPTIONS
|
||
CM$HLP==:4 ; Helper
|
||
CM$SDC==:5 ; AOBJN ptr to short documentation
|
||
CM$LDC==:6 ; AOBJN ptr to long doc
|
||
CM$LEN==:7
|
||
|
||
cmdcnt==0
|
||
|
||
define COMMAND name,aname,routin,flags,options,helper,&short,long
|
||
cmdcnt==cmdcnt+1
|
||
ifb aname, Z$!NAME:
|
||
ifnb aname, Z$!ANAME:
|
||
SIXBIT /name/
|
||
ifnb routin, routin
|
||
.else 0
|
||
ifnb flags, flags
|
||
.else 0
|
||
optexp [options]
|
||
0
|
||
<.length short>,,[asciz short]
|
||
<.length long>,,[asciz long]
|
||
termin
|
||
|
||
|
||
;; hack an expression of OPTIONS
|
||
define OPTEXP options,\.bar
|
||
-.bar,,[
|
||
.foo==0
|
||
.bar==0
|
||
irpw x,y,[options]
|
||
optex1 .bar,\<1_.foo>,x,[y]
|
||
.foo==.foo+1
|
||
termin
|
||
]
|
||
termin
|
||
|
||
define optex1 .bar,val,symbol,strings
|
||
; The following IRPS is to strip trailing blanks off the symbol (termin)
|
||
IRPS x,,[symbol]
|
||
x==:val
|
||
termin
|
||
irp x,,[strings]
|
||
<.length /x/>,,[ascii /x/]
|
||
val
|
||
<.length /-x/>,,[ascii /-x/]
|
||
val
|
||
.bar==.bar+2
|
||
termin
|
||
termin
|
||
|
||
;;; Macro to print error message and write crash file.
|
||
|
||
define error &mesage
|
||
errdmp [asciz mesage]
|
||
termin
|
||
|
||
;;; in SIOTO, the AC is assummed to contain the count initially. It is
|
||
;;; clobbered. The channel defaults to TYOC
|
||
|
||
define sioto ac,[bp],chan=tyoc
|
||
movem ac,siotct ;save the SIOT count
|
||
move ac,bp
|
||
syscal siot,[argi chan ? ac ? siotct]
|
||
loss
|
||
termin
|
||
|
||
|
||
define $echo .ch.
|
||
|
||
push sp,ch
|
||
move ch,[.ch.]
|
||
echoch
|
||
pop sp,ch
|
||
termin
|
||
|
||
|
||
;;;; ***** MEMORY MAP *****
|
||
;;;;
|
||
;;;; Data is assigned to one of two areas according to whether it follows
|
||
;;;; one of two macros, .PURE and .UPURE
|
||
;;;; Things following .UPURE are allocated in the unpure core, at the lowest
|
||
;;;; extreme of the job. Things following .PURE are allocated in the pages
|
||
;;;; following the impure. See the macro definitions for more details
|
||
;;;;
|
||
;;;; 0-13 impure data space
|
||
;;;; Pure code space
|
||
;;;; LSRTNS space
|
||
;;;; HOSTS3 table
|
||
;;;; password database (54-200)
|
||
;;;;
|
||
;;;; 360-363 badpag -- pages loaded into by DBGHAK. When anylyzing crash files
|
||
;;;; these pages are also mapped into the impure data area
|
||
;;;; (0-3)
|
||
;;;; 364-370 goodpg -- This is where DBGHAK saves it's own good pages when it
|
||
;;;; has BADPAG mapped into the impure data area
|
||
;;;; 375 dpdlpg -- debuging pdl allocated by DBGHAK
|
||
;;;; 376 tmpag1 -- temporary page # 1, must be contiguous with tmpag2
|
||
;;;; 377 tmpag2 -- temporary page # 2, must be contiguous with tmpag1
|
||
|
||
lsrpag==32 ;first page for LSRTNS to hack
|
||
lsrpgc==16. ;# pages for LSR1
|
||
|
||
hstpag==lsrpag+lsrpgc ;first page for NETWRK to hack
|
||
hstpgc==80. ;# pages for HOSTS3
|
||
|
||
pwpage==hstpag+hstpgc ;page where we map the password file
|
||
|
||
badpag==360
|
||
badloc==2000*badpag
|
||
|
||
goodpg==364
|
||
good=goodpg*2000
|
||
|
||
dpdlpg==375 ;page to use as debugging PDL
|
||
dpdl=2000*dpdlpg ;location of debugging pdl
|
||
|
||
tmpag1==376
|
||
tmpag2==377
|
||
|
||
|
||
SUBTTL UUO Routines etc.
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;;; ;;;
|
||
;;; UUO routines etc. ;;;
|
||
;;; ;;;
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
||
loc 35 ;in case get's switched in middle of an $X
|
||
.break 16,500000
|
||
.break 16,70000
|
||
|
||
loc 40
|
||
uuo: 0 ;location for UUO's
|
||
JSR UUOH ;go handle UUO's
|
||
loc 60
|
||
suuo: 0
|
||
jsr suuoh ;go handle system-returned UUO's
|
||
-intlng,,tsint ;abjon ptr to interrupt table
|
||
loclst: 0 ;nothing on locked switch list yet
|
||
-6,,critic ;Critical Routine table
|
||
|
||
|
||
loc 100
|
||
uuoh: 0 ;foo! Where did this come from?
|
||
jrst uuodsp ;go dispatch on the UUO
|
||
|
||
uuoac: 0 ;saved AC of UUO
|
||
uuoarg: 0 ;saved arg of UUO
|
||
suuoh: 0
|
||
jrst errfoo
|
||
.pure
|
||
|
||
errfoo: movem tt,ac.tt ;save an AC to hack with
|
||
ldb tt,[opcode suuo] ;check it for legitness
|
||
caie tt,<.ldb opcode,errdmp> ;is it real?
|
||
jrst [movei tt,[440700,,[asciz /Bad SUUO/]]
|
||
movem tt,errmsg
|
||
movem x,ac.x
|
||
jrst errput]
|
||
ldb tt,[accum suuo]
|
||
movei tt,@erruuo (tt) ;get address of handler
|
||
exch tt,uuoac ;recover the orriginal AC
|
||
jrst @uuoac ; yes, hack the error
|
||
|
||
;;; this is the magical dispatch for the ERRDMP uuo
|
||
;;; it is indexed by AC field of the ERRDMP uuo
|
||
|
||
;;; ERRDMP <0 to 4>,[ASCIZ /STRING/]
|
||
;;; if 0, ordinary error
|
||
;;; if 1, it's a LOSS, I.e. random error
|
||
;;; if 2, it's an OPEN that failed that
|
||
;;; shouldn't have, and should dump
|
||
;;; if 3, it's an I/O operation that should
|
||
;;; print the error and filename, the
|
||
;;; effective address of this should be
|
||
;;; a file block instead.
|
||
;;; if 4, AC's have already been saved, don't
|
||
;;; clobber.
|
||
|
||
|
||
erruuo: errmng ;basic ERROR uuo
|
||
loserr
|
||
dskerr ;disk error
|
||
opfail ;OPEN failure?
|
||
errmn1 ;AC's already saved ERROR?
|
||
repeat <20-<.-erruuo>>,baduer
|
||
|
||
baduer: movem x,ac.x
|
||
move tt,ac.tt
|
||
movei x,[asciz /ERRDMP with bad AC field!/]
|
||
movem x,errmsg
|
||
jrst errput
|
||
|
||
errdmp=50000,,0 ;UUO that goes through system, don't clobber
|
||
;.JPC !!
|
||
loss=errdmp 1,
|
||
dsklos=errdmp 2,
|
||
filoss=errdmp 3,
|
||
|
||
|
||
;;; macros to save and restore locations needed for UUO handler
|
||
;;; (for interrupts)
|
||
define uuopsh
|
||
save [UUO,UUOH,UUOAC]
|
||
termin
|
||
|
||
define uuopop
|
||
restore [uuoac,uuoh,uuo]
|
||
termin
|
||
|
||
uuodsp: save [T,TT] ;save a few AC's to work with
|
||
ldb t,[opcode uuo] ;get the opcode
|
||
ldb tt,[accum uuo] ;and the accumulator
|
||
caige t,uuomax ;legal?
|
||
jrst @optab(t) ; yes, hack it
|
||
uuoerr: error /Internal Error: Unknown UUO/
|
||
|
||
|
||
uxuuor: restore [uuoh] ;restore our return address!
|
||
xuuort: restore [x] ;restore our borrowed AC
|
||
uuoret: restor [tt,t] ;restore the stolen AC's
|
||
jrst @uuoh ;return
|
||
|
||
define uuodef name,loc
|
||
loc
|
||
name=<.-optab-1>_33
|
||
termin
|
||
|
||
optab: uuoerr ;no 0's allowed!
|
||
uuodef output,strt ;OUTPUT <CHANNEL>,[ASCIZ /STRING/]
|
||
uuodef outstr,istrt ;OUTSTR <CHANNEL>,[<bp [<string>]]
|
||
uuodef 6type,type6 ;6type chan,loc
|
||
uuodef 8type,type8 ;8type chan,loc
|
||
uuodef htype,typeh ;htype chan,loc
|
||
uuodef 10type,type10 ;10type chan,loc
|
||
uuodef aiot,aciot ;AIOT ac,loc (ac contains channel)
|
||
ifn $$PAND,uuodef tyo,utyo ;TYO chan,loc
|
||
ife $$PAND,tyo==.iot
|
||
uuodef idpb6,uidpb6 ;IDPB6 ac,[bp for output] (AC contains 6bit)
|
||
uuodef idpb8,uidpb8 ;IDPB8 ac,[bp for output] (AC has octal)
|
||
uuodef idpb10,udpb10 ;IDPB10 ac,[bp for output] (AC has decimal)
|
||
uuodef typout,outtyp ;TYPOUT chan,[spec] (see spec format below)
|
||
uuodef .mail,mailit ;.MAIL [mail-spec]
|
||
uuodef copy,scopy ;COPY ac,[bp] (ac contains from bp)
|
||
uuodef askusr,usrask ;ASKUSR [ASCIZ /STRING/]
|
||
;documentation for command
|
||
uuomax==.-optab
|
||
|
||
; DSKLOS is for dsk output opens that fail and shouldn't
|
||
|
||
|
||
;;; TYPOUT expects the EA to contain a frob as follows:
|
||
|
||
; 1) Byte pointers
|
||
; 2) 0, in which case it returns without doing anything
|
||
; 3) one of the following opcodes. These are indirected with, so indirection
|
||
; or indexing may be used.
|
||
|
||
typcod:
|
||
tp$ind==730000,,0 ;points to a footyp word to be interpreted
|
||
error /TP$IND not handled/
|
||
tp$dec=740000,,0 ;output word as decimal
|
||
10type @uuoarg
|
||
tp$htp=750000,,0 ;output word as half-words
|
||
htype @uuoarg
|
||
tp$oct=760000,,0 ;output the word as octal
|
||
8type @uuoarg
|
||
tp$6bt=770000,,0 ;6bit word to be output as 6bit
|
||
6type @uuoarg
|
||
|
||
outtyp: movem tt,uuoac ;remember the channel we hack
|
||
move tt,(sp) ;in case the argument lives in an AC
|
||
move t,-1(sp) ;gotta get the original vals for AC's
|
||
typot0: skipn t,@uuo ;get the argument
|
||
jrst uuoret ; null argument, just return
|
||
call typdsp ;dispatch on the type
|
||
jrst uuoret ;return
|
||
|
||
typdsp: hlrz tt,t ;get the argument type
|
||
andi tt,777740 ;clear out any indirection, etc.
|
||
|
||
cain t,0 ;is the whole thing 0?
|
||
ret ; yes, don't do anything at all.
|
||
cain tt,0 ;is it 0?
|
||
error /Null type code in TYPOUT/
|
||
cain tt,(tp$ind) ;is it indirect?
|
||
jrst [movem t,uuo ; substitute it for the UUO
|
||
move t,-2(sp) ; recover old AC values for indirection
|
||
move tt,-1(sp)
|
||
skipn t,@uuo ; perform the indirection
|
||
ret ; nothing there, don't do a thing
|
||
jrst typdsp] ; and re-do argument checking
|
||
caile tt,770000 ;is it too large
|
||
jrst typabj ; it's an AOBJN ptr
|
||
caige tt,450000 ;or too small?
|
||
jrst typbp ; it's a byte pointer
|
||
caige tt,720000 ;is it out of our range?
|
||
error /Bad argument to TYPOUT/
|
||
movem t,uuoarg ;remember the arg, to indirect through
|
||
ldb tt,[360300,,t] ;get the type-code of the arg
|
||
subi tt,3 ;three unused ones
|
||
move tt,typcod(tt) ;get the UUO to do that operation
|
||
move t,uuoac ;recover our AC
|
||
dpb t,[accum tt] ;and insert it into our consed up instr
|
||
movem tt,uuo ;store in convenient slot
|
||
move tt,-1(sp) ;recover the original contents of the AC's
|
||
move t,-2(sp) ;except for the stack, of course
|
||
push sp,uuoh ;remember where we're from
|
||
xct uuo ;perform the new UUO
|
||
pop sp,uuoh
|
||
ret
|
||
|
||
;;; handle the AOBJN ptr case
|
||
.upure
|
||
ABJSAV: 0 ;storage for our AOBJN ptr
|
||
.pure
|
||
|
||
typabj: push sp,abjsav ;we may be recursive
|
||
push sp,uuoac
|
||
typlop: movem t,abjsav ;remember our AOBJN ptr
|
||
hrrzm t,uuoarg ;cons up address of arg
|
||
move t,(sp) ;recover UUOAC
|
||
movem t,uuoac
|
||
move t,-2(sp) ;recover AC values
|
||
move tt,-3(sp)
|
||
move t,@uuoarg ;get the actual argument
|
||
call typdsp ; dispatch on the type of argument
|
||
move t,abjsav ;recall our AOBJN ptr
|
||
aobjn t,typlop ;if there are more args, get the next
|
||
pop sp,uuoac
|
||
pop sp,abjsav ;back to the way the world was
|
||
ret
|
||
|
||
;;; Cons up and execute a OUTSTR to type out from our Byte Pointer!
|
||
typbp: move tt,[outstr t] ;basic instruction
|
||
movem tt,uuo ;convenient place to put it!
|
||
move tt,uuoac ;get the AC field
|
||
dpb tt,[accum uuo] ;and add it into the instruction
|
||
push sp,uuoh ;remember where we're from!
|
||
xct uuo ;Do it!
|
||
pop sp,uuoh ;restore OUR return!
|
||
ret ;all done, return!
|
||
|
||
;;; STRT expects the UUO to have had the string at it's E.A, and it to start
|
||
;;; on a word boundary.
|
||
;;; ISTRT expects it to have had the byte pointer as it's E.A. and not start on
|
||
;;; a word boundary
|
||
|
||
.upure
|
||
mdlflg: 0 ;non-zero if we're to type MUDDLE strings
|
||
.pure
|
||
|
||
istrt: movem tt,uuoac ;remember the channel we hack
|
||
move tt,(sp) ;in case the B.P. lives in an AC
|
||
move t,-1(sp)
|
||
move t,@uuo ;get the B.P.
|
||
istrt0: move tt,uuoac ;recover the channel we hack
|
||
jrst strt1 ;and hack the rest of it.
|
||
|
||
strt: hrlzi t,440700
|
||
hrr t,uuo ;cons up a byte pointer to the string
|
||
|
||
strt1: save [count,t]
|
||
setz count, ;prepare to count characters
|
||
|
||
strt3: ildb ch,t ;grab the char
|
||
cain ch,^L ;is it ^L?
|
||
jrst strt4 ; ^L ends a file too, for us
|
||
caie ch,^C ;is it a ^C?
|
||
cain ch,0 ; is it null?
|
||
jrst strt4 ; one or the other, exit loop
|
||
skipn mdlflg ;are we hacking MUDDLE strings?
|
||
jrst strt39
|
||
caie ch,"" ;is it a " ?
|
||
cain ch,"\ ; or a \ ?
|
||
jrst strt40 ; take funny exit
|
||
|
||
strt39: aoja count,strt3 ;nope, keep on trucking
|
||
|
||
strt40: seto ch, ;note that this is a funny case!
|
||
|
||
strt4: syscal rfname,[tt ? val t] ;get the device this is to.
|
||
error /OUTPUT called on closed channel/
|
||
camn t,[sixbit /TTY/] ;Is this TTY output?
|
||
jrst typer ; yes, type it instead
|
||
pop sp,t ;recover the byte pointer
|
||
syscal siot,[tt ? t ? count] ;type it
|
||
loss
|
||
|
||
typecs: restore [count]
|
||
skipl ch ;was this a funny case?
|
||
jrst uuoret ; no, just return
|
||
ildb ch,t ;yes, get the funny character
|
||
push sp,uuoh ;remember our return address!
|
||
aiot tt,ch ;send it out quoted
|
||
pop sp,uuoh ;restore our return address!
|
||
jrst strt1 ;and continue typing from there!
|
||
|
||
typer: pop sp,t ;recover the byte pointer
|
||
save [siotct] ;save it in case we're at interrupt level
|
||
movem count,siotct ;put it in SIOTCT so ^S can clear
|
||
syscal siot,[tt ? t ? siotct]
|
||
.lose 1400 ; We must be losing to badly!
|
||
restore [siotct]
|
||
jrst typecs ;return or loop as needed
|
||
|
||
|
||
type6: movem tt,uuoac ;remember the channel to hack
|
||
restore [tt,t] ;in case the word is in an AC
|
||
save [t,tt,x]
|
||
|
||
move tt,@uuo ;byte pointer to our arg on our stack
|
||
move x,uuoac
|
||
push sp,uuoh ;remember where we came from, we want to
|
||
;go back!
|
||
|
||
type60: setz t, ;clelar out cruft in T for new char
|
||
lshc t,6 ;get the first character
|
||
skipn t ;is there something there?
|
||
aiot x,[^Q] ; no, quote the space
|
||
addi t,40 ;convert to ascii
|
||
aiot x,t ;type char in CH to channel in X
|
||
jumpn tt,type60 ;if there's more to type, type it
|
||
jrst uxuuor ;and return
|
||
|
||
|
||
uidpb6: movem tt,uuoac ;remember our ac
|
||
restore [tt,t] ;in case the word is in an AC
|
||
|
||
save [x,t,tt] ;Save the AC's we need..note not in usual
|
||
;order
|
||
push sp,@uuoac ;AC contains the data. Put it on the stack
|
||
move x,@uuo ;;get the byte pointer
|
||
pop sp,tt ;get the 6bit in our AC
|
||
|
||
idpb60: setz t, ;no garbage to throw us off.
|
||
lshc t,6 ;pick off a character
|
||
skipn t ;iff it's a blank
|
||
do [movei t,^Q ; grab a ^&Q
|
||
idpb t,x ; and stuff it down the Byte Pointer
|
||
setz t,] ; and restore the state of the world
|
||
addi t,40 ;convert to ascii
|
||
idpb t,x ;deposit it
|
||
jumpn tt,idpb60 ;if there's any more to output, hack it
|
||
wbackx: restore [tt,t] ;recover the temporary AC's
|
||
exch x,(sp) ;recover original contents of X
|
||
pop sp,@uuo ;and write back our Byte Pointer to wherever
|
||
jrst @uuoh ;and return
|
||
|
||
type10: movem tt,uuoac ;remember our AC
|
||
restore [tt,t] ;restore AC's in case data in AC's
|
||
save [t,tt,x] ;borrow another AC
|
||
move t,@uuo ;get our data
|
||
move x,uuoac ;get the channel to type to
|
||
save [uuoh] ;save our return address
|
||
call decpnt ;do the printing
|
||
jrst uxuuor ;and return to caller
|
||
|
||
decpnt: idivi t,10. ;figure first digit
|
||
push sp,tt ;push remainder
|
||
skipe t ;done?
|
||
call decpnt ; no compute next one
|
||
|
||
decpn1: pop sp,t ;yes, take out in opposite order
|
||
addi t,60 ;make ascii
|
||
aiot x,t ;type char in T to channel in X
|
||
ret ;and return for the next one.
|
||
|
||
udpb10: movem tt,uuoac ;remember our AC
|
||
restore [tt,t] ;restore AC's in case data in AC's
|
||
save [x,t,tt] ;borrow another AC
|
||
push sp,@uuo ; Get our byte pointer
|
||
move t,@uuoac ;get our data
|
||
pop sp,x ; Get our byte pointer into X
|
||
call decdpb ;do the writing
|
||
jrst wbackx ; write back X and exit
|
||
|
||
decdpb: idivi t,10. ;figure first digit
|
||
push sp,tt ;push remainder
|
||
skipe t ;done?
|
||
call decdpb ; no compute next one
|
||
|
||
decdp1: pop sp,t ;yes, take out in opposite order
|
||
addi t,60 ;make ascii
|
||
idpb t,x ; write character in T to BP in X
|
||
ret ;and return for the next one.
|
||
|
||
type8: movem tt,uuoac ;remember what AC field we had
|
||
restore [tt,t] ;restore val of AC's, in case data resides
|
||
save [t,tt,x,uuoh] ;therein. Borrow X, and save return addr.
|
||
move t,@uuo ;get our argument
|
||
move x,uuoac ;get channel to hack
|
||
call octpnt ;do the typing
|
||
jrst uxuuor ;and return to caller
|
||
|
||
octpnt: setz tt,
|
||
lshc t,-3 ;shift instead of IDIVI, don't forget
|
||
lsh tt,-41 ;negative!
|
||
push sp,tt ;push remainder
|
||
skipe t ;done?
|
||
call octpnt ;no compute next one
|
||
|
||
octpn1: pop sp,tt ;yes, take out in opposite order
|
||
addi tt,60 ;make ascii
|
||
aiot x,tt
|
||
ret ;and return for the next one.
|
||
|
||
;;; like OCTPRT except deposits down byte pointer in E.A. and gets data in AC
|
||
|
||
uidpb8: movem tt,uuoac ;remember what AC has the data
|
||
restore [tt,t] ;restore val of AC's, in case data resides
|
||
save [x,t,tt] ;therein. Also, borrow X. Note unusual
|
||
;order for things going to WBACKX
|
||
push sp,@uuo ;get our argument Byte pointer
|
||
move t,@uuoac ;Get contents of AC
|
||
pop sp,x ;Byte Pointer to X
|
||
call octdpb ;do the typing
|
||
jrst wbackx
|
||
|
||
octdpb: setz tt,
|
||
lshc t,-3 ;shift instead of IDIVI, don't forget
|
||
lsh tt,-41 ;negative!
|
||
push sp,tt ;push remainder
|
||
skipe t ;done?
|
||
call octdpb ;no compute next one
|
||
|
||
pop sp,tt ;yes, take out in opposite order
|
||
addi tt,60 ;make ascii
|
||
idpb tt,x ;output down the Byte pointer
|
||
ret ;and return for the next one.
|
||
|
||
typeh: movem tt,uuoac ; Remember the AC
|
||
restore [tt,t] ;restore the vals of AC's in case the data
|
||
save [tt,t,x,uuoh] ;resides therein. Borrow X, save return
|
||
push sp,@uuo ;recover the data without clobbering AC's
|
||
hlrz t,(sp) ;get left half
|
||
move x,uuoac ;remember the channel
|
||
call octpnt ;print it
|
||
aiot x,[",] ;,,
|
||
aiot x,[",]
|
||
hrrz t,(sp) ;get the right half
|
||
call octpnt ;print it
|
||
pop sp,x
|
||
jrst uxuuor ;return
|
||
|
||
;;; one instruction SYSCAL IOT that checks for TTYFLG if TTY channel
|
||
|
||
aciot: movem tt,uuoac ;remember the AC with the info
|
||
move tt,(sp) ;recover original data of AC's
|
||
move t,-1(sp)
|
||
|
||
push sp,@uuo ;fetch the value, but don't clobber AC's
|
||
move tt,@uuoac ;<AC> has channel, not is channel
|
||
pop sp,t ;and recover the value
|
||
|
||
cain tt,tyoc ;is it neither TTY channel?
|
||
caie tt,dspc
|
||
jrst aiot66 ; no, don't check for TTY turned off
|
||
|
||
skipe ttyflg ;has the TTY ben turned off?
|
||
jrst uuoret ; yep, just return
|
||
aiot66: call mmquot ;maybe muddle quote the character!
|
||
syscal iot,[tt ? t] ;actually do it
|
||
loss
|
||
jrst uuoret ;and return from the UUO
|
||
|
||
;;; Maybe Muddle Quote !
|
||
mmquot: skipn mdlflg ;hacking muddle strings?
|
||
ret
|
||
caie t,"\ ;is it a special char?
|
||
cain t,""
|
||
caia ; yep, gotta hack specially
|
||
ret ; nope, just output it
|
||
syscal iot,[tt ? ["\]] ;quote the frob first!
|
||
loss
|
||
ret
|
||
|
||
utyo: movem tt,uuoac ;remember the channel
|
||
move tt,(sp) ;recover original data of AC's
|
||
move t,-1(sp)
|
||
move t,@uuo ;get the data
|
||
move tt,uuoac ;and the channel
|
||
cain tt,tyoc ;is it neither TTY channel?
|
||
caie tt,dspc
|
||
jrst utyo66 ; no, don't check for TTY turned off
|
||
|
||
skipe ttyflg ;has the TTY ben turned off?
|
||
jrst uuoret ; yep, just return
|
||
|
||
utyo66: call mmquot ;maybe muddle quote the character!
|
||
syscal iot,[tt ? t] ;actually do it
|
||
loss
|
||
skipn logflg ;are we logging?
|
||
jrst uuoret ; no, return from the UUO
|
||
caie tt,tyoc ;is it either TTY channel?
|
||
cain tt,dspc
|
||
caia ; yes, don't stop now!
|
||
jrst uuoret ; no, don't log it!
|
||
syscal iot,[argi logc ? x] ;yes, log it
|
||
loss
|
||
jrst uuoret ;return
|
||
|
||
|
||
scopy: movem tt,uuoac ;remember which AC has our FROM pointer
|
||
move tt,(sp) ;recover original data of AC's
|
||
move t,-1(sp)
|
||
move tt,@uuoac ;get from pointer
|
||
move t,@uuo ;get TO pointer
|
||
save [ch] ;get a temporary AC to hack with!
|
||
scopy0: ildb ch,tt ;get a character
|
||
caie ch,^C ;is it a ^C
|
||
cain ch,0 ; or a ^@?
|
||
jrst scopy9 ; yes, end of loop
|
||
idpb ch,t ;deposit, and
|
||
jrst scopy0 ;do it again
|
||
|
||
scopy9: push sp,t ; Without advancing the BP
|
||
setz ch, ; follow the string with a ^@
|
||
idpb ch,t ; where it will be clobbered if further
|
||
pop sp,t ; copying is done
|
||
restore [ch] ; restore borrowed AC
|
||
bpback: exch tt,(sp) ; get back the original contents of the ACs
|
||
exch t,-1(sp) ; while saving the modified Byte pointer's
|
||
pop sp,@uuoac ; write back the modifed Byte Pointer's
|
||
pop sp,@uuo ; from whence they came
|
||
jrst @uuoh ; and return.
|
||
|
||
;;; ASKUSR [ASCIZ /STRING/] types string and reads a char, echoing Yes or No.
|
||
;;; it skips if the answer is Yes.
|
||
|
||
usrask: save [ch,dsprmp,uuo,uuoh]
|
||
move t,[output dspc,] ;cons up a display UUO
|
||
hrri t,@uuo ;with the right effective address
|
||
movem t,dsprmp
|
||
usras1: output dspc,@uuo
|
||
type tyoc,/ (Y or N) /
|
||
tyi
|
||
jrst usrext ; We'll take that as NO
|
||
jrst usras1 ; Help out
|
||
jrst usrext ; ditto
|
||
cain ch,40 ; Pretend that a space is a Yes also.
|
||
movei ch,"Y
|
||
caie ch,"y ;is it yes?
|
||
cain ch,"Y
|
||
jrst [type tyoc,/Yes. / ; successful
|
||
restore [uuoh] ; recover our return address
|
||
aos uuoh ; skip
|
||
jrst usrex1] ; and return
|
||
usrext: type dspc,/No. /
|
||
restore [uuoh]
|
||
usrex1: restore [uuo,dsprmp,ch]
|
||
jrst uuoret ;fail return
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;;; ;;;
|
||
;;; Password routines. ;;;
|
||
;;; ;;;
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
||
%COHLP==1 ;says command is not to be documented
|
||
|
||
byebye: ;this is the location to use instead of
|
||
;.logout, to avoid people logging out and
|
||
;linking
|
||
phaser==.suset [.spirqc,,[%piltp]] ;sneaky way to get here
|
||
clock:
|
||
klock:: syscal finish,[argi tyoc] ;finish up our output
|
||
jfcl
|
||
IFN 1,[ skipn debug
|
||
.logout 1,
|
||
.break 16,100000
|
||
.logout 1,
|
||
]; END IFN 1,
|
||
|
||
IFN 0,[ .suset [.rsuppro,,tt]
|
||
cail tt,0 ;Are we running as an inferior?
|
||
.logout 1, ; Go away, but don't gun TELSER
|
||
syscal rfname,[argi tlnc ;is there a job open on this channel?
|
||
val t ; device
|
||
val x ; UNAME
|
||
val tt] ; JNAME
|
||
loss ; eh?
|
||
cain t,0 ;is the Device 0?
|
||
.logout 1, ; yes, there is no job there
|
||
tlz x,777700 ;clear out the TTY # part of nnTLNT
|
||
came x,[sixbit / TLNT/] ;is it really a telser?
|
||
.logout 1, ; nope
|
||
came tt,[sixbit /TELSER/] ;including JNAME?
|
||
.logout 1, ; nope
|
||
.uset tlnc,[.ruind,,t] ;get his index
|
||
.gun t, ;make it go away
|
||
]; END IFN 0,
|
||
|
||
telbye: .logout 1, ;Bye-bye!
|
||
.logout 1,
|
||
|
||
jtingl: type tyoc,/The TINGLE command does not yet exist
|
||
/
|
||
ret
|
||
|
||
init: syscal corblk,[cnti %cbndw ;need to write to initialize
|
||
argi 0
|
||
argi %jself
|
||
argi pwpage ;just the first page
|
||
argi pwdc ;from the file
|
||
argi 0]
|
||
loss
|
||
|
||
syscal RQDATE,[val x ? val t]
|
||
loss
|
||
jumpl t,[type dspc,/AThe system doesn't know the time yet, please
|
||
wait.
|
||
/
|
||
movei t,300. ;system doesn't know time,
|
||
.sleep t, ;sleep 10. sec and hope it
|
||
jrst init] ;finds out the time.
|
||
init0: move tt,t
|
||
exch t,pwinit ;claim privilege of init'ing.
|
||
init1: camn t,pwinit ;should we init?
|
||
jrst initw ; no, someone else is, wait for him
|
||
setom pwlock ;unlock the lock
|
||
move x,pwcnt ;check the count, must be even
|
||
trz x,3 ;flush any odd words
|
||
movem x,pwcnt ;and save it back again
|
||
|
||
init2: movem tt,pwdone ;mark init complete.
|
||
jrst initd ;We're all done.
|
||
|
||
initw: camn tt,pwdone ;wait till someone else's init is finished.
|
||
jrst initd ; yes, they finished already.
|
||
type dspc,/APassword database being initialized by another program.
|
||
Please wait.
|
||
/
|
||
movei t,30.
|
||
.sleep a, ;also consider that the job doing the
|
||
move t,tt ;init'ing may have aborted.
|
||
jrst init0 ;so go back to try it again just in case.
|
||
|
||
initd: syscal corblk,[cnti %cbndr ;back to read-only
|
||
argi 0
|
||
argi %jself
|
||
argi pwpage]
|
||
loss
|
||
syscal pgwrit,[argi pwpage] ; Make sure the disk copy is up to date
|
||
loss ; too
|
||
syscal dskupd,[argi pwdc] ;update creation date, etc.
|
||
loss ; Why would this fail?
|
||
ret
|
||
|
||
constants
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;;;;
|
||
;;;; Lock manipulation routines.
|
||
;;;;
|
||
;;;; LOCK is the multi-purpose entry, which takes the address of the lock in D
|
||
;;;; PLOCK is the entry for locking the password database.
|
||
;;;;
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
||
plock: .suset [.sdf1,,[-1]] ;prepare to lock the database
|
||
.suset [.sdf2,,[-1]] ;defer interrupts
|
||
call pwdopn ;access the database again
|
||
movei d,pwlock ;lock the database
|
||
lock: syscal corblk,[cnti %cbndw ;make it writeable again
|
||
argi 0
|
||
argi %jself ;get into self
|
||
argi pwpage ;at our password file location
|
||
argi pwdc ;the 0th page of the pword file
|
||
argi 0]
|
||
loss
|
||
.suset [.ruind,,tt] ;get our user-index to identify ourself
|
||
skipl (d) ;wait for switch to be free.
|
||
.hang
|
||
aose (d) ;try to lock it.
|
||
jrst lock ;(somone else grabbed it between
|
||
;our .hang and our aose)
|
||
lock1: movem tt,pwlkid ;identify ourself as the culprit
|
||
move tt,loclst ;put the switch on the
|
||
hrli tt,(setom) ;locked switch list
|
||
movem tt,1(d) ;link it in
|
||
movem d,loclst ;and install it in the chain
|
||
|
||
lock2: .suset [.runame,,t] ;record who we are
|
||
movem t,pwuhak ;for debugging and delousing
|
||
.suset [.rjname,,t] ;ditto for JNAME
|
||
movem t,pwjhak
|
||
aos pwaccc ;count accesses, for STAT command
|
||
move t,pwrbfp
|
||
aobjp t,.+1
|
||
aobjp t,[movsi t,-pwrbfl ? jrst .+1]
|
||
movem t,pwrbfp
|
||
move x,pwuhak
|
||
movem x,pwrbuf(t)
|
||
move x,pxunam
|
||
movem x,pwrbuf+1(t)
|
||
|
||
ret ;it's locked, continue
|
||
|
||
;; This routine will set up the switch as a switch block, and make
|
||
;; loclst point to it. The contents of the switch block will be:
|
||
;;
|
||
;; 0 ;This word is the switch itself!
|
||
;; SETOM <previous contents of loclst>
|
||
;; ;The SETOM is the unlock instruction.
|
||
;; ;The RH has nothing to do with the SETOM;
|
||
;; ;it points to the next block of the list.
|
||
;;
|
||
;; Note that the HRLI instruction is superfluous, because 0 in the
|
||
;; left half of the second word of the block is the same as (SETOM).
|
||
;;
|
||
;; The three instructions starting at LOCK1 are critical because
|
||
;; the switch has been locked but is not on the locked switch list.
|
||
;; Therefore, an entry in the critical routine table of the form
|
||
;;
|
||
;; LOCK1,,LOCK2
|
||
;; SETOM @t
|
||
;;
|
||
;; is needed, in case the job is killed while executing there.
|
||
|
||
|
||
;;;; 2. UNLOCKING AN AOSE-STYLE SWITCH.
|
||
|
||
;; The correct way to unlock a switch follows:
|
||
;; (assuming that A points to the switch block and that
|
||
;; the switch block is the first item on the locked switch list).
|
||
|
||
;; This has gross bug of removing anything on the list from top to the
|
||
;; switch being removed. Thus, before using any more locks, I should fix
|
||
;; it. but it came from .INFO.;ITS LOCKS, so foo!
|
||
|
||
unlock: save [tt]
|
||
hrrz tt,1(d) ;remove the switch from the
|
||
movem tt,loclst ;locked switch list.
|
||
unloc1: setom (d) ;then unlock the switch.
|
||
unloc2: syscal corblk,[cnti %cbndr ;make read only
|
||
argi 0
|
||
argi %jself
|
||
argi pwpage]
|
||
loss
|
||
syscal pgwrit,[argi pwpage] ; Update the lock page on disk
|
||
loss
|
||
restore [tt]
|
||
ret
|
||
|
||
pulock: save [d]
|
||
movei d,pwlock ;unlock the database
|
||
call unlock
|
||
syscal pgwrit,[argi pwpage] ; Make sure the disk copy is up to date
|
||
loss
|
||
.suset [.sdf1,,[0]]
|
||
.suset [.sdf2,,[0]] ;undefer interruputs
|
||
syscal dskupd,[argi pwdc] ;update creation date, etc.
|
||
loss ; Why would this fail?
|
||
.close pwdc,
|
||
restore [d]
|
||
ret
|
||
|
||
;; The instruction at UNLOC1 is critical because the switch is
|
||
;; locked but not on the locked switch list. Therefore, an entry
|
||
;; is needed in the critical routine table as follows:
|
||
|
||
;; UNLOC1,,UNLOC2
|
||
;; SETOM @t
|
||
|
||
|
||
;;;; This is the critical routine table
|
||
|
||
critic: init1,,init2 ;from init1 to init2 the database has been
|
||
movem tt,pwinit ;marked as being inited. If killed undo it
|
||
|
||
unloc1,,unloc2 ;Here the lock has been removed from chain
|
||
setom @tt ;but is still locked.
|
||
lock1,,lock2 ;Here, the switch is locked, but we are
|
||
setom @tt ;still in the process of putting it on the
|
||
;chain
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;;;;
|
||
;;;; Password encryption and lookup/insert routines.
|
||
;;;;
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
||
|
||
;;; This encrypts the contents of PWBUF into the format it is in the file
|
||
;;; The result is returned in T and in PDPASS
|
||
|
||
pwdmak: save [a,b,c,d]
|
||
call ustrip ;get the UNAME in TT, stripped of digits
|
||
skipn tt ;is there something there?
|
||
error /Null UNAME!/
|
||
movem tt,pxunam ;remember who we're hacking
|
||
move x,pwbuf ;grab the pword into one word
|
||
xor x,pwbuf+1 ;xor'd into the other
|
||
rot x,31 ;rotate it oddly
|
||
add x,TT ;mix the UNAME in with the mess
|
||
addi x,736251 ;garble it some more
|
||
setz a, ;clear what we'll accumulate
|
||
setz b,
|
||
move c,pwbuf ;gobble them down
|
||
move d,pwbuf+1
|
||
movei e,110 ;Stir well
|
||
pwdma0: trnn x,1 ;odd?
|
||
jrst [rot x,-1 ; not odd enough, make it odder
|
||
rotc a,1 ; gyrate wildly
|
||
sojg e,pwdma0 ; rock and roll
|
||
move t,a ; T is answer
|
||
movem t,pdpass
|
||
jrst pwdma9 ]
|
||
add a,c
|
||
add b,d
|
||
rotc a,1 ;mixed up?
|
||
rot x,-1 ;you ain't seen nothing yet
|
||
sojge e,pwdma0 ;brain salad surgery
|
||
move t,a ;T is the answer
|
||
add t,b ; But the T shuts down by 1:00 am
|
||
movem t,pdpass
|
||
pwdma9: restore [d,c,b,a]
|
||
ret ;that's the whole password
|
||
|
||
;;; PWDUMK encodes the UNAME in it's trivial reversable fashion
|
||
;;; returns result in TT, and PDUNAM
|
||
;;; PWDUMS is the same, bug first strips off any final digit.
|
||
|
||
pwdums: call ustrip ;strip the UNAME
|
||
caia ;got it already, don't gobble again
|
||
pwdumk: move tt,uname ;gobble down the UNAME
|
||
rot tt,13 ;mix it up a bit too
|
||
add tt,[742532,,732643] ;Will oddities never cease?
|
||
ret ;return for refund
|
||
|
||
|
||
ustrip: save [T,A] ;a couple of AC's to play with
|
||
move t,uname ;gobble UNAME
|
||
movei a,5 ;don't strip single character frobs!
|
||
setz tt,
|
||
ustrp0: lshc t,-6 ;check final position
|
||
caie tt, ;Got the last character?
|
||
jrst [lsh tt,-36 ; right-align it
|
||
cail tt,'0 ; is it a digit?
|
||
caile tt,'9
|
||
caia ; nope
|
||
jrst [move tt,t ; get it in TT, where we expect it
|
||
movei t,6
|
||
sub t,a
|
||
imuli t,6 ; yep, calculate how many real bits
|
||
lsh tt,(t) ; re-align left, without digit
|
||
restore [A,T]
|
||
ret] ; and take the express bus, we're set
|
||
move tt,uname ; not ending in digit, return whole UNAME
|
||
restore [A,T]
|
||
ret] ; It doesn't end in a digit, so OK.
|
||
sojge a,ustrp0 ; do it again!
|
||
move tt,uname ; not ending in digit, return this tiny
|
||
;UNAME
|
||
restore [A,T]
|
||
ret
|
||
|
||
;;; PWDCNS conses up an entry in PDATA buffer. It takes a UNAME
|
||
;;; un UNAME, a password in PWBUF, and initializes the flags according
|
||
;;; to the machine's defaults.
|
||
;;; PWDCID sets the creator and creation-date fields.
|
||
|
||
pwdcid: save [x,tt]
|
||
jrst pwdcd0
|
||
|
||
pwdcns: save [x,tt]
|
||
call pwdums ;cons UNAME
|
||
call pwdmak ;cons password
|
||
setzm pdmore ;extra word initially 0
|
||
hrlzi x,%pfnew ;get the default flags
|
||
movem pdflag ;and make them ours
|
||
setzm pdinfo
|
||
setom pddate
|
||
pwdcd0: call crtidx ; Get our creator index into TT
|
||
dpb tt,[pi$crt pdinfo] ; put that into the entry
|
||
syscal RQDATE,[val x]
|
||
loss
|
||
hllm x,pddate ; Put today's date in creator date
|
||
restore [tt,x]
|
||
ret
|
||
|
||
;;; PWDINI expects a UNAME in UNAME, and a password in PWBUF, and either
|
||
;;; returns the entry for that UNAME in PDATA or a new entry in PDATA if there
|
||
;;; was no entry for that UNAME
|
||
|
||
PWDINI: call pwdlok ;find it
|
||
pjrst pwdcns ; not there, cons it up
|
||
pjrst pwdget ;It's there, get it
|
||
|
||
|
||
;;; this opens the password file
|
||
;;; It must be done before any attempt can be made to make it writable
|
||
|
||
pwdopn: syscal open,[cnti .uii ;for input
|
||
argi pwdc ;open on the p-word channel
|
||
pw.dev
|
||
pw.fn1
|
||
pw.fn2
|
||
pw.snm]
|
||
ERROR /Can't access password file!/
|
||
syscal sdmpbt,[argi pwdc ? argi 0] ;clear dump bit, so always back up
|
||
loss
|
||
ret
|
||
|
||
;;; this maps in the password file for reading
|
||
.upure
|
||
pwmapd: 0 ; -1 if file mapped
|
||
.pure
|
||
|
||
pwdmap: skipe pwmapd ; Have we already mapped it?
|
||
ret ; Yes, don't bother repeating
|
||
call pwdopn ;open the file
|
||
syscal fillen,[argi pwdc ? val t] ;get how long the bastard is
|
||
ERROR /Can't get length of password file!/
|
||
save [t,tt]
|
||
addi t,1777 ;convert words to pages
|
||
idivi t,2000
|
||
movn tt,t ;and convert to AOBJN ptr to file
|
||
hrlz tt,tt ;, length in left half
|
||
movei t,pwpage ;and do same for the core side of things
|
||
hll t,tt ;from there to here
|
||
syscal corblk,[cnti %cbndr ;get read access.
|
||
argi 0
|
||
argi %jself
|
||
t
|
||
argi pwdc
|
||
tt]
|
||
ERROR /Can't map password file!/
|
||
|
||
call init ;make sure it's up to date.
|
||
.close pwdc, ;close it up, we don't need it any more!
|
||
setom pwmapd ; Note we've mapped it
|
||
restore [tt,t]
|
||
ret
|
||
|
||
;;; PWDLOK looks up a UNAME in the database, returns the pointer to
|
||
;;; the entry in A
|
||
;;; PWDLK0 is an alternate entry for pre-computed UNAMEs
|
||
;;; PWDLKX is alternate entry for not striping the UNAME. for PWDEL.
|
||
|
||
pwdlkx: call pwdumk ;don't strip uname
|
||
jrst pwdlk5
|
||
|
||
pwdlk0: move tt,pdunam ;get the pre-computed UNAME garbled in TT
|
||
caia ;don't get it again.
|
||
|
||
pwdlok: call pwdums ;get the UNAME garbled in TT
|
||
pwdlk5: setz a, ;count the entries
|
||
pwdlk1: camn tt,pwname(a) ;is this our UNAME?
|
||
jrst popj1 ; just find it, don't move it
|
||
addi a,pwleng ;move to next entry
|
||
camle a,pwcnt ;have we reached the end?
|
||
jrst [movem tt,pdunam ; failure return, remember who we wanted
|
||
ret] ; failed
|
||
jrst pwdlk1 ;not at end, keep looking
|
||
|
||
|
||
;;; PWDGET takes a pointer to the entry in A, and moves it to the buffer
|
||
;;; it first does an error check.
|
||
pwdget: movem a,pdloc ; Remember where we got it from
|
||
trne a,3 ;Is this a multiple of 4?
|
||
ERROR /Bad database pointer in PWDGET/
|
||
hrlzi x,pwname(a) ;set up to BLT
|
||
hrri x,pdata ;the info on this person to our buffer
|
||
blt x,pdata+pwleng-1 ;to the Bahamas
|
||
move x,pwname(a) ;get the name...
|
||
pwdunm: sub x,[742532,,732643] ;Will oddities never cease?
|
||
rot x,-13
|
||
movem x,uname ;save it for later
|
||
ret
|
||
|
||
;;; This routine computes our creator index, adding us to the table of
|
||
;;; administrators if needed
|
||
|
||
crtidx: save [x,t,a,b]
|
||
movei a,pwadmn ; table of people who have modified entries
|
||
call pwsget ; Get the table of entries
|
||
hlre b,runame ; Check out this for unloggedinness
|
||
aoje b,[ move x,[sixbit /___NNN/]
|
||
jrst crtida ]
|
||
move x,runame
|
||
crtida: move b,t ; Remember this AOBJN ptr
|
||
setz tt, ; Entry #
|
||
crtid0: camn x,(t) ; Is this us?
|
||
jrst crtid1 ; Yes
|
||
aos tt ; count the entries
|
||
aobjn t,crtid0 ; Next entry
|
||
movem x,tmpbuf(tt) ; Make this the next entry
|
||
sub b,[1,,0] ; grow the AOBJN ptr
|
||
movei a,pwadmn
|
||
call pwsput ; put the table back into the database
|
||
crtid1: restore [b,a,t,x]
|
||
aos tt ; 0 means unknown
|
||
ret
|
||
|
||
;;; This routine installs a password into the database.
|
||
;;; It takes it's data in the PDATA buffer.
|
||
;;; The protocol is to ALWAYS look up the entry AFTER
|
||
;;; locking the database.
|
||
|
||
pwdput: save [x,t,tt,a,b]
|
||
IFN $$PAND,[
|
||
syscal RQDATE,[val t]
|
||
loss
|
||
hllm t,pdmod ; Remember the modification date
|
||
call crtidx ; Get the creator index in TT
|
||
|
||
pwdpt1: dpb tt,[pi$mod pdinfo] ; Store who modified this entry
|
||
|
||
] ; END of IFN $$PAND,
|
||
|
||
call plock ;Open and lock the password database
|
||
call pwdlk0 ;does the entry exist?
|
||
do [ move a,pwcnt ; so grab the count
|
||
movei a,pwleng(a)] ; and move to the next case
|
||
|
||
movei t,(a) ;Get pointer where we expect it
|
||
tlze t,pwleng-1 ;it must not be odd
|
||
jrst [ movem t,pwcnt ; so straighten it out
|
||
call pulock ; close up the database
|
||
error /Odd length password file./]
|
||
|
||
idivi t,2000 ;T now has page # wrt pwdata
|
||
movei t,pdpage(t) ;Get page # in the file
|
||
hrlzi x,pdata ;construct a BLT word for the password data
|
||
hrri x,pwname(a) ;to where we want to put it.
|
||
syscal corblk,[cnti %cbndw ;gotta write it.
|
||
argi 0
|
||
argi %jself
|
||
argi pwpage(t)
|
||
argi pwdc
|
||
argi (t)]
|
||
jrst [call pulock
|
||
error /Can't write password file./]
|
||
|
||
blt x,pwdata+pwleng-1(a)
|
||
|
||
syscal corblk,[cnti %cbndr ;make read-only again
|
||
argi 0
|
||
argi %jself
|
||
argi pwpage(t)]
|
||
loss ;eh? We're all fucked up!
|
||
syscal pgwrit,[argi pwpage(t)] ; Update the disk copy
|
||
loss
|
||
camle a,pwcnt ;have we added anything?
|
||
movem a,pwcnt ; yes, be sure to save that
|
||
call pulock ; Unlock the database
|
||
restore [b,a,tt,t,x]
|
||
ret
|
||
|
||
;;; PWSGET -- get a string from the database string area.
|
||
;;; address of string pointer is taken in A, length is returned in A.
|
||
;;; T gets an AOBJN ptr to the data.
|
||
;;; Data is copied into TMPBUF.
|
||
|
||
PWSGET: save [d,x,tt]
|
||
call plock ; lock the database
|
||
move a,(a) ; Get the string pointer
|
||
hrli x,pwstr(a) ; Get address of string
|
||
hrri x,tmpbuf ; where to put it
|
||
hlre a,a ; -<length>
|
||
movns a ; <length>
|
||
setzm tmpbuf ; Always have a 0 there in case null string
|
||
jumpe a,pwsgt0 ; if nothing to move, don't try
|
||
blt x,tmpbuf-1(a) ; Move the data into TMPBUF
|
||
pwsgt0: movn t,a ; create an AOBJN ptr to data for T
|
||
hrl t,t
|
||
hrri t,tmpbuf
|
||
call pulock ; Unlock the database
|
||
restore [tt,x,d]
|
||
ret
|
||
|
||
;;; PWSPUT writes data into the database string area.
|
||
;;; IN A is the address of the database entry to store ptr into.
|
||
;;; IN B is AOBJN to data to be installed
|
||
|
||
; String Space. This is divided into thre consing areas, NEW, OLD, and NEXT
|
||
; When NEW is filled, all pointers into OLD are copied into NEXT space, which
|
||
; then becomes the NEW space. The old NEW space, not suprisingly, becomes the
|
||
; OLD space. This is done to avoid half-moved strings, to guarantee consistancy
|
||
; at all times. Strings are pointed to by AOBJN ptrs, relative to PWSTR. The
|
||
; AOBJN ptrs are examined and updated only with the database locked, and are
|
||
; updated only after any necessary copying is done. Each consing area is 2 pgs
|
||
; long.
|
||
|
||
PWSPUT: save [d,x,t,tt]
|
||
push sp,a
|
||
call plock ; Database MUST BE LOCKED
|
||
skipe pwsgcp ; Is there a GC in progess?
|
||
call pwsgc ; Yes, GC first!
|
||
setz a, ; No full GC done yet
|
||
pwspt0: hlre t,b ; get -<size>
|
||
jumpge t,pwspte ; empty, just zero it
|
||
hlre x,pwsptr ; Get -<room>
|
||
sub x,t ; get -<room left>
|
||
jumpg x,[ caile a,1 ; GC failed?
|
||
jrst pwsgcf ; Complain about it
|
||
call pwsgc ; full, gotta GC first
|
||
aos a ; say we've already GC'd
|
||
jrst pwspt0]
|
||
hrrz tt,pwsptr ; get pwstr offset of free area
|
||
movei d,(tt) ; copy for our consed ptr
|
||
sub tt,t ; get new pwstr offset of remaining free
|
||
hrl tt,x ; get new free AOBJN ptr
|
||
movem tt,pwsptr ; update it in single instruction
|
||
hrli d,(t) ; get AOBJN ptr to newly consed string
|
||
movei x,pwstr(d) ; prepare to put the data there
|
||
hrl x,b ; from our given string
|
||
move tt,d ; Copy our AOBJN ptr to store when done
|
||
sub d,t ; get idx of word after our string
|
||
save [t,tt]
|
||
hrrz t,x ; first page to be hacked
|
||
lsh t,-12 ; page # within job
|
||
subi t,pwpage ; page # within file
|
||
movei tt,pwstr-1(d) ; addr within job of last word
|
||
lsh tt,-12 ; page # within job of last word
|
||
subi tt,pwpage ; page # of last word
|
||
syscal corblk,[ argi %cbndr\%cbndw
|
||
argi %jself
|
||
argi pwpage(t) ; page # within job
|
||
argi pwdc
|
||
argi (t)]
|
||
loss
|
||
camn t,tt ; are they on the same page?
|
||
jrst pwspt2
|
||
syscal corblk,[ argi %cbndr\%cbndw
|
||
argi %jself
|
||
argi pwpage(tt) ; page # within job
|
||
argi pwdc
|
||
argi (tt)] ; page # within file
|
||
loss
|
||
pwspt2: blt x,pwstr-1(d) ; Move it!
|
||
syscal pgwrit,[ argi pwpage(t) ] ; Write the page
|
||
loss
|
||
camn t,tt ; Are they on the same page?
|
||
jrst pwspt3 ; yes
|
||
syscal pgwrit,[ argi pwpage(tt) ] ; no, hack the second one too
|
||
loss
|
||
pwspt3: restore [tt,t]
|
||
pop sp,a
|
||
movem tt,(a) ; Store our now-valid pointer
|
||
pwspt4: call pulock ; unlock the database
|
||
restore [tt,t,x,d]
|
||
ret
|
||
|
||
pwspte: pop sp,a
|
||
setzm (a) ; No more string
|
||
jrst pwspt4
|
||
|
||
;; now we gotta GC
|
||
pwsgc: save [x,t,tt,a,b,c,d,e]
|
||
hrrz d,pwsptr ; Let's see which space is NEW
|
||
caige d,pistr0+pstrln ; Is NEW space = 0?
|
||
jrst [ movei d,pistr0 ; NEW space = 0
|
||
movei a,pistr1 ; NEXT space = 1
|
||
movei b,pistr2 ; and OLD space = 2
|
||
jrst pwsgca]
|
||
caige d,pistr1+pstrln ; Is NEW space = 1
|
||
jrst [ movei d,pistr1 ; NEW space = 1
|
||
movei a,pistr2 ; NEXT space = 2
|
||
movei b,pistr0 ; and OLD space = 0
|
||
jrst pwsgca]
|
||
caige d,pistr2+pstrln
|
||
jrst [ movei d,pistr2 ; NEW space = 2
|
||
movei a,pistr0 ; NEXT space = 0
|
||
movei b,pistr1 ; and OLD space = 1
|
||
jrst pwsgca]
|
||
error /Illegal String space pointer in PWSGC/
|
||
|
||
;; state now is that OLD is in B, NEW in D, and NEXT in A
|
||
pwsgca: hrli a,-pstrln ; make an AOBJN ptr to NEXT space
|
||
skipn c,pwsgcp ; If GC not in progress
|
||
movem a,pwsgcp ; remember our GC pointer
|
||
skipe c ; If GC *WAS in progress
|
||
move a,c ; use the old GC pointer
|
||
movei t,(a) ; Compute page # of NEXT space in string
|
||
idivi t,2000 ; space
|
||
syscal CORBLK,[ argi %cbndr\%cbndw ; Need read and write
|
||
argi %jself
|
||
argi pwpage+pwstpg(t) ; NEXT space page 0
|
||
argi pwdc
|
||
argi pwstpg(t)]
|
||
loss
|
||
syscal CORBLK,[ argi %cbndr\%cbndw
|
||
argi %jself
|
||
argi pwpage+pwstpg+1(t) ; NEXT space page 1
|
||
argi pwdc
|
||
argi pwstpg+1(t)]
|
||
loss
|
||
|
||
move t,[-pwstln,,pwstbg] ; AOBJN ptr to strings to be GC'ed
|
||
|
||
pwsgc0: skipl c,(t) ; Is there a string here?
|
||
jrst pwsgc1 ; no, ignore it
|
||
movei x,(c) ; Get the index portion
|
||
trz x,pstrln-1 ; Flush where in space it is
|
||
caie x,(a) ; Is it already in NEXT space? Aborted GC
|
||
cain x,(d) ; Is it in NEW space?
|
||
jrst pwsgc1 ; yes, ignore it
|
||
caie x,(b) ; Is it in OLD space?
|
||
error /Gubbish database-string pointer./
|
||
move e,a ; Remember un-updated pointer
|
||
hlre x,a ; Get -<room>
|
||
hlre tt,c ; Get -<length>
|
||
movns tt ; <length>
|
||
add x,tt ; Get -<remaining room>
|
||
jumpge x,pwsgcf ; If no room, go complain
|
||
hrl a,x ; Update the amount of room
|
||
addi a,(tt) ; Update the pointer
|
||
movem a,pwsgcp ; Update it in memory
|
||
movei x,pwstr(e) ; Get address to move to
|
||
hrli x,pwstr(c) ; Address to move from
|
||
blt x,pwstr-1(a) ; Move it!
|
||
hll e,c ; Put length into AOBJN ptr
|
||
movem e,(t) ; store the updated pointer
|
||
pwsgc1: aobjn t,pwsgc0 ; Next!
|
||
movem a,pwsptr ; Be sure pointer is updated in memory
|
||
setzm pwsgcp ; Saw we've finished our GC
|
||
restore [e,d,c,b,a,tt,t,x]
|
||
ret
|
||
|
||
; GC failure
|
||
pwsgcf: type dspc,/AString space in the database is full. You'll have
|
||
to make room first.
|
||
/
|
||
call pulock
|
||
jrst quit
|
||
|
||
|
||
ifn $$PAND,[
|
||
|
||
;;; PWSTXT reads text from the terminal and stores it into string space
|
||
;;; A contains address of AOBJN ptr to hack
|
||
;;; Skip-returns if successful
|
||
|
||
pwstxt: save [b]
|
||
save [a]
|
||
type dspc,/Enter text, end with ^C
|
||
/
|
||
call readtx ; Read in the text
|
||
jrst pwstxx
|
||
pwstx0: restore [a] ; where to put it
|
||
movn t,argcnt
|
||
subi t,4
|
||
idivi t,5 ; get -<# of words required>
|
||
camn tt,[-4] ; Was it a multiple of 5 characters?
|
||
jumpn t,[ movns t ; <# of words required>
|
||
setzm msgbuf(t) ; make into an ASCIZ string
|
||
aos t ; including room for it
|
||
movns t
|
||
jrst pwstx1]
|
||
pwstx1: hrl b,t ; build an AOBJN ptr
|
||
hrri b,msgbuf
|
||
call pwsput ; put it into the database
|
||
restore [b]
|
||
jrst popj1
|
||
|
||
pwstxx: restore [a]
|
||
restore [b]
|
||
ret
|
||
|
||
pwslin: save [b]
|
||
save [a]
|
||
type dspc,/AEnter 1 line of text: /
|
||
move bp,[440700,,msgbuf]
|
||
call readln
|
||
jrst pwstxx
|
||
jrst pwstx0
|
||
|
||
|
||
] ; END -- IFN $$PAND,
|
||
|
||
pwgtxt: save [a,b]
|
||
call pwsget
|
||
ifn $$PAND,[
|
||
type dspc,/A [/
|
||
10type tyoc,a
|
||
type tyoc,/ words long]
|
||
/
|
||
] ; END of IFN $$PAND,
|
||
|
||
output tyoc,tmpbuf
|
||
restore [b,a]
|
||
ret
|
||
|
||
|
||
ife $$PAND,[
|
||
;;; This routine expects that PWDGET has been called
|
||
|
||
syschk: move x,pdflag ;fetch the flag word
|
||
tlne x,%pfbad ;is logging in from loser sites ok?
|
||
call sitchk ; no, check it out!
|
||
|
||
ldb x,[pi$sta pdinfo] ; Get the account state
|
||
cain x,ps%new ; State=new?
|
||
error /State = PS%NEW, account should never be in this state/
|
||
cain x,ps%apl ;has he applied for an account?
|
||
jrst [setzm ttyflg ; be sure he sees this
|
||
type dspc,/AYour application has not yet been processed.
|
||
Please try later.
|
||
/
|
||
jrst sysrfs]
|
||
cain x,ps%sys ;is it a system name?
|
||
jrst [type dspc,/AThat is a reserved name, please choose another.
|
||
/
|
||
jrst sysrfs]
|
||
|
||
caie x,ps%rfs
|
||
cain x,ps%hld
|
||
jrst prob
|
||
cain x,ps%off
|
||
jrst prob
|
||
jrst popj1 ; nope, no problem
|
||
cain x,ps%off ; Is it turned off?
|
||
jrst popj1 ; nope, no problem
|
||
prob: type dspc,/AThat account has been /
|
||
move t,uname ; UNAME will be used as the FN2
|
||
cain x,ps%rfs ;refused?
|
||
jrst [ type tyoc,/denied.
|
||
/
|
||
movei b,rfsnam
|
||
call prtrsn
|
||
jrst rfsnot] ; Note that the refuse has been seen
|
||
cain x,ps%off
|
||
jrst [ type tyoc,/temporarily turned off.
|
||
/
|
||
movei b,offnam
|
||
call prtrsn
|
||
jrst rfsnot] ; Note that the refuse has been seen
|
||
|
||
cain x,ps%hld
|
||
jrst [ type tyoc,/placed on hold.
|
||
/
|
||
movei b,hldnam
|
||
call prtrsn
|
||
jrst rfsnot]
|
||
|
||
error /Unknown account state/
|
||
|
||
prtrsn: call fn2opn
|
||
jrst sysrfs
|
||
type tyoc,/Reason:
|
||
/
|
||
call printf
|
||
|
||
sysrfs: type dspc,/AAny questions may be directed to USER-ACCOUNTS
|
||
/
|
||
ret
|
||
|
||
|
||
;; Note in flag word that he's seen this message
|
||
|
||
rfsnot: movsi x,%pfmsg
|
||
iorm x,pdflag
|
||
jrst pwdput
|
||
|
||
;;; SITCHK checks if a login is from a bad site and if it is, it flushes the
|
||
;;; imposter.
|
||
|
||
sitchk: movei a,losers ; AOBJN ptr for the table of losers
|
||
call pwsget ; get the data from the database
|
||
jumpe a,cpopj ; Check for empty BAD sites list.
|
||
move tt,fhost ;where are we from?
|
||
sitch1: camn tt,(t) ;is it a loser?
|
||
jrst [.suset [.smsk2,,[0]] ;no interrupts!
|
||
.reset dspc, ;reset output
|
||
.reset tyic, ;reset input
|
||
terpri
|
||
6type tyoc,uname
|
||
type tyoc,/ is restricted to the local area.
|
||
/
|
||
move x,uname ;pretend the xuname is the uname
|
||
movem x,pxuname
|
||
call pwdwrn ;note this failure
|
||
phaser]
|
||
aobjn t,sitch1
|
||
ret ;ok!
|
||
|
||
;;; DILTIM fails if a user is not authorized for this system load or this
|
||
;;; line. It expects PWDGET to have been called
|
||
|
||
diltim: ldb x,[pi$sta pdinfo] ; Get the account state
|
||
cain x,ps%apl ;has he just applied?
|
||
jrst popj1 ; don't hack him
|
||
move x,pdflag
|
||
tlne x,%pfdil ;is he authorized for dialup?
|
||
pjrst timchk ; yes, just check on the time
|
||
ldb a,[pi$grp pdinfo] ; Get our group
|
||
movei tt,1 ; start with one bit
|
||
lsh tt,(a) ; get the bit to check
|
||
tdnn tt,pwgdil ; Is this group priveleged?
|
||
pjrst timchk ; yes, let him on
|
||
|
||
movei tt,1 ;start with one bit
|
||
|
||
move a,consol ;get consol # for bit shift
|
||
lshc t,(a) ;shift it to it's position
|
||
tdnn tt,dltty0 ;is it a dialup?
|
||
tdne t,dltty1
|
||
jrst [ ldb a,[pi$grp pdinfo] ; Get our group
|
||
movei a,dilmsg(a) ; Get address of message AOBJN ptr
|
||
call pwgtxt ; Print the message
|
||
jrst sysrfs]
|
||
|
||
timchk: skipn pwholp ;If this is a holiday
|
||
tlne x,%pfday ; Or if he authorized for daytime
|
||
jrst popj1 ; Let him go
|
||
.ryear t, ;Check out the date
|
||
ldb x,[320300,,t] ;Get the day of the week
|
||
syscal rqdate,[val b] ; Disk date
|
||
seto b,
|
||
camn b,[-1] ;Does the system know the time?
|
||
jrst [type dspc,/AThe system does not yet know the time, you cannot yet log in.
|
||
Please wait. Someone is still in the process of bringing up the system,
|
||
and will soon fix the them, when you can log in.
|
||
/
|
||
jrst sysrfs]
|
||
ldb a,[pi$grp pdinfo] ; Get the group index for this user
|
||
movei t,(b) ; Get the time of day
|
||
movss b ; Get the date in RH
|
||
idivi t,2*60.*30. ; get # of 1/2 hours after midnight
|
||
movei ct,6 ; let's look at the six exception dates
|
||
move d,[442200,,pwordt] ; Byte Pointer to exception dates
|
||
exday0: ldb tt,d ; Get an exception date
|
||
cain tt,(b) ; Is this the exception date?
|
||
jrst exday ; yes, handle as exception
|
||
sojg ct,exday0
|
||
|
||
setz d, ; assume weekday
|
||
cain x,0 ; is it Sunday?
|
||
movei d,1
|
||
cain x,6 ; or Saturday?
|
||
movei d,2
|
||
ldb c,[ dm$wds pwgrdm(a) ; Get start time
|
||
dm$sns pwgrdm(a)
|
||
dm$sts pwgrdm(a)](d)
|
||
|
||
ldb d,[ dm$wde pwgrdm(a) ; Get end time
|
||
dm$sne pwgrdm(a)
|
||
dm$ste pwgrdm(a)](d)
|
||
cain c,77 ; no restriction on time-of-day?
|
||
jrst popj1 ; Yes, let him on!
|
||
caml t,c ; Is it earlier than the restricted period?
|
||
caml t,d ; or later than it?
|
||
jrst popj1 ; yes, let him on.
|
||
terpri
|
||
movei a,timmsg(a)
|
||
call pwgtxt ; type it
|
||
jrst sysrfs
|
||
|
||
exday: movei tt,6 ; # of override dates
|
||
sub tt,ct ; get override date #
|
||
imuli tt,-6 ; # of bits
|
||
move c,pwgors(a) ; Get the override start times for our grp
|
||
lsh c,(tt) ; Position this date's at bottom
|
||
move d,pwgore(a) ; Get the override end times
|
||
lsh d,(tt) ; Position this date's at bottom
|
||
andi c,77 ; Flush all others
|
||
andi d,77
|
||
cain c,77 ; no restriction on time-of-day?
|
||
jrst popj1 ; Yes, let him on!
|
||
caml t,c ; Is it earlier than the restricted period?
|
||
camle t,d ; or later than it?
|
||
jrst popj1 ; yes, let him on.
|
||
terpri
|
||
|
||
imuli tt,20 ; get idx for table of grp*date messages
|
||
addi tt,a ; get index of our message
|
||
movei a,timmsg(a) ; If no special message, print the usual...
|
||
skipe ovrmsg(tt) ; Get the message for this group today
|
||
movei a,ovrmsg(tt)
|
||
call pwgtxt
|
||
jrst sysrfs
|
||
|
||
] ; END IFE $$PAND
|
||
|
||
ifn $$pand,[
|
||
spew: call pwread
|
||
.logout 1,
|
||
move x,[sixbit /FOO/]
|
||
movem x,uname
|
||
call pwdmak
|
||
ret
|
||
]; end ifn $$pand
|
||
|
||
|
||
;;; Routine to read a password.
|
||
|
||
pwprmp: type dspc,/APassword: /
|
||
ife $$PAND,[
|
||
move x,crgbts ;gotta get it again, TYPE flushes X
|
||
trne x,cf$lms ;is he paranoid?
|
||
type dspc,/##%##&##$##=H*%**&**$**=*H%@#&@#$@#=@#H/
|
||
]
|
||
ret
|
||
|
||
pwread: setzm ttyflg ;turn on typeout so this is sure to be seen!
|
||
move x,[call pwprmp] ;on re-display, re-prompt
|
||
movem x,dsprmp
|
||
call pwprmp
|
||
setz count, ;count them
|
||
move t,[440600,,pwbuf] ;point into our buffer
|
||
setzm pwbuf ;clear out our buffer
|
||
setzm pwbuf+1 ;so that anything at the end is blank
|
||
|
||
pwrlop: tyi ;get a character
|
||
ret ; quiting, return
|
||
jrst [type dspc,/A(Enter your password, end with a carriage return)/
|
||
jrst pwread] ;tell him what's what and ask again
|
||
|
||
jrst [sosge count ; keep track of count
|
||
jrst [movei d,11. ; over-rubout
|
||
call wipe ; so wipe it out
|
||
setzm dsprmp ; and no more funny prompt
|
||
terpri ; don't wait to go to next line
|
||
ret] ; return to caller as failure
|
||
setz ch, ; clear out that char from our buffer
|
||
dpb ch,t ; so that it doesn't lose if end
|
||
decbp6 t ; and back up.
|
||
jrst pwrlop] ; still in the running, gobble another
|
||
|
||
caie ch,^M ;is it a CR
|
||
cain ch,^C ; or a ^C
|
||
jrst [setzm dsprmp ; yes, no more funny prompt
|
||
jrst popj1] ; then we've won!
|
||
|
||
caige ch,140 ;Convert to 6bit: if it's small
|
||
subi ch,40 ;convert it so numbers work out right
|
||
|
||
aos count
|
||
caig count,14 ;if we've not had our fill
|
||
idpb ch,t ; deposit this in our account
|
||
jrst pwrlop ;and gobble down more.
|
||
|
||
;;; PWASK asks for a password, and skips if correct, and tries again if not
|
||
|
||
pwask: call pwdak1
|
||
jrst [type dspc,/AIncorrect.
|
||
/
|
||
call pwdwrn
|
||
call pwdak1
|
||
pjrst pwdwrn ; warn account of lossage!
|
||
jrst popj1]
|
||
jrst popj1
|
||
|
||
pwdak1: call pwread ;read the password
|
||
jrst pwdak1 ; just return if he quits or rubs out
|
||
push sp,pdpass ;save the real password
|
||
call pwdmak ;create the password he just gave
|
||
came t,(sp) ;is it the same as the saved one?
|
||
jrst [pop sp,pdpass ; restore real password
|
||
.reset tyic, ; flush typeahead, like multi-CR lossage
|
||
ret] ; and fail-return
|
||
pop sp,pdpass ;restore real password
|
||
jrst popj1 ;and success return
|
||
|
||
pwdwrn: skipn t,pxunam ;do we have a bug?
|
||
error /PWDWRN detected null PXUNAM/
|
||
|
||
logit: movei b,lognam
|
||
syscal open,[cnti .uao\100000 ;write over mode
|
||
argi dsko
|
||
(b)
|
||
1(b)
|
||
2(b)
|
||
3(b)]
|
||
ret ; if failed, don't bother.
|
||
syscal fillen,[argi dsko ? val x] ;get end position
|
||
ret
|
||
syscal access,[argi dsko ? x] ;and go there
|
||
ret
|
||
6type dsko,uname
|
||
.iot dsko,[^I]
|
||
output dsko,hstnam ; Output the foreign host name
|
||
skipe tipnum
|
||
jrst [ tyo dsko,["#]
|
||
8type dsko,tipnum
|
||
jrst .+1]
|
||
.iot dsko,[40]
|
||
8type dsko,consol
|
||
.iot dsko,[40]
|
||
call datime"timget ;get the time
|
||
push sp,a ;save the time word for later
|
||
call datime"timdow ;convert to day of week
|
||
|
||
output dsko,@datime"dowlng(b) ;print it into the file
|
||
type dsko,/, /
|
||
|
||
move d,[440700,,msgbuf] ;put the date down msgbuf
|
||
pop sp,a ;get thhe time word
|
||
call datime"timexp
|
||
output dsko,msgbuf ;output the stuff in the input buffer
|
||
skipl linkno ; is this under link?
|
||
call lnklog
|
||
type dsko,/
|
||
/
|
||
.close dsko,
|
||
ret
|
||
|
||
lnklog: type dsko,/ Link from TTY #/
|
||
8type dsko,linkno
|
||
type dsko,/, UNAME = /
|
||
6type dsko,linker
|
||
ret
|
||
|
||
ifn $$pand,[
|
||
|
||
pwdel: call plock ;lock the password database
|
||
call pwdlkx ;find the beggar
|
||
pjrst pulock ; trivial case, not there
|
||
movei t,(a) ;Get pointer where we expect it
|
||
tlne t,3 ;it must not be odd
|
||
jrst [call pulock ; unlock the password database
|
||
error /Odd length password file./]
|
||
idivi t,2000 ; T <= page # in data area
|
||
movei t,pdpage(t) ; Get page # in file
|
||
movei b,(t) ;save it for when we re-purify
|
||
syscal corblk,[cnti %cbndw ;gotta write it.
|
||
argi 0
|
||
argi %jself
|
||
argi pwpage(t)
|
||
argi pwdc
|
||
argi (t)]
|
||
jrst [call pulock ;unlock the password database
|
||
error /Can't write password file./]
|
||
move t,pwcnt
|
||
hrlzi tt,pwdata(t) ;LH(TT) <- pointer to last password
|
||
hrri tt,pwdata(a) ;RH(TT) <- new home for last password
|
||
blt tt,pwdata+pwleng-1(a) ;move one entry
|
||
move x,pwcnt
|
||
subi x,pwleng ;subtract off one entry from total
|
||
movem x,pwcnt
|
||
syscal corblk,[cnti %cbndr ;make read-only again
|
||
argi 0
|
||
argi %jself
|
||
argi pwpage(b)]
|
||
loss ;eh? We're all fucked up!
|
||
call pulock ;all done, unlock the database
|
||
jrst popj1 ;successful return
|
||
|
||
pwprul: call stinit
|
||
jfcl
|
||
call maplsr
|
||
setz d, ; start counting
|
||
pwpru0: movei a,lsrc
|
||
move x,pwname(d) ; Get the UNAME
|
||
call pwdunm ; un-decode it
|
||
move b,uname ; store it
|
||
call lsrtns"lsrunm ; Is he in INQUIR?
|
||
caia
|
||
jrst pwpru9 ; Yes, don't print it
|
||
call usrprt ; print the info on this user
|
||
ret ; typeing flushed
|
||
pwpru9: addi d,pwleng ; Next user
|
||
camg d,pwcnt ; are we at the end yet?
|
||
jrst pwpru0 ; Nope, keep on trukin'
|
||
pjrst pstats ; Yep, all done, so let's print some stats
|
||
|
||
|
||
;;; Routine to print out null-passwords users.
|
||
|
||
pwprnl: save [a,b]
|
||
call maplsr ; Ensure INQUIR mapped
|
||
setz d, ; D points to account entry
|
||
pwprn1: move a,d
|
||
call pwdget ; Fetch password and UNAME
|
||
move b,pdpass
|
||
setzm pwbuf ; Null password
|
||
setzm pwbuf+1
|
||
call pwdmak ; Get the encrypted form into T
|
||
camn t,b ; Same?
|
||
jrst [ call usrprt ; Yes - print info for this luser
|
||
jrst pwprn9 ; (typing flushed)
|
||
jrst .+1 ]
|
||
addi d,pwleng ; Pointer to next luser
|
||
camg d,pwcnt ; Are we at the end yet?
|
||
jrst pwprn1 ; Nope, keep on trukin'
|
||
pwprn9: restore [b,a]
|
||
ret
|
||
|
||
|
||
;;; Routine to print out never-logged-in users.
|
||
|
||
pwprnw: call stinit
|
||
jfcl
|
||
call maplsr
|
||
setz d, ; start counting
|
||
pwprw0: move x,pwflag ; Check the flags
|
||
tlnn x,%pfnew ; Has he ever logged in?
|
||
jrst pwprw9 ; Yes, don't print him
|
||
call usrprt ; print the info on this user
|
||
ret ; typeing flushed
|
||
pwprw9: addi d,pwleng ; Next user
|
||
camg d,pwcnt ; are we at the end yet?
|
||
jrst pwprw0 ; Nope, keep on trukin'
|
||
pjrst pstats ; Yep, all done, so let's print some stats
|
||
|
||
|
||
pwdprt: call stinit ;initialize statistics and print leading
|
||
;info
|
||
jfcl ; We've gotta grovel over them anyway...
|
||
type tyoc,/
|
||
Data follows:
|
||
/
|
||
setz d, ;start counting, bud.
|
||
move c,crgbts ;check out whether we are brief mode
|
||
trnn c,CF$PBF ;are we?
|
||
call maplsr
|
||
|
||
prtlop: skipe allflg ;are we printin extra info?
|
||
type dspc,/A_________________________
|
||
|
||
/
|
||
call usrprt ;print out the entry
|
||
ret ; typeing flushed
|
||
addi d,pwleng ;next entry
|
||
camg d,pwcnt ;are we at the end yet?
|
||
jrst prtlop ;keep on trukin'
|
||
pjrst pstats ; yep, all done, so let's print some stats
|
||
|
||
|
||
pwdsts: call stinit ;initialize status counts and print leading
|
||
pjrst pstats ;info
|
||
setz d, ;start counting, bud.
|
||
call maplsr
|
||
|
||
psdst1: move a,d ;PWDGET expects pointer in A
|
||
call pwdget ;get the entry to have stats counted
|
||
call gstats ;get the flag stats
|
||
movei a,lsrc ;tell LSRTNS what channel it can hack
|
||
move b,uname ;ask about this UNAME
|
||
call lsrtns"lsrunm ;is it there?
|
||
jrst [aos pnonam ; count how many of these there are
|
||
jrst psdst3] ; Don't hack INQUIR any more!
|
||
movem b,lsrptr ;save pointer to this entry
|
||
movei a,lsrtns"i$grp ;find his group
|
||
call lsrtns"lsritm
|
||
jrst [aos ptype ; count it
|
||
jrst psdst3] ; nothing to do
|
||
|
||
move t,a ;copy it
|
||
ildb ch,t ;check it out
|
||
cain ch,0 ;is it null?
|
||
jrst [aos ptype ; count it
|
||
jrst psdst3] ; and don't bother otherwise
|
||
|
||
cail ch,140 ;upper-casify
|
||
subi ch,100
|
||
subi ch,40 ;make it into 6bit
|
||
skipge ch ;make ssure it's in range
|
||
setz ch,
|
||
aos ptype(ch) ;count the beggar
|
||
psdst3: addi d,pwleng ;net one!
|
||
camg d,pwcnt ;are we at the end yet?
|
||
jrst psdst1 ;keep on trukin'
|
||
pjrst pstats ; yep, all done, so let's print some stats
|
||
|
||
|
||
stinit: tyo dspc,[^P] ;clear the screen
|
||
tyo dspc,["C]
|
||
move x,pwcnt ;check the count
|
||
trne x,3 ;is it off?
|
||
do [type tyoc,/
|
||
The count is out of phase!
|
||
Count = /
|
||
8type tyoc,pwcnt
|
||
]
|
||
type tyoc,/
|
||
Last modified by: /
|
||
6type tyoc,pwuhak
|
||
tyo tyoc,[40]
|
||
6type tyoc,pwjhak
|
||
type tyoc,/
|
||
Access count: /
|
||
10type tyoc,pwaccc
|
||
terpri
|
||
move x,pwaccc ;get this access count
|
||
camn x,opwacc ;is it still the same?
|
||
ret ; yes, don't bother
|
||
movem x,xpwacc ;remember...
|
||
setzm ptype ;clear ptype
|
||
move x,[ptype,,ptype+1]
|
||
blt x,cntend ;all of them!
|
||
|
||
jrst popj1
|
||
|
||
|
||
pstats: move x,xpwacc ;remember when we started
|
||
movem x,opwacc
|
||
type tyoc,/
|
||
*** Statistics ***
|
||
|
||
Total users: /
|
||
move x,pwcnt ;calculate # of entries
|
||
idivi x,pwleng
|
||
movem pwbuf ;temporary spot
|
||
10type tyoc,pwbuf ;# of users in decimal!
|
||
type tyoc,/
|
||
*'s: /
|
||
10type tyoc,pnull
|
||
type tyoc,/ +'s:/
|
||
10type tyoc,pzunam
|
||
type tyoc,/
|
||
Flag counts:
|
||
SYSTEM APPLIED NEW REFUSED NODAY NODIAL
|
||
/
|
||
irp flg,,[sys,apl,new,rfs,day,dil]
|
||
10type tyoc,pz%!flg
|
||
tyo tyoc,[^I]
|
||
termin
|
||
|
||
type tyoc,/
|
||
1
|
||
Breakdown by INQUIR group:
|
||
Group Count
|
||
----- -----
|
||
/
|
||
move t,[-100,,0] ;index into PTYPE table
|
||
|
||
pstat1: skipe ttyflg ;if TTY is off
|
||
ret ; don't bother any more
|
||
skipn ptype(t) ;if it's zero
|
||
jrst [aobjn t,pstat1 ; loop
|
||
terpri ; until the end
|
||
ret]
|
||
hrrz ch,t ;get the character
|
||
addi ch,40 ;convert to ascii again
|
||
tyo tyoc,ch ;type it out
|
||
tyo tyoc,[^I] ;tab over for count
|
||
|
||
push sp,t ;save T, we need it!
|
||
10type tyoc,ptype(t) ;type it out
|
||
pop sp,t ;restore T
|
||
|
||
terpri ;new line
|
||
aobjn t,pstat1 ;loop until the end
|
||
ret ; that's it.
|
||
|
||
;;; print out the database data for a user. USRWHO is for pre-calculated UNAME
|
||
;;; and USRPRT is for having a pointer to entry in D.
|
||
|
||
usrprt: skipe ttyflg ;was the TTY turned off?
|
||
ret ; yes, stop printing
|
||
push sp,a ;takes pointer in A
|
||
move a,d
|
||
call pwdget ;get the entire entry
|
||
pop sp,a
|
||
call usrwho ;print out the stuff!
|
||
aos pnonam ; count how many of these there are
|
||
pwprt8: call fstats ;get the stats for the flags
|
||
jrst popj1 ;skip return
|
||
|
||
;;; USRPRI skips if there is an INQUIR entry, and prints the name, etc.
|
||
;;; takes uname in UNAME
|
||
;;; clobbers PWBUF
|
||
|
||
usrpri: move bp,[440700,,msgbuf]
|
||
aos (sp) ; Skip unless USRPR2 doesn't
|
||
call usrpr2 ; compute up the text
|
||
sos (sp) ; (no INQUIR entry)
|
||
setz ch, ; be sure to end with NUL
|
||
idpb ch,bp
|
||
output tyoc,msgbuf ; output it to the TTY
|
||
ret
|
||
|
||
|
||
;;; USRDAT skips if there is an INQUIR entry,
|
||
;;; takes UNAME in UNAME
|
||
;;; clobbers PWBUF
|
||
;;; assumes password info already in PDBUF
|
||
usrdat: move x,uname
|
||
idpb6 x,bp ; write the uname
|
||
tyobpi bp,^I
|
||
setom nodate ; suppress creator/modifier date info
|
||
jrst usrdt0
|
||
|
||
;;; USRPR1 skips if there is an INQUIR entry.
|
||
;;; takes uname in UNAME
|
||
;;; clobbers PWBUF
|
||
|
||
usrpr1: move tt,uname ;get it
|
||
movem tt,pwbuf ;as password as well
|
||
setzm pwbuf+1 ; (second word 0)
|
||
move x,uname ; Get the uname
|
||
idpb6 x,bp ;type it out
|
||
tyobpi bp,^I ;space over to column for that
|
||
call pwdlok ;find this user
|
||
pjrst [write bp,/ [NEW] /
|
||
call pwdcns ; cons up an entry
|
||
jrst usrpr2] ; go handle the INQUIR end of it
|
||
call pwdget ;and get his data
|
||
usrdt0: call uflgp0 ;print his flags
|
||
usrpr2: skipe brfflg ;are we supposed to be brief?
|
||
ret ; yes, just return
|
||
tyobpi bp,^I ;Tab over to NAME column!
|
||
call grplsr ;get the group for this loser
|
||
jrst [write bp,/ (No INQUIR entry)/
|
||
jrst usrdpr] ; and just print his name
|
||
idpb ch,bp
|
||
movem ch,lstgrp ;remember it for SCAN
|
||
subi ch,40 ;make it into 6bit
|
||
skipge ch ;make ssure it's in range
|
||
setz ch,
|
||
aos ptype(ch) ;count the beggar
|
||
|
||
pwprt3: movei a,lsrtns"i$rel ;find his relationship
|
||
call lsrget
|
||
movei ch,40 ; substitute a space
|
||
upper ch
|
||
idpb ch,bp
|
||
tyobpi bp,40
|
||
move b,lsrptr
|
||
movei a,lsrtns"i$name ;find his name
|
||
call lsrtns"lsritm
|
||
jrst [write bp,/-=> [His INQUIR entry is missing his NAME!!]/
|
||
jrst usrdpr] ; unsuccessful
|
||
move b,bp ;where to get his name
|
||
call lsrtns"lsrnam ;get his name in human-readable form
|
||
jfcl ; eh?
|
||
move bp,b ; Recover the byte pointer
|
||
decbp bp ; back over the null
|
||
usrdpr: hrlz a,pddate ; Get last login date
|
||
tyobpi bp,^I
|
||
call datwrt
|
||
skipe nodate ; If we don't want the date,
|
||
ret ; don't print the rest of this stuff
|
||
movei a,pwadmn
|
||
call pwsget ; Get the table of creators
|
||
write bp,/
|
||
Creator: /
|
||
ldb tt,[pi$crt pdinfo] ; Get the creator index
|
||
jumpe tt,[ write bp,/Unknown /
|
||
jrst usrpx0]
|
||
move tt,tmpbuf-1(tt) ; Get the name
|
||
idpb6 tt,bp ; Include it in our output
|
||
write bp,/ /
|
||
usrpx0: hllz a,pddate
|
||
call datwrt
|
||
write bp,/, Last Mod: /
|
||
ldb tt,[pi$mod pdinfo] ; Get the last modification index
|
||
jumpe tt,[ write bp,/Unknown /
|
||
jrst usrpx1]
|
||
move tt,tmpbuf-1(tt)
|
||
idpb6 tt,bp
|
||
write bp,/ /
|
||
usrpx1: hllz a,pdmod
|
||
call datwrt
|
||
write bp,/
|
||
/
|
||
jrst popj1
|
||
|
||
|
||
datwrt: save [d]
|
||
hlre d,a
|
||
skipe d
|
||
aosn d
|
||
jrst [ write bp,/[Date Unknown]/
|
||
jrst datwrx]
|
||
move d,bp
|
||
call datime"datasc
|
||
move bp,d
|
||
datwrx: restore [d]
|
||
ret
|
||
|
||
datprt: save [d]
|
||
hlre d,a ; If date part is -1
|
||
skipe d
|
||
aosn d
|
||
jrst [ type tyoc,/[Date Unknown]/
|
||
jrst datprx]
|
||
move d,[440700,,msgbuf]
|
||
call datime"datasc ; deposit date into MSGBUF
|
||
output tyoc,msgbuf ; Type it
|
||
datprx: restore [d]
|
||
ret
|
||
|
||
;;; UFLGPR prints the user's flags
|
||
uflgpr: move bp,[440700,,msgbuf]
|
||
call uflgp0
|
||
setz t,
|
||
idpb t,bp
|
||
output tyoc,msgbuf
|
||
ret
|
||
|
||
uflgp0: ldb t,[pi$grp pdinfo] ; Get his group
|
||
move t,pwgnam(t) ; get the group's name
|
||
idpb6 t,bp
|
||
tyobpi bp,^I
|
||
|
||
ldb tt,[pi$sta pdinfo] ; Get the state of this account
|
||
cain tt,ps%del ; if this account is deleted
|
||
move tt,delsta ; Get the state before deletion
|
||
cain tt,ps%new ; Is this a new account?
|
||
jrst [ write bp,/[NEW] / ; note the fact
|
||
jrst .+1]
|
||
cain tt,ps%sys ;is this a system name?
|
||
jrst [ write bp,/[SYS] / ; note the fact
|
||
jrst .+1]
|
||
cain tt,ps%rfs ;is he refused?
|
||
jrst [ write bp,/[RFS] /
|
||
jrst .+1]
|
||
cain tt,ps%off ; Temporary hold?
|
||
jrst [ write bp,/[OFF] /
|
||
jrst .+1]
|
||
cain tt,ps%hld ;account on hold?
|
||
jrst [ write bp,/[HLD] /
|
||
jrst .+1]
|
||
cain tt,ps%apl
|
||
jrst [ write bp,/[APL] /
|
||
jrst .+1]
|
||
cain tt,ps%ok
|
||
jrst [ write bp,/[OK] /
|
||
jrst .+1]
|
||
push sp,pdpass ;save the users password
|
||
call pwdmak ;cons up the password
|
||
pop sp,pdpass ;restore the world
|
||
camn t,pdpass ;is it the same Pword and UNAME?
|
||
jrst [ tyobpi bp,"+ ; yes, print + to note it
|
||
aos pzunam ; and count it
|
||
jrst uflgp1]
|
||
skipn pdpass ;is the password null?
|
||
jrst [ tyobpi bp,52 ; and mark this oddity
|
||
aos pnull ; count the odities
|
||
jrst uflgp1]
|
||
|
||
tyobpi bp,40
|
||
|
||
uflgp1: tyobpi bp,40
|
||
move tt,pdflag ;check the flags
|
||
tlze tt,%pfnew ;is this new?
|
||
jrst [ tyobpi bp,"!
|
||
jrst .+1]
|
||
tlze tt,%pfday ;daytime?
|
||
jrst [ tyobpi bp,"L ; (L for Load)
|
||
jrst .+1]
|
||
tlze tt,%pfdil ;dialups?
|
||
jrst [ tyobpi bp,"T ; (T for Telephone)
|
||
jrst .+1]
|
||
tlze tt,%pfbad ;forbid bad sites?
|
||
jrst [ tyobpi bp,"B ; (B for Bad)
|
||
jrst .+1]
|
||
tlze tt,%pfmsg ; Seen REFUSE/OFF message?
|
||
jrst [ tyobpi bp,"S ; (S for Seen)
|
||
jrst .+1]
|
||
skipe tt ;Other bits on?
|
||
call flgerr ; Yes! Warn of it!
|
||
ret
|
||
|
||
;;; GSTATS takes stats on an entry in PDATA buffer
|
||
;;; FSTATS takes just the flag stats.
|
||
|
||
gstats: move tt,pdunam ;get the name...
|
||
sub tt,[742532,,732643] ;Will oddities never cease?
|
||
rot tt,-13
|
||
movem tt,uname ;save it for later
|
||
movem tt,pwbuf ;as password as well
|
||
setzm pwbuf+1 ; (second word 0)
|
||
skipn pdpass ;is the password null?
|
||
aos pnull ; count the odities
|
||
push sp,pdpass ;save the real password
|
||
call pwdmak ;cons up the password
|
||
pop sp,pdpass ;restore the original password
|
||
camn t,pdpass ;is this the original password?
|
||
aos pzunam ; count how many of these there are
|
||
fstats: ldb x,[pi$sta pdinfo] ; Get the state
|
||
cain x,ps%apl ; PS%APL?
|
||
aos pz%apl
|
||
cain x,ps%rfs ; PS%RFS?
|
||
aos pz%rfs
|
||
cain x,ps%off ; PS%OFF?
|
||
aos pz%off
|
||
cain x,ps%hld ; PS%HLD?
|
||
aos pz%hld
|
||
cain x,ps%sys ; PS%SYS?
|
||
aos pz%sys
|
||
move x,pdflag ; check out the flag word
|
||
tlze x,%pfnew ; %PFNEW?
|
||
aos pz%new
|
||
tlze x,%pfday ; %PFDAY?
|
||
aos pz%day
|
||
tlze x,%pfdil ; %PFDIL?
|
||
aos pz%dil
|
||
tlze x,%pfbad ; %PFBAD?
|
||
aos pz%bad
|
||
tlze x,%pfmsg ; %PSMSG?
|
||
aos pz%msg
|
||
skipe x ;that should be all
|
||
call flgerr ; It's not, warn of it
|
||
ret
|
||
|
||
|
||
|
||
;;; routine to warn of a flag word having bits on that it's not supposed to
|
||
flgerr: type dspc,/AFIE!!! Bad flag word found.
|
||
Index = /
|
||
8type tyoc,pdloc ; It may change, but...
|
||
type dspc,/AUNAME = /
|
||
6type tyoc,uname
|
||
type dspc,/APDFLAG = /
|
||
htype tyoc,pdflag ; type it out in half-words
|
||
type dspc,/ACall CSTACY!!
|
||
/
|
||
ret
|
||
|
||
.upure
|
||
|
||
ptype: block 100 ;count of each group
|
||
|
||
pnonam: 0 ; count of no-names
|
||
pzunam: 0 ; count of entries with UNAME=Password
|
||
pnull: 0 ; count of null entries
|
||
pz%apl: 0 ; count of PS%APL's seen
|
||
pz%sys: 0 ; count of PS%SYS's seen
|
||
pz%new: 0 ; count of %PFNEW's seen
|
||
pz%rfs: 0 ; count of PS%RFS's seen
|
||
pz%off: 0 ; count of PS%OFF's seen
|
||
pz%hld: 0 ; count of PS%HLD's seen
|
||
pz%dil: 0 ; count of %PFDIL's seen
|
||
pz%day: 0 ; count of %PFDAY's seen
|
||
pz%bad: 0 ; count of %PFBAD's seen
|
||
pz%msg: 0 ; count of %PFMSG's seen
|
||
|
||
cntend: 0 ;dummy, end of cleared entries
|
||
|
||
pwaddf: 0 ;non-zero if we want to append rather than
|
||
;replace
|
||
|
||
opwacc: 0 ;stats uses this to notice changes
|
||
xpwacc: 0 ;count when STATS was started
|
||
|
||
.pure
|
||
|
||
] ; END IFN $$PAND,
|
||
|
||
.upure
|
||
lsrptr: 0 ;pointer into INQUIR database
|
||
|
||
pxunam: 0 ;UNAME being hacked
|
||
pdloc: 0 ; Where this entry was found
|
||
|
||
delsta: 0 ; State of account before deletion
|
||
popass: 0 ; Password before setting
|
||
|
||
pdata:: ;block of data containing info for one user
|
||
pdunam: 0 ;temporary for encoded uname word
|
||
pdpass: 0 ;temporary for encoded password word
|
||
pdflag: 0 ;temporary for database flag word
|
||
pdinfo: 0 ; temporary for misc. info word
|
||
pddate: 0 ; temporary for creation/login date word
|
||
pdmod: 0 ; temporary for modification date word
|
||
0 ; empty
|
||
pdmore: 0 ;temporary for database extra word
|
||
|
||
newflg: 0 ;new flag for PWDCHG to use in place of old
|
||
|
||
|
||
.pure
|
||
p==sp ;synonym for LSRTNS and RFN
|
||
|
||
|
||
$$ulnp==0 ;don't assemble in last-name prefix-matcher
|
||
$$ulnm==0 ;Don't assemble in last-name finder
|
||
$$hsnm==1 ; DO assemble in HSNAME hackery
|
||
.insrt syseng;lsrtns
|
||
|
||
;;; Basically wining file name reader goes here.
|
||
|
||
$$MNAME==0 ;We want DSK: to print as DSK:
|
||
$$RFN==1 ;we want to read them.
|
||
$$PFN==1 ;we want to print them
|
||
$$SWITCH==0 ;we don't allow switches
|
||
$$PFNBRF==0 ;we don't use short forms.
|
||
$$RUC==0 ;the default means of reading is adaquate.
|
||
|
||
.insrt syseng;rfn
|
||
|
||
;;; basically winning time printer goes here.
|
||
$$out==1 ;we want the output routines.
|
||
$$outz==1 ;fancy time zones, etc.
|
||
$$outt==1 ;and the tables of days of the week
|
||
|
||
.insrt syseng;datime
|
||
|
||
.insrt sysen1;pwfile
|
||
|
||
$$HST3==1 ; Use HOSTS3 database
|
||
$$ARPA==1 ; Support ARPA hosts
|
||
$$CHAOS==1 ; Support CHAOS hosts
|
||
$$HSTCMP==1 ; Routine to compare host addresses
|
||
$$OWNHST==1 ; Routine to get our host address
|
||
$$HSTMAP==1 ; Host table routines
|
||
$$SYMGET==1 ; Completing host-name reader
|
||
$$HOSTNM==1 ; Host-name lookup
|
||
|
||
.insrt syseng;netwrk
|
||
|
||
popj1: aos (sp) ;popskip
|
||
cpopj: ret
|
||
|
||
;;; Input/Output Routines for NETWRK package.
|
||
|
||
netwrk"getchr:
|
||
tyi
|
||
caia
|
||
movei ch,"?
|
||
jfcl
|
||
movei t,(ch)
|
||
jrst popj1
|
||
|
||
netwrk"putchr:
|
||
tyo tyoc,t
|
||
idpb t,bp ; Remember it for the mail
|
||
ret
|
||
|
||
netwrk"spchan:
|
||
caie ch,^G
|
||
cain ch,^D
|
||
ret
|
||
jrst popj1
|
||
|
||
|
||
|
||
|
||
|
||
;;;; Command table definitions go here
|
||
cmdtab:
|
||
|
||
ife $$pand,[
|
||
command ACOUNT,,kacount,,,,/For information about getting an account, do
|
||
:ACOUNT
|
||
/,/Applications for accounts can sometimes be done online.
|
||
Do :ACOUNT to find out if online applications are being accepted.
|
||
If they are, simply answer the questions which :ACOUNT asks you,
|
||
and a USER-ACCOUNTS person will process your application quickly.
|
||
If you are in a particular hurry, you may contact USER-ACCOUNTS
|
||
people by sending network mail to USER-ACCOUNTS.
|
||
You should come back later and check if your account has been approved
|
||
by attempting to log in.
|
||
/
|
||
|
||
command LOGIN,,klogin,(%cocrg+%coarg),[
|
||
CF$LPW ;password,pw,change
|
||
CF$LNI ;noinit,brief,bf
|
||
CF$LMS ;mask
|
||
|
||
],/Identify yourself to the machine.
|
||
Type :LOGIN <name> <optional arguments>
|
||
|
||
(If you do not have a password, do :HELP ACOUNT
|
||
for information.)
|
||
/,/
|
||
The LOGIN command takes any of the following optional arguments:
|
||
-change or -ch change your password after you log in
|
||
-password or -pw change your password after you log in
|
||
-brief or -bf don't run your init file
|
||
-noinit same as -brief
|
||
-mask print a mask over where the password will print
|
||
/
|
||
command TCTYP,,jtctyp,(%cojcl),,,/Set terminal type
|
||
/,/Runs the TCTYP program to set your terminal type.
|
||
Do :TCTYP HELP
|
||
for more info.
|
||
/
|
||
|
||
command LUSER,,jluser,(%cojcl),,,/Ask people for help.
|
||
/,/Asks certain people (if they're logged in) for help.
|
||
/
|
||
|
||
command ITS,,,(%cotop),,,/Information about this system.
|
||
/,/You are connected to a PDP-10 computer running the ITS operating
|
||
system. ITS stands for Incompatible Timesharing System, and was
|
||
written at the MIT Artificial Intelligence Laboratory.
|
||
|
||
To request assistance from any available user, you may do :LUSER.
|
||
/
|
||
|
||
command JCL,,,(%cotop),,,/JCL is additional information that you give a command.
|
||
(Note: This is not like IBM Job Control Language!)
|
||
/,/It is typed on the same line following the command, and is usually
|
||
terminated with a carriage return. The only common exception to
|
||
this is terminating the :SEND and :MAIL commands with ^C (control-C)
|
||
causes them to send immediately.
|
||
/
|
||
|
||
command PRINT,,kprint,(%cojcl\%cofil),,,/Print a file.
|
||
/,/:print <file>
|
||
prints a file. Files are in the format <device>:<directory>;<name1> <name2>
|
||
where each field is six characters or less.
|
||
|
||
Device defaults to DSK:, <directory> defaults initially to a user's
|
||
directory, or USERS for people without directories, or .INFO. if you aren't
|
||
logged in yet.
|
||
|
||
You may use an [ALTMODE] (sometimes labelled ESC or ESCAPE) to print the
|
||
defaults. [ALTMODE] prints as a dollar sign.
|
||
|
||
/
|
||
|
||
;;; QUIT will tell him how to do what's he's looking for.
|
||
;;; also in LOGOFF, BYE, etc. variations
|
||
|
||
command QUIT,,kquit,(%conls\%cohlp),,,//,//
|
||
|
||
command LOGOUT,,klogout,(%cocrg),[
|
||
CF$LBY ;bye
|
||
],/Terminate connection with this machine.
|
||
/,/The :LOGOUT command should always be given when you are done
|
||
using the system to clean up any jobs you may have and close your
|
||
connection.
|
||
The -bye option runs the BYE program before logging you out.
|
||
/
|
||
|
||
]; END IFE $$PAND
|
||
|
||
ifn $$PAND,[
|
||
|
||
command quit,,klogou,(%cocrg),,,/Quit out of the program
|
||
/,//
|
||
|
||
command DELETE,,kkill,(%coarg),,,/Delete a name from the database
|
||
/,/Takes the name as an argument.
|
||
/
|
||
|
||
command SET,,USRSET,(%COARG\%COCRG),[
|
||
CF$SSY ;system
|
||
CF$SPW ;password,pwd,p
|
||
CF$SDY ;day
|
||
CF$SND ;nday
|
||
CF$STL ;dial
|
||
CF$SNT ;ndial
|
||
CF$SRF ;rfs,refuse
|
||
CF$SHL ;hold,hld
|
||
CF$SBD ;bad
|
||
CF$SNB ;nbad
|
||
CF$SOF ;off
|
||
CF$SOK ;ok,on
|
||
CF$GRP ;group,grp,gr
|
||
],/Set a user's password and other attributes.
|
||
/,/If the user is not in the database, it defaults his password to his UNAME
|
||
Control arguments:
|
||
|
||
PASSWORD
|
||
-pass, -pw, -pwd Set his password
|
||
FLAGS
|
||
-day Override group restriction for daytime use
|
||
-nday Remove override of group restriction for daytime use
|
||
-dial Override group restriction for dialup use
|
||
-ndial Remove override of group restriction for dialup use
|
||
-bad don't allow to log in from bad sites
|
||
-nbad undo a -bad
|
||
GROUP
|
||
-group, -grp User Group
|
||
STATE
|
||
-ok, -on Turn an account on
|
||
-off Turn an account off
|
||
-refuse, -rfs Denies this user an account.
|
||
-hold, -hld hold this account for more info
|
||
-system, -sys This is a reserved system name.
|
||
/
|
||
|
||
command VAR,,kvar,%coarg,,,\Examine/Set a database variable.
|
||
\,\VAR <varname>
|
||
You will be asked if you wish to set it. If so, you will be
|
||
prompted for additional information.
|
||
|
||
Do "VAR <cr>" to list variables which can be examined/modified.
|
||
\
|
||
|
||
command GROUP,,grpset,%coarg,,,\Examine/Modify group characteristics.
|
||
\,\Interactively examine and modify groups' restrictions.
|
||
\
|
||
|
||
command FIND,,kfind,(%cojcl\%coarg\%cocrg),[
|
||
CF$PBF ;bf,brf,brief
|
||
],\Find out which accounts someone has created.
|
||
\,\ FIND <creator> [-BRIEF]
|
||
|
||
All the accounts created by <creator> are listed in the output file
|
||
which you will be asked for. If you specify the -BRIEF option, only
|
||
the unames will be listed; otherwise you will also get their names and
|
||
status of the account.
|
||
\
|
||
|
||
command CHECK,,kcheck,,,,\Checks a list of users to see if they are accounts.
|
||
\,/CHECK reads a file of UNAMES (there should be one on each line) and
|
||
produces another file which tells you which UNAME's corrsponded to
|
||
valid accounts in the PWORD database. You are prompted for both the
|
||
input and output file. You are also asked if the output file should
|
||
list people with accounts, or the unknown UNAMEs.
|
||
/
|
||
|
||
command PRINT,,kuprin,(%coarg\%cocrg),[
|
||
CF$PBF ;bf,brf,brief
|
||
CF$PAL ;all
|
||
CF$PND ;nodate
|
||
|
||
],\Print out the users in the database.
|
||
\,\Also gives various statistics as in the STATS command
|
||
PRINT <user> <cargs> <CR> prints info on a single user.
|
||
PRINT * <cargs> or :PRINT<CR> prints out data on all users.
|
||
PRINT *UNKNOWN prints information on users without INQUIR entries
|
||
PRINT *NEW prints information on people who have never logged in.
|
||
PRINT *NULL prints information on people with null passwords.
|
||
|
||
Optional control args:
|
||
-all list all of the information from INQUIR on this person
|
||
If the -ALL option is given, the HOLD or REFUSE or APPLY file
|
||
for this user will be printed.
|
||
-brief Don't even list his name! Much faster if you are listing all
|
||
users with :PRINT ALL or :PRINT<CR>
|
||
-nodate Don't list the creator and modifier (and dates)
|
||
|
||
What is printed for a user without the -ALL option is as follows
|
||
<UNAME> <group> <state> <pw> <FLAGS> TU <human-style-name> <login date>
|
||
Creator: <uname> <date; Last modification: <uname> <date>
|
||
|
||
The T column is his INQUIR group, the U column is his INQUIR affiliation.
|
||
<group> is one of the 16 different user groups listed by the GROUP command.
|
||
<state> is one of the following: [NEW] [APL] [OK] [RFS] [HLD] [OFF] [SYS]
|
||
<pw> is *, +, or blank, for a password of null, UNAME, or other
|
||
|
||
Flags are as follows:
|
||
! Never logged in.
|
||
L Allowed daytime use, overriding his GROUP. [-NDAY]
|
||
T Allowed dialup (Telephone) use, overriding his group [-NDIAL]
|
||
B Don't allow this person on from bad sites.
|
||
S Has seen his REFUSE/OFF/HOLD file.
|
||
\
|
||
|
||
|
||
command SCAN,,KSCAN,(%COARG),,,/Map over the database, asking what to do with each
|
||
user matching a given condition.
|
||
/,/
|
||
Conditions currently include ALL, NEW, APPLY (APL), SYSTEM (SYS),
|
||
REFUSE (RFS), and HOLD (HLD), unknown users (UNK), and INQUIR
|
||
(INQ) which reads a line of INQUIR groups to scan for.
|
||
Options for actions are:
|
||
|
||
N -- Not. Do the opposite of next given option. Reads another char.
|
||
A -- Authorize
|
||
B -- Bad ... disallow logins for this name from bad sites
|
||
D -- Delete
|
||
R -- Refuse account
|
||
H -- Put on hold
|
||
O -- Temporarily turn account OFF
|
||
T -- Authorize for Telephone
|
||
L -- Authorize for Loaded Hours
|
||
I -- Ignore this entry (Go on to next)
|
||
X -- Perform the operations.
|
||
^D and [RUBOUT] reset the entry
|
||
[RETURN] simply allows the entry
|
||
[SPACE] goes onto next entry
|
||
|
||
USAGE: ":SCAN APPLY"
|
||
It will then print out info on each user who has applied but not been
|
||
processed, then prompt for one of the above characters.
|
||
/
|
||
|
||
command STATS,,pwdsts,,,,/Print out statistics on the password database.
|
||
/,/Includes such things as # of people in each INQUIR group.
|
||
/
|
||
|
||
] ; END IFN $$PAND
|
||
|
||
command SEND,,KSEND,(%COSND),,,/SEND a message to a user.
|
||
/,/:SEND <user> <message>^C sends <message> to <user> immediately
|
||
if he is logged in. If he is not logged in or is not receiving
|
||
messages, it will be mailed. The <message> may be more than
|
||
one line long. The form "User@Host" does not work for SEND.
|
||
type ":SEND ?" for more help.
|
||
/
|
||
|
||
command NAME,,J.NAME,(%COJCL),,,/See what users are running what jobs. (FINGER)
|
||
/,/If given no JCL (do :HELP JCL), it prints TTY #'s, user-names (UNAME's),
|
||
full names, the job they are currently running, and where they are from.
|
||
If given JCL, that should be in the form
|
||
NAME <name>@<site>,<name>@<site>,....
|
||
<name> is the user you want to find out about, or everyone at that site
|
||
if you omit it. "@<site>" if omitted defaults to the site you are on.
|
||
/
|
||
|
||
command host,,J.HST,(%COJCL),,,/Look up information about a network host.
|
||
/,/Given a host name or host address, tells you all the names and addresses
|
||
of the host and what protocols it supports.
|
||
/
|
||
|
||
command sstatu,,ksstat,,,,\Print out info on system/version etc.
|
||
\,/This is like the :VERSIO and :SSTATU commands combined.
|
||
Fair share is a measure of system load, if it is less than
|
||
about 40% you might wish to try when it is less crowded.
|
||
/
|
||
|
||
command loadp,,jloadp,,,,/See how loaded the system is.
|
||
/,/This prints out various pieces of information about how
|
||
many system resources are in use.
|
||
/
|
||
|
||
command whoj,,jwho,(%COJCL),,,/See what users are running what jobs.
|
||
/,/This is like WHO except that it prints out what job
|
||
a person is currently in.
|
||
/
|
||
|
||
command bug,,jmail,(%cojcl),,,/Mail a bug report to a program's maintainers.
|
||
/,/Runs the mail program, but it takes the name of a program instead of a
|
||
person. It will send mail to the people who maintain a given program.
|
||
You should try to give any information that would help reproduce the problem.
|
||
Usage is:
|
||
:BUG MACSYMA
|
||
The MACSYMA program has gross bugs.
|
||
^C
|
||
/
|
||
|
||
command who,,jwho,(%COJCL),,,/See who is logged in at a site.
|
||
/,/Differs from :WHOJ and :FINGER in that it only prints TTY# and user-name,
|
||
The format of the JCL (See :HELP JCL) is:
|
||
:WHO AI
|
||
to find out who is on AI.
|
||
/
|
||
|
||
command date,,jdate,(%cojcl),,,/Types time and date.
|
||
/,//
|
||
|
||
command time,,jtime,(%cojcl),,,/Types the time of day.
|
||
/,//
|
||
|
||
command times,stime,jtimes,(%cojcl),,,/Types times from several different machines.
|
||
/,//
|
||
|
||
command timoon,,jtimoo,(%cojcl),,,/Types time of day, and the phase of the moon.
|
||
/,//
|
||
|
||
command octpus,,joctps,(%cojcl),,,/A program to read and echo characters.
|
||
/,/For testing terminals and finding out what your terminal sends.
|
||
/
|
||
|
||
command WHOIS,,j.name,(%cojcl),,,/Print out info on who a person is.
|
||
/,/If given no JCL (Do :HELP JCL), it does it for everyone who is logged in.
|
||
If given JCL, it should be the login name of a person, or his last name.
|
||
It will print out relevant info on that person. (A more extreme :NAME)
|
||
/
|
||
|
||
command help,,khelp,(%coarg\%cocrg\%coopt),[
|
||
CF$HAL ;all
|
||
CF$HBF ;bf,brief
|
||
|
||
],/Print help on commands and concepts.
|
||
Takes a single argument of the command to print help on.
|
||
/,/
|
||
This command only exists before you log in.
|
||
|
||
:HELP optionally takes the following after it's argument:
|
||
|
||
-bf Brief. This just prints the first line of the documentation.
|
||
:HELP ALL -bf just prints the names of the commands.
|
||
|
||
Also, there is often help available by typeing H or ?, until you log in.
|
||
/
|
||
|
||
command mail,,jmail,(%cojcl),,,/Send mail to a user or users.
|
||
/,/This runs the mail program. It takes a login-name as JCL
|
||
(See :HELP JCL) and sends mail to that user. Terminate the message
|
||
with a Control-C. More documentation on the :MAIL program may be
|
||
obtained by doing:
|
||
:MAIL <user>
|
||
<altmode>H?
|
||
/
|
||
|
||
command prmail,,kprmai,(%coarg),,,/Read a user's mail.
|
||
/,/:PRMAIL <user>
|
||
prints a users mail file.
|
||
/
|
||
|
||
command prsend,,kprsen,(%coarg),,,/Print a user's SENDS file.
|
||
/,/:PRSEND <user>
|
||
prints a users SEND's, that is the messages that he has been sent while he
|
||
has been logged in.
|
||
/
|
||
|
||
command listf,,klistf,(%cojcl),,,/List a directory.
|
||
/,/:listf <directory name>
|
||
prints a file. <directory name> must me six characters or less.
|
||
/
|
||
|
||
command users,,jusers,(%cojcl),,,/List the users on the system. Nice for printing terminals.
|
||
/,//
|
||
|
||
define equiv a,b
|
||
sixbit /a/
|
||
sixbit /b/
|
||
termin
|
||
|
||
eqvtab: equiv M,MAIL
|
||
equiv W,WHO
|
||
equiv F,NAME
|
||
equiv FINGER,NAME
|
||
equiv WHEN,NAME
|
||
equiv FING,NAME
|
||
equiv ACCOUN,ACOUNT
|
||
equiv S,SEND
|
||
equiv VERSIO,SSTATU
|
||
equiv U,USERS
|
||
|
||
ife $$PAND,[
|
||
equiv TCTYPE,TCTYP
|
||
equiv BYE,QUIT
|
||
equiv LOGOFF,QUIT
|
||
equiv KJOB,QUIT
|
||
]; END IFE $$PAND,
|
||
|
||
ifn $$PAND,[
|
||
equiv ADD,SET
|
||
equiv DEL,DELETE
|
||
equiv SCN,SCAN
|
||
equiv PR,PRINT
|
||
equiv STAT,STATS
|
||
equiv LOGOUT,QUIT
|
||
equiv BYE,QUIT
|
||
equiv KILL,QUIT
|
||
equiv DONE,QUIT
|
||
equiv Q,QUIT
|
||
equiv EXIT,QUIT
|
||
]; END IFN $$PAND,
|
||
|
||
eqvlen==.-eqvtab
|
||
.upure
|
||
|
||
;;;; data areas
|
||
|
||
msgbuf: block <msgbfl+4>/5 ;input buffer.
|
||
|
||
tmpbuf: block 4000 ; Temporary buffer
|
||
|
||
jclbuf: block 100 ;JCL buffer, input and output.
|
||
|
||
outbuf: block 200 ; buffer for generating output
|
||
|
||
dsprmp: 0 ;if non-zero, XCT it instead of usual
|
||
;prompting
|
||
|
||
morflg: 0 ;-1 if at a --MORE--. TYI will take
|
||
;non-skip on ^L.
|
||
|
||
jclct: 0 ;# of chars in JCL
|
||
|
||
pwbuf: block 2 ;two words for a password in clear
|
||
hispas: block 2 ;similarly. Set by PWDCHG, used by KACOUN
|
||
|
||
uname: 0 ;UNAME he wants to log in as
|
||
linker: 0 ; Who did the linking
|
||
linkno: -1 ; TTY no of who did the linking
|
||
cretor: 0 ; Creator uname to FIND.
|
||
checkp: 0 ; -1 if CHECK looks for non-accounts.
|
||
|
||
;;; reader switches go here
|
||
|
||
logflg: 0 ;-1 if keeping log file
|
||
hfdupf: 0 ;half duplex switch
|
||
sailp: 0 ; -1 if TTY understands sail chars
|
||
bsflag: 0 ;non-zero if terminal can backspace
|
||
|
||
helper: call bhelp ;the routine to call to respond to a HELP
|
||
;typed.
|
||
vpos: 0 ;current vertical position
|
||
hpos: 0 ;current horizontal position
|
||
|
||
lfflag: 0 ;set non-zero if we have just rubbed out
|
||
;means to LF when get a real char.
|
||
|
||
jlflag: 0 ;set non-zero if last char rubbed out was a
|
||
;LF. For avoiding double-lf's
|
||
|
||
|
||
cliarg::
|
||
nuprt: 0 ;UNAME read in from CLA device
|
||
njprt: 0 ;JNAME read in from CLA device
|
||
savewd: 0 ;saved word, read in from CLI for to check
|
||
;first char for being a rubout
|
||
chsave: 0 ;saved first char, in case it wasn't a
|
||
;rubout
|
||
|
||
|
||
crgbts: 0 ;These bits correspond to which
|
||
;control-arguments were found by RCARG
|
||
|
||
cargbf: block cargct ;buffer for control-arguments
|
||
acrgbf: block 30 ;ascii chars read by RCARG
|
||
|
||
cladir: sixbit /.TEMP./ ;directory that SENDS files are found on.
|
||
|
||
|
||
;;; call block to open a .UAI file on DSKI
|
||
.pure
|
||
uaiopn: setz ? sixbit /OPEN/ ? cnti .uai ? argi dski
|
||
(b)
|
||
1(b)
|
||
2(b)
|
||
3(b)
|
||
<setz>+<errret>+calerr
|
||
|
||
|
||
;;; filename block for application message in lieu of application proceedure
|
||
|
||
mlname: sixbit /DSK/
|
||
sixbit / APPLY/
|
||
sixbit / MSG/
|
||
sixbit /ACOUNT/
|
||
|
||
.upure
|
||
|
||
;;; filename block for application file
|
||
aplnam:
|
||
fa.dev: sixbit /DSK/
|
||
fa.fn1: sixbit /APPLY/
|
||
fa.fn2: 0
|
||
fa.snm: sixbit /ACOUNT/
|
||
|
||
|
||
;;; filename block for :PRINT defaults
|
||
filnam: ;block of 4 words:
|
||
ife $$PAND,[
|
||
fi.dev: sixbit /DSK/ ;DEVICE
|
||
fi.fn1: sixbit /ITS/ ;FN1
|
||
fi.fn2: sixbit /NEW/ ;FN2
|
||
fi.snm: sixbit /.INFO./ ;SNAME
|
||
]
|
||
ifn $$PAND,[
|
||
fi.dev: sixbit /DSK/
|
||
fi.fn1: sixbit /USER/
|
||
fi.fn2: sixbit /ACOUNT/
|
||
fi.snm: sixbit /ACOUNT/
|
||
|
||
;;; Filename blocks for FIND and CHECK commands.
|
||
outfil:
|
||
ot.dev: sixbit /DSK/
|
||
ot.fn1: sixbit /ACCTS/
|
||
ot.fn2: sixbit />/
|
||
ot.snm: sixbit /ACOUNT/ ; Gets changed to our hsname.
|
||
infil:
|
||
in.dev: sixbit /DSK/
|
||
in.fn1: sixbit /.FOO./
|
||
in.fn2: sixbit /.BAR./
|
||
in.snm: sixbit /ACOUNT/
|
||
]
|
||
;;; filename block used for :LISTF
|
||
dirnam: ;block of 4 words:
|
||
fd.dev: 0 ;DEVICE read by a :LISTF FOO:
|
||
fd.fn1: 0 ;:LISTF FOO or FOO^F
|
||
fd.fn2: 0 ;ignored
|
||
fd.snm: 0 ;:LISTF FOO;
|
||
|
||
;;; filename block for the log file
|
||
.pure
|
||
lognam:
|
||
fl.dev: sixbit /DSK/
|
||
fl.fn1: sixbit /FAILED/
|
||
fl.fn2: sixbit /LOGINS/
|
||
fl.snm: sixbit /ACOUNT/
|
||
.upure
|
||
|
||
;;; filname block for file names in error
|
||
errnam: ;block of 4 words:
|
||
fe.dev: 0
|
||
fe.fn1: 0
|
||
fe.fn2: 0
|
||
fe.snm: 0
|
||
|
||
;;; filename block for refusal reason file
|
||
rfsnam:
|
||
fr.dev: sixbit /DSK/
|
||
fr.fn1: sixbit /REFUSE/
|
||
fr.fn2: 0
|
||
fr.snm: sixbit /ACOUNT/
|
||
|
||
;;; filename block for OFF reason file
|
||
offnam:
|
||
ft.dev: sixbit /DSK/
|
||
ft.fn1: sixbit /OFF/
|
||
ft.fn2: 0
|
||
ft.snm: sixbit /ACOUNT/
|
||
|
||
;;; filename block for a HOLD file
|
||
hldnam:
|
||
fh.dev: sixbit /DSK/
|
||
fh.fn1: sixbit /HOLD/
|
||
fh.fn2: 0
|
||
fh.snm: sixbit /ACOUNT/
|
||
|
||
;;; filename block for output files
|
||
outnam:
|
||
fo.dev: sixbit /DSK/
|
||
fo.fn1:
|
||
ifn $$PAND,sixbit /_PANDA/
|
||
ife $$PAND,sixbit /_PWORD/
|
||
fo.fn2: sixbit /OUTPUT/
|
||
fo.snm: 0
|
||
|
||
|
||
;;; filename block for :PRINT-style opens (CALL PRTOPN)
|
||
fdxnam:
|
||
fx.dev: 0
|
||
fx.fn1: sixbit /.FILE./
|
||
fx.fn2: sixbit /(DIR)/
|
||
fx.snm: 0
|
||
|
||
;;; the info to be passed to DDT goes here.
|
||
altusw: 0 ;if -1, we logged in with $U
|
||
lbrief: 0 ;if -1, we used $0U or -BF in login.
|
||
|
||
;;; Stuff for the inferior handlers goes here.
|
||
|
||
infp: 0 ;-1 if we are in an inferior
|
||
j.file:
|
||
infdev: sixbit /DSK/
|
||
inffn1::sixbit /TS/ ;FN1 of the file to load inferior
|
||
;from
|
||
inffn2: 0 ;FN2
|
||
infsnm: sixbit /SYS/ ;sname
|
||
|
||
j.upc: 0 ;location of interrupt
|
||
jinstr: 0 ;instruction causing interrupt
|
||
jaddr: 0 ;address field of instruction
|
||
jindex: 0 ;index field of instruction
|
||
jindrp: 0 ;non-zero if indirect
|
||
jopcod: 0 ;operation code of inferior
|
||
jaccum: 0 ;accumulator field of operation in inferior
|
||
|
||
jclpag: 0 ;the page # that JCL is to be moved to
|
||
jclloc: 0 ;the offset from the begging of that page
|
||
|
||
;;; random parameters go here
|
||
cmhcnt: 6 ;initially 6 commands per line.
|
||
hcnt: 0 ;# of commands still room for on line
|
||
failct: 2 ;the number of failures allowed before
|
||
;logging the loser out
|
||
failun: 0 ;# of times loser has tried unkown account
|
||
|
||
;;; Data collected by the error handler goes here.
|
||
dbgdir:
|
||
ifn $$DBUG,sixbit /CSTACY/
|
||
ife $$DBUG,sixbit /CRASH/ ;where to write crash files
|
||
dbgfn1:
|
||
ifn $$PAND,sixbit /PANDA/
|
||
.else sixbit /PWORD/
|
||
dbgfn2: sixbit />/
|
||
|
||
iocchn: 0 ;channel that had an IOC error
|
||
iocsts: 0 ;STATUS of channel that had IOC error
|
||
|
||
erracs:: block 20 ;saved AC's in event of error
|
||
irp ZZ,,[x,a,b,c,d,e,t,tt,ch,count,bp,ct,sp]
|
||
ac.!zz=erracs+zz
|
||
termin
|
||
|
||
erradr: 0 ;address of the error
|
||
ebsts: 0 ;status word of bad channel
|
||
ebchn: 0 ;collect the bad channel
|
||
empva: 0 ;when we get around to catching MPV's
|
||
euind: 0 ;get user index, for identification if we
|
||
;get it before it is killed!
|
||
euname: 0 ;get worthless data, usually
|
||
ejname: 0
|
||
etty: 0
|
||
epirqc: 0 ;interrupts?
|
||
eifpir: 0 ;inferiority complex?
|
||
ecnsl: 0 ;what TTY ....
|
||
esv40: 0
|
||
|
||
baderr: 0 ;a saved error from the system
|
||
deathp:
|
||
ifn $$pand,-1
|
||
.else 0
|
||
|
||
pat::
|
||
patch: block 100 ;a large patch area
|
||
|
||
calerr: 0 ;.CALL errors
|
||
debug: 0 ;set -1 if debuging.
|
||
noddt: 0 ;set -1 if noone is to get DDT (debugging)
|
||
startd: 0 ;set -1 if initialization has been done
|
||
vrsadr: .fnam1 ;same as DDT's in purpose, so DBGHAK can
|
||
.fnam2 ;know if it won or not
|
||
|
||
goodf:0 ;-1 if this is our good working set, and we
|
||
;have a crash file loaded
|
||
puname: 0 ;UNAME of person who purified us last
|
||
;;; various ITS data goes here.
|
||
consol: 0 ;our console #
|
||
ttycom: 0 ;the TTYCOM variable
|
||
vsize: 0
|
||
hsize: 0
|
||
ttyopt: 0
|
||
ttytyp: 0 ;TTYTYP variable, for testing various things
|
||
|
||
|
||
tsrtab: 0 ; Magic identifier (should be 'TERMID)
|
||
termid: block 8 ; If non-zero, an ASCIZ terminal name
|
||
hstnam: ascii /LOCAL/ ; If non-zero, the name of the host in ASCIZ
|
||
block 7
|
||
tipnum: 0 ; If non-zero, port number on TIP
|
||
fhost: 0 ; Foreign host connected to
|
||
hstsix: 0 ; Sixbit name of host
|
||
funame: 0 ; sixbit name of user at foreign site
|
||
|
||
tsrloc==:100 ; Where data lives in TELSER
|
||
tsrcnt==:funame-tsrtab+1 ; # of words of data in TELSER
|
||
|
||
ife $$PAND,lclsit: 0 ;site this host is
|
||
|
||
machin: 0 ;sixbit machine name
|
||
dm.flg: 0 ;-1 if this is DM
|
||
itsver: 0 ;sixbit ITS version
|
||
susrs: 0 ;count of users on system
|
||
sysdbg: 0 ;SYSDBG in system
|
||
parnxm: 0 ;sum of parity errors and NXM's
|
||
time: 0 ;time system has been up
|
||
shutdn: 0 ;time till system goes down.
|
||
xuname: 0 ;the initial uname login is attempted as
|
||
runame: 0 ;UNAME of this job
|
||
|
||
;;; This location is only written, never read
|
||
nul: 0
|
||
|
||
;;; PDL
|
||
pdl: block pdllen
|
||
block 30 ;lots of room for PDL over flow handling.
|
||
qitpdl: block 30 ;PDL for things to XCT on unwinding of the
|
||
;pdl.
|
||
|
||
vpatch: block 10 ;an extra patch areea
|
||
.pure
|
||
|
||
ifn $$pand,[
|
||
|
||
usrwho: move bp,[440700,,msgbuf]
|
||
push sp,[-1]
|
||
call usrpr1 ;print out the info on this user
|
||
setz (sp) ; Say we didn't see any INQUIR info
|
||
setz ch,
|
||
idpb ch,bp ; end text with a nul
|
||
terpri
|
||
output tyoc,msgbuf
|
||
pop sp,t
|
||
skipn allflg ; Is that all?
|
||
jrst [ jumpe t,cpopj ; Yes, just fail-return, no INQUIR entry
|
||
jrst popj1] ; INQUIR entry, success return
|
||
jumpe t,usrnm7 ; No INQUIR entry, just type other info
|
||
|
||
usrnm2: movei a,lsrtns"i$nick ;get his nickname
|
||
move b,lsrptr
|
||
call lsrget
|
||
jrst inqr04 ; yes, don't bother
|
||
type tyoc,/ (/
|
||
outstr tyoc,a
|
||
tyo tyoc,[")]
|
||
inqr04: movei a,lsrtns"I$neta ;find his net address
|
||
move b,lsrptr
|
||
call lsrget
|
||
jrst inqr06 ; not there
|
||
type tyoc,/ [/
|
||
outstr tyoc,a
|
||
type tyoc,/]/
|
||
inqr06: movei a,lsrtns"i$mitt ;find his MIT Tel.
|
||
move b,lsrptr
|
||
call lsrget
|
||
jrst inqr12
|
||
type tyoc,/(MIT: /
|
||
outstr tyoc,a
|
||
type tyoc,/) /
|
||
inqr12: movei a,lsrtns"i$homt ;find his home tel.
|
||
move b,lsrptr
|
||
call lsrget
|
||
jrst inqr14
|
||
type tyoc,/(Home: /
|
||
outstr tyoc,a
|
||
tyo tyoc,[")]
|
||
inqr14: terpri
|
||
movei a,lsrtns"i$proj ;find his project
|
||
move b,lsrptr
|
||
call lsrget
|
||
jrst inqr08 ; not there
|
||
type tyoc,/Hacking /
|
||
outstr tyoc,a
|
||
tyo tyoc,[40]
|
||
inqr08: movei a,lsrtns"i$supr ;find his supervisor
|
||
move b,lsrptr
|
||
call lsrget
|
||
jrst inqr10
|
||
type tyoc,/for /
|
||
outstr tyoc,a
|
||
inqr10: terpri
|
||
movei a,lsrtns"i$mita ;get his MIT address
|
||
move b,lsrptr
|
||
call lsrget
|
||
jrst inqr16
|
||
outstr tyoc,a
|
||
terpri
|
||
inqr16: movei a,lsrtns"i$homa ;get his home address
|
||
move b,lsrptr
|
||
call lsrget
|
||
jrst inqr18
|
||
outstr tyoc,a
|
||
terpri
|
||
inqr18: movei a,lsrtns"i$rem ;get remarks
|
||
move b,lsrptr
|
||
call lsrget
|
||
jrst inqr20
|
||
outstr tyoc,a
|
||
terpri
|
||
inqr20: movei a,lsrtns"i$altr ;get alterer
|
||
move b,lsrptr
|
||
call lsrget
|
||
jrst usrnm7
|
||
outstr tyoc,a
|
||
call usrnm7 ;USRNM7 prints APPLY file, and no more
|
||
jrst popj1 ;success return
|
||
|
||
;; USRNM7 is internal for USRWHO, prints APPLY files, or REFUSE files
|
||
usrnm7: type dspc,/A======================================
|
||
/
|
||
call pwdlok ;check for already there
|
||
jrst [type dspc,/A[Not in database]
|
||
/
|
||
ret] ; it isn't there, but no problem
|
||
|
||
type dspc,/A[In database]
|
||
/
|
||
call pwdget ;get this entry
|
||
move t,uname
|
||
ldb x,[pi$sta pdinfo] ;and gobble the account state
|
||
cain x,ps%apl ;applied?
|
||
pjrst [type dspc,/AThis person has applied./
|
||
movei b,aplnam ;fileblock for applications
|
||
jrst usrnmx]
|
||
cain x,ps%rfs ;has he been put on hold or refused?
|
||
pjrst [type dspc,/AThis person has been refused
|
||
/
|
||
movei b,rfsnam ;we want the REFUSE file
|
||
jrst usrnmx]
|
||
cain x,ps%off ; temporarily held
|
||
jrst [type tyoc,/temporarily held.
|
||
/
|
||
movei b,offnam
|
||
jrst usrnmx]
|
||
cain x,ps%hld
|
||
jrst [type tyoc,/held for more info.
|
||
/
|
||
movei b,hldnam ;we want the HOLD file
|
||
jrst usrnmx]
|
||
|
||
caie x,ps%sys
|
||
cain x,ps%ok
|
||
ret
|
||
|
||
error /Illegal account state found./
|
||
|
||
usrnmx: move t,uname
|
||
call fn2opn
|
||
pjrst [type dspc,/ANo info on file.
|
||
/
|
||
ret]
|
||
terpri
|
||
pjrst printf
|
||
|
||
usrnam: setom allflg ;note we want it all
|
||
setzm brfflg ;not brief
|
||
call usrwho
|
||
jfcl ; ignore non-presense in INQUIR
|
||
usrnm8: ask /AIs this OK?/
|
||
jrst [type dspc,/ Left alone./
|
||
ret] ; fail return
|
||
call pwdmap ;so map it in and skip
|
||
jrst popj1
|
||
|
||
;;; get lsr item, skiping if present
|
||
lsrget: call lsrtns"lsritm
|
||
ret
|
||
move t,a
|
||
ildb ch,t
|
||
cain ch,0
|
||
ret
|
||
jrst popj1
|
||
|
||
|
||
usrset: call r6arg ; Parse the command
|
||
call rcarg
|
||
ret
|
||
|
||
skipn t,arg6 ;get the argument
|
||
jrst [type dspc,/AType "SET <uname> [<options>]"
|
||
/
|
||
ret]
|
||
movem t,uname ;UNAME to hack
|
||
movem t,pwbuf ;and it serves as a default password
|
||
setzm t,pwbuf+1
|
||
type dspc,/CSETTING: /
|
||
tyo tyoc,[133] ;open-square-bracket
|
||
|
||
move x,crgbts
|
||
trze x,CF$SOK ;Turning this account on?
|
||
do [type tyoc,/-on/ ; more to come, space between!/
|
||
tyo tyoc,[40]]
|
||
trze x,CF$SBD
|
||
do [type tyoc,/-bad/
|
||
tyo tyoc,[40]]
|
||
trze x,CF$SNB ; OK from bad site?
|
||
do [type tyoc,/-nbad/
|
||
tyo tyoc,[40]]
|
||
trze x,CF$SRF
|
||
do [type tyoc,/-refuse/
|
||
tyo tyoc,[40]]
|
||
trze x,CF$SHL
|
||
do [type tyoc,/-hold/
|
||
tyo tyoc,[40]]
|
||
trze x,CF$SOF
|
||
do [type tyoc,/-off/
|
||
tyo tyoc,[40]]
|
||
trze x,CF$SDY
|
||
do [type tyoc,/-day/
|
||
tyo tyoc,[40]]
|
||
trze x,CF$SPW
|
||
do [type tyoc,/-pw/
|
||
tyo tyoc,[40]]
|
||
trze x,CF$SND
|
||
do [type tyoc,/-nday/
|
||
tyo tyoc,[40]]
|
||
trze x,CF$STL
|
||
do [type tyoc,/-dial/
|
||
tyo tyoc,[40]]
|
||
trze x,CF$SNT
|
||
do [type tyoc,/-ndial/
|
||
tyo tyoc,[40]]
|
||
trze x,CF$SSY
|
||
do [type tyoc,/-system/
|
||
tyo tyoc,[40]]
|
||
trze x,CF$GRP
|
||
do [type tyoc,/-group/
|
||
tyo tyoc,[40]]
|
||
trze x,CF$SHL
|
||
type tyoc,/-hold/
|
||
argdef: skipn crgbts
|
||
type tyoc,/DEFAULT/
|
||
tyo tyoc,[135] ;close-square-bracket
|
||
terpri
|
||
call maplsr ;map in the INQUIR database
|
||
call usrnam ;check his name, etc
|
||
ret ; not right
|
||
setzm usrrsn ; so that .MAIL NOTMAL will win
|
||
move bp,[440700,,usrbfr] ; Remember how it was for the notification
|
||
call usrdat
|
||
jfcl
|
||
setzm msgbuf ; make sure empty at start
|
||
move x,pdpass ; remember the old password
|
||
movem x,popass
|
||
move x,crgbts ;check the control arguments
|
||
trne x,CF$SPW ;set password?
|
||
do [type tyoc,/
|
||
Enter new password.
|
||
/
|
||
call pwadd5 ;do the work of asking
|
||
ret ; lost
|
||
][ call pwdini] ;cons/get the entry
|
||
move a,crgbts ;check the control arguments
|
||
trne a,CF$SOK ; Turning on this user?
|
||
jrst [ movei x,ps%ok
|
||
ldb t,[pi$sta pdinfo]
|
||
dpb x,[pi$sta pdinfo]
|
||
movsi x,%pfmsg ; Say we've not seen any refuse message
|
||
andcam x,pdflag ; since the flag isn't aplicable
|
||
cain t,ps%apl ; If this was an application
|
||
call pwdcid ; Set the creator field
|
||
jrst daydel]
|
||
trne a,CF$SOF ; Temporarily hold this user?
|
||
jrst [ call offwrt ; write the message
|
||
movsi x,%pfmsg ; Say he's not seen the message
|
||
andcam x,pdflag ; since it was just written
|
||
jrst dayp] ; and don't delete anything
|
||
trne a,CF$SRF ;refuse this user?
|
||
jrst [ call rfswrt ; yes, write the refusal
|
||
movsi x,%pfmsg ; Say he's not seen the message
|
||
andcam x,pdflag
|
||
jrst dayp] ; and don't delete anything
|
||
trne a,CF$SHL ;put this user on hold?
|
||
jrst [ call hldwrt ; yes, write the HOLD file
|
||
movsi x,%pfmsg ; Say he's not seen the message
|
||
andcam x,pdflag
|
||
jrst dayp] ; and don't delete anything
|
||
daydel: call acdel ;delete any left over APLY or REFUSE files
|
||
dayp: move x,pdflag ; Check the flag bits
|
||
trne a,CF$SBD ;Prohibit bad sites?
|
||
tlo x,%pfbad
|
||
trne a,CF$SNB ; bad site OK?
|
||
tlz x,%pfbad
|
||
trne a,CF$SDY ;daytime OK?
|
||
tlo x,%pfday
|
||
trne a,CF$SND ;daytime not ok?
|
||
tlz x,%pfday
|
||
trne a,CF$STL ;Dialups?
|
||
tlo x,%pfdil
|
||
trne a,CF$SNTL ;Dialups NOT ok?
|
||
tlz x,%pfdil
|
||
movem x,pdflag ;in the flag word
|
||
trne a,CF$SSY ;Is it supposed to be system reserved name?
|
||
do [movei x,ps%sys ; note this fact
|
||
dpb x,[pi$sta pdinfo]
|
||
movsi x,%pfmsg ; Flush inapplicable flag
|
||
andcam x,pdflag
|
||
setom pdpass] ; no password in particular
|
||
ldb x,[pi$sta pdinfo] ; Check the state for being PS%NEW
|
||
cain x,ps%new ; which isn't legal. This can happen
|
||
jrst [ movei x,ps%ok ; when creating an account
|
||
dpb x,[pi$sta pdinfo] ; via SET FOO<cr>.
|
||
jrst .+1]
|
||
trne a,CF$GRP
|
||
do [ call rdgrp ; Read in the group
|
||
ret
|
||
dpb a,[pi$grp pdinfo]]
|
||
move bp,[440700,,usraft]
|
||
call usrdat ; Get the new state of the user
|
||
jfcl
|
||
move x,popass
|
||
came x,pdpass ; Has the password been changed?
|
||
jrst [ write bp,/
|
||
[new password]
|
||
/
|
||
jrst .+1]
|
||
call malset ;send off a note
|
||
pjrst pwdput ;put this entry in the database
|
||
|
||
rdgrp: call grpprt ; Print the group names
|
||
type dspc,/AGroup: /
|
||
save [bp]
|
||
move bp,[440700,,msgbuf]
|
||
call read6 ; Read in the 6bit name of the group
|
||
jrst [ restore [bp]
|
||
ret]
|
||
restore [bp]
|
||
rdgrp6: save [x]
|
||
movsi a,-20 ; AOBJN ptr to group names
|
||
move x,arg6
|
||
rdgrp0: camn x,pwgnam(a) ; Is this our group?
|
||
jrst rdgrp1 ; Yep
|
||
aobjn a,rdgrp0 ; Nope
|
||
|
||
type dspc,/AThat group is not known.
|
||
/
|
||
|
||
restore [x]
|
||
ret
|
||
|
||
rdgrp1: movei a,(a) ; Eliminate the count
|
||
restore [x]
|
||
jrst popj1
|
||
|
||
|
||
;;; local function for SET and SCAN. X contains future flag word (PWFLAG)
|
||
;;; writes ACOUNT;REFUSE <UNAME> file
|
||
|
||
rfswrt: push sp,x ;save X
|
||
movei x,ps%rfs ; Set the state to REFUSE
|
||
dpb x,[pi$sta pdinfo]
|
||
call acdel
|
||
push sp,[440700,,[asciz /
|
||
Has been denied /]]
|
||
call aplcop ;copy over the apply file with
|
||
pop sp,nul
|
||
move t,uname ;rename with FN2 of UNAME
|
||
movei b,rfsnam
|
||
pop sp,x
|
||
call rnmfn2 ;rename the file
|
||
pjrst apldel ;and flush the old cruft
|
||
|
||
;;; local function for SET and SCAN. X contains future flag word (PWFLAG)
|
||
;;; writes ACOUNT;REFUSE <UNAME> file
|
||
|
||
offwrt: push sp,x ;save X
|
||
movei x,ps%off ; Put into OFF state
|
||
dpb x,[pi$sta pdinfo]
|
||
call acdel
|
||
push sp,[440700,,[asciz /
|
||
Has been denied /]]
|
||
call aplcop ;copy over the apply file with
|
||
pop sp,nul
|
||
move t,uname ;rename with FN2 of UNAME
|
||
movei b,offnam
|
||
pop sp,x
|
||
call rnmfn2 ;rename the file
|
||
pjrst apldel ;and flush the old cruft
|
||
|
||
;;; HLDWRT is like RFSWRT except for HOLD files
|
||
|
||
hldwrt: push sp,x ;save x
|
||
movei x,ps%hld
|
||
dpb x,[pi$sta pdinfo]
|
||
call acdel
|
||
push sp,[440700,,[asciz /
|
||
Has been held /]]
|
||
call aplcop ;copy the apply file to a new file
|
||
pop sp,nul
|
||
move t,uname ;rename with FN2 of UNAME
|
||
movei b,hldnam
|
||
pop sp,x
|
||
call rnmfn2 ;rename the file
|
||
pjrst apldel ;and flush the old
|
||
|
||
aplcop: move b,[sixbit /ACOUNT/] ;output directory is ACOUNT
|
||
call opnout ;output a file to it
|
||
movei b,aplnam ;file with the applicatiton
|
||
move t,uname
|
||
call fn2opn ;open application file
|
||
jrst filwrt ; Not there
|
||
type dsko,/The following application:
|
||
/
|
||
call copyf
|
||
aplwrt: outstr dsko,(sp)
|
||
filwrt: move t,[type dspc,/CThe user will se this when he tries to log in.
|
||
End with a ^C.
|
||
Because: /]
|
||
movem t,helper ;set up some help for the user
|
||
call becaus ; get the reason from the user
|
||
output dsko,usrrsn ;output our reason
|
||
ret
|
||
|
||
becaus: setzm usrrsn
|
||
move t,[usrrsn,,usrrsn+1]
|
||
blt t,usrrsn+400-1 ;clear out the previous contents
|
||
move t,[440700,,[asciz /Because: /]]
|
||
move bp,[440700,,usrrsn] ;place to put the input!
|
||
copy t,bp
|
||
type dspc,/ABecause: /
|
||
save [a,x]
|
||
call readsn ;read the message
|
||
jrst [restore [x,a]
|
||
syscal delewo,[argi dsko] ;don't leave garbage around
|
||
ret
|
||
ret]
|
||
restore [x,a]
|
||
ret
|
||
|
||
kkill: call r6arg
|
||
skipn t,arg6 ;ARG6 is the one to delete
|
||
jrst [type dspc,/AType ":DELETE <uname>"
|
||
/
|
||
ret] ; explain it to him!
|
||
movem t,uname
|
||
type dspc,/CDELETING: /
|
||
call maplsr
|
||
call usrnam
|
||
ret
|
||
ldb x,[pi$sta pdinfo]
|
||
movem x,delsta
|
||
movei x,ps%del
|
||
dpb x,[pi$sta pdinfo]
|
||
call acdel
|
||
move bp,[440700,,usrbfr]
|
||
setzm usraft
|
||
call usrdat
|
||
call pwdel ;delete it
|
||
jrst [type dspc,/ANot found.
|
||
/
|
||
ret]
|
||
call becaus ; get the reason
|
||
call maldel ;set a note
|
||
type dspc,/ADone./
|
||
ret
|
||
|
||
acdel: syscal delete,[[sixbit /DSK/]
|
||
[sixbit /REFUSE/]
|
||
uname
|
||
[sixbit /ACOUNT/]]
|
||
jfcl
|
||
syscal delete,[[sixbit /DSK/]
|
||
[sixbit /HOLD/]
|
||
uname
|
||
[sixbit /ACOUNT/]]
|
||
jfcl
|
||
|
||
syscal delete,[[sixbit /DSK/]
|
||
[sixbit /OFF/]
|
||
uname
|
||
[sixbit /ACOUNT/]]
|
||
jfcl
|
||
apldel: syscal delete,[[sixbit /DSK/]
|
||
[sixbit /APPLY/]
|
||
uname
|
||
[sixbit /ACOUNT/]]
|
||
jfcl
|
||
ret
|
||
|
||
;;; SCAN command
|
||
|
||
define scanop [names],init,pred
|
||
irp name,,names
|
||
irps x,,[name]
|
||
sixbit /x/
|
||
termin
|
||
ifnb init,init,,pred
|
||
.else popj1,,pred
|
||
|
||
termin
|
||
termin
|
||
|
||
SCNOPS:
|
||
|
||
irp x,,[[NEW,,scnnew],[ALL,,popj1],[[APPLY,APL,APPLY],,scnapl],[UNK,sinunk,scnunk],
|
||
[[SYS,SYSTEM],,scnsys],[[REFUSE,RFS],,scnrfs],[[HOLD,HLD],,scnhld],
|
||
[[OFF,TOFF],,scnoff],[[INQUIR,INQ],sininq,scninq],[BAD,,scnbad]]
|
||
scanop x
|
||
termin
|
||
|
||
scnlng==.-scnops
|
||
.upure
|
||
notsw: 0 ; Initially NOT NOT
|
||
|
||
;; the next 3 should be together in the same order. They are sometimes used
|
||
;; together as a single buffer, i.e. for the GROUP command
|
||
|
||
usrbfr: block 40 ; Buffer for user status BEFORE we modify
|
||
usraft: block 40 ; Buffer for user status AFTER we modify
|
||
usrrsn: block 400 ; text of reason for refusal
|
||
|
||
.pure
|
||
kscan: setzm notsw ;NOT NOT
|
||
call r6arg ; Hack the JCL
|
||
skipn t,arg6 ;get the argument
|
||
move t,[sixbit /APPLY/] ;default to searching applications
|
||
movsi b,-scnlng
|
||
kscan1: camn t,scnops(b) ;is this the command?
|
||
jrst kscan2 ; yes, let's to hack!
|
||
add b,[1,,1] ;skip the address
|
||
aobjn b,kscan1 ;and hack the next command name
|
||
type dspc,/Foo! I don't know that sub-command!/
|
||
ret
|
||
|
||
kscan2: hlrz t,scnops+1(b) ;get the initialization routine
|
||
call (t) ;initialize it
|
||
ret ; he flushed it
|
||
setz a, ;start counting entries
|
||
krscan: call pwdget ;get this entry
|
||
move x,pdflag ;get the flags
|
||
movem x,opdflg ;remember the way they were
|
||
move x,pdinfo
|
||
movem x,opdinf
|
||
move x,pdunam ;convert his name to normal 6bit
|
||
sub x,[742532,,732643] ;Will oddities never cease?
|
||
rot x,-13
|
||
movem x,uname ;save it for later
|
||
save [b,a] ;save our AC's for later
|
||
hrrz t,scnops+1(b) ;get the predicate
|
||
call (t) ;and call it
|
||
jrst kscan9 ; nope, get next
|
||
call maplsr ;map in the INQUIR database
|
||
kscask: tyo dspc,[^P] ;clear the screen
|
||
tyo dspc,["C]
|
||
setom allflg ;make sure we get all the info!
|
||
setzm nodate
|
||
call usrwho ;print out loads of info
|
||
jfcl
|
||
move bp,[440700,,usrbfr] ; let's remember state before hackery
|
||
call usrdat
|
||
jfcl
|
||
ksask1: type dspc,/ALZUUUE/
|
||
6type tyoc,uname
|
||
tyo tyoc,[^I]
|
||
call uflgpr ;print his flags
|
||
call usrpri ;print his name etc.
|
||
jfcl
|
||
setzm ttyflg ;turn on the TTY...
|
||
type dspc,/ALWhat now boss? (A,N,I,D,T,L,B,H,O,R,S,X,?,<CR>,^D) /
|
||
setzm notsw ;not negative
|
||
|
||
ksask2: move x,[call [movei ch,^D ;pretend it's a ^D instead
|
||
movem ch,reread
|
||
ret]]
|
||
movem x,dsprmp
|
||
tyi
|
||
jrst [pop sp,a
|
||
call pwdget ;back to the way we were
|
||
move x,pdflag ;get the flags
|
||
movem x,opdflg ;remember the way we were
|
||
move x,pdinfo
|
||
movem x,opdinf
|
||
push sp,a
|
||
jrst kscask]
|
||
jrst [type dspc,/CA -- Authorize
|
||
A -- Accept application.
|
||
N -- Not (negate next character)
|
||
I -- Ignore, go to next entry
|
||
D -- Delete this entry
|
||
T -- Telephone usage
|
||
L -- Loaded usage (daytime)
|
||
B -- Disallow bad sites
|
||
H -- Put on hold
|
||
R -- Refuse this account
|
||
S -- SYSTEM name
|
||
O -- Temporarily Off
|
||
X -- Done, make changes permanent.
|
||
^D, [RUBOUT] -- reset
|
||
<CR> -- do the default
|
||
? -- This help.
|
||
|
||
---type space to redisplay---
|
||
/
|
||
|
||
.iot tyic,ch
|
||
jrst kscask]
|
||
jrst [pop sp,a
|
||
call pwdget
|
||
push sp,a
|
||
jrst kscask]
|
||
setzm dsprmp ;no more funny stuff!
|
||
upper ch ;uuppercasify
|
||
cain ch,"A ; Approved?
|
||
jrst [ type tyoc,/Approved./
|
||
skipe notsw ; Not?
|
||
jrst kscask ; Then don't do it!
|
||
call rdgrp ; Get the group
|
||
jrst kscask ; Punt
|
||
dpb a,[pi$grp pdinfo] ; Store the group
|
||
movei x,ps%ok
|
||
ldb t,[pi$sta pdinfo] ; check out the old state
|
||
dpb x,[pi$sta pdinfo] ; Set the state to OK
|
||
cain t,ps%apl ; Was this new application?
|
||
call pwdcid ; Set the creator field.
|
||
jrst kscan8] ; Next
|
||
|
||
cain ch,"I
|
||
jrst [type tyoc,/Ignored./
|
||
skipe notsw ;not?
|
||
jrst kscask ; don't ignore it!
|
||
jrst kscan9]
|
||
cain ch,"D
|
||
jrst [type tyoc,/Delete/
|
||
skipn notsw ; positive?
|
||
jrst [tyo tyoc,[".] ;yes, period
|
||
move x,[sixbit /DELETE/] ;pretend we are a DELETE
|
||
movem x,comand
|
||
ask /ADelete this user?/
|
||
jrst [type dspc,/ANot Deleted./
|
||
jrst ksask1]
|
||
ldb x,[pi$sta pdinfo]
|
||
movem x,delsta ; remember the old state for printing
|
||
movei x,ps%del ; Set the state to something random
|
||
dpb x,[pi$sta pdinfo]
|
||
call acdel ;flush files
|
||
call pwdel
|
||
type tyoc,/(Not found????)/
|
||
jrst kscanx]
|
||
type tyoc,/d./
|
||
jrst ksask1]
|
||
cain ch,"R
|
||
jrst [type tyoc,/Refuse/
|
||
skipe notsw ; negative?
|
||
jrst kscnok
|
||
movei x,ps%rfs ; New state = REFUSE
|
||
jrst kscan4] ; and re-save in database
|
||
cain ch,"O
|
||
jrst [type tyoc,/Temporary Hold (off)./
|
||
skipe notsw ; negative?
|
||
jrst kscnok
|
||
movei x,ps%off
|
||
jrst kscan4]
|
||
cain ch,"H ;hold?
|
||
jrst [type tyoc,/Hold./
|
||
skipe notsw ; negative?
|
||
jrst kscnok
|
||
movei x,ps%hld ; Make state HOLD
|
||
jrst kscan4]
|
||
cain ch,"S ;system?
|
||
jrst [type tyoc,/SYSTEM./
|
||
skipe notsw ; negative?
|
||
jrst kscan5 ; turn off PS%SYS
|
||
setzm pdflag ; No flags on, please
|
||
setom pdpass ;no password in particular
|
||
movei x,ps%sys ; Make the state SYSTEM
|
||
jrst kscan4]
|
||
cain ch,"T ;turn off telephone authorization
|
||
jrst [type tyoc,/Telephone./
|
||
move x,pdflag ;get the flags
|
||
skipn notsw ;if positive
|
||
tlo x,%pfdil ; allow telephone
|
||
skipe notsw ;if negative
|
||
tlz x,%pfdil ; don't allow telephone
|
||
movem x,pdflag ;use new
|
||
jrst kscan5] ;and re-save in database
|
||
cain ch,"L
|
||
jrst [type tyoc,/Loaded use./
|
||
move x,pdflag ;;get the flags
|
||
skipn notsw ;if positive
|
||
tlo x,%pfday ; turn off daytime prohibition
|
||
skipe notsw ;if negative
|
||
tlz x,%pfday ; prohibit daytime use
|
||
movem x,pdflag
|
||
jrst kscan5] ; and re-save in database
|
||
|
||
cain ch,"B ;Badness?
|
||
jrst [type tyoc,/Bad site prohibit. /
|
||
move x,pdflag ; get the flags
|
||
tlo x,%pfbad ; turn on prohibition
|
||
skipe notsw ; unless negative
|
||
tlz x,%pfbad ; turn it off
|
||
movem x,pdflag
|
||
jrst kscan5] ; and re-save in database.
|
||
|
||
cain ch,"N ;Not?
|
||
jrst [type tyoc,/Not /
|
||
move x,notsw
|
||
xori x,-1
|
||
movem x,notsw
|
||
jrst ksask2]
|
||
|
||
cain ch,"X ;X ?
|
||
jrst kscan8 ; deposit and go.
|
||
|
||
skipe crgbts ;have we done anything?
|
||
jrst ksask1 ; yes, none of the rest should exit then.
|
||
|
||
cain ch,^M ;CR?
|
||
jrst kscnok ; just do the minimum
|
||
|
||
cain ch,40 ;space?
|
||
jrst kscan9 ; on to the next one!
|
||
|
||
|
||
type tyoc,/Huh?/
|
||
jrst kscask ;ask again
|
||
|
||
kscnok: movei x,ps%ok
|
||
kscan4: dpb x,[pi$sta pdinfo]
|
||
kscan5: movsi x,%pfmsg ; We're setting the state, say we've not
|
||
andcam x,pdflag ; seen this message yet
|
||
jrst ksask1
|
||
|
||
kscan8: setzm usrrsn ; no reason given yet
|
||
ldb x,[pi$sta opdinf] ; compare with the old flags
|
||
ldb t,[pi$sta pdinfo] ; with what we have now.
|
||
camn x,t ; are they the same?
|
||
jrst kscn8a ; yes, don't send any mail or anything
|
||
cain t,ps%rfs ; Did we refuse him?
|
||
jrst [ call rfswrt ; yes, write a refuse file
|
||
jrst kscn8a]
|
||
cain t,ps%hld ; Did we put him on hold?
|
||
jrst [ call hldwrt ; yes, write a hold file
|
||
jrst kscn8a]
|
||
cain t,ps%off ; Did we turn him off?
|
||
jrst [ call offwrt ; yes, write a off file
|
||
jrst kscn8a]
|
||
call acdel ; Else clean up special files
|
||
|
||
kscn8a: move bp,[440700,,usraft] ; now get new state of account
|
||
call usrdat
|
||
jfcl
|
||
call malset ; Send out mail about it
|
||
call pwdput ;put it back
|
||
kscan9: restore [a,b]
|
||
addi a,pwleng ;point to next entry
|
||
camg a,pwcnt ;is this all?
|
||
jrst krscan ; nope, loop
|
||
ret ;yes, that's all folks!
|
||
|
||
;; for after deletion, re-tries same entry slot, since it has changed who
|
||
;; is in it!
|
||
kscanx: call becaus ; find out why
|
||
call maldel ; Send mail about it
|
||
restore [a,b] ;restore the world
|
||
camg a,pwcnt ;if we haven't flushed the last entry
|
||
jrst krscan ; loop around hitting this one first
|
||
ret ;else done.
|
||
|
||
;;; SCNNEW skips if this is a new entry
|
||
scnnew: move x,pdflag ;get the flag
|
||
tlnn x,%pfnew ;is it new?
|
||
ret ; nope, no skip
|
||
jrst popj1 ;yes, skip
|
||
|
||
scnapl: ldb x,[pi$sta pdinfo] ;get the flag
|
||
cain x,ps%apl ; Has he only applied?
|
||
jrst popj1 ; Yes, this is it
|
||
ret ; nope, no patch
|
||
|
||
scnbad: move x,pdflag ;get the flag
|
||
tlnn x,%pfbad ;is he forbidden from bad sites?
|
||
ret ; nope
|
||
jrst popj1 ;yep
|
||
|
||
scnrfs: ldb x,[pi$sta pdinfo]
|
||
cain x,ps%rfs ;has he been refused?
|
||
jrst popj1
|
||
ret
|
||
|
||
scnoff: ldb x,[pi$sta pdinfo]
|
||
cain x,ps%off ; Is it off?
|
||
jrst popj1
|
||
ret
|
||
|
||
scnhld: ldb x,[pi$sta pdinfo]
|
||
cain x,ps%hld ; Is he on hold?
|
||
jrst popj1
|
||
ret
|
||
|
||
scnsys: ldb x,[pi$sta pdinfo]
|
||
cain x,ps%sys ;is it a system name?
|
||
jrst popj1
|
||
ret
|
||
|
||
sininq: setz count,
|
||
move bp,[440700,,inqbuf]
|
||
sin0: type dspc,/AEnter INQUIR groups to scan for: /
|
||
sin3: tyi
|
||
ret ;^D typed
|
||
jrst [type dspc,/AType as many groups as you wish, end with
|
||
a CR. Null group is the same as [SPACE].
|
||
/
|
||
jrst sin0]
|
||
jrst [sojl count,[ret]
|
||
decbp bp
|
||
call 1wipe ;wipe it from the screen
|
||
jrst sin3]
|
||
|
||
cain ch,^M ;is it the end?
|
||
jrst sin9 ; yes, remember this
|
||
upper ch ;uppercasify
|
||
echoch
|
||
idpb ch,bp
|
||
aos count
|
||
|
||
caige count,24 ;are there too many of them?
|
||
jrst sin3 ; nope, ask for more
|
||
sin9: terpri ;let him know he got it.
|
||
movem count,inqcnt
|
||
save [a,b] ;save important stuff
|
||
call maplsr ;map in the INQUIR database
|
||
restore [b,a]
|
||
jrst popj1 ;yes, don't take any more
|
||
|
||
scninq: move count,inqcnt ;set up for count
|
||
jumpe count,[ret]
|
||
move bp,[440700,,inqbuf]
|
||
call grplsr
|
||
movei ch,40 ;pretend it's a space
|
||
scinq0: ildb x,bp ;get a character
|
||
camn ch,x ;is it one of them?
|
||
jrst popj1 ; yes. Win win.
|
||
sojg count,scinq0 ;keep on trying
|
||
ret ;not there.
|
||
|
||
.upure
|
||
inqbuf: block 4 ; 20. groups max
|
||
inqcnt: 0 ; count of groups searched for
|
||
lstgrp: 0 ; remembered group from USRPR1
|
||
opdflg: 0 ; old PDFLAG word for this user
|
||
opdinf: 0 ; old PDINFO word for this user
|
||
sukchk: 0 ; -1 if should ignore special unknowns
|
||
.pure
|
||
|
||
;;; SCNUNK skips iff luser has no INQUIR entry (SINUNK inits)
|
||
|
||
sinunk: setzm sukchk ;Normally process everyone.
|
||
ask /AIgnore special users (reserved names, people on HOLD, etc.)? /
|
||
caia
|
||
setom sukchk ;Yes - ignore them.
|
||
save [a,b]
|
||
call maplsr ;Map in the INQUIR database.
|
||
restore [b,a]
|
||
jrst popj1
|
||
|
||
scnunk: skipn sukchk ;Ignoring special entries?
|
||
jrst scnun1 ; No, go process everyone.
|
||
move x,pdflag
|
||
; tlne x,%pfnew ;New account?
|
||
; ret ; Yes, ignore it.
|
||
ldb x,[pi$sta pdinfo]
|
||
caie x,ps%apl ;Applicant?
|
||
cain x,ps%rfs ; Or refusal?
|
||
ret ; Yes, leave alone.
|
||
caie x,ps%off ;Off?
|
||
cain x,ps%hld ; Or held?
|
||
ret ; Yes, leave alone.
|
||
cain x,ps%sys ;If this is a system name
|
||
ret ; ignore it.
|
||
scnun1: movei a,lsrc ;Tell LSRTNS what channel it can hack.
|
||
move b,uname ;Ask about this UNAME.
|
||
call lsrtns"lsrunm ;Is it there?
|
||
jrst popj1 ; No - hack this guy.
|
||
ret ;Yes, leave alone.
|
||
|
||
|
||
|
||
SUBTTL Parameters, Variables, Tables
|
||
|
||
.upure
|
||
varnam: 0 ; Name of variable set
|
||
.pure
|
||
|
||
;;; Macro for defining parameters.
|
||
|
||
parcnt==0 ;Number of PANDA parameters defined.
|
||
|
||
define param name,erout,srout,arg,mail,&doc
|
||
sixbit /NAME/ ;Name
|
||
erout ;Examining routine
|
||
srout ;Setting routine
|
||
arg ;Argument (passed in A) for above
|
||
mail ;Argument for .MAIL
|
||
[asciz doc] ;Parameter documentation
|
||
parcnt==parcnt+1
|
||
termin
|
||
parlen==:6
|
||
|
||
partab:
|
||
parnam=:partab
|
||
parex=:partab+1
|
||
parset=:partab+2
|
||
pararg=:partab+3
|
||
parmal=:partab+4
|
||
pardoc=:partab+5
|
||
|
||
param GOOD,enet,snet,lucktb,varmml,/Hosts which get DDT instead of PWORD/
|
||
param BAD,enet,snet,losers,varmml,/Hosts to check the -BAD bit on/
|
||
param PEOPLE,e6tab,0,pwadmn,0,/People who have run PANDA/
|
||
param APPLY,flgprt,flgset,atoapl,varmml,/When true, allow applications/
|
||
param APLTXT,pwgtxt,pwstxt,naplmg,varmml,/Message to print in lieu of accepting applications/
|
||
param PHONE,pwgtxt,pwslin,phone,varmml,/Phone number for users to call for help/
|
||
param DDTTTY,ttylis,ttyset,ddtttb,varmml,/TTY lines to get DDT instead of PWORD/
|
||
param DILTTY,ttylis,ttyset,dilttb,varmml,/TTY lines to be considered reserved dialups/
|
||
param BADCMD,e6tab,s6tab,nocmnd,varmml,/PWORD commands to suppress/
|
||
param HOLDAY,flgprt,flgset,pwholp,varmml,/When true, PWORD ignores login time restrictions./
|
||
|
||
|
||
;;; .MAIL text to type variable name and ASCIZ text from MSGBUF.
|
||
varmml: -4,,[ 440700,,[asciz /Variable: /]
|
||
tp$6bt varnam
|
||
440700,,[asciz /
|
||
Value: /]
|
||
440700,,msgbuf]
|
||
|
||
.upure
|
||
varmal: 440700,,[asciz /USER-ACCOUNTS/]
|
||
tp$6bt runame
|
||
0
|
||
440700,,[asciz /New Variable setting in PWORD/]
|
||
varinf: 0
|
||
.pure
|
||
|
||
;;; Implement the VAR command for PANDA.
|
||
|
||
|
||
;;; Routine to handle VAR command in PANDA.
|
||
|
||
kvar: call r6arg ; Parse the command
|
||
skipn t,arg6 ; Did we get an argument?
|
||
jrst kvarh ; No - just list the variables.
|
||
movem t,varnam ; Remember the name for the mail
|
||
call kvar0 ; Find the parameter
|
||
ret ; No such var!
|
||
move a,pararg(tt) ; argument to the routine
|
||
save [tt]
|
||
call @parex(tt) ; Do it
|
||
jfcl ; Maybe it might skip-return
|
||
restore [tt]
|
||
skipn parset(tt) ; is there a routine to set it?
|
||
ret ; no, that's it.
|
||
ask /ADo you wish to set it?/
|
||
ret
|
||
move a,pararg(tt) ; argument to the routine
|
||
save [tt]
|
||
move bp,[440700,,msgbuf]
|
||
call @parset(tt)
|
||
jfcl
|
||
restore [tt]
|
||
setz ch, ; Ensure everything ends with a nul
|
||
idpb ch,bp
|
||
move t,parmal(tt) ; tell the .MAIL what to hack
|
||
movem t,varinf
|
||
movei t,(tp$ind)
|
||
hrlm t,varinf
|
||
.mail varmal ; Mail notification
|
||
ret
|
||
|
||
|
||
kvar0: movei t,parcnt
|
||
setz tt,
|
||
move x,arg6
|
||
kvar1: camn x,partab(tt) ; Is this the parameter?
|
||
jrst popj1
|
||
addi tt,parlen
|
||
sojg t,kvar1
|
||
type dspc,/AI never heard of that variable!
|
||
/
|
||
ret
|
||
|
||
|
||
kvarh: type dspc,/CThe VAR command will examine any of the following vars:
|
||
|
||
/
|
||
movei t,parcnt
|
||
setz tt,
|
||
kvarh0: skipn parset(tt) ; * if setable
|
||
type tyoc,/ /
|
||
skipe parset(tt)
|
||
type tyoc,/* /
|
||
6type tyoc,parnam(tt)
|
||
type tyoc,/ -- /
|
||
output tyoc,@pardoc(tt)
|
||
terpri
|
||
addi tt,parlen
|
||
sojg t,kvarh0
|
||
type tyoc,/
|
||
* ==> Variable can be set.
|
||
/
|
||
ret
|
||
|
||
|
||
|
||
;;; Flags are a simple kind variable.
|
||
;;; Here are the routines to Examine and Set a flag variable.
|
||
|
||
flgprt: skipn (a)
|
||
jrst [ type dspc,/AValue = FALSE
|
||
/
|
||
ret]
|
||
type dspc,/AValue = TRUE
|
||
/
|
||
ret
|
||
|
||
;;; Set a flag-style variable.
|
||
|
||
flgset: call plock ; Lock database for unpurity.
|
||
aose (a) ; if -1, make it zero
|
||
setom (a) ; Else -1
|
||
move t,[440700,,[asciz /TRUE/]]
|
||
skipn (a)
|
||
move t,[440700,,[asciz /FALSE/]]
|
||
copy t,bp
|
||
call pulock ; unlock it and repurify.
|
||
ret
|
||
|
||
|
||
|
||
;;; HAKTAB is a utility for hacking tables.
|
||
;;; It can be called by parameter setting routines such as SNET.
|
||
|
||
;;; The argument table for HAKTAB describes useful combinations of
|
||
;;; object-reading, object-comparing, and table-printing routines.
|
||
|
||
hk%rd==:0 ;Function to call to read object.
|
||
hk%dsp==:1 ;Function to call to display table.
|
||
hk%cmp==:2 ;Function to call to compare objects.
|
||
; A and B and skip if they are equal.
|
||
define hakdef read,prt,cmp
|
||
read
|
||
prt
|
||
IFSE cmp,EQ, [ came a,b ? jrst cpopj ? jrst popj1 ]
|
||
.ELSE cmp
|
||
termin
|
||
|
||
6tabtb: hakdef tread6,e6tab,EQ
|
||
snthtb: hakdef rdhost,enet,netwrk"hstcmp
|
||
|
||
;;; Routines called from HAKTAB for various kinds of objects.
|
||
;;; Readers skip return with the frob in A, else non-skip.
|
||
|
||
;;; Read a sixbit frob.
|
||
|
||
tread6: type dspc,/AEntry: /
|
||
call read6 ; Read it.
|
||
ret
|
||
move a,arg6 ; Get it to return.
|
||
IFN 0,[
|
||
idpb6 a,bp ; Output it to mail
|
||
move t,[440700,,[asciz /
|
||
/]]
|
||
copy t,bp
|
||
] ;IFN 0
|
||
jrst popj1 ;Win.
|
||
|
||
|
||
;;; Routine to read a network host name.
|
||
;;; Returns a host number.
|
||
|
||
rdhost: save [d]
|
||
terpri
|
||
call netwrk"hostnm ; Read in the host name.
|
||
jrst [ type dspc,/ANo such host.
|
||
/
|
||
movei t,30.
|
||
.sleep t,
|
||
restore [d]
|
||
ret ]
|
||
rdhos9: restore [d]
|
||
jrst popj1
|
||
|
||
|
||
|
||
;;; HAKTAB - Add or Delete an item from a table.
|
||
;;; The user types in an object, and it is added or delete to a table.
|
||
;;; Takes address in database of table (ie., LUCKTB) in A.
|
||
;;; Requires HAKDEF pointer in D.
|
||
;;; (Note: BP should point to MSGBUF for logging. KVAR does this.)
|
||
|
||
.upure
|
||
tabptr: 0 ;Table pointer
|
||
tabadr: 0 ;Table address.
|
||
.pure
|
||
|
||
haktab: save [a,b,c,d,e]
|
||
movem a,tabadr
|
||
call pwsget ; Get the table from the database.
|
||
movem t,tabptr
|
||
hakta1: ask /ADo you wish to add an entry?/
|
||
caia ; Maybe he wants to delete.
|
||
jrst hakadd ; He wants to add.
|
||
skipe a ; If no entries, can't delete.
|
||
ask /ADo you wish to delete an entry?/
|
||
jrst [ type dspc,/AYou're confused!
|
||
/
|
||
jrst hakta9 ] ; Maybe he was just confused.
|
||
; Fall through for deletion.
|
||
|
||
;;; Here to delete an entry.
|
||
|
||
hakdel: move tt,[440700,,[asciz /Deleting /]]
|
||
copy tt,bp ; Log what we are doing.
|
||
call @hk%rd(d) ; A gets user object.
|
||
jrst hakta9 ; Reading failed?
|
||
move c,tabptr
|
||
hakde0: move b,(c) ; B gets table object.
|
||
call @hk%cmp(d) ; Compare them.
|
||
jrst [ aobjn c,hakde0 ; No match - try another.
|
||
type dspc,/ANot found.
|
||
/
|
||
movei a,30.
|
||
.sleep a, ; Pause a moment.
|
||
jrst hakde9 ] ; Give up if frob not in table.
|
||
hakde2: hlre a,c ; Now move stuff around.
|
||
movns a ; Get the count remaining (positive).
|
||
soje a,hakde3 ; If last entry, just update pointer.
|
||
hrli b,1(c) ; Where to get entries.
|
||
hrri b,(c) ; Where to put them.
|
||
addi a,-1(c) ; Where to end.
|
||
blt b,(a) ; Move them.
|
||
hakde3: move b,tabptr ; AOBJN ptr to data.
|
||
add b,[1,,0] ; Shrink the table ptr by one.
|
||
movem b,tabptr
|
||
move a,tabadr ; Retrieve address of table.
|
||
call pwsput ; Store the shrunken table
|
||
|
||
hakde9: type dspc,/C/ ; Display the table
|
||
move a,tabadr ; Retrieve table address
|
||
call @hk%dsp(d)
|
||
ask /AWould you like to delete another entry?/
|
||
caia ; No. Maybe add?
|
||
jrst hakdel ; Go delete another.
|
||
ask /AWould you like to add a entry?/
|
||
caia ; No. all done.
|
||
jrst hakadd ; Go to addition loop
|
||
jrst hakta9 ; All done.
|
||
|
||
;;; Here to add an entry.
|
||
|
||
hakadd: move tt,[440700,,[asciz /Adding /]]
|
||
copy tt,bp ; Log what we are doing.
|
||
call @hk%rd(d) ; A gets user object.
|
||
jrst hakta9 ; Reading failed?
|
||
move c,tabptr ; Check table for the object.
|
||
hakad0: move b,(c) ; B gets table object.
|
||
call @hk%cmp(d) ; Compare them.
|
||
jrst [ aobjn c,hakad0 ; No match - try another.
|
||
jrst hakad1 ] ; OK - it's not already there.
|
||
type dspc,/AAlready in table.
|
||
/
|
||
movei a,30.
|
||
.sleep a, ; Pause a moment.
|
||
jrst hakad9 ; It's already there?
|
||
|
||
hakad1: movem a,(c) ; Store the host in the table
|
||
move b,tabptr ; AOBJN ptr to data.
|
||
sub b,[1,,0] ; Grow the table ptr by one.
|
||
movem b,tabptr
|
||
move a,tabadr ; Retrieve table address
|
||
call pwsput ; Store updated table
|
||
hakad9: type dspc,/C/ ; Display the table.
|
||
move a,tabadr ; Retrieve table address
|
||
call @hk%dsp(d)
|
||
ask /AWould you like to add another entry?/
|
||
caia
|
||
jrst hakadd
|
||
ask /AWould you like to delete a entry?/
|
||
jrst hakta9
|
||
jrst hakdel
|
||
hakta9: restore [e,d,c,b,a] ; Exit.
|
||
ret
|
||
|
||
|
||
|
||
|
||
;;; These routines Examine and Set parameters.
|
||
;;; (Reference these in PARAM declarations.)
|
||
;;; All these routines expect a pointer to the table in A.
|
||
|
||
;;; Examine a table of 6bit items.
|
||
|
||
e6tab: save [t,a]
|
||
call pwsget ; Get the table
|
||
movei t,tmpbuf ; ptr into TMPBUF of items
|
||
call e6tab0 ; Print them all
|
||
restore [a,t]
|
||
ret
|
||
|
||
e6tab0: save [t,tt,a]
|
||
e6taba: jumpe a,e6tab3 ; if no items, just return
|
||
movei tt,8 ; 8 items accross
|
||
e6tab1: 6type tyoc,(t) ; type this item
|
||
aos t
|
||
sojg tt,e6tab2 ; one item typed
|
||
terpri ; End of line
|
||
sojg a,e6taba
|
||
jrst e6tab3
|
||
e6tab2: tyo tyoc,[^I] ; tab to next position
|
||
sojg a,e6tab1 ; next item
|
||
e6tab3: restore [a,tt,t]
|
||
ret
|
||
|
||
;;; Set 6bit table.
|
||
|
||
s6tab: save [d]
|
||
movei d,6tabtb
|
||
call haktab
|
||
caia
|
||
aos -1(p)
|
||
restore [d]
|
||
ret
|
||
|
||
|
||
;;; Examine Network Host Table.
|
||
|
||
enet: save [a,b,d,bp]
|
||
call pwsget ; Get table from database.
|
||
jumpe a,enet5 ; If zero length, all done.
|
||
move ct,(a) ; Count in A, AOBJN in T.
|
||
seto tt,
|
||
enet0: move b,(t) ; Get host address.
|
||
jumpe b,enet4
|
||
save [t,tt] ; (Save temps from NETWRK.)
|
||
move bp,[440700,,outbuf] ; BP to typeout buffer.
|
||
call netwrk"hstsrc ; Look up this host address
|
||
jrst [ idpb8 a,bp ; No name - just print its number.
|
||
tyobpi bp,0 ; Tie off the BP.
|
||
jrst enet1 ] ; Found it!
|
||
hrr x,a ; Get BP to host name.
|
||
hrli x,440700
|
||
copy x,bp ; Copy host name into output buffer.
|
||
enet1: move bp,[440700,,outbuf] ; Reset the byte pointer.
|
||
restore [tt,t] ; (Get back temps.)
|
||
jumpl tt,[ terpri ; First position
|
||
jrst enet3]
|
||
JUMPE tt,[ type dspc,/H!/
|
||
jrst enet3] ; Second position
|
||
|
||
type dspc,/H@/ ; Last position
|
||
seto tt, ; First position again
|
||
caia
|
||
enet3: aos tt ; Next position
|
||
outstr tyoc,bp ; Type out the host name.
|
||
enet4: aobjn t,enet0 ; Get another entry.
|
||
terpri
|
||
enet5: restore [bp,d,b,a]
|
||
ret
|
||
|
||
;;; Set Network Host table.
|
||
|
||
snet: save [d]
|
||
movei d,snthtb
|
||
call haktab
|
||
caia
|
||
aos -1(p)
|
||
restore [d]
|
||
ret
|
||
|
||
|
||
|
||
|
||
;;; Print the table of TTY lines
|
||
|
||
ttylis: move tt,@ttyin0(a)
|
||
move t,@ttyin1(a)
|
||
setz x, ; TTY #
|
||
setz a, ; # of tty's typed
|
||
ttyls0: caile x,77 ; Last TTY?
|
||
jrst ttyls3
|
||
trnn tt,1 ; Is this one in the table?
|
||
jrst ttyls2 ; Nope, don't print
|
||
skipe a ; If not first, separate
|
||
type tyoc,/, /
|
||
tyo tyoc,["T] ; TTY number,
|
||
caige x,10
|
||
tyo tyoc,["0] ; complete with no leading zero suppression
|
||
8type tyoc,x
|
||
aos a ; count # printed on this line
|
||
caige a,20 ; Line full?
|
||
jrst ttyls2 ; line not full
|
||
setz a, ; start
|
||
terpri ; a new line
|
||
ttyls2: lshc t,-1 ; next TTY
|
||
aoja x,ttyls0
|
||
ttyls3: terpri
|
||
ret
|
||
|
||
DDTTTB:
|
||
ttyms0==:0
|
||
440700,,[asciz /ADo you wish to make some TTY's get DDT?/]
|
||
440700,,[asciz /ADo you wish to make some TTY's get PWORD?/]
|
||
ttyms1==:2
|
||
440700,,[asciz /The following TTY's now get DDT:
|
||
/]
|
||
440700,,[asciz /The following TTY's now get PWORD:
|
||
/]
|
||
ttyin0==:4
|
||
iorm tt,ddtty0
|
||
andcam tt,ddtty0
|
||
ttyin1==:6
|
||
iorm t,ddtty1
|
||
andcam t,ddtty1
|
||
|
||
|
||
DILTTB:
|
||
440700,,[asciz /ADo you wish to make some TTY's reserved?/]
|
||
440700,,[asciz /ADo you wish to make some TTY's not reserved?/]
|
||
|
||
440700,,[asciz /The following TTY's are now reserved:
|
||
/]
|
||
440700,,[asciz /The following TTY's are no longer reserved:
|
||
/]
|
||
|
||
iorm tt,dltty0
|
||
andcam tt,dltty0
|
||
|
||
iorm t,dltty1
|
||
andcam t,dltty1
|
||
|
||
; END of DILTTB
|
||
|
||
ttyset: move bp,[440700,,msgbuf]
|
||
move b,a ; Remember the address of our info block
|
||
askusr @ttyms0(b)
|
||
jrst ttyttp
|
||
jrst ttyttx
|
||
|
||
ttyttp: aos b ; Let's get the alternate version
|
||
askusr @ttyms0(b) ; Ask about it
|
||
ret
|
||
ttyttx: move t,ttyms1(b) ; Get the informative message
|
||
copy t,bp ; and copy to mail output
|
||
type dspc,/ATTY #'s (Tnn, Tnn): /
|
||
call readln ; Read in a line
|
||
ret
|
||
move bp,argloc
|
||
ttyst0: sosge argcnt ; Take one character
|
||
ret ; Nothing left
|
||
ildb ch,bp
|
||
caie ch,40 ; space
|
||
cain ch,",
|
||
jrst ttyst0 ; Ignore
|
||
caie ch,"t
|
||
cain ch,"T
|
||
jrst ttyst1 ; Ignore, number follows
|
||
cain ch,^I
|
||
jrst ttyst0 ; Ignore
|
||
jrst ttyst2
|
||
|
||
ttyst1: sosge argcnt ; Take one character
|
||
jrst ttystx
|
||
ildb ch,bp
|
||
ttyst2: cail ch,"0 ; Digit-p?
|
||
caile ch,"9
|
||
jrst ttystx ; No, lose
|
||
subi ch,"0
|
||
movei a,(ch)
|
||
sosge argcnt ; Take one character
|
||
jrst ttyst3 ; Nothing left
|
||
ildb ch,bp ; Next character
|
||
caie ch,", ; Terminator?
|
||
cain ch,40
|
||
jrst ttyst3
|
||
cain ch,^I
|
||
jrst ttyst3
|
||
cail ch,"0 ; Digit-p?
|
||
caile ch,"9
|
||
jrst ttystx ; No, lose
|
||
subi ch,"0 ; convert to number
|
||
lsh a,3
|
||
addi a,(ch) ; full 2-digit octal number
|
||
ttyst3: movei tt,1 ; get the bit
|
||
setz t,
|
||
lshc t,(a) ; refering to this TTY number
|
||
save [t,tt]
|
||
call plock ; Lock the database
|
||
restore [tt,t]
|
||
xct ttyin0(b)
|
||
xct ttyin1(b)
|
||
call pulock ; unlock the database
|
||
jrst ttyst0
|
||
|
||
ttystx: type dspc,/AInvalid TTY #
|
||
/
|
||
ret
|
||
|
||
|
||
SUBTTL Hacking Groups
|
||
|
||
grpprt: save [t,a]
|
||
terpri
|
||
movei t,pwgnam ; Table of group names
|
||
movei a,pwgrct ; Count of entries
|
||
call e6tab0 ; Print the table
|
||
restore [a,t]
|
||
ret
|
||
|
||
;; Print the status of a group, offering to set it
|
||
|
||
grpset: save [x,ch,t,a,c]
|
||
call r6arg ; Parse our argument
|
||
grpstr: move bp,[440700,,usrbfr]
|
||
skipe arg6
|
||
jrst [ call rdgrp6 ; Look up the group
|
||
jrst grpst ; Lost...
|
||
jrst grpst1]
|
||
grpst: type dspc,/C/
|
||
call rdgrp ; List all the groups
|
||
jrst grpstx
|
||
grpst1: movei c,(a) ; Get group #
|
||
save [bp]
|
||
move bp,[440700,,msgbuf]
|
||
call grpdsc ; Describe the group
|
||
restore [bp]
|
||
terpri
|
||
output tyoc,msgbuf ; print the description on the screen
|
||
ask /ADo you wish to modify anything?/
|
||
jrst grpst
|
||
|
||
call grpdsc
|
||
|
||
grpst2: type dspc,/C/
|
||
movei a,(c)
|
||
save [bp]
|
||
move bp,[440700,,msgbuf]
|
||
call grpdsc ; Describe the group in the mail
|
||
restore [bp]
|
||
output tyoc,msgbuf ; put description at top of screen
|
||
type dspc,/A
|
||
1 -- Weekday time restriction
|
||
2 -- Saturday time restriction
|
||
3 -- Sunday time restriction
|
||
4 -- Name of group
|
||
5 -- Daytime use message
|
||
6 -- Dialup use message
|
||
7 -- Dialup permission
|
||
8 -- Choose another Group
|
||
9 -- Quit
|
||
|
||
Enter one: /
|
||
.iot tyic,ch
|
||
cain ch,"1
|
||
jrst [ call gtimrd ; Read the date
|
||
jrst grpstf ; Failed, retry
|
||
call plock ; Make the page writable
|
||
dpb a,[dm$wds pwgrdm(c)] ; Set the start time
|
||
dpb b,[dm$wde pwgrdm(c)] ; and the unstart time
|
||
call pulock ; Repurify the page
|
||
jrst grpst9] ; More!
|
||
cain ch,"2 ; saTurday time restriction
|
||
jrst [ call gtimrd ; Read the date
|
||
jrst grpstf ; Failed, retry
|
||
call plock ; Make the page writable
|
||
dpb a,[dm$sts pwgrdm(c)]
|
||
dpb b,[dm$ste pwgrdm(c)]
|
||
call pulock
|
||
jrst grpst9]
|
||
cain ch,"3
|
||
jrst [ call gtimrd
|
||
jrst grpstf
|
||
call plock
|
||
dpb a,[dm$sns pwgrdm(c)]
|
||
dpb b,[dm$sne pwgrdm(c)]
|
||
call pulock
|
||
jrst grpst9]
|
||
cain ch,"4 ; Change the name of the group?
|
||
jrst [ type dspc,/AEnter new name for this group: /
|
||
save [bp]
|
||
call read6 ; Read a 6bit name
|
||
jrst [ restore [bp]
|
||
jrst grpst2]
|
||
restore [bp]
|
||
skipn a,arg6 ; The new name!
|
||
jrst grpst2 ; A Real Nothing
|
||
call plock ; Depurify it
|
||
movem a,pwgnam(c) ; update the name!
|
||
call pulock
|
||
jrst grpst9]
|
||
cain ch,"5 ; Daytime message?
|
||
movei a,timmsg(c) ; Address of where to put it
|
||
cain ch,"6 ; Dialup message?
|
||
movei a,dilmsg(c) ; Address of where to put it
|
||
caie ch,"5
|
||
cain ch,"6
|
||
jrst [ type dspc,/AEnter new message: /
|
||
save [bp]
|
||
call pwstxt ; Read in the message
|
||
jfcl
|
||
restore [bp]
|
||
jrst grpst9] ; Abort, keep hacking
|
||
cain ch,"7
|
||
jrst grpsdl
|
||
cain ch,"8 ; Choose another group?
|
||
jrst grpstn ; yep!
|
||
caie ch,"9
|
||
cain ch,"Q ; Quit?
|
||
jrst grpstx
|
||
cain ch,"q
|
||
jrst grpstx
|
||
type tyoc,/ Huh?? /
|
||
jrst grpst2 ; try again!
|
||
|
||
grpstn: skipn rdxct ; Have we done anything yet?
|
||
jrst grpstr ; nope, just keep trying
|
||
call grpsml ; send the mail
|
||
jrst grpstr ; reset!
|
||
|
||
grpsml: write bp,/
|
||
---- becomes ----
|
||
/
|
||
call grpdsc ; Describe the new state
|
||
.mail grpmal ; Send the mail
|
||
setzm rdxct
|
||
ret
|
||
|
||
|
||
grpst9: movem c,rdxarg ; Remember the group for sending mail
|
||
movem bp,rdxbp
|
||
move x,[call grpsml]
|
||
movem x,rdxct ; make sure this gets sent when done
|
||
jrst grpst2
|
||
|
||
grpstf: type dspc,/AIllegal date format!/
|
||
movei x,15.
|
||
.sleep x,
|
||
jrst grpst2 ; loop
|
||
|
||
; hack dialup toggling
|
||
grpsdl: call plock
|
||
movei t,1 ; Bit for group # to mask in dialup
|
||
lsh t,(c) ; restriction test
|
||
tdne t,pwgdil ; Check against database
|
||
jrst grpsdn
|
||
iorm t,pwgdil
|
||
call pulock
|
||
jrst grpst9
|
||
|
||
grpsdn: andcam t,pwgdil
|
||
call pulock
|
||
jrst grpst9
|
||
|
||
grpstb: restore [bp]
|
||
grpstx: restore [c,a,t,ch,x]
|
||
ret
|
||
|
||
;; GRPDSC takes a group in A, and describes that group
|
||
|
||
grpdsc: save [x,t,tt,a]
|
||
move x,pwgnam(a) ; include the group name
|
||
idpb6 x,bp
|
||
write bp,/ Weekday: /
|
||
ldb t,[dm$wds pwgrdm(a)] ; Get when it starts
|
||
ldb tt,[dm$wde pwgrdm(a)] ; Get when it ends
|
||
call gprtim
|
||
write bp,/; Saturday: /
|
||
ldb t,[dm$sts pwgrdm(a)]
|
||
ldb tt,[dm$ste pwgrdm(a)]
|
||
call gprtim
|
||
write bp,/; Sunday: /
|
||
ldb t,[dm$sns pwgrdm(a)]
|
||
ldb tt,[dm$sne pwgrdm(a)]
|
||
call gprtim
|
||
push sp,a
|
||
skipn timmsg(a) ; Does this group have a restriction
|
||
jrst grdsc2 ; message?
|
||
movei a,timmsg(a)
|
||
write bp,/
|
||
This group's daytime restriction message is:
|
||
/
|
||
call pwsget ; get the message
|
||
move x,[440700,,tmpbuf]
|
||
copy x,bp ; copy it into the text
|
||
|
||
grdsc2: pop sp,a
|
||
movei t,1 ; Bit for group # to mask in dialup
|
||
lsh t,(a) ; restriction test
|
||
tdne t,pwgdil ; Check against database
|
||
jrst [ write bp,/
|
||
This group is NOT allowed to use the dialups.
|
||
Message:
|
||
/
|
||
movei a,dilmsg(a) ; Get the dialup message
|
||
call pwsget
|
||
move x,[440700,,tmpbuf]
|
||
copy x,bp
|
||
jrst grdsc3]
|
||
write bp,/
|
||
This group IS allowed to use the dialups.
|
||
/
|
||
grdsc3: setz x, ; Follow the output with a NUL to be IDPB'd
|
||
move t,bp
|
||
idpb x,t
|
||
restore [a,tt,t,x]
|
||
ret
|
||
|
||
|
||
;; Take start time in T and end time in TT (group restriction format, of
|
||
;; # of 1/2 hours past midnight; 77 ==> no restriction). Write the time to BP
|
||
|
||
gprtim: save [x,t]
|
||
cain t,77 ; No restriction?
|
||
jrst [ write bp,/NONE/
|
||
restore [t,x]
|
||
ret]
|
||
lsh t,-1 ; Get # of hours past midnite
|
||
caige t,10. ; If < 10, type leading zero explicitly
|
||
jrst [ tyobpi bp,"0
|
||
jrst .+1]
|
||
idpb10 t,bp ; Write the time to the BP
|
||
restore [t]
|
||
trne t,1 ; 1/2 hour?
|
||
jrst [ write bp,/30-/
|
||
jrst .+1]
|
||
trnn t,1 ; On the hour?
|
||
jrst [ write bp,/00-/
|
||
jrst .+1]
|
||
save [tt]
|
||
lsh tt,-1 ; Get # of hours past midnite
|
||
caige tt,10. ; If < 10, type leading zero explicitly
|
||
jrst [ tyobpi ,"0
|
||
jrst .+1]
|
||
idpb10 tt,bp
|
||
restore [tt]
|
||
trne tt,1 ; 1/2 hour?
|
||
jrst [ write bp,/30/
|
||
jrst .+1]
|
||
trnn tt,1 ; On the hour?
|
||
jrst [ write bp,/00/
|
||
jrst .+1]
|
||
restore [x]
|
||
ret
|
||
|
||
;;; GTIMRD reads in a restriction-format time rage into A and B.
|
||
;;; Allowable formats are: NONE; 6-12; 600-1230
|
||
|
||
gtimrd: save [bp]
|
||
type dspc,\AEnter time range accurate to 1/2 hour (i.e. 6-1430) or NONE
|
||
Time: \
|
||
move bp,[440700,,msgbuf]
|
||
call readln ; Read in a line
|
||
jrst gtimrx
|
||
move bp,argloc
|
||
move ct,argcnt
|
||
cain ct,4 ; Is this 4 long?
|
||
jrst gtimra ; Maybe it's NONE?
|
||
gtimr0: setzb a,b
|
||
call gtimrn ; Get the first #
|
||
jrst gtimrx
|
||
ildb ch,bp ; Advance past the termination
|
||
soje ct,cpopj
|
||
exch a,b
|
||
call gtimrn ; Get the second #
|
||
jrst gtimrx
|
||
exch a,b
|
||
caile a,48. ; Had better be less than or = midnight
|
||
jrst gtimrx
|
||
caile b,48.
|
||
jrst gtimrx
|
||
cain a,77 ; If this is ALL, they can be the same
|
||
jrst gtimwn
|
||
caml a,b ; Otherwise
|
||
jrst gtimrx ; A had better be less than B
|
||
gtimwn: skipn ct ; Is there still more stuff?
|
||
gtimx1: aos -1(sp) ; No, fine, skip return
|
||
gtimrx: restore [bp]
|
||
ret
|
||
|
||
gtimra: push sp,bp
|
||
ildb ch,bp ; Check first char
|
||
caie ch,"n
|
||
cain ch,"N
|
||
caia
|
||
jrst gtima0
|
||
ildb ch,bp
|
||
caie ch,"o
|
||
cain ch,"O
|
||
caia
|
||
jrst gtima0
|
||
ildb ch,bp
|
||
caie ch,"n
|
||
cain ch,"N
|
||
caia
|
||
jrst gtima0
|
||
ildb ch,bp
|
||
caie ch,"e
|
||
cain ch,"E
|
||
caia
|
||
jrst gtima0
|
||
movei a,77 ; Return ALL time
|
||
movei b,77
|
||
pop sp,bp
|
||
jrst gtimx1
|
||
|
||
gtima0: pop sp,bp
|
||
jrst gtimr0
|
||
|
||
;; Gobble one number
|
||
gtimrn: call gtimrp ; Count the digits
|
||
ret ; Syntax error
|
||
cain x,1 ; 1 is simple
|
||
jrst gtimn1
|
||
cain x,2 ; 2 is also fairly simply
|
||
jrst gtimn2
|
||
cain x,3 ; 3 is of 100 or 130 variety
|
||
jrst gtimn3
|
||
cain x,4 ; 4 is full 24 hr time
|
||
jrst gtimn4
|
||
ret ; Too many digits, syntax error
|
||
|
||
gtimn2: ildb ch,bp ; Get 10's digit
|
||
cail ch,"3 ; Illegal digit?
|
||
ret
|
||
subi ch,"0 ; DIGIT-WEIGHT
|
||
movei a,(ch) ; accumulate in A
|
||
imuli a,10. ; 10's digit
|
||
gtimn1: ildb ch,bp ; Next digit
|
||
subi ch,"0
|
||
addi a,(ch) ; That's the number!
|
||
imuli a,2 ; convert to # of half-hours
|
||
jrst popj1
|
||
|
||
gtimn3: call gtimn1 ; Gobble down the hour's digit
|
||
ret
|
||
caia
|
||
gtimn4: call gtimn2 ; Gobble down the hour's digits
|
||
jfcl
|
||
ildb ch,bp ; Get the 10-minute digit
|
||
cain ch,"3 ; 1/2 hour?
|
||
aos a ; Count it
|
||
caie ch,"0 ; Is it a legal time?
|
||
cain ch,"3
|
||
caia
|
||
ret ; Nope!
|
||
ildb ch,bp ; Is it a legal time?
|
||
cain ch,"0 ; Either 00 or 30
|
||
jrst popj1 ; yes
|
||
ret ; no
|
||
|
||
;; Count off the digits of one number
|
||
gtimrp: move t,bp ; Remember where our number begins
|
||
setz x, ; # of characters in this number
|
||
gtimp0: ildb ch,bp ; or maybe not
|
||
cain ch,"- ; -?
|
||
jrst gtimp1
|
||
caig ch,"9 ; Digitp?
|
||
caige ch,"0
|
||
ret ; Nope, syntax error
|
||
aos x
|
||
sojg ct,gtimp0
|
||
|
||
gtimp1: move bp,t ; Back up our BP
|
||
jrst popj1
|
||
|
||
|
||
|
||
SUBTTL Assorted Commands
|
||
|
||
;;; Implement the FIND command in PANDA.
|
||
|
||
kfind: call r6arg ; Parse out "creator" arg.
|
||
call rcarg ; Parse out control args.
|
||
ret
|
||
move x,crgbts ; Check out control options.
|
||
setzm brfflg ; Assume we want verbosity.
|
||
trne x,CF$PBF ; If we want it brief
|
||
setom brfflg ; remember so.
|
||
skipn t,arg6 ;check for an argument.
|
||
jrst [ type dspc,/AHuh? I dont know who to look for.
|
||
/
|
||
ret ]
|
||
movem t,cretor ; Remember the target creator.
|
||
kfind1: .suset [.rhsname,,ot.snm] ; Change output sname to our own dir.
|
||
movei x,[asciz /AWhere should I file the list?/]
|
||
movem x,filprm ; Set up prompt.
|
||
movei x,outfil ; Say this is the default.
|
||
call flprmp ; Prompt for file name with default.
|
||
call readfi ; Read the file name.
|
||
jfcl ; Eh?
|
||
move d,argptr ; Pointer to the file name string.
|
||
movei b,outfil ; Where to put the file name.
|
||
call rfn"rfn ; Parse file name.
|
||
syscal open,[cnti .uao ; Open our output file.
|
||
argi dsko
|
||
ot.dev
|
||
ot.fn1
|
||
ot.fn2
|
||
ot.snm ]
|
||
jrst [ type dspc,/ACannot open output file.
|
||
/
|
||
ret ]
|
||
call maplsr ; Map in the INQUIR database.
|
||
setz a, ; Begin counting entries.
|
||
kfind2: call pwdget ; Get an entry.
|
||
move x,pdunam ; Convert his name to normal 6bit.
|
||
sub x,[742532,,732643] ; Will oddities never cease?
|
||
rot x,-13 ; (obviously not).
|
||
movem x,uname ; Save it for later.
|
||
save [b,a] ; Save our AC's for later.
|
||
movei a,pwadmn ; Get the table of creators.
|
||
call pwsget
|
||
ldb tt,[pi$crt pdinfo] ; Get the creator index.
|
||
jumpe tt,kfind9 ; Cannot match unknown creator.
|
||
move tt,tmpbuf-1(tt) ; Get this entry's creator name.
|
||
came tt,cretor ; If this is not the target creator
|
||
jrst kfind9 ; try another entry.
|
||
kfind3: move bp,[440700,,msgbuf] ; Bp to information we find.
|
||
tyobpi bp,^M
|
||
tyobpi bp,^J
|
||
move x,uname
|
||
idpb6 x,bp ; Write the uname.
|
||
skipe brfflg ; If we are being brief
|
||
jrst kfind8 ; dont print anything else.
|
||
tyobpi bp,^I
|
||
ldb tt,[pi$sta pdinfo] ; Get the state of this account
|
||
cain tt,ps%sys ; Is this a system name?
|
||
jrst [ write bp,/[sys]/
|
||
jrst .+1]
|
||
cain tt,ps%rfs ; Is he refused?
|
||
jrst [ write bp,/[rfs]/
|
||
jrst .+1]
|
||
cain tt,ps%off ; Turned off?
|
||
jrst [ write bp,/[off]/
|
||
jrst .+1]
|
||
cain tt,ps%hld ; On hold?
|
||
jrst [ write bp,/[hld]/
|
||
jrst .+1]
|
||
cain tt,ps%ok
|
||
jrst [ write bp,/[ok]/ ; Would you believe, normal?
|
||
jrst .+1]
|
||
tyobpi bp,^I
|
||
kfind4: movei a,lsrc ; Tell LSRTNS what channel it can hack.
|
||
move b,uname ; Get Inquire entry address.
|
||
call lsrtns"lsrunm ; Is it there?
|
||
jrst [ write bp,/ --> Not in Inquire database <--/
|
||
jrst kfind8 ]
|
||
movem b,lsrptr ; Save pointer to this Inquire entry.
|
||
movei a,lsrtns"i$name ; Find his name.
|
||
call lsrtns"lsritm
|
||
jrst [write bp,/ --> Name Missing in Inquire <--/
|
||
jrst kfind8 ] ; unsuccessful.
|
||
move b,bp ; Where to get his name.
|
||
call lsrtns"lsrnam ; Write his name nicely.
|
||
jfcl ; eh?
|
||
move bp,b ; Recover the byte pointer.
|
||
decbp bp ; Back over the null.
|
||
kfind8: setz ch, ; End text with a nul.
|
||
idpb ch,bp
|
||
output dsko,msgbuf ; Write text to file.
|
||
kfind9: restore [a,b] ; Pick up count where we left off.
|
||
addi a,pwleng ; Point to next entry.
|
||
camg a,pwcnt ; Is this all?
|
||
jrst kfind2 ; Nope, loop for another one.
|
||
.close dsko, ; All done. Close output file.
|
||
ret
|
||
|
||
|
||
;;; Implement the CHECK command in PANDA.
|
||
|
||
kcheck: save [a,b,c,d,e]
|
||
movei x,[asciz /AInput file of alleged users?/]
|
||
movem x,filprm ; Set up prompt.
|
||
movei x,infil ; Say this is the default.
|
||
call flprmp ; Prompt for file name with default.
|
||
call readfi ; Read the file name.
|
||
jfcl ; Eh?
|
||
move d,argptr ; Pointer to the file name string.
|
||
movei b,infil ; Where to put the file name.
|
||
call rfn"rfn ; Parse file name.
|
||
syscal open,[cnti .uai ; Open our input file.
|
||
argi dski
|
||
in.dev
|
||
in.fn1
|
||
in.fn2
|
||
in.snm ]
|
||
jrst [ type dspc,/AUnable to open the file!
|
||
/
|
||
jrst kchec9 ]
|
||
setzm checkp ; Assume we are looking for accounts.
|
||
ask /ALooking for valid accounts?/
|
||
jrst [ setom checkp
|
||
type dspc,/AOK, listing unknown UNAMEs./
|
||
jrst .+1 ]
|
||
movei x,[asciz /AFile to list invalid UNAMEs in:/]
|
||
skipn checkp ; Alter prompt if looking for winners.
|
||
movei x,[asciz /AFile to list valid accounts in:/]
|
||
movem x,filprm ; Set up prompt.
|
||
movei x,outfil ; Say this is the default.
|
||
call flprmp ; Prompt for file name with default.
|
||
call readfi ; Read the file name.
|
||
jfcl ; Eh?
|
||
move d,argptr ; Pointer to the file name string.
|
||
movei b,outfil ; Where to put the file name.
|
||
call rfn"rfn ; Parse file name.
|
||
syscal open,[cnti .uao ; Open our output file.
|
||
argi dsko
|
||
ot.dev
|
||
ot.fn1
|
||
ot.fn2
|
||
ot.snm ]
|
||
jrst [ type dspc,/ACannot open output file.
|
||
/
|
||
jrst kchec9 ]
|
||
setz e, ; Count UNAMEs read from file.
|
||
setz d, ; Count UNAMEs which are really accounts.
|
||
kchec1: setz a, ; Accumulate uname from DSKI.
|
||
move b,[440600,,a] ; Sixbit BP to result.
|
||
kchec2: .iot dski,ch
|
||
cain ch,^M ; Check for CR
|
||
jrst [ .iot dski,ch ; Gobble LF.
|
||
jrst kchec3 ] ; End of UNAME.
|
||
andi ch,-1
|
||
cain ch,^C
|
||
jrst kchec7 ; EOF - no more names.
|
||
cail ch,140 ; Hack case.
|
||
subi ch,40 ; To sixbit.
|
||
tlnn b,770000 ; Gobble only six characters.
|
||
jrst kchec3
|
||
subi ch,40
|
||
idpb ch,b ; Remember this char.
|
||
jrst kchec2 ; Go get another.
|
||
kchec3: aos e ; Count each UNAME
|
||
movem a,uname
|
||
kchec4: call pwdlok ; Check for uname in A.
|
||
jrst [ skipn checkp ; No account.
|
||
jrst kchec6 ; (We're looking for accounts.)
|
||
jrst kchec5 ] ; (We're looking for others.)
|
||
skipe checkp ; Has account.
|
||
jrst kchec6 ; (We're looking for others.)
|
||
kchec5: aos d ; Write down this UNAME.
|
||
6type dsko,uname ; Type uname in file.
|
||
tyo dsko,[^M]
|
||
tyo dsko,[^J]
|
||
kchec6: jrst kchec1 ; Get another.
|
||
|
||
kchec7: type dspc,/AChecked /
|
||
10type tyoc,e
|
||
type dspc,/ UNAMEs; /
|
||
10type tyoc,d
|
||
skipn checkp
|
||
jrst [ type dspc,/ corresponded to real accounts./
|
||
jrst kchec9 ]
|
||
type dspc,/ did not correspond to accounts./
|
||
kchec9: .close dski, ; All done.
|
||
.close dsko, ; Close files.
|
||
restore [e,d,c,b,a]
|
||
ret
|
||
|
||
|
||
;;; Implement the PRINT command in PANDA
|
||
|
||
kuprin: call r6arg ; Parse the command
|
||
call rcarg
|
||
ret
|
||
move x,crgbts ;check it out
|
||
setzm allflg
|
||
setzm brfflg
|
||
setzm nodate
|
||
trne x,CF$PAL ;do we want it all?
|
||
setom allflg ; yes, note the fact
|
||
trne x,CF$PND ; suppress dates
|
||
setom nodate ; yes, note the fact
|
||
|
||
trne x,CF$PAL ;if it's -ALL,
|
||
do [tyo dspc,[^P]
|
||
tyo dspc,["C]] ; clear the screen
|
||
trne x,CF$PBF ; do we want it brief?
|
||
setom brfflg
|
||
skipn t,arg6 ;check for an argument.
|
||
pjrst pwdprt ; none, print them all
|
||
came t,[sixbit /*/]
|
||
camn t,[sixbit /ALL/] ; is it special case of "ALL" ?
|
||
pjrst pwdprt ; yes, print all them wihtout INQUIR
|
||
camn t,[sixbit /*UNKNOWN/]
|
||
jrst pwprul
|
||
camn t,[sixbit /*NULL/]
|
||
jrst pwprnl
|
||
camn t,[sixbit /*NEW/]
|
||
jrst pwprnw
|
||
movem t,uname ;remember this person
|
||
move d,a ;transfer pointer
|
||
call maplsr
|
||
pjrst usrwho ;who? are You?
|
||
|
||
|
||
] ; End of IFN $$PAND
|
||
|
||
|
||
SUBTTL Login
|
||
|
||
IFE $$PAND,[
|
||
ulogin: setom altusw ;note that we did it this way
|
||
terpri
|
||
setzm lbrief
|
||
skipe altifx ; If 0U or friends
|
||
setom lbrief ; note we want no init file.
|
||
jrst klog0
|
||
|
||
;;; We enter here from the :LOGIN form.
|
||
lbfbts=16 ;bits saying brief login
|
||
|
||
klogin: call r6arg ; Parse up the 6bit name
|
||
skipn arg6 ; Did he do :LOGIN<CR> ?
|
||
jrst [type dspc,/ADo :LOGIN <NAME>
|
||
/
|
||
ret]
|
||
call rcarg ; Decode the control arguments
|
||
ret
|
||
move x,crgbts ;check the switches
|
||
trne x,cf$lni ;did he ask for no init file? (-bf, -noinit)
|
||
setom lbrief ; note that he wants brief login
|
||
|
||
klog0: move x,arg6 ;our argument is our XUNAME
|
||
movem x,xuname ; retry it here
|
||
movem x,uname
|
||
.suset [.ssname,,x] ;for the sake of PEEK
|
||
call pwdmap ;map in the database
|
||
call pwdlok ;does he have a password?
|
||
pjrst pwhelp ; no, let's help him out.
|
||
|
||
save [uname]
|
||
call pwdget ;get his old entry
|
||
restore [uname]
|
||
call syschk ;check for system name
|
||
jrst [ldb x,[pi$sta pdinfo] ; check again, for HOLD
|
||
caie x,ps%hld
|
||
ret
|
||
pjrst ungot] ;Hackity hack, he's on hold, let him hack
|
||
|
||
call diltim ;prohibited by dialup or daytime?
|
||
phaser ; yes, flush him.
|
||
move x,crgbts ;check to see if he wanted to change it
|
||
trne x,cf$lpw ;did it?
|
||
do [setzm ttyflg ; be sure he sees this
|
||
type dspc,/AEnter your old password now!
|
||
/]
|
||
|
||
call pwask
|
||
jrst [type dspc,/AIncorrect.
|
||
/
|
||
sosge failct ; don't let him hack passwords forever
|
||
phaser
|
||
ret]
|
||
setzm pwbuf
|
||
setzm pwbuf+1
|
||
move x,crgbts ;get our flags
|
||
trne x,cf$lpw ;do we want to change it?
|
||
do [call pwdchg ; yes, change it!
|
||
ret] ; he rubbed out!
|
||
|
||
;;; When we get here, we've either gotten the entry via PWDGET or
|
||
;;; a new one from PWDCHG via PWDCNS.
|
||
|
||
log.in: move x,pdflag ;get the flags
|
||
tlze x,%pfnew ;turn off the new user bit if any
|
||
movem x,pdflag ; restore it
|
||
syscal rqdate,[val t] ;get the current date
|
||
setom t ; don't know!?
|
||
hlrm t,pddate ;right half = login date
|
||
call pwdput ; replace it
|
||
syscal login,[uname ? argi 0 ? xuname]
|
||
caia ;don't go to DDT if we didn't win!
|
||
jrst goddt
|
||
move x,calerr ;get the error returned
|
||
loglos: caie x,%erojb ;is it "CAN'T MODIFY JOB" ?
|
||
cain x,%etop ; or "NOT TOP LEVEL"?
|
||
jrst [type dspc,/AYou are hacking me.
|
||
/
|
||
jrst goddt] ; load DDT anyway
|
||
cain x,%ebdfn ;is it "ILLEGAL FILENAME" ?
|
||
error /Attempt to log in with illegal name./
|
||
cain x,%ensmd ;is it "MODE NOT AVAILABLE" ?
|
||
error /Attempt to log with intact inferiors./
|
||
caie x,%eexfl ;is it "FILE ALREADY EXISTS" ?
|
||
error /Unknown error from LOGIN call./
|
||
|
||
move t,[000600,,UNAME] ;yes, let's hack the uname
|
||
klogn0: ldb ch,t ;gobble a char
|
||
cain ch,0 ;is it a space?
|
||
jrst [decbp6 t ; back up the byte ptr
|
||
jrst klogn0] ; and try another
|
||
came t,[000600,,UNAME] ;is it 6 chars wide?
|
||
ibp t ; no, space over the last char
|
||
movei ch,'0 ;add a zero in at the end
|
||
dpb ch,t ;deposit it
|
||
|
||
klogn1: syscal login,[UNAME ? argi 0 ? xuname] ;try again with name0
|
||
jrst [move x,calerr ; lost, find out why.
|
||
caie x,%eexfl ; was it because duplication?
|
||
jrst loglos ; no, go barf and return to caller
|
||
addi ch,1 ;yes, advance the digit at end of name
|
||
dpb ch,t
|
||
caig ch,'@ ;don't advance into the letters
|
||
jrst klogn1
|
||
type dspc,/AToo many users all logged in with the same name.
|
||
/
|
||
ret ]
|
||
|
||
type dspc,/AAlready logged in, so logged you in as /
|
||
6type tyoc,UNAME ;tell him who he is
|
||
terpri
|
||
jrst goddt
|
||
|
||
] ; end of IFE $$PAND
|
||
|
||
pwdchg: type dspc,/AI will now ask you for a password.
|
||
Give anything you like, up to 12 characters.
|
||
Case does not matter.
|
||
End it with a carriage return.
|
||
/
|
||
pwadd5: call pwread
|
||
ret ;rubbed out or something
|
||
move x,pwbuf ;get the response
|
||
movem x,hispas ;and save it in HISPAS
|
||
move x,pwbuf+1 ;so we can compare with his next response
|
||
movem x,hispas+1 ;to avoid typo's and lossage
|
||
type dspc,/AI will now ask you to type the password in again,
|
||
to avoid the possibility of errors.
|
||
/
|
||
call pwread ;get it again
|
||
ret ; rubbed out?
|
||
|
||
move t,pwbuf ;get his second response
|
||
move tt,pwbuf+1
|
||
camn t,hispas ;is it right
|
||
came tt,hispas+1 ; the same as before?
|
||
jrst [type dspc,/AThey weren't the same. We will try it again.
|
||
/
|
||
jrst pwadd5] ; give him another chance
|
||
call pwdini ;Initialize the entry.
|
||
call pwdmak ;and add in the password
|
||
ife $$pand,[
|
||
type dspc,/AOK, be sure to remember it!
|
||
If you have any difficulties, send mail to USER-ACCOUNTS
|
||
or call /
|
||
movei a,phone
|
||
call pwgtxt ; Print the phone #
|
||
]
|
||
.else [ type dspc,/ADone.
|
||
/]
|
||
jrst popj1 ;skip-return to denote success
|
||
|
||
constants
|
||
|
||
|
||
;;; Unknown user routines.
|
||
;;; TELAPL sees how many losing unames have been tried.
|
||
;;; TELAP1 types verbose "no auto-applications" message.
|
||
|
||
telapl: move a,failun ; See how many times loser has lost.
|
||
caige a,2 ; If only first time, just mention it.
|
||
jrst [ type dspc,/AThat name is not known.
|
||
/
|
||
ret ] ; (Save long messages for two-time losers.)
|
||
telap1: movei a,naplmg ; Message about why no applications.
|
||
terpri
|
||
call pwgtxt ; Type it out.
|
||
terpri
|
||
ret
|
||
|
||
;;; help routine for unknown names.
|
||
|
||
ife $$pand,[
|
||
pwhelp: aos failun ; Count the number of unkown unames tried.
|
||
skipn atoapl ; Are we automatically running applications?
|
||
jrst telapl ; No, so make sure he gives a good name.
|
||
pwhel0: call maplsr
|
||
movei a,lsrc
|
||
move b,uname
|
||
call lsrtns"lsrunm
|
||
jrst [type dspc,/AThat name is not known.
|
||
/
|
||
sosge failct
|
||
phaser
|
||
jrst pwhel1] ;help him out
|
||
type dspc,/AThere is no password associated with that name.
|
||
/
|
||
sosge failct ;don't let him hack us forever
|
||
phaser ; a loser, hack him back
|
||
|
||
pwhel1: ask /Do you wish to apply for an account?/
|
||
ret
|
||
pjrst acoun1 ;give him help!
|
||
|
||
constants
|
||
|
||
;;; Ask for various info useful to USER-ACCOUNTS
|
||
|
||
kacoun: setzm uname ;no UNAME is known!
|
||
skipn atoapl ; If we are not doing auto-applications
|
||
jrst telap1 ; verbosely explain the situation.
|
||
acoun1: tyo dspc,[^P] ;clear the screen
|
||
tyo dspc,["C]
|
||
type dspc,/ANote: If you get into difficulties and wish to
|
||
abort this, just type a ^G (Control-G, the character that beeps)
|
||
/
|
||
setom apltim
|
||
skipe uname ;If there is no UNAME
|
||
jrst unchk ; there can't be any valid password!
|
||
|
||
setzm ttyflg ;turn on the TTY
|
||
move x,[
|
||
call [type dspc,/AHere are a few questions about your desire for an account.
|
||
|
||
A login name may be up to 6 characters, preferably letters.
|
||
There may be no spaces in this name.
|
||
Case is not preserved. It should *NOT* end in digits.
|
||
Enter your chosen login name:
|
||
/
|
||
setzm ttyflg ;turn on the TTY
|
||
skipn uname ;if there is a uname
|
||
type tyoc,/
|
||
Enter your chosen login name: /
|
||
ret]]
|
||
movem x,helper ;print help on this phase of the world
|
||
movem x,dsprmp
|
||
xct x ;print out the help
|
||
type tyoc,/
|
||
(You may type "^_H" (Control-underscore H)
|
||
(or the [HELP] key if you have one)
|
||
for more help at any point in this program.)
|
||
/
|
||
|
||
aurd0: type tyoc,/(End your input with a Carriage Return)
|
||
Enter your chosen login name: /
|
||
|
||
auread: move bp,[440700,,msgbuf] ;input buffer
|
||
setz count, ;no characters read yet.
|
||
call read6 ;read a 6-bit word
|
||
jrst aurd0 ; ask him for it again
|
||
cain ch,40 ;did he end with a space?
|
||
jrst [type dspc,/AThe name must not have any spaces in it!
|
||
Enter your chosen user-name: /
|
||
jrst auread]
|
||
skipn t,arg6 ;get his chosen UNAME
|
||
jrst [xct helper ; help him out
|
||
jrst auread] ; try some more
|
||
movem t,uname ;remember this name
|
||
|
||
;;; check the UNAME for trailing digits
|
||
unchk: type dspc,/AYou have given the login name "/
|
||
6type tyoc,uname
|
||
type tyoc,/"
|
||
/
|
||
move t,uname ;get the UNAME we want to check
|
||
setz tt, ;clear TT for shifting into
|
||
lshc t,-6 ;get the last 6bit char
|
||
jumpe tt,.-1 ;looping until we get it!
|
||
lsh tt,-36 ;right justify it
|
||
cail tt,'0 ;is it between 0
|
||
caile tt,'9 ; and 9?
|
||
caia ; no, so don't complain
|
||
jrst [type dspc,/AThe name must not end in a digit!
|
||
Please try again./
|
||
jrst aurd0] ; gobble down another attempt
|
||
|
||
;now that we've got the UNAME, do the work
|
||
|
||
call pwdmap ;map in the database
|
||
call pwdini ;get a password, (or make it!)
|
||
ldb x,[pi$sta pdinfo]
|
||
caie x,ps%hld ; Is it a account held for more info
|
||
cain x,ps%new ; or a new account?
|
||
caia ; Great, let him hack it
|
||
jrst accuse ; Nope, tell him it's in use
|
||
|
||
acounx: call pwdlok ;is he in the database? Can't let him ask
|
||
;for somebody elses!
|
||
jrst ungot ; not there. Get info
|
||
accuse: type dspc,/AThat name is in use already. Please choose another.
|
||
/
|
||
jrst acexit ;and exit
|
||
|
||
|
||
ungot: setom apltim
|
||
move bp,[440700,,msgbuf]
|
||
write bp,/Name: /
|
||
movem bp,namloc ;remember where his name starts!
|
||
call maplsr ;map in the database
|
||
movei a,lsrc ;tell LSRTNS what channel it can hack
|
||
move b,uname ;ask about this UNAME
|
||
setzm gotinq ; Set by ASKNAM if INQUIR entry exists
|
||
call lsrtns"lsrunm ;is it there?
|
||
namfoo: do [ type dspc,/AEnter your FULL name.
|
||
(end your input with a Carriage Return)
|
||
/
|
||
move x,[type dspc,/CPlease type your full name, followed by
|
||
a carriage return.
|
||
/]
|
||
movem helper
|
||
call readln ; Read a single line
|
||
jrst qitnam ; nope, he quit on us. Don't
|
||
][
|
||
call asknam ; ask if he's the right one
|
||
jrst qitnam] ; nope, stop this!
|
||
|
||
setz ch, ;a null byte terminates the name
|
||
idpb ch,bp ;so we can hack the name separately
|
||
movem bp,uinfo ;UINFO gets point to start of user info
|
||
write bp,/From net site /
|
||
move t,[440700,,hstnam]
|
||
copy t,bp
|
||
write bp,/
|
||
/
|
||
write bp,/Purpose: /
|
||
type tyoc,/
|
||
What do you wish to use the machine for?
|
||
(end your input with a ^C ([Control-C]))
|
||
/
|
||
move x,[type dspc,/CPlease explain briefly what you indend to use
|
||
our machine for.
|
||
End your input with a control-C.
|
||
(type a ^C (Control-C) by holding down the control key
|
||
and typeing "C")
|
||
/]
|
||
movem x,helper
|
||
call readsn ; Read multiple lines
|
||
jrst qitnam
|
||
type dspc,/APlease give us your telephone number and (paper postal) mailing
|
||
address where you can be contacted.
|
||
(End your input with a ^C)
|
||
/
|
||
|
||
write bp,/Address: /
|
||
move x,[type dspc,/CEnter your U.S. MAIL adress and phone number:
|
||
/]
|
||
movem x,helper
|
||
call readsn ; Read multiple lines
|
||
jrst qitnam
|
||
write bp,/Affiliation: /
|
||
type dspc,/AWhat, if any, is your affiliation?
|
||
(End your input with a ^C)
|
||
/
|
||
|
||
move x,[type dspc,/CEnter your affiliation. Just a name of
|
||
an organization connected with this machine or the net, a school, or
|
||
simply "none".
|
||
(End your input with a ^C)
|
||
/
|
||
]
|
||
|
||
movem x,helper
|
||
call readsn ;read the frob
|
||
jrst qitnam ; quit!
|
||
|
||
type dspc,/ANow you get to tell what password you wish.
|
||
/
|
||
move t,uname
|
||
move b,[sixbit /ACOUNT/] ;gotta open an output file for the account
|
||
call opnout ;open an output file
|
||
typout dsko,aplmal+ml.txt ;output the text of the application
|
||
movei b,aplnam ;rename to final application file name
|
||
call rnmfn2
|
||
call pwdchg ;get him a password
|
||
jrst .-1 ; keep at him!
|
||
|
||
movei x,ps%apl ; Now lets set the account state
|
||
dpb x,[pi$sta pdinfo] ; to 'Applied'
|
||
|
||
call pwdput ;and install it
|
||
|
||
.mail aplmal ;mail in an application
|
||
.mail telmal ;and notify
|
||
|
||
type dspc,/A
|
||
Please wait now for a few minutes; Someone may
|
||
contact you online. If not, then check back in a day or so;
|
||
try loging in. If it hasn't been granted yet, there may be mail for
|
||
you. You may read it by doing
|
||
:PRMAIL /
|
||
6type tyoc,uname ;spell it out for him!
|
||
type tyoc,/
|
||
|
||
Should you desire to change your password, you may do
|
||
:HELP LOGIN for info on how to change your password, or
|
||
simply do:
|
||
":LOGIN /
|
||
6type tyoc,uname
|
||
type tyoc,/ -CHANGE"
|
||
It will then ask you for your old password (to make sure you are you!)
|
||
and then it will ask you to give it a new password, of your
|
||
own chosing.
|
||
/
|
||
skipn gotinq ; If he lacks an INQUIR entry, tell him
|
||
; about INQUIR
|
||
type dspc,/A
|
||
The first time you log in, a program will be automatically
|
||
run to get certain information about you. Please answer it
|
||
as well as you can. Don't be intimidated, think of it as
|
||
your introducing yourself to us. In return, you will find
|
||
us quite friendly.
|
||
/
|
||
acexit: setzm apltim
|
||
ret ;that's all, folks!
|
||
|
||
qitnam: syscal delewo,[argi dsko] ;flush the mail file
|
||
jfcl
|
||
.close dsko, ;close the file too!
|
||
jrst acexit ;and exit
|
||
|
||
.upure
|
||
uinfo: 0 ;byte pointer to user info block
|
||
namloc: 0 ;byte pointer to start of user's name!
|
||
.pure
|
||
|
||
] ;; END IFE $$PAND,
|
||
|
||
|
||
SUBTTL Command Handlers
|
||
|
||
ife $$pand,[
|
||
;;; TCTYP
|
||
jtctyp: move t,[ftctyp,,j.file]
|
||
blt t,j.file+4
|
||
call infcr
|
||
syscal cnsget,[argi tyic ? val x ? val x ? val x ? val x ? val ttyopt]
|
||
loss
|
||
setzm hfdupf ; Reset default terminal characteristics.
|
||
setzm bsflag
|
||
setzm sailp
|
||
move x,ttyopt ; Now check this TTY out.
|
||
tlne x,%tosai ; does this TTY know about sail characters?
|
||
setom sailp ; yes, so echo contols right
|
||
tlne x,%tohdx ; Is this TTY a loser?
|
||
setom hfdupf ; yep, note the fact!
|
||
tlne x,%tomvb ; can this TTY move backwards?
|
||
setom bsflag ; yep, notice it for half-duplex jobs that
|
||
ret ; try ^H !
|
||
|
||
ftctyp: sixbit /DSK/
|
||
sixbit /TS/
|
||
sixbit /TCTYP/
|
||
sixbit /SYS1/
|
||
] ;; End IFE $$PAND
|
||
|
||
;;; LOADP
|
||
jloadp: move t,[floadp,,j.file]
|
||
jrst jwho1
|
||
floadp: sixbit /DSK/
|
||
sixbit /TS/
|
||
sixbit /LOADP/
|
||
sixbit /SYS2/
|
||
|
||
;;; WHO
|
||
jwho: move t,[fwho,,j.file]
|
||
jwho1: blt t,j.file+4
|
||
call infcr
|
||
ret
|
||
fwho: sixbit /DSK/
|
||
sixbit /TS/
|
||
sixbit /WHO/
|
||
sixbit /SYS1/
|
||
|
||
;;; HOST
|
||
j.hst: move t,[f.hst,,j.file]
|
||
j.hst1: blt t,j.file+4
|
||
call infcr
|
||
ret
|
||
f.hst: sixbit /DSK/
|
||
sixbit /TS/
|
||
sixbit /HOST/
|
||
sixbit /SYS3/
|
||
|
||
|
||
;;; NAME
|
||
j.name: move t,[f.name,,j.file]
|
||
blt t,j.file+4
|
||
call infcr
|
||
ret
|
||
|
||
f.name: sixbit /DSK/
|
||
sixbit /TS/
|
||
sixbit /NAME/
|
||
sixbit /SYS/
|
||
|
||
;;; LUSER
|
||
jluser: move t,[f.LUSE,,j.file]
|
||
blt t,j.file+4
|
||
call infcr
|
||
ret
|
||
|
||
f.luse: sixbit /DSK/
|
||
sixbit /TS/
|
||
sixbit /LUSER/
|
||
sixbit /SYS1/
|
||
|
||
joctps: move t,[f.octp,,j.file]
|
||
blt t,j.file+4
|
||
call infcr
|
||
ret
|
||
|
||
f.octp: sixbit /DSK/
|
||
sixbit /TS/
|
||
sixbit /OCTPUS/
|
||
sixbit /SYS2/
|
||
|
||
;;; DATE
|
||
jdate: move t,[f.date,,j.file]
|
||
blt t,j.file+4
|
||
call infcr
|
||
ret
|
||
|
||
f.date: sixbit /DSK/
|
||
sixbit /TS/
|
||
sixbit /DATE/
|
||
sixbit /SYS1/
|
||
|
||
jtime: move t,[f.time,,j.file]
|
||
blt t,j.file+4
|
||
call infcr
|
||
ret
|
||
|
||
f.time: sixbit /DSK/
|
||
sixbit /TS/
|
||
sixbit /TIME/
|
||
sixbit /SYS1/
|
||
|
||
jtimes: move t,[f.tims,,j.file]
|
||
blt t,j.file+4
|
||
call infcr
|
||
ret
|
||
|
||
f.tims: sixbit /DSK/
|
||
sixbit /TS/
|
||
sixbit /TIMES/
|
||
sixbit /SYS1/
|
||
|
||
jtimoo: move t,[f.timo,,j.file]
|
||
blt t,j.file+4
|
||
call infcr
|
||
ret
|
||
|
||
f.timo: sixbit /DSK/
|
||
sixbit /TS/
|
||
sixbit /TIMOON/
|
||
sixbit /SYS1/
|
||
|
||
|
||
SUBTTL :SSTATUS
|
||
|
||
;;; Command to print out system info
|
||
|
||
ksstat: syscal sstatu,[val shutdn ;collect info from ITS for header
|
||
val sysdbg
|
||
val susrs
|
||
val parnxm
|
||
val time
|
||
val machin
|
||
val itsver]
|
||
loss
|
||
aos susrs ;count ourself
|
||
6type tyoc,machin ;MC
|
||
tyo tyoc,[40] ;space
|
||
type tyoc,/ITS./ ;ITS.
|
||
6type tyoc,itsver ;1097
|
||
ife $$pand,type tyoc,/. PWORD./
|
||
ifn $$pand,type tyoc,/. PANDA./
|
||
6type tyoc,[.fnam2] ;<our version #>
|
||
type tyoc,/.
|
||
TTY / ;more stuff
|
||
8type tyoc,consol ;type our TTY #
|
||
type tyoc,/
|
||
/
|
||
10type tyoc,susrs ;type out # of users.
|
||
type tyoc,/. Lusers, Fair Share = /
|
||
eval tt,sloadu ;get the system load
|
||
movei t,10000. ;magic # to divide into to get %
|
||
idiv t,tt ;perform it
|
||
10type tyoc,t ;and type it
|
||
type tyoc,/%
|
||
/
|
||
skipl shutdn
|
||
call sysded ; handle system going down, as if got
|
||
;interrupt
|
||
skipe sysdbg ;debuging?
|
||
call sysbug ; handle ITS Being debugged message
|
||
ret
|
||
|
||
sysdwn: .dtty
|
||
jfcl
|
||
.iopush dski, ;prevent any conflict of channels
|
||
uuopsh
|
||
call sysded ;call the routine
|
||
uuopop
|
||
skipe infp ; are we in an inferior job?
|
||
jrst [.atty usrc, ;give the TTY back
|
||
jfcl
|
||
jrst .+1]
|
||
.iopop dski, ; restore the channel
|
||
jrst dismis ;dismiss the interrupt
|
||
|
||
syshak: .dtty
|
||
jfcl
|
||
uuopsh
|
||
call sysbug ;call the routine
|
||
uuopop
|
||
jrst gobak ;return, maybe give back TTY to inferior
|
||
|
||
|
||
|
||
;interrupt routine, so save the AC's
|
||
sysded: save [X,T,TT,A,B,ch,siotct,ttyflg,iobuf,dskbp,ttyprp,prmode,pbufl,pbtsiz,remain,foobp]
|
||
syscal sstatu,[val shutdn] ;gotta make sure it's current
|
||
loss
|
||
|
||
terpri ;make it look nice
|
||
6type tyoc,machin ;type the machine name
|
||
|
||
skipg shutdn ;is it going down or up?
|
||
pjrst [type tyoc,/ ITS Revived.
|
||
/
|
||
jrst popded] ;restore our AC's
|
||
type tyoc,/ ITS Going down in /
|
||
|
||
;; <
|
||
;; The following has the following flow structure, for leading zero suppression
|
||
;; hours ? --> print hours
|
||
;; | |
|
||
;; | (0 hours) |
|
||
;; | |
|
||
;; minutes? --> print minutes
|
||
;; | |
|
||
;; | (0 mins) |
|
||
;; | |
|
||
;; +--------->print seconds
|
||
;; |
|
||
;; |
|
||
;; V
|
||
;;
|
||
|
||
move a,shutdn ;get the current time-to-go
|
||
idivi a,3600.*30. ;grab # of hours
|
||
skipe a ;is it that long?
|
||
jrst hprt ; yes, print the hours
|
||
exch a,b ;let's hack the remainder
|
||
idivi a,60.*30. ;convert to minutes and seconds*30.
|
||
skipe a ;are there any minutes?
|
||
jrst mprt ; yes, type them out
|
||
jrst sprt ;there must be seconds!
|
||
|
||
hprt: 10type tyoc,a ;print it with leading 0's suppressed
|
||
tyo tyoc,[":] ;separator
|
||
exch a,b ;let's hack the remainder
|
||
idivi a,60.*30. ;convert to minutes and seconds*30.
|
||
mprt: call tprt ;print it as NN
|
||
tyo tyoc,[":] ;and the separator
|
||
sprt: exch a,b ;let's hack the rest of it
|
||
idivi a,30. ;convert to seconds
|
||
call tprt ;print it as NN
|
||
terpri ;look pretty
|
||
|
||
move x,[dskbuf+buflen]
|
||
movem x,iobuf ;use the other buffer!
|
||
|
||
syscal open,[cnti .uai ;access the info as to why we're going down!
|
||
argi dski
|
||
[sixbit /DSK/]
|
||
[sixbit /DOWN/]
|
||
[sixbit /MAIL/]
|
||
[sixbit /SYS/]]
|
||
caia ; Not there? Don't bother printing it then
|
||
call printf ; it's there, print it!
|
||
terpri
|
||
;restore the AC's etc.
|
||
popded: restore [foobp,remain,pbtsiz,pbufl,prmode,ttyprp,dskbp,iobuf,ttyflg,siotct,ch,b,a,tt,t,x]
|
||
ret
|
||
|
||
tprt: move t,a ;get copy to work with
|
||
idivi t,10. ;split into tens and units
|
||
addi t,60 ;convert to ascii decimal
|
||
tyo tyoc,t ;type it
|
||
addi tt,60 ;convert to ascii decimal
|
||
tyo tyoc,tt ;type it
|
||
ret
|
||
|
||
sysbug: save [X,T,TT] ;interrupt routine, save the AC's
|
||
|
||
terpri
|
||
6type tyoc,machin
|
||
type tyoc,/ ITS being debugged.
|
||
/
|
||
restore [TT,T,X]
|
||
ret
|
||
|
||
|
||
SUBTTL Logout
|
||
|
||
ife $$PAND,[
|
||
kquit: type dspc,/AThe proper command for logging off of this system is
|
||
:LOGOUT
|
||
/
|
||
phaser
|
||
|
||
klogou: move x,crgbts ;did he ask for the -BYE option?
|
||
trnn x,cf$lby
|
||
phaser ; nope, bye-bye
|
||
move x,[fbye,,j.file]
|
||
blt x,j.file+4 ;tell it what file to load from
|
||
call infcr ;run it
|
||
phaser
|
||
|
||
fbye: sixbit /DSK/
|
||
sixbit /TS/ ;file names for the BYE program
|
||
sixbit /BYE/
|
||
sixbit /SYS1/
|
||
|
||
]; END IF# $$PAND
|
||
|
||
ifn $$PAND,[
|
||
klogou:
|
||
kquit: .logout 1,]; END IFN $$PAND,
|
||
|
||
|
||
SUBTTL Some more commands
|
||
|
||
ulistj: type dspc,/A* CONIVR P 63
|
||
EMACS P 24
|
||
MAIL P 25
|
||
LISP R 5
|
||
FOO - 17
|
||
MACSYM R 34
|
||
PLANER R 45
|
||
DIRECT P 57
|
||
UNIVERSE-SIMULATION W 107
|
||
/
|
||
ret
|
||
|
||
ulogou: phaser ;that's all, folks!
|
||
|
||
|
||
khelp: skipn arg6 ;find out about our argument
|
||
call r6arg
|
||
move tt,arg6
|
||
jumpe tt,bhelp ; If no arg print what we have help on
|
||
camn tt,[sixbit /ALL/] ; Does he want help on everything?
|
||
jrst allhlp ; Yes, a moby luser, give it to him!
|
||
call ttkget ; Look up the command.
|
||
jrst khelp1
|
||
movei a,(t) ; Save it from the hungry typers
|
||
move tt,cm$flg(t) ; Get the info on this.
|
||
tlnn tt,%cohlp ; Is this forbotten?
|
||
jrst [ type dspc,/C/ ; OK. Clear the screen first.
|
||
jrst docit ]
|
||
khelp1: type dspc,/AI know nothing of the / ; Else complain.
|
||
6type tyoc,arg6 ; Tell him what he typed
|
||
type tyoc,/ command!
|
||
/
|
||
ret ; Return unsuccesfully.
|
||
|
||
|
||
docit: type tyoc,/Help info on / ;print header
|
||
6type tyoc,arg6 ;including the command requested
|
||
type tyoc,/:
|
||
|
||
/
|
||
move tt,crgbts ;get the switches he gave
|
||
push sp,arg6 ;get the help string for this
|
||
trne tt,cf$hbf ;did he ask for -bf or -brief
|
||
do [call psdoc ; yes, print short documentation
|
||
][call pldoc] ; no, print the long documentation
|
||
pop sp,nul ;restore the stack
|
||
terpri
|
||
jrst popj1 ;and return, successful
|
||
|
||
allhlp: save [a,b,t,tt]
|
||
move a,[-cmdcnt,,cmdtab] ; AOBJN ptr to everything there's help on!
|
||
allhl1: move tt,cm$nam(a) ;Get the name of the command
|
||
IFE $$PAND,[ ;No bad commands in PANDA!
|
||
call bdcmd ;If this is a baddie command?
|
||
jrst allhl4 ; dont bother to mention it.
|
||
]
|
||
allhl3: movem tt,arg6 ; that's our argument
|
||
call docit ; document it
|
||
jfcl
|
||
allhl4: addi a,cm$len-1
|
||
aobjn a,allhl1 ; do it for the next one
|
||
restore [tt,t,b,a]
|
||
ret ; and then ret
|
||
|
||
|
||
jmail: move t,[fmail,,j.file]
|
||
blt t,j.file+4
|
||
call infcr
|
||
ret
|
||
|
||
IFN $$PAND,[
|
||
fmail: sixbit /DSK/
|
||
sixbit /TS/
|
||
sixbit /QMAIL/ ; Use regular QMAIL program.
|
||
sixbit /SYS/
|
||
]
|
||
|
||
IFE $$PAND,[
|
||
fmail: sixbit /DSK/
|
||
sixbit /TS/
|
||
sixbit /PWMAIL/ ; Use hacked up QMAIL program.
|
||
sixbit /SYS/
|
||
]
|
||
|
||
uprrma: skipa a,[sixbit /RMAIL/] ; Access RMAIL file
|
||
uprmail:
|
||
kprmail:
|
||
move a,[sixbit /MAIL/] ; access MAIL file
|
||
move tt,[sixbit /PRMAIL/]
|
||
movem tt,comand
|
||
call bdcmd
|
||
jrst rtbadc
|
||
call r6arg ; Parse the argument
|
||
kprma5: skipn b,arg6 ; whose mail to read
|
||
move b,sndflt
|
||
movem b,sndflt ; remember this as our default
|
||
jumpe b,[ type dspc,/ARead whose mail?
|
||
/
|
||
ret]
|
||
setz c, ; find it wherever it goes
|
||
call gtmail ; find it
|
||
jrst [ type dspc,/ANo mail
|
||
/
|
||
ret]
|
||
pjrst printf ;print it
|
||
|
||
|
||
.upure
|
||
netabp: 0 ; Byte Pointer to NETADR entry in INQUIR
|
||
.pure
|
||
;;; Stolen from DDT
|
||
|
||
;; OPMAIL clobbers A, takes the XUNAME to look for in B, and either 0 in C
|
||
;; or an ITS to over-ride the one specified in INQUIR. It will return
|
||
;; the HSNAME in A, the XUNAME in B, and the ITS name in C
|
||
|
||
opmail: push p,d ;Don't clobber D
|
||
push p,c ;remember the ITS name we were given
|
||
push p,b ;save XUNAME for later
|
||
call maplsr ;map in the database
|
||
movei a,lsrc
|
||
movei d,dski
|
||
call lsrtns"lsrunm ;find this person in INQUIR
|
||
jrst [setz b, ; Remember that there was no INQUIR entry
|
||
jrst inqmal] ;and get his HSNAME from INQUIR
|
||
jumpn c,inqmal ;If we were given an explicit ITS, look only there
|
||
movei a,lsrtns"i$neta ;check out the network address field
|
||
call lsrtns"lsritm ;dig it out!
|
||
jrst inqmal
|
||
movem a,netabp ;remember where this info is
|
||
move d,a ;D gets the BP to the NET Adress
|
||
call lread6 ;read a token
|
||
jrst inqmal
|
||
caie c,"% ;Did he terminate in an % or @?
|
||
cain c,"@
|
||
jrst [call getits ;yes, use this for the XUNAME
|
||
jrst inqmal ;somehow this is garbage!
|
||
jrst inqml0] ;OK, NOW we got the site
|
||
call mchokp ;Is this a valid ITS?
|
||
jrst [ call notits ; Tell him about forwarded mail
|
||
jrst inqmal] ; and don't fuck with the machine name
|
||
inqml0: movem a,-1(p) ;salt machine name away
|
||
|
||
inqmal: move a,(p) ;remember our XUNAME
|
||
movei d,dski ;channel to open the directory on
|
||
move c,-1(p) ;remember our ITS
|
||
skipn c ;is it unspecified?
|
||
move c,machin ; Use current
|
||
movem c,-1(p) ;and salt this improved version away
|
||
call lsrtns"lsrhsn ;get the HSNAME
|
||
jrst [ type tyoc,/(Net or INQUIR error)
|
||
/ ; Eh??? Tell the user.
|
||
move a,(p) ;use our XUNAME as the HSNAME
|
||
jrst inqml5]
|
||
aos -3(p) ; Skip return
|
||
move a,d ;collect the HSNAME
|
||
inqml5: call unmapl ;don't need these any more, release
|
||
pop p,b ;and the XUNAME
|
||
pop p,c ;recover the ITS name
|
||
pop p,d ;remember D (unchanged)
|
||
ret
|
||
|
||
|
||
lread6: setzb a,t
|
||
push p,b
|
||
move b,[440600,,a]
|
||
6readl: ildb c,d
|
||
aos t
|
||
cain c,40
|
||
jrst 6readl ; spaces are ignored.
|
||
cain c,"% ; % is a terminator
|
||
jrst mpopj1
|
||
caie c,"@ ; @, comma are terminators
|
||
cain c,",
|
||
jrst mpopj1
|
||
cain c,^Q ; let ^Q quote a character.
|
||
ildb c,d
|
||
caige c,40
|
||
jrst mpopj1 ; control chars terminate even if ^Q'd
|
||
cail c,140
|
||
subi c,40
|
||
subi c,40
|
||
tlne b,770000
|
||
idpb c,b
|
||
jrst 6readl
|
||
|
||
mpopj1: pop p,b
|
||
skipe a ;unless this is a null entry
|
||
aos (p)
|
||
popj p,
|
||
|
||
|
||
;; person said FOO@BAR
|
||
|
||
getits: push p,a ;remember the FOO part
|
||
pushj p,lread6 ;get more of it
|
||
setz a, ; not there! Fail return
|
||
jumpe a,[pop p,a ? ret] ;if null, same as not there
|
||
call mchokp ;is this a known machine?
|
||
jrst gtitsx ;If not an ITS, same as not there!
|
||
move c,a ;That was the ITS name
|
||
movei a,lsrc
|
||
pop p,b ;recover our XUNAME
|
||
movem b,-1(p) ;and set the XUNAME saved on the stack
|
||
call lsrtns"lsrunm ;Find the new frobule
|
||
setz b, ; No INQUIR entry for that XUNAME
|
||
move a,c
|
||
jrst popj1
|
||
|
||
gtitsx: pop p,a
|
||
move a,-2(p) ;use whatever ITS was specified!
|
||
jrst notits ;Tell him the mail goes off of ITS
|
||
ret
|
||
|
||
mchcnt==:4 ;4 ITS's
|
||
mchtab: irp machine,,[AI,ML,MC,DM]
|
||
sixbit /machine/
|
||
termin
|
||
|
||
;;; Expects BP to net address in NETABP, prints same with message
|
||
notits: type dspc,/A(This person's mail is forwarded to /
|
||
notit1: ildb d,netabp ;get a char
|
||
jumpe d,[ type tyoc,/)
|
||
/ ; if that's the end, that's all, so finish the line
|
||
popj p,]
|
||
tyo tyoc,d ;type the char
|
||
jrst notit1 ;and get the next
|
||
|
||
;;; canonicalize and check the machine name. (Handles MIT-MC and MC)
|
||
;;; Takes machine in A, returns canonicalized machine in A.
|
||
;;; Stolen from DDT
|
||
|
||
mchokp: camn b,[sixbit /DSK/] ;= machine we're on
|
||
jrst [move a,machin ? jrst popj1]
|
||
push p,b
|
||
ldb b,[143000,,a] ;get the MIT- of MIT-xx
|
||
camn b,[sixbit / MIT-/] ;Was it in that form?
|
||
jrst [ ldb a,[001400,,a] ;Get the xx part
|
||
lsh a,30 ;put it in it's place
|
||
jrst .+1]
|
||
call mchok0 ;is this a real machine?
|
||
caia
|
||
bret: aos -1(p)
|
||
pop p,b
|
||
popj p, ;no more nexts, bad!
|
||
|
||
mchok0: movsi b,-mchcnt ;for all the machines
|
||
mchok1: camn a,mchtab(b) ;is it this one?
|
||
jrst popj1 ; yes, it's OK
|
||
aobjn b,mchok1 ;no, try next
|
||
ret
|
||
|
||
;;; GTMAIL takes in A the FN2, B a XUNAME, an ITS name in C, or 0 meaning
|
||
;;; wherever his mail would normally be found, and opens on DSKI the mail file
|
||
;;; for that user. If it fails, it will not skip, and return a .CALL type error
|
||
;;; code in D. It will also return the HSNAME in A, the XUNAME in B, and the
|
||
;;; ITS name in C. Stolen from DDT
|
||
|
||
gtmail: movem a,fd.fn2 ;save the fn2 of the file we're after
|
||
call opmail ;Find the mail to look at
|
||
ret
|
||
movem b,fd.fn1
|
||
camn c,machin ;Is it from this ITS?
|
||
movsi c,'DSK ; yes, use DSK instead
|
||
movem c,fd.dev
|
||
movem a,fd.snm
|
||
camn b,xuname ;is this the same XUNAME and
|
||
came c,machin ; is this from this machine?
|
||
caia ; no, gotta tell the user
|
||
jrst gtmal9 ; yes, don't bother telling user.
|
||
gtmal5: type dspc,/A(Checking mail from /
|
||
movei b,dirnam
|
||
move d,[440700,,dskbuf]
|
||
call rfn"pfn ; generate the filename string
|
||
output tyoc,dskbuf ; and print it out
|
||
move a,fd.snm ;recover A from it's hiding place in B
|
||
move b,fd.fn1 ;recover B from it's hiding place in file block
|
||
move c,fd.dev ;recover C from it's hiding place in file block
|
||
tyo tyoc,[")] ;balance!
|
||
terpri ;new line!
|
||
gtmal9: movei b,dirnam
|
||
.call uaiopn ;open the file
|
||
caia ; no skip
|
||
jrst [ aos (p) ; found it, skip return
|
||
jrst gtmalx] ; (cause that's all!)
|
||
move d,calerr ; check out what kind of error it was
|
||
jumpe d,gtmalx ;no error, we win!
|
||
caie d,%ensfl ;Was it that the file wasn't there?
|
||
filoss dirnam ; no, complain of another kind of error
|
||
gtmalx: push p,b ;save B across umapping and flush old A
|
||
pop p,b ;restore B to it's rightful placs
|
||
ret
|
||
|
||
.upure
|
||
sndflt: 0 ; default SENDS file to use
|
||
.pure
|
||
kprse1: skipn a,arg6 ; get whose SENDs to hack
|
||
move a,sndflt
|
||
caia
|
||
kprsen: move a,arg6 ; remember this as the default SENDS file
|
||
movem a,sndflt
|
||
syscal open,[cnti .uai ;open the sends file
|
||
argi dski
|
||
[sixbit /DSK/]
|
||
a
|
||
[sixbit /SENDS/]
|
||
cladir]
|
||
jrst [type dspc,/ANo sends
|
||
/
|
||
ret]
|
||
pjrst printf ;print it
|
||
|
||
|
||
;; SEND command.
|
||
;; Note: if the SEND command is disallowed, failing sends will
|
||
;; turn into mail regardless of whether the MAIL command is allowed.
|
||
|
||
ksend: move bp,snaptr ; Pointer to who to send to
|
||
move ct,snacnt ; Ensure it points to something plausible
|
||
skipn ct ; Complain if there's no one to send to
|
||
jrst [ type dspc,/AYou must specify who to SEND to.
|
||
/
|
||
ret ]
|
||
caile ct,6. ; Complain if rcpt could not be a UNAME
|
||
jrst ksen11 ; Probably trying to send across network
|
||
setz a, ; Accumulate UNAME in A
|
||
move b,[440600,,a] ; Bp to UNAME
|
||
ksen10: ildb ch,bp ; Get a char from string
|
||
cain ch,",
|
||
jrst [ type dspc,/ASEND only lets you send to one person at a time.
|
||
/
|
||
ret ]
|
||
caie ch,"% ; FOO@BAR doesn't work
|
||
cain ch,"@
|
||
ksen11: jrst [ type dspc,/ASEND does not work across the network.
|
||
/
|
||
ret ]
|
||
caige ch,40 ; Control chars terminate reading
|
||
soja ct,ksen20
|
||
cail ch,140 ; SIXBITify the character
|
||
subi ch,40
|
||
subi ch,40
|
||
tlne b,770000
|
||
idpb ch,b ; Deposit it into the UNAME
|
||
sojg ct,ksen10 ; Loop until end
|
||
ksen20: movem bp,snaptr ; Got it, update the BP
|
||
movem ct,snacnt ; and the count
|
||
jumpl ct,cpopj ; Huh?
|
||
syscal OPEN,[ cnti .uao ? argi dsko ? [sixbit /CLI/] ? a
|
||
[sixbit /HACTRN/]]
|
||
jrst gomail
|
||
call sndtim ; Get the time word in A
|
||
.iot dsko,[177]
|
||
typout dsko,sndtyp
|
||
.close dsko,
|
||
ret
|
||
|
||
|
||
gomail: move d,[440700,,tmpbuf]
|
||
idpb6 a,d ; generate asciz for the TO: field
|
||
setz e, ; and make sure it's ASCIZ
|
||
idpb e,d
|
||
.mail sndmal ; Send it as mail
|
||
type dspc,/A(Mailed)
|
||
/
|
||
ret
|
||
|
||
|
||
;; table of special devices NOT to set our default to
|
||
|
||
devtab: irp dev,,[TTY,T,MLTTY,MCTTY,DMTTY,AITTY,D,MCD,MLD,AID,DMD,XGP,TPL,GLP,DVR,COR,DIR,DIRML,DIRAI,DIRCOM,DIRSYS,DIRDSK,CLO,CLI,CLA,CLU]
|
||
sixbit /dev/
|
||
termin
|
||
devlen==.-devtab ;# of devices
|
||
|
||
ulistf: move tt,[sixbit /LISTF/]
|
||
movem tt,comand
|
||
call bdcmd
|
||
jrst rtbadc
|
||
skipn t,arg6 ;null command says, same as before
|
||
jrst kc.fop ; so hack without any setup
|
||
setzm fd.dev ;clear out any old ones
|
||
setzm fd.snm ;Clear out SNAME left over from :LISTF FOO;
|
||
movem t,fd.fn1 ;put in FN1 slot for KLISTF
|
||
jrst kc.fop ;and continue with hack
|
||
|
||
;;; A non-zero name in FD.FN1 is from FOO^F or :LISTF FOO, and is tried as
|
||
;;; both a directory with the DSK device and as a device
|
||
|
||
klistf: setzm fd.fn1 ;eliminate pre-conceived notions
|
||
setzm fd.snm ;:LISTF FOO;
|
||
move x,fi.dev
|
||
movem x,fd.dev ;and :LISTF FOO:
|
||
|
||
move d,argptr ;pointer to the file-name
|
||
movei b,dirnam ;pointer to file name!
|
||
call rfn"rfn ;read the names
|
||
kc.fop: call dirdev ;get the dir and dev
|
||
|
||
movem t,fx.snm ;save our new-found names in a fileblock
|
||
movem tt,fx.dev ;where we can can open and print
|
||
movei b,fdxnam ;B get's location of that fileblock
|
||
call prtopn ;open that file
|
||
jrst [skipn tt,fd.fn1 ; nothing to fill in with?
|
||
filoss (b) ; yes -- give error
|
||
move x,calerr ;what was the error?
|
||
caie x,%ensdr ; non-existant directory?
|
||
filoss (b) ; nope, give the error
|
||
skipn t,fd.snm ; was there a directory given?
|
||
move t,fi.snm ; no, get the default
|
||
save [fx.dev,fx.snm,calerr] ;save circumstances of error
|
||
movem t,fx.snm ; save our new-found names
|
||
movem tt,fx.dev
|
||
call prtopn ; open our file in the right mode
|
||
jrst [restore [calerr,fx.snm,fx.dev]
|
||
filoss (b)] ; still nothing, give error
|
||
restore [calerr,fx.snm,fx.dev]
|
||
jrst .+1]
|
||
tyo dspc,[^P] ;clear the screen
|
||
tyo dspc,["C]
|
||
|
||
movem t,fi.snm ;we found it, make it the default
|
||
hrlzi t,-devlen ;AOBJN ptr for DEVTAB
|
||
kc.fdv: camn tt,devtab(t) ;is it a dir only device?
|
||
pjrst printf ; yes, just print out and return
|
||
aobjn t,kc.fdv ;try the next one
|
||
movem tt,fi.dev ;it's not one of them, so make it the
|
||
;default
|
||
pjrst printf
|
||
|
||
|
||
;; get the dir in T and dev in TT
|
||
dirdev: skipn t,fd.snm ;was a sname given?
|
||
skipe t,fd.fn1 ; or was a FN1 given?
|
||
caia ; yes, use it
|
||
move t,fi.snm ; no, use the default
|
||
|
||
skipn tt,fd.dev ;was a device given?
|
||
move tt,[sixbit /DSK/] ; no, use the DSK instead
|
||
ret ;return
|
||
|
||
;; Prompt for file name with defaulting.
|
||
;;; X should be the address of default file block, or zero.
|
||
|
||
flprmp: save [b,d]
|
||
output dspc,@filprm ;output a prompt for the frob
|
||
type dspc,/ADefault = / ;prompt for the file
|
||
move d,[440700,,DSKBUF] ;use DSKBUF, since we don't need it yet
|
||
movei b,filnam ; The default default.
|
||
skipe x ; If we were given a new default
|
||
move b,x ; use it instead.
|
||
call rfn"pfn ;convert it back again
|
||
output tyoc,dskbuf ;and type it out
|
||
type dspc,/AFILE = /
|
||
restore [d,b]
|
||
ret
|
||
.upure
|
||
filprm: 0 ;prompt for file operation
|
||
.pure
|
||
|
||
uprint: ;Here from ^R
|
||
kprint: move tt,[sixbit /PRINT/]
|
||
movem tt,comand
|
||
call bdcmd
|
||
jrst rtbadc
|
||
move d,argptr ;pointer to the file-name
|
||
movei b,filnam ;pointer to file name!
|
||
call rfn"rfn ;read the names
|
||
|
||
move x,fi.dev ;for sake of TTY^F ^R<CR>^F
|
||
movem x,fd.dev ;reset it to it's default
|
||
setzm x,fd.fn1 ;this should work for ML^F ^R<CR> ^F
|
||
|
||
movei b,filnam ;point to the file we are using
|
||
call prtopn ;open it
|
||
filoss (b) ; we lost, tell him
|
||
tyo dspc,[^P] ;clear the screen first
|
||
tyo dspc,["C]
|
||
pjrst printf ;print it out
|
||
|
||
;;; USERS command
|
||
|
||
jusers: terpri ;make sure you start on a new line
|
||
move t,[f.usrs,,j.file] ;run the damn thing already!
|
||
blt t,j.file+4
|
||
pjrst infcr
|
||
|
||
f.usrs: sixbit /DSK/ ;here's home for the USERS command
|
||
sixbit /TS/
|
||
sixbit /USERS/
|
||
sixbit /SYS2/
|
||
|
||
;;;; Here goes the documentation printer etc.
|
||
|
||
; The documentation printers take a sixbit command to document, and
|
||
; look it up and print either the short or the entire documentation.
|
||
|
||
; print short documentation
|
||
psdoc: move tt,-1(sp) ; Get the command to document
|
||
call ttkget ; Get the command index
|
||
error /Attempt to document non-existant command/
|
||
psdoc1: hrrz tt,cm$sdc(t) ; Get address of short doc
|
||
hlrz t,cm$sdc(t) ; Get length of short doc
|
||
psdoc2: hrli tt,440700 ;make t into a byte pointer
|
||
syscal siot,[argi tyoc ? tt ? t] ;type it out
|
||
loss
|
||
ret
|
||
|
||
; print long documentation
|
||
pldoc: move tt,-1(sp) ; Get the command to document
|
||
call ttkget ; Get command index
|
||
error /Attempt to document non-existant command/
|
||
push sp,t ; Remember the index
|
||
call psdoc1 ; Print out the short documentation first
|
||
pop sp,t
|
||
hrrz tt,cm$ldc(t) ; Get address of long documentation
|
||
hlrz t,cm$ldc(t) ; Get length of long documentation
|
||
pjrst psdoc2 ; Print it out
|
||
|
||
;;; type out a list of all the commands, 5 to a line
|
||
|
||
bhelp: type dspc,/CThese are the topics for which HELP can give more info.
|
||
Type:
|
||
:HELP <topic>
|
||
for more info on a given topic.
|
||
|
||
/
|
||
save [b,tt] ;Save B for use as count of commands off
|
||
move a,[-cmdcnt,,cmdtab] ;aobjn pointer to name table
|
||
move t,cmhcnt ;cmhcnt per line
|
||
movem t,hcnt ;so set hcnt
|
||
bhelp0: move tt,cm$nam(a) ;Get the name of the command
|
||
IFE $$PAND,[
|
||
call bdcmd ;Is this an OK command?
|
||
jrst bhelp3 ; Nope.
|
||
]
|
||
bhelp2: move t,cm$flg(a) ;get the flags
|
||
tlne t,%cohlp\%conls ;maybe no need to print?
|
||
jrst bhelp3 ;just do your thing.
|
||
tyo tyoc,[^I] ;tab to next location
|
||
6type tyoc,cm$nam(a) ;type the name
|
||
sosg hcnt ;hcnt is count of times we've typed entries
|
||
do [ terpri ;if we've typed enough on this line
|
||
move t,cmhcnt ;just go to another.
|
||
movem t,hcnt]
|
||
bhelp3: addi a,cm$len-1
|
||
aobjn a,bhelp0 ;loop for all of them
|
||
terpri
|
||
restore [tt,b]
|
||
ret
|
||
|
||
|
||
|
||
SUBTTL Interrupt handlers and Inferior hackery
|
||
|
||
;;;; Here goes the inferior handler routines
|
||
;;;; Here go the interrupt handlers
|
||
|
||
intspc==:100000 ;push extra debugging info
|
||
tsint: intspc,,sp
|
||
%pimpv\%piwro\%pioob\%piilo\%pidis ? 0 ? -1 ? -1 ? badint
|
||
%pipdl ? 0 ? -1 ? -1 ? pdlovr
|
||
%piioc ? 0 ? -1 ? -1 ? iocerr
|
||
0 ? <1_tyoc>\<1_dspc> ? 0 ? 0 ? morint
|
||
%piltp ? 0 ? -1 ? -1 ? clock
|
||
0 ? 1_tlnc ? -1 ? -1 ? telbye
|
||
0 ? 1_tyic ? %picli ? -1 ? ttyint
|
||
0 ? -1,,0 ? %picli ? -1 ? infint
|
||
%picli ? 0 ? %picli ? -1,,0 ? cliget
|
||
%pidbg ? 0 ? #%pimpv#%pipdl#%piioc#%piltp ? -1,,0 ? syshak
|
||
%pidwn ? 0 ? #%pimpv#%pipdl#%piioc#%piltp ? -1,,0 ? sysdwn ;Gronk
|
||
%pirlt ? 0 ? #%pimpv#%pipdl#%piioc#%piltp#%pirlt ? -1 ? timout
|
||
;%PIRLT's don't defer themselves, so
|
||
;hung terminals might log out.
|
||
intlng==.-tsint
|
||
|
||
gobak: skipe infp ;If we're in an inferior
|
||
.atty usrc, ; give back the TTY
|
||
jfcl
|
||
dismis: syscal dismis,[cnti intspc ? sp] ;Go back to what you were doing.
|
||
loss
|
||
|
||
|
||
nlitim==5. ;Not Logged In lusers time out after five minutes.
|
||
.upure
|
||
apltim: 0 ; -1 => luser applying, don't time out
|
||
timflg: -1 ;set >= 0 if we've already warned about time
|
||
.pure
|
||
|
||
timout: uuopsh
|
||
push p,t
|
||
syscal cnsget,[argi tyic ? val nul ? val nul ? val nul ? val TTYCOM]
|
||
loss
|
||
skipe apltim ; If luser is applying for an account
|
||
jrst timou1 ; don't hassle him.
|
||
hrrz t,ttycom ; Get com mode info.
|
||
camn t,[0,,-1] ; TTY linked to someone?
|
||
jrst timou2 ; No, see if completely timed out.
|
||
timou1: move t,[move [nlitim*60.*60.]] ; Yes, restart the countdown.
|
||
.realt t,
|
||
jfcl
|
||
pop p,t
|
||
uuopop
|
||
jrst dismis
|
||
|
||
timou2: aose timflg ; Is this the first time?
|
||
.logout 1, ; no, time to flush.
|
||
move t,[move [2*60.*60.]] ; Else give 2 more minutes
|
||
.realt t, ; till final bye-bye.
|
||
jfcl
|
||
.dtty ; Make sure we have the TTY.
|
||
jfcl
|
||
type dspc,/A
|
||
Timeout: You have two minutes remaining in which to log in or be logged out.
|
||
This policy is necessary to avoid tying up job slots and network ports.
|
||
If you are having difficulties and need assistance, please type:
|
||
|
||
:LUSER
|
||
and someone will assist you.
|
||
/
|
||
pop p,t
|
||
uuopop
|
||
jrst gobak ; Relinquish TTY and dismiss.
|
||
|
||
|
||
cliget: .dtty
|
||
jfcl
|
||
.iopush dski, ;don't clobber anything we may be doing!
|
||
syscal open,[cnti .uii ;image mode, to get the UNAME/JNAME
|
||
argi dski
|
||
[sixbit /CLA/]]
|
||
jrst [.iopop dski, ; Restore the channel
|
||
jrst gobak] ; And return, maybe give back TTY
|
||
|
||
;;; save the world
|
||
save [x,t,tt,a,ch,siotct,ttyflg,iobuf,dskbp,ttyprp,prmode,pbufl,pbtsiz,remain,foobp]
|
||
uuopsh
|
||
syscal cnsget,[argi tyic ? val nul ? val nul ? val nul ? val TTYCOM]
|
||
loss
|
||
move t,ttycom
|
||
tlo t,%tcoco ;turn on OCO!
|
||
syscal cnsset,[argi tyic ? [-1] ? [-1] ? [-1] ? t]
|
||
loss
|
||
|
||
.iot dski,nuprt ;get the UNAME
|
||
.iot dski,njprt ;and the JNAME
|
||
.iot dski,savewd ;get first char, plus a few
|
||
move a,[440700,,savewd] ;BP to first char
|
||
ildb ch,a ;get the first one
|
||
cain ch,177 ;is it a rubout?
|
||
jrst nujprt ; yes, don't print message from ... etc
|
||
movem ch,chsave ;save for later re-typeout
|
||
type dspc,/AMessage from /
|
||
6type tyoc,nuprt ;type the UNAME
|
||
tyo tyoc,[40] ;space
|
||
6type tyoc,njprt ;JNAME
|
||
terpri
|
||
tyo tyoc,chsave ;time to type it
|
||
|
||
;; this has the bug that short messages (< 5 chars) still get 5 chars (4 if
|
||
;; first is a rubout) typed. Tough shit.
|
||
nujprt: movei t,4 ;4 characters
|
||
movem t,siotct ;make ^S win!
|
||
syscal siot,[argi tyoc ? a ? siotct] ;to type
|
||
loss
|
||
|
||
move x,[dskbuf+buflen]
|
||
movem x,iobuf ;use the other buffer!
|
||
call printf ;print the rest
|
||
;restore OCO to it's former state !!
|
||
syscal cnsset,[argi tyic ? [-1] ? [-1] ? [-1] ? ttycom]
|
||
loss
|
||
;restore world
|
||
uuopop
|
||
restore [foobp,remain,pbtsiz,pbufl,prmode,ttyprp,dskbp,iobuf,ttyflg,siotct,ch,a,tt,t,x]
|
||
|
||
.iopop dski, ;restore the channel
|
||
terpri ;make sure don't leave it hanging
|
||
jrst gobak
|
||
|
||
|
||
;;; TTY interrupt handlers
|
||
|
||
ttyint: uuopsh
|
||
save [ch]
|
||
ttypsh==.-ttyint
|
||
syscal whyint,[argi tyic ? val nul ? val ch]
|
||
jrst ttidsm ; dismissed!
|
||
cain ch,^Z ;quit?
|
||
jrst c.quit ; quit!
|
||
|
||
cain ch,^G ;quit?
|
||
jrst g.quit ; quit with funny message!
|
||
|
||
caie ch,^S ;is it ^S?
|
||
jrst ttidsm
|
||
syscal ttyfls,[cnti 0 ? argi tyic] ;flush the ^S, but not typeahead
|
||
loss
|
||
.reset tyoc, ; flush typeout
|
||
setzm siotct ; no more!
|
||
setzm ttyflg ; turn on the TTY while handling it
|
||
hrrz ch,-ttypsh(p) ; get where we interrupted from
|
||
skipe morflg ; are we inside a more?
|
||
caie ch,tyiiot ; waiting in a TYI?
|
||
caia ; nope
|
||
jrst [ restore [ch] ; yes
|
||
movei ch,177 ; we're gonna pretend we saw a rubout
|
||
aos -ttypsh+1(p) ; pretend the .IOT returned
|
||
jrst ttids1] ; dismis to next instruction
|
||
$echo ^S ; echo it now. Don't echo in a --MORE--,
|
||
; since that would just get flushed anyway
|
||
cain ch,tyiiot ; were we reading?
|
||
jrst ttidsm
|
||
setom ttyflg ; prevent more cruft from starting
|
||
ttidsm: restore [ch]
|
||
ttids1: uuopop
|
||
jrst dismis ; and return to what you were doing!
|
||
|
||
g.quit: call ttyclr ; clear output/input on TTY
|
||
type tyoc,/ (Quit)
|
||
/
|
||
quit ; reset the world
|
||
|
||
c.quit: call ttyclr ; clear the TTY I/O
|
||
quit
|
||
|
||
ttyclr: .reset tyoc, ;clear the output
|
||
syscal ttyfls,[cnti 1 ? argi tyic] ;flush typein up to interrupt char
|
||
loss
|
||
setzm siotct ;clear the SIOT count!
|
||
ret
|
||
|
||
;;; --MORE-- interrupt
|
||
morint: skipe ttyflg ; if we aren't typing anyway
|
||
jrst dismis ; just ignore it
|
||
save [ch,x]
|
||
uuopsh
|
||
push sp,siotct ;save SIOTCT seperately
|
||
syscal finish,[argi tyoc] ;wait for it to come out
|
||
jfcl ; ignore failure
|
||
type tyoc,/--MORE-- (Space yes, rubout no, ? for help)/
|
||
setom morflg ;note we are at a more
|
||
morin1: tyi
|
||
jrst flushd
|
||
jrst [
|
||
type dspc,/TLWhen you see --MORE-- at the bottom of your screen,
|
||
it means that there is more output to come, but the system
|
||
is waiting for you to finish reading it. When you are
|
||
ready for more output, just type a space, and it will type
|
||
out the next screenful.
|
||
|
||
On the other hand, if you do not wish to see the output, you
|
||
may type a rubout instead. This will throw away the remaining
|
||
output.
|
||
|
||
-----------
|
||
ZH3/
|
||
jrst morin1]
|
||
jrst flushd ; rubbed out, flush.
|
||
setzm morflg ;turn of --MORE-- flag
|
||
cain ch,40 ;is it a space?
|
||
jrst [type dspc,/
|
||
/ ; yes, go to top
|
||
jrst mordsm] ; to continue typeing
|
||
|
||
caie ch,^M ;loser type a CR anyway?
|
||
movem ch,reread ; garbage char, re-read it later
|
||
|
||
|
||
flushd: setzm morflg ;^G or ^D -- turn off --MORE-- flag
|
||
.reset tyoc, ;throw it all away
|
||
type dspc,/ZL--FLUSHED--TL/ ;tell him about it
|
||
setom ttyflg ;no more output
|
||
setzm siotct ;flush ongoing output
|
||
mordsm: pop sp,nul ;throw away old SIOTCT
|
||
uuopop
|
||
restor [x,ch]
|
||
jrst dismis ;and end of interrupt
|
||
|
||
;;; error interrupt handlers
|
||
badint: error /Unknown Interrupt./
|
||
pdlovr: error /PDL Overflow./
|
||
pdlund: error /PDL Underflow./
|
||
|
||
iocerr: .suset [.rbchn,,iocchn] ;find out what channel lost
|
||
syscal status,[iocchn ? val iocsts] ;get the status
|
||
loss
|
||
syscal open,[cnti .uai
|
||
argi dski
|
||
[sixbit /ERR/]
|
||
argi 3 ;means 2nd file name is status word
|
||
iocsts]
|
||
loss
|
||
movem x,erracs ;save X for analysys
|
||
move x,[1,,erracs+1] ;and use it to BLT the rest of the AC's to
|
||
blt x,erracs+17 ;safty
|
||
call printf ;print the error message
|
||
ldb t,[330500,,iocsts] ;get the error #
|
||
movei tt,1 ;set up to shift one bit into position
|
||
lsh tt,(t) ;shift it
|
||
tdnn tt,iocfpr ;Should the file name be printed?
|
||
do [ syscal rfname,[argi %jself ;yep, find out the true filename
|
||
iocchn
|
||
val fi.dev
|
||
val fi.fn1
|
||
val fi.fn2
|
||
val fi.snm]
|
||
loss
|
||
type dspc,/ABad file = /
|
||
move d,[440700,,msgbuf] ;use msgbuf, since we don't need it now
|
||
movei b,filnam ;
|
||
call rfn"pfn ; convert it back again
|
||
output tyoc,msgbuf] ; type that string again!
|
||
|
||
syscal delewo,[argi dsko] ;flush any writing we may be doing
|
||
jfcl ;must not have been there or doable
|
||
|
||
ldb t,[330500,,iocsts] ;get the error #
|
||
movei tt,1 ;set up to shift one bit into position
|
||
lsh tt,(t) ;shift it
|
||
ldb t,[330500,,iocsts] ;get the error #
|
||
movei tt,1 ;set up to shift one bit into position
|
||
lsh tt,(t) ;shift it
|
||
tdne tt,iocbad ;Is this safely ignorable?
|
||
jrst gotop
|
||
errdmp 4,[asciz /Input-Output Error/] ;AC's have been saved
|
||
|
||
gotop: move sp,[-pdllen,,pdl] ;clean out the stack
|
||
.uclose usrc,
|
||
.suset [.sdf1,,[0]] ; Re-enable interrupts
|
||
.suset [.sdf2,,[0]]
|
||
jrst rdloop ;back to reading
|
||
|
||
|
||
;;; IOC errors to print file names for
|
||
; 11 - Device Full
|
||
; 14 - Directory Full
|
||
iocfpr: irp x,,[11,14]
|
||
<1_x>\termin
|
||
|
||
;;; IOC errors to continue after
|
||
; 7 - USR Operation Channel does not have USR device open
|
||
; 10 - Channel not open
|
||
; 13 - Illegal Character after ^P on display channel
|
||
|
||
iocbad: irp x,,[7,10,13]
|
||
<1_x>\termin
|
||
|
||
|
||
infint: save [x,t,tt]
|
||
uuopsh
|
||
.dtty ;get back the TTY
|
||
jfcl
|
||
syscal usrvar,[argi usrc ;get his interrupts
|
||
[sixbit /PIRQC/]
|
||
val t]
|
||
loss
|
||
trne t,%pibrk ;break?
|
||
jrst break ; handle that
|
||
setzm infp ;note we aren't in inferior anymore
|
||
trne t,%pival ;.VALUE?
|
||
jrst value ; go barf at him, I didn't say I was DDT
|
||
trnn t,<%pic.z> ;^Z ?
|
||
tlne t,%pjdcl ; or ^_D ?
|
||
jrst kjob ; kill it off.
|
||
|
||
type dspc,/AInferior got random interrupt!/
|
||
jrst gotop
|
||
|
||
define pagmak a
|
||
andi a,-1 ;clear left half
|
||
lshc a,-12 ;split off page number from rest
|
||
lsh <a+1>,12-44 ;and make remainder
|
||
termin
|
||
|
||
accum==:.bp <740,,0>
|
||
index==:.bp <17,,0>
|
||
indirc==:.bp <20,,0>
|
||
opcode==:.bp <777000,,0>
|
||
|
||
break: move t,[-6,,[sixbit /PIRQC/ ? trz %pibrk ;turn off the interrupt
|
||
sixbit /UPC/ ? movem j.upc ;get the PC to restart at, and
|
||
;for debugging
|
||
sixbit /SV40/ ? movem jinstr]] ;get the causing inst.
|
||
syscal usrvar,[argi usrc ? t] ;get the info
|
||
loss
|
||
|
||
ldb t,[accum jinstr] ;pick out the accumulator
|
||
movem t,jaccum
|
||
|
||
hrrz t,jinstr ;t <- address field
|
||
movem t,jaddr ;address field
|
||
|
||
ldb t,[opcode jinstr] ;get the opcode
|
||
movem t,jopcod ;and save it for debuging's sake.
|
||
cain t,c.op ;is it a .oper ?
|
||
jrst kjob ; just kill it
|
||
|
||
move t,jaccum ;check the accumulator
|
||
cain t,12 ;is it a .BREAK 12, ?
|
||
jrst brk12 ; yes
|
||
|
||
setzm infp ;note we aren't in inferior any more
|
||
caie t,16 ;is it garbage?
|
||
jrst unbrk ;go handle unknown break
|
||
|
||
kjob: setzm infp ;note we aren't in inferior anymore
|
||
syscal rfname,[argi usrc
|
||
val t] ;is there an inferior?
|
||
loss
|
||
skipn t
|
||
ERROR /Attempt to kill non-existant inferior./
|
||
.uclose usrc, ;kill it
|
||
type dspc,/A:KILL
|
||
/
|
||
.uclose usrc, ;it must have been asking to die since we
|
||
;told it we weren't a DDT
|
||
jrst infdon
|
||
|
||
brk12: syscal usrmem,[argi usrc ? jaddr ? val t] ;A <- cont (e.a)
|
||
jrst kjob ; lose!
|
||
jumpl t,[hlrz t,t ;if writing
|
||
caie t,400005 ; if clearing JCL
|
||
jrst [setzm jclct ;clear it and
|
||
jrst infdon] ;be done
|
||
ERROR /Inferior trying to write superior./]
|
||
;complain
|
||
hlrz tt,t ;get operation
|
||
trne tt,200000 ;is it block mode?
|
||
error /Inferior trying to use block mode .BREAK 12,/
|
||
cail tt,brktbl ;is it out-of-range?
|
||
jrst unbrk
|
||
xct brktb(tt)
|
||
|
||
|
||
unbrk: error /Inferior got a bad .BREAK interrupt./
|
||
|
||
brktb: jrst unbrk
|
||
jrst unbrk
|
||
jrst unbrk
|
||
jrst unbrk
|
||
jrst unbrk
|
||
jrst getjcl
|
||
brktbl==.-brktb
|
||
|
||
getjcl: hrrz t,t ;get address again
|
||
pagmak t ;make it into a page # and loc in that page
|
||
movem t,jclpag ;save page and location in page
|
||
movem tt,jclloc ;for JCL
|
||
syscal corblk,[cnti %cbndw ;need write access
|
||
argi 0 ;no XORing, please
|
||
argi %jself ;map into ourself
|
||
argi tmpag1 ;at the highest possible location
|
||
argi usrc ;our inferior's
|
||
jclpag] ;page which is contained in A
|
||
jrst jclovf
|
||
aos jclpag ;get next page too
|
||
skipn t,jclct ;get length pointer of JCL
|
||
jrst infcnt ; no JCL, continue
|
||
addi t,4+1 ; (+1 to count ^M)
|
||
idivi t,5 ;(ptr+4)/5==length in words
|
||
add t,jclloc ;the final loc
|
||
cail t,2000 ;overflow?
|
||
do [syscal corblk,[cnti %cbndw ;need writing
|
||
argi 0 ;barf, no XOR, please
|
||
argi %jself
|
||
argi tmpag2 ;very moby
|
||
argi usrc ;our very inferior inferior
|
||
jclpag] ;and the next page
|
||
jrst jclovf] ;complain of indigestion
|
||
|
||
|
||
move t,jclct ;get the JCL length
|
||
addi t,4+1 ;convert to words (+1 to count ^M)
|
||
idivi t,5 ;from characters
|
||
move tt,jclloc ;get the offset for the address
|
||
add t,tt ;include it in the final total end address
|
||
hrri tt,<tmpag1_12>(tt) ;and put in right half for blt
|
||
hrli tt,jclbuf ;get our source for the BLT from the JCLPTR
|
||
blt tt,<tmpag1_12>-1(t) ;and perform the transfer
|
||
jrst infcnt
|
||
|
||
infcnt: uuopop
|
||
restor [tt,t,x]
|
||
|
||
.atty usrc, ;give it to him
|
||
jrst [.dtty ;get it back
|
||
.atty usrc, ;and try again
|
||
loss ;nope, we're screwed somehow
|
||
jrst infcn1] ;good, one with the show
|
||
|
||
call start
|
||
|
||
infcn1: syscal dismis,[cnti intspc
|
||
sp]
|
||
loss
|
||
|
||
jclovf: ERROR /Inferior tried to read JCL
|
||
into pure or non-existant memory./
|
||
|
||
value: syscal usrvar,[argi usrc ;turn off the interrupt
|
||
[sixbit /APIRQC/]
|
||
[%PIVAL]]
|
||
loss
|
||
type dspc,/AInferior .VALUE'd /
|
||
|
||
.uclose usrc,
|
||
jrst infdon
|
||
|
||
|
||
infdon: uuopop
|
||
restore [tt,t,x]
|
||
|
||
syscal dismis,[cnti intspc
|
||
sp]
|
||
loss
|
||
|
||
start: syscal usrvar,[argi usrc ;copy his old state
|
||
[sixbit /OPTION/]
|
||
val t]
|
||
loss
|
||
tlz a,optcmd+optbrk ;clear the OPTCMD bit (+ the OPTBRK since
|
||
;LISP demands it!)
|
||
skipe jclct ;if there is JCL
|
||
tlo t,optcmd+optbrk ;set it again
|
||
syscal usrvar,[argi usrc ;and set it up
|
||
[sixbit /OPTION/]
|
||
t] ;write it back again
|
||
loss
|
||
|
||
setom infp ;note we are in inferior
|
||
syscal usrvar,[argi usrc ;GO!
|
||
[sixbit /USTP/]
|
||
argi 0]
|
||
loss
|
||
|
||
ret
|
||
|
||
|
||
|
||
;;; run an inferior. Takes a job name in COMAND, and file names in
|
||
;;; INFFN1, FINFN2, and INFSNM
|
||
|
||
infcr: call jclcop ; Set up the JCL
|
||
.status usrc,t ; look at the channel
|
||
caie t,0 ; if there is something open
|
||
.uclose usrc, ; kill it
|
||
|
||
syscal open,[cnti .uii ; create a job
|
||
argi usrc
|
||
[sixbit /USR/]
|
||
argi 0 ; same UNAME as ourselves
|
||
COMAND] ; we look in COMAND for the UNAME
|
||
jrst [type dspc,/ACannot create inferior, maybe system full?
|
||
/
|
||
ret]
|
||
syscal open,[cnti .uii ; open a file to load into it
|
||
argi dski
|
||
[sixbit /DSK /]
|
||
inffn1
|
||
inffn2
|
||
infsnm]
|
||
error /Program missing/
|
||
|
||
syscal load,[argi usrc ; load it
|
||
argi dski]
|
||
jrst [move x,errret ; fetch the error code
|
||
cain x,%enacr ; no core?
|
||
jrst [type dspc,/AThe system is overcrowded to the point that you cannot even log in,
|
||
so I am logging you out.
|
||
/
|
||
phaser]
|
||
ifn $$PAND,[ cain x,%erojb ; Have we got a non-inferior?
|
||
jrst [type dspc,/AJob not inferior!
|
||
/
|
||
ret]
|
||
] ; END IFN $$PAND,
|
||
error /Can't load job/]
|
||
syscal iot,[argi dski ;get starting address
|
||
argi t] ;in a
|
||
loss
|
||
andi t,-1 ;ignore the JRST part
|
||
|
||
syscal close,[argi dski] ;close it
|
||
loss
|
||
|
||
syscal usrvar,[argi usrc ;make it start there
|
||
[sixbit /UPC/]
|
||
t] ;a has address
|
||
loss
|
||
|
||
syscal usrvar,[argi usrc ;get what bit to enable
|
||
[sixbit /INTB/]
|
||
val t]
|
||
loss
|
||
|
||
syscal usrvar,[argi %jself ;and enable it
|
||
[sixbit /IMSK2/]
|
||
t]
|
||
loss
|
||
|
||
TTYGO: call start
|
||
.atty usrc, ;give up the TTY and wait for return
|
||
jfcl
|
||
skipe infp ;until we aren't in inferior
|
||
.hang
|
||
.dtty
|
||
jfcl
|
||
ret
|
||
|
||
|
||
|
||
|
||
SUBTTL Initialization
|
||
|
||
;;;; Here goes the initialization code
|
||
|
||
ife $$pand,[
|
||
;; Following due to EAK
|
||
|
||
comchk: move t,ttycom ; Get our TTY com var
|
||
.suset [.runame,,uname] ; Make sure we know our UNAME for logging
|
||
tlne t,%tcrft\%tcico ; Did this loser slave another terminal
|
||
jrst ttyhak ; Yes, don't give him DDT as a reward.
|
||
movei count,100 ;if 100 TTY's are linked, we' must be
|
||
;looping looking for TTY that isn't there
|
||
;any more
|
||
comch0: syscal cnsget,[argi %jsnum(b) ;get the TTYCOM for given terminal
|
||
val t ? val t ? val t
|
||
val b]
|
||
loss
|
||
hrrzs b ; throw away the bits
|
||
camn b,consol ;are we back to the start?
|
||
jrst ttyhak ; yes, so must not be any winners, ask for
|
||
;password
|
||
cain b,-1
|
||
jrst ttyhak
|
||
syscal styget,[argi %jsnum(b) ;get a job for that TTY
|
||
val t ? val t
|
||
val c]
|
||
loss
|
||
jumple c,[sojg count,comch0 ;if it's free, try next
|
||
jrst ttyhak] ; oops, must be looping, no winners
|
||
syscal usrvar,[argi %jsnum(c)
|
||
[sixbit /UNAME/]
|
||
val c] ; find UNAME of linker
|
||
loss
|
||
movem c,linker ; remember who lunk to
|
||
hlrz c,c ; linker logged in?
|
||
caie c,-1 ;
|
||
jrst goddt4 ;winner, get him a DDT
|
||
sojg count,comch0 ; he's not responsible, try another
|
||
jrst ttyhak ;infinite loop, try again
|
||
] ;; end IFE $$PAND
|
||
|
||
run: setom debug ;this is the debug starting address
|
||
setom noddt ;don't get DDT for any TTY's
|
||
|
||
go: .close 1, ;if we're loaded by system, CH1 is open
|
||
move sp,[-pdllen,,pdl] ;initialize pdl
|
||
call ginit1 ;do early initialization
|
||
|
||
ife $$pand,jrst goddt5 ; lost somehow, bad....try to get DDT
|
||
ifn $$pand,.lose
|
||
ife $$pand,[
|
||
move t,ttycom ;check out the TTYCOM status
|
||
jumpl t,comchk ;it's in com link, don't do the default
|
||
;stuff
|
||
skipe noddt ; special debugging crock?
|
||
jrst ttyhak ; yes, be sure to get PWORD
|
||
|
||
;;; Ok, now we check out to see if it's a very important console.
|
||
;;; If it is, we be damned sure to get us DDT rather than risking lossage
|
||
;;; The less hair the better, I.e. what if there is a bug in a system call,
|
||
;;; Or GOD FORBID, in this program.
|
||
|
||
eval tt,syscn
|
||
skipe b,consol ;is it machine console?
|
||
camn b,tt ; or system console?
|
||
jrst goddt5 ; Go load up a DDT
|
||
move x,ttytyp ;what type?
|
||
tlne x,%TTLCL ;is it a local TTY?
|
||
jrst goddt5 ; Go load up a DDT
|
||
|
||
;;; Not a VIP terminal, go through regular checks.
|
||
|
||
move x,ttytyp
|
||
skipn debug ; debugin?
|
||
trnn x,%tysty ;is it a STY?
|
||
jrst notsty
|
||
|
||
syscal styget,[argi %jsnum(b) ? val tt] ;get info on this STY
|
||
loss
|
||
syscal open,[cnti .bii\10 ;open as foreign job
|
||
argi tlnc ;telnet channel
|
||
[sixbit /USR/]
|
||
argi %jsnum(tt) ;open the telser by job number
|
||
argi 0] ;0 JNAME means <JOB> spec
|
||
loss
|
||
|
||
syscal rfname,[argi tlnc ;is there a job open on this channel?
|
||
val t ; device
|
||
val x ; UNAME
|
||
val tt] ; JNAME
|
||
loss ; eh?
|
||
cain t,0 ;is the Device 0?
|
||
jrst goddt5
|
||
tlz x,777700 ;clear out the TTY # part of nnTLNT
|
||
came x,[sixbit / TLNT/] ;is it really a telser?
|
||
jrst goddt5
|
||
came tt,[sixbit /TELSER/] ;including JNAME?
|
||
jrst goddt5 ; nope
|
||
.access tlnc,[tsrloc] ; Where to get cruft from TELSER
|
||
move tt,[-1,,tsrtab] ; Transfer the first word
|
||
.iot tlnc,tt
|
||
move x,tsrtab ; Check it for validity
|
||
came x,[sixbit /TERMID/] ; Valid?
|
||
jrst ttyhak ; Funny TELSER??
|
||
move tt,[-<tsrcnt-1>,,<tsrtab+1>]
|
||
.iot tlnc,tt ; input the rest of the data from the TELSER
|
||
|
||
call ginit2 ; Gotta get the local site!
|
||
|
||
move a,lclsit ; Is this our local site?
|
||
skipn b,fhost
|
||
jrst ttyhak ; Huh? Shouldn't be possible
|
||
call netwrk"hstcmp ; If from local host, give PWORD
|
||
caia ;
|
||
jrst ttyhak ; so we can debug
|
||
|
||
movei a,lucktb ; AOBJN ptr to LUCKTB of sites to let on
|
||
call pwsget ; Get it into our buffer, T gets AOBJN ptr
|
||
luckp: move a,fhost
|
||
move b,(t)
|
||
call netwrk"hstcmp
|
||
caia
|
||
jrst goddt5 ; Give him DDT
|
||
aobjn t,luckp ; no, try next one
|
||
jrst ttyhak ; continue, check if system console.
|
||
|
||
notsty: call ginit2 ;perform rest of initialization
|
||
skipe noddt ;are we debugging?
|
||
jrst ttyhak ; yes, don't ever give DDT
|
||
move b,consol ; Console bit...
|
||
movei tt,1 ;one bit
|
||
setz t,
|
||
lshc t,(b) ;translate into bit for this TTY
|
||
tdnn tt,ddtty0 ; can we give him DDT for it?
|
||
tdne t,ddtty1
|
||
jrst goddt5 ; yes, win, get him DDT
|
||
;;; now check for dialups, for sake of TELSIT
|
||
movei tt,1 ;one bit
|
||
setz t,
|
||
move x,[440700,,[asciz /DIALUP/]]
|
||
lshc t,(b)
|
||
move bp,[440700,,hstnam]
|
||
tdnn tt,dltty0 ;is this a dialup?
|
||
tdne t,dltty1
|
||
copy x,bp ; yes, claim to be a dialup!
|
||
|
||
];; end ife $$PAND
|
||
|
||
ttyhak: call ginit2 ;perform rest of initialization
|
||
hlrz tt,runame ;get left half
|
||
ife $$pand,[
|
||
caie tt,-1 ;is it logged in?
|
||
skipe debug ; and debugging?
|
||
caia ; debuggin, don't go
|
||
jrst goddt5 ; not debuging, just get him DDT.
|
||
move t,[move [nlitim*60.*60.]] ;Start countdown
|
||
.realt t,
|
||
jfcl
|
||
]
|
||
ifn $$pand,[
|
||
call pwread ;read it
|
||
.logout 1,
|
||
move x,[sixbit /FOO/]
|
||
movem x,uname ;fake uname
|
||
call pwdmak
|
||
came t,spword
|
||
.logout 1,
|
||
setzm deathp ;note no errors
|
||
hlrz tt,runame ;check if we're logged in
|
||
cain tt,-1 ; not logged in?
|
||
.logout 1,
|
||
|
||
call pwdmap ;map in the database
|
||
.close pwdc, ;don't need it anymore
|
||
] ; END IFN $$PAND
|
||
|
||
;don't let him screw himself
|
||
syscal cnsset,[argi tyic ? [-1] ? [-1] ? [-1] ? argi 0]
|
||
loss
|
||
|
||
syscal sstatu,[val shutdn ;collect info from ITS for header
|
||
val sysdbg
|
||
val susrs
|
||
val parnxm
|
||
val time
|
||
val machin
|
||
val itsver]
|
||
loss
|
||
|
||
aos susrs ;count ourself
|
||
|
||
|
||
ife $$pand,[
|
||
tyo dspc,[^P] ;clear the screen
|
||
tyo dspc,["C]
|
||
call ksstat ;print out statistics
|
||
syscal open,[cnti .uai
|
||
argi dski
|
||
[sixbit /DSK/]
|
||
[sixbit /SYSTEM/]
|
||
[sixbit /MAIL/]
|
||
[sixbit /SYS/]]
|
||
jrst nsysm ;no system mail
|
||
call printf ;print the file
|
||
|
||
nsysm: move x,ttytyp ;find out what kind of TTY we've got
|
||
trne x,%tysty\%tydil ;is it a network sty? or dialup?
|
||
jrst jrst rdloop ; yes, don't print local mail
|
||
|
||
nnet: syscal open,[cnti .uai
|
||
argi dski
|
||
[sixbit /DSK/]
|
||
[sixbit /LOCAL/]
|
||
[sixbit /MAIL/]
|
||
[sixbit /SYS/]]
|
||
jrst nlocal ; no local mail
|
||
call printf
|
||
] ;; end ife $$PAND
|
||
|
||
ifn $$pand,[
|
||
tyo dspc,[^P] ;clear the screen
|
||
tyo dspc,["C]
|
||
type tyoc,/PANDA./
|
||
6type tyoc,[.fnam2] ;<our version #>
|
||
] ;; end IFN $$PAND
|
||
|
||
|
||
|
||
SUBTTL Read Loop
|
||
|
||
nlocal::
|
||
rdloop:
|
||
ifn $$PAND,[
|
||
setzm nodate ; be sure commands don't see this preset
|
||
skipn rdxct ; some cleanup action needing to be done?
|
||
jrst rdlop1
|
||
move a,rdxarg
|
||
move bp,rdxbp
|
||
xct rdxct ; run the cleanup handler
|
||
jfcl
|
||
setzm rdxct
|
||
rdlop1:
|
||
]; end of IFN $$PAND,
|
||
|
||
call readin ; main read loop
|
||
jrst [cain ch,^D ; or a ^D quit?
|
||
type tyoc,/ ^D XXX?
|
||
/
|
||
jrst rdloop] ; we've over rubbed out, or null operation
|
||
|
||
|
||
;; here is where we come if we successfully got a command
|
||
|
||
setz count, ;no input any more
|
||
|
||
;; Here is is where we come if we successfully get a command
|
||
|
||
terpri
|
||
call kdspch ;yes, dispatch off of it.
|
||
jrst rdloop ;loop even though we failed
|
||
jrst rdloop ;We won, do it again
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;;;;
|
||
;;;; Here goes the input parser/rubout processor
|
||
;;;;
|
||
;;;; Theory of operation of the command reader.
|
||
;;;; This operates in a "Parse as you go" mode.
|
||
;;;; The format of the input lines is as follows:
|
||
;;;;
|
||
;;;; 1) The line starts out with :'s, spaces, and tabs. These are ignored.
|
||
;;;; Only :'s are echoed.
|
||
;;;;
|
||
;;;; 2) Next is the command name, which is read as a single word of sixbit.
|
||
;;;; It is stored in the location COMAND when read
|
||
;;;;
|
||
;;;; 3) The command name is terminated with [SPACE], CR, ^K or [ALTMODE]
|
||
;;;;
|
||
;;;; If terminated with [ALTMODE], COMAND is taken to be a UNAME to log in
|
||
;;;; as, and it is fed to the ULOGIN routine to watch for <n>U or U. If
|
||
;;;; these are not given, it is an error.
|
||
;;;;
|
||
;;;; If CR or ^K is given, the command line is complete, and the successful
|
||
;;;; return is taken. (If it is over-rubbed out, the failure return is
|
||
;;;; taken.)
|
||
;;;;
|
||
;;;; If [SPACE] terminates the command name, the command is looked up.
|
||
;;;; If it doesn't exist, It goes into a BEEP loop waiting for him to rubout
|
||
;;;; the faulty command. If it does exist, the space is echoed, and the
|
||
;;;; command-name reader checks the commands flag bits to see who should
|
||
;;;; be called next.
|
||
;;;; If %COARG is present, it calls the 6bit argument reader, which is then
|
||
;;;; resposible for checking the %COCRG and %COJCL bits to decide who
|
||
;;;; to call after that. More on the 6bit argument reader (R6ARG) in a bit.
|
||
;;;; If %COARG is absent, and %COCRG is present, it calls the the control-
|
||
;;;; argument reader, which reads control-arguments. These are members of
|
||
;;;; an explicit set of possible arguments stored in the CARGHS table
|
||
;;;; The control-argument reader (RCARG) will either return successfully
|
||
;;;; with the offsets of the control-argument strings in the control
|
||
;;;; arg buffer (CARGB)
|
||
;;;; If %COCRG is absent as well, but %COJCL is present, it will call the
|
||
;;;; JCL reader. This simply reads in the characters until a ^C, ^_, or ^M
|
||
;;;; is encountered, and sets up the pointers to this string (in msgbuf)
|
||
;;;; in the reader data area
|
||
;;;; If none of %COJCL, %COCRG or %COARG is present, it
|
||
;;;; simply returns successful, since the command is one that ignores it's
|
||
;;;; arguments.
|
||
;;;;
|
||
;;;; 5) R6ARG is responsible for reading a 6bit argument, for commands such
|
||
;;;; as SEND and HELP. It does so in a manner very similar to the
|
||
;;;; command reader which calls it, but stores the result in ARGUMENT
|
||
;;;; and doesn't hack [ALTMODE].
|
||
;;;; R6ARG checks the command's flags that it is reading for, when it
|
||
;;;; is done, if terminated with other than line terminators, and if it has
|
||
;;;; %COCRG, it calls the command reader. If not, if it has %COJCL, it
|
||
;;;; calls the JCL reader, otherwise it returns successfully.
|
||
;;;;
|
||
;;;; 6) RCARG is responsible for reading control-arguments. This is for
|
||
;;;; dual purpose of allowing the HELP or ? keys to print which arguments
|
||
;;;; are available for a given command, and to pre-parse the input line
|
||
;;;; so that individual commands don't have to do any parsing of their input
|
||
;;;; It will not accept illegal control-arguments.
|
||
;;;; It does not call further parsers, but returns successfully in all
|
||
;;;; cases except over rubout.
|
||
;;;;
|
||
;;;; 7) RJCL is the routine which reads random JCL, such as that passed to
|
||
;;;; other programs or the SEND command. This does no parsing, but
|
||
;;;; simply saves the pointer into the input buffer when it is called, and
|
||
;;;; the count before and after, and returns successfully when an line
|
||
;;;; termination character is encountered, or unsuccessfully on over-rubout.
|
||
;;;;
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;;;;
|
||
;;;; How the rubout processing works.
|
||
;;;;
|
||
;;;; The rubout processing works quite simply:
|
||
;;;; Each reader is responsible for being able to rub out within its region.
|
||
;;;; If it calls another reader after it is done, it must be a returnable
|
||
;;;; call, which can either be successful, in which case, it may return
|
||
;;;; successfully as well, or unsuccessful, in which case it should wipe out
|
||
;;;; the character which terminated it's reading, and revert to reading (or
|
||
;;;; possibly rubing out instead).
|
||
;;;;
|
||
;;;; The routine WIPECH is the routine which handles erasing the characters
|
||
;;;; from the screen. It expects the character which would appear on the
|
||
;;;; screen to be rubbed out to be in CH. If it is a printing terminal, it
|
||
;;;; will do EMACS style rubouts, where it backspace-/-backspace's each
|
||
;;;; character character, seting LFFLAG. Each routine which echo's characters
|
||
;;;; should do so with the macro ECHO, which will do the LF when needed.
|
||
;;;;
|
||
|
||
.upure
|
||
rstate: %rsnul ; Reader State
|
||
ostate: %rsnul ; Previous reader state (no stack needed)
|
||
comand: 0 ; Command being hacked
|
||
altifx: 0 ; Infix in Altmode commands (FOO<0U)
|
||
argcnt: 0 ; Number of characters of argument
|
||
argptr: 0 ; Byte Pointer to argument
|
||
snacnt: 0 ; Number of characters of 'To:' line
|
||
snaptr: 0 ; Pointer to To: line
|
||
posloc: ; (save as COLLOC) where we entered %RSPOS
|
||
colloc: 0 ; Where on command line we entered %RSCOL
|
||
cmdloc: 0 ; Where on command line we entered %RSCMD
|
||
argloc: 0 ; Where on command line we entered %RSCOL
|
||
ps1loc: 0 ; Where on command line we entered %RSPS1
|
||
6cnt: 0 ; Number of characters 6bit reader read
|
||
arg6: 0 ; Prefix frobs put their arg here
|
||
linbeg: 0 ; Where line begins for rubbing out.
|
||
|
||
|
||
sndrds: 0 ; We've redisplayed the :SEND line
|
||
.pure
|
||
|
||
%RS==:400000,,-1 ; Typeout mask for %RS symbols
|
||
|
||
.foo==0
|
||
IRPW X,,[
|
||
%RSNUL ; Empty
|
||
%RSCOL ; Initial colons and spaces
|
||
%RSCMD ; Reading 6bit command name
|
||
%RSPOS ; Reading 6bit for postfix command
|
||
%RSPS1 ; 1 Altmode of postfix command
|
||
%RSPS2 ; 2 Altmodes of postfix command
|
||
%RSALT ; Altmode at beginning of line
|
||
%RSAL2 ; Second Altmode at beginning of line
|
||
%RSARG ; Reading arguments to a command
|
||
%RSFIL ; Reading filenames for a file, hack ALT
|
||
%RSSND ; Reading text for a :SEND
|
||
%RSSNA ; Reading addressee's for a :SEND
|
||
%RSTXT ; Reading text ended with ^C
|
||
%RSBAD ; Illegal gubbish on the line
|
||
%RS6BT ; Reading a word of 6bit
|
||
]
|
||
IRPS y,,[x]
|
||
Y==.foo
|
||
TERMIN
|
||
.foo==.foo+1
|
||
TERMIN
|
||
|
||
define TRANSITION state
|
||
jrst [movei x,%RS!state ? jrst newstate]
|
||
termin
|
||
|
||
|
||
;; STATE TRANSITION TABLE (reading forward)
|
||
;;
|
||
;; +--------+ : +--------+ 6bit +--------+ +--------+
|
||
;; | %RSNUL |--->| %RSCOL |----->| %RSCMD |--->| %RSARG |
|
||
;; +--------+ +--------+ +--------+ +--------+
|
||
;; | | +....................^ | |
|
||
;; | +----|------+ | +----------+
|
||
;; V ....+ V V V
|
||
;; +--------+ +--------+ +--------+ +--------+
|
||
;; | %RSPOS | | %RSALT |---+ | %RSFIL | | %RSSNA |
|
||
;; +--------+ +--------+ | +--------+ +--------+
|
||
;; | +-------+ |
|
||
;; V V V
|
||
;; +--------+ +--------+ +--------+ +--------+
|
||
;; | %RSPS1 |--->| %RSPS2 | | %RSAL2 | | %RSSND |
|
||
;; +--------+ +--------+ +--------+ +--------+
|
||
;;
|
||
;; +--------+
|
||
;; | %RS6BT |
|
||
;; +--------+
|
||
|
||
rdinit: movem bp,linbeg
|
||
setzb ct,count
|
||
setzm sndrds ; Say we haven't redisplayed :SEND buffer
|
||
setzm argcnt
|
||
setzm argloc
|
||
setzm snacnt
|
||
setzm arg6
|
||
ret
|
||
|
||
read6: save [a,c]
|
||
call rdinit
|
||
setz count,
|
||
move a,[440600,,arg6]
|
||
movei x,%rs6bt
|
||
movem rstate
|
||
call read0
|
||
jrst read6x
|
||
read6w: restore [c,a]
|
||
jrst popj1
|
||
|
||
read6x: restore [c,a]
|
||
ret
|
||
|
||
readln: save [a,c]
|
||
call rdinit ; read a line
|
||
movem bp,argloc
|
||
call readl0
|
||
jrst read6x
|
||
jrst read6w
|
||
|
||
readl0: TRANSITION ARG
|
||
|
||
readtx: move bp,[440700,,msgbuf]
|
||
readsn: save [a,c]
|
||
call rdinit ; Read multiple lines
|
||
movem bp,argloc
|
||
movem bp,argptr
|
||
call reads0
|
||
jrst read6x
|
||
jrst read6w
|
||
|
||
reads0: TRANSITION TXT
|
||
|
||
readfi: move bp,[440700,,msgbuf] ; Read a filename
|
||
call rdinit
|
||
movem bp,argloc
|
||
movem bp,argptr
|
||
TRANSITION FIL
|
||
|
||
readin: move bp,[440700,,msgbuf]
|
||
setzm helper ; Full command read has help built in
|
||
setzm dsprmp ; No special prompting
|
||
rdrset: call rdinit
|
||
movei x,%rsnul ; Initial EMPTY state
|
||
movem x,rstate
|
||
call prompt ; Prompt
|
||
read0: skipge ch,reread ; A character to be re-read?
|
||
.iot tyic,ch ; Get a chracter
|
||
setom reread
|
||
move t,rstate ; Get the state
|
||
cain ch,^L ; Redisplay?
|
||
jrst readrd ; Do it
|
||
cain ch,177 ; Rubout?
|
||
jrst readrb ; Do it
|
||
cain ch,%TXTOP+"H ; [HELP]?
|
||
jrst readhl
|
||
|
||
echoch ; ECHO it
|
||
|
||
cain ch,"? ; ??
|
||
jrst readhl ; Give help caie ch,^D
|
||
|
||
caie ch,^C
|
||
cain ch,^M
|
||
jrst readex
|
||
|
||
caie ch,^D
|
||
cain ch,^G
|
||
jrst [ type tyoc,/ XXX? /
|
||
jrst readfl ]
|
||
move x,rstate
|
||
cain x,%RSPOS
|
||
jrst read1
|
||
cain ch,^H ; Backspace instead of rubout?
|
||
jrst [ type dspc,/A;Use RUBOUT or DELETE to delete characters.
|
||
;BACKSPACE is for overstriking.
|
||
/
|
||
jrst redis ]
|
||
read1: idpb ch,bp ; Store the byte
|
||
aos ct ; Count it
|
||
caile ct,msgbfl ; Overflow?
|
||
jrst [ type dspc,/A(Line too long)/
|
||
jrst redis ] ; Redisplay it for him to rub out
|
||
|
||
readc: jrst @.+1(t)
|
||
RDNUL ? RDCOL ? RDCMD ? RDPOS ? RDPS1 ? RDPS2 ? RDALT ? RDAL2 ? RDARG
|
||
RDFIL ? RDSND ? RDSNA ? RDTXT ? RDBAD ? RD6BT
|
||
|
||
readex: move t,rstate
|
||
jrst @.+1(t)
|
||
RTNUL ? RTCOL ? RTCMD ? RTPOS ? RTPS1 ? RTPS2 ? RTALT ? RTAL2 ? RTARG
|
||
RTFIL ? RTSND ? RTSNA ? RTTXT ? RTBAD ? RT6BT
|
||
|
||
readw1: skipn comand ; Win if there's anything there
|
||
jrst readfl
|
||
|
||
readwn: setz ch, ; ensure ends with a null
|
||
push sp,bp
|
||
idpb ch,bp
|
||
pop sp,bp
|
||
setom reread
|
||
jrst popj1
|
||
readw0: push p,bp
|
||
setz x,
|
||
idpb x,bp
|
||
pop p,bp
|
||
jrst readwn
|
||
|
||
RTBAD: move x,ostate ; What state went bad?
|
||
cain x,%rscmd ; Command reading?
|
||
jrst rtbadc ; Barf about unknown command
|
||
type dspc,/AI don't understand that.
|
||
/
|
||
jrst readfl
|
||
|
||
rtbadc: type dspc,/AI don't know the '/
|
||
6type tyoc,comand
|
||
type tyoc,/' command.
|
||
/
|
||
jrst readfl
|
||
|
||
RTNUL:
|
||
RTCOL:
|
||
readfl: setom reread
|
||
ret
|
||
|
||
readrb: ldb ch,bp ; Get the character to be eliminated
|
||
call wipech ; Wipe it from the screen
|
||
decbp bp ; Back up the pointer
|
||
soja ct,@.+1(t)
|
||
RBNUL ? RBCOL ? RBCMD ? RBPOS ? RBPS1 ? RBPS2 ? RBALT ? RBAL2 ? RBARG
|
||
RBFIL ? RBSND ? RBSNA ? RBTXT ? RBBAD ? RB6BT
|
||
|
||
readhl: jrst @.+1(t)
|
||
RHNUL ? RHCOL ? RHCMD ? RHPOS ? RHPS1 ? RHPS2 ? RHALT ? RBAL2 ? RHARG
|
||
RHFIL ? RHSND ? RHSNA ? RHTXT ? RHBAD ? RL6BT
|
||
|
||
readh0: skipe helper ; Have we got a special helper?
|
||
xct helper ; Provide the help
|
||
jrst redis ; and redisplay
|
||
|
||
readrd: move t,rstate
|
||
jrst @.+1(t)
|
||
RLNUL ? RLCOL ? RLCMD ? RLPOS ? RLPS1 ? RLPS2 ? RLALT ? RLAL2 ? RLARG
|
||
RLFIL ? RLSND ? RLSNA ? RLTXT ? RLBAD ? RL6BT
|
||
|
||
newstate:
|
||
movem x,rstate
|
||
jrst read0
|
||
|
||
RDNUL: cain ch,40
|
||
jrst read0 ; Spaces we ignore
|
||
cain ch,^M ; Return
|
||
jrst readex
|
||
cain ch,^R ; A control-R to print a file
|
||
jrst read.r ; Go do it now.
|
||
cain ch,^F
|
||
jrst read.f
|
||
movem ct,colloc
|
||
cain ch,":
|
||
TRANSITION COL
|
||
caie ch,%txtop+"H ; If he's asking for help, give it to him
|
||
cain ch,"?
|
||
jrst [call bhelp ? jrst read0]
|
||
movem ct,posloc
|
||
cain ch,33 ; Altmode?
|
||
TRANSITION ALT
|
||
caie ch,".
|
||
cain ch,"%
|
||
jrst begpos
|
||
caie ch,"!
|
||
cain ch,"/
|
||
jrst begpos
|
||
|
||
cail ch,"0
|
||
caile ch,"9
|
||
caia
|
||
jrst begpos
|
||
cail ch,"a
|
||
caile ch,"z
|
||
caia
|
||
jrst begpos
|
||
cail ch,"A
|
||
caile ch,"Z
|
||
caia
|
||
jrst begpos
|
||
jrst gobad ; Go into BAD state
|
||
|
||
read.r: move x,[sixbit /UPRINT/] ; Prepare to read ^R-style
|
||
movem x,comand
|
||
movei x,[asciz /A(Print File)/]
|
||
movem x,filprm ; Set up prompt for printing a file
|
||
setz x ; Use the normal default.
|
||
call flprmp ; Prompt with the filename default
|
||
movem ct,argloc ; Remember where the filename begins
|
||
movem bp,argptr
|
||
TRANSITION FIL ; Start reading the filename
|
||
|
||
rdflal: move x,[asciz /A(Print File)/]
|
||
movem x,filprm
|
||
setz x
|
||
call flprmp
|
||
move bp,[440700,,msgbuf]
|
||
call rdinit
|
||
jrst read0
|
||
|
||
read.f: move x,[sixbit /ULISTF/]
|
||
movem x,comand
|
||
setzm arg6
|
||
jrst readwn
|
||
|
||
begpc: move a,[440600,,comand]
|
||
setzm comand ; Initialize it to blanks
|
||
cail ch,140
|
||
subi ch,40
|
||
subi ch,40
|
||
idpb ch,a ; and deposit
|
||
movei count,1 ; 1 character
|
||
ret
|
||
|
||
begcmd: call begpc
|
||
TRANSITION CMD ; We're now in %RSCMD state
|
||
|
||
begpos: call begpc
|
||
TRANSITION POS
|
||
|
||
RBNUL: jrst rdrset ; Ignore rubouts here
|
||
|
||
RHCOL: call bhelp
|
||
jrst redis
|
||
|
||
RHNUL: call bhelp ; Tell what commands exist
|
||
jrst rdrset ; Flush blanks, etc, and reprompt
|
||
|
||
RLNUL: type dspc,/C/
|
||
jrst rdrset ; Show an empty line
|
||
|
||
RHBAD: type dspc,/ARandom garbage on the command line, delete /
|
||
10type tyoc,count
|
||
type tyoc,/ character(s) to correct.
|
||
/
|
||
jrst redis
|
||
|
||
RBBAD: sojg count,read0 ; Still bad ...
|
||
move x,ostate ; Enough rubouts to fix up
|
||
movem x,rstate ; so return to previous state
|
||
jrst read0
|
||
|
||
gobad: movei count,1 ; Number of bad characters
|
||
move x,rstate ; Remember what state we came from
|
||
movem x,ostate
|
||
TRANSITION BAD
|
||
|
||
RDBAD: aoja count,read0 ; More badness
|
||
|
||
RLCOL:
|
||
RLFIL:
|
||
RLARG:
|
||
RL6BT:
|
||
RLCMD:
|
||
RLPS2:
|
||
RLPS1:
|
||
RLALT:
|
||
RLAL2:
|
||
RLPOS:
|
||
RLBAD: jrst credis
|
||
|
||
RDCOL: caie ch,": ; Colon?
|
||
caig ch,40 ; non-printing character?
|
||
caia
|
||
jrst begcmd
|
||
jrst read0 ; Just ignore them after 1st colon
|
||
|
||
RBCOL: camge ct,colloc ; Anything left in buffer?
|
||
TRANSITION NUL
|
||
jrst read0
|
||
|
||
RDPOS: cain ch,^A ; Single-character commands
|
||
jrst readxm ; PRMAIL
|
||
cain ch,^F
|
||
jrst readxf ; LISTF
|
||
caie ch,^H
|
||
cain ch,^K
|
||
jrst readw1
|
||
|
||
setzm altifx ; An infix arg to $U?
|
||
cain ch,33 ; Altmode?
|
||
TRANSITION PS1
|
||
|
||
call rd6 ; Do the work for reading in 6bit
|
||
caia
|
||
jrst read0
|
||
ife $$PAND,[
|
||
rtpos1:
|
||
type dspc,/A(You must begin commands with a colon)
|
||
/
|
||
jrst readfl
|
||
|
||
] ; END of IFE $$PAND,
|
||
.else [
|
||
jrst rtcmd0
|
||
] ; End of IFN $$PAND, (.else)
|
||
|
||
readxm: move x,comand
|
||
movem x,arg6
|
||
move x,[sixbit /PRMAIL/]
|
||
movem x,comand
|
||
jrst readwn
|
||
|
||
readxf: move x,comand
|
||
movem x,arg6
|
||
move x,[sixbit /ULISTF/]
|
||
movem x,comand
|
||
jrst readwn
|
||
|
||
RTPOS: skipn comand ; Anything there?
|
||
jrst readfl ; Nope, just return failure
|
||
ife $$PANDA,[
|
||
jrst rtpos1 ; Yes, complain about no colon
|
||
] ; END of IFE $$PANDA,
|
||
.else [
|
||
jrst readwn ; We got a command
|
||
]
|
||
|
||
RBPOS: sojge count,rbcmd0 ; If there's anything left, back up one
|
||
TRANSITION NUL ; Nothing left
|
||
|
||
RDPS1: cain ch,33 ; Altmode?
|
||
TRANSITION PS2 ; Yes, it's two altmodes
|
||
cail ch,"0
|
||
caile ch,"9
|
||
jrst rdps10
|
||
movem ch,altifx
|
||
jrst read0
|
||
rdps10: cain ch,^A ; FOO
|
||
jrst rdps11
|
||
caie ch,"u
|
||
cain ch,"U
|
||
caia
|
||
jrst gobad ; Lossage, go into BAD state
|
||
move x,comand
|
||
movem x,arg6
|
||
move x,[sixbit /ULOGIN/]
|
||
movem x,comand
|
||
jrst readwn
|
||
|
||
rdps11: move x,comand
|
||
movem x,arg6
|
||
move x,[sixbit /UPRMAIL/]
|
||
movem x,comand
|
||
jrst readwn
|
||
|
||
RTPS1: move x,comand ; Assume he meant to say 'U'
|
||
movem x,arg6
|
||
move x,[sixbit /ULOGIN/]
|
||
movem x,comand
|
||
jrst readwn
|
||
|
||
RBPS1: camge ct,ps1loc ; Have we rubbed out all of this state?
|
||
TRANSITION POS ; Yes, previous state
|
||
setzm altifx ; No more infix then
|
||
jrst read0
|
||
|
||
RDPS2: cail ch,"0
|
||
caile ch,"9
|
||
jrst rdps20
|
||
movem ch,altifx
|
||
jrst read0
|
||
rdps20: caie ch,^A
|
||
jrst rdalt0 ; Complain if not ^A
|
||
move x,comand
|
||
movem x,arg6
|
||
move x,[sixbit /PRRMAI/]
|
||
movem x,comand
|
||
jrst readwn
|
||
|
||
RBPS2: TRANSITION PS1
|
||
|
||
RHPOS: type dspc,/Acommand <==> :command
|
||
/
|
||
RHPS1: type dspc,/AnameU <==> :LOGIN name
|
||
name <==> :PRMAIL name
|
||
/
|
||
RHPS2: type dspc,/Aname <==> :PRRMAIL name
|
||
/
|
||
|
||
RDALT: setzm arg6
|
||
cain ch,^A ; <alt>^A?
|
||
jrst [move x,[sixbit /UPRMAI/] ? movem x,comand ? jrst readwn]
|
||
cain ch,33
|
||
TRANSITION AL2
|
||
rdalt0: type dspc,/AHuh? I don't understand that!
|
||
/
|
||
jrst readfl
|
||
|
||
RBALT: TRANSITION NUL
|
||
|
||
|
||
RDAL2: caie ch,"v
|
||
cain ch,"V ; V?
|
||
jrst rdal20
|
||
caie ch,"u
|
||
cain ch,"U
|
||
jrst rdal21
|
||
cain ch,^A ; <alt><alt>^A?
|
||
jrst [ move x,[sixbit /PRRMAI/]
|
||
movem x,comand
|
||
jrst readwn ]
|
||
cail ch,"0 ; Numeric infix?
|
||
caile ch,"9
|
||
jrst rdalt0 ; nope, gubbish
|
||
movem ch,altifx
|
||
jrst read0
|
||
|
||
rdal20: move x,[sixbit /LISTJ/]
|
||
movem x,comand
|
||
jrst readwn
|
||
|
||
rdal21: move x,[sixbit /ULOGOU/]
|
||
movem x,comand
|
||
jrst readwn
|
||
|
||
|
||
RTPS2:
|
||
RTALT:
|
||
RTAL2: type dspc,/AHuh? I don't understand that.
|
||
/
|
||
jrst readfl
|
||
|
||
RBAL2: TRANSITION ALT ; Previous state
|
||
|
||
RHALT:
|
||
RHAL2: type dspc,/A
|
||
$U -- :LOGOUT (Prepare to disconnect from ITS.)
|
||
V -- :LISTJ (List what jobs you have. Not applicable until logged in.)
|
||
/
|
||
jrst redis
|
||
|
||
RD6BT: call rd6 ; Read in the 6bit
|
||
jrst readwn ; Read won
|
||
jrst read0 ; More to come
|
||
|
||
RDCMD: call rd6 ; Read in the 6bit
|
||
jrst rtcmd0 ; Terminate it
|
||
jrst read0 ; More to come
|
||
|
||
rd6: caie ch,^I
|
||
cain ch,40
|
||
ret ; Ended
|
||
cail count,6 ; Is there any more room in the word?
|
||
aoja count,popj1 ; No, just count it
|
||
cail ch,140
|
||
subi ch,40
|
||
subi ch,40
|
||
idpb ch,a ; Deposit the character
|
||
aoja count,popj1
|
||
|
||
rtcmdx: cail count,6 ; any blanks in the word?
|
||
ret ; If not, just return
|
||
move x,6blk(count) ; Else gotta clear them out
|
||
andcam x,comand
|
||
ret
|
||
|
||
6blk: 777777,,777777
|
||
007777,,777777
|
||
000077,,777777
|
||
000000,,777777
|
||
000000,,007777
|
||
000000,,000077
|
||
|
||
RT6BT: call rt6btx ; Pad with blanks
|
||
skipn arg6
|
||
jrst readfl
|
||
jrst readwn
|
||
|
||
rt6btx: cail count,6 ; any blanks in the word?
|
||
ret ; If not, just return
|
||
move x,6blk(count) ; Else gotta clear them out
|
||
andcam x,arg6
|
||
ret
|
||
|
||
|
||
RTCMD: call rtcmdx ; pad with blanks
|
||
skipn comand ; Anything left of the command?
|
||
jrst readfl ; No, a failure
|
||
jrst readwn ; Yes, success
|
||
|
||
rtcmd0: movem count,6cnt ; Remember in case we rub back here
|
||
move tt,comand ; Get the command involved
|
||
call ttkget ; Get ptr to it
|
||
jrst gobad ; Undefined, it's bad
|
||
movem bp,argptr ; Save pointer to where command's args begin
|
||
setzm argcnt
|
||
move x,cm$flg(t) ; Get the flag bits
|
||
tlne x,%COFIL
|
||
transition FIL
|
||
tlnn x,%COSND
|
||
transition ARG
|
||
movem bp,snaptr ; Remember where name begins
|
||
setzm snacnt
|
||
transition SNA
|
||
|
||
RH6BT: xct helper
|
||
jrst read0
|
||
|
||
RHCMD: cail ct,6 ; If we have too few characters
|
||
jrst rhcmd0
|
||
move x,6blk(ct) ; We must mask off the unfilled part of
|
||
andcam x,comand ; the command name
|
||
rhcmd0: move tt,comand ; Get the command
|
||
call ttkget ; Get the index to it's info
|
||
jrst rhcmd1 ; No command, foo
|
||
push sp,comand
|
||
call pldoc ; print the documentation for this command
|
||
pop sp,nul
|
||
jrst read0 ; Onward
|
||
|
||
rhcmd1: call bhelp ; Tell him what he has to choose from
|
||
jrst redis ; show what he's got
|
||
|
||
RB6BT: sojl count,readfl ; Fail if we over-rubout
|
||
call rt6btx ; Pad arg with blanks
|
||
caige count,6 ; If we're over, we're OK
|
||
move a,6bp(count) ; Get the new byte pointer
|
||
hrri a,arg6 ; We're putting 6bit in ARG6, not COMAND
|
||
jrst read0 ; So now we're backed up
|
||
|
||
RBCMD: sojl count,rbcmd1 ; uncount it
|
||
rbcmd0: call rtcmdx ; Pad command with blanks
|
||
caige count,6 ; If we're over, we're OK
|
||
move a,6bp(count) ; Get the new byte pointer
|
||
jrst read0 ; so now we're backed up.
|
||
|
||
rbcmd1: TRANSITION COL
|
||
|
||
6bp: 440600,,comand
|
||
360600,,comand
|
||
300600,,comand
|
||
220600,,comand
|
||
140600,,comand
|
||
060600,,comand
|
||
|
||
RTTXT:
|
||
RTSND: cain ch,^C
|
||
jrst readw0
|
||
movei ch,^M
|
||
idpb ch,bp
|
||
movei ch,^J
|
||
idpb ch,bp
|
||
movei x,2
|
||
addm x,ct
|
||
addm x,argcnt
|
||
jrst read0
|
||
|
||
RTSNA: movem bp,argptr
|
||
setzm argcnt
|
||
TRANSITION SND
|
||
|
||
RTARG:
|
||
RTFIL: setz ch, ; Ensure that it ends with a NUL
|
||
idpb ch,bp ; For the sake of RFN
|
||
jrst readwn
|
||
|
||
RDSNA: caie ch,40 ; Whitespace
|
||
cain ch,^I
|
||
jrst rtsna ; Go on to SND state
|
||
aos snacnt ; Count this character
|
||
jrst read0 ; Loop
|
||
|
||
RDTXT:
|
||
RDSND: cain ch,^W
|
||
jrst rdsndw
|
||
cain ch,^U
|
||
jrst rdsndu
|
||
cain ch,^R
|
||
jrst rdsndr
|
||
cain ch,^K
|
||
jrst rlsnd0
|
||
|
||
RDARG: aos argcnt ; Count the argument
|
||
jrst read0
|
||
|
||
|
||
snddis: move x,argptr ; The line for rediplay begins with the text
|
||
movem x,linbeg
|
||
move ct,argcnt
|
||
call sndhdr ; Print the :SEND header
|
||
setom sndrds ; say we've reformated it
|
||
pjrst redsj ; Redisplay our stuff
|
||
|
||
rdsndw: call wipech ; Wipe the ^W from the screen
|
||
decbp bp ; Back up the pointer
|
||
sos ct ; over the ^W
|
||
skipn sndrds ; Have we reformated the SEND buffer?
|
||
call snddis
|
||
move c,argcnt ; Count of characters originally in buffer
|
||
move d,bp
|
||
call rdsnup ; Maybe move up to previous line
|
||
jrst rdsnw1
|
||
|
||
rdsnw0: decbp bp ; We've decided to delete it
|
||
rdsnw1: jumple c,rdsnx ; Update the screen and return if empty
|
||
ldb ch,bp ; Check out this character
|
||
cain ch,^J ; Linefeed?
|
||
call lfnlck ; Yes, see if part of a newline (CRLF)
|
||
jrst rdsnw2 ; No, just treat as control char
|
||
call rubnl ; Newline, flush it
|
||
soja c,rdsnw0 ; and keep looking for the word
|
||
rdsnw2: call alphap ; Special character?
|
||
soja c,rdsnw0 ; Yes, skip it
|
||
|
||
decbp bp ; We've decided to delete this
|
||
sojle c,rdsnx ; Update the screen and return if empty
|
||
rdsnw3: ldb ch,bp ; Check out this character
|
||
call alphap ; Special character?
|
||
jrst rdsnx ; Yes, that delimits the word
|
||
decbp bp ; Be sure to delete this one too.
|
||
sojg c,rdsnw3 ; Part of the word, flush it
|
||
jrst rdsnx ; Start of word, update display
|
||
|
||
rdsndu: call wipech ; Remove the ^U from the screen
|
||
decbp bp ; Back over the ^U
|
||
sos ct
|
||
skipn sndrds ; Have we reformated the SEND buffer?
|
||
call snddis
|
||
move c,argcnt ; Count of characters originally in buffer
|
||
move d,bp
|
||
; Let's back over the first character
|
||
jumpe c,rdsnx ; if at beginning of line, will go to
|
||
; previous line
|
||
call rdsnup ; Maybe move up a line
|
||
jrst rdsnu1 ; hack all this
|
||
|
||
rdsnu0: decbp bp
|
||
sos c
|
||
ldb ch,bp ; Check out this character
|
||
rdsnu1: cain ch,^J ; Linefeed?
|
||
call lfnlck ; Yes, see if part of a newline (CRLF)
|
||
caia
|
||
jrst rdsnx ; Don't back over it, redisplay
|
||
jumpg c,rdsnu0 ; Update the screen and return if empty
|
||
jrst rdsnx ; Empty, update screen
|
||
|
||
rdsnup: ldb ch,bp
|
||
rdsup1: caie ch,^J ; Is it a linefeed?
|
||
ret ; No, this isn't a line begin
|
||
call lfnlck ; Is this part of a newline (CRLF)?
|
||
ret ; No, just hack as bare ^J
|
||
decbp bp ; Move over the ^M as well
|
||
sos c
|
||
sos ct
|
||
move x,ttyopt
|
||
tlnn x,%tomvu ; Can we move up?
|
||
jrst rdsnrl ; No, just redisplay previous line
|
||
tlne x,%toovr ; no-overstrike (a way to erase)
|
||
tlnn x,%toers ; Otherwise erasible?
|
||
caia ; yes
|
||
jrst rdsnrl ; no, don't confusingly move up
|
||
type dspc,/U/
|
||
save [x,t,a,b]
|
||
move t,bp ; copy some data temporarily
|
||
move b,c
|
||
call findnl ; Find out the beginning of this line
|
||
call rdsnxa ; Find out where on this line we are
|
||
type dspc,/H/ ; let's position ourself on this line
|
||
movei ch,10(a)
|
||
tyo dspc,ch
|
||
restore [b,a,t,x]
|
||
ret
|
||
|
||
rdsndr: decbp bp ; Back over the ^U
|
||
sos ct
|
||
skipn sndrds ; Have we reformated the SEND buffer?
|
||
call snddis
|
||
call rdsnrl ; Redisplay the line
|
||
jrst read0
|
||
|
||
rdsnrl: save [x,t,b]
|
||
move b,argcnt ; Count of characters originally in buffer
|
||
move t,bp
|
||
call findnl ; Find the beginning of the line
|
||
caml b,argcnt ; Did we back up at all?
|
||
jrst rdsnrx ; Nope, don't do anything
|
||
move x,ttyopt
|
||
tlne x,%toovr ; Can't over-strike? Can erase that way!
|
||
tlne x,%TOERS ; Skip if can't erase
|
||
jrst rdsnrd ; Aha, we can do it nicely
|
||
type tyoc,/
|
||
/ ; Nope, just start a new line
|
||
caia
|
||
rdsnrd: type dspc,/HL/ ; Display, we can clear this line
|
||
rdsnr0: caml b,argcnt ; Are we back to where we began?
|
||
jrst rdsnrx ; Yep, all done
|
||
ildb ch,t ; Pick up a character
|
||
echoch ; Echo it
|
||
aoja b,rdsnr0 ; next character
|
||
|
||
rdsnrx: restore [b,t,x]
|
||
ret
|
||
|
||
; In C is the count of characters in the edited argument.
|
||
; In ARGCNT is original count. It will be updated to the new count
|
||
; In BP is the Byte pointer to the remaining argument
|
||
; In D is the old byte pointer
|
||
; Update the display and go to READ0
|
||
|
||
rdsnx: caml c,argcnt ; Do we have anything to do?
|
||
jrst read0 ; No change, do nothing
|
||
save [t,ch,b]
|
||
move t,bp ; Copy of the BP
|
||
move b,c ; Copy of the count
|
||
call findnl ; Find the beginning of this line
|
||
call rdsnxa ; Get in A the # of character positions
|
||
; now on the line
|
||
save [a,c]
|
||
move c,argcnt ; Now we get to find out how character
|
||
move t,argptr
|
||
call rdsnxa ; positions were rubbed out
|
||
move b,a ; B gets count
|
||
restore [c,a] ; A recovers hpos
|
||
movem c,argcnt ; We don't need the old count anymore
|
||
move x,ttyopt
|
||
tlne x,%toovr ; Can't over-strike? Can erase that way!
|
||
tlne x,%TOERS ; Skip if can't erase
|
||
jrst rdsnxd ; Aha, we can do it nicely
|
||
cail a,20. ; If we're close to left we can always
|
||
jrst rdsnx0
|
||
tlnn x,%tomvb ; back up, even if our TTY won't backspace
|
||
jrst rdsnxl ; Otherwise, we're a loser
|
||
|
||
rdsnx0: type dspc,/H/ ; Win, let's do it with slashes
|
||
movei x,10(a) ; Compute character to indicate our position
|
||
tyo dspc,x ; output it
|
||
|
||
sosl b
|
||
tyo tyoc,["/] ; Output a slash, b types
|
||
sojge b,.-1
|
||
type dspc,/H/
|
||
movei x,10(a)
|
||
tyo dspc,x
|
||
setom lfflag
|
||
restore [b,ch,t]
|
||
move ct,argcnt
|
||
jrst read0
|
||
|
||
rdsnxd: restore [b,ch,t]
|
||
type dspc,/H/
|
||
movei x,10(a)
|
||
tyo dspc,x
|
||
type dspc,/L/
|
||
rdsnxx: move ct,argcnt
|
||
jrst read0
|
||
|
||
rdsnxl: restore [b,ch,t]
|
||
sojl b,rdsnxx ; When no more characters left, done
|
||
ldb ch,d ; Get first character rubbed out
|
||
tyo tyoc,ch ; Type it
|
||
decbp d ; Back up the byte pointer
|
||
jrst rdsnxl ; loop until sick of it
|
||
|
||
;; FINDNL takes a Byte Pointer in T, a count in B, and sets them to point
|
||
;; to the last NL or the beginning of the buffer.
|
||
|
||
|
||
findnl: jumpe b,cpopj
|
||
fndnl0: ldb ch,t
|
||
cain ch,^J ; Looking for a linefeed
|
||
ret
|
||
decbp t ; Back up pointer
|
||
sojg b,fndnl0 ; or the beginning of the buffer
|
||
ret
|
||
|
||
; Get the current horizontal position in A
|
||
; C has the count to end at, T has the Byte Pointer to follow.
|
||
|
||
rdsnxa: setz a, ; A counts the character positions
|
||
caml b,c ; Already to the end?
|
||
ret
|
||
rdsxa0: ildb ch,t ; Check out a character
|
||
cain ch,^I ; TAB?
|
||
jrst rdsnxI ; Special case
|
||
caie ch,177 ; Rubout?
|
||
caige ch,40 ; Control?
|
||
aos a ; count the uparrow
|
||
aos a ; Count it
|
||
aos b
|
||
rdsxa1: came b,c ; Is this all?
|
||
jrst rdsxa0 ; Nope, keep counting
|
||
ret
|
||
|
||
rdsnxI: addi a,7 ; Go to next tab stop
|
||
andi a,-10 ; but no further
|
||
aoja b,rdsxa1 ; Return to the loop
|
||
|
||
alphap: caige ch,"A ; Special character?
|
||
caig ch,"9
|
||
caia
|
||
ret
|
||
caige ch,"0 ; Special character?
|
||
ret
|
||
jrst popj1
|
||
|
||
|
||
;Check to see if a LF is part of a CRLF pair. Skip if so.
|
||
lfnlck: caig c,1 ; Is this the last character?
|
||
ret ; Yes, it's not part of CRLF
|
||
push sp,x
|
||
move x,bp
|
||
decbp x
|
||
ldb x,x
|
||
cain x,^M ; A ^M to match it?
|
||
aos -1(sp)
|
||
pop sp,x
|
||
ret
|
||
|
||
;Handle backing over a newline.
|
||
rubnl: move x,ttyopt ; Get TTY characteristics
|
||
tlnn x,%tomvu ; Can it move up?
|
||
jrst rubnl1 ; No, do something else
|
||
rubnl0: type dspc,/H/ ; Go to beginning of this line
|
||
call findnl
|
||
ret ; Return
|
||
|
||
rubnl1: tlne x,%toovr ; Can't over-strike? Can erase that way!
|
||
tlne x,%TOERS ; Skip if can't erase
|
||
caia ; Aha, we can do it nicely
|
||
jrst rubnl0 ; Boo, can't do it
|
||
|
||
rlsnd0: type dspc,/A/
|
||
decbp bp ; Back over the ^K
|
||
sos ct
|
||
jrst rlsnd1
|
||
|
||
|
||
RLTXT: type dspc,/C/
|
||
setom sndrds
|
||
jrst rlsnd2
|
||
|
||
RLSND: type dspc,/C/
|
||
rlsnd1: setom sndrds
|
||
call sndhdr ; Print the header
|
||
rlsnd2: move x,argptr ; Say things begin with the argument
|
||
movem x,linbeg
|
||
move ct,argcnt
|
||
RLSNA: jrst redis
|
||
|
||
sndtyp: -11,,snddsc ; Header and message
|
||
sndltp: -10,,snddsc ; Just header
|
||
|
||
snddsc: 440700,,[asciz /[Message from /]
|
||
tp$6bt runame
|
||
440700,,[asciz / at /]
|
||
tp$6bt machin
|
||
440700,,[asciz / /]
|
||
tp$6bt a
|
||
tp$ind (b)[ 440700,,[asciz /am/]
|
||
440700,,[asciz /pm/] ]
|
||
440700,,[asciz /]
|
||
/]
|
||
tp$ind argptr
|
||
|
||
sndhdr: move x,rstate
|
||
caie x,%rssnd ; Is this really sending?
|
||
ret ; nope, don't print SEND header!
|
||
terpri
|
||
call sndtim
|
||
typout tyoc,sndltp
|
||
ret
|
||
|
||
sndtim: .rtime tt, ; Get 0 ? HHMMSS
|
||
and tt,[-10000] ; Get 0 ? HHMM__
|
||
setz t,
|
||
lshc t,14 ; Get HH ? MM____
|
||
setz b, ; flags pm instead of am
|
||
cail t,(sixbit / 12/) ; Is it 12:00-23:59?
|
||
aos b ; yes, it's PM
|
||
caile t,(sixbit / 12/) ; Is it 24hour time?
|
||
jrst [subi t,100 ; Convert it. Subtract the 10
|
||
ldb x,[000600,,t] ; Get the second digit
|
||
caige x,'2 ; Is it less than 2?
|
||
subi t,000070 ; Must perform a borrow type operation
|
||
cail x,'2 ; Otherwise
|
||
subi t,2 ; Can just decrement by 2
|
||
jrst .+1]
|
||
lsh t,6 ; Get HH0 ? MM____
|
||
iori t,(sixbit / :/) ; Get HH: ? MM____
|
||
lshc t,-14 ; Get H ? H:MM__
|
||
caie t,(sixbit / 0/) ; Leading zero?
|
||
lshc t,-6 ; No, include it
|
||
move a,tt ; Because TYPOUT can't hack TT
|
||
ret
|
||
|
||
RDFIL: aos argcnt ; Count the argument
|
||
caie ch,33
|
||
jrst read0
|
||
setz ch, ; Let's make this an ASCIZ string
|
||
dpb ch,bp ; replacing the altmode with a NUL
|
||
|
||
move d,bp ;pointer to the file-name
|
||
movei b,filnam ;pointer to filename block
|
||
call rfn"rfn ;read the names
|
||
|
||
movei x,[asciz /(Print File)/]
|
||
movem x,filprm
|
||
movei x,filnam
|
||
call flprmp ; Reprompt with our new info
|
||
setz argcnt
|
||
move bp,argptr ; Re-initialize our reader to be just after
|
||
move ct,argloc ; where we began
|
||
jrst read0 ; and read in the filename.
|
||
|
||
RBSNA: move count,6cnt ; In case we rub back into the command
|
||
sosge snacnt ; uncount this character
|
||
TRANSITION CMD ; Underflow
|
||
jrst read0
|
||
|
||
RBTXT:
|
||
RBSND: sosge c,argcnt ; uncount this char
|
||
transition SNA ; underflow
|
||
jumpe c,read0 ; Anything left?
|
||
call rdsup1
|
||
movem c,argcnt ; Update the new argument count
|
||
jrst read0
|
||
|
||
RBFIL:
|
||
RBARG: move count,6cnt ; In case we rub back into the command
|
||
skipg argcnt ; Nothing left?
|
||
transition CMD ; underflow
|
||
sos argcnt ; uncount this char
|
||
jrst read0
|
||
|
||
RHARG: move tt,comand
|
||
call ttkget
|
||
error /TTKGET didn't find command, but we're in RHARG??/
|
||
push sp,comand
|
||
call pldoc ; Give him the documentation
|
||
pop sp,nul
|
||
jrst redis ; Redisplay
|
||
|
||
|
||
RHFIL: cain ch,"? ; Is it a ?
|
||
jrst read1 ; ? is legal in filenames
|
||
type dspc,/AReading an ITS filename. ITS filenames have
|
||
4 components, specified as follows:
|
||
|
||
dev: dir; fn1 fn2
|
||
|
||
the device name ('dev') is followed by a colon. If omitted, the most recently
|
||
referenced device is used, or DSK: (the main disks) is assumed. The directory
|
||
name is followed by a semicolon. If omitted, the most recently referenced
|
||
directory is used, or your home directory is assumed. The two filenames (fn1
|
||
and fn2) are separated by a space. The character '>' has the special meaning
|
||
of 'greatest numerical name'. This is generally used as a second filename.
|
||
It's behaviour is difficult to predict if no files with the specified first
|
||
name have numerical second filenames. However, if there is only one file with
|
||
a given first filename, say FOO BAR, it will find that file.
|
||
|
||
All filenames are in 'sixbit', i.e. 1-6 characters long, using 0-9, A-Z,
|
||
and the following special characters: '";:-_+=<>,.%^&$#@!*()[]
|
||
Many of those special characters must be quoted by proceeding them with a
|
||
control-Q character, however.
|
||
/
|
||
jrst readh0
|
||
|
||
RHTXT: cain ch,"? ; ? is ok character of text
|
||
jrst read1
|
||
type dspc,/C/
|
||
jrst rhsnd0
|
||
|
||
RHSND: cain ch,"? ; ? is ok character of text
|
||
jrst read1
|
||
RHSNA: type dspc,/CType ":SEND <username> <cr> <message> ^C". Within
|
||
the message, these characters have the following meanings:
|
||
|
||
/
|
||
rhsnd0: type dspc,/A
|
||
rubout deletes backwards
|
||
^C Send message
|
||
^D Quit
|
||
^G Quit!!
|
||
^L Redisplay message
|
||
^R Redisplay line
|
||
^U Kill current line
|
||
^W Kill Word
|
||
[HELP] Prints documentation. This is Top-H on TV's and ^_H on non-TV's
|
||
|
||
All other characters are self-inserting.
|
||
/
|
||
jrst readh0
|
||
|
||
|
||
pchar1: aos count ;both ways
|
||
pchar: idpb ch,bp ;save the character
|
||
aos ct ;count it
|
||
cail ct,msgbfl ; overflow?
|
||
jrst [type dspc,/AInput buffer overflow
|
||
/
|
||
setz ch, ; simulate a quit
|
||
ret]
|
||
echoch ;echo it so he can see what t'fuck he's doin
|
||
jrst popj1 ;successful!
|
||
|
||
uchar1: sos count ;back up local count as well
|
||
uchar: ldb ch,bp ;get the character we're rubbing out
|
||
call 1wipe ;wipe it off the screen
|
||
sos ct ;uncount it.
|
||
decbp bp ;and back it up
|
||
ret
|
||
|
||
credsj: type dspc,/C/
|
||
redsj: setzm lfflag
|
||
jumpe ct,cpopj
|
||
save [x,t]
|
||
move t,linbeg
|
||
move x,ct
|
||
redis0: ildb ch,t
|
||
cain ch,^M ; Is this maybe CRLF?
|
||
jrst redism
|
||
echoch
|
||
redis1: sojg x,redis0
|
||
restore [t,x]
|
||
ret
|
||
|
||
redism: caig x,1 ; Is there another chracter?
|
||
jrst redsm0 ; no, just a bare ^M
|
||
move ch,t
|
||
ildb ch,ch ; Is the next character ^J?
|
||
caie ch,^J
|
||
jrst redsm0 ; No, just do ^M bit
|
||
type tyoc,/
|
||
/ ; Yes, output a newline
|
||
ibp t ; Skip the ^J then
|
||
soja x,redis1
|
||
|
||
redsm0: call echosl ; Echo ^M, with ^ or
|
||
jrst redis1 ; Loop
|
||
|
||
credis: type dspc,/C/
|
||
call credsj
|
||
jrst read0
|
||
|
||
redis: call redsj
|
||
jrst read0
|
||
|
||
r6arg: save [count,ch,a,ct,x]
|
||
skipn ct,argcnt
|
||
jrst r6arg1
|
||
setzb count,x
|
||
setzm arg6
|
||
move a,[440600,,arg6]
|
||
r6arg0: ildb ch,argptr ; Take away one character of the argument
|
||
sos argcnt
|
||
call rd6 ; Add it to our argument
|
||
jrst r6arg1 ; Whitespace!
|
||
sojg ct,r6arg0 ; loop
|
||
|
||
r6arg1: restore [x,ct,a,ch,count]
|
||
ret
|
||
|
||
rcarg: save [a,b,c,x,t,tt,bp,ct,ch]
|
||
move tt,comand
|
||
call ttkget ; in the table
|
||
error /RCARG got an unknown command./
|
||
setzm crgbts ; No bits yet
|
||
rcarg1: skipg c,argcnt ; count of chars
|
||
jrst rcarwn ; If we didn't read anything, done
|
||
move b,argptr ; Ptr to start of it, temporary
|
||
rcare0: ildb ch,b ; Scan for leading whitespace
|
||
caie ch,^I ; whitespace?
|
||
cain ch,40
|
||
caia
|
||
jrst rcare. ; nope, flush it.
|
||
movem b,argptr ; Whitespace, flush it
|
||
sosg c,argcnt
|
||
jrst rcarex ; If that's all, punt
|
||
jrst rcare0 ; look for more whitespace
|
||
|
||
rcare.: move a,cm$opt(t) ; Get the options AOBJN
|
||
setz ct, ; Count how long this option is
|
||
move bp,argptr ; Ptr to start of it
|
||
move b,argptr ; Ptr to start of it
|
||
rcare1: jumpe c,rcarew
|
||
ildb ch,b ; Search for the end of it
|
||
sos c
|
||
caie ch,^I ; (whitespace marks the end)
|
||
cain ch,40
|
||
caia
|
||
aoja ct,rcare1 ; Next character
|
||
|
||
rcarew: movem c,argcnt ; Save our updated pointers
|
||
movem b,argptr
|
||
rcarec: call rcarck ; See if it matches this option
|
||
caia ; No match
|
||
jrst rcare2 ; Match!
|
||
aos a ; Skip the bit
|
||
aobjn a,rcarec ; and loop
|
||
|
||
type dspc,/AUnknown option '/
|
||
rcaree: syscal SIOT,[argi tyoc ? bp ? ct]
|
||
loss
|
||
type tyoc,/'
|
||
/
|
||
jrst rcarex
|
||
|
||
rcare2: setz c, ; C ==> -1 iff ambiguous
|
||
move b,a ; Remember the winning entry
|
||
rcare3: hlrz x,(a) ; Get the option length
|
||
camn x,ct ; Is it an exact match?
|
||
jrst rcare9 ; Yes, win
|
||
aos a ; Check the rest of the entries to see
|
||
rcare4: aobjp a,rcare8 ; if it's unambiguous. If so, win
|
||
call rcarck ; Does this one match too?
|
||
aoja a,rcare4 ; No match, next one
|
||
setom c ; Note that it's ambiguous
|
||
jrst rcare3 ; Check the rest and this for exact match
|
||
|
||
rcare8: jumpe c,rcare9 ; If unambiguous, it's a win
|
||
type dspc,/AAmbiguous option '/
|
||
jrst rcaree ; Go tell which one
|
||
|
||
rcare9: move x,1(b) ; Get the bit
|
||
iorm x,crgbts ; Know that we have it
|
||
skiple argcnt ; Any remaining arguments?
|
||
jrst rcarg1 ; No, gobble down some more
|
||
|
||
rcarwn: restore [ch,ct,bp,tt,t,x,c,b,a] ; The end, exit with success
|
||
jrst popj1
|
||
|
||
rcarex: restore [ch,ct,bp,tt,t,x,c,b,a] ; The end, exit with failure
|
||
ret
|
||
|
||
; In CT -- Number of characters of supplied args
|
||
; In BP -- Byte pointer to supplied args
|
||
; In A -- AOBJN ptr to an [len,,address ? bit] for an option
|
||
|
||
rcarck: save [bp,t,ct,x,c,ch]
|
||
move t,(a) ; Get an option
|
||
hlrz x,t ; Get it's length
|
||
hrli t,440700 ; Create a byte pointer
|
||
rcarc1: sojl ct,rcarcw ; End of supplied, matches!
|
||
sojl x,rcarcx ; We're longer, no match
|
||
ildb ch,t ; A character from the option
|
||
ildb c,bp ; A character from the supplied arg
|
||
cail ch,"a ; Uppercasify
|
||
caile ch,"z
|
||
caia
|
||
subi ch,40
|
||
cail c,"a ; Uppercasify
|
||
caile c,"z
|
||
caia
|
||
subi c,40
|
||
camn c,ch ; Are the characters the same?
|
||
jrst rcarc1
|
||
rcarcx: restore [ch,c,x,ct,t,bp]
|
||
ret
|
||
|
||
rcarcw: restore [ch,c,x,ct,t,bp]
|
||
jrst popj1
|
||
|
||
ukwarn: ife $$pand,[
|
||
type dspc,/AThat command is not known to this program.
|
||
Maybe you should log in? Type :HELP for info.
|
||
/
|
||
] ;; end IFE $$PAND
|
||
.else [
|
||
type dspc,/AThat command is not known.
|
||
Type :HELP for info.
|
||
/
|
||
] ;; end IFN $$PAND
|
||
ret
|
||
|
||
prcmln==0
|
||
define prcmd name,loc
|
||
sixbit /name/ ? loc
|
||
prcmln==prcmln+1
|
||
termin
|
||
|
||
prcmtb: prcmd PRRMAI,uprrmail
|
||
prcmd UPRMAI,uprmail
|
||
ife $$PAND, prcmd ULOGIN,ulogin
|
||
prcmd ULOGOU,ulogout
|
||
prcmd LISTJ,ulistj
|
||
prcmd ULISTF,ulistf
|
||
prcmd UPRINT,uprint
|
||
|
||
kdspch: move tt,comand
|
||
move t,[-prcmln,,prcmtb]
|
||
kdspcl: camn tt,(t) ; Is this a prefix command?
|
||
jrst kdspc0 ; Yes, hack it
|
||
aos t
|
||
aobjn t,kdspcl ; Loop
|
||
|
||
call ttkget ;get a pointer to the command
|
||
pjrst ukwarn ; tell him he lost, and return
|
||
|
||
move tt,cm$flg(t) ;get it's flags
|
||
tlne tt,%COTOP ;is it a topic, rather than a command?
|
||
jrst [terpri
|
||
type tyoc,/That's a topic for HELP, not a command!
|
||
/
|
||
ret] ;and return that we were not successful
|
||
call @cm$rtn(t) ;it's OK, go to it!
|
||
jrst popj1 ;and return our success in running it
|
||
jrst popj1
|
||
|
||
kdspc0: call @1(t) ; Invoke the function
|
||
jrst popj1
|
||
jrst popj1
|
||
|
||
;; TTKGET takes a sixbit command in TT, and returns in T the index into CMDTAB
|
||
;; Skip returns unless the command is unknown (ie bad).
|
||
|
||
ttkget: hrlzi t,-eqvlen ;T <- AOBJN ptr for equivilance tables
|
||
kget0: camn tt,eqvtab(t) ;is there an equivalence?
|
||
jrst [move tt,eqvtab+1(t) ;get the equiuvalent command
|
||
jrst kget2] ; and look it up
|
||
add t,[1,,1] ;skip the equivalence
|
||
aobjn t,kget0 ;try next one
|
||
|
||
kget2: move t,[-cmdcnt,,cmdtab] ;t <- AOBJN ptr for command tables
|
||
kget3: camn tt,cm$nam(t) ;is it this entry?
|
||
jrst bdcmd ; we found it, skip if it is OK!
|
||
addi t,cm$len-1 ;Ignore the next entry.
|
||
aobjn t,kget3 ;Try the next one!
|
||
ret ;Not known, don't skip
|
||
|
||
;; BDCMD takes in TT a sixbit command name, and skip-returns if it is OK.
|
||
|
||
bdcmd: save [t]
|
||
IFE $$PAND,[ ;No commands are bad in PANDA!
|
||
call pwdmap ;Be sure we have the database mapped
|
||
save [a] ;Dont smash A.
|
||
movei a,nocmnd ;Let's check the table of bad commands
|
||
call pwsget ;Get the bad-commands table into TMPBUF.
|
||
move t,a ;T gets the count of bad commands.
|
||
restore [a] ;Done with A.
|
||
bdcmd1: camn tt,tmpbuf(t) ;If this is a bad command
|
||
jrst popjt ; Just return.
|
||
sojge t,bdcmd1 ;Loop for all bad commands.
|
||
];End of PWORD-only code.
|
||
popj1t: aos -1(p) ;Skip return.
|
||
popjt: restore [t]
|
||
ret
|
||
|
||
|
||
|
||
;;; WIPECH takes one character in CH and wipes it off the screen.
|
||
|
||
wipech: save [d]
|
||
movei d,1 ; Assume 1 character position
|
||
caie ch,177 ; is it a rubout
|
||
caige ch,40 ; or a control?
|
||
aos d ; then it takes two
|
||
|
||
cain ch,33 ; is it an altmode?
|
||
sos d ; then it's an exception
|
||
|
||
call wipe ; so let wipe do it's stuff
|
||
wipecx: restore [d]
|
||
ret
|
||
|
||
;;; wipe away one character
|
||
1wipe: push sp,d
|
||
movei d,1 ;one position
|
||
pjrst wipe0 ;wipe it away!
|
||
|
||
;;; WIPE takes an argument in D, which is the number of character positions to
|
||
;;; delete from the screen.
|
||
|
||
wipe: push sp,d
|
||
wipe0: save [t,tt,b]
|
||
syscal rcpos,[argi tyoc ;get the cursor position
|
||
val a]
|
||
loss
|
||
hrrz t,a
|
||
movem t,hpos
|
||
hlrz tt,a
|
||
movem tt,vpos
|
||
wipe1: move b,ttyopt
|
||
tlne b,%toovr ;can't over-strike? Can erase that way!
|
||
tlne b,%TOERS ;skip if can't erase
|
||
jrst [move t,hpos ; get the current horizontal position
|
||
subi t,(d) ; get our desired horizontal position
|
||
skipge t ; paranoid.
|
||
setz t, ; substitute 0 for negatives
|
||
movei t,10(t) ; allow for ^P code strangeness
|
||
tyo dspc,[^P] ; move to the calculated position
|
||
tyo dspc,["H]
|
||
tyo dspc,t
|
||
tyo dspc,[^P] ; and clear the rest of the line
|
||
tyo dspc,["L]
|
||
jrst enmass]
|
||
tlnn b,%tomvb ;if this TTY can't backspace directly
|
||
jrst [push sp,bp
|
||
ldb b,bp ; we can't erase, so, we
|
||
decbp bp ; decrement our temporary bp
|
||
tyo tyoc,b ; echo deleted char (crude, but effective)
|
||
pop sp,bp
|
||
jrst gobk] ;and return
|
||
caig d, ;if it's non-positive
|
||
jrst enmass ; don't hack any more!
|
||
move b,d ;copy the counter
|
||
tyo tyoc,[^H] ;backspace
|
||
sojg b,.-1 ;Do it that many times
|
||
move b,d ;copy the counter
|
||
tyo tyoc,["/] ;wipe it out
|
||
sojg b,.-1 ;do it that many times
|
||
move b,d ;copy the counter
|
||
tyo tyoc,[^H] ;and back over it
|
||
sojg b,.-1 ;do it that many times
|
||
setom lfflag ;and note to LF when we get real char.
|
||
caia ;done with this loop
|
||
gobk: sojg d,wipe1 ;loop for each character.
|
||
enmass: setzm jlflag ;we didn't just LF
|
||
restore [b,tt,t]
|
||
pop sp,d
|
||
ret ;return to caller
|
||
|
||
|
||
|
||
;; This copies our JCL to the JCL buffer, so that it is word-aligned etc.
|
||
|
||
jclcop: move t,[440700,,jclbuf]
|
||
move bp,argptr ;get BP to start
|
||
move ct,argcnt ;Get # of characters of JCL
|
||
movem ct,jclct ; Remember how much JCL we got
|
||
jclco1: ildb ch,bp ;get character
|
||
idpb ch,t ;put the character
|
||
sojg ct,jclco1 ;try again, maybe
|
||
movei ch,^M ; End with CRLF
|
||
idpb ch,t
|
||
movei ch,^J
|
||
idpb ch,^M
|
||
setz ch, ;padd with nulls
|
||
movei ct,10 ;bunches of spaces
|
||
jclco2: idpb ch,t ;putting it in !
|
||
sojg ct,jclco2 ;and do another
|
||
ret
|
||
|
||
;;;; Here goes the error recovery system.
|
||
|
||
loserr: movem x,ac.x
|
||
move x,[440700,,[asciz /Miscellaneous error/]]
|
||
movem x,errmsg
|
||
jrst errput ;and do the rest of the error stuff
|
||
|
||
errmng: movem x,erracs ;save X for analysys
|
||
hrrz x,suuo ;grab the error message
|
||
hrli x,440700 ;make a byte pointer to it for .MAIL
|
||
movem x,errmsg ;save the error message!
|
||
errput: move tt,ac.tt ;recover the already saved AC
|
||
move x,[1,,erracs+1] ;and use it to BLT the rest of the AC's to
|
||
blt x,erracs+17 ; saftey
|
||
errmn1: move x,calerr ;collect the system error code
|
||
movem x,baderr ;and save it for posterity
|
||
move t,suuoh ;get address of error
|
||
movem t,erradr ;save address of error
|
||
|
||
move x,errdat ;collect various data
|
||
.suset x
|
||
syscal status,[ebchn ;get the I/O status for bad channel
|
||
val ebsts]
|
||
jfcl ; Fie!
|
||
|
||
syscal open,[cnti .uio ;image output dump file
|
||
argi dsko
|
||
[sixbit /DSK/]
|
||
ife $$PAND, [sixbit /PWORD/]
|
||
.else [sixbit /PANDA/]
|
||
[sixbit />/]
|
||
dbgdir] ;in case we don't want it to go there
|
||
quit
|
||
move t,[444400,,0] ;pointer to impure
|
||
movei tt,<<<impend+1777>/2000>*2000> ;write full pages!
|
||
syscal siot,[argi dsko ? t ? tt] ;write it out!
|
||
jfcl ; eh?
|
||
.close dsko, ;close it off
|
||
|
||
type dspc,/AInternal Error: /
|
||
output tyoc,@errmsg
|
||
type dspc,/APlease do :BUG PWORD <description of the problem> ^C
|
||
/
|
||
|
||
skipn debug
|
||
.mail bugmal ;mail the info
|
||
|
||
pdlfix: syscal delewo,[argi dsko] ;flush the output file
|
||
jfcl ; ignore any errors, probably closed
|
||
quit=jrst pdlfix
|
||
.close dsko,
|
||
move sp,[-pdllen,,pdl] ;flush the stack out
|
||
syscal unlock,[argi %jself] ;unlock our locks!
|
||
.lose %lssys
|
||
setzm infp ;note we aren't in inferior anymore
|
||
.status usrc,t ;is there an inferior?
|
||
skipe t ;is it there?
|
||
.uclose usrc, ; kill it
|
||
setzm lfflag ;clear rubout-controling flags
|
||
setzm jlflag
|
||
setzm ttyflg
|
||
setzm siotct ;we aren't in the middle of output
|
||
setzm newflg ;clear out flag for PWDCHG
|
||
setom ttyprp ;default PRINTF to TTY output
|
||
setzm morflg ;turn of --MORE-- flag
|
||
setzm mdlflg ;we aren't hacking MUDDLE !!
|
||
setzm tyiflg ;normal mode of TYI
|
||
setzm dsprmp ;Don't do anything special for prompting
|
||
ifn $$PAND, setzm nodate
|
||
.iopdl ;reset the I/O PDL
|
||
move t,errclr ;clear various things
|
||
.suset t
|
||
skipn deathp
|
||
jrst rdloop ;and back to hacking!
|
||
.logout 1,
|
||
|
||
.upure
|
||
|
||
ifn $$PAND,[
|
||
rdxarg: 0 ; Arg for cleanup handler
|
||
rdxbp: 0 ; BP to use for cleanup handler
|
||
rdxct: 0 ; Item to be XCT'd to clean up
|
||
]; end of IFN $$PAND,
|
||
|
||
errmsg: 0 ;saved error message
|
||
errbuf: block 40
|
||
.pure
|
||
;;; Error Clear table
|
||
errclr: -errcln,,errctb ;AOBJN ptr to stuf to reset on error
|
||
errctb: .spirqc,,[0] ;no interrupts
|
||
.sifpir,,[0]
|
||
.sdf1,,[0] ;un-defer things
|
||
.sdf2,,[0]
|
||
.smsk2,,[<1_tyic>\<1_tyoc>\<1_dspc>\<1_tlnc>] ;turn interrupts back on
|
||
errcln==.-errctb ;ERRCLN is lenght of ERRCTB
|
||
|
||
errdat: -sstlng,,ssttab ;AOBJN ptr to lots of info
|
||
ssttab: .rbchn,,ebchn ;collect the bad channel
|
||
.rmpva,,empva ;when we get around to catching MPV's
|
||
.ruind,,euind ;get user index, for identification if we
|
||
;get it before it is killed!
|
||
.runame,,euname ;get worthless data, usually
|
||
.rjname,,ejname
|
||
.rtty,,etty
|
||
.rpirqc,,epirqc ;interrupts?
|
||
.rifpir,,eifpir ;How do you expect me to get any work done
|
||
;with all these interruptions?
|
||
.rcnsl,,ecnsl ;what TTY ....
|
||
.rsv40,,esv40
|
||
.samsk2,,[<1_tyic>\<1_tyoc>\<1_dspc>\<1_tlnc>] ;turn off random ints.
|
||
sstlng==.-ssttab
|
||
|
||
|
||
dskerr: movem x,erracs ;save X for analysys
|
||
move x,[1,,erracs+1] ;and use it to BLT the rest of the AC's to
|
||
blt x,erracs+17 ;safty
|
||
move x,calerr ;gotta salvage the error now! PRINTF will
|
||
movem x,baderr ;clober it if we don't
|
||
syscal open,[cnti .uai ;open the ERR device
|
||
argi dski
|
||
[sixbit /ERR/]
|
||
argi 4 ;2nd file name is the error code
|
||
baderr]
|
||
.lose %lsfil
|
||
call printf ;print the error message
|
||
|
||
move a,baderr ;get the error #
|
||
movem a,calerr ;move it back to CALERR so main error
|
||
;handler can find it
|
||
movei tt,1 ;set up to shift one bit into position
|
||
setz t, ;T get's shifted into
|
||
lshc tt,(a) ;shift it
|
||
tdnn t,dskbd0 ;Is this safely ignorable?
|
||
tdne tt,dskbd1
|
||
quit ; ignore it, back to work.
|
||
errdmp 4,[asciz /Couldn't open file./] ;AC's have been saved
|
||
|
||
;;; OPEN errors to simply quit on, #'s 0-43
|
||
; %EFLDR -- Directory full
|
||
; %EFLDV -- Device full
|
||
|
||
dskbd0: irp x,,[%EFLDR,%EFLDV]
|
||
<1_x>\termin
|
||
|
||
;;; OPEN errors to simply quit on, #'s 44-107
|
||
|
||
dskbd1: irp x,,[0]
|
||
<1_<x-44>>\termin
|
||
0
|
||
|
||
|
||
|
||
;;; failure in an open, not bug.
|
||
|
||
opfail: push sp,calerr ;save the error code
|
||
;we have the block containing the error
|
||
;file
|
||
terpri
|
||
move d,[440700,,DSKBUF] ;use DSKBUF, since we don't need it yet
|
||
hrr b,suuo ;get the fileblock
|
||
call rfn"pfn ;Make it printable
|
||
output tyoc,dskbuf
|
||
type dspc,/ -- /
|
||
|
||
syscal open,[cnti .uai ;open the ERR device
|
||
argi dski
|
||
[sixbit /ERR/]
|
||
argi 4 ;FN2 is error return from .CALL
|
||
(sp)] ;(standard call error)
|
||
loss
|
||
|
||
call printf ;print the error message
|
||
quit ;and quit
|
||
|
||
|
||
SUBTTL System Utility Routines
|
||
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;;; ;;;
|
||
;;; Here go the system utility routines ;;;
|
||
;;; ;;;
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
||
;; find the entry, and get the group
|
||
|
||
grplsr: movei a,lsrc ;tell LSRTNS what channel it can hack
|
||
move b,uname ;ask about this UNAME
|
||
call lsrtns"lsrunm ;is it there?
|
||
ret ; nope, fail
|
||
movem b,lsrptr ;save pointer to this entry
|
||
movei a,lsrtns"i$grp ;find his group
|
||
call lsrtns"lsritm
|
||
jrst [movei ch,40 ; nothing there, a space will do
|
||
jrst popj1] ; and consider it successful
|
||
|
||
ildb ch,a ;check it out
|
||
cain ch,0 ;is it null?
|
||
jrst [movei ch,40 ; yes, use space instead
|
||
jrst popj1] ; and consider that a success
|
||
|
||
upper ch ;uppercasify
|
||
jrst popj1
|
||
|
||
;;; map in the INQUIR database
|
||
maplsr: save [a,b]
|
||
movei a,lsrc ;A <- channel for LSRTNS
|
||
move b,[-lsrpgc,,lsrpag] ;AOBJN ptr to pages for LSRTNS
|
||
call lsrtns"lsrmap ;map in the INQUIR database
|
||
error /Failure to map in INQUIRE database!/
|
||
restore [b,a]
|
||
ret
|
||
|
||
unmapl: move b,[-lsrpgc,,lsrpag] ; AOBJN ptr to pages LSRTNS uses
|
||
syscal CORBLK,[ argi 0 ; DELETE!
|
||
argi %jself ; our own pages
|
||
b] ; all that LSRTNS used
|
||
loss ; huh? Won't let me give away pages??????
|
||
.close lsrc, ; don't need it any more
|
||
ret
|
||
|
||
;;; A routine to read a person's human name from INQUIR and ask if it's him
|
||
;;; clobbers A, B, and others. Takes a Byte Pointer to a working area in BP
|
||
|
||
asknam: movei a,lsrtns"i$name ;find his name
|
||
call lsrtns"lsritm
|
||
jrst [type dspc,/AThere is a problem with that name's INQUIR entry.
|
||
/
|
||
ret]
|
||
move b,bp ;Byte Pointer to our storage area
|
||
call lsrtns"lsrnam ;get his name in human-readable form
|
||
jfcl ; eh?
|
||
|
||
asknm2: setom gotinq
|
||
type dspc,/AAre you / ;ask him
|
||
outstr tyoc,bp
|
||
decbp b ;it advances it a character
|
||
move bp,b ;and get pointer to the end
|
||
type tyoc,/? (Y or N) / ;ask
|
||
.reset tyic, ;throw away type ahead.
|
||
tyi
|
||
ret ; he quit, take it as NO
|
||
jrst asknm2 ; ask him again
|
||
jfcl
|
||
caie ch,"Y ;is it Y
|
||
cain ch,"y ; or y ?
|
||
caia ; yes, don't
|
||
jrst [type tyoc,/No.
|
||
That login name is already in use! Please choose another name and try again!
|
||
/
|
||
ret] ; just give up
|
||
type tyoc,/Yes./
|
||
movei ch,^M ;CRLF
|
||
idpb ch,b
|
||
movei ch,^J
|
||
idpb ch,b
|
||
move bp,b ;get our final byte pointer
|
||
jrst popj1 ;yep, that's the one!
|
||
|
||
;;; table of devices to use .IOT on
|
||
iottab: irp dev,,[NUL,MT0]
|
||
sixbit /dev/
|
||
termin
|
||
iotlen==.-iottab
|
||
|
||
prtopn: save [TT,T]
|
||
move t,1(b)
|
||
|
||
move tt,2(b)
|
||
camn t,[sixbit /..NEW./]
|
||
came tt,[sixbit /(udir)/]
|
||
caia ; Not trying to create directory
|
||
jrst [type dspc,/AIllegal file name
|
||
/
|
||
ret]
|
||
|
||
movsi tt,-iotlen ;AOBJN ptr to table of bad devices
|
||
movei x,.bai ;assume we must use .BAI
|
||
move t,(b) ;get the DEV of the file
|
||
prtdv1: camn t,iottab(tt) ;is it one of those damned losers?
|
||
jrst prtdv2 ; continue
|
||
aobjn tt,prtdv1 ;try next one
|
||
movei x,.uai ;WIN, we can SIOT
|
||
prtdv2: restore [T,TT]
|
||
syscal open,[argi dski ? cnt x ;open in whichever mode
|
||
(b)
|
||
1(b)
|
||
2(b)
|
||
3(b)]
|
||
ret
|
||
jrst popj1
|
||
|
||
;;; routine to open .uao output file on DSKO. It takes the directory in B
|
||
;;; it returns the file-block pointer in B
|
||
|
||
opnout: movem b,fo.snm ;fill in the blanks for directory
|
||
movei b,outnam ;point to file block
|
||
syscal open,[cnti .uao ;open it
|
||
argi dsko
|
||
(b)
|
||
1(b)
|
||
2(b)
|
||
3(b)]
|
||
filoss (b) ; lost!
|
||
ret
|
||
|
||
;;; fill in the FN2 and open a file. Skips if successful.
|
||
;;; takes fileblock pointer in B. Takes FN2 as argument in T
|
||
|
||
fn2opn: movem t,2(b)
|
||
.call uaiopn
|
||
ret
|
||
jrst popj1
|
||
|
||
;;; similar, but for filling in the FN1
|
||
fn1opn: movem t,1(b)
|
||
.call uaiopn
|
||
ret
|
||
jrst popj1
|
||
|
||
;;; rename file open on DSKO according to filename block pointed to by B
|
||
;;; then close the file
|
||
rnmfn2: movem t,2(b)
|
||
rnmcls: syscal renmwo,[argi dsko
|
||
1(b)
|
||
2(b)]
|
||
filoss (b)
|
||
.close dsko,
|
||
ret
|
||
|
||
|
||
;;; Routine to print, given an input file is already open in either .UII or
|
||
;;; .UAI on the DSKI channel (now .BAI too) COPYF entry is for copying to DSKO
|
||
;;; instead.
|
||
|
||
|
||
copyf: setzm ttyprp ;note output not to TTY
|
||
printf: syscal rfname,[argi dski ? val x ? val x ? val x ? val x ;ignore names
|
||
val prmode] ;but get that mode
|
||
error /RFNAME failed in PRINTF/
|
||
move t,prmode
|
||
move tt,[440700,,dskbuf] ;byte pointer to handle .UAI files
|
||
movei x,buflen*5 ;bytes buffer will hold for .UAI files
|
||
movei a,1 ;conversion factor for .UAI to .UAO
|
||
cain t,.bai ;is it .BAI?
|
||
jrst prtbai ; yes, use what we have
|
||
cain t,.uii ;is it .UII?
|
||
do [move tt,[444400,,dskbuf] ;word at a time instead!
|
||
movei x,buflen ; buffer capacity in words instead
|
||
movei a,5 ; to convert .UII to .UAO
|
||
][
|
||
caie t,.uai ; else, is it .UAI ?
|
||
error /PRINTF called with illegal mode/
|
||
]
|
||
prtbai: hrr tt,iobuf
|
||
movem tt,dskbp ;this is our byte pointer
|
||
movem x,pbufl ;this is the length of our buffer
|
||
movem a,pbtsiz ;this is the # of chars per input byte
|
||
|
||
morcop: skipe ttyflg ;if we have turnned of the TTY,
|
||
jrst [ .close dski, ; then we don't need the channel
|
||
ret] ; cause we're all done printing
|
||
move t,dskbp ;get our byte pointer
|
||
move tt,pbufl ;and our buffer size
|
||
call dvsiot ;reaad from any device
|
||
jrst [syscal close,[argi dski]
|
||
jfcl
|
||
setom ttyprp
|
||
ret]
|
||
movem t,foobp ;foo byte pointer
|
||
move t,pbufl ;lets figure out how many were moved
|
||
sub t,tt ;look MA, no random +1 or -1 's! (ITS WINS)
|
||
imul t,pbtsiz ;and be sure we have it in characters,~words
|
||
movem t,siotct ;move these out to storage so we can win on
|
||
movem t,remain ;save for later testing
|
||
caige t,buflen*5 ;if not the whole thing
|
||
call c.cadj ; adjust for TECO cretinism
|
||
|
||
move t,[440700,,dskbuf] ;get another copy of our byte pointer
|
||
hrr t,iobuf
|
||
skipe ttyprp ;are we writing to the TTY?
|
||
do [syscal siot,[argi tyoc ;type it
|
||
t
|
||
siotct]
|
||
loss ; Eh?
|
||
][ ;ELSE
|
||
move x,remain ;get the count from remain, since SIOTCT is
|
||
syscal siot,[argi dsko ;subject to reseting at ^S int level
|
||
t ? x]
|
||
loss]
|
||
|
||
move t,remain
|
||
cain t,buflen*5 ;zero? Are we really done?
|
||
jrst morcop ; nope, copy some more
|
||
.close dski, ;make sure it get's closed
|
||
skip ;ignore
|
||
setom ttyprp ;note that we're writing to TTY: usually
|
||
ret
|
||
|
||
;;; read from any device on DSKI, with BP in T and count in TT
|
||
dvsiot: move x,prmode ;look at our mode.
|
||
caie x,.bai ;can we SIOT?
|
||
jrst [syscal siot,[argi dski ;yes, thank the lord
|
||
t
|
||
tt]
|
||
ret ;lost, don't skip return
|
||
jrst popj1] ;won, skip return
|
||
dvsio3: movsi x,-buflen
|
||
hrr x,iobuf ;cons up an AOBJN PTR to use
|
||
.iot dski,x ;read it in
|
||
hrr t,x ;fix up the byte pointer
|
||
hlre tt,x ;and figure up how many characters that was
|
||
imul tt,[-5] ;words -> ascii
|
||
jrst popj1
|
||
|
||
;;; Routine for goddamn fucking TECO that doesn't set FILLEN for end of file
|
||
;;; like it ought to. This means it writes out cretinouse ^C's at the end
|
||
;;; to pad the word! Also, the ERR device ends off with a ^L, so we flush
|
||
;;; those too!
|
||
|
||
c.cadj: move t,foobp ;get the possibly cretinouse byte pointer
|
||
tlne t,004000 ;is it a full-word pointer?
|
||
hrli t,010700 ; yes, make it a ascii pointer
|
||
movei tt,5 ;at most 5 of the losers
|
||
setz x, ;count the beggars
|
||
norm7 t ;back up to last one
|
||
c.caj0: ldb ch,t ;get the possibly offensive character
|
||
caie ch,^L ;is it a trailing ^L ?
|
||
cain ch,^C ;is it offensive?
|
||
caia
|
||
jrst [exch x,siotct ; nope, but maybe predecessors were
|
||
subm x,siotct
|
||
ret] ; record and return
|
||
decbp t ;back up!
|
||
aos x ;boy is it offensive
|
||
sojg tt,c.caj0 ;find another?
|
||
exch x,siotct
|
||
subm x,siotct
|
||
ret ;nope that's all
|
||
|
||
.upure
|
||
gotinq: 0 ; Set -1 if person applying for account has
|
||
; an INQUIR entry already.
|
||
foobp: 0 ;byte pointer to the end of the buffer
|
||
remain: 0 ;# of bytes unused in buffer
|
||
fleng: 0 ;length of the file
|
||
ttyflg: 0 ;set to -1 whenever we wish to flush typeout
|
||
siotct: 0 ;count of chars left to be typed out in this
|
||
;SIOT
|
||
|
||
allflg: 0 ;ALL option has been specified. Used only
|
||
;in among consenting adults.
|
||
nodate: 0 ; -1 means suppress create/modify date
|
||
brfflg: 0 ;similarly, BRFFLG is for -brief option
|
||
|
||
reread: -1 ;if non-negative, is character to re-read
|
||
|
||
dskbp: 0 ;the byte pointer to use for input
|
||
prmode: 0 ;contain's the mode this channel is open in.
|
||
ttyprp: -1 ;-1 means output is to TYOC, not DSKO
|
||
pbtsiz: 0 ;the # of chars per byte. This is used to
|
||
;convert input bytes to output chars
|
||
pbufl: 0 ;size of the buffer in current bytes
|
||
|
||
iobuf: dskbuf ;buffer to use for PRINTF
|
||
|
||
dskbuf: block buflen
|
||
block buflen ;buffer for use by :SEND's
|
||
|
||
.pure
|
||
|
||
ife $$pand,[
|
||
goddt4: movem b,linkno ; remember we were lunk to
|
||
call logit ; unusual login, log it
|
||
goddt5: move x,[jfcl] ;make it not add anything to the start adr
|
||
movem x,lodoff
|
||
jrst goddt1 ;don't type anything!
|
||
|
||
goddt: type dspc,/A[OK]
|
||
/ ;[OK]
|
||
|
||
goddt0: syscal ttyget,[argi tyic ? val t ? val tt ? val a]
|
||
loss
|
||
tlz a,%TSSII ;clear out the super-image bit!
|
||
syscal ttyset,[argi tyic ? t ? tt ? a]
|
||
loss
|
||
goddt1: .suset [.smask,,[0]] ;turn off all interrupts, let DDT do it when
|
||
.suset [.smsk2,,[0]] ;it is ready!
|
||
move a,[400000,,[0]] ;turn off realtime interrupts
|
||
.realt a,
|
||
jfcl
|
||
syscal open,[cnti .uii ;open the file to load in DDT from
|
||
argi lodc
|
||
[sixbit /SYS/]
|
||
[sixbit /ATSIGN/]
|
||
[sixbit /DDT/]]
|
||
error /Can't access SYS:ATSIGN DDT, can't log you in, sorry!/
|
||
;We've got it open, time to load up our AC's
|
||
|
||
; close up our channels so DDT doesn't get confused (only the TTY channels
|
||
; should be open at this point, but just in case, close them all)
|
||
|
||
irp x,,[dspc,tyic,tyoc,lsrc,pwdc,dski,dsko,usrc]
|
||
.close x,
|
||
termin
|
||
|
||
setz t, ;clear T for offset start address
|
||
skipe lbrief ;did he specify -bf ?
|
||
movei t,1 ; yes, start at even offset instead
|
||
skipe altusw ;did he $U instead of :LOGIN ?
|
||
addi t,2 ;yes, account for that
|
||
addm t,lodoff ;so start up at our offset
|
||
hrlzi 17,lodblk ;for BLT from LODBLK to AC 0
|
||
blt 17,17 ;move code to AC's
|
||
jrst 1 ;and execute it.
|
||
|
||
.upure ;can't be pure, since we modify LODOFF
|
||
lodblk: jfcl
|
||
.suset <lsuset-lodblk> ;flush our memory
|
||
.CALL <lcalbk-lodblk> ;the SETZ of the call lives in AC 6
|
||
.logout ;probably no core. Can't do anything.
|
||
.iot 1,1 ;read start address
|
||
lodoff: addi 1,1 ;start at our special address instead
|
||
jrst (1) ;and away we go!
|
||
lcalbk: setz
|
||
sixbit /LOAD/ ;load
|
||
argi %jself ;into self
|
||
401000,,1 ;from channel 1
|
||
lsuset: .smemt,,<lmemt-lodblk>
|
||
lmemt: 4000
|
||
0
|
||
0
|
||
0
|
||
|
||
.pure
|
||
] ; END IFE $$PAND
|
||
|
||
ifn $$PAND,[
|
||
|
||
grpmal: 440700,,[asciz /ACCOUNTS-HELD-REFUSED/]
|
||
tp$6bt runame
|
||
0
|
||
440700,,[asciz /New GROUP settings/]
|
||
-1,,[440700,,usrbfr]
|
||
|
||
rmsmal: 440700,,[asciz /ACCOUNTS-HELD-REFUSED/]
|
||
tp$6bt runame
|
||
0
|
||
0
|
||
-7,,airtyp
|
||
|
||
notmal: 440700,,[asciz /ACCOUNTS-NOTIFICATION/]
|
||
tp$6bt runame
|
||
0
|
||
0
|
||
-7,,airtyp
|
||
.upure
|
||
airtyp: 0 ; Type (SET/DELETE)
|
||
440700,,[asciz /Was: /]
|
||
440700,,usrbfr ; State before
|
||
440700,,[asciz /
|
||
Is: /]
|
||
440700,,usraft ; State after
|
||
440700,,[asciz /
|
||
/]
|
||
440700,,usrrsn ; Reason, if any
|
||
.pure
|
||
maldel: move t,[440700,,[asciz /[DELETED]/]]
|
||
move bp,[440700,,usraft]
|
||
copy t,bp
|
||
skipa t,[440700,,[asciz /I deleted the following account:
|
||
/]]
|
||
malset: move t,[440700,,[asciz /I set the following account:
|
||
/]]
|
||
movem t,airtyp
|
||
|
||
ldb x,[pi$sta pdinfo] ; Is this something RMS want to see?
|
||
caie x,ps%hld
|
||
cain x,ps%rfs
|
||
jrst rmshak
|
||
cain x,ps%off
|
||
jrst rmshak
|
||
|
||
.mail notmal ;send mail on it
|
||
ret
|
||
|
||
; filter out deletions and refuse-holds for RMS
|
||
rmshak: .mail rmsmal
|
||
ret
|
||
|
||
] ; END IFN $$PAND,
|
||
|
||
ml.to==0 ;Byte pointer to TO: field
|
||
ml.frm==1 ;Byte pointer to FROM: field
|
||
;or address of 6bit word
|
||
ml.snt==2 ;Byte pointer to SENT-BY field
|
||
;or address of 6bit word
|
||
ml.sbj==3 ;Byte pointer to SUBJECT: field
|
||
ml.txt==4 ;AOBJN pointer to Byte pointer's to
|
||
;strings to be placed in the TEXT field
|
||
;;;; MAIL forms
|
||
|
||
sndmal: 440700,,tmpbuf
|
||
tp$6bt runame
|
||
tp$6bt runame
|
||
0
|
||
-1,,[ tp$ind argptr ]
|
||
|
||
lflmal: tp$6bt PXUNAM ;XUNAME, not UNAME
|
||
440700,,[asciz /PASSWORD-SYSTEM/]
|
||
0
|
||
440700,,[asciz /Failed login/]
|
||
-3,,[440700,,[asciz /Your password was given incorrectly from /]
|
||
440700,,hstnam ;site name or LOCAL or DIALUP
|
||
440700,,[asciz /
|
||
/]] ;TERPRI
|
||
|
||
bugmal:
|
||
ife $$PAND,[
|
||
tp$ind bugnam
|
||
440700,,[asciz /BUGGY-PWORD/]
|
||
0 ;no SENT-BY field
|
||
440700,,[asciz /PWORD crash file/]
|
||
]; END IFE $$PAND
|
||
ifn $$PAND,[
|
||
tp$ind bugnam
|
||
440700,,[asciz /BUGGY-PWORD/]
|
||
0 ;no SENT-BY field
|
||
440700,,[asciz /PANDA crash file/]
|
||
]; END IFN $$PAND
|
||
-4,,[ 440700,,[asciz /There is a crash file to examine.
|
||
Error message:
|
||
/]
|
||
tp$ind errmsg ;type the error message
|
||
440700,,[asciz /
|
||
Error code: /]
|
||
tp$oct calerr]
|
||
ife $$PAND,[
|
||
|
||
aplmal: 440700,,[asciz /USER-ACCOUNTS-ARCHIVE/]
|
||
440700,,[asciz /PASSWORD-SYSTEM/]
|
||
0
|
||
0
|
||
-6,,[ 440700,,[asciz /Uname: /]
|
||
tp$6bt uname
|
||
440700,,[asciz /
|
||
/]
|
||
440700,,msgbuf
|
||
440700,,[asciz /
|
||
/]
|
||
tp$ind uinfo]
|
||
|
||
telmal: 440700,,[asciz /ACCOUNTS-NOTIFICATION/]
|
||
tp$6bt uname
|
||
tp$ind namloc ;who it's from is put here
|
||
-2,,[440700,,[asciz /Application from TTY /] ? tp$oct consol]
|
||
-3,,[ 440700,,msgbuf ? 440700,,[asciz /
|
||
/]
|
||
tp$ind uinfo]
|
||
] ; END IFE $$PAND,
|
||
|
||
mailit: push sp,uuoh ;save where we came from!
|
||
push sp,b ;need this AC
|
||
move b,fm.snm ;open an output file on the mail directory
|
||
call opnout
|
||
move t,uuo ;get the address to find these frobs in!
|
||
; skipe dm.flg ;is this on DM?
|
||
; ; DM runs a winning mailer now.
|
||
; jrst comsys ; write for losing mailer
|
||
|
||
;;; how to mail on winning system
|
||
|
||
comsat: type dsko,/FROM-JOB:/
|
||
ifn $$PAND,[type dsko,/PANDA
|
||
TO:(/]
|
||
.else [type dsko,/PWORD
|
||
TO:(/]
|
||
typout dsko,ml.to(t)
|
||
|
||
ife $$pand,[
|
||
hrrzs t ; flush the op-code part
|
||
cain t,telmal ; Is this notification mail?
|
||
jrst [
|
||
type dsko,/ /
|
||
6type dsko,machin ; tell where to send it
|
||
type dsko,/ (R-HEADER-FORCE NULL)/ ; force into RFC733 format
|
||
jrst .+1]
|
||
]; END IFE $$PAND,
|
||
|
||
type dsko,/)
|
||
SENT-BY:/
|
||
typout dsko,ml.frm(t)
|
||
skipn ml.snt(t) ;sent-by field?
|
||
jrst comst1 ; null, don't write it, COMSAT loses
|
||
type dsko,/
|
||
CLAIMED-FROM:/
|
||
skipn ml.snt(t) ;nothing there?
|
||
typout dsko,ml.frm(t) ; substitute the FROM field
|
||
skipe ml.snt(t)
|
||
typout dsko,ml.snt(t) ; something there, use it!
|
||
|
||
comst1: skipn ml.sbj(t) ;subject field?
|
||
jrst comst2 ; null, don't write it
|
||
type dsko,/
|
||
SUBJECT:/
|
||
|
||
comst2: typout dsko,ml.sbj(t)
|
||
type dsko,/
|
||
TEXT;-1
|
||
/
|
||
|
||
ife $$pand, cain t,telmal ; Is this TELMAL?
|
||
ife $$pand, call fakhed ; yes, fake a header
|
||
|
||
typout dsko,ml.txt(t) ;type out all the text frobs
|
||
movei b,mlmnam ;rename to the mail filenames
|
||
call rnmcls
|
||
pop sp,b ;restore AC
|
||
pop sp,uuoh
|
||
jrst uuoret ;and return!
|
||
|
||
fakhed: type dsko,/Date: /
|
||
call datime"timget ; get the time
|
||
push sp,d
|
||
move d,[440700,,dskbuf] ; get a place to copy the time
|
||
call datime"timexp ; get the time as "7 AUG 1976 0831-EST"
|
||
output dsko,dskbuf ; send it out
|
||
outstr dsko,d ; send out the -EST too! (DATIME bug?)
|
||
pop sp,d
|
||
type dsko,/
|
||
From: / ; now for the FROM: field
|
||
move tt,ml.snt(t)
|
||
call malqck ; check for need of " quoting
|
||
jrst [ tyo dsko,[""] ; quote the insides
|
||
setom mdlflg
|
||
typout dsko,ml.snt(t) ; should muddle-quote with right char
|
||
setzm mdlflg
|
||
tyo dsko,[""]
|
||
jrst .+2]
|
||
typout dsko,ml.snt(t) ; no quoting needed, just send it
|
||
type dsko,/ </ ; end of name
|
||
setom mdlflg
|
||
typout dsko,[tp$6bt uname] ; tell the UNAME involved
|
||
setzm mdlflg
|
||
type dsko,/ at /
|
||
6type dsko,machin ; tell where
|
||
type dsko,/>
|
||
To: USER-ACCOUNTS at /
|
||
6type dsko,machin ; tell where
|
||
type dsko,/
|
||
/
|
||
ret
|
||
|
||
malqck: push sp,ch
|
||
malqk0: hlrz ch,tt ; get the LH
|
||
andi ch,777740 ; eliminate the indirection and indexing
|
||
cain ch,tp$ind ; is it an indirect frob?
|
||
jrst [ move tt,@tt ; get what it points to
|
||
jrst malqk0] ; and start from scratch
|
||
cail ch,450000 ; is it a byte pointer?
|
||
jrst [ pop sp,ch ? ret] ; no, assume it's OK (punt!)
|
||
malqk1: ildb ch,tt
|
||
caie ch,",
|
||
cain ch,""
|
||
jrst [ pop sp,ch ? ret]
|
||
caie ch,"<
|
||
cain ch,">
|
||
jrst [ pop sp,ch ? ret]
|
||
cain ch,"\
|
||
jrst [ pop sp,ch ? ret]
|
||
caie ch,^C ; end of the string?
|
||
cain ch,0
|
||
jrst [ pop sp,ch ? jrst popj1] ; we made it, no quotes needed
|
||
jrst malqk1
|
||
|
||
comsys: setzm mdlflg ;hack muddle strings
|
||
type dsko,/"TO" ("/
|
||
setom mdlflg ;hack muddle strings
|
||
typout dsko,ml.to(t)
|
||
setzm mdlflg ;don't hack muddle strings
|
||
type dsko,/")
|
||
/
|
||
skipn ml.snt(t) ;is there a claimed-from?
|
||
jrst comsnd ; no, just hack the sender field
|
||
type dsko,/"SENDER" "/
|
||
setom mdlflg ;hack muddle strings
|
||
typout dsko,ml.snt(t)
|
||
setzm mdlflg ;don't hack muddle strings
|
||
type dsko,/"
|
||
/
|
||
comsnd: type dsko,/"FROM" "/
|
||
setom mdlflg ;hack muddle strings
|
||
typout dsko,ml.frm(t)
|
||
setzm mdlflg ;don't hack muddle strings
|
||
type dsko,/"
|
||
"SCHEDULE" ("SENDING")
|
||
/
|
||
skipn ml.sbj(t) ;is there a subject field?
|
||
jrst csytxt ; No, just go hack the text!
|
||
type dsko,/"SUBJECT" "/
|
||
setom mdlflg ;hack muddle strings
|
||
typout dsko,ml.sbj(t)
|
||
setzm mdlflg
|
||
type dsko,/"
|
||
/
|
||
csytxt: setzm mdlflg ;don't hack muddle strings
|
||
type dsko,/"TEXT" "/
|
||
setom mdlflg ;hack muddle strings
|
||
typout dsko,ml.txt(t)
|
||
setzm mdlflg ;don't hack muddle strings
|
||
type dsko,/"/
|
||
movei b,mlmnam ;rename to the mail filenames
|
||
call rnmcls
|
||
restore [b,uuoh] ;restore the world so we can go back
|
||
jrst uuoret ;and return
|
||
|
||
crlf: skipe ttyflg ;is TTY off?
|
||
ret ; yes, don't do it!
|
||
tyo dspc,[^P] ;type a ^PA ala DDT
|
||
tyo dspc,["A]
|
||
ret
|
||
|
||
terpri=call crlf
|
||
|
||
;;;; GINIT does basic initialization, opening the TTY, etc.
|
||
;;;; GINIT1 is the subset of GINIT that initializes interrupts and essential
|
||
;;;; variables that are needed before the TTY is opened even.
|
||
;;;; GINIT2 opens the TTY and initializes TTYSTS and TTYST1 and TTYST2
|
||
;;;; and the password database
|
||
|
||
ginit: skipe startd ;has it been started already?
|
||
ret ; yes, don't bother
|
||
call ginit1
|
||
loss ;it lost somehow
|
||
call ginit3
|
||
ret
|
||
|
||
ginit1: .suset [.soption,,[<%opopc\%opint\%oplok\%oplkf>,,0]] ;set up winnage.
|
||
.suset [.s40addr,,[suuo]] ;where we handle system UUO's and ints
|
||
.suset [.smask,,[ ;enable interrupts
|
||
%pidwn\%pidbg\%pimpv\%pipdl\%pirlt\%piioc\%piltp\%picli\%piwro\%pioob\%piilo\%pidis]]
|
||
.suset [.smsk2,,[<1_tyic>\<1_tyoc>\<1_dspc>\<1_tlnc>]]
|
||
.suset [.rcnsl,,consol] ;get the console number
|
||
move b,consol
|
||
syscal cnsget,[argi %jsnum(b) ;collect info on our TTY
|
||
val vsize
|
||
val hsize
|
||
val nul
|
||
val ttycom
|
||
val ttyopt
|
||
val TTYTYP]
|
||
ret ; lost, don't skip
|
||
|
||
setzm sailp ; Clear these flags, in case they were
|
||
setzm hfdupf ; set by PURIFY$G
|
||
move x,ttyopt ;check this TTY out
|
||
tlne x,%tosai ; does this TTY know about sail characters?
|
||
setom sailp ; yes, so echo contols right
|
||
tlne x,%tohdx ;is this TTY a loser?
|
||
setom hfdupf ; yep, note the fact!
|
||
tlne x,%tomvb ;can it backspace directly?
|
||
setom bsflag ; note the fact for losers (see ECHO)
|
||
call bltspc ;Set up appropriate file specs.
|
||
jrst popj1 ;Win away...
|
||
|
||
;;; BLTSPC - blt in the correct file specs for this machine.
|
||
;;; Returns if won.
|
||
|
||
bltspc: syscal sstatu,[val x ? val x ? val x ? val x ? val x
|
||
val machin] ;get the machine name
|
||
loss
|
||
move x,machin ;get it in an AC
|
||
came x,[sixbit /MX/]
|
||
camn x,[sixbit /MC/] ;is it MC?
|
||
jrst [move x,[mcspec,,tsspec] ;yes, so use MC's specs
|
||
blt x,spcend-1
|
||
ret ]
|
||
camn x,[sixbit /ML/] ;is it ML?
|
||
jrst [move x,[mlspec,,tsspec] ;yes, so use ML's specs
|
||
blt x,spcend-1 ; all of them, to the end
|
||
ret ]
|
||
camn x,[sixbit /AI/] ;is it AI?
|
||
jrst [move x,[aispec,,tsspec] ;yes, so use AI's specs
|
||
blt x,spcend-1 ; all of them, to the end
|
||
ret ]
|
||
camn x,[sixbit /MD/] ;is it MD?
|
||
jrst [move x,[mdspec,,tsspec] ;yes, so use MD's specs
|
||
blt x,spcend-1 ; all of them, to the end
|
||
ret ]
|
||
camn x,[sixbit /DB/] ;is it DB?
|
||
jrst [move x,[mdspec,,tsspec] ;yes, so use MD's specs
|
||
blt x,spcend-1 ; all of them, to the end
|
||
ret ]
|
||
camn x,[sixbit /KA/] ;is it KA?
|
||
jrst [move x,[mdspec,,tsspec] ;yes, so use MD's specs
|
||
blt x,spcend-1 ; all of them, to the end
|
||
ret ]
|
||
camn x,[sixbit /DM/] ;DM-P?
|
||
jrst [move x,[dmspec,,tsspec] ;yes, use DM's specs
|
||
blt x,spcend-1 ; all of them to the bitter end
|
||
setom dm.flg
|
||
ret ]
|
||
.lose ; Unknown machine!
|
||
|
||
|
||
.upure
|
||
ginitd: 0 ; -1 means we've done GINIT2 before
|
||
.pure
|
||
|
||
ginit2: skipe ginitd ; Have we already initialized ourself?
|
||
ret ; Yes, go no further
|
||
call ginit3
|
||
|
||
movei a,hstpag
|
||
movei b,hstc
|
||
call netwrk"hstmap
|
||
IFN $$PAND,[ error /Can't map host table!/
|
||
]
|
||
.ELSE jfcl
|
||
IFE $$PAND,[
|
||
move a,[netwrk"nw%arp]
|
||
call netwrk"ownhst
|
||
jfcl
|
||
movem a,lclsit
|
||
]; End of IFE $$PAND,
|
||
call pwdmap ; Map in the password database
|
||
setom ginitd ; note we're initialized
|
||
ret
|
||
|
||
ginit3: syscal open,[cnti .uai
|
||
argi tyic
|
||
[sixbit /TTY/]]
|
||
loss
|
||
|
||
.suset [.runame,,RUNAME] ;get our UNAME
|
||
|
||
syscal ttyget,[argi tyic ? val x ? val x ? val t]
|
||
loss
|
||
skipe sailp ; if terminal can handle it
|
||
tlo t,%tssai ; we want SAIL mode available
|
||
|
||
.suset [.rsuppro,,tt]
|
||
; caig tt,0 ;are we top level?
|
||
; ;don't use super-image just now, MRC gripes.
|
||
; tlo t,%tssii ; turn on super-image input
|
||
syscal ttyset,[argi tyic
|
||
[020202,,020202]
|
||
[030202,,020202]
|
||
t]
|
||
loss
|
||
|
||
|
||
;display channel
|
||
syscal open,[cnti .uao\%TJDIS
|
||
argi dspc
|
||
[sixbit /TTY/]]
|
||
loss
|
||
;ordinary TTY output channel
|
||
syscal open,[cnti .uao
|
||
argi tyoc
|
||
[sixbit /TTY/]]
|
||
loss
|
||
|
||
setom startd ;note that we've run the initialization
|
||
|
||
syscal open,[cnti .uii ;does the .TEMP.; directory exist?
|
||
argi dski
|
||
[sixbit /DSK/]
|
||
[sixbit /.FILE./]
|
||
[sixbit /(DIR)/]
|
||
[sixbit /.TEMP./]]
|
||
do [move x,[sixbit /COMMON/] ; no .TEMP. directory
|
||
movem x,cladir] ; so must be COMMON instead
|
||
.close dski,
|
||
ret
|
||
|
||
.even=<.+1>/2*2
|
||
loc .even
|
||
|
||
iuname: 0 ;UNAME of person purifying
|
||
ifn $$pand,[
|
||
spword: 707644,,721261 ;6/7/85 for new KS10 ITS machines.
|
||
] ;MX => 225747,,366135 (prev 320744,,541326)
|
||
|
||
constants
|
||
|
||
|
||
purify: move sp,[-pdllen,,pdl]
|
||
call ginit ;init
|
||
setzm startd ;we haven't started, really
|
||
syscal corblk,[cnti %cbndw\%cbndr ;get a new page
|
||
argi 0 ;no superfluous XORING, please!
|
||
argi %jself
|
||
argi tmpag1 ;moby page
|
||
argi %jsnew]
|
||
.lose 1400
|
||
move t,[<<iuname/2000>*2000>,,tmpag1*2000]
|
||
blt t,<tmpag1*2000>+1777 ;copy the page
|
||
syscal corblk,[cnti %cbndw\%cbndr ;move it into old location
|
||
argi 0 ;no superfluous XORING, please!
|
||
argi %jself
|
||
argi iuname/2000 ;home, sweet home
|
||
argi %jself
|
||
argi tmpag1]
|
||
.lose 1400
|
||
syscal corblk,[cnti 0 ;delete!
|
||
argi 0
|
||
argi %jself
|
||
argi tmpag1]
|
||
.lose 1400
|
||
.suset [.runame,,iuname] ;remember this
|
||
move x,iuname ;remember in the impure for crash dumps
|
||
movem x,puname
|
||
ifn $$pand,[
|
||
type dspc,/AThis is PANDA, not PWORD.
|
||
Do not install as SYS:ATSIGN HACTRN!!
|
||
/
|
||
]
|
||
move t,[-<<<corend+1777>/2000>-.purpg>,,.purpg]
|
||
syscal corblk,[cnti %cbndr
|
||
argi 0
|
||
argi %jself
|
||
t]
|
||
.lose 1400
|
||
type dspc,/APurified.
|
||
/
|
||
puree: .break 16,100000 ;return
|
||
jrst puree
|
||
|
||
|
||
;;; DBGHAK - Routine to read in a crash file and anylize a bit.
|
||
|
||
|
||
dbghak: skipn startd ;has this been started before?
|
||
move sp,[-pdllen,,pdl] ;use the main pdl for now
|
||
skipe goodf ;if we have already allocated good and bad
|
||
jrst [call goodsw ; get good context back again
|
||
jrst dbghk1] ; don't do it again!
|
||
|
||
move t,[-4,,goodpg] ;move our own low impure for safekeeping
|
||
setz tt, ;starts in page 0
|
||
setom goodf ;note that this set is our "GOOD" set
|
||
syscal corblk,[cnti %cbndw\%cbndr
|
||
argi 0
|
||
argi %jself
|
||
t
|
||
argi %jself
|
||
tt]
|
||
.lose %lssys
|
||
move t,[-4,,badpag]
|
||
syscal corblk,[cnti %cbndw\%cbndr ;get pages for bad data
|
||
argi 0
|
||
argi %jself
|
||
t
|
||
argi %jsnew]
|
||
.lose %lssys
|
||
|
||
dbghk1: syscal corblk,[cnti %cbndw\%cbndr ;RW page for PDL
|
||
argi 0
|
||
argi %jself
|
||
argi dpdlpg
|
||
argi %jsnew]
|
||
.lose 1400
|
||
move sp,[-400,,dpdl] ;get debug pdl ptr
|
||
call ginit ;initialize the universe
|
||
|
||
syscal open,[cnti .uii ;access the file
|
||
argi dski
|
||
[sixbit /DSK/]
|
||
dbgfn1
|
||
dbgfn2
|
||
dbgdir]
|
||
.lose %lsfil
|
||
|
||
move t,[444400,,badloc] ;load file into our new BAD pages!
|
||
movei tt,10000 ;4 blocks of cruft
|
||
syscal siot,[argi dski ? t ? tt] ;move it in
|
||
.lose 1400 ; old CALERR is saved in BADERR
|
||
.close dski, ;close up
|
||
move t,badloc+vrsadr ;get the source filenames to compare
|
||
move tt,badloc+vrsadr+1 ;so we can see if we have the same one
|
||
camn t,[.fnam1] ;same first name?
|
||
came tt,[.fnam2] ; and second name?
|
||
jrst [type dspc,/AWrong version:
|
||
Bug file --> / ; nope!
|
||
6type tyoc,t ;type FN1 of loser
|
||
.iot tyoc,[40] ;space
|
||
6type tyoc,tt ;type FN2 of loser
|
||
type tyoc,/
|
||
Current version --> /
|
||
6type tyoc,[.fnam1]
|
||
.iot tyoc,[40] ;space
|
||
6type tyoc,[.fnam2]
|
||
call badsw ;revert to bad context
|
||
.lose]
|
||
type dspc,/AUNAME = /
|
||
6type tyoc,badloc+runame
|
||
skipe badloc+baderr ;if there was an .CALL error returned
|
||
do [ type dspc,/AError code = /
|
||
8type tyoc,badloc+baderr]
|
||
|
||
type dspc,/ALast error message was:
|
||
/
|
||
output tyoc,@badloc+errmsg
|
||
|
||
call badsw ;revert to bad context
|
||
.break 16,100000 ;and return to superior
|
||
|
||
;;; routine to switch context to good (our own) pages
|
||
|
||
goodsw: push sp,t ;save AC's, we need all the flexibility we
|
||
push sp,tt ;can get when hacking low impure
|
||
move t,[-4,,0] ;AOBJN ptr to low impure data
|
||
movei tt,goodpg ;page goodpg is our good (own) data pages
|
||
syscal corblk,[cnti %cbndw\%cbndr
|
||
argi 0
|
||
argi %jself
|
||
t ;AOBJN ptr to low impure
|
||
argi %jself
|
||
tt] ;source of good data
|
||
.lose %lssys
|
||
pop sp,tt
|
||
pop sp,t
|
||
ret
|
||
|
||
;;; routine to switch context to bad (from crash file) pages
|
||
|
||
badsw: push sp,t ;save AC's, we need all the flexibility we
|
||
push sp,tt ;can get when hacking low impure
|
||
move t,[-4,,0] ;AOBJN ptr to low impure data
|
||
movei tt,badpag ;page badpag is our good (own) data pages
|
||
syscal corblk,[cnti %cbndw\%cbndr
|
||
argi 0
|
||
argi %jself
|
||
t ;AOBJN ptr to low impure
|
||
argi %jself
|
||
tt] ;source of bad data
|
||
.lose %lssys
|
||
pop sp,tt
|
||
pop sp,t
|
||
ret
|
||
|
||
;;; routine to print as half-words. Expects one arg on the stack.
|
||
printh: move x,-1(sp) ;get argument
|
||
hlrz x,x ;isolate left half
|
||
8type tyoc,x ;type it
|
||
type tyoc,/,,/ ;separate it
|
||
move x,-1(sp) ;get argument
|
||
hrrz x,x ;isolate right half
|
||
8type tyoc,x ;type it
|
||
ret
|
||
|
||
|
||
ifn $$pand,[
|
||
|
||
;;; CLOBBR - Initialize a new database.
|
||
;;;
|
||
;;; This can be hand-called from DDT to make a new database.
|
||
;;; Note: The file is written into your current SNAME
|
||
|
||
pwflen==15. ;Length in pages of PWORD file.
|
||
|
||
clobbr: move sp,[-pdllen,,pdl] ;Initialize pdl.
|
||
;; First, make empty password database pages exist.
|
||
move a,[-pwflen,,pwpage]
|
||
syscal CORBLK,[ argi %cbndr+%cbndw ? argi %jself ? a ? argi %jsnew ]
|
||
.lose %lsfil
|
||
setzm pwfile
|
||
move x,[pwfile,,pwfile+1]
|
||
blt x,pwfile+<2000*pwflen>-1
|
||
;; Then fill in default values for the database.
|
||
setzm pwcnt ;Init user count.
|
||
setom atoapl ;Init allow applications.
|
||
setom pwordt ;Init no date override.
|
||
setom pwordt+1
|
||
setom pwordt+2
|
||
setom pwinit ;Init database locks
|
||
setom pwdone
|
||
setzm pwrbfp ;Init Bp.
|
||
setom pwgrdm ;Init group restrictions.
|
||
move x,[pwgrdm,,pwgrdm+1]
|
||
blt x,pwgors-1
|
||
;; Now create default groups.
|
||
..foo==0
|
||
irp gr,,[USER,DAY,DIAL,TURIST,GRP.04,GRP.05,GRP.06,GRP.07,GRP.08,GRP.09,GRP.10,GRP.11,GRP.12,GRP.13,GRP.14,GRP.15]
|
||
move x,[sixbit /GR/]
|
||
movem x,pwgnam+..foo
|
||
..foo==..foo+1
|
||
TERMIN
|
||
.suset [.runame,,pwuhak] ;Note database user.
|
||
.suset [.rjname,,pwjhak]
|
||
;; Now we're gonna write the database out to disk.
|
||
call bltspc ;Now set up appropriate file specs.
|
||
syscal OPEN,[cnti .uio ? argi pwdc ? pw.dev ? pw.fn1 ? pw.fn2 ]
|
||
.lose %lsfil
|
||
move t,[444400,,pwfile]
|
||
movei tt,<2000*pwflen>
|
||
syscal SIOT,[ argi pwdc ? t ? tt]
|
||
.lose %lsfil
|
||
.close pwdc,
|
||
clobr9: .logout 1, ;All done.
|
||
|
||
];$$pand
|
||
|
||
|
||
|
||
;;; Per machine specifications end up here
|
||
.upure
|
||
tsspec:: ;table specifiying way this machine likes em
|
||
spec:
|
||
pwfnam::
|
||
pw.dev: 0
|
||
pw.fn1: 0
|
||
pw.fn2: 0
|
||
pw.snm: 0
|
||
|
||
;;; filename block for mail files
|
||
mlmnam::
|
||
fm.dev: 0
|
||
fm.fn1: 0
|
||
fm.fn2: 0
|
||
fm.snm: 0
|
||
|
||
bugnam: 0
|
||
|
||
spcend::
|
||
.pure
|
||
|
||
;;;; MC and MX's specifications go here
|
||
|
||
mcspec: offset tsspec-. ;Specs are offset and BLT'ed
|
||
pwfnam::
|
||
pw.dev:: sixbit /DSK/
|
||
pw.fn1:
|
||
ife $$DBUG,sixbit / BIG/
|
||
ifn $$DBUG,sixbit / FOO/
|
||
pw.fn2: sixbit / 0DAT/
|
||
pw.snm:
|
||
ife $$DBUG,sixbit /SYSBIN/
|
||
ifn $$DBUG,sixbit /CSTACY/
|
||
|
||
;;; filename block for mail files
|
||
mlmnam::
|
||
fm.dev: sixbit /DSK/
|
||
fm.fn1: sixbit /MAIL/
|
||
fm.fn2: sixbit />/
|
||
fm.snm:
|
||
ife $$DBUG,sixbit /.MAIL./
|
||
ifn $$DBUG,sixbit /CSTACY/
|
||
|
||
bugnam:
|
||
ife $$PAND,440700,,[asciz /BUG PWORD/]
|
||
ifn $$PAND,440700,,[asciz /BUG PANDA/]
|
||
|
||
spcend::
|
||
offset 0
|
||
mcspce:: ;end of MC's specs
|
||
|
||
;;;; ML's specifications go here
|
||
|
||
mlspec: offset tsspec-.
|
||
pwfnam: sixbit /DSK/
|
||
ife $$DBUG,sixbit / BIG/
|
||
ifn $$DBUG,sixbit / FOO/
|
||
sixbit / 0DAT/
|
||
ife $$DBUG,sixbit /SYSBIN/
|
||
ifn $$DBUG,sixbit /CSTACY/
|
||
|
||
;;; filename block for mail files
|
||
mlmnam::
|
||
fm.dev: sixbit /DSK/
|
||
fm.fn1: sixbit /MAIL/
|
||
fm.fn2: sixbit />/
|
||
fm.snm:
|
||
ife $$DBUG,sixbit /.MAIL./
|
||
ifn $$DBUG,sixbit /CSTACY/
|
||
|
||
bugnam:
|
||
ife $$PAND,440700,,[asciz /BUG PWORD/]
|
||
ifn $$PAND,440700,,[asciz /BUG PANDA/]
|
||
|
||
spcend:
|
||
offset 0
|
||
mlspce:
|
||
|
||
;;;; AI's specifications go here
|
||
aispec: offset tsspec-.
|
||
pwfnam::
|
||
pw.dev:: sixbit /DSK/
|
||
pw.fn1: sixbit / BIG/
|
||
pw.fn2: sixbit / 0DAT/
|
||
pw.snm:
|
||
ife $$DBUG,sixbit /SYSBIN/
|
||
ifn $$DBUG,sixbit /CSTACY/
|
||
|
||
;;; filename block for mail files
|
||
mlmnam::
|
||
fm.dev: sixbit /DSK/
|
||
fm.fn1: sixbit /MAIL/
|
||
fm.fn2: sixbit />/
|
||
fm.snm:
|
||
ife $$DBUG,sixbit /.MAIL./
|
||
ifn $$DBUG,sixbit /CSTACY/
|
||
|
||
bugnam:
|
||
ife $$PAND,440700,,[asciz /BUG PWORD/]
|
||
ifn $$PAND,440700,,[asciz /BUG PANDA/]
|
||
|
||
spcend::
|
||
offset 0
|
||
aispce:: ;end of AI's specs
|
||
|
||
;;;; MD's specifications go here
|
||
mdspec: offset tsspec-.
|
||
pwfnam::
|
||
pw.dev:: sixbit /DSK/
|
||
pw.fn1: sixbit / BIG/
|
||
pw.fn2: sixbit / 0DAT/
|
||
pw.snm:
|
||
ife $$DBUG,sixbit /SYSBIN/
|
||
ifn $$DBUG,sixbit /CSTACY/
|
||
|
||
;;; filename block for mail files
|
||
mlmnam::
|
||
fm.dev: sixbit /DSK/
|
||
fm.fn1: sixbit /MAIL/
|
||
fm.fn2: sixbit />/
|
||
fm.snm:
|
||
ife $$DBUG,sixbit /.MAIL./
|
||
ifn $$DBUG,sixbit /CSTACY/
|
||
|
||
bugnam:
|
||
ife $$PAND,440700,,[asciz /BUG PWORD/]
|
||
ifn $$PAND,440700,,[asciz /BUG PANDA/]
|
||
|
||
spcend::
|
||
offset 0
|
||
mdspce:: ;end of MD's specs
|
||
|
||
;;;; ES's specifications go here
|
||
esspec: offset tsspec-.
|
||
pwfnam::
|
||
pw.dev:: sixbit /DSK/
|
||
pw.fn1: sixbit / BIG/
|
||
pw.fn2: sixbit / 0DAT/
|
||
pw.snm:
|
||
ife $$DBUG,sixbit /SYSBIN/
|
||
ifn $$DBUG,sixbit /CSTACY/
|
||
|
||
;;; filename block for mail files
|
||
mlmnam::
|
||
fm.dev: sixbit /DSK/
|
||
fm.fn1: sixbit /MAIL/
|
||
fm.fn2: sixbit />/
|
||
fm.snm:
|
||
ife $$DBUG,sixbit /.MAIL./
|
||
ifn $$DBUG,sixbit /CSTACY/
|
||
|
||
bugnam:
|
||
ife $$PAND,440700,,[asciz /BUG PWORD/]
|
||
ifn $$PAND,440700,,[asciz /BUG PANDA/]
|
||
|
||
spcend::
|
||
offset 0
|
||
esspce:: ;end of ES's specs
|
||
|
||
|
||
;;; DM's specs
|
||
|
||
dmspec: offset tsspec-. ;DM's table of specs are offset and bLT'ed
|
||
pwfnam:: sixbit /DSK/
|
||
sixbit / 0PWRD/
|
||
sixbit />/
|
||
ife $$DBUG,sixbit /SYSENG/
|
||
ifn $$DBUG,sixbit /CSTACY/
|
||
|
||
;;; filename block for mail files
|
||
mlmnam::
|
||
fm.dev: sixbit /DSK/
|
||
fm.fn1: sixbit /MAIL/
|
||
fm.fn2: sixbit />/
|
||
fm.snm:
|
||
ife $$DBUG,sixbit /.MAIL./
|
||
ifn $$DBUG,sixbit /CSTACY/
|
||
|
||
bugnam:
|
||
ife $$PAND,440700,,[asciz /(BUG PWORD)/]
|
||
ifn $$PAND,440700,,[asciz /(BUG PANDA)/]
|
||
|
||
spcend::
|
||
offset 0
|
||
dmspce::
|
||
|
||
;; type our prompt
|
||
|
||
prompt: setzm ttyflg ;turn the TTY!
|
||
|
||
tyo dspc,[^P] ;new line if we need one
|
||
tyo dspc,["A] ;just like DDT.
|
||
skipe dsprmp ;do we have an alternate prompt?
|
||
pjrst [xct dsprmp ; yes, do it
|
||
ret] ; instead
|
||
ife $$pand,tyo tyoc,[52] ;followed by "*"
|
||
ifn $$pand,tyo tyoc,[76] ;followed by ">"
|
||
ret
|
||
|
||
echo: skipe lfflag ; are we on fresh line?
|
||
call [tyo tyoc,[^J] ; get one
|
||
setzm lfflag ; and notice we did it
|
||
ret] ; and continue
|
||
skipe hfdupf ; is it full duplex?
|
||
ret ; yes, don't echo
|
||
cain ch,^M ; CR?
|
||
jrst [ tyo tyoc,ch ; type it
|
||
tyo tyoc,[^J] ; and a LF too!
|
||
ret]
|
||
caie ch,33 ; not altmode?
|
||
cail ch,40 ; abnormal character?
|
||
cain ch,177 ; or rubout?
|
||
cain ch,^G ; ^G is echod as self
|
||
jrst [ tyo tyoc,ch ; OK, echo it normally
|
||
ret]
|
||
call echosl ; Echo it maybe in sail mode
|
||
ret ; and return
|
||
|
||
echoch=call echo ;simple memonic
|
||
|
||
|
||
echosl: save [ch] ; recover the real char
|
||
skipn sailp ; do we have sail characters?
|
||
tyo tyoc,["^] ; no, circumflex will do
|
||
skipe sailp
|
||
tyo tyoc,[^K] ; yes, uparrow is the thing!
|
||
tro ch,100 ; make this into a non-control-char
|
||
tyo tyoc,ch ; and echo that
|
||
restore [ch] ; save the real character
|
||
ret
|
||
|
||
;; routine to read from TTY following conventions WRT ?, _H, etc.
|
||
;; no-skip means ^D typed.
|
||
;; 1-skip means ? or ^_H typed.
|
||
;; 2-skips means rubout
|
||
;; 3-skips means other character
|
||
|
||
tyiget: setzm ttyflg ;reading turns the TTY back on!
|
||
|
||
tyi=call tyiget ;operation to get a character
|
||
skipge ch,reread ;is there anything to re-read?
|
||
tyiiot: .iot tyic,ch ; no, read the character
|
||
setom reread ;nothing to re-read any more, for sure!
|
||
|
||
caie ch,4110 ;is it the [HELP] key?
|
||
cain ch,77 ; or ? "?"
|
||
jrst popj1 ; skip-1 return
|
||
|
||
caile ch,36 ;is it garbage?
|
||
jrst popj23 ; non-garbage, use it!
|
||
|
||
cain ch,0 ;is it ^@ ?
|
||
jrst tyiget ; yes, ignore it
|
||
|
||
cain ch,^D
|
||
ret ;blow nose and return
|
||
|
||
cain ch,^S ; is it a ^S ?
|
||
ret ; yes, return.
|
||
|
||
cain ch,^M ;Allow a ^M to make it through!
|
||
jrst popj23 ; as a real live character
|
||
|
||
save [x] ;borrow X from the world
|
||
move x,tyiflg ;get the flag word
|
||
|
||
trnn x,ty.edt ;Are we hacking editing characters?
|
||
jrst nedit ; no, don't check for them!
|
||
caie ch,^W ;kill word?
|
||
cain ch,^U ; Kill line?
|
||
jrst popj3x ; yes, let them through!
|
||
cain ch,^R ;Retype line?
|
||
jrst popj3x ; yes, retype it
|
||
|
||
nedit: cain ch,^C ;is it a ^C? Let it through!
|
||
jrst popj3x
|
||
restore [x] ; anything else IS garbage, so ignore it.
|
||
echoch ; echo the loser
|
||
tyo tyoc,[^G] ; beep
|
||
jrst tyiget ; and try again
|
||
|
||
popj3x: restore [x]
|
||
popj23: caie ch,177 ;is it a rubout?
|
||
aos (sp) ; no, skip-3 return, ordinary garbage.
|
||
|
||
aos (sp) ;otherwise skip-2, for rubout.
|
||
aos (sp)
|
||
ret
|
||
.upure
|
||
tyiflg: 0 ;flag word for what special chars to let thu
|
||
ty.==525252,,525252
|
||
ty.edt==4 ;flag for allowing editing commands
|
||
.pure
|
||
;;;; Predicates for the RFN package, to skip if must be proceeded by ^Q
|
||
|
||
rsixtp:
|
||
psixtp: cain a,54 ;comma?
|
||
jrst popj1 ; skip!
|
||
ret ;otherwise, just ordinary
|
||
|
||
constants
|
||
versio: .fnam1
|
||
.fnam2
|
||
|
||
.upure
|
||
variables
|
||
impend: ;end of impure!
|
||
.pure
|
||
corend:: ;end of core
|
||
ifg corend-lsrpag*2000, .ERR Code overlaps with INQUIR database, you will lose!
|
||
.perch ;check our allocations
|
||
|
||
;;; Local Modes :::
|
||
;;; Comment Begin:; :::
|
||
;;; Comment Column:35 :::
|
||
;;; End: :::
|
||
|
||
end go
|