zrgc002@DTUPEV5A.BITNET.UUCP (07/10/87)
With my last request to info-vax I causes some misundestanding, it was totally my fault. But thanks to many who have pointed into the right direction, here comes the program: This program will read somebody else's recall buffer as far as possible, that means not only 20 lines, but the whole 1024. This way you may well jeopardize the last rest of privacy, thus its use is discouraged. Christoph Gatzka zrgc002@dtupev5a.bitnet $ create readme.doc ALWAYS REMEMBER THAT THERE ARE SYSTEM POSITION DEPENDENCIES IN THIS CODE. SEE BELOW ! THIS WILL RUN ON VMS 4.3 ONLY ! I am very interested in obtaining the correct addresses for the other system versions, would you send mail to zrgc002@dtupev5a.bitnet ? $ type readme.doc $ create ussgetrec.mar .title USSGETDD Get Default Directory String .ident "V01" ; ;**************************************************************************** ;* * ;* COPYRIGHT (c) 1980 * ;* BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. * ;* * ;* THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED * ;* ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE * ;* INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER * ;* COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY * ;* OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY * ;* TRANSFERRED. * ;* * ;* THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE * ;* AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT * ;* CORPORATION. * ;* * ;* DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS * ;* SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL. * ;* * ;**************************************************************************** ; ; This sample program has been modified by zrgc002@dtupev5a.bitnet (Christoph ; D. Gatzka) to print a copy of another user's recall buffer. The problem ; is that there are version dependant offsets used in ctl$ag_clidata. ; ; They can be obtained using analyze/system. Do an 'examine ctl$ag_clidata;700' ; you will find somewhere your recall buffer. Now go some bytes back and you ; will find a pointer into the recall buffer as an absolute address. This ; address should point to a longword of value '0'. Now you have found both ; base_index and base_data. Fill your recall buffer with some large commands ; now. It should fill up the next HeX400 bytes. This is length_data. base_index = ^x2af ; this is the pointer to the last command ; saved base_data = ^x2b3 ; this is the start of recall buffer data length_data= ^x401 ; this is the length of the recall buffer ;++ ; ; Facility: ; ; This is an exqmple of a user written system service that obtains ; the default directory string from any process. ; ; Environment: ; ; The procedure executes in kernel mode to queue the special AST ; to the specified process. A special AST is also used to return the ; information to the requesting process. ; ; Author: ; ; Larry Kenah ; ; Creation Date: ; ; 15 July 1980 ; ; Revisions: ; ; Nothing Yet ; ;-- .page .subtitle Declarations .LIBRARY /SYS$LIBRARY:LIB.MLB/ ; ; Include files: ; $ACBDEF ;AST Control Block definitions $DYNDEF ;Data structure type codes $IPLDEF ;Synchronization IPL values $PCBDEF ;Software PCB fields $PHDDEF ;Process Header fields $PRIDEF ;Priority boost class $PSLDEF ;Fields in PSL ; ; Define Extended AST Control Block ; $DEFINI ACB . = ACB$L_KAST + 4 $DEF ACB_L_GET_AST ;Address of GET AST in nonpaged pool .BLKL 1 $DEF ACB_L_PUT_AST ;Address of PUT AST in nonpaged pool .BLKL 1 $DEF ACB_L_DDDESC ;Store address of data descriptor .BLKL 1 $DEF ACB_L_EFN ;Save event flag number .BLKL 1 $DEF ACB_L_IOSB ;Save address of status block .BLKL 1 $DEF ACB_L_OLD_PID ;Save PID of requester .BLKL 1 $DEF ACB_L_IMGCNT ;Store image count for synchronization .BLKL 1 $DEF ACB_L_REC_INDEX ;This will store the index into REC_DATA .BLKL 1 $DEF ACB_T_REC_DATA ;This is the recall buffer data from .BLKB LENGTH_DATA ;the target process $DEF ACB_K_NEW_LEN ;Symbol for extended length ACB_K_STR_LEN = ACB_K_NEW_LEN - <ACB_L_REC_INDEX + 1> $DEFEND ACB ; ; Arguement List Definition (patterned after $GETJPI) ; EFN = 4 ;Event flag number PIDADR = 8 ;Address of process ID PRCNAM = 12 ;Address of process name descriptor DDDESC = 16 ;Address of three longword descriptor ; that describes destination of data IOSB = 20 ;Address of longword that receives ; final status ASTADR = 24 ;AST address for notification ASTPRM = 28 ;AST parameter ; ; Define special type field codes for blocks containing AST code ; dyn_k_get_ast = ^x80 - 2 dyn_k_put_ast = ^x80 - 3 .page .subtitle USS_GETDD Get Default Directory String Procedure ;++ ; ; Functional Description: ; ; This procedure obtains the default directory string for any process ; in the system. The method used parallels the $GETJPI system service. ; A special kernal AST is delivered to the target process, where the ; default directory string is copied from its P1 space location to ; the extended AST control block. That block is then used to deliver ; another AST back to the requesting process. ; ; Input Parameters: ; ; EFN(AP) Number of event flag to set when the requested ; information is available. ; ; PIDADR(AP) Address of longword containing the process ID of the ; process for which the information is being requested. ; ; PRCNAM(AP) Address of the string descriptor for the process name ; of the process for which the information is being ; requested. ; ; DDDESC(AP) Address of three longword descriptor that describes ; where information will be stored. ; ; +-------------------------------+ ; | spare | Buffer Length | ; +-------------------------------+ ; | Buffer Address | ; +-------------------------------+ ; | Address to Return Length | ; +-------------------------------+ ; ; IOSB(AP) Used by the kernel AST to report errors back to ; the original caller that cannot be detected in ; the initial procedure. One such error might be ; a protection change in the user's buffer. ; ; ASTADR(AP) Address of an AST that will be called when all of ; the requested data has been supplied. ; ; ASTPRM(AP) Parameter that will be passed to the AST ; ; Implicit Input: ; ; R4 Address of PCB of caller (current process) ; ; Output Parameters: ; ; The default string (and optionally its length) are passed ; back to the caller. ; ; Return Status: ; ; SS$_NORMAL AST has been successfully queued to the target process ; ; SS$_ACCVIO One of the input parameters cannot be successfully read ; or the output string buffer or length buffer cannot ; be written. ; ; SS$_EXQUOTA Not enough AST quota to deliver notification AST ; ; SS$_INVLOGNAM Invalid process name string was supplied ; ; SS$_NONEXPR Either an invalid process ID was supplied or the ; process no longer exists. ; ; SS$_NOPRIV Caller does not have the privilege to request ; information from the target process. ; ;-- .PSECT USS_CODE PIC,SHR,NOWRT .ENTRY ANALYZE_REC_BUF,^M<r2,R3,R4,R5> SUBL #256,SP PUSHAL (SP) MOVL @4(AP),R4 MOVL R4,R3 ADDL #3,R3 TSTL (R4) BEQL 13$ ADDL (R4),R4 MOVL R4,R5 ; saved start address decl R4 ; first loop cmpl R4,R3 bNEQ 4$ addl #^x401,R4 4$: movzbl (R4),r1 13$: beql 3$ PUSHL r1 moval 8(SP),r2 2$: decl r1 blss 1$ decl R4 cmpl R4,R3 bNEQ 41$ addl #^x401,R4 41$: movb (R4),(r2)[r1] brb 2$ 1$: decl R4 DECL R4 pushal (SP) calls #1,g^lib$put_output MOVAL 4(SP),SP 30$: cmpl R4,R5 beql 3$ decl R4 ; second and other loops cmpl R4,R3 bNEQ 42$ addl #^x401,R4 42$: movzbl (R4),r1 beql 3$ PUSHL r1 moval 8(SP),r2 20$: decl r1 blss 10$ decl R4 cmpl R4,R3 bNEQ 43$ addl #^x401,R4 43$: movb (R4),(r2)[r1] brb 20$ 10$: decl R4 decl R4 pushal (SP) calls #1,g^lib$put_output MOVAL 4(SP),SP brb 30$ 3$: movl #1,R4 RET .ENTRY USS_GETDD,^m<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11> ;++++++++++ ; ; Add code to put the current pcb into R4 ; ;---------- MOVL @#SCH$GL_CURPCB,R4 .ENABL LSB ; Get process ID of target process LOCK_BEGIN: PUSHL R4 ;Save current PCB address SETIPL LOCK_IPL ;Must lock pages because EXE$NAMPID ADDL #4,AP ;Make PIDADR first argument JSB G^EXE$NAMPID ; returns at IPL$_SYNCH SETIPL #0 ;No need to stay at elevated IPL SUBL #4,AP ;Reset AP BLBC R0,10$ CMPW R1,G^SCH$GL_SWPPID ;NULL and SWAPPER are illegal BGTRU 15$ MOVZWL #SS$_NONEXPR,R0 BRB 10$ LOCK_IPL: .LONG IPL$_SYNCH LOCK_END: ASSUME <LOCK_END - LOCK_BEGIN> LE 512 ACCVIO: MOVZWL #SS$_ACCVIO,R0 10$: BRW ERROR_RETURN 15$: MOVL R1,R11 ;Save PID of target process POPR #^M<R4> ;Restore caller's PCB address ; Check for and clear possilbe status block MOVL IOSB(AP),R1 ;Get IOSB address BEQL 20$ ;Skip if none IFNOWRT #4,(R1),ACCVIO ;Check accessibility CLRL (R1) ;Clear it initially ; Clear event flag 20$: MOVZBL EFN(AP),R3 ;Get event flag number JSB G^SCH$CLREF ;Clear that flag BLBC R0,10$ ;Exit if errors ; Check for enough AST quota if ASTADR argument present TSTL ASTADR(AP) ;Argument specified BEQL 25$ ;Skip check if not MOVZWL #SS$_EXQUOTA,R0 ;Assume not enough quota TSTW PCB$W_ASTCNT(R4) ;Any quota left BLEQU 10$ ;Error if none ; Check accessibilty of the data descriptor 25$: MOVL DDDESC(AP),R5 ;Get address of descriptor IFNORD #12,(R5),ACCVIO ;Is descriptor readable? MOVZWL (R5),R6 ;Buffer size to R6 MOVL 4(R5),R7 ; and address to R7 IFNOWRT R6,(R7),ACCVIO ;Is text buffer writeable? MOVL 8(R5),R8 ;Get address of length buffer IFNOWRT #4,(R8),ACCVIO ;Is it writeable? ; At this point, all checks have been made. The access checks must still ; be made again when it is time to move the data to the user's buffer. ; The asynchronous nature of this service allows the calling process ; to continue execution while the default directory string is being ; obtained. Protection could be changed on the buffer, causing a ; possible access violation from kernel mode. ; ; One optimization that is possible here is to check whether the ; target process is the same as the caller. The default directory ; can be obtained in a much more straightforward manner than is being ; done here. In fact, an RMS call already exists to accomplish this. ; ; Now allocate an extended AST control block and store the ; relevant parameters. MOVL #ACB_K_NEW_LEN,R1 ;Set size of extended ACB JSB G^EXE$ALLOCBUF ;Allocate nonpaged pool space ;We are at IPL 2 now BLBC R0,10$ ;Return error status through common ; exit path MOVL R11,ACB$L_PID(R2) ;Store PID of target process MOVW R1,ACB$W_SIZE(R2) ;Store size of structure MOVB #DYN$C_ACB,ACB$B_TYPE(R2) ; and its type MOVPSL R1 EXTZV #PSL$V_PRVMOD,#PSL$S_PRVMOD,R1,R1 ;Get caller's access mode BISB3 #<1@ACB$V_KAST>,R1,ACB$B_RMOD(R2) ; and store it in ACB MOVL ASTADR(AP),ACB$L_AST(R2) ; address of user's AST, MOVL ASTPRM(AP),ACB$L_ASTPRM(R2) ; and associated parameter MOVL EFN(AP),ACB_L_EFN(R2) ;Store event flag number MOVL IOSB(AP),ACB_L_IOSB(R2) ; and status block address MOVL DDDESC(AP),ACB_L_DDDESC(R2) ;Save address of data descriptor MOVL PCB$L_PID(R4),ACB_L_OLD_PID(R2) ;Save caller's PID MOVL G^CTL$GL_PHD,R5 ; and image sequence number MOVL PHD$L_IMGCNT(R5),ACB_L_IMGCNT(R2) ; for later synchronization CLRL ACB_L_GET_AST(R2) ;Clear these two longwords to CLRL ACB_L_PUT_AST(R2) ; prevent possible deallocation ; errors ; ; Now copy the two ASTS into nonpaged pool. A separate block will ; be allocated for each of the two ASTS. If either deallocation ; fails, the error path must be sure to deallocate any already ; allocated pool space. ; ; First do the GET AST MOVL R2,R7 ;Save ACB address MOVL #GET_LENGTH+12,R1 ;Allow 12 bytes for a header JSB EXE$ALONONPAGED BLBS R0,30$ BRW 55$ 30$: MOVL R2,ACB_L_GET_AST(R7) CLRQ (R2)+ ;Clear two link longwords MOVW R1,(R2)+ ;Store size MOVZBW #DYN_K_GET_AST,(R2)+ ;Store type and clear spare byte PUSHR #^M<R0,R1,R2,R3,R4,R5> ;Save registers for MOVC3 MOVC3 #GET_LENGTH,GET_STRING,(R2) ;Copy code to pool POPR #^M<R0,R1,R2,R3,R4,R5> ;Restore registers ADDL3 #12,ACB_L_GET_AST(R7),ACB$L_KAST(R7) ;Store address of special ; AST, skipping header in block ; Do exactly the same thing for PUT AST MOVL #PUT_LENGTH+12,R1 ;Allow 12 bytes for a header JSB EXE$ALONONPAGED BLBC R0,55$ MOVL R2,ACB_L_PUT_AST(R7) CLRQ (R2)+ ;Clear two link longwords MOVW R1,(R2)+ ;Store size MOVZBW #DYN_K_PUT_AST,(R2)+ ;Store type and clear spare byte PUSHR #^M<R0,R1,R2,R3,R4,R5> ;Save registers for MOVC3 MOVC3 #PUT_LENGTH,PUT_STRING,(R2) ;Copy code to pool POPR #^M<R0,R1,R2,R3,R4,R5> ;Restore registers ; ; Ready to queue the AST to the target process. This routine does not ; make all the checks that are performed by $GETJPI. For that reason, ; the caller may have to wait for some time for information to be passed ; back from the target process. The one check that must be made even ; here is whether the target process has been deleted (or is in the process ; of being deleted). ; 35$: SETIPL 45$ ;Need to lock down some more code MOVL R7,R5 ;Put ACB address into usual register MOVZWL ACB$L_PID(R5),R4 ;Get PID of target MOVL G^SCH$GL_PCBVEC,R1 ;Get target PCB address in PIC manner MOVL (R1)[R4],R4 CMPL PCB$L_PID(R4),ACB$L_PID(R5) ;Are PIDs the same BNEQ 50$ ;Error if not BBS #PCB$V_DELPEN,PCB$L_STS(R4),50$ ;Check if being deleted TSTL ACB$L_AST(R5) ;Any user AST specified? BEQL 40$ ;Skip accounting if none ;This accounting cannot be done until ; here because DCLAST in the error path ; does its own accounting DECW PCB$W_ASTCNT(R4) ;Count AST against quota BBSS #ACB$V_QUOTA,ACB$B_RMOD(R2),40$ 40$: MOVL #PRI$_TICOM,R2 ;Give a whopping boost JSB G^SCH$QAST MOVZWL #SS$_NORMAL,R0 SETIPL #0 RET 45$: .LONG IPL$_SYNCH ASSUME <.-35$> LE 512 ; Process has gone away in the interim. Deallocate ACB and the ; two code blocks that contain the GET and PUT ASTs and return through ; common exit path. Entry 55$ is used if an error occurs after some ; of the three pool blocks have already been allocated. Essentially, ; the ACB is always deallocated. If the GET and PUT ASTs have been loaded into ; nonpaged pool, those blocks must be deallocated, too. 50$: MOVZWL #SS$_NONEXPR,R0 ;This is error if process has gone away 55$: PUSHL R0 ;Save status across deallocation MOVL ACB_L_PUT_AST(R5),R0 ;Any PUT AST? BEQL 60$ JSB G^EXE$DEANONPAGED ;If so, deallocate it 60$: MOVL ACB_L_GET_AST(R5),R0 ;Any GET AST? BEQL 70$ JSB G^EXE$DEANONPAGED ;If so, deallocate it 70$: MOVL R5,R0 ;Get addresas of pool to be deallocated JSB G^EXE$DEANONPAGED SETIPL #0 MOVL (SP)+,R0 ;Restore status BRB ERROR_RETURN ; and enter common exit path. .DSABL LSB .page .SUBTITLE ERROR_RETURN - Common error return ;+ ; This is the common exit path for errors detected in arguments ; to the service. The event flag is set. If a status block was ; specified, final status is reported there. If an AST was requested, ; it is queued to the caller. ;- ERROR_RETURN: PUSHL R0 ;Save error status MOVL G^SCH$GL_CURPCB,R4 ;Make sure R4 contents are correct MOVL PCB$L_PID(R4),R1 ;Get PID of caller CLRL R2 ;No boost here MOVL EFN(AP),R3 ;Get event flag number JSB G^SCH$POSTEF ; and set the flag MOVL IOSB(AP),R1 ;Get status block address BEQL 10$ ;Branch if none specified IFNOWRT #4,(R1),10$ ;Also skip if inaccessible MOVL (SP),(R1) ;Report final status 10$: MOVL ASTADR(AP),R5 ;Get AST address BEQL 20$ ;Skip if none MOVPSL R4 ;Get PSL EXTZV #PSL$V_PRVMOD,#PSL$S_PRVMOD,R4,R4 ;Extract caller's access mode $DCLAST_S (R5),ASTPRM(AP),R4 ;Queue the AST 20$: POPR #^M<R0> ;Restore status RET .page .SUBTITLE GET_STRING - Get string from user buffer ;+ ; This routine executes as a special kernel AST in the context of ; the target process. It loads the default directory string from ; P1 space into the extended ACB and uses the same ACB to queue ; another special AST back to the original caller of the service. ; ; Input Parameters: ; ; R0:R3 - Scratch ; R4 - PCB address of target process ; R5 - Address of extended ACB ; ; Calling Sequence: ; ; JSB GET_STRING from AST delivery routine at IPL 2 ; ; Output Parameters: ; ; The default directory string is copied from the target process ; P1 space to the end of the extended ACB. ; ; Side Effects: ; ; If the initial calling process still exists, a special AST ; is queued to that process. The routine PUT_STRING will be ; the AST that executes in the context of the original caller. ;- GET_STRING: PUSHR #^M<R4,R5,R6> MOVL ACB_L_OLD_PID(R5),ACB$L_PID(R5) ;Turn ACB around ADDL3 #12,ACB_L_PUT_AST(R5),ACB$L_KAST(R5) ;Different special AST BISB2 #<1@ACB$V_KAST>,ACB$B_RMOD(R5) ;Reset special bit MOVAB G^CTL$AG_CLIDATA,R3 SUBL3 R3,BASE_INDEX(R3),ACB_L_REC_INDEX(R5) ; Get index SUBL2 #BASE_INDEX,ACB_L_REC_INDEX(R5) MOVC3 #LENGTH_DATA,BASE_DATA(R3),ACB_T_REC_DATA(R5) ; Get Data POPR #^M<R4,R5,R6> ; Now queue an AST back to the original caller 10$: SETIPL 30$ ;Need to raise IPL here MOVZWL ACB_L_OLD_PID(R5),R1 ;Get PID (PIX only) of caller MOVL G^SCH$GL_PCBVEC,R2 ;Get is PCB address MOVL (R2)[R1],R1 ; in a PIC manner CMPL PCB$L_PID(R1),ACB$L_PID(R5) ;Same PID in both places? BNEQ 20$ ;Error if not BBS #PCB$V_DELPEN,PCB$L_STS(R1),20$ CLRL R2 ;No boost going this way JSB G^SCH$QAST SETIPL #IPL$_ASTDEL ;Lower IPL back to 2 MOVL ACB_L_GET_AST(R5),R0 ;and return to AST dispatcher JMP G^EXE$DEANONPAGED ; through EXE$DEANONPAGED ; Original caller has gone away. Deallocate ACB nd simply exit. 20$: SETIPL #IPL$_ASTDEL ;Lower IPL to 2 PUSHL ACB_L_GET_AST(R5) ;Save GET AST block across deallocation MOVL ACB_L_PUT_AST(R5),R0 ;Put AST block is the first to go. JMP G^EXE$DEANONPAGED MOVL R5,R0 ;Now to do the ACB JSB G^EXE$DEANONPAGED ;Deallocate ACB MOVL (SP)+,R0 ;Finally deallocate the block ; containing this code JMP G^EXE$DEANONPAGED ;Jump there. RSB in EXE$DEANONPAGED ; will return to AST dispatcher. 30$: .LONG IPL$_SYNCH ASSUME <.-10$> LE 512 GET_LENGTH = . - GET_STRING .page .SUBTITLE PUT_STRING - Return string to original caller ;+ ; This routine executes as a special kernel AST in the context of ; the original caller. It moves the default directory string ; of the target process from the extended ACB into the user specified buffer. ; ; Input Parameters: ; ; R0:R3 - Scratch ; R4 - PCB address of original caller ; R5 - Address of extended ACB ; ; Calling Sequence: ; ; JSB PUT_STRING from AST delivery routine at IPL 2 ; ; Output Parameters: ; ; The default directory string is copied from the extended ACB ; to the user specified buffer. ; ; Side Effects: ; ; If all access checks are OK, data is moved to user buffer. The ; designated event flag is set. An AST may be delivered if the ; original caller requested one. ;- PUT_STRING: PUSHL ACB_L_PUT_AST(R5) ;Sace address of block containing this ; code for JMP exit through routine ; EXE$DEANONPAGED ; Make sure that the same image is running MOVL G^CTL$GL_PHD,R3 CMPL PHD$L_IMGCNT(R3),ACB_L_IMGCNT(R5) BEQL 10$ BBC #ACB$V_QUOTA,ACB$B_RMOD(R5),5$ ;was caller's AST adjusted? INCW PCB$W_ASTCNT(R4) ;Give it back because ASTDEL ; which usually gives back AST quota, ; cannot, because it never gets called 5$: BRW 70$ 10$: PUSHR #^M<R4,R5,R6,R7,R8,R9> ;Save some registers MOVAB ACB_L_REC_INDEX(R5),R2 ;Address of string in ACB MOVL ACB_L_DDDESC(R5),R3 ;Get buffer descriptor MOVZBL ACB$B_RMOD(R5),R9 ;Get caller's original access mode IFNORD #12,(R3),40$,R9 ;Can it still be read? MOVL 8(R3),R8 ;Get address of length buffer BEQL 20$ IFNOWRT #2,(R8),40$,R9 ;Is it writeable? MOVL #ACB_K_STR_LEN,(R8) 20$: MOVW (R3),R6 ;Buffer size to R6 BEQL 30$ ;If equal, then zero length buffer MOVL 4(R3),R7 ; and address to R7 BEQL 30$ ;If equal, none specified IFNOWRT R6,(R7),40$,R9 ;Is text buffer writeable? MOVC5 #ACB_K_STR_LEN,(R2),#0,R6,(R7) 30$: MOVZWL #SS$_NORMAL,R0 BRB 50$ 40$: MOVZWL #SS$_ACCVIO,R0 50$: POPR #^M<R4,R5,R6,R7,R8,R9> ;Restore registers PUSHL R0 ;Save the final status MOVL ACB_L_EFN(R5),R3 ;Get event flag number MOVL PCB$L_PID(R4),R1 ; and PID of requester CLRL R2 ;No boot for this JSB G^SCH$POSTEF ;Set the event flag POPR #^M<R0> ;Restore final status MOVL ACB_L_IOSB(R5),R3 ;Any IOSB? BEQL 60$ IFNOWRT #4,(R3),60$,ACB$B_RMOD(R5) ;Simply ignore it if not writeable MOVL R0,(R3) ; If an AST was requested, then use the ACB one more time to queue ; that AST to the caller. Otherwise, deallocate the extended ACB. 60$: TSTL ACB$L_AST(R5) ;Any AST? BEQL 70$ ;If equal, then none CLRL R2 ;No boost here either JSB G^SCH$QAST ;Queue the regular AST BRB 80$ ;Exit through EXE$DEANONPAGED 70$: MOVL R5,R0 ;Address of ACB to be deallocated JSB G^EXE$DEANONPAGED ;Deallocate ACB 80$: MOVL (SP)+,R0 ;NOw deallocate code block JMP G^EXE$DEANONPAGED PUT_LENGTH = . - PUT_STRING .END $ create ussgetrec.for PROGRAM GET DEFAULT DIRECTORY ! ! This program asks for a PID and returns the default directory ! for the specified process. ! ! This program has been tested up through VAX/VMS V4.5 and works ! fine. It was originally coded on 4-Jul-1982. ! ! Derek Haining ! Academic Computing Services ! University of Washington ! Seattle, Washington, USA ! ! DEREK@UWACDC.BITNET ! CHARACTER * 2000 DEFDIR INTEGER pid, length INTEGER SYS$CMKRNL common /c1/ pid, length, defdir, istat EXTERNAL SCALL PRINT*, ' Enter a PID' READ ( 5, 10 ) pid 10 FORMAT ( Z8 ) CALL SYS$CLREF( %VAL(12) ) IX = sys$cmkrnl ( scall, ) IF ( IX .NE. 1 ) CALL SYS$EXIT ( %VAL (IX) ) CALL SYS$WAITFR( %VAL(12) ) CALL ANALYZE_REC_BUF (%loc(defdir)) END subroutine scall CHARACTER * 2000 DEFDIR INTEGER*4 DESCR (3) INTEGER USS_GETDD INTEGER pid, efn, length, istat common /c1/ pid, length, defdir, istat DESCR (1) = 2000 DESCR (2) = %LOC(defdir) DESCR (3) = %LOC(length) efn = 3 istat = USS_GETDD ( %VAL(efn), pid, , DESCR, , , ) CALL SYS$WAITFR( %VAL(3) ) CALL SYS$SETEF( %VAL (12) ) return end $ create build.com $ deck $ for/nocheck/nodeb ussgetrec $ mac/nodeb ussgetrec $ lin/notrace/nodeb ussgetrec,ussgetrec;-1,sys$system:sys.stb/sel $ del ussgetrec.obj;* $ eod $ write sys$output "Ready." Christoph D. Gatzka zrgc002@dtupev5a.bitnet Student of medicine University of Tuebingen Germany