;******************************************************************************* ;* Title: What_look * ;* * ;* Version: 2-000 * ;* * ;* Facility: System information formating and requests. * ;* * ;* Abstract: This module contains the procedure that requests the process * ;* information from the system and formats it as follows: * ;* * ;* Full Format: * ;* * ;* Username Pid Process Name Group Term Login State Cpu Program * ;* ------------------------------------------------------------------------- * ;* ABC1234X xxxx abcdefghijklmno ABCDEFG ABxxxx: XX:XX ABCDE XXXX K ABCDEFGH * ;* * ;* * ;* Brief Format: * ;* * ;* Username Node PID Process Name Terminal * ;* ABC1234 ABCDEF 2AE008FB abcdefghijklmno ABCxxx: * ;* * ;* Environment: What_look is non-reentrant since it is written in MACRO with- * ;* out useing the stack to store variables. You can pass it an * ;* an address of a channel or buffer descriptor of where to put * ;* information it gathers. It needs WORLD privilege in order to * ;* look at all the processes on the system for their stats. It * ;* does not return any information unless it finds processes * ;* that it can get the information on with out privilege. * ;* * ;* Author: Andrew W. Potter, 198? * ;* * ;* Modified by: Dave P. Mulvihill: 1986 * ;* - Changed output so it can go down a given channel * ;* * ;* Peter A. Portante: February, 1988 * ;* - Broke entire routine down in to smaller modules. * ;* - Rewrote FORTRAN subroutines in MACRO, just for fun * ;* - Changed the language from FORTRAN to MACRO, just for fun * ;* - Removed original internal sort routine. * ;* - Eliminated double looping to search for system processes. * ;* Now the process is totally parsed together on one pass * ;* through the loop and sent to the appropriate place. * ;* - Can either send down given channel or put into a users * ;* buffer. * ;* - Status returns for the system have been moved to another * ;* module. * ;* * ;******************************************************************************* ; .title WHAT_LOOK ; $iodef ; Get the system definitions $ssdef $jpidef $dvidef $syidef ; SCH$C_COLPG = 1 SCH$C_MWAIT = 2 SCH$C_CEF = 3 SCH$C_PFW = 4 SCH$C_LEF = 5 SCH$C_LEFO = 6 SCH$C_HIB = 7 SCH$C_HIBO = 8 SCH$C_SUSP = 9 SCH$C_SUSPO = 10 SCH$C_FPG = 11 SCH$C_COM = 12 SCH$C_COMO = 13 SCH$C_CUR = 14 ; DAE_M_CHANNEL = 128 ; Mask for the channel DAE_M_NODE = 16 ; Mask for adding in the node DAE_BRIEF = 0 ; Send user processes in brief format DAE_SYSTEM = 9 ; Send all processes in full format DAE_FULL = 8 ; Send user processes in full format ; INFO_SIZE = 24000 ; 300 80 byte lines ALL_PROC = 0 ; Get all processes INT_ONLY = 3 ; Get only interactive processes ; SUBPROC = 4 ; We have a subprocess here... ; ; ; .psect what_look_data, con, noexe, lcl, pic, noshr, wrt, rd, rel ; ; Data storage for building the nodes ; buffer: .blkb INFO_SIZE ; Size of the information block to hold user strings buffer_desc: .long 0 ; Length of the buffer .address buffer ; Address of where the buffer is ; ; The table is used by MOVTC to translate characters. ; table: .byte 32[33] .ascii ~!"#$%&'()*+,-./0123456789:;<=>?@~ .ascii /ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`/ .ascii /abcdefghijklmnopqrstuvwxyz{|}~/ .byte 32[34] .byte 161,162,163,32,165,32,167,168,169,170,171 .byte 32[4],176,177,178,179,32,181,182,183,32 .byte 185,186,187,188,189,32,191,192,193,194,195,196,197 .byte 198,199,200,201,202,203,204,205,206,207,32 .byte 209,210,211,212,213,214,215,216,217,218,219,220 .byte 221,32,223,224,225,226,227,228,229,230,231,232,233 .byte 234,235,236,237,238,239,32,241,242,243,244,245,246 .byte 247,248,249,250,251,252,253,32,32 ; null_time: .ascii / --- / null_cpu: .ascii / ---/ suspnd_str: .ascii /Suspended/ swapped_str: .ascii /Swapped / ; char_state_arr: .ascii /CPG/ ; Character string representations .ascii /MWT/ ; - of the different process .ascii /CEF/ ; - states .ascii /PFW/ .ascii /LEF/ .ascii /LEF/ .ascii /HIB/ .ascii /HIB/ .ascii /SUS/ .ascii /SUS/ .ascii /FPG/ .ascii /COM/ .ascii /COM/ .ascii /CUR/ .ascii / / ; char_mode_arr: .ascii /-Det- / ; Character string for the different process modes .ascii /-Net- / .ascii /-Bat- / .ascii /-Disc-/ .ascii /-Sub- / ; ctrl_brief: .ascid / !AD !+!+!XL !AF !+!+!AD/ ; Skip the nodename, and the group ctrl_full: .ascid /!AD !+!+!XW !AF !AD !AD !AD !AD !AD !AD/ ; Skip the nodename ctrl_brief_node: .ascid / !AD !AD !XL !AF !+!+!AD/ ; Skip the the group ctrl_full_node: .ascid /!AD !AD !XW !AF !AD !AD !AD !AD !AD !AD/ ; ctrl_list: .address ctrl_brief ; List of the different string formats .address ctrl_full .address ctrl_brief_node .address ctrl_full_node ; node: .byte 32[6] ; Where the DECnet node name is stored strings_to_blank: ; All these are cleared for cleanlyness username: .byte 32[8] ; User name from JPI account: .byte 32[8] ; Account from JPI term: .byte 32[16] ; Terminal name returned image: .byte 32[128] ; Image name of the process prcnam: .byte 32[15] ; Process name returned ; name_only: .byte 32[17] ; Actuall image name, with out rms stuff outstr: .byte 32[256] ; Output string from the SYS$FAO service ; char_time: .byte 32[20] ; Character representation of the time char_state: .byte 32[3] ; Character representation of the state char_cpu: .byte 32[4] ; Character representation of the cpu time ; BYTES_TO_BLANK = . - strings_to_blank ; image_descr: .long 0 ; Length of the image .address image ; Where the image is term_descr: .long 0 ; Length of the terminal .address term ; Where the terminal is ; owner: .long 0 ; Owner of the process state: .long 0 ; State the process is in cpu_time: .long 0 ; Cpu time for process .long 0 login_time: .long 0 ; Login time for the process .long 0 mode: .long 0 ; Mode of the process chan_buf: .long 0 ; Default to useing a buffer chan_buf_adr: .long 0 ; Address of where buffer or channel is ; char_time_descr: .long 5 ; How long the time is .address char_time ; Where the time should be put char_cpu_descr: .long 4 ; How long we want it .address char_cpu ; Where the character cpu should be put ; name_descr: .long 17 ; Maximum length of the name .address name_only ; Where the name of the image is stored outstr_descr: .long 256 ; Length of the outstr, doubles as its descriptor .address outstr ; Address out output string l_ostr: .long 0 ; Length of the outstr, returned by SYS$FAOL ; retlength: .long 0 ; Dummy place to hold some return lengths from SYS$GETJPI iosblk: .quad 0 ; IO status block ; fcpu: .long 0 ; Converted cpu time ; filter: .byte 0 ; Assume we will filter no processes out ; fao_list: .long 8 ; How much of the username we want printed out .address username ; Where the username is .long 6 ; How long the node is .address node ; Where the node name is pid: .long 0 ; Process Identification number .long 15 ; How much of the processname we want printed out .address prcnam ; Where the process name is .long 7 ; How much of the account we want printed out .address account ; Where the group name is .long 7 ; How much of the terminal we want printed out .address term ; Where the terminal name is .long 5 ; How much of the time we want printed out .address char_time ; Where the character time is .long 3 ; How much of the character state we want printed out .address char_state ; Where the character state is .long 4 ; How much of the character cpu usage we want printed out .address char_cpu ; Where the character cpu usage is .long 17 ; How much of the image name we want printed out .address name_only ; Where the name is ; ; DVI item list to get the physical terminal information ; dvi_list: .word 16 .word DVI$_TT_PHYDEVNAM .address term .address term_descr ; .long 0 ; End of DVI list ; ; SYI item list to get the system wide information ; syi_list: .word 6 .word SYI$_NODENAME .address node .address retlength ; .long 0 ; End of SYI list ; ; JPI item list to get information that won't swap a process ; jpi_wild: .long -1 ; We want a wild card lookup of processes ; jpi_lookup: .word 4 ; The pid is a longword, four bytes .word JPI$_PID ; We want the process identification number .address pid ; Where to store the pid .address retlength ; Dummy return length ; .word 4 ; The state is a longword, four bytes .word JPI$_STATE ; We want the state .address state ; Where to put the state .address retlength ; Dummy return length ; .word 4 ; The mode is a longword, four bytes .word JPI$_MODE ; We want the process's mode .address mode ; Where to put the mode .address retlength ; Dummy return length ; .word 8 ; Length we want for the username .word JPI$_USERNAME ; We want the username .address username ; Where to put the username .address retlength ; How long our username is ; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% join with part 2 %%%%%%%%%%%%%%%%%%%%%%%%% ; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% join with part 1 %%%%%%%%%%%%%%%%%%%%%%%%% ; .word 8 ; Length we want for the account .word JPI$_ACCOUNT ; We want the account .address account ; Where to put the account .address retlength ; Dummy return length ; .word 16 ; Length we want for the terminal .word JPI$_TERMINAL ; Get the terminal of the process .address term ; Where to put the terminal .address term_descr ; Dummy return length ; .word 15 ; Length we want for the process name .word JPI$_PRCNAM ; We want a process name .address prcnam ; Where to put the process name .address retlength ; Dummy return length ; .long 0 ; End of JPI list that won't swap a process in ; ; JPI item list to get information that will swap a process in ; jpi_p1: .word 128 ; Length we want for the image name .word JPI$_IMAGNAME ; We want the image name .address image ; Where to put the image name .address image_descr ; Where to put the length of the image ; .word 8 ; Length we want for the CPU time .word JPI$_CPUTIM ; We want the CPU time .address cpu_time ; Where to put the cpu time .address retlength ; Dummy return length ; .word 8 ; Length we want for the login time .word JPI$_LOGINTIM ; We want the login time .address login_time ; Where to put the login time .address retlength ; Where to put the return length ; .word 4 ; Length we want for the owner .word JPI$_OWNER ; We want the owner .address owner ; Where to put the owner .address retlength ; Dummy return length ; .long 0 ; End of JPI list that will swap a process in ; ; ; ;******************************************************************************* ;* What_look * ;* This procedure is intended to take a function code that specifies a * ;* format of output, and either a channel number or the address of a buffer * ;* to put the information returned in. The function codes currently supported * ;* for either channel or buffer are: * ;* * ;* DAE_BRIEF * ;* DAE_SYSTEM * ;* DAE_FULL * ;* * ;* Arguments: BUFFER or CHANNEL, address of either a buffer to put info into * ;* - or a channel to send the info down. Buffer is passed by * ;* - descriptor. * ;* * ;* FUNCTION, the function code to perform. Only the first byte * ;* - is used. If the high order bit in the byte is set then * ;* - the first argument is interpreted as a channel number, * ;* - else it is interpreted as a buffer descriptor. FUNCTION * ;* - is passed by value. * ;* * ;* USER, address of a descriptor of the user names to search for. * ;* * ;* Register Use: * ;* * ;* r6 - Holds the address of the format strings to be used * ;* r7 - Holds the current address in the print buffer * ;* r8 - Holds the address of the character state array * ;* r9 - Holds the address of the character mode array * ;* r10 - Holds the address of the buffer or channel to dump info to * ;* r11 - Holds the function code we are working with, then it holds the * ;* number of the control string we want * ;* * ;******************************************************************************* ; .psect what_look_code, con, exe, lcl, shr, nowrt, pic, rel ; .entry what_look, ^m ; moval ctrl_list, r6 ; Put the control list into a memory for later use moval buffer, r7 ; Holds the address of the current position in print buffer moval char_state_arr, r8 ; Move the address of the character state for indexing later moval char_mode_arr, r9 ; Move the address of the character modes for indexing later movl 4(ap), chan_buf_adr ; Move either the address of a channel or address of a descriptor movzbl 8(ap), r11 ; Move address of function code movl 12(ap), r10 ; Move address of user descriptor so we can work with it ; mnegl #1, jpi_wild ; We want to search all the processes ; blbs r11, get_all ; If the 0 bit is set, get all the process on system movb #INT_ONLY, filter ; Get the interactive ones only brb keep_parsing ; Go and skip the swapper and null processes ; get_all: movb #ALL_PROC, filter ; Get all the system processes ; keep_parsing: extzv #7, #1, r11, chan_buf ; Extract whether we want to use first arg as a channel of buffer extzv #3, #2, r11, r11 ; Extract out the format number ; skip_swap: $getjpiw_s - ; Skip the NULL process pidadr = jpi_wild, - ; We want to search all the processes itmlst = jpi_lookup ; We want to lookup normal information $getjpiw_s - ; Skip the SWAPPER process pidadr = jpi_wild, - ; We want to search all the processes itmlst = jpi_lookup ; We want to lookup normal information $getsyiw_s - itmlst = syi_list ; Get the specified info movc5 retlength, node, #32, #6, node ; loop: movc5 #0, #0, #32, - #BYTES_TO_BLANK, - strings_to_blank ; Clear out the strings ; $getjpiw_s - ; Get the next process pidadr = jpi_wild, - ; We want to search all the processes itmlst = jpi_lookup ; We want to lookup normal information cmpl #SS$_NOMOREPROC, r0 bneq cont_loop ; Continue processing if there are still more ; brw end_loop ; We are done, get out ; cont_loop: cmpl #SS$_NOPRIV, r0 ; Do we have the privilege to a get process beql loop ; Keep going, and get next process ; cmpb mode, filter ; If the mode is greater than or equal to the blss loop ; - process mode we want, keep it ; ; Compare username returned from SYS$GETJPI to the username passed in ; cmpw (r10), #8 ; If we have less than 8 chars, we will do a cmpc3 bleq variable_cmp ; locc #32, #8, username ; Find end of the string subl3 r0, #8, r0 ; Find out how long it is matchc r0, username, (r10), @4(r10) beql process_it ; If we match, keep going brw loop ; Else get next dude ; variable_cmp: cmpc3 (r10), @4(r10), username ; Are the string equal beql process_it ; If we match, keep going brw loop ; Else get next dude ; process_it: movtc #15, prcnam, #32, table, #15, prcnam ; Clean out the processname string ; tstb term bneq has_term ; We have a terminal ; brw get_other_info ; We don't have a terminal ; has_term: locc #^a/:/, term_descr, term ; Find a colon in device name bneq get_phys ; If we found, get physical device name ; movb #^a/:/, (r1) ; Add in a colon, cause we couldn't find one incl term_descr ; Increase the length ; get_phys: $getdviw_s - devnam = term_descr, - ; What name we are looking for itmlst = dvi_list ; What information we want ; cmpb #^a/_/, term ; Do we have an underline? bneq get_other_info ; If we don't, keep going ; decl term_descr ; Decrease its length movc5 term_descr, term+1, #32, #16, term ; Move the string back one ; ; ; get_other_info: movtc #8, account, #32, table, #8, account ; Clean out the account string cmpb #32, account ; Do we have a crap account bneq calc_state movc5 #0,#0,#32,#8,account ; Clean out crap accounts ; calc_state: mull3 #3, state, r0 ; Get the offset into the state array movc3 #3, -3(r8)[r0], char_state ; Move the character representation of the state ; movc3 #5, null_time, char_time ; Default value for character time movc3 #4, null_cpu, char_cpu ; Default value for character cpu ; cmpl state, #SCH$C_SUSPO beql we_are_swap cmpl state, #SCH$C_LEFO beql we_are_swap cmpl state, #SCH$C_COMO beql we_are_swap cmpl state, #SCH$C_HIBO bneq not_swap ; we_are_swap: movc5 #9, swapped_str, #32, #17, name_only brw have_a_term ; not_swap: $getjpiw_s - pidadr = pid, - ; Get more info on current process itmlst = jpi_p1 ; Here is the info we want blbc r0, proc_suspend ; If it failed, process is suspended ; $asctim_s - ; Convert the login time to a string timlen = char_time_descr, - ; How long the string is timbuf = char_time_descr, - ; Where the buffer is timadr = login_time, - ; The time to be converted cvtflg = #1 ; We just want the time pushal name_descr ; Where to put the length pushal name_descr ; Where to put the image pushal image_descr ; The image we have calls #3, g^what_parseimage ; Parse out the image string brb cont_swap ; Finish the swap ; proc_suspend: movc5 #9, suspnd_str, #32, #17, name_only ; cont_swap: divl3 #100, cpu_time, fcpu pushal char_cpu_descr pushal fcpu calls #2, g^ots$cvt_l_ti ; Convert the cpu time to a string ; have_a_term: tstb term ; Did we get a terminal? bneq format_strings ; If owner is 0 then just format the strings ; tstl owner ; If we are not a subprocess beql get_term ; Get the terminal string with the current mode ; movl #SUBPROC, mode ; We are a subprocess otherwise ; get_term: mull3 #6, mode, r0 ; Compute offset of into character array movc5 #6, (r9)[r0], #32, #16, term ; - that contains the mode string for bad terminals ; ; ; format_strings: pushal fao_list ; Push our address of our arguments pushal outstr_descr ; Push the descriptor of out output string pushal l_ostr ; Push where the output length should be put pushl (r6)[r11] ; Push the address of the control string we want calls #4, g^sys$faol ; Call the Formatted Ascii Output service movc5 l_ostr, outstr, #32, #80, (r7) ; Move the formatted string movl r3, r7 ; Save new address in print buffer ; brw loop ; Go back and get next process ; ; ; end_loop: moval buffer, r1 ; Move the address of our buffer for computation movl chan_buf_adr, r10 ; Move address of channel or buffer into r10, easier to work with blbs chan_buf, use_channel ; Do we want to use a channel? subl3 r1, r7, (r10) ; Compute the length of the buffer movc5 (r10), buffer, #32, (r10), @4(r10) ; Move all the information to the user specified buffer ret ; use_channel: subl3 r1, r7, r6 ; Compute the length of the buffer $qiow_s - chan = (r10), - ; What channel to write to func = #IO$_WRITEVBLK,- ; Write out the line iosb = iosblk, - ; Status of operation p1 = buffer, - ; Where to write from p2 = r6 ; Length of bytes to put out movzwl iosblk, r0 ; Return the status condition ret ; End of What_look ; .end