;********************************************************* ;Program: show_proc_files ;Author: Billy Bitsenbites (Bruce Ellis) ;Synopsis: This program displays the files currently ; open to the specified process. Along with ; each file, the number of mapping pointers ; that map the file is displayed, as well as ; the reads/writes on this open. ; ; ;********************************************************* ;Macro definitions .macro check ?lab blbs r0,lab $exit_s r0 lab: .endm check ;Macro library includes .library /sys$library:lib/ .link /sys$system:sys.stb/ $dcdef ;Device classes $pcbdef $phddef $pridef $ipldef $acbdef $ccbdef $wcbdef $fcbdef $ucbdef $secdef $sbdef $ddbdef $dyndef ef=32 ;data area pid_asc: .long 8 .address 10$ 10$: .blkb 8 pid: .blkl 1 prompt: .ascid /Pid?/ lock_adr: .address lock1 .address lock2 ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ;Allocate header for file information buffer ;Note: Position dependence is crucial. ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ proc_files: .blkb 12 ;reserved space for pool header info header1=0 ;;offset to the first longword (unused) header2=4 ;offset to second longword (unused) block_size=8 ;size of pool allocated to the block block_type=10 ;type of dynamic structure prc_name: .blkb 16 ;process name prcnam=prc_name-proc_files ;offset to process name in block pid_other: ;returned pid .long 0 pid_other_off=pid_other-proc_files ;offset to pid in block count: .long 0 ;count of number of files open by the process ret_count=count-proc_files ;offset to the returned count file_buffer_loc: ;location of the file buffers file_buffer_max=256 ;philosophically we should not even allow for ; this many concurrent files file_buffers=file_buffer_loc-proc_files ;offset to file buffers header=file_buffers node=0 ;offset within buffer to scs nodename devnam=8 ;offset to device name (NOTE: This program assumes ; that precedent has not been broken with three ; character device names. If it is, the area for ; device names will have to be increased in size. unit=12 ;offset within buffer to the unit fid=14 ;offset within buffer to the file id fid_rvn=18 ;offset within the buffer to the the rvn of file reads=20 ;offset into buffer to locate the count of reads writes=24 ;offset within buffer to locate the count of writes file_buffer_size=28 ;size of each file buffer ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Allocate space for per file information buffers ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .rept file_buffer_max .blkb 8 ;node name .blkb 4 ;device name .blkb 6 ;file id .blkl 2 ;count of reads and writes .endr prc_args: .long 2 .address pid .long 0 fmt: .ascid /Process: !15AC with pid !8XL has the following files open:/ out_buf: .long 80 .address 10$ 10$: .blkb 80 no_file_msg: .ascid /This process has no files open. / ;Code .psect code shr,nowrt,pic,exe .entry show_proc_files,^m<> $lkwset_s inadr=lock_adr ;No page faults at high ipl check pushal pid_asc ;Determine which process we pushal prompt ; are supposed to get the info pushal pid_asc ; from. calls #3,g^lib$get_input check pushal pid ;Convert pid from ascii to binary pushal pid_asc ; calls #2,g^ots$cvt_tz_l ; check $clref_s efn=#ef ;clear event flag we are going to wait check ; on for completion of kast $cmkrnl_s routin=get_file,arglst=prc_args ;Queue a special kernel ast to the check ;process to obtain the needed info $waitfr_s efn=#ef ;wait until sp kast sets efn for check ; asynchronous completion ;************************************************** ;Format and spill the process name and PID ;************************************************** $fao_s ctrstr=fmt,outbuf=out_buf,outlen=out_buf,p1=#prc_name,- p2=pid_other check pushal out_buf calls #1,g^lib$put_output movl count,r6 ;How many open files beql no_files_open moval proc_files+file_buffers,- ;locate the beginning of file buffers r7 10$: pushl r7 ;dump the file information 1 file at calls #1,spill_file_info ; a time addl #,r7 ;point to next file buffer sobgtr r6,10$ ;loop till all files processed over_and_out: ret ;Auf Wiedersehen! no_files_open: pushal no_file_msg calls #1,g^lib$put_output brb over_and_out ;**************************************************** ; Special kast setup ;**************************************************** lock1: .entry get_file,^m ;**************************************************** ; Get process PCB address ;**************************************************** ; Inputs: 4(ap) - pidadr/ 8(ap) - prcnam desc adr / r4 - PCB jsb g^exe$nampid ; Outputs: ; r0 - status ; r1 - ipid of the other guy ; r4 - pcb of the other guy ; ipl is at synch, with sched spinlock blbs r0,ok2 setipl #0 ret ;**************************************************** ; Allocate pool for ACB ;**************************************************** ok2: ; by exe$nampid movl r4,r10 ;save his pcb moval acb,r6 ;set up acb movl g^ctl$gl_pcb,r4 ;Save my movl pcb$l_pid(r4),acb_l_mypid ; pid for return sp kast bbc #pcb$v_suspen,pcb$l_sts(r10),hes_ok1 setipl #0 movl #ss$_suspended,r0 brw err_ret hes_ok1: bbc #pcb$v_delpen,pcb$l_sts(r10),hes_ok2 movl #ss$_nonexpr,r0 brw err_ret hes_ok2: movl @#ctl$gl_phd,r9 ;get phd address movl phd$l_imgcnt(r9),imgcnt ;Save the image count so return AST ; knows whether we are in same image or ; not moval proc_files,file_ret_adr ;save return address from p0 space moval count,count_ret_adr ;save return count address from p0 movl #size_of_pool,r1 ;Set up for allocating pool jsb g^exe$alononpaged ;get it blbs r0,ok3 ;continue if all is cool brw err_ret ;else get out ok3: pushr #^m ;save regs from movc3 movc3 #size_of_pool,acb,(r2) ;copy acb and routines to pool popr #^m ;restore regs movw r1,acb$w_size(r2) ;save size of pool movb #dyn$c_acb,acb$b_type(r2) ;setup type movb #<1@acb$v_kast>,acb$b_rmod(r2) ;set up for sp kast movl pcb$l_pid(r10),acb$l_pid(r2) ;define acb of process to get ast moval (r2),acb$l_kast(r2) ;set ast address for kast movl r2,r5 ;set up r5 for sch$qast ;**************************************************** ; Allocate pool for channel info ;**************************************************** movzwl g^sgn$gw_pchancnt,r1 ;get channelcnt sysgen parameter cmpl #file_buffer_max,r1 ;too many channels? bgtr channcnt_ok ; branch if not movl #file_buffer_max,r1 ;else reset to max (sorry, charlie!) channcnt_ok: mull2 #file_buffer_size,r1 ;calculate max buffer size needed addl2 #header,r1 ;add on header movl r1,r6 ;save pool size requested jsb g^exe$alononpaged ;get the pool for the buffer blbs r0,still_cool ;continue if sufficient pool brw err_ret_deallo ;cannot continue/not enough pool still_cool: pushr #^m ;save regs for movc5 movc5 #0,.,#0,r6,(r2) ;zero the buffer popr #^m ;restore regs movw r1,block_size(r2) ;save the size of pool movb #dyn$c_bufio,block_type(r2) movl r2,file_info_buffer(r5) ;save the buffer pointer ;**************************************************** ; Queue the ast ;**************************************************** ;lock1: setipl #ipl$_synch ;synch w/sched db movzwl acb$l_pid(r5),r4 ;retrieve the pid of the process we want movl #pri$_ticom,r2 ;give him a boost movl g^ctl$gl_pcb,r4 ;restore our pcb address jsb g^sch$qast ;queue an ast to the process unlock lockname=SCHED,newipl=#0 ;lower ipl from synch implied movl #ss$_normal,r0 ;Get outta here ret err_ret_deallo: movl file_info_buffer(r5),r0 ;get pool buffer address beql no_buffer_to_deallo ; jsb g^exe$deanonpaged ;deallocate the buffer no_buffer_to_deallo: movl r5,r0 ;r0 points to the pool to return jsb g^exe$deanonpaged movl #ss$_insfmem,r0 err_ret:unlock lockname=SCHED,newipl=#0 ret .psect data_and_code wrt,exe acb: .blkb acb$l_kast+4 ;allocate space for the acb portion acb_l_mypid: .blkl 1 ;My pid for return ast ret_ast_adr: .blkl 1 ;return ast address file_info_buffer=.-acb .blkl 1 ;location of file info buffer in pool count_ret: .long 0 ;return count of files processed file_ret_adr: .blkl 1 ;P0 buffer address count_ret_adr: .blkl 1 ;return location for count imgcnt: .blkl 1 ;count of images run ;**************************************************** ; AST get file/channel info ;**************************************************** ;***************************************************** ;Special kernel ast code ;***************************************************** copy_file: pushr #^m movl acb_l_mypid,acb$l_pid(r5) ;reset pid for return trip moval ret_ast,acb$l_kast(r5) ;set return ast address bisb2 #<1@acb$v_kast>,acb$b_rmod(r5) ;set up for sp kast movl file_info_buffer(r5),r11 ;locate the buffer movl g^ctl$gl_pcb,r10 ;get this guy's pcb address movq pcb$t_lname(r10),prcnam(r11) ;copy the process name movq (r10),(r11) ;copy the rest movl pcb$l_epid(r10),pid_other_off(r11) ;get his pid moval file_buffers(r11),r9 ;locate the file buffers clrl ret_count(r11) ;zero counter of file names movl @#ctl$gl_ccbbase,r10 ;set up link to fix up vectors clrl r6 movl g^ctl$gl_pcb,r4 moval g^ioc$gl_mutex,r0 jsb g^sch$lockr nxt_ccb: ;Index from base back subl #16,r10 ; 1 CCB at a time addl #16,r6 ;keep track of current chan # cmpw r6,g^ctl$gw_chindx ;if past max scram bgtr done movl ccb$l_ucb(r10),r7 ;get ucb beql all_done1 cmpb #dc$_disk,ucb$b_devclass(r7) ;if not a disk skip it bneq not_a_file movl ccb$l_wind(r10),r8 ;get wcb beql not_a_file blss not_a_section_file cvtwl ccb$l_wind(r10),r2 ;get negative pstx out of ccb movl g^ctl$gl_phd,r1 ;get the phd address addl2 phd$l_pstbasoff(r1),r1 ;locate the end of the pst movl sec$l_window(r1)[r2],r8 ;get the wcb pointer not_a_section_file: movl wcb$l_reads(r8),reads(r9) ;get reads since open movl wcb$l_writes(r8),writes(r9) ;get writes since open movl wcb$l_fcb(r8),r8 ;get fcb movl fcb$w_fid(r8),fid(r9) ;get file id movw fcb$w_fid_rvn(r8),fid_rvn(r9) ;get rest of fid movw ucb$w_unit(r7),unit(r9) ;get unit number movl ucb$l_ddb(r7),r7 ;get the device name movl ddb$t_name(r7),devnam(r9) movl ddb$l_allocls(r7),(r9) ;get allo class if any beql no_alloclass ; branch if none movw #-1,node(r9) ;mark that alloclass exists brb skip_name ;don't need name no_alloclass: movl ddb$l_sb(r7),r7 ;get the node name movl sb$t_nodename(r7),node(r9) ; movl sb$t_nodename+4(r7),(r9) skip_name: incl ret_count(r11) ;count fo files +=1 cmpw #file_buffer_max,ret_count(r11) ;too many? blss all_done1 addl2 #file_buffer_size,r9 ;point to next buffer not_a_file: all_done2: brw nxt_ccb ;get the next file done: all_done1: ;**************************************************** ; AST return file/channel info ;**************************************************** ;***************************************************** ;We have the info now let us send it back to the ;original process. ;***************************************************** movl g^ctl$gl_pcb,r4 moval g^ioc$gl_mutex,r0 jsb g^sch$unlock lock lockname=SCHED,lockipl=#ipl$_sched movzwl acb$l_pid(r5),r1 ;set up return pid for astdel movl g^sch$gl_pcbvec,r2 ;get at pcb vector table movl (r2)[r1],r1 ;get our pcb address ;Who are we anyway? (Zelig) cmpl pcb$l_pid(r1),acb$l_pid(r5) ;are we still around or are we ; The Ghost in the Machine bneq err_ast_exit ;if initial process is not ;here exit unlock lockname=SCHED,newipl=#ipl$_astdel clrl r2 ;no boost for the ast jsb g^sch$qast ;return to home setipl #ipl$_astdel ;return to initial ipl popr #^m rsb ;back to astdel err_ast_exit: unlock lockname=SCHED,newipl=#ipl$_astdel popr #^m movl file_info_buffer(r5),r0 ;return file info buffer to ;pool jsb g^exe$deanonpaged ; movl r5,r0 ;deallocate ourselves jmp g^exe$deanonpaged ;and don't come back here ;instead go directly back to ;astdel and do not collect $200 ;**************************************************************** ;We are back home now so lets put the info at his ;doorstep, ring the doorbell, and disappear ;**************************************************************** ret_ast: pushr #^m movl pcb$l_phd(r4),r3 ;get our process header cmpl phd$l_imgcnt(r3),imgcnt ;are we still in the same ;image? If not get out. bneq exit ; movl file_info_buffer(r5),r6 ;locate the file info buffer mull3 #,- ; ret_count(r6),r2 ;how much to return? addl2 #header,r2 ;return header info pushr #^m movc3 r2,(r6),- ; @file_ret_adr ;return the goods popr #^m movl ret_count(r6),@count_ret_adr ;return the count movl #ef,r3 ;set efn ef movl pcb$l_pid(r4),r1 ;for ourselves clrl r2 ;no boost jsb g^sch$postef ; set it exit: popr #^m movl file_info_buffer(r5),r0 ;return file info buffer to ;pool jsb g^exe$deanonpaged ; movl r5,r0 jmp g^exe$deanonpaged ;become a nonentity size_of_pool = .-acb lock2: .end show_proc_files ;****************************************************** ; Subroutine - Spill_File_Info ; Author: Billy Bitsenbites (Bruce Ellis) ; Synopsis: This subroutine is called to ; format and display the Device name, file ; name, file id, reads and writes on the ; file since opened, and the number of mapping ; pointers in the file header(s). ; Inputs: address of a block of the following form: ; 8 bytes containing the scsnode ; 4 bytes containing the device name ; 2 bytes containing the unit number of the device ; 6 bytes containing the file id of the file ; 4 bytes containing the count of reads on the window ; 4 bytes containing the count of writes on the window ; ;****************************************************** ;Macros .macro check ?l blbs r0,l $exit_s r0 l: .endm check ;Data dev: .long 15 ;Descriptor holding the device name .address dev_a dev_a: .blkb 15 out_string: ;Output string buffer .long 256 .address 10$ 10$: .blkb 256 ;formats file_dev: .ascid <10><13>/File:/ fid_fmt:.ascid /File id: (!UW,!UW,!UW)/ fmt_rw: .ascid /Reads on window: !10UL Writes on window: !10UL/ out_ptr: ;Output buffer .long 80 .address 10$ 10$: .blkb 80 ptr_count: ;Count of the number of mapping pointers .blkl 1 file_buffer: ;Local copy of the passed file buffer node: .blkb 8 devnam: .blkb 4 unit: .blkw 1 fid: .blkb 6 reads: .long 0 writes: .long 0 buffer_size=.-file_buffer allo: .long 3 ;Allocation class descriptor .address allo_a allo_a_prefix: .ascii /$/ allo_a: .blkb 3 allo_f: .ascid /!UB/ unit_f: .ascid /!UW/ unit_d: .long 5 .address unit_a unit_a: .blkb 5 ;Code .entry spill_file_info,^m<> movc3 #buffer_size,@4(ap),file_buffer ;Copy the buffer to local ; storage cmpw node,#-1 ;Alloclass? bneq no_alloclass ;branch if not ;^^^^^^^^^^^^ ;Format the allocation class to ascii ;^^^^^^^^^^^^ $fao_s ctrstr=allo_f,outbuf=allo,outlen=allo,p1=node+2 check incl allo ;increment to include ; last '$' sign movc3 allo,allo_a_prefix,dev_a brb finish_node ;skip to rest of devnam no_alloclass: movzbl node,r0 ;Get node name size bneq got_node ;Process the node name moval dev_a,r3 ;no node so skip it brb skip_node ; got_node: movc3 r0,,dev_a ;Copy node name finish_node: movb #^a/$/,(r3)+ ;Plug in a $ after node name skip_node: movw devnam+1,(r3)+ ; Get device and controller movb devnam+3,(r3)+ ; portion of the device name movl #5,unit_d ;Format the unit # $fao_s ctrstr=unit_f,outbuf=unit_d,outlen=unit_d,p1=unit check movc3 unit_d,unit_a,(r3) ;Append unit (in ascii) to devnam movb #^a/:/,(r3)+ ;Append ':' subl3 #dev_a,r3,dev ;Calculate size of device name pushal file_dev ;Spill header calls #1,g^lib$put_output movl #256,out_string ;Alllow for a large file name pushal out_string ;Pass location to return size ; of file name string pushal out_string ;Pass file spec descriptor pushal fid ;Pass the file id pushal dev ;Pass the device name calls #4,g^lib$fid_to_name ;Convert the fid to file name check pushal out_string ;spill the file name calls #1,g^lib$put_output ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ;Format the file id ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ movl #80,out_ptr $fao_s ctrstr=fid_fmt,outbuf=out_ptr,outlen=out_ptr,- p1=fid,p2=fid+2,p3=fid+4 check pushal out_ptr calls #1,g^lib$put_output ;Spill the file id ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ;format the count of reads/writes ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ movl #80,out_ptr $fao_s ctrstr=fmt_rw,outbuf=out_ptr,outlen=out_ptr,p1=reads,- p2=writes check pushal out_ptr ;Spill the count calls #1,g^lib$put_output ret ;Sayonara .end