.TITLE SET_PRCNAM .IDENT /03-000/ ; ; Copyright 1991 by Hunter Goatley. This code may be freely distributed ; and modified for non-commercial purposes as long as this copyright notice ; is retained. ; ;++ ; ; Facility: SET_PRCNAM ; ; Author: Hunter Goatley ; ; Date: August 13, 1986 ; ; Functional Description: ; ; This program will set the process name for any process on the system. ; ; An exercise for learning about the PCB vector table and what ; information is stored for each active process. ; ; Very little (if any) practical use. ; ; Modified by: ; ; 03-000 Hunter Goatley 28-APR-1991 08:13 ; Rewrite for DECUS seminar. ; ; 02-000 Hunter Goatley 2-AUG-1988 11:42 ; Converted for use under VMS V5.0. ; ; 01-000 Hunter Goatley August 13, 1986 ; Original version. ; ;-- .SUBTITLE Data area .LIBRARY /SYS$LIBRARY:LIB.MLB/ .LINK "SYS$SYSTEM:SYS.STB"/selective_search .DSABL GLOBAL ; Declare external references .ENABL SUPPRESSION ; Don't list unreferenced syms .NOSHOW BINARY ; Turn off binary in listings ; ; External system routines: ; .EXTRN LIB$GET_INPUT ; Read from SYS$INPUT .EXTRN OTS$CVT_TZ_L ; Convert ASCII to hex ; ; Global variables used here: ; .EXTRN SCH$GL_PIXWIDTH ; Width of PIX field in EPID .EXTRN SCH$GL_PCBVEC ; Vector of PCB address .EXTRN SCH$GL_MAXPIX ; Maximum PIX for system .EXTRN SCH$GL_SWPPID ; PID of SWAPPER process .EXTRN SCH$AR_NULLPCB ; PCB address for NULL process $DSCDEF ; Descriptor symbols $PHDDEF ; Process header symbols $PCBDEF ; Process control block symbols $SSDEF ; System service status symbols .SHOW BINARY ; Include binary in listings .PSECT _SET_PRCNAM_DATA,NOEXE,WRT,LONG,SHR PRCNAM_D: .WORD PCB$S_LNAME-1 ; New process name descriptor .BYTE DSC$K_DTYPE_T ; ... .BYTE DSC$K_CLASS_S ; ... .ADDRESS .+4 ; ... .BLKB PCB$S_LNAME ; ... Buffer EPID_D: .WORD 8 ; ASCII PID descriptor .BYTE DSC$K_DTYPE_T ; ... .BYTE DSC$K_CLASS_S ; ... .ADDRESS .+4 ; ... .BLKB 8 ; ... Buffer EPID: .LONG 0 ; The PID of the target process PID_PROMPT: .LONG 3 ; LIB$GET_INPUT argument list .ADDRESS EPID_D ; ... Buffer to receive PID .ADDRESS 10$ ; ... The prompt .ADDRESS EPID_D ; ... Buffer to receive length 10$: .ASCID /Enter the PID of the target process: / PRCNAM_PROMPT: .LONG 3 ; LIB$GET_INPUT argument list .ADDRESS PRCNAM_D ; ... Buffer to receive name .ADDRESS 10$ ; ... The prompt .ADDRESS PRCNAM_D ; ... Buffer to receive length 10$: .ASCID /Enter the new process name: / CVTPID: .LONG 2 ; OTS$CVT_TZ_L argument list .ADDRESS EPID_D ; ... ASCII PID address .ADDRESS EPID ; ... Hex PID address KSET_ARGS: .LONG 2 ; KERNEL_SET_PRCNAM arg. list .ADDRESS EPID ; ... The PID to change .ADDRESS PRCNAM_D ; ... The new process name ; ; The code PSECT is left writable so we can copy the process name to a ; temporary buffer in this PSECT. ; .PSECT _SET_PRCNAM_CODE,EXE,WRT,LONG,PIC,SHR .ENTRY SET_PRCNAM,^M CALLG PID_PROMPT,G^LIB$GET_INPUT ; Get the target process's PID BLBC R0,10$ ; Branch on error CALLG CVTPID,G^OTS$CVT_TZ_L ; Convert PID from ASCII to hex BLBC R0,10$ ; Branch on error CALLG PRCNAM_PROMPT,G^LIB$GET_INPUT ; Get the new process name BLBC R0,10$ ; Branch on error $CMKRNL_S - ; Go to kernel mode to change ROUTIN=KERNEL_SET_PRCNAM,- ; ... the process name ARGLST=KSET_ARGS ; ... 10$: RET ; Return to caller .PAGE .SUBTITLE KERNEL_SET_PRCNAM routine ;+ ; ; Routine: KERNEL_SET_PRCNAM ; ; Functional description: ; ; This routine executes in kernel mode to change the process name ; for a specified process. It accesses the PCBs for all processes ; in the system via the PCB vector table in system memory. The ; name cannot be set if a if another member of the target process's ; group has the same name. ; ; Inputs: ; ; 4(AP) - Address of the EPID of the target process ; 8(AP) - Descriptor address for the new process name ; ; Implicit inputs: ; ; SCH$GL_PCBVEC, SCH$GL_MAXPIX, SCH$GL_PIXWIDTH ; ; Outputs: ; None. ; ; Returns: ; ; R0 - Status ; SS$_NORMAL - Routine successfully completed ; SS$_DUPLNAM - The specified name duplicates one ; already specified within that group ; SS$_NONEXPR - Nonexistent process (there was no ; process matching the specified PID) ; ;+ KSP_PID = 4 KSP_NAM = 8 .ENTRY KERNEL_SET_PRCNAM,^M ; ; To avoid having to lock down the data area containing the new process ; name, copy it to the space provided at the end of this routine. This ; buffer will be faulted-in via the "poor-man's lockdown", ensuring that ; its access won't cause a pagefault. Note that it is stored as ASCIC. ; MOVL KSP_NAM(AP),R0 ; Get the descriptor address MOVAB 130$,R2 ; Load address of temp. buffer MOVZWL (R0),R1 ; Get length of process name CMPW #,R1 ; Is the name too long? BGEQU 10$ ; Branch if it's OK MOVL #,R1 ; Set the maximum length 10$: MOVL 4(R0),R0 ; R3 -> string itself MOVB R1,(R2)+ ; Store the length byte 20$: MOVB (R0)+,(R2)+ ; Copy the string to temp SOBGTR R1,20$ ; Loop until all copied MOVL @KSP_PID(AP),R6 ; Copy the target PID to R6 ; ; Our PCB address is still in R4 ($CMKRNL put it there). ; ; Fault in the critical code and grab the SCHED (scheduler) spinlock. ; 30$: .IF DEFINED PCB$L_CPU_ID ; - VMS V5.x code TSTB 140$ ; Fault in critical code LOCK LOCKNAME=SCHED,- ; Grab the Scheduler spinlock SAVIPL=-(SP) ; ... and raise the IPL .IFF ; - VMS V4.x code DSBINT 140$ ; Disable interrupts .ENDC ; .IF ; ; Get the group number of the target process ; TSTL R6 ; Was a target PID specified? BNEQ 40$ ; If PID ^= 0, go look for PCB MOVL PCB$L_EPID(R4),R6 ; If 0, use current process PCB 40$: MOVL G^SCH$GL_PIXWIDTH,R0 ; Get the width (in bits) of the ; ... process index MOVL G^SCH$GL_PCBVEC,R7 ; Get the PCB vector table addr ; ; We could JSB G^EXE$EPID_TO_IPID to convert the PID from an EPID to IPID, ; but it's not necessary. We can compare the specified EPID with the EPID in ; the target PCB. ; EXTZV #0,R0,R6,R5 ; Get the process index CMPL G^SCH$GL_MAXPIX,R5 ; Is the process index > max? BLSSU 50$ ; Yes -- not valid PID CMPW G^SCH$GL_SWPPID,R5 ; NULL and SWAPPER are illegal BGEQ 50$ ; ... Branch to return error MOVL (R7)[R5],R0 ; Get the target PCB address CMPL PCB$L_EPID(R0),R6 ; Compare the two PIDs BEQL 60$ ; If not equal, nonexistent proc 50$: BRW 110$ ; Branch to return error 60$: MOVZWL PCB$W_GRP(R0),R3 ; Get the target group number ; ; Check to make sure the new process name does not duplicate one already ; used by a member of the same group. This is accomplished by stepping ; through the PCB vector table and comparing the new name with the name ; of each process belonging to the PID process's group. ; MOVL G^SCH$GL_MAXPIX,R4 ; Get the maximum proc index ; ; Start searching at the bottom of the vector table ; 70$: MOVL (R7)[R4],R0 ; Get a PCB address CMPL G^SCH$AR_NULLPCB,R0 ; Point to NULL? BEQL 90$ ; Yes---no need to check it CMPW PCB$W_GRP(R0),R3 ; Is the process in target grp? BNEQ 90$ ; No -- try next PCB ; ; Here, we've found another process in this group. Compare the process ; names to make sure we there's no conflict. ; CMPL R0,R6 ; Is it the target process? BEQL 90$ ; Branch if so; no need to check MOVAB 130$,R1 ; Point to temp. buffer MOVZBL (R1)+,R2 ; Get the length MOVAB PCB$T_LNAME(R0),R0 ; Point to the name CMPB R2,(R0)+ ; Are the lengths the same BNEQ 90$ ; No? Try next PCB 80$: CMPB (R1)+,(R0)+ ; Compare each byte in names BNEQ 90$ ; Branch when not equal SOBGTR R2,80$ ; Loop until all bytes compared MOVL #SS$_DUPLNAM,R0 ; No -- duplicate name BRB 120$ ; Return to caller 90$: SOBGTR R4,70$ ; Loop until all PCBs checked ; ; If here, valid PID AND no duplicate names ; MOVL (R7)[R5],R0 ; Get the PCB address of target CMPL PCB$L_EPID(R0),R6 ; Do the PIDs still match? ; (Has the process been deleted ; ... before we got here?) BNEQ 110$ ; No -- nonexistent process MOVAB 130$,R1 ; R1 -> new process name MOVZBL (R1),R3 ; Get the length MOVAB PCB$T_LNAME(R0),R2 ; R2 -> process name in PCB 100$: MOVB (R1)+,(R2)+ ; Copy the prc name to the PCB SOBGEQ R3,100$ ; Loop until all copied MOVZWL #SS$_NORMAL,R0 ; Set normal status BRB 120$ ; Return to caller 110$: MOVZWL #SS$_NONEXPR,R0 ; Set non-existent process msg 120$: .IF DEFINED PCB$L_CPU_ID ; - VMS V5.x code UNLOCK LOCKNAME=SCHED,- ; Release the scheduler spinlock NEWIPL=(SP)+,- ; ... and lower IPL CONDITION=RESTORE ; ... .IFF ; - VMS V4.x code ENBINT ; Enable interrupts .ENDC ; .IF RET ; Return to caller 130$: .BLKB PCB$S_LNAME ; Space for the new process name 140$: .LONG IPL$_SYNCH ; Synchronization IPL ASSUME <.-30$> LE 512 ; Make sure it's all one page .END SET_PRCNAM