~ RLOGIN.BCKѬ RLOGIN.BCKYBACKUP/LOG/LOG CMUIP_ROOT:[SRC.RLOGIN.DIST]*.*; RLOGIN.BCK/SAVE/INTERCHANGE/NOCRC/GROUP=0 DON hV5.4 Toyvax::  _TOYVAX$DUA0: V5.4 ~)!*[SRC.RLOGIN.DIST]000-README.1ST;1+,S . /h 4L B- 0123KPWO 56_7@dN`89GhHJ KRLOGIN/RSH/RLOGIND/RSHD V1.1 3/12/95/dcsFThis saveset contains implementations if the BSD 'r' commands, RLOGIN and RSH. The files are as follows:) 000-README.1st This fileE INSTALL_RLOGIN.COM Procedure to fully install RLOGIN/RSHH COMPILE_RLOGIN.COM Procedure to compile and link RLOGIN/RSHF RFC1282.TXT Specifications and implications of BSD/ RLOGIN protocolF RLOGIN.CLD Command definitions for RLOGIN and RSH, RLOGIN.HLP Help entries for RLOGIN and RSH: RLOGIN.MAR, .OBJ RLOGIN remote login clientC RSH.MAR, .OBJ RSH remote command execution clientD RCMD.MAR, .OBJ Routine to issue commands using the - "r" protocols< NETERROR.OBJ CMU/OpenVMS IP message codes: RLOGIND.MAR, .OBJ RLOGIN remote login serverC RSHD.MAR, .OBJ RSH remote command execution server= RSHD_CMD.COM Wrapper procedure run by RSHDL GETREMHOST.MAR, .OBJ Routine to determine remote host informationF RAUTHORIZE.MAR, .OBJ Routine to authorize users via .RHOSTSF SET_ACCPORNAM.MAR, .OBJ Routine to set access port information3 on terminal devicesC STARTLOGIN.MAR Routine to start a process under a 2 specified usernameIThe command file INSTALL_RLOGIN.COM does all the necessary things to makeIRLOGIN and RSH available to users on the system. You should read throughJthis file before running it, as your local configuration may be different,Heg you may have CMU help in separate help libraries or separate command Htables. If nothing else, this procedure will show the steps required toinstall the software.FThe RLOGIND and RSHD servers utilise the .rhosts mechanism popular on IUnix systems. (The '*' mechanism, source of many security problems, has Fbeen left unimplemented however.) However, there are implications in Gthis, as the mechanism allows users to permit access to their accounts Ewithout a password independent of site security procedures. See the Hsection "A Cautionary Tale" in RFC1282.TXT (included with this package).FBecause of the security implications, the installation procedure gives?the option to install only the client programs, RLOGIN and RSH.FNote that while RSH & RLOGIN only need PHY_IO privilege to get at the Hprivileged ports they need to do authentication, the servers RLOGIND andHRSHD have quite a bit of kernel code in them to fiddle with things like Gthe access port information, username the process runs under and so-on.CSupport for RSH/RLOGIN: I guarantee nothing. It works for me. BugHreports are more likely to be responded to if you make an effort to findFthe actual problem. Again, there is kernel code involved, use at own risk!HRSH/RLOGIN is copyright Don Stokes 1995. Non-commercial distribution isFpermitted, but contributions to my hacking fund or blood alcohol levelare always welcome. ,Don Stokes , 23-Apr-1995.Release 1.1 3-Dec-1995C Added support for passing terminal type and speed to remote system in RLOGIN.F Worked around weirdness where if RSH used SYS$INPUT as input, F and SYS$INPUT is the terminal, and RSH completes before being B given an EOF (Ctrl/Z), Ctrl/T handling would stop working.G Now if no input file is given, and SYS$INPUT is a terminal, TT:H is used instead of SYS$INPUT: (since it's not a PPF). I'm sure G this is going to screw something up but if it's documented it's a feature, not a bug.4 Added RLOGIND and RSHD. Major hackery here.%*[SRC.RLOGIN.DIST]COMPILE_RLOGIN.COM;1+,Q./h 4G- 0123KPWO56ʛX7N`89GhHJG$! Procedure to compile RLOGIN/RSH/RLOGIND/RSHD from source 23/4/95/dcs$!D$! Note that CMU_SRC must point to the root of the CMUIP source tree$!#$ message CMU_SRC:[central]NETERROR$ macro GETREMHOST$ macro RAUTHORIZE $ macro RCMD$ macro RLOGIN$ macro RLOGIND $ macro RSH $ macro RSHD$ macro SET_ACCPORNAM$ macro STARTLOGIN$ link rlogin/notrace$ link rsh/notrace$ link rlogind $ link rshd!*[SRC.RLOGIN.DIST]GETREMHOST.MAR;1+, ./h 46- 0123KPWO56@:R 7wN`89GhHJ5 .title GETREMHOST Return the name of the remote host;6; GETREMHOST chan remotehost remoteport [remipaddress]; $DSCDEF $IODEF .macro debug pushl #SS$_DEBUG calls #1, g^LIB$SIGNAL .endm .macro status stat, dest, ?L1 blbs stat, L1' .iif idn ,, movzwl stat, R0 debug brw dest L1: .endm .macro cmustat iosb, dest, ?L2 blbs iosb, L2 movab iosb, R0 movl 4(R0), R0 debug brw dest L2: .endmNET$INFO = IO$_MODIFY+ .psect GETREMHOST_RW, long,wrt,noexe,noshrnetinfo:CI$FHOST_NAME_SIZE: .blkbCI$LHOST_NAME_SIZE: .blkbCI$FOREIGN_HOST: .blkb 128 .blkb 2 ; dorkish alignmentCI$FOREIGN_PORT: .blkw .blkwCI$LOCAL_HOST: .blkb 128CI$LOCAL_PORT: .blkw .blkwCI$LOCAL_INTERNET_ADRS: .blklCI$REMOTE_INTERNET_ADRS:.blklnetinfo_l = .-netinfoiosb: .blkw 4 ) .psect GETREMHOST_RE, long,nowrt,exe,shr chan = 4remotehost = 8remoteport = 12 remoteip = 16 .entry GETREMHOST, ^M<>5 $QIOW_S chan=chan(AP), iosb=iosb, func=#NET$INFO, - p1=netinfo, p2=#netinfo_l status R0, 99$ cmustat iosb, 99$ movl remotehost(AP), R0! movzbw CI$FHOST_NAME_SIZE, (R0). movw #, 2(R0) movab CI$FOREIGN_HOST, 4(R0)) movzwl CI$FOREIGN_PORT, @remoteport(AP) cmpl (AP), #4 bneq 1$- movl CI$REMOTE_INTERNET_ADRS, @remoteip(AP)1$: movl #SS$_NORMAL, R0 99$: ret .end!*[SRC.RLOGIN.DIST]GETREMHOST.OBJ;1+,# ./h 4- 0123KPWO56@Y4X7 N`89GhHJ4 GETREMHOST0 3-DEC-1995 22:36 VAX MACRO T5.2V-4MACRO GETREMHOST$Return the name of the remote host GETREMHOST: LIB$SIGNAL SS$_DEBUG SS$_NORMALSYS$QIOW . ABS .P$ABS$ PP GETREMHOST_RWAPQQQQQQQQQQQQ GETREMHOST_REP  GETREMHOST&|~|~ݏ|~<6~<~ SYS$QIOWP$! subroutine to check if installation is possible and desired$ init:J$ files="GETREMHOST.OBJ,NETERROR.OBJ,RAUTHORIZE.OBJ,RCMD.OBJ,RLOGIN.CLD,"-= + "RLOGIN.HLP,RLOGIN.OBJ,RLOGIND.OBJ,RSH.OBJ,RSHD.OBJ,"-8 + "RSHD_CMD.COM,SET_ACCPORNAM.OBJ,STARTLOGIN.OBJ,"-, + "CMUIP_ROOT:[SYSMGR]IP_STARTUP.COM,"-+ + "CMUIP_ROOT:[SYSMGR]INTERNET.CONFIG"$ i = 0"$ 1: file = f$element(i,",",files)$ if file .nes. ","7$ then if f$parse(file) .eqs. "" then goto cant_install4$ if f$search(file) .eqs. "" then goto cant_install $ i = i + 1 $ goto 1$ endif$ type/page SYS$INPUT:HThis procedure will install the RLOGIN/RSH and ROGIND/RSHD files on yourIsystem, and make appropriate changes to your CMU-OpenVMS configuration. AYou should view this file carefully before attempting to run it. +The procedure performs the following steps:< 1. Insert the HELP information into SYS$HELP:HELPLIB.HLBD 2. Insert the command definitions into SYS$LIBRARY:DCLTABLES.EXE& 3. Link the RLOGIN and RSH images . 4. Place the images in CMUIP_ROOT:[sysexe]/ 5. Install the images with PHY_IO privilegeG 6. Append the INSTALL commands to CMUIP_ROOT:[sysmgr]IP_STARTUP.COMIIf RLOGIND/RSHD installation is requested, the following additional steps are taken:! 7. Link RLOGIND & RSHD images; 8. Place images and RSHD_CMD.COM in CMUIP_ROOT:[sysexe]K 9. Append logical name assignments to CMUIP_ROOT:[sysmgr]IP_STARTUP.COM@ 10. Append WKS records to CMUIP_ROOT:[sysmgr]INTERNET.CONFIG FIf you you wish to change or omit any of these steps, or are unsure ofJthe actions being taken, answer NO to the question below and view or edit this file accordingly.HNote that this procedure does not compile from source. Use the command Ifile COMPILE_RLOGIN to do this. Note that the file NETERROR.MSG from the?CMUIP source kit is required to compile  fully from source code.*$ read SYS$COMMAND confirmed/error=abort -% /prompt="Do you wish to continue? "$ if .not. confirmed then exit$ type SYS$INPUT:CSince RLOGIND & RSHD (which allow users to log in from outside yourIsystem) have security implications, the installation of these components Dis optional. RFC1282.TXT outlines these implications (along with a ,general description of the RLOGIN protocol).EIf RLOGIND/RSHD is installed, you will need to shut down and restart 7CMU-OpenVMS TCP/IP for the installation to take effect.($ read SYS$COMMAND rlogind/error=abort -1 /prompt="Do you wish to install RLOGIND/RSHD? "$ return $abort: exit$ cant_install:?$ write SYS$OUTPUT "The file ", file, " could not be accessed."$ type SYS$INPUT:;The installation can not continue. Please ensure that you:6 - are in the same directory as the installation files - have sufficient privilege! - that CMU-OpenVMS IP is runningand restart the procedure.$ exit*[SRC.RLOGIN.DIST]NETERROR.OBJ;1+, ./h 4 V- 0123KPWO563X7 z]O`89GhHJ1NETWORK0 3-DEC-1995 22:36 3-DEC-1995 22:36VAX-11 Message V04-00k$ABS$f MSG$SECTIONMSG$AAAAAAAAAAAMSG$AAAAAAAAAABMSG$AAAAAAAAAACBc NET$_KILL:cNET$_NRT2cNET$_GP_NSDOWN*cNET$_GP_TOOBIG"cNET$_GP_NOTIMPcNET$_GP_UNKMBXcNET$_GP_NOTFND cNET$_GP_NOHINFcNET$_GP_NONMSRcNET$_GP_RSBUSYcNET$_GP_INVCLScNET$_GP_INVMBXcNET$_GP_INVADRځcNET$_GP_INVNAMҁcNET$_GP_INVINFʁcNET$_GP_INVREQc NET$_GREENERRc NET$_DSREFEXCc NET$_DSUNKERRc NET$_DSNONSRVc NET$_DSREFUSDc NET$_DSNOTIMPc NET$_DSNAMERRc NET$_DSSRVERRc NET$_DSFMTERRzc NET$_DSNONAMErc NET$_DSNOADDRjc NET$_DSINCOMPbc NET$_DSNODSZc NET$_DSDOWNRc NET$_NSQFULLJc NET$_NONSBc NET$_NSEXIT:c NET$_NMLTO2cNET$_DAE*c NET$_GTHFUL"c NET$_NOADRc NET$_NOANAc NET$_NOINA c NET$_NOPNcNET$_NYIcNET$_FTOcNET$_TEcNET$_TWTcNET$_CTOڀcNET$_CCҀcNET$_UNUʀcNET$_UNA€cNET$_IGFcNET$_URCcNET$_EPDcNET$_BDIcNET$_IHIcNET$_BTScNET$_FIPc NET$_CCANc NET$_CREFzcNET$_VTFrcNET$_UNNjcNET$_FSUbcNET$_CRZcNET$_CDERcNET$_CIPJc NET$_NOPRVBcNET$_CSE:cNET$_NUC2cNET$_ILP*cNET$_IFS"cNET$_UCTcNET$_IPCcNET$_IFC cNET$_IRcIPACP$_FACILITYPeP*P'Pf(\pH{cpcc c(c0c68cV@cHcPcXc`cFhcrpcxccc&cZccccccDȀchЀc؀cccc c@cccc c:(cx0c8c@c HcJ Pc Xc `c hc\ pc xc c* cp c c c, ct c c c8 ȁcr Ёc ؁c cHcccc`ccc cJ(c0c8c@c<*IRInsufficient system resources,IFCInvalid network function code,IPCInvalid network protocol code"UCTUnable to create TCB"IFSInvalid foreign port ILPInvalid local port.NUCNon-unique connection specified.CSE Connection table space exhausted:NOPRV*No privilege for access to well-known port2CIP#Connection illegal for this process(CDEConnection does not exist,CRConnection RESET by remote host&FSUForeign host unspecified"UNNUnknown network node<VTF-Valid-TCB table full (all connections in use)0CREF!Connection refused by remote host4CCAN%Connection cancelled by process abort&FIPIO Function in Progress0BTS"User specified buffer is Too small&IHIInvalid known host indexBDIBad device index*EPDError processing device dump&URCDestination Unreachable$IGFInvalid GTHST function UNAUnknown host name"UNUUnknown host number6CC)Connection is closing - operation invalid CTOConnection TimeOut TWTTime-Wait TimeOut TENet ACP is Exiting@FTO2User function timeout. Network event didn't happen0NYI!User function not yet implemented4NOPN$UDP wildcard connection not yet open,NOINAInternet access not allowed*NOANAARPANET access not allowed>NOADR.Name lookup not yet complete - no host addressDGTHFUL2GTHST queue full - can't queue name/address lookup&DAENET$DUMP argument error*NMLTOHost name lookup time-out>NSEXIT-Name lookup failure: name resolver is exiting@NONS1Name lookup failure: name resolver is not runningBNSQFULL0Name lookup failure: name resolver queue is fullJDSDOWN9Name not found in host table (domain service unavailable)FDSNODS4Domain service: no domain servers could be contactedJDSINCOMP7Domain service: received incomplete domain server replyDDSNOADDR0Domain service: no addresses found for host name@DSNONAME,Domain service: no name found for IP addressFDSFMTERR3Domain service: domain server returned format error6DSSRVERR#Domain service: domain server error<DSNAMERR)Domain service: name error (no such name)JDSNOTIMP6Domain service: domain server returned not implementedHDSREFUSD5Domain service: domain server refused to resolve nameJDSNONSRV6Domain service: no usable servers returned by referral8DSUNKERR$Domain service: unknown server errorBDSREFEXC/Domain service: maximum referral limit exceeded:GREENERR'Name lookup failure, unknown error codeB GP_INVREQ-Name lookup: invalid request (internal error)H GP_INVINF4Name lookup: invalid host info item (internal error)L GP_INVNAM8Name lookup: invalid domain name syntax (internal error)H GP_INVADR4Name lookup: invalid address syntax (internal error)H GP_INVMBX4Name lookup: invalid mailbox syntax (internal error)F GP_INVCLS2Name lookup: invalidl domain class (internal error)B GP_RSBUSY-Name lookup: resolver to busy to handle query> GP_NONMSR*Name lookup: no name server could be foundF GP_NOHINF2Name lookup: request host info item does not exist4 GP_NOTFND Name lookup: host name not found2 GP_UNKMBXName lookup: mailbox not foundH GP_NOTIMP3Name lookup: unimplemented request (internal error)> GP_TOOBIG)Name lookup: request data too big for UDP@ GP_NSDOWN+Name lookup: all name servers declared down,NRTNo route found for destination KILLConnection killedcIPACP!*[SRC.RLOGIN.DIST]RAUTHORIZE.MAR;1+,) ./h 4?- 0123KPWO56 CX7njO`89GhHJ . .title RAUTHORIZE Check .rhosts authorization;8; status = RAUTHORIZE remote_host remote_user local_user; $UAIDEF $DSCDEF1 .macro descriptor addr=0, len=0, type=T, class=S .word len .byte DSC$K_DTYPE_'type' .byte DSC$K_CLASS_'class' .long addr .endm, .macro item code, buflen, address, lenadr=0 .word buflen .word code .long address .long lenadr .endm .macro status stat, dest, ?L1 blbs stat, L1' .iif idn ,, movzwl stat, R0 debug brw dest L1: .endm .macro debug ;pushl #SS$_DEBUG ;calls #1, g^LIB$SIGNAL .endm + .psect RAUTHORIZE_RW, long,noexe,wrt,noshr,uai_itmlst: item UAI$_DEFDEV, 32, uai_defdev" item UAI$_DEFDIR, 64, uai_defdir item 0,0,0uai_defdev: .blkbrhostbuf: .blkb 127uai_defdir: .blkb 64rhosts: .ascii ".RHOSTS" .align longrhosts_fab: $FAB fna=rhostbuf?rhosts_rab: $RAB fab=rhosts_fab, ubf=rhosts_ubf, usz=rhosts_uszrhosts_ubf: .blkb 80rhosts_usz = .-rhosts_ubf$rhost_name: descriptor rhosts_ubf, 0$rhost_user: descriptor rhosts_ubf, 0 ) .psect RAUTHORIZE_RE, long,exe,nowrt,shrremote_host = 4remote_user = 8local_user = 12) .entry rauthorize, ^m5 $GETUAI_S usrnam=@local_user(AP), itmlst=uai_itmlst status R0, fail movzbl uai_defdev, R6 movzbl uai_defdir, R7& movc3 R7, uai_defdir+1, rhostbuf(R6) addl2 R7, R6 movc3 #7, rhosts, rhostbuf(R6) addl2 #7, R6 movb R6, rhosts_fab+FAB$B_FNS $OPEN rhosts_fab status R0, fail $CONNECT rhosts_rab status R0, rhosts_donerhosts_loop: $GET rhosts_rab cmpl R0, #RMS$_EOF bneq 1$ brw rhosts_done1$: status R0, rhosts_done! movzwl rhosts_rab+RAB$W_RSZ, R4 beql rhosts_loop2$: cmpb rhosts_ubf-1(R4), #32 bgtr 3$ decl R4 bneq 2$ brw rhosts_loop3$: movw R4, rhost_name" movq @local_user(AP), rhost_user locc #32, R4, rhosts_ubf bneq 31$ locc #9, R4, rhosts_ubf beql 5$31$: subl2 #rhosts_ubf, R1 movw R1, rhost_name 4$: incl R1 cmpb rhosts_ubf(R1), #32 bleq 4$$ movab rhosts_ubf(R1), rhost_user+4 subw3 R1, R4, rhost_user5$: pushaq rhost_name pushaq @remote_host(AP)$ calls #2, g^STR$CASE_BLIND_COMPARE tstl R0 bneq 6$ pushaq rhost_user pushaq @remote_user(AP)$ calls #2, g^STR$CASE_BLIND_COMPARE tstl R0 beql 7$6$: brw rhosts_loop7$: $CLOSE rhosts_fab movl #1, R0 retrhosts_done: $CLOSE rhosts_fabfail: clrl R0 ret .end!*[SRC.RLOGIN.DIST]RAUTHORIZE.OBJ;1+,$ ./h 4- 0123KPWO56`PX7O`89GhHJ4 RAUTHORIZE0 3-DEC-1995 22:36 VAX MACRO T5.2V-4MAC RAUTHORIZECheck .rhosts authorization RAUTHORIZEoRMS$_EOFSTR$CASE_BLIND_COMPARE SYS$CLOSE SYS$CONNECTSYS$GET SYS$GETUAISYS$OPEN . ABS .P$ABS$ PP RAUTHORIZE_RWP $@QQQ@.RHOSTSQPPQNQQ%QQ<PDQBQQQP&QQPN RAUTHORIZE_REP  RAUTHORIZE&|~  SYS$GETUAIP,, movzwl stat, R0 debug brw dest L1: .endm .macro cmustat iosb, dest, ?L2 blbs iosb, L2 movab iosb, R0 movl 4(R0), R0 debug brw dest L2: .endm, .macro item code, buflen, address, lenadr=0 .word buflen .word code .long address .long lenadr .endm1 .macro descriptor addr=0, len=0, type=T, class=S .word len .byte DSC$K_DTYPE_'type' .byte DSC$K_CLASS_'class' .long addr .endm & .psect RCMD_RW, long, noexe,wrt,noshrnul = 0>;init_fao_err: .ascid "!UL""!AS""!AS""!AS"4init_fao: .ascid "!AS""!AS""!AS"init_d: descriptor init, 255init: .blkb 255@jpi_itmlst: item JPI$_USERNAME, 12, jpi_username, jpi_username_d item 0,0,0'jpi_username_d: descriptor jpi_usernamejpi_username: .blkb 12rem_username_d: .blkqhost: .blkb 128ip: .ascid "IP0:" ipbuf: .blkliosb: .blkw 4 $ .psect RCMD_RE, long, exe,nowrt,shr p_host = 4 p_port = 8 p_cmd = 12 p_chan = 16 p_ruser = 20&p_errchan = 24 ; not implemented (yet) .entry rcmd, ^M;/; Copy host name to buffer and nul-terminate it; movl p_host(AP), R0 movzwl (R0), R1 clrb host(R1) movc3 R1, @4(R0), host;%; Get local username and lowercase it; $GETJPI_S itmlst=jpi_itmlst status R0, abort clrl R0#11$: cmpb jpi_username(R0), #^A" " bleq 13$ cmpb jpi_username(R0), #^A"A" blss 12$ cmpb jpi_username(R0), #^A"Z" bgtr 12$$ bisb #^b00100000, jpi_username(R0)12$: aoblss #12, R0, 11$13$: movw R0, jpi_username_d;%; If remote username supplied, use it; tstl p_ruser(AP) beql 23$ tstw @p_ruser(AP) beql 23$# movq @p_ruser(AP), rem_username_d brb 24$)23$: movq jpi_username_d, rem_username_d$24$: ; else user local username;; Connect to remote host;' $ASSIGN_S chan=@p_chan(AP), devnam=ip' status R0, abort ; Assign IP channel movl #1023, R2<41$: $QIOW_S chan=@p_chan(AP), iosb=iosb, func=#NET$OPEN, -. p1=host, p2=p_port(AP), p3=R2, p4=#3, p6=#0% status R0, abort ; Connect to host blbs iosb, 42$ 6 cmpl iosb+4, #NET$_NUC ; If not unique, try a lower bneq 42$ ; port number decl R2" cmpl R2, #512 ; Minimum is 512 bgtr 41$42$: cmustat iosb, abort;#; Create handshake string & send it;* $FAO_S ctrstr=init_fao, outlen=init_d, -; outbuf=init_d, p1=#jpi_username_d, p2=#rem_username_d, - p3=p_cmd(AP)0 status R0, abort ; Construct handshake string movzwl init_d, R08 $QIOW_S chan=@p_chan(AP), iosb=iosb, func=#NET$SEND, -" p1=@init_d+4, p2=R0, p4=#0 ; #1 status R0, abort ; Send it cmustat iosb, abort; $QIOW_S chan=@p_chan(AP), iosb=iosb, func=#NET$RECEIVE, - p1=ipbuf, p2=#10 status R0, abort ; Wait for reverse handshake cmustat iosb, abort abort: ret .end*[SRC.RLOGIN.DIST]RCMD.OBJ;1+,4 ./h 42- 0123KPWO56 $7 P`89GhHJ.RCMD023-APR-1995 16:59 VAX MACRO T5.2V-4 MACRO RCMD!RCMD module for RLOGIN, RSH etc RCMDi DSC$K_CLASS_S DSC$K_DTYPE_TNET$_NUC SYS$ASSIGNSYS$FAO SYS$GETJPISYS$QIOW&CMUIP_ROOT:[syslib]NETERROR.OBJ . ABS .P$ABS$PPPPRCMD_RWP3!AS!AS!ASQ &Q DSC$K_DTYPE_T% DSC$K_CLASS_S%Q <4 DSC$K_DTYPE_T%~ RLOGIN.BCK4  RC.RLOGIN.DIST]RCMD.OBJ;1v DSC$K_CLASS_S%<Q QQ3IP0:Q&Q QQRCMD_REP< <RCMD&ЬP<`QP(QP|~ SYS$GETJPIP Internet standard. Distribution of this memo is unlimited.Protocol DescriptionH The rlogin facility provides a remote-echoed, locally flow-controlledE virtual terminal with proper flushing of output [1]. It is widelyG used between Unix hosts because it provides transport of more of theE Unix terminal environment semantics than does the Telnet protocol,E and because on many Unix hosts it can be configured not to requireB user entry of passwords when connections originate from trusted hosts.H The rlogin protocol requires the use of the TCP. The contact port is4 513. An eight-bit transparent stream is assumed.Connection EstablishmentG Upon connection establishment, the client sends four null-terminatedA strings to the server. The first is an empty string (i.e., itE consists solely of a single zero byte), followed by three non-nullF strings: the client username, the server username, and the terminal$ type and speed. More explicitly:  client-user-name server-user-name! terminal-type/speed For example:  bostic kbostic vt100/9600H The server returns a zero byte to indicate that it has received theseHKantor [Page 1] HRFC 1282 BSD Rlogin December 1991E strings and is now in data transfer mode. Window size negotiation0 may follow this initial exchange (see below).(From Client to Server (and Flow Control)D Initially, the client begins operation in "cooked" (as opposed toC to "raw") mode. In this mode, the START and STOP (usually ASCIIG DC1,DC3) characters are intercepted and interpreted by the client toF start and stop output from the remote server to the local terminal,E whereas all other characters are transmitted to the remote host as= they are received. (But see below for the handling of the local-escape character.)A In "raw" mode, the START and STOP characters are not processedE locally, but are sent as any other character to the remote server.A The server thus determines the semantics of the START and STOPF characters when in "raw" mode; they may be used for flow control orG have quite different meanings independent of their ordinary usage on the client.Screen/Window SizeF The remote server indicates to the client that it can accept windowF size change information by requesting a window size message (as out= of band data) just after connection establishment and userD identification exchange. The client should reply to this request with the current window size.F If the remote server has indicated that it can accept client windowH size changes and the size of the client's window or screen dimensionsF changes, a 12-byte special sequence is sent to the remote server toE indicate the current dimensions of the client's window, should the> user process running on the server care to make use of that information.G The window change control sequence is 12 bytes in length, consistingG of a magic cookie (two consecutive bytes of hex FF), followed by twoE bytes containing lower-case ASCII "s", then 8 bytes containing the@ 16-bit values for the number of character rows, the number ofG characters per row, the number of pixels in the X direction, and theE number of pixels in the Y direction, in network byte order. Thus: FF FF s s rr cc xp ypH Other flags than "ss" may be used in future for other in-band control) messages. None are currently defined.HKantor [Page 2] HRFC 1282 BSD Rlogin December 1991From Server to ClientC Data from the remote server is sent to the client as a stream ofG characters. Normal data is simply sent to the client's display, but@ may be processed before actual display (tabs expanded, etc.).G The server can imbed single-byte control messages in the data streamG by inserting the control byte in the stream of data and pointing theE TCP "urgent-data" pointer at the control byte. When a TCP urgent-G data pointer is received by the client, data in the TCP stream up toE the urgent byte is buffered for possible display after the controlC byte is handled, and the control byte pointed to is received and interpreted as follows:G02 A control byte of hex 02 causes the client to discard all bufferedG data received from the server that has not yet been written to the client user's screen.D10 A control byte of hex 10 commands the client to switch to "raw"G mode, where the START and STOP characters are no longer handled by7 the client, but are instead treated as plain data.H20 A control byte of hex 20 commands the client to resume interceptionD and local processing of START and STOP flow control characters.E80 The client responds by sending the current window size as above.H All other values of the urgent-data control byte are ignored. In allG cases, the byte pointed to by the urgent data pointer is NOT written to the client user's display.Connection ClosureD When the TCP connection closes in either direction, the client orC server process which notices the close should perform an orderly@ shut-down, restoring terminal modes and notifying the user orF processes of the close before it closes the connection in the other direction.Implementation NotesG The client defines a client-escape character (customarily the tilde,H "~"), which is handled specially only if it is the first character toD be typed at the beginning of a line. (The beginning of a line isE defined to be the first character typed by the client user after aF new-line [CR or LF] character, after a line-cancel character, afterG resumption of a suspended client session, or after initiation of the connection.)HKantor [Page 3] HRFC 1282 BSD Rlogin December 1991E The client-escape character is not transmitted to the server untilE the character after it has been examined, and if that character isH one of the defined client escape sequences, neither the client-escape@ nor the character following it are sent. Otherwise, both theE client-escape character and the character following it are sent to% the server as ordinary user input.D If the character following the client-escape character is the dotH ".", or the client-defined end-of-file character (usually control-D),G the connection is closed. This is normally treated by the server as2 a disconnection, rather than an orderly logout.E Other characters (client-defined, usually control-Z and control-Y)F are used to temporarily suspend the rlogin client when the host hasF that ability. One character suspends both remote input and output;G the other suspends remote input but allows remote output to continue1 to be directed to the local client's terminal.G Most client implementations have invocation switches that can defeatE normal output processing on the client system, and which can forceG the client to remain in raw mode despite switching notification from the server.A Cautionary Tale [2]H The rlogin protocol (as commonly implemented) allows a user to set upH a class of trusted users and/or hosts which will be allowed to log on? as himself without the entry of a password. While extremely D convenient, this represents a weakening of security that has beenF successfully exploited in previous attacks on the internet. If oneF wishes to use the password-bypass facilities of the rlogin service,B it is essential to realize the compromises that may be possible thereby.oE Bypassing password authentication from trusted hosts opens ALL theeE systems so configured when just one is compromised. Just as usingeD the same password for all systems to which you have access lets aE villain in everywhere you have access, allowing passwordless login G among all your systems gives a marauder a wide playing field once hesB has entered any of your systems. One compromise that many feelE achieves a workable balance between convenience and security is tooG allow password bypass from only ONE workstation to the other systemsqG you use, and NOT allow it between those systems. With this measure,n7 you may have reduced exposure to a workable minimum.G The trusted host specification is ordinarily one of a host name. It H is possible, by compromise of your organization's domain name server,A or compromise of your network itself, for a villain to make ansHKantor [Page 4] eHRFC 1282 BSD Rlogin December 1991G untrusted host masquerade as a trusted system. There is little thatoA a user can do about this form of attack. Luckily, so far such When the file containing a user's list of trusted logins isG inadvertently left writeable by other users, untrustworthy additionsc may be made to it.nE Secure authentication extensions to the rlogin protocol (Kerberos,lG et al) can greatly reduce the possibility of compromise whilst still B allowing the convenience of bypassing password entry. As theseE become more widely deployed in the internet community, the hazardsa of rlogin will decrease.c ReferencesF [1] Stevens, W., "UNIX Network Programming", ISBN 0-13-949876-1.: [2] Garfinkel & Spafford, "Practical Unix Security", ISBN 0-937175-72-2.eSecurity Considerationsr- See the "A Cautionary Tale" section above.hAuthor's Address Brian KantorI( University of California at San Diego Network Operations C-024l La Jolla, CA 92093-0214 Phone: (619) 534-6865 EMail: brian@UCSD.EDUHKantor [Page 5] *[SRC.RLOGIN.DIST]RLOGIN.CLD;1+,; ./h 4Iz- 0123KPWO56t7P`89GhHJdefine verb rlogin' image CMUIP_ROOT:[sysexe]RLOGIN@ parameter p1, label=host, value(required), prompt="Host"A qualifier username, label=remuser, value(required), nonnegatable0 qualifier escape, value(required), nonnegatabledefine verb rsh$ image CMUIP_ROOT:[sysexe]RSH@ parameter p1, label=host, value(required), prompt="Host"I parameter p2, label=command, value(required,type=$rest_of_line),  prompt="Command"A qualifier username, label=remuser, value(required), nonnegatable0 qualifier output, value(required,type=$outfile). qualifier input, value(required,type=$infile)*[SRC.RLOGIN.DIST]RLOGIN.HLP;1+, ./h 4J- 0123KPWO56`t 7 FP`89GhHJ 1 RLOGINF RLOGIN implements the BSD Rlogin protocol to provide login to remote J systems. Rlogin allows remote login from trusted hosts without password exchange.@ Once connected, a tilde (~) followed by a dot (.) as the first C characters on a line can be used to close the connection and exit I RLOGIN. Similarly, tilde followed by Control-Z will spawn a subprocess.I The tilde character can be replaced with another character by using the  /ESCAPE qualifier. Format: RLOGIN hostname 2 Parameters? RLOGIN has only one parameter, the host name or address to be  connected to. 2 Qualifiers/ESCAPE /ESCAPE=characterI Sets the escape character to the specified character. If not specified,C the escape character is the tilde (~). Control characters can be = specied using the caret notation, eg ^] refers to Control-]. /USERNAME /USERNAME=remote-username3 Sets the username to be used on the remote system.1 RSHI RLOGIN implements the BSD Rsh protocol to provide execution of commands I on a remote system. RSH allows remote access from trusted hosts without password exchange.+ Format: RSH hostname remote-command 2 ParametersH RSH has two parameters, the remote host to execute the command on, and C the command and its parameters. The command will be translated toG lowercase unless the string is quoted. Note that qualifiers affectingI the RSH command itself must be placed before the remote command or they A will be included in the command sent to the remote host and not  interpretyed locally. 2 Qualifiers /INPUT /INPUT=inputfile /NOINPUTF Specifies the input file to pass as input to the remote command. By E default, RSH reads from SYS$INPUT. Specifying /NOINPUT prevents RSH# from taking input from any source./OUTPUT /OUTPUT=outputfile /NOOUTPUTI Specifies the ouptput file to write output from the remote command to. F By default, RSH writes to SYS$OUTPUT. Specifying /NOOUTPUT cause RSHI to discard any output from the remote command. Note that /NOOUTPUT doesD not prevent data from being sent to the local system, it is merely  discarded on arrival. /USERNAME /USERNAME=remote-username3 Sets the username to be used on the remote system.*[SRC.RLOGIN.DIST]RLOGIN.MAR;1+,s ./h 4A^- 0123KPWO56,, movzwl stat, R0 debug brw dest L1: .endm .macro cmustat iosb, dest, ?L2 blbs iosb, L2 movab iosb, R0 movl 4(R0), R0 debug brw dest L2: .endm, .macro item code, buflen, address, lenadr=0 .word buflen .word code .long address .long lenadr .endm1 .macro descriptor addr=0, len=0, type=T, class=S .word len .byte DSC$K_DTYPE_'type' .byte DSC$K_CLASS_'class' .long addr .endm .macro terment term, name .byte TT$_'term' .ascic name .endm ( .psect RLOGIN_RW, long, noexe,wrt,noshrnul = 0cr = 13 ctrlz = 260ttype_speed: .ascid " ">ttype_speed_fao:.ascid "!AC/!ZL" ; FAO for tty / speed string=wsize: .long ^x7373FFFF, 0, 0 ; String to tell remote about ; window size=rem_username_d: descriptor rem_username, 16 ; Remote usernamerem_username: .blkb 16*host_d: descriptor 0,0,T,D ; Remote hostipchan: .blkw ; I/O stuffipiosb1: .blkw 4ipiosb2: .blkw 4ttchan: .blkwtt: .ascid "SYS$COMMAND:"ttiosb1: .blkw 4ttiosb2: .blkw 4ttchars: .blkb 12ttchars1: .blkb 8iosb: .blkw 4ipbuf: .blkb 8192 ; Buffersipbuf_l = .-ipbufttbuf: .blkb 2ttbuf_l = .-ttbufsaved_seq: .blkb 2exitcode: .blklfive_secs: .long -50000000 .long -1escape_d: descriptor escape, 2escape: .blkl ; Command sequences: (crescdot: .long ^x0D7E2e ; CR ~ . exit,crescctrlz: .long ^x0D7E1A ; CR ~ ^Z spawn$crescesc: .long ^x0D7E7E ; CR ~ ~ cresc: .long ^x0D7E ; CR ~#crescwild: .long ^x0D7E00 ; CR ~ (cli_host: .ascid "HOST" ; CLI entitiescli_remuser: .ascid "REMUSER"cli_escape: .ascid "ESCAPE"@termtable: terment VK100, "vk100" ; Terminal type to name table terment TEK401X, "tek4010" terment VT52, "vt52" terment VT200_Series, "vt220" terment VT300_Series, "vt320" terment VT400_Series, "vt420"9 terment UNKNOWN, "vt100" ; If not in table assume VT100;termspeed: .long 0,50,75,110,134,150,300,600,1200,1800,2000, .long 2400,3600,4800,7200,9600,19200,38400 ; Terminal speeds; these # ; correspond to TT$C_BAUD_nnn ; slots  & .psect RLOGIN_RE, long, exe,nowrt,shr .entry rlogin, ^M;; Get host to connect to; pushaq host_d pushaq host_d pushaq cli_host calls #3, g^CLI$GET_VALUE- status R0, abort ; Get host name parameter;; Get remote username; pushaq rem_username_d pushaq rem_username_d pushaq cli_remuser3 calls #3, g^CLI$GET_VALUE ; Check /USER qualifier cmpl R0, #CLI$_ABSENT beql 23$ status R0, escape) clrl R0 ; If present, lowercase name#21$: cmpb rem_username(R0), #^A"@" bleq 22$$ bisb #^b00100000, rem_username(R0)22$: aoblss #16, R0, 21$ brb 24$623$: clrq rem_username_d ; Else RCMD uses local user24$:;; Get escape character; pushaq escape_d pushaq escape_d pushaq cli_escape0 calls #3, g^CLI$GET_VALUE ; Get /ESCAPE= value cmpl R0, #CLI$_ABSENT beql 32$ status R0, abort% cmpb escape, #^A"^" ; ^C -> ctrl/C bneq 31$% bicb3 #^b11100000, escape+1, escape=31$: movb escape, crescdot+1 ; replace ~s in escape command< movb escape, crescctrlz+1 ; sequences with supplied escape movb escape, crescesc ; char movb escape, crescesc+1 movb escape, cresc movb escape, crescwild+132$:;; Sort out terminal;" $ASSIGN_S chan=ttchan, devnam=tt status R0, abort ; Assign8 $QIOW_S chan=ttchan, iosb=iosb, func=#IO$_SENSEMODE, -* p1=ttchars, p2=#12 ; Get current status status R0, abort status iosb, abort1 movab termtable, R0 ; Serach for terminal type,41$: movb (R0)+, R1 ; R1=possible TT type# beql 42$ ; 0 (UNKNOWN)? done...! cmpb R1, ttchars+1 ; Our type? beql 42$ ; yes? done movzbl (R0)+, R1 ; string len addl2 R1, R0 ; next... brb 41$#42$: movzbl iosb+2, R1 ; Speed.../ movl termspeed[R1], R1 ; ... in bps6 $FAO_S ctrstr=ttype_speed_fao, outbuf=ttype_speed, -# outlen=ttype_speed, p1=R0, p2=R1+ status R0, abort ; format as ttype/speed;; Send command to remote host; pushl #0 ; errchan pushaq rem_username_d ; ruser pushaw ipchan ; chan# pushaq ttype_speed ; ttype/speed pushl #513 ; port pushaq host_d ; host calls #6, RCMD' status R0, abort ; Assign IP channel;; Now set PASTHRU;4 bisl2 #TT2$M_PASTHRU, ttchars+8 ; Set PASTHRU bit6 $QIOW_S chan=ttchan, iosb=iosb, func=#IO$_SETMODE, -2 p1=ttchars, p2=#12 ; and tell terminal about it status R0, abort status iosb, abort;; Be a terminal program; clrl exitcode jsb set_window. $SCHDWK_S daytim=five_secs, reptim=five_secs status R0, cleanup jsb ttqio ; Kick off QIOs jsb ipqio.loop: $HIBER_S ; Quietly wait for something- tstl exitcode ; to go wrong or an orderly beql 3$ ; exit signalled brw cleanup;3$: $QIOW_S chan=ttchan, iosb=iosb, func=#IO$_SENSEMODE, -0 p1=ttchars1, p2=#8 ; Check if window size has" status R0, cleanup ; changed... status iosb, cleanup cmpb ttchars+7, ttchars1+7 bneq 1$ cmpw ttchars+2, ttchars1+2 beql 2$71$: movq ttchars1, ttchars ; If it has, update things+ jsb set_window ; and tell the other end 2$: brw loop ; ; Clean up;6cleanup: $CANCEL_S chan=ttchan ; Cancel stray TTY I/O5 bicl2 #TT2$M_PASTHRU, ttchars+8 ; Clear PASSALL bit6 $QIOW_S chan=ttchan, iosb=iosb, func=#IO$_SETMODE, - p1=ttchars, p2=#12/ cmpl #-1, exitcode ; Was this really a spawn beql spawn ; request( $CANCEL_S chan=ipchan ; Cancel IP I/O7 $QIOW_S chan=ipchan, iosb=iosb, func=#NET$CLOSE, p1=0- $DASSGN_S chan=ipchan ; Generally clean up $DASSGN_S chan=ttchan movl exitcode, R0abort: ret ; and exit;; Come here on SPAWN;&spawn: calls #0, g^LIB$SPAWN ; SPAWN status R0, abort9 bisl2 #TT2$M_PASTHRU, ttchars+8 ; set PASSALL bit again6 $QIOW_S chan=ttchan, iosb=iosb, func=#IO$_SETMODE, - p1=ttchars, p2=#12' jsb ttqio ; Kick TTY QIOs off again clrl exitcode brw loop ; Back into it ;; IP read completion AST; .entry ipast, ^M cmpw ipiosb1, #SS$_CANCEL beql 2$ cmpw ipiosb1, #SS$_ABORT bneq 1$2$: ret1$: cmustat ipiosb1, exit cvtwl ipiosb1+2, R2 bneq 3$ movl #SS$_NORMAL, R0 brw exit)3$: $QIOW_S chan=ttchan, iosb=ttiosb2, -' func=#IO$_WRITEVBLK!IO$M_NOFORMAT, - p1=ipbuf, p2=R2 status R0, exit status ttiosb2, exit jsb ipqio ret9ipqio: $QIO_S chan=ipchan, iosb=ipiosb1, astadr=ipast, - func=#NET$RECEIVE, - p1=ipbuf, p2=#ipbuf_l status R0, exit rsb ;; Terminal read completion AST; .entry ttast, ^M<> cmpw ttiosb1, #SS$_CANCEL beql 1$ cmpw ttiosb1, #SS$_ABORT bneq 2$1$: ret2$: status ttiosb1, exit movl #1, R00 movzwl saved_seq, R1 ; Check escape sequences ashl #8, R1, R1 movb ttbuf, R1 cmpl R1, crescdot ; CR ~ . bneq 3$ ; Exit program movl #SS$_NORMAL, R0 clrw saved_seq brw exit#3$: cmpl R1, crescctrlz ; CR ~ ^Z bneq 4$ ; Spawn subprocess movl #-1, R0 clrw saved_seq brw exit 4$: cmpl R1, crescesc ; CR ~ ~ beql 6$ ; Send single ~ cmpw R1, cresc ; CR ~! bneq 5$ ; Eat next character movw R1, saved_seq brb 7$!5$: clrb R1 ; CR ~ 0 cmpl R1, crescwild ; Stuff ~ into data stream bneq 6$ movb ttbuf,ttbuf+1 movb saved_seq, ttbuf incl R0A6$: movzbw ttbuf-1(R0), saved_seq ; Clear sequence out otherwise6 $QIOW_S chan=ipchan, iosb=ipiosb2, func=#NET$SEND, - p1=ttbuf, p2=R0, p4=#0 status R0, exit cmustat ipiosb2, exit7$: jsb ttqio ret9ttqio: $QIO_S chan=ttchan, iosb=ttiosb1, astadr=ttast, -$ func=#IO$_READVBLK!IO$M_NOECHO, - p1=ttbuf, p2=#1 ; ttbuf_l status R0, exit rsbexit: movl R0, exitcode $WAKE_S ret  ;.; Tell remote system about window size changes;#set_window: clrb wsize+4 movb ttchars+7, wsize+5 movb ttchars+3, wsize+6 movb ttchars+2, wsize+73 $QIOW_S chan=ipchan, iosb=iosb, func=#NET$SEND, - p1=wsize, p2=#12, p4=#0 ; #1 status R0, 99$ cmustat iosb, 99$ rsb99$: movl R0, exitcode $WAKE_S rsb .end rlogin*[SRC.RLOGIN.DIST]RLOGIN.OBJ;1+,= . /h 4 - 0123KPWO 56 SaX7 Q`89GhHJ0RLOGIN0 3-DEC-1995 22:37 VAX MACRO T5.2V-4 MAC RLOGIN&BSD Rlogin client for CMU/VMS TCP/IP RLOGIN CLI$GET_VALUE CLI$_ABSENT DSC$K_CLASS_D DSC$K_CLASS_S DSC$K_DTYPE_T LIB$SPAWNRCMD SYS$ASSIGN SYS$CANCEL SYS$DASSGNSYS$FAO SYS$HIBERSYS$QIOSYS$QIOW SYS$SCHDWKSYS$WAKE RCMDNETERROR . ABS .P$ABS$PPPPP! RLOGIN_RWP3 Q&Q &3!AC/!ZLQ&Q ss DSC$K_DTYPE_T% DSC$K_CLASS_S%EQ DSC$K_DTYPE_T% DSC$K_CLASS_D%QQQQu3SYS$COMMAND:Q &QQQQ QQQ QQQ DSC$K_DTYPE_T% DSC$K_CLASS_S% Q.~ ~ ~~ ~ ~  3HOSTQ&Q  3REMUSERQ&Q !3ESCAPEQ&Q vk100QQ tek4010QQ@vt52QQnvt220QQpvt320QQqvt420QQvt100QQ2Kn,X`  %K* RLOGIN_REP< <RLOGIN&UU  CLI$GET_VALUEP`|~|~ ,, movzwl stat, R0 debug brw dest L1: .endm .macro cmustat iosb, dest, ?L2 blbs iosb, L2 movab iosb, R0 movl 4(R0), R0 debug brw dest L2: .endm, .macro item code, buflen, address, lenadr=0 .word buflen .word code .long address .long lenadr .endmP~ RLOGIN.BCK [SRC.RLOGIN.DIST]RLOGIND.MAR;1Lر81 .macro descriptor addr=0, len=0, type=T, class=S .word len .byte DSC$K_DTYPE_'type' .byte DSC$K_CLASS_'class' .long addr .endmF .macro ttyentry devnam, ttytype, ansi=0,avo=0,edit=0,eight=0,tab=0, -& sixel=0,regis=0,soft=0,block=0, - dec=0,dec2=0,dec3=0,dec4=0 .ascii devnam .byte DC$_TERM .byte TT$_'ttytype' .word 809 .long <<24@TT$V_PAGE>!TT$M_SCOPE!TT$M_WRAP!TT$M_LOWER -- !!>2 .long ! -+ !! -: !!! -/ !! -- !!> .endm termentry_size = 16 " .sbttl "PTD$ communications area") .psect RLOGIND_PTD, page,noexe,wrt,noshr .align pageptcomm:ptriosb: .blkl 1ptrbuf: .blkb 508ptrbuf_l = .-ptrbufptwiosb: .blkl 1ptwbuf: .blkb 508ptwbuf_l = .-ptwbufpt_devchar: .blkl 5ptcomm_l = .-ptcomm  .sbttl "Data") .psect RLOGIND_RW, long, noexe,wrt,noshrip: .ascid "INET$DEVICE:"ipchan: .blkwerrchan: .blkwipiosb: .blkw 4readstrpos: .long 0readstrbuf: .blkb 512 nul: .blkl 0ptchan: .blkliosb: .blkw 4exitrsn: .long 0ptinadr: .address ptcomm" .address !511/locuser: .ascid "xxxxxxxxxxxx" ; Local usercode0remuser: .ascid "xxxxxxxxxxxx" ; Remote usercode(remhost: descriptor 1$, 64 ; Remote host 1$: .blkb 64%remport: .blkl ; Remote port number6dvi_itmlst: item DVI$_DEVNAM, 64, fta_name, fta_name_d5 item 0,0,0 ; To get device name of pseudo-terminalfta_name: .blkb 64#fta_name_d: descriptor fta_name, 64;accpornam_fao: .ascid "!AS@!AS" ; Terminal access port nameaccpornam_buf: .blkb 64accpornam_d: .long 63 .address accpornam_bufKtermtable: ttyentry "unkn", UNKNOWN ; Known terminal types & chracteristics ttyentry "vt52", VT52, tab=13 ttyentry "vt10", VT100, tab=1,dec=1,avo=1,ansi=16 ttyentry "vt13", VT131, tab=1,dec=1,avo=1,block=1,- ansi=1,edit=16 ttyentry "vt12", VT125, tab=1,dec=1,avo=1,regis=1,- ansi=1,sixel=1; ttyentry "vt20", VT200_Series, tab=1,dec=1,dec2=1,avo=1,-" ansi=1,eight=1,soft=1,edit=1; ttyentry "vt22", VT200_Series, tab=1,dec=1,dec2=1,avo=1,-" ansi=1,eight=1,soft=1,edit=1; ttyentry "vt24", VT200_Series, tab=1,dec=1,dec2=1,avo=1,- ansi=1, eight=1,soft=1,- regis=1,sixel=1,edit=1< ttyentry "vt30", VT300_Series, tab=1,dec=1,dec2=1,dec3=1,-# avo=1,eight=1,soft=1,ansi=1,- edit=1< ttyentry "vt32", VT300_Series, tab=1,dec=1,dec2=1,dec3=1,-# avo=1,eight=1,soft=1,ansi=1,- edit=1< ttyentry "vt33", VT300_Series, tab=1,dec=1,dec2=1,dec3=1,-# avo=1,eight=1,soft=1,ansi=1,- sixel=1,regis=1,edit=1< ttyentry "vt34", VT300_Series, tab=1,dec=1,dec2=1,dec3=1,-# avo=1,eight=1,soft=1,ansi=1,- sixel=1,regis=1,edit=1< ttyentry "vt40", VT400_Series, tab=1,dec=1,dec2=1,dec3=1,-# avo=1,eight=1,soft=1,ansi=1,- dec4=1,edit=1< ttyentry "vt42", VT400_Series, tab=1,dec=1,dec2=1,dec3=1,-# avo=1,eight=1,soft=1,ansi=1,- dec4=1,edit=1. ttyentry "vk10", VK100 tab=1,ansi=1,regis=1 ttyentry "tekt", TEK401X ttyentry "tek4", TEK401X: ttyentry "xter", VT102, tab=1,dec=1,avo=1,ansi=1,edit=1 .long 0:send_window: .byte ^x80 ; "I can do window changes" flag4set_win_chan: .word 0 ; Stuff for handling window"set_win_iosb: .blkw 4 ; changes4set_win_itmlst: item DVI$_DEVDEPEND, 4, pt_devchar+4' item DVI$_DEVTYPE, 4, set_win_devtype .long 0set_win_devtype:.blkl & .sbttl "Initialisation & Handshaking"' .psect RLOGIND_RE, long, exe,nowrt,shr .entry rlogind, ^M;; Accept connection in port 513;" $ASSIGN_S chan=ipchan, devnam=ip status R0, abort9 $QIOW_S chan=ipchan, iosb=iosb, func=#NET$OPEN, p3=#513% status R0, abort ; Connect to host cmustat iosb, abort;; Read handshake data<; 00 remote-user 00 local-username 00 term-type '/' speed 00; bsbw readstr ; read 0" bsbw readstr ; remote username movw R0, remuser, movc5 R0, readstrbuf, #32, #12, @remuser+4! bsbw readstr ; local username movw R0, locuser, movc5 R0, readstrbuf, #32, #12, @locuser+4 pushaq locuser pushaq locuser calls #2, g^STR$UPCASE bsbw readstr ; terminaltype;6; Determine terminal type (we don't worry about speed); movab readstrbuf, R0* movab termtable, R2 ; R2=terminal table" movl R2, R1 ; R1=default entry- bisl2 #^x20202020, (R0) ; Lowercase string6 cmpw #^a"de", (R0) ; dec??? (eg dev_vt100,decvt100) bneq 11$ addl2 #3, R0, cmpb #^x7f, (R0) ; dec_??? (eg dec_vt100) bneq 11$ incl R0#11$: movl (R0), R0 ; R0=termtype bisl2 #^x20202020, R012$: cmpl (R2), R0 ; Match? beql 13$" addl2 #termentry_size, R2 ; Next tstl (R2) bneq 12$ movl R1, R2+13$: movc5 #12, 4(R2), #0, #20, pt_devchar# ; Copy chars to default chars;&; Get remote host name and port number; pushal remport pushaq remhost movzwl ipchan, -(SP) calls #3, g^GETREMHOST status R0, abort;7; Check if port is privileged (<1024), reject otherwise; cmpl remport, #1024 blss 1$7 $QIOW_S chan=ipchan, iosb=iosb, func=#NET$CLOSE, p1=0 movl #SS$_ABORT, R0 brw abort;*; Send acknowledgement of connection (nul)A; Tell the other end we're happy to listen to window size changes;B1$: $QIOW_S chan=ipchan, iosb=iosb, func=#NET$SEND, p1=nul, p2=#1 status R0, abort cmustat iosb, abort3 $QIOW_S chan=ipchan, iosb=iosb, func=#NET$SEND, - p1=send_window, p2=#1, p5=#1 status R0, abort cmustat iosb, abort;; Do we know this person?; pushaq locuser pushaq remuser pushaq remhost calls #3, g^RAUTHORIZE blbs R0, 2$ brw 3$;G; Yes? We need to create the PTD with the user as the owner, and startL; a login under that usercode. STARTLOGIN, SETUIC & RESETUIC are privileged%; routines to do the necessary magic.;2$: pushaq locuser( calls #1, g^SETUIC ; Set UIC to owner status R0, abort? PTD$CREATE_S chan=ptchan, inadr=ptinadr, astadr=ptcloseast, -# charbuff=pt_devchar, buflen=#124 status R0, abort ; Create PTD (which will inherit ; ownership as set above)& calls #1, g^RESETUIC ; Put UIC back* $GETDVI_S chan=ptchan, itmlst=dvi_itmlst, status R0, abort ; Get actual device name. pushaq fta_name_d ; And start a login on it pushaq locuser calls #2, g^STARTLOGIN status R0, abort brw 4$;E; Don't know this person? Fine, just create the PTD and let LOGINOUTA; deal with mucky things like autorisation, device ownership etc.;B3$: PTD$CREATE_S chan=ptchan, inadr=ptinadr, astadr=ptcloseast, -# charbuff=pt_devchar, buflen=#12 status R0, abort* $GETDVI_S chan=ptchan, itmlst=dvi_itmlst status R0, abort pushaq fta_name_d pushl #0 calls #2, g^STARTLOGIN status R0, abort;0; Set the access port info to user@remote.host B; (SET_ACCPORNAM is more privileged code to do magic with the UCB);74$: $FAO_S ctrstr=accpornam_fao, outbuf=accpornam_d, -/ outlen=accpornam_d, p1=#remuser, p2=#remhost status R0, abort pushaq accpornam_d pushaq fta_name_d calls #2, g^SET_ACCPORNAM;H; But first send a single nul down the PTY. This is voodoo -- for some G; reason the first PTD$WRITE only gets the first character of the firstA; request into the input buffer. Don't ask me why, I don't know.; clrb ptwbuf 8 PTD$WRITE_S chan=ptchan, wrtbuf=ptwiosb, wrtbuf_len=#1* status R0, abort ; Send the voodoo byte;; Start things rolling. ;&5$: jsb ipqio ; Start reading input$ jsb ptqio ; Start reading output  .sbttl "Main Loop";$; Main loop. Small, aint it ... 8-);loop: $HIBER_S ; Wait.... status R0, abort% movl exitrsn, R0 ; Reason to exit? beql loop abort: ret " .sbttl "Read from PTY, send to IP;H; AST to handle incoming data from PTY and transmit it to the IP channel; .entry ptast, ^M<>6 movzwl ptriosb, R0 ; Ignore cancelled or aborted IO cmpl R0, #SS$_CANCEL beql 1$ cmpw R0, #SS$_ABORT bneq 2$1$: ret(2$: status R0, astabort ; Check status# movzwl ptriosb+2, R0 ; R0=length( $QIOW_S chan=ipchan, func=#NET$SEND, - iosb=iosb, p1=ptrbuf, p2=R03 status R0, astabort ; Send it to the remote user status iosb, astabort bsbb ptqio ; Queue new read ret ; Done;; Queue a read to the PTY;@ptqio: PTD$READ_S chan=ptchan, astadr=ptast, readbuf=ptriosb, - readbuf_len=#ptrbuf_l status R0, astabort rsb ? .sbttl "Read from IP, send to PTY, handle window size changes";H; AST to handle incoming data from IP channel and transmit it to the PTY; .entry ipast, ^M3 movzwl ipiosb, R0 ; Ignore aborted/cancelled I/O cmpl R0, #SS$_CANCEL beql 1$ cmpl R0, #SS$_ABORT bneq 2$1$: ret2$: status R0, astabort" movzwl ipiosb+2, R2 ; R2=length% beql 98$ ; 0? Channel closing...3 locc #^xFF, R2, ptwbuf ; Look for FF In stream, % beql 3$ ; might be window change, bsbw process_window ; If so, check it out* tstl R2 ; Nothing but? Just requeue  beql 4$ ; the read;3$: PTD$WRITE_S chan=ptchan, wrtbuf=ptwiosb, wrtbuf_len=R2$ status R0, astabort ; Send to PTY"4$: bsbb ipqio ; Queue new read 99$: ret98$: brw ptcloseast_b;; Queue read on IP channel;8ipqio: $QIO_S chan=ipchan, iosb=ipiosb, astadr=ipast, -- func=#NET$RECEIVE, p1=ptwbuf, p2=#ptwbuf_l status R0, astabort rsb;,; This might be a change window size request;; Quoth RFC 1282:;J; > The window change control sequence is 12 bytes in length, consistingJ; > of a magic cookie (two consecutive bytes of hex FF), followed by twoH; > bytes containing lower-case ASCII "s", then 8 bytes containing theC; > 16-bit values for the number of character rows, the number ofJ; > characters per row, the number of pixels in the X direction, and theH; > number of pixels in the Y direction, in network byte order. Thus:; > ; > FF FF s s rr cc xp yp;E; *HACK* we assume that we got the whole window change in the buffer.;process_window: cmpw (R1), #^xFFFF ; FF FF ?* bneq 1$ ; No, just continue as normal cmpw 2(R1), #^a"ss" ; s s ?+ beql 2$ ; Yup, this is a window change1$: rsb2$: subl2 #12, R0% blss 1$ ; < 12 chars? ignore...' pushr #^m ; Save regs7 movb 6(R1), pt_devchar+3 ; mutter mutter network byte8 movb 7(R1), pt_devchar+2 ; order why couldn't they use3 movzbl 5(R1), R6 ; a real computer mutter mutter tstl R0, beql 3$ ; Anything left over in buffer?+ movc3 R0, 12(R1), (R1) ; Shuffle it down*3$: tstw set_win_chan ; Chan still open? beql 4$8 $DASSGN_S chan=set_win_chan ; Yes, close it (and abort% ; current I/O, we don't need it ; no more)34$: $ASSIGN_S chan=set_win_chan, devnam=fta_name_d) status R0, astabort ; Assign temp chan4 $GETDVI_S chan=set_win_chan, itmlst=set_win_itmlst0 status R0, astabort ; Get current device info$ movb set_win_devtype, pt_devchar+1 ; Save device type. movb R6, pt_devchar+7 ; Set the page lengthB $QIO_S chan=set_win_chan, iosb=set_win_iosb, func=#IO$_SETMODE,-+ astadr=set_win_ast, p1=pt_devchar, p2=#86 status R0, astabort ; Queue SETMODE, may not happen ; immediately) popr #^m ; Restore regs) subl2 #12, R2 ; Return updated length rsb  ;2; Handle completion of set-window-size SETMODE QIO; .entry set_win_ast, ^M<>1 blbc set_win_iosb, 1$ ; Error? Just ignore it& tstw set_win_chan ; Already closed? beql 1$1 $DASSGN_S chan=set_win_chan ; Close the channel( clrw set_win_chan ; And note the fact1$: ret  .sbttl "Exiting...";E; Handle PTY closed (ptcloseast) or IP channel closing (ptcloseast_b); .entry ptcloseast, ^M<>0ptcloseast_b: tstl exitrsn ; Already aborting? beql 1$ ret.1$: movl #SS$_NORMAL, R0 ; Assume successful2astabort: movl R0, exitrsn ; Save exit condition ' PTD$DELETE_S chan=ptchan ; Delete PTY7 $QIOW_S chan=ipchan, iosb=iosb, func=#NET$CLOSE, p1=0. $DASSGN_S chan=ipchan ; Close IP connection $WAKE_S ; wake mainline movl exitrsn, R0 ret 5 .sbttl "Read nul-terminated trsings from IP channel";!; Read strings until nul received;1readstr: pushr #^M ; Save regs0 movl readstrpos, R7 ; R7 = position in buffer beql 2$&1$: locc #0, R7, ptwbuf ; Find a nul beql 2$ ; R1=address of nul# ; not found -> read some more. subl3 #ptwbuf, R1, R6 ; R6=length of string$ movl R0, R7 ; R7=remaining bytes! decl R7 ; ... minus 1< movc3 R6, ptwbuf, readstrbuf ; Copy string into readstrbufA movc3 R7, ptwbuf+1(R6), ptwbuf ; Copy remainder to start of buf$ movl R7, readstrpos ; Save length movl R6, R0 ; Return length2 popr #^M ; Done, restore regs rsb98$: movl #SS$_ABORT, R099$: brw abort-2$: movl R7,R0 ; Come here if we need more+ subl3 R0, #ptwbuf_l, R0 ; Buffer o/flow? blss 98$6 $QIOW_S chan=ipchan, iosb=iosb, func=#NET$RECEIVE, -( p1=ptwbuf(R7), p2=R0 ; Read some more status R0, 99$ cmustat iosb, 99$ cvtwl iosb+2, R0 beql 98$$ addl2 R0, R7 ; Return new length brw 1$) .end rlogind ; Er, that's all, folks!*[SRC.RLOGIN.DIST]RLOGIND.OBJ;1+,. /h 4 N- 0123KPWO 56`!7 89GhHJ1RLOGIND0 4-DEC-1995 18:21 VAX MACRO T5.2V-4 MAC RLOGINDRLogin daemon for CMU TCP/IPRLOGIND@ DSC$K_CLASS_S DSC$K_DTYPE_T GETREMHOST LIB$SIGNAL PTD$CREATE PTD$DELETEPTD$READ PTD$WRITE RAUTHORIZERESETUICSETUIC SET_ACCPORNAM STARTLOGIN STR$UPCASE SYS$ASSIGN SYS$DASSGNSYS$FAO SYS$GETDVI SYS$HIBERSYS$QIOSYS$QIOWSYS$WAKE&CMUIP_ROOT:[syslib]NETERROR.OBJRAUTHORIZE.OBJGETREMHOST.OBJSTARTLOGIN.OBJSET_ACCPORNAM.OBJ . ABS .P$ABS$!PPPPPPPP  RLOGIND_PTDPQQQQQ RLOGIND_RWP3INET$DEVICE:Q &QQQQQQQQ348@3xxxxxxxxxxxxQ &QT3xxxxxxxxxxxxQ &Q@ DSC$K_DTYPE_T% DSC$K_CLASS_S%lQ@Q@ Q@@ DSC$K_DTYPE_T% DSC$K_CLASS_S%3!AS@!ASQ&Q Q@?unknBPvt52B@Pvt10B`P)vt13BeP=vt12BdP+vt20BnP yvt22BnP yvt24BnP0{vt30BpP vt32BpP vt33BpP0vt34BpP0vt40BqP vt42BqP vk10BPtektB Ptek4B PxterBbP9Q 3Qk RLOGIND_REP RLOGIND&|~ SYS$ASSIGNP- 0123KPWO56v7`wQ`89GhHJ"- .title RSH BSD Rsh client for CMU/VMS TCP/IP;<; Usage: RSH [/USERNAME=remote-username] [/INPUT=input-file]:; [/OUTPUT=output-file] hostname remote-command; .ident "RSH 1.1" .link "RCMD" .link "NETERROR" $JPIDEF $TT2DEF $TRMDEF $IODEF $DCDEF $SSDEFNET$OPEN = IO$_CREATENET$CLOSE = IO$_DELETENET$SEND = IO$_WRITEVBLKNET$RECEIVE = IO$_READVBLK .macro debug ;pushl #SS$_DEBUG ;calls #1, g^LIB$SIGNAL .endm .macro istatus stat, dest, ?L1 blbs stat, L1 movzwl stat, R0 debug brw dest L1: .endm .macro status stat, dest, ?L1 blbs stat, L1% .iif idn ,, movl stat, R0 debug brw dest L1: .endm .macro cmustat iosb, dest, ?L2 blbs iosb, L2 movab iosb, R0 movl 4(R0), R0 debug brw dest L2: .endm, .macro item code, buflen, address, lenadr=0 .word buflen .word code .long address .long lenadr .endm1 .macro descriptor addr=0, len=0, type=T, class=S .word len .byte DSC$K_DTYPE_'type' .byte DSC$K_CLASS_'class' .long addr .endm % .psect RSH_RW, long, noexe,wrt,noshrnul = 0cr = 13 ctrlz = 264init_fao: .ascid "!AS""!AS""!AS"init_d: descriptor init, 256init: .blkb 256+rem_username_d: descriptor rem_username, 16rem_username: .blkb 16host_d: descriptor 0,0,T,Dipchan: .blkwipiosb1: .blkw 4ipiosb2: .blkw 4iosb: .blkw 4ipbuf: .blkb 8192ipbuf_l = .-ipbufipoutbuf: .blkb 32768ipoutptr: .blklexitcode: .blklcommand_d_d: descriptor 0,0,T,Dcommand_d: .blkqcli_host: .ascid "HOST"cli_command: .ascid "COMMAND"cli_remuser: .ascid "REMUSER"cli_input: .ascid "INPUT"cli_output: .ascid "OUTPUT"flg_input: .byte 0flg_output: .byte 00dcl_ctrl_mask: .long 0 ; Ctrl/Y & Ctrl/T flags/dvi_itmlst: item DVI$_DEVCLASS, 4, dvi_devclass .long 0dvi_devclass: .blkltt: .ascii "TT:"sys_input: .ascid "SYS$INPUT:" .align longoutput_d: descriptor 0,0,T,D;output_fab: $FAB fnm=, dnm=, rat=cr, .output_rab: $RAB fab=output_fab, ; Output file .align longinput_d: descriptor 0,0,T,D.input_fab: $FAB fnm= ; Input file<input_rab: $RAB fab=input_fab,rop=asy,ubf=input_ubf,usz=2047input_ubf: .blkb 2048 # .psect RSH_RE, long, exe,nowrt,shr .entry rsh, ^M;; Get host to connect to; pushaq host_d pushaq host_d pushaq cli_host calls #3, g^CLI$GET_VALUE- status R0, abort ; Get host name parameter;; Get remote username; pushaq rem_username_d pushaq rem_username_d pushaq cli_remuser3 calls #3, g^CLI$GET_VALUE ; Check /USER qualifier cmpl R0, #CLI$_ABSENT beql 23$ status R0, abort) clrl R0 ; If present, lowercase name#21$: cmpb rem_username(R0), #^A"@" bleq 22$$ bisb #^b00100000, rem_username(R0)22$: aoblss #16, R0, 21$ brb 24$23$: clrq rem_username_d$24$: ; else user local username; ; Get command8; Remove quotes, treat "" as " when inside quoted string; pushaq command_d_d pushaq cli_command) calls #2, g^CLI$GET_VALUE ; get command status R0, abort/ movq command_d_d, command_d ; Copy descriptor# movzwl command_d, R0 ; R0=length clrl R1 ; R1=quoteflag) clrq R2 ; R2=src index. R3=dst index! movl command_d+4, R4 ; R4=base movl R2,R3 ; R3=dst pointer31$: cmpb (R2)[R4], #^A/"/ bneq 33$ cmpl R1, #2 bneq 32$ movb #^A/"/, (R3)+[R4] incw command_d 32$: incl R1 decw command_d brb 35$33$: blbs R1,34$ cmpb (R2)[R4], #^A/A/ blss 34$ cmpb (R2)[R4], #^A/Z/ bgtr 34$ bisb #^b00100000, (R2)[R4]34$: movb (R2)[R4],(R3)+[R4] bicl #2, R1 35$: aoblss R0,R2,31$;; Get input file; pushaq cli_input. calls #1, g^CLI$PRESENT ; check for /noinput cmpl R0, #CLI$_NEGATED bneq 41$ brw 43$41$: incb flg_input pushaq input_d pushaq cli_input+ calls #2, g^CLI$GET_VALUE ; get file name cmpl R0, #CLI$_ABSENT bneq 44$/ $GETDVI_S devnam=sys_input, itmlst=dvi_itmlst status R0, abort cmpl dvi_devclass, #DC$_TERM bneq 42$ movab tt, input_fab+FAB$L_FNA movb #3, input_fab+FAB$B_FNS brb 42$44$: status R0, abort% movl input_d+4, input_fab+FAB$L_FNA$ cvtwb input_d, input_fab+FAB$B_FNS42$: $OPEN input_fab status R0, abort $CONNECT input_rab status R0, abort43$:;; Get output file; pushaq cli_output. calls #1, g^CLI$PRESENT ; check if /nooutput cmpl R0, #CLI$_NEGATED bneq 51$ brw 53$51$: pushaq output_d pushaq cli_output- calls #2, g^CLI$GET_VALUE ; get output file cmpl R0, #CLI$_ABSENT beql 52$ status R0, abort' movl output_d+4, output_fab+FAB$L_FNA& cvtwb output_d, output_fab+FAB$B_FNS52$: $CREATE output_fab status R0, abort $CONNECT output_rab status R0, abort clrl ipoutptr incb flg_output53$:;&; Connect to remote host, send command; pushl #0 ; errchan pushaq rem_username_d ; ruser pushaw ipchan ; chan pushaq command_d ; cmd pushl #514 ; port pushaq host_d ; host calls #6, RCMD' status R0, abort ; Assign IP channel;; Be a terminal program; clrl exitcode+ bsbw ipqio ; Start read QIOs for output- tstb flg_input ; If no input don't bother beql loop ; reading+ bsbw ttget ; Otherwsie start read $GETs ; on input stream.loop: $HIBER_S ; Quietly wait for something- tstl exitcode ; to go wrong or an orderly beql loop ; exit signalled. tstl ipoutptr ; If anything left in buffer beql cleanup ; write it out& movab ipoutbuf, output_rab+RAB$L_RBF% movw ipoutptr, output_rab+RAB$W_RSZ $PUT output_rab; ; Clean up;>cleanup: $QIOW_S chan=ipchan, iosb=iosb, func=#NET$CLOSE, p1=0- $DASSGN_S chan=ipchan ; Generally clean up& bicl #RAB$M_ASY, input_rab+RAB$L_ROP $DISCONNECT input_rab- $CLOSE input_fab ; We don't care if any of( $CLOSE output_fab ; these things fail movl exitcode, R0abort: ret ; and exit ;; IP read completion AST;' .entry ipast, ^M. cmpw ipiosb1, #SS$_CANCEL ; Check for errors beql 2$ cmpw ipiosb1, #SS$_ABORT bneq 1$2$: ret1$: cmustat ipiosb1, exit* cvtwl ipiosb1+2, R2 ; R2=length of data! bneq 3$ ; If zero we're done movw #SS$_NORMAL, R0 ; exit brw exit"3$: movl R2, R6 ; R6=buf length movab ipbuf, R7 ; R7=buf ptr1 tstb flg_output ; If /NOOUTPUT discard output bneq 4$ brw 6$ ; but keep reading.4$: locc #10, R6, (R7) ; R0=len of remainder beql 5$ ; R1=addr of LF) movl R7,R3 ; Save base address of buf- movq R0,R6 ; R6=new buflen, R7=addr of LF! subl R3, R1 ; R1=len up to LF' movl ipoutptr, R2 ; R2=output buffer addl R1, ipoutptr movc3 R1, (R3), ipoutbuf(R2)& movab ipoutbuf, output_rab+RAB$L_RBF% movw ipoutptr, output_rab+RAB$W_RSZ' $PUT output_rab ; Put output buffer status R0, exit ' clrl ipoutptr ; output buffer empty decl R6 ; Skip LF incl R7 brb 4$ ; Check for more LFs65$: movl ipoutptr, R0 ; Copy buffer to output buffer movc3 R6, (R7), ipoutbuf(R0)/ addl R6, ipoutptr ; Increment output pointer6$: bsbb ipqio ret9ipqio: $QIO_S chan=ipchan, iosb=ipiosb1, astadr=ipast, - func=#NET$RECEIVE, - p1=ipbuf, p2=#ipbuf_l status R0, exit rsb ;; Input GET completion ASTs;) .entry ttgetast_err, ^M<> ; $GET failed% cmpl input_rab+RAB$L_STS, #RMS$_EOF bneq 1$ movw #SS$_NORMAL, R0 ; exit brw exit%1$: status input_rab+RAB$L_STS, exit ret( .entry ttgetast, ^M<> ; GET succeeded3 movzwl input_rab+RAB$W_RSZ, R0 ; R0=record buffer- movb #10, L^input_ubf(R0) ; Add trailing LF incl R06 $QIOW_S chan=ipchan, iosb=ipiosb2, func=#NET$SEND, - p1=input_ubf, p2=R0, p4=#0 status R0, exit ; Send it cmustat ipiosb2, exit bsbb ttget ; Re-queue I/O ret,ttget: $GET input_rab,ttgetast_err,ttgetast cmpl R0, #RMS$_EOF beql 1$ status R0, exit rsb!1$: movw #SS$_NORMAL, R0 ; exitexit: movl R0, exitcode $WAKE_S ret .end rsh*[SRC.RLOGIN.DIST]RSH.OBJ;1+,E . /h 4 - 0123KPWO 56cgX7`KQ`89GhHJ 3RSHRSH 1.1 3-DEC-1995 22:37 VAX MACRO T5.2V-4 MAC RSH#BSD Rsh client for CMU/VMS TCP/IP  RSHY CLI$GET_VALUE CLI$PRESENT CLI$_ABSENT CLI$_NEGATED DSC$K_CLASS_D DSC$K_CLASS_S DSC$K_DTYPE_T DVI$_DEVCLASSRCMDRMS$_EOF SYS$CLOSE SYS$CONNECT SYS$CREATE SYS$DASSGNSYS$DISCONNECTSYS$GET SYS$GETDVI SYS$HIBERSYS$OPENSYS$PUTSYS$QIOSYS$QIOWSYS$WAKE RCMDNETERROR . ABS .P$ABS$PPPPPPRSH_RWP3!AS!AS!ASQ &Q DSC$K_DTYPE_T% DSC$K_CLASS_S%Q DSC$K_DTYPE_T% DSC$K_CLASS_S%%Q DSC$K_DTYPE_T% DSC$K_CLASS_D%QQQQQ QQQ DSC$K_DTYPE_T% DSC$K_CLASS_D%Qs3HOSTQ&Q 3COMMANDQ&Q 3REMUSERQ&Q 3INPUTQ&Q 3OUTPUTQ&Q  DVI$_DEVCLASS&ʡQTT:ա3SYS$INPUT:Q &QQ DSC$K_DTYPE_T% DSC$K_CLASS_D%PPQNQQQ$RMSNAMPSYS$OUTPUT:7PQQ  PRSH.LIS!PQ QQ<PDQBQQQQ DSC$K_DTYPE_T% DSC$K_CLASS_D%PQNQQQPSYS$INPUT:ӢPQQ QDQBQQQQQRSH_REP< <RSH&55o CLI$GET_VALUEPPP1 CLI$GET_VALUEP CLI$_ABSENTPPP1P%@ %P|_{ CLI$GET_VALUEPPP1}_g<gPQ|Rg3TRSDb"Q "DgQgQDbA DbZ DbDbDQPR CLI$PRESENTP CLI$_NEGATED1 CLI$GET_VALUEP CLI$_ABSENTH|~ѡ<~ SYS$GETDVIPPP1ʡB3Ρ,343PPP13,3343SYS$OPENPPP1آ SYS$CONNECTPPP1p CLI$PRESENTP CLI$_NEGATED1s ~ RLOGIN.BCKE  [SRC.RLOGIN.DIST]RSH.OBJ;1 CLI$GET_VALUEP CLI$_ABSENTPPP123,3343 SYS$CREATEPPP1< SYS$CONNECTPPP1W?=gݏ5RCMDPPP1[0n0 SYS$HIBER[W#W!<(3W<"3<SYS$PUT|~|~|~O<5~<=~ SYS$QIOW<=~ SYS$DASSGNآ3آSYS$DISCONNECT SYS$CLOSE SYS$CLOSE[P %IPAST&j?0 ?,??PРP1r2?3RP1cRVWW1o: VgUWS}PVSQWRQW(QcW!W!<(3W<"3<SYS$PUTPPP1WVWWP(VgW!VW|~|~ݏ W(?<1~<=~ SYS$QIOPPP1   TTGETAST_ERR&:آ3RMS$_EOFP1آ31 @TTGETAST&<آ"3P P|~|~P|~G<0~<=~ SYS$QIOWPPP1AGGPРP1,߯߯آSYS$GETPRMS$_EOF PPP1PP[SYS$WAKEN %IPAST RSH@TTGETAST  TTGETAST_ERR>RSH_RW$RMSNAMRSH_RE*[SRC.RLOGIN.DIST]RSHD.MAR;1+,d ./h 4N- 0123KPWO56`:K7` R`89GhHJ & .title RSHD Rsh daemon for CMU TCP/IP  .sbttl "Macros & stuff") .link "CMUIP_ROOT:[syslib]NETERROR.OBJ" ; CMUIP error codes1 .link "RAUTHORIZE.OBJ" ; .RHOSTS Authorization5 .link "GETREMHOST.OBJ" ; Get remote host name/port6 .link "STARTLOGIN.OBJ" ; Start a login (privileged): .link "SET_ACCPORNAM.OBJ" ; Set access port (privileged) $PTDDEF $JPIDEF $DVIDEF $DCDEF $TTDEF $TT2DEF $IODEF $SSDEFNET$OPEN = IO$_CREATENET$CLOSE = IO$_DELETENET$SEND = IO$_WRITEVBLKNET$RECEIVE = IO$_READVBLK .macro debug;; pushl #SS$_DEBUG;; calls #1, g^LIB$SIGNAL .endm .macro status stat, dest, ?L1 blbs stat, L1' .iif idn ,, movzwl stat, R0 debug brw dest L1: .endm .macro cmustat iosb, dest, ?L2 blbs iosb, L2 movab iosb, R0 movl 4(R0), R0 debug brw dest L2: .endm, .macro item code, buflen, address, lenadr=0 .word buflen .word code .long address .long lenadr .endm1 .macro descriptor addr=0, len=0, type=T, class=S .word len .byte DSC$K_DTYPE_'type' .byte DSC$K_CLASS_'class' .long addr .endm  .sbttl "Data") .psect RLOGIND_RW, long, noexe,wrt,noshripbuf: .blkb 2048ipbuf_l = .-ipbufmbbuf: .blkb 2048mbbuf_l = .-mbbufmbiosb: .blkw 4ipiosb: .blkw 4ipchan: .blkwerrchan: .word 0errport: .blkl%inmbxname_d: descriptor inmbxname, 16inmbxname: .blkb 16'outmbxname_d: descriptor outmbxname, 16outmbxname: .blkb 16:inmbx_itmlst: item DVI$_DEVNAM, 16, inmbxname, inmbxname_d .long 0=outmbx_itmlst: item DVI$_DEVNAM, 16, outmbxname, outmbxname_d .long 0inmbxchan: .blkwoutmbxchan: .blkwiosb: .blkw 4readstrpos: .long 0readstrbuf: .blkb 2048$cmdlen: .blkl ; Length of commandcvt_d: descriptor readstrbufip: .ascid "INET$DEVICE:"ip0: .ascid "IP0:"4terminator: .byte 0 ; Termination byte for READSTR nul: .byte 0/locuser: .ascid "xxxxxxxxxxxx" ; Local usercode0remuser: .ascid "xxxxxxxxxxxx" ; Remote usercode(remhost: descriptor 1$, 64 ; Remote host 1$: .blkb 64%remport: .blkl ; Remote port number(remoteip: .blkl ; IP address of remotelf = 101badlogin: .ascii "User authorization failure"badlogin_l = .-badlogin5daemon_cmd: .ascii "@CMUIP_ROOT:[sysexe]RSHD_CMD.COM"daemon_cmd_l = .-daemon_cmd & .sbttl "Initialisation & Handshaking"' .psect RLOGIND_RE, long, exe,nowrt,shr .entry rlogind, ^M;; Accept connection in port 514;" $ASSIGN_S chan=ipchan, devnam=ip status R0, abort9 $QIOW_S chan=ipchan, iosb=iosb, func=#NET$OPEN, p3=#514% status R0, abort ; Connect to host cmustat iosb, abort;&; Get remote host name and port number; pushal remoteip pushal remport pushaq remhost movzwl ipchan, -(SP) calls #4, g^GETREMHOST status R0, abort;7; Check if port is privileged (<1024), reject otherwise; cmpl remport, #1024 blss 1$7 $QIOW_S chan=ipchan, iosb=iosb, func=#NET$CLOSE, p1=0 movl #SS$_ABORT, R0 brw abort;D; Begin handshake -- get error port number and make connection to itI; We do this just to make the remote rsh happy, we don't actually use theH; error channel (since VMS stuffs error messages down both SYS$INPUT and"; SYS$ERROR if they're different).;; Handshake format:8; errport 00 remote-user 00 local-username 00 command 00;&1$: bsbw readstr ; Read port number movw R0, cvt_d pushal errport pushaq cvt_d/ calls #2, g^OTS$CVT_TU_L ; Convert to integer tstl errport bneq 13$ brw 14$ *13$: $ASSIGN_S chan=errchan, devnam=ip0  status R0, abort movl #1023, R2811$: $QIOW_S chan=errchan, iosb=iosb, func=#NET$OPEN, -/ p1=remoteip, p2=errport, p3=R2, p4=#7, p6=#0+ status R0, abort ; Connect error channel6 cmpl iosb+4, #NET$_NUC ; If not unique, try a lower bneq 12$ ; port number decl R2" cmpl R2, #512 ; Minimum is 512 bgtr 11$12$: status iosb, abort14$:;=; Get authorisation part of handshake and command to execute.;" bsbw readstr ; remote username movw R0, remuser, movc5 R0, readstrbuf, #32, #12, @remuser+4! bsbw readstr ; local username movw R0, locuser, movc5 R0, readstrbuf, #32, #12, @locuser+4 pushaq locuser pushaq locuser calls #2, g^STR$UPCASE bsbw readstr ; command movl R0, cmdlen;*; Send acknowledgement of connection (nul);? $QIOW_S chan=ipchan, iosb=iosb, func=#NET$SEND, p1=nul, p2=#1 status R0, abort cmustat iosb, abort;; Do we know this person?; pushaq locuser pushaq remuser pushaq remhost calls #3, g^RAUTHORIZE blbs R0, 2$3 $QIOW_S chan=ipchan, iosb=iosb, func=#NET$SEND, - p1=badlogin, p2=#badlogin_l status R0, abort cmustat iosb, abort brw abort ;M; Yes? We need to create the mailboxes with the user as the owner, and startN; a process under that usercode. STARTLOGIN, SETUIC & RESETUIC are privileged%; routines to do the necessary magic.;2$: pushaq locuser( calls #1, g^SETUIC ; Set UIC to owner status R0, abort9 $CREMBX_S chan=inmbxchan, bufquo=#2048, maxmsg=#2048, - promsk=#^xFF00* status R0, abort ; Create input mailbox: $GETDVI_S chan=inmbxchan, itmlst=inmbx_itmlst, iosb=iosb* status R0, abort ; Find its device name status iosb, abort: $CREMBX_S chan=outmbxchan, bufquo=#2048, maxmsg=#2048, - promsk=#^xFF00+ status R0, abort ; Create output mailbox< $GETDVI_S chan=outmbxchan, itmlst=outmbx_itmlst, iosb=iosb* status R0, abort ; Find its device name status iosb, abort& calls #1, g^RESETUIC ; Put UIC back pushab finished pushaq outmbxname_d pushaq inmbxname_d( pushaq locuser ; And start a process calls #4, g^STARTLOGIN status R0, abort;; Start things rolling. G; We get the output mailbox reading immediately, in case there's outputH; to handle before we complete the handshake. Then send the DCL command=; to start the wrapper, then send the command to the wrapper.;N; The wrapper's aim in life is simply to make sure one command and one commandM; only gets executed, and the process is then wrapped up silently and surely.;$ jsb mbqio ; Start reading output; $QIOW_S chan=inmbxchan, iosb=iosb, func=#IO$_WRITEVBLK, -" p1=daemon_cmd, p2=#daemon_cmd_l1 status R0, abort ; Send the command to run the) status iosb, abort ; wrapper procedure; $QIOW_S chan=inmbxchan, iosb=iosb, func=#IO$_WRITEVBLK, - p1=readstrbuf, p2=cmdlen. status R0, abort ; Send the command to the  status iosb, abort ; wrapper 8 .sbttl "Main Loop, read lines from IP, send to mailbox"6 movb #lf, terminator ; Set readstr terminator to LF#loop: bsbw readstr ; Read a line tstl R0 ; EOF or shutdown? blss 1$= $QIOW_S chan=inmbxchan, iosb=ipiosb, func=#IO$_WRITEVBLK, - p1=readstrbuf, p2=R0 status R0, abort movzwl ipiosb, R0) cmpw R0, #SS$_ABORT ; Abort or cancel?' beql 2$ ; Go sit in the corner.... cmpw R0, #SS$_CANCEL beql 2$ status R0, abort brb loop/1$: cmpl R0, #-2 ; If terminating, then skip beql 2$ ; the mailbox EOFA $QIOW_S chan=inmbxchan, iosb=ipiosb, func=#IO$_WRITEOF!IO$M_NOW ; Send EOF to mailbox% ; Don't care about IOSB here...+2$: $HIBER_S ; ... and sleep 0 status R0, abort ; till everything else stops brb 2$ abort: ret & .sbttl Read from mailbox, send to IP;L; AST to handle incoming data from mailbox and transmit it to the IP channel; .entry mbast, ^M<> movzwl mbiosb, R04 cmpl R0, #SS$_ENDOFFILE ; If EOF we're done here. beql 2$8 cmpl R0, #SS$_CANCEL ; Ignore cancelled or aborted IO beql 1$ cmpl R0, #SS$_ABORT bneq 3$1$: ret42$: brw finished_b ; mutter mutter byte-relative  ; branches mutter mutter(3$: status R0, astabort ; Check status" movzwl mbiosb+2, R0 ; R0=length0 movb #lf, mbbuf(R0) ; Append a LF to the line incl R0( $QIOW_S chan=ipchan, func=#NET$SEND, - iosb=mbiosb, p1=mbbuf, p2=R03 status R0, astabort ; Send it to the remote user status mbiosb, astabort bsbb mbqio ; Queue new read ret ; Done;; Queue a read to the PTY;Cmbqio: $QIO_S chan=outmbxchan, astadr=mbast, func=#IO$_READVBLK, -' iosb=mbiosb, p1=mbbuf, p2=#mbbuf_l-1 status R0, astabort rsb  .sbttl Cleanup code .entry finished, ^M<>!finished_b: $CANCEL_S chan=ipchan7 $QIOW_S chan=ipchan, iosb=iosb, func=#NET$CLOSE, p1=0 ; Close IP connection+ $DASSGN_S chan=ipchan ; Close IP channel& tstw errchan ; Error channel open? beql 1$8 $QIOW_S chan=errchan, iosb=iosb, func=#NET$CLOSE, p1=0 ; Close error connection/ $DASSGN_S chan=errchan ; Close error channel/1$: $DASSGN_S chan=inmbxchan ; Close mailboxes $DASSGN_S chan=outmbxchan pushl #SS$_NORMAL 7 calls #1, g^SYS$EXIT ; And exit with saved ret. code ret ; yeahright4astabort: pushl R0 ; Put return code on stack for  ; SYS$EXIT& calls #0, finished ; Close channels7 calls #1, g^SYS$EXIT ; And exit with saved ret. code ret ; yeahright 8 .sbttl "Read nul/LF terminated strings from IP channel";!; Read strings until nul received;1readstr: pushr #^M ; Save regs0 movl readstrpos, R7 ; R7 = position in buffer! beql 2$ ; 0? Read some more., movl R7, R0 ; If EOF, return -1 (already blss 98$ ; in R7).31$: locc terminator, R7, ipbuf ; Find a terminator' beql 2$ ; R1=address of terminator# ; not found -> read some more- subl3 #ipbuf, R1, R6 ; R6=length of string$ movl R0, R7 ; R7=remaining bytes! decl R7 ; ... minus 1; movc3 R6, ipbuf, readstrbuf ; Copy string into readstrbuf? movc3 R7, ipbuf+1(R6), ipbuf ; Copy remainder to start of buf$ movl R7, readstrpos ; Save length movl R6, R0 ; Return length698$: popr #^M ; Done, restore regs rsb-2$: movl R7,R0 ; Come here if we need more* subl3 R0, #ipbuf_l, R0 ; Buffer o/flow? blss 98$8 $QIOW_S chan=ipchan, iosb=ipiosb, func=#NET$RECEIVE, -' p1=ipbuf(R7), p2=R0 ; Read some more status R0, 99$( cmpl ipiosb+4, #NET$_CCAN ; Cancelled? beql 31$ ; Treat like EOF% cmpl ipiosb+4, #NET$_CC ; Closing? beql 31$ ; Treat like EOF cmustat ipiosb, 99$ cvtwl ipiosb+2, R0 ; EOF? beql 3$$ addl2 R0, R7 ; Return new length brw 1$3$: tstl R7 ; Empty buffer?+ bneq 4$ ; Yup, just signal EOF & we're movl #-1, R0 ; finished here brw 98$431$: movl #-2, R0 ; Killed off by other thread... brw 98$>4$: movc3 R7, ipbuf, readstrbuf ; Copy string into readstrbuf' movl R7, R0 ; return current length7 movl #-1, readstrpos ; Signal EOF the next time thru brw 98$99$: brw abort) .end rlogind ; Er, that's all, folks!*[SRC.RLOGIN.DIST]RSHD.OBJ;1+,G C. /h 4 @- 0123KPWO 56+oX7`0 $GETDVIW_S devnam=@4(AP), itmlst=getdvi_itmlst$ blbc R0, 99$ ; Check terminal out movl #SS$_IVDEVNAM, R0 cmpl #DC$_TERM, dvi_devclass  bneq 99$ ; Terminal?+ bbc #UCB$V_ONLINE, dvi_sts, 99$ ; Online?. bbs #UCB$V_TEMPLATE, dvi_sts, 99$; Template? movq @8(AP), accpornam_d8 cmpw accpornam_d, #63 ; If >63 chars long, trunc to 63 blss 1$ movw #63, accpornam_d%1$: $CMKRNL_S routin=set_accpornam_k 99$: ret< .entry set_accpornam_k, ^M movl g^CTL$GL_PCB, R45 jsb g^SCH$IOLOCKW ; Lock the I/O database for write movab dvi_devnam_d, R1' jsb g^IOC$SEARCHDEV ; Find the device blbc R0, 99$ movl R1, R5 ; R5=UCB address, cmpw UCB$W_SIZE(R5), #UCB$L_TT_ACCPORNAM+4 blssu 99$ ; UCB big enough?" movl UCB$L_TT_ACCPORNAM(R5), R2 # ; R2=ACCPORNAM buffer address - blss 1$ ; If LSS use the one that's there * bbs #UCB$V_DELETEUCB, UCB$W_STS(R5), 99$) ; If ephemeral device, do not create+ ; buffer else pool lossage will happen movl #64, R16 jsb g^EXE$ALONPAGVAR ; Get pool for ACCPORNAM buffer# blbc R0, 99$ ; R2=buffer address" movl R2, UCB$L_TT_ACCPORNAM(R5)  ; link to UCB3 bbss #TTY$V_PC_ACCPORNAM, UCB$W_TT_PRTCTL(R5), 1$ ; Say we've done it)1$: movzwl accpornam_d, R0 ; Get length 3 movb R0, (R2)+ ; Place at start of ACCPORNAM buf movc3 R0, @accpornam_d+4, (R2) ; Store ACCPORNAM2$: pushl #SS$_NORMAL movl g^CTL$GL_PCB, R4. jsb g^SCH$IOUNLOCK ; Unlock the I/O database popl R0 ret99$: pushl #SS$_DEVREQERR brb 2$ .end$*[SRC.RLOGIN.DIST]SET_ACCPORNAM.OBJ;1+,N ./h 4<- 0123KPWO56 |X7|R`89GhHJ7 SET_ACCPORNAM0 3-DEC-1995 22:38 VAX MACRO T5.2V-4MAC SET_ACCPORNAMSet Access Port Name in UCB SET_ACCPORNAMu CTL$GL_PCBEXE$ALONPAGVAR IOC$SEARCHDEV SCH$IOLOCKW SCH$IOUNLOCK SYS$CMKRNL SYS$GETDVIWSYS$SYSTEM:SYS.STB . ABS .P$ABS$PPPPPPSET_ACCPORNAM_RWVP04@8xQQQ@8QSET_ACCPORNAM_REP  SET_ACCPORNAM&|~<~ SYS$GETDVIWPKЏDPяB074/ 4'}??l SYS$CMKRNL lSET_ACCPORNAM_K& CTL$GL_PCBT SCH$IOLOCKWxQ IOC$SEARCHDEVPWQU\LXR x@Џ@QEXE$ALONPAGVARP0RX ><PP(P3b CTL$GL_PCBT SCH$IOUNLOCKЎPݏ46 SET_ACCPORNAMlSET_ACCPORNAM_K>SET_ACCPORNAM_RWSET_ACCPORNAM_RE!*[SRC.RLOGIN.DIST]STARTLOGIN.MAR;1+, . /h 4H L- 0123KPWO 56WRW>7PS`89GhHJ. .title STARTLOGIN Start a login on a terminal;6; STARTLOGIN [username], input [, output [, astadr ]]; SETUIC username ; RESETUIC;'; Kernel mode hacky stuff is in here. ; .library "SYS$LIBRARY:LIB.MLB" $UAIDEF $PRCDEF $DVIDEF $PCBDEF $JIBDEF $ACCDEF $SSDEF .macro debug pushl #SS$_DEBUG calls #1, g^LIB$SIGNAL .endm .macro status stat, dest, ?L1 blbs stat, L1' .iif idn ,, movzwl stat, R0 debug brw dest L1: .endm, .macro item code, buflen, address, lenadr=0 .word buflen .word code .long address .long lenadr .endm+ .psect STARTLOGIN_RW, long,noexe,wrt,noshr*loginout: .ascid "SYS$SYSTEM:LOGINOUT.EXE"Hdvi_itmlst: item DVI$_REFCNT, 4, dvi_refcnt ; Itemlst to get refcnt from item 0,0,0 ; devicedvi_refcnt: .blkl>uai_itmlst: item UAI$_UIC, 4, uai_uic ; Itmlst to get UIC for # item 0,0,0 ; specified usermameuai_uic: .blkl ; UICsave_uic: .blkl ; Saved UIC)a_tick: .float 0.1 ; Period to wait...)our_username: .blkb 12 ; Saved username<prcnam_d_t: .ascid "xxxxxxxxxxxxxxx" ; Process name template(prcnam_d: .blkq ; Actual process name+prcnam_temp: .blkq ; Base part of prcnam=prcnam_fao: .ascid "!AS#!ZL" ; FAO to construct process name.mbxchan: .blkl ; Channel for completion mbx'mbx_itmlst: item DVI$_UNIT, 4, mbx_unit .long 0(mbx_unit: .blkl ; Mailbox unit numbermbx_iosb: .blkw 4accblk: .blkb ACC$K_TERMLEN  .sbttl "Start a login";8; stat = STARTLOGIN [username], input [, output, error ];) .psect STARTLOGIN_RE, long,exe,nowrt,shr username = 4input_file = 8output_file = 12 astadr = 16# .entry STARTLOGIN, ^M$ movl #PRC$M_INTER!PRC$M_DETACH, R5 ; R5=$CREPRC flags+ movl input_file(AP), R2 ; R2=output file! clrl mbx_unit ; clear mailbox# movq @input_file(AP), prcnam_temp" ; Use device as process name# ; in case username is no good- tstl username(AP) ; If username specified,( beql 4$ ; set user to that username( $CMKRNL_S routin=set_user, arglst=(AP) status R0, 99$ callg (AP), SETUIC status R0, 99$5 movl #PRC$M_INTER!PRC$M_NOPASSWORD!PRC$M_DETACH, R5# ; and add NOPASSWORD to flags, cmpl (AP), #3 ; Is this a batch startup? blss 1$ movl output_file(AP), R2) movl #PRC$M_NOPASSWORD!PRC$M_DETACH, R5! cmpl (AP), #4 ; AST required? blss 1$ bsbw setup_ast !1$: movq @username(AP), prcnam_d! movq @username(AP), prcnam_temp clrl R4D4$: $CREPRC_S image=loginout, input=@input_file(AP), output=(R2), -9 prcnam=prcnam_d, baspri=#4, stsflg=R5, mbxunt=mbx_unit cmpw R0, #SS$_DUPLNAM bneq 5$# incl R4 ; Count upwards from 1 movq prcnam_d_t, prcnam_d> $FAO_S ctrstr=prcnam_fao, outbuf=prcnam_d, outlen=prcnam_d -: p1=#prcnam_temp, p2=R4 ; Format process name username_n status R0, 99$ brb 4$&5$: movl R0,R2 ; Create the process( tstl username(AP) ; If user specified- beql 2$ ; set username back like it wuz. $CMKRNL_S routin=reset_user calls #0, RESETUIC2$: status R2, 99$/ cmpl (AP), #4 ; Detached login doesn't need beql 99$ ; to wait movl #100, R2,3$: decl R2 ; Now hang around until that& beql 98$ ; process has siezed the - pushaf a_tick ; terminal, so we don't get0 calls #1, g^LIB$WAIT ; multiple logins on it.5 $GETDVI_S devnam=@input_file(AP), itmlst=dvi_itmlst status R0, 99$/ tstl dvi_refcnt ; Do this by peeking at the beql 3$ ; refcount 99$: ret"98$: movl #SS$_ABORT, R0 ; done. ret4setup_ast: $CREMBX_S chan=mbxchan, promsk=#^xFF00, -/ bufquo=#ACC$K_TERMLEN, maxmsg=#ACC$K_TERMLEN% status R0, 99$ ; Create a mailbox+ $GETDVI_S chan=mbxchan, itmlst=mbx_itmlst$ status R0, 99$ ; Get its unit no; $QIO_S chan=mbxchan, iosb=mbx_iosb, func=#IO$_READVBLK, -" p1=accblk, p2=#ACC$K_TERMLEN, -) astadr=complete_ast, astprm=astadr(AP)' status R0, 99$ ; Queue a read to it 99$: rsb .entry complete_ast, ^M<> $DASSGN_S chan=mbxchan movl 4(AP), R0 tstw (R0)+ ; addl2 #2, R0# movl accblk+ACC$L_FINALSTS, 4(AP) jmp (R0);2; Kernel routine to set user name, saving old name;C .entry set_user,^m ; CMKRNL has pointed R4 at PCB., movl PCB$L_JIB(R4), R6 ; Point R6 at JIB.: movc3 #JIB$S_USERNAME, JIB$T_USERNAME(R6), our_username  movl username(AP), R0> movc5 (R0), @4(R0), #32, #JIB$S_USERNAME, JIB$T_USERNAME(R6)# ; Copy new username passed in- movl #SS$_NORMAL, R0 ; to JIB$T_USERNAME. ret;*; Kernel routine to restore saved username;E .entry reset_user,^m ; CMKRNL has pointed R4 at PCB.+ movl PCB$L_JIB(R4), R6 ; Point R6 at JIB.9 movc3 #JIB$S_USERNAME, our_username, JIB$T_USERNAME(R6)# ; Copy new username passed in- movl #SS$_NORMAL, R0 ; to JIB$T_USERNAME. ret  .sbttl "Set and reset UIC";; stat = SETUIC( username )4; string username by desc User name of UIC to set to; .entry setuic, ^m<>, $GETUAI_S usrnam=@4(AP), itmlst=uai_itmlst blbc R0, 99$ ; Get UIC% $CMKRNL_S routin=setuic_k ; Set UIC 99$: ret0 .entry setuic_k, ^M<> ; Kernel code for SETUIC1 movl PCB$L_UIC(R4), save_uic ; Save current UIC+ movl uai_uic, PCB$L_UIC(R4) ; Set new UIC movl #SS$_NORMAL, R0 ret;; stat=RESETUIC(); .entry resetuic, ^m<>) $CMKRNL_S routin=resetuic_k ; Reset UIC ret .entry resetuic_k, ^M<>* movl save_uic, PCB$L_UIC(R4) ; Reset UIC movl #SS$_NORMAL, R0 ret .end!*[SRC.RLOGIN.DIST]STARTLOGIN.OBJ;1+,n K./h 4- 0123KPWO56oX7/S`89GhHJ4 STARTLOGIN0 3-DEC-1995 22:38 VAX MACRO T5.2V-4MAC STARTLOGINStart a login on a terminal STARTLOGIN IO$_READVBLK LIB$SIGNALLIB$WAIT SYS$CMKRNL SYS$CREMBX SYS$CREPRC SYS$DASSGNSYS$FAO SYS$GETDVI SYS$GETUAISYS$QIO . ABS .P$ABS$PPPPPPP STARTLOGIN_RW P3SYS$SYSTEM:LOGINOUT.EXEQ&Q7QSQQ>Q o3xxxxxxxxxxxxxxxQ&QQQ3!AS#!ZLQ&Q Q QQQT  STARTLOGIN_REP< < STARTLOGIN&ЏUЬR}լsls SYS$CMKRNLP