~ NET_WHAT.BCKe NET_WHAT.BCK*BACK *.* [-]NET_WHAT.BCK/SAV/NOCRC/GROUP:0 AWPSYS ӒV5.2 _CMKRNL::  _CMKRNL$DUB0: V5.2 ~y,*[ANONYMOUS.SAVE_SETS.NETWHAT]AAAREADME.TXT;1+,0. / 4M -0123KPWO 56d-Ӓ7-Ӓ89GHJ D********** NOTE: Several files have been broken up to accomodate aG infovax distribution you MUST run AA_FIX_FILES.COM1 Before building the procedure.% - Awp. WHAT Version 1.1L****************************************************************************, 15 June 1988D This is a newer version than the one submitted to the Sprting 88,A Cincinatti DECUS Symposia Tape. Improvements over version 1.0 include:F 1) Callable system sort is replaced by an internal Quick sort.A Performance on a MicroVAXes is substantually improved.$ 2) Numerous minor bug fixes.0 3) Format change for the /STATUS displayJ This version of What is upward and downward compatible with version ofH 1.0 so you do not need to upgrade all WHAT systems at the same time. - AwpM*****************************************************************************K A FAST Cluster and network-wide SHOW USERS (and Much more) type command. Authors:) Pete Portante, (most of the work) Andrew W. Potter David Mulvihill) Rochester Institute of Technology% Distributed and supported by: Andrew W. Potter Systems Programmer) Information Systems and Computing) Rochester Institute of Technology. Rochester NY, 14623 PH (716) 475-6994& Email: awpsys@ritvax.BITNET$ awp8101@ritcv.UUCP: **** Installation instructions are in WHAT.DOC ***KWHAT is a very fast utility that uses DECnet non-transparent communications8to produce three different displays. These displays are:C 1) A SHOW USERS like display from one or more DECnet nodes.A 2) A full user activity display. (Similar to the Unix "w" command.I 3) A one line summary of system activity, (User counts,uptime...)@ Qualifiers exist to effectly subset the user list. (I.E.; look only for users A,B and C on nodes X, Y, and Z)$ Complete online help exists.?What use a detached process that provides very fast response toAmultiple incomming network requests when serving a request from aremote system.= WHAT uses some of the following techniques for speed.D 1) Looks at process state BEFORE calling $getjpi to retrieveD information in P1 space. This allows WHAT to NOT request? that information if doing so would require a inswap.E 2) Does NOT use DECnet to retreive information from the local= node. For example assume the user is logged on to+ LARRY and he issues the command:- $ WHAT/NODE=(CURLY,LARRY,MOE)C What would connect to the non-transparent object only to0 retrieve the info from CURLY and MOE.B 3) Sends the qualifing information (/USER=userlist) to theC remote node for remote subsetting. This prevents havingC to transmit over the net large data buffers of ALL users- just to filter it all out locally.-*[ANONYMOUS.SAVE_SETS.NETWHAT]BUILD_WHAT.COM;1+,"./ 4I-0123KPWO56@/Ӓ7`'/Ӓ89GHJ!$ set protection = (world:re)/def#$ IF p1 .eqs. "LINK" THEN GOTO LINK$$! Creating What$$ pascal /noobj/envi what_defs$ pascal /nodebug/nocheck what $ macro /nodebug what_parseimage$ macro /nodebug what_look$ macro /nodebug what_status$ macro /nodebug dae_func$ macro /nodebug what_trnlnm$ macro /nodebug what_uptime$ macro /nodebug what_retnodes $ macro /nodebug what_buildusers$ message what_msg$ !$ ! Creating Daemon$ !$ cc /nodebug nd$ macro /nodebug getncb $ macro /nodebug what_parseimage$ macro /nodebug what_look$ macro /nodebug what_status$ ! $ ! Link them$ !$ LINK:D$ link/exe=what /nodebug/notrace what, what_parseimage, what_look, -C what_status, dae_func, what_trnlnm, what_uptime, what_retnodes, -( what_buildusers, what_msg, what/OptionI$ link/exe=nd /nodebug/notrace nd, getncb, what_parseimage, what_look, - what_status, nd.opt/option+*[ANONYMOUS.SAVE_SETS.NETWHAT]DAE_FUNC.MAR;1+,>.A/ 4pA>-0123KPWOB56 Jo5Ӓ75Ӓ89GHJ P;*******************************************************************************P;* *P;* Daemon Functions *P;* *P;*******************************************************************************; .title DAE_FUNC;J $dscdef ; Get the descriptor codesM $ssdef ; Get the system return codesH $iodef ; Get the IO definitionsO $prvdef ; Get the privilege definitionsR $syidef ; Get the system value definitions;;; Mask and function codes for daemon and look routine;!; +--+--+--+--+--+--+--+--+:; | | | | | | | | | Function code byte!; +--+--+--+--+--+--+--+--+!; 7 6 5 4 3 2 1 0;XDAE_M_CHANNEL = 128 ; Mask to use channel to get informationVDAE_M_STATUS = 64 ; Mask to get the status from the node]DAE_M_USER = 32 ; Mask to get the users on the specified listfDAE_M_NODE = 16 ; Mask for the node to be included in what ever formatJDAE_M_FULL = 8 ; Mask for the full format[DAE_M_SILENT = 4 ; Mask to shut off signaling of node errorsKDAE_M_ALL = 1 ; Mask to get all processes;hDAE_V_CHANNEL = 7 ; Bit which selects whether to use a channel or a buffernDAE_V_STATUS = 6 ; Bit which selects whether or not to just get the status infofDAE_V_USER = 5 ; Bit which selects whether to get the users specifiedgDAE_V_NODE = 4 ; Bit which selects whether the node should be includedXDAE_V_FULL = 3 ; Bit which selects brief or full formatTDAE_V_SILENT = 2 ; Bit which shuts off error messageshDAE_V_ALL = 0 ; Bit which selects either users or all system processes;; Sort constants;JBRIEF_USER_OFFSET = 1 ; Offset of brief usernameIFULL_USER_OF FSET = 0 ; Offset of full usernameFBRIEF_NODE_OFFSET = 11 ; Offset of brief nodeEFULL_NODE_OFFSET = 9 ; Offset of full nodeGSTAT_NODE_OFFSET = 0 ; Offset of status node;9; Constants for transfer values and storage;KDAE_USER_LEN = 8 ; Length the username takesRDAE_MAX_NODE_LEN = 6 ; Current maximum length of a nodeQDAE_MAX_NODES = 128 ; Max number of nodes to get infoPDAE_MAX_USERS = 128 ; Max number of users we can get]DAE_MAX_USER_STR = * DAE_MAX_USERS ; Maximum size of user string to searchMDAE_LRL = 80 ; Length of the return recordKDAE_MAX_REC = 2560 ; Maximum number of recordsKSTAT_LEN = 52 ; Length of status returnedfINFO_SIZE = 24000 ; Twenty four thousand bytes are capable of being sentmMAX_BUFFER = DAE_MAX_REC * DAE_LRL ; The maximum number of 80 byte records we'll accept is 2560.;.; Offsets into the status record;TOTAL_INT = 28TOTAL_BAT = 30TOTAL_NET = 32TOTAL_PRC = 34;2; Data areas for network information;K .psect dae_data, noexe, pic, noshr, lcl, wrt, rd, rel, con;L; Stat_buf is where we keep all the status information from the nodes.J; We have record size of STAT_LEN. The format of the record we store; here is:;3; Field Bytes6; +------------------+---------+6; | node | 0 - 5 |6; +------------------+---------+6; | op sys version | 6 - 13 |6; +------------------+---------+6; | cpu type | 14 - 17 |6; +------------------+---------+6; | boot time | 18 - 25 |6; +------------------+---------+6; | max # of proc | 26 - 27 |6; +------------------+---------+6; | interactive proc | 28 - 29 |6; +------------------+---------+6; | batch proc | 30 - 31 |6; +------------------+---------+6;  | network proc | 32 - 33 |6; +------------------+---------+6; | total proc | 34 - 35 |6; +------------------+---------+6; | load average | 36 - 47 |6; +------------------+---------+6; | freepages | 48 - 51 |6; +------------------+---------+;;; Data for SOR$ routines;Guser_offset: .word BRIEF_USER_OFFSET ; Key off set in stringLnode_offset: .word BRIEF_NODE_OFFSET ; Where the key is in string;Iret_len: .word 0 ; Length of return string;Qsignal_bool: .long 0 ; If this is clear, signal errors;; Data for Network stuff;Rnet_device: .ascid "_NET:" ; Descriptor for the net work name;Onet_obj: .ascii '::"252="' ; Net work object to connect toBlen_net_obj = .-net_obj ; Length of string;Mtrans_length: .long 0 ; Number of bytes to transferDfunc_code: .byte 0 ; User function codeXusers_len: .word 0 ; Initialy we aren't looking for anybodyOusers: .byte 32[DAE_MAX_USER_STR] ; String of users to search forkREQUEST_SIZE = . - func_code ; Determine size of string to send over in function request;(users_descr: .long DAE_MAX_USER_STRY .address users ; Descriptor for passing the users string;Qncb: .blkb 100 ; Net work connect block stucture?ncb_descr: .long len_net_obj ; Length of ncbN .address ncb ; Descriptor for connect block;Fnode_descr: .long DAE_MAX_NODE_LEN ; How long our node isR .address node ; Node we are currently talking to;@node_len: .long 0 ; Length of nodeRnode: .byte 32[DAE_MAX_NODE_LEN] ; Node we are currently talking to;Ecurr_node_len: .long 0 ; Length of this nodeScurr_node: .byte 32[DAE_MAX_NODE_LEN] ; Node we are currently residing on;Elocal_look: .byte 0 ; Can we look locallyFprv_mask: .long PRV$M_WORLD ; Set these privilegesO .long 0 ; Priv mask must be a quad word;8; SYI item list to get the system wide information;syi_list: .word 6% .word SYI$_NODENAME" .address curr_node& .address curr_node_len;A .long 0 ; End of SYI list;%; Data for system service calls;Aiosblk: ; IO status blockPcond_val: .word 0 ; Additional return value statusLtrans_cnt: .word 0 ; Number of bytes transferedFdev_spec: .long 0 ; Process id of daemon;Jbuf_quot: .long 128 ; Buffer quota for mailbox@dev_chan: .word 0 ; Device channelAmbx_chan: .word 0 ; Mailbox channel; buffer_len:Mbuffer_descr: .long 0 ; Number of bytes transferredKbuffer_adr: .address buffer ; Descriptor for local look;; Data buffers;N .psect dae_buffers, noexe, pic, noshr, lcl, wrt, rd, rel, con; stat_rec::stat_num: .blkb 1stat_tot_int: .blkw 1stat_tot_bat: .blkw 1stat_tot_net: .blkw 1stat_tot_prc: .blkw 1Istat_buf: .blkb STAT_LEN*DAE_MAX_NODES ; Reserve info for status;Obuffer: .blkb INFO_SIZE ; Total info that could be sent; data_rec::Odata_num: .blkl 1 ; We have no data to start withVdata_ptr: .blkl DAE_MAX_REC ; Total number of pointers into buffer;Gdata_buf: .blkb MAX_BUFFER ; Where to put all info;;;E .psect dae_code, con, exe, lcl, shr, nowrt, pic, rel;P;*******************************************************************************P;* *P;* DAE_GETINFO *P;* The purpose of this routine is to talk to each of the nodes specified *P;* and return the get the information from each, storing it all in sorted *P;* order. The information is returned to the caller through the other two *P;* procedures; DAE_RETURNINFO, DAE_RETURNSTATS *P;* *P;* Arguments: NODES - Address of buffer with following format : *P;* *P;* Byte Counted String - *P;* +------------+--------------+-----+ *P;* | # of nodes | Ascic String | ... | *P;* +------------+--------------+-----+ *P;* *P;* FUNC - function code to be executed by daemon, byte, by value *P;* - Bit 0: 1 all processes, 0 interactive only *P;* - Bit 1: Unused *P;* - Bit 2: Unused *P;* - Bit 3: 1 full format, 0 brief format *P;* - Bit 4: 1 node included, 0 node ommitted *P;* - Bit 5: 1 get users on list, 0 ingnore users *P;* - Bit 6: 1 status only, 0 both status and info *P;* - Bit 7: 1 use channel, 0 use buffer *P;* *P;* USER, address of a list of user names to search for. *P;* *P;* Returns: False if operation failed, True if connection was made *P;* *P;*******************************************************************************;H .entry dae_getinfo, ^m;V clrl signal_bool ; Clear our boolean signaling variable;G tstb @8(ap) ; Do we have any nodes?E bneq cont_getinfo ; Keep going if not 0P brw end_getinfo ; We have no nodes to get, error;%; Set up the sorting stuff here;Icont_getinfo: movb 4(ap), func_code ; Store the function codeZ bbcc #DAE_V_SILENT, func_code, get_nxt_arg ; Do we want errors signaledY mnegl #1, signal_bool ; Flag that we don't want errors signaled;Gget_nxt_arg: movl 8(ap), r11 ; Save address of nodesK movl 12(ap) , r10 ; Save address of usernames_ beql skip_username ; If zero was moved into r10, skip the username;. movc5 (r10), @4(r10), #32, -W #DAE_MAX_USER_STR, users ; Save the actual user matching string\ movw (r10), users_len ; Save the length to get passed over the netT movzwl (r10), users_descr ; Save the length for the descriptora addl3 #3, users_len, trans_length ; Save the actual number of bytes to transfer;I moval stat_buf, r8 ; Store our status bufferL moval data_buf, r7 ; Store our main data bufferF clrl r6 ; Count of total bytes;Hskip_username: $getsyiw_s - ; Get system information^ itmlst = syi_list ; Specifically, get the current node we are onD movc5 curr_node_len, curr_node, #32, #6, curr_node; $setprv_s -L enbflg = #1, - ; Enable the specified privsF prvadr = prv_mask ; What privs to enableO cmpl #SS$_NORMAL, r0 ; Could we get the needed privsU bneq skip_priv ; If we don't set the local look flag;U movb #1, local_look ; Do local looks for the current node;:skip_priv: bbc #DAE_V_FULL, func_code, setup_sort;l movw #FULL_USER_OFFSET, user_offset ; Change the offset values if we want the full formatR movw #FULL_NODE_OFFSET, node_offset ; - for the sort operations;Jsetup_sort: movzbl (r11)+, r9 ; Save the number of nodes;Jloop: movb (r11)+, node_len ; Save current node lengthV movc3 #DAE_MAX_NODE_LEN, (r11), node ; Save the node, left justifiedL movl r1, r11 ; Move past the current node;E cmpc5 node_len, node, #32, curr_node_len, curr_nodeW bneq call_daemon ; If they aren't equal, call the daemon;] tstb local_look ; Do we not have the priv to get info locallyU beql call_daemon ; If byte is zero, we don't have priv;b jsb get_local ; Get the information locally, if we have the privI brb loop_ctrl ; Skip calling the daemon;Ucall_daemon: jsb get_foreign ; Get the information from the daemon;Jloop_ctrl: sobgtr r9, loop ; Keep going if more nodes;H divl3 #DAE_LRL, r6, data_num ; Find number of records;^ movl data_num, r2 ; Save number of records to build the pointersI moval data_buf, r0 ; Where the records startK moval data_ptr, r1 ; Where to put the pointers;Lbuild_ptr: movl r0, (r1)+ ; Move address into the listJ addl2 #DAE_LRL, r0 ; Move to the next address> sobgtr r2, build_ptr ; Loop control;+ subl3 #1, data_num, -(sp) pushl #0E calls #2, quick ; Quick sort our data;R moval stat_buf, r0 ; Move address in for calculationsM subl3 r0, r8, r1 ; Subtract beginning from end*K divl3 #STAT_LEN, r1, r2 ; Find number of statistics $ movb r2, stat_num; ^end_getinfo: movl #1, r0 ; Return whether we talked to any nodes or not= ret ; Dae_getinfo*;*;*;*P;*******************************************************************************P;* Get_local *P;* Get the information locally *P;*******************************************************************************; Eget_local: clrl buffer_len ; We have no data yetp bbs #DAE_V_STATUS, func_code, get_local_stat ; Just get the local status if that bit is set;o% movzbl func_code, r0 R bicb2 #DAE_M_CHANNEL, r0 ; Make sure we don't get a channelW bisb2 #DAE_M_NODE, r0 ; We want the node included in the name_R pushal users_descr ; Pass the user name to search forN pushl r0 ; Pass the function to performS pushal buffer_descr ; Pass where to put the informationtZ calls #3, g^what_look ; Call the look routine to get informationI jsb storedata ; Store the data returned ; aget_local_stat: pushl #0 ; We want the infor returned in the buffer passedaP pushl r8 ; Here is where to put the stats? calls #2, g^what_status ; Get the stats B jsb sum_stats ; Sum up the statsE addl2 #STAT_LEN, r8 ; Move to next recordr;tB rsb ; End of Get_local; ; ; P;*******************************************************************************P;* Get_foreign *P;* This procedure establishes a connection to a node and gets all the *P;* information. The node is passed by a counted ascii string. *P;*******************************************************************************;eIget_foreign: clrl buffer_len ; Clear the buffer lengthSQ movc3 node_len, node, ncb ; Move the node name into the NCBTR movc3 #len_net_obj, net_obj, (r3) ; Move the rest of the stringa addl3 node_len, #len_net_obj, ncb_descr ; Add the node length to the descriptorf;t[ pushaw mbx_chan ; Address to receive mailbox channel numberZ pushaw dev_chan ; Address to receive device channel number? pushal buf_quot ; Mailbox quotaNV pushal buf_quot ; Largest size mailbox message allowedS pushaq net_device ; Address of device name descriptor V calls #5, g^lib$asn_wth_mbx ; Assign channel and associate mailboxC blbs r0, continue ; If LBC then errorAK brw failure ; Exit with an error status;_\continue: moval ncb_descr, r0 ; Save address of the network function blockP $qiow_s - ; Issue connect initiate requestF chan = dev_chan, - ; Use assigned channelH func = #IO$_ACCESS, - ; Request a logical linkL iosb = iosblk, - ; Address of IO status blockK p2 = r0 ; Address of NCB descriptor_C blbs r0, 10$ ; If LBC then errorK brw failure ; Exit with an error status;J10$: movzwl iosblk, r0 ) ; Get IO completion statusC blbs r0, send_func ; If LBC then erroreK brw failure ; Exit with an error statusy;Vsend_func: $qiow_s - ; Issue a write request to the mailboxF chan = dev_chan, - ; Use assigned channelN func = #IO$_WRITEVBLK,- ; Send a message to the daemonL iosb = iosblk, - ; Address of IO status blockN p1 = func_code,- ; Where the message to send isU p2 = trans_length ; Send the function code and the data-C blbs r0, 20$ ; If LBC then error K brw failure ; Exit with an error status ; J20$: movzwl iosblk, r0 ; Get IO completion statusC blbs r0, read_info ; If LBC then error|K brw failure ; Exit with an error status ; lread_info: bbs #DAE_V_STATUS, func_code, get_status ; Just get the local status if that bit is set; U $qiow_s - ; Issue a read request to the mailbox F chan = dev_chan, - ; Use assigned channelM func = #IO$_READVBLK, - ; Read a info from the daemon L iosb = iosblk, - ; Address of IO status blockT p1 = buffer, - ; Buffer to hold all the informationb p2 = #INFO_SIZE ; All three hundred DAE_LRL byte character stringsC blbs r0, 30$ ; If LBC then erroruK brw failure ; Exit with an error statusc;rJ30$: movzwl iosblk, r0 ; Get IO completion statusC blbs r0, move_transcnt ; If LBC then errorK brw failure ; Exit with an error statust;Vmove_transcnt: movzwl trans_cnt, buffer_len ; Save the number of bytes transferredR jsb storedata ; We receive information, store it; Uget_status: $qiow_s - ; Issue a read request to the mailbox F chan = dev_chan, - ; Use assigned channelP func = #IO$_READVBLK, - ; Read a message from the daemonL iosb = iosblk, - ; Address of IO status blockQ . p1 = (r8),- ; Where we should put the messagesL p2 = #STAT_LEN ; Receive all the statisticsC blbc r0, failure ; If LBC then errorJ movzwl iosblk, r0 ; Get IO completion statusC blbc r0, failure ; If LBC then errork;B jsb sum_stats ; Sum up the statsE addl2 #STAT_LEN, r8 ; Move to next recordrL $dassgn_s - ; Issue the deassign request' chan = dev_chanMD rsb ; End of Get_foreign;l; jfailure: blbs signal_bool, just_dassgn ; If we don't want to signal errors, skip LIB$SIGNAL call; I pushl r0 ; Push the error returned B pushal node_descr ; What node failedS pushl #1 ; How many arguments we are passingsO pushl #WHAT_TALKFAIL ; Failure talking to the daemoniB calls #4, g^lib$signal ; Signal the error;MLjust_dassgn: $dassgn_s - ; Issue the deassign request' chan = dev_chan ; G clrl r0 ; Return that we failed7 rsb ; Leavea; ;c;P;*******************************************************************************P;* Storedata *P;* This procedure is intended to take the information returned and add *P;* it to the accumulated data, if there is enough room. *P;*******************************************************************************; astoredata: tstl buffer_len ; If we don't have any process, skip sending them C beql end_storedata ; Branch to the end ; D subl3 r6, #MAX_BUFFER, r0 ; How much room left& cmpl buffer_len, r0M bgtr move_some ; Move only what we have leftt;t0 movc3 buffer_len, buffer, (r7)F movl r3, r7 ; Store ending address& addl2 buffer_len, r6: rsb ; Leave...; Kmove_some: addl2 r0, r6 ; We have filled the bufferk( movc3 r0, buffer, (r7)F movl r3, r7 ; Store ending address; Bend_storedata: rsb ; End of storedata; ; ; P;*******************************************************************************P;* Sum_stats *P;* This subroutine is intended to add the current statistic to the total. *P;***************************************************************************@~ NET_WHAT.BCK>+[ANONYMOUS.SAVE_SETS.NETWHAT]DAE_FUNC.MAR;1pAv4****; [sum_stats: addw2 TOTAL_INT(r8), stat_tot_int ; Sum up the total interactive jobs U addw2 TOTAL_BAT(r8), stat_tot_bat ; Sum up the total batch jobssW addw2 TOTAL_NET(r8), stat_tot_net ; Sum up the total network jobs U addw2 TOTAL_PRC(r8), stat_tot_prc ; Sum up the total processessJ rsb ; End of sum_stats;*;*;gP;*******************************************************************************P;* Quick *P;* This routine sorts the data pointers using the quick sort. *P;*******************************************************************************; B .entry quick, ^m;> movl 4(ap), r10 ; Left pointer? movl 8(ap), r11 ; Right pointer ; cmpl r10, r11" blss split_half ret ;esplit_half: pushl r11  pushl r10sE calls #3, split ; Split array in halfe movl r0, r9; % subl3 #1, r9, -(sp):E pushl r10 ; Sort the first half ! calls #2, quicko;t pushl r11 F addl3 #1, r9, -(sp) ; Sort the second half! calls #2, quickg;uB ret ; We have finished; ;1;aP;*******************************************************************************P;* Split *P;* This routine split the array in half, such that everything to the left *P;* of the split point is less then everything to the right of the split point. *;*2;* Register Use: R11 - Original Right index1;* R10 - Original Left indexn;;* R9 - Address of pointers to strings 4;* R8 - Pivot pointer to string+;* R7 - New left index*;*P;*******************************************************************************;rB .entry split, ^m; < movl 4(ap), r10 ; Left index= movl 8(ap), r11 ; Right index ;qI moval data_ptr, r9 ; Where data pointers are B movl (r9)[r10], r8 ; Save pivot point;eF addl3 #1, r10, r7 ; Leftindex is r10 + 1H ; Rightindex is just r11;fEwhile_left: cmpl r7, r11 ; End if left > rightg" bgtr final_swap; F movl r7, r6 ; Index to be comparedN jsb cmpr ; Cmpr index and pivot stringsH bleq while_right ; Go and check the rightP incl r7 ; Else increment to next elementD brb while_left ; Do it again sam...;uEwhile_right: cmpl r7, r11 ; End if left > rightr" bgtr final_swap; B movl r11, r6 ; Index to compareN jsb cmpr ; Cmpr pivot and index stringsP bgeq do_swap ; Swap the left and right indexsE decl r11 ; Move to next string D brb while_left ; Do it again sam...; $do_swap: movl (r9)[r7], r0L movl (r9)[r11], (r9)[r7] ; Swap left and right indexs% movl r0, (r9)[r11] I incl r7 ; Move to next left indexwJ decl r11 ; Move to next right indexP brw while_left ; Go back and do it again sam...; %final_swap: movl (r9)[r10], r0 O movl (r9)[r11], (r9)[r10] ; Swap left and right index ptrl% movl r0, (r9)[r11]g;tD movl r11, r0 ; Return split point> ret ; End of split; ;a;oP;*******************************************************************************P;* Cmpr *P;* This subroutine does the comparison of the current indexes and the *P;* pivot point. *P;*******************************************************************************; 'cmpr: movzwl user_offset, r0r" addl3 r0, r8, r2( addl3 r0, (r9)[r6], r3& cmpc3 #8, (r2), (r3)! beql test_node  rsbn;o'test_node: movzwl node_offset, r0 " addl3 r0, r8, r2( addl3 r0, (r9)[r6], r3& cmpc3 #6, (r2), (r3)@ rsb ; End of compare; ;  .endo locallyU beql call_daemon ; If byte is zero, we don't have priv;b jsb get_local ; Get the information locally, if we have the privI brb lo+*[ANONYMOUS.SAVE_SETS.NETWHAT]DAE_FUNC.OBJ;1+,e./ 4-0123KPWO56cӒ7.[Ӓ89GHJ 2DAE_FUNC0 3-NOV-1989 14:38 VAX MACRO V5.0-8MACRO/NODEBUG DAE_FUNC  wDATA_RECLIB$ASN_WTH_MBX LIB$SIGNAL STAT_REC SYS$DASSGN SYS$GETSYIWSYS$QIOW SYS$SETPRV WHAT_LOOK WHAT_STATUS WHAT_TALKFAIL . ABS .P$ABS$PPPPPgDAE_DATAP 3_NET:Q&Q ::"252=" '&Qd& ' '0, Ϳ DAE_BUFFERS7PQQQQQQQ]QQ(Q tDAE_CODEP  DAE_GETINFO&1Q##Ь[Ь Z7,j &j$;M addl3 4(ap), #4, r8 ; Save pointer to mbx message;C movzbl (r8)+, r2 ; Get the dev countF addl2 r2, r8 ; Skip over the stringO movzbl (r8)+, @8(ap) ; Get the byte count of the str;L movc3 @8(ap), (r8), @12(ap) ; Save the string in the NCB;? ret ; End of Getncb; .end)*[ANONYMOUS.SAVE_SETS.NETWHAT]GETNCB.OBJ;1+,./ 40-0123KPWO56ƊӒ7@Ӓ89GHJ0GETNCB0 3-NOV-1989 14:39 VAX MACRO V5.0-8MACRO/NODEBUG GETNCB  . ABS .P GETNCBCODEP GETNCB&XRRX(h **[ANONYMOUS.SAVE_SETS.NETWHAT]INSTALL.COM;1+,./ 4H-0123KPWO56@"9Ӓ7@{G9Ӓ89GHJ$ VM = 'F$VER(0)$!$!$ type sys$inputAThis procedure will install WHAT on your system disk, Install theDWHAT.CLD in SYS$COMMON:[SYSLIB]DCLTABLES.EXE and Install WHAT.HLP inSYS$COMMON:[SYSHLP]HELPLIB.;You need to have Built the images by running BUILD_WHAT.COM"before you can run this procedure.0$ inquire ans "Do you wish to do procede? [NO] "$ ans = f$edit("''ans'","trim")$ if ans.eqs."" then ans = "N"8$ if .not.ans then write sys$Output "What NOT installed"$ if .not.ans then exit$!$$ write sys$output "Installing WHAT"$!$ set proc/priv=all<$ create/dir/own=[1,4]/log/prot=(s:rewd,g:rewd,o:rewd,w:e) - sys$sysdevice:[net_what]6$ define/system/exec what_dir sys$sysdevice:[net_what]$! $ set noon $ copy *.exe what_dir:/prot=w:re $ copy *.com what_dir:/prot=w:Re $ copy *.cld what_dir:/prot=w:re $ copy *.hlp what_dir:/prot=w:Re$!;$ create/dir /prot=w:re/log sys$sysdevice:[net_what.source]H$ copy *.pas,*.c,*.msg,*.mar,*.opt,*.cld sys$sysdevice:[net_what.source]$ set def what_dir:#$ write sys$output "installing CLD"$ set command what.cld3$ set command/tables=sys$common:[syslib]dcltables -: /output=sys$common:[syslib]dcltables what.cld$ install == "$install/command"%$ install replace sys$share:dcltables$!'$ write sys$output "Installing HELP..." $ set noon $ set ver)$ library/help sys$help:helplib what.hlp$ VM = 'F$VER(0)$ type sys$input: Please remember to add the following lines to your' sys$manager:systartup.com file:; $ define/sys/exec what_dir sys$sysdevice:[net_what] $ @what_dir:start_what? You may want to customize the file WHAT_DIR:WHATLOG.COM- Installation complete.. Starting WHAT$!$@what_dir:start_what#*[ANONYMOUS.SAVE_SETS.NETWHAT]ND.C;1+,,.</ 4<9J-0123KPWO=56'?Ӓ7 6@Ӓ89GHJ #include #include #include #include #include #line 6 nd.c~#define DAE_M_CHANNEL 128 /* Mask to return info over a given channel */#define DAE_M_STATUS 64 /* Mask to just get the status from the node */#define DAE_M_USER 32 /* Mask to get the users on the specified list */|#define DAE_M_NODE 16 /* Mask to return the node in information */x#define DAE_M_FULL 8 /* Mask to return info in full format */#define DAE_M_ALL 1 /* Mask to return all processes in what ever format */o#define DAE_V_CHANNEL 7 /* Offset into function mask */o#define DAE_V_STATUS 6 /* Offset into function mask */o#define DAE_V_USER 5 /* Offset into function mask */o#define DAE_V_NODE 4 /* Offset into function mask */o#define DAE_V_FULL 3 /* Offset into function mask */o#define DAE_V_ALL 0 /* Offset into function mask */#define DAE_BRIEF 0 /* Get interactive processes in brief format */~#define DAE_FULL 8 /* Get interactive processes in full format */v#define DAE_SYSTEM 9 /* Get all processes in full format */z#define DAE_STATUS 64 /* Function code to just get the status */t#define DAE_MAX_USER_LEN 8 /* Maximum length for a user name */#define DAE_MAX_USERS 128 /* Maximum number of users we will translate */~#define DAE_MAX_USER_STR DAE_MAX_USERS * (DAE_MAX_USER_LEN + 1) /* Maximum size in bytes of matching string */d#define ___ 0 /* Null pa rameter */h#define TRUE 1 /* Boolean true value */i#define FALSE 0 /* Boolean false value */l#define EMPTY 0 /* Empty slot in CONNECTS */|#define FUNC_SIZE 3 + DAE_MAX_USER_STR /* Number of bytes in func_code, longword */t#define MAXMESGLEN 128 /* Max message length for mailbox */q#define MAX_LINKS 128 /* Max number of network links */{#define OBJ_NUM 252 /* Object number we are going to work on */struct iosblock{v short condition; /* Condition value of the operation */z short trans_cnt; /* Number of bytes actually transferred */s int dev_specific; /* Device specific return values */};sstruct nfb_block /* Network function block format */{r unsigned char func_code; /* Function code to the network */s int object_num; /* Argument to the function code */};pstruct blk_desc /* Descriptor for NFB and NCB */{c int size; /* Size of block */f int addr_blk; /* Pointer to block */};struct user_desc{m int length; /* Length of the user name */k int pointer; /* Pointer to the string */};struct com_blk /* Structure to hold connect info for each link */{d short channel; /* Channel number */a int unit; /* Unit number */n struct iosblock iosb;  /* I/O status block pointer */s char func_code; /* Function code to be performed */x short user_len; /* Length of the string to search for */o char user_string[DAE_MAX_USER_STR]; /* User string to search for */};jstruct itm_lst /* Item list for GETDVI */{k short length; /* Length of item buffer */h short item_code; /* Item code for item */i int buf_addr; /* Item buffer address */m int buf_len; /* Length of returned info */p int endoflist; /* End of item list of GETDVI */};nshort daemon_chan; /* Channel for Daemon's MBX */eshort mbxchan; /* Mailbox channel */ichar mbxmesg[MAXMESGLEN]; /* Buffer for MBX mesg */istruct iosblock iostatus; /* QIO io status block */hstruct iosblock ast_iostat; /* Ast iostatus block */rstruct blk_desc ncb_desc; /* Descriptor for connect block */kchar ncb[100]; /* Network connect block */kstruct blk_desc nfb_desc; /* Descriptors for above */lstruct nfb_block nfb; /* Network function block */nstruct user_desc user_name; /* Descriptor for user name */oint link_cnt; /* Count number active links */ostruct com_blk connects[MAX_LINKS]; /* Array of link info blocks */h$DESCRIPTOR(device,"_NET:"); /* Name of net device */h$DESCRIPTOR(mbx_name,"DAEMON$MBX");  /* Object mailbox */P/******************************************************************************/P/* What_daemon */P/* This program is intended to as a server for looking up the current */P/* process on the system. This can be done individually or through multiple */P/* requests. */P/******************************************************************************/main(){v int stat; /* Return status for function calls */k int i; /* Loop control variable */y link_cnt = 0; /* Set our link count to zero initialy */u nfb_desc.size = 5; /* Net function block for object # */t nfb_desc.addr_blk = &nfb; /* Size and integer function code */e nfb.func_code = NFB$C_DECLOBJ; /* Fill in network */b nfb.object_num = OBJ_NUM; /* Function blk */ ncb_desc.size = 100; /* Network control block descriptor length and */o ncb_desc.addr_blk = ncb; /* Length and pointer to NCB */' for (i = 0; i < MAX_LINKS; i++) {y clearconnect(i); /* Clear out all the connection blocks */ }/* Create Daemon mailbox */g stat = sys$crembx(___, /* Perm or temp flag */e &mbxchan, /* Mailbox channel */l &MAXMESGLEN, /* Maximum message length */b ___, /* Buffer quota */e ___, /* Protection mask */a ___, /* Access mode */j &mbx_name); /* Logical name for MBX */$ if (~stat&1) lib$stop(stat);/* Assign channel to device */a stat = sys$assign(&device, /* Device name */m &daemon_chan, /* Returned channel number */a ___, /* Access mode */b &mbx_name); /* Mailbox name */t if (~stat&1) lib$stop(stat); /* Stop if a severe error message */6/* Use QIO call to declare process a network object */` stat = sys$qiow(___, /* Event flag */d daemon_chan, /* Device channel */g IO$_ACPCONTROL, /* QIO function code */b ___, /* Iostatus blk */a ___, /* AST address */^ ___, /* AST parm */k &nfb_desc, /* P1 - net function blk */] ___,___,___,___,___); /* P2 - p6 */ if (~stat&1) { lib$signal(stat); /* Signal a message and stop if a major error */+ lib$signal(iostatus.condition); }j stat = set_mbx_ast(); /* Enable communication */h if (~stat&1) lib$stop(stat); /* (mailbox read ast) */j stat = sys$hiber(); /* Go to sleep (zzz...) */~ if (~stat&1) lib$stop(stat); /* Signal a message and stop if major error */ exit(); } /* Main */P/******************************************************************************/P/* Set_mbx_ast */P/* This procedure is used to initialize the mailbox AST. */P/******************************************************************************/ set_mbx_ast(){x  int mailbox_ast(); /* Routine to call upon IO completion */r int stat; /* Status value of system calls */z stat = sys$qio(___, /* QIO issue of AST routine on full mbx */a mbxchan, /* MBX channel */v IO$_READVBLK, /* Read virtual block function code */h &ast_iostat, /* AST I/O status var */~ mailbox_ast, /* Routine to execute when message comes in */ ___,h &mbxmesg, /* MBX message buffer */l MAXMESGLEN, /* Maximum message length */! ___,___,___,___); return;} /* Set_mbx_ast */P/******************************************************************************/P/* Mailbox_ast */P/* This procedure is intended to handle the AST on a mailbox. */P/******************************************************************************/ mailbox_ast(){t int unit; /* Unit number of current message */n int index; /* Index into connect table */y int stat; /* Status return value of system calls */s short mesgtype; /* Word for the message returned */m if (~ast_iostat.condition&1) return; /* Stop if AST QIO was bad */{ mesgtype = *(short *)&mbxmesg[0]; /* Extract message type from mbx message */i unit = *(short *)&mbxmesg[2]; /* Extract unit number */r switch (mesgtype) /* What message was received... */ {l case MSG$_CONNECT: /* Handle connect request */k if (connect_accept(&index)) /* See if we can connect */q stat = read_chan(index); /* If we can, read the channel */ elsey disconnect(index); /* Disconnect the index, if one exists */o stat = set_mbx_ast(); /* Set the mailbox AST again */{ return; /* Go back to sleep until next AST fires */l case MSG$_NETSHUT: /* Handle DECNET shutdown */g stat = sys$wake(___,___); /* Wake ourselves up */ return;y case MSG$_REJECT: /* Rejection and confirmation requests */" case MSG$_CONFIRM:x stat = set_mbx_ast(); /* Just wait for another mail message */ return;2s case MSG$_ABORT: /* Handle multitude of abortions */T! case MSG$_DISCON:  case MSG$_EXIT: ! case MSG$_INTMSG:e# case MSG$_PATHLOST: # case MSG$_PROTOCOL: % case MSG$_THIRDPARTY:h" case MSG$_TIMEOUT:p index = findunit(unit); /* Find the unit number given */ disconnect(index); /* Do we have to get rid of any connect info */Ap stat = set_mbx_ast(); /* - when we disconnect them? */ return;Ez DEFAULT: /* Handle fall through invalid requests */' exit(mesgtype); j } /* End switch statement */return; } /* Mailbox_ast */tP/******************************************************************************/P/* Connect_accept */P/* This procedure is intended to handle the connect request from another */P/* node, and determine if we can handle a link to ~ NET_WHAT.BCK,#[ANONYMOUS.SAVE_SETS.NETWHAT]ND.C;1<,$it or not. */P/******************************************************************************/connect_accept(index)Gsint *index; /* Index into array of link blks */ { d int unit; /* Unit of device */s int dummy_len; /* Dummy place to put the length */ i int stat; /* Status return value */ t int ret_code; /* Code to return upon completion */| int dev_chan; /* Device channel we are going to talk on */y struct itm_lst items; /* We need an item list for SYS$GETDVI */ p struct iosblock iosb; /* We need an IO status block */i items.length = 4; /* itemlist for GETDVI */ k items.item_code = DVI$_UNIT; /* We want a unit nubmer */ k items.buf_addr = &unit; /* Where to put the unit */ d items.buf_len = &dummy_len; /* Length of unit */j items.endoflist = 0; /* Set end of item list */t *index = -1; /* We don't point to anything yet */x getncb(&mbxmesg, &ncb_desc, &ncb); /* Get the NCB of the calling process */w if (link_cnt MAX_LINKS-1) return(-1); /* If we have reached this point, we have probs */} /* findunit */ P/******************************************************************************/P/* Clearconnect */P/* This routine will clear out a given connect block */P/******************************************************************************/clearconnect(index) sint index; /* Which connection to clear out */ { k int i; /* Loop control variable */ o connects[index].unit = 0; /* Clear out the unit number */ r connects[index].channel = 0; /* C8lear out the channel number */t connects[index].func_code = 0; /* Clear out the function request */r connects[index].user_len = 0; /* Initialize character to zero */. for (i = 0; i < DAE_MAX_USER_STR; i++) {;o connects[index].user_string[i] = 32; /* Blank out the user string */ } n link_cnt = link_cnt - 1; /* Decrement our link count */} /* clearconnect */*ignal a message and stop if major error */ exit(); } /* Main */P/******************************************************************************/P/* Set_mbx_ast */P/* This procedure is used to initialize the mailbox AST. */P/******************************************************************************/ set_mbx_ast(){x %*[ANONYMOUS.SAVE_SETS.NETWHAT]ND.EXE;1+,-./ 4-0123 KPWO56ExӒ7jӒ89GHJ0DX0205(SNDV1.0MӒ05-052  #% .&TX]  ? ! VAXCRTL_001! LIBRTL_001! MTHRTL_001_NET:DAEMON$MBX K !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ --- ---SuspendedSwapped CPGMWTCEFPFWLEFLEFHIBHIBSUSSUSFPGCOMCOMCUR -Det- -Net- -Bat- -Disc--Sub-  !AD !+!+!XL !AF !+!+!AD'!AD !+!+!XW !AF !AD !AD !AD !AD !AD !ADL !AD !AD !XL !AF !+!+!AD'p!AD !AD !XW !AF !AD !AD !AD !AD !AD !ADDh ͫm\mMm\"MͫނDDDB@!LAV0:43o~E9A^= RTSdbbdc\\A\ݚ|~߭?GP\\ P ﭚ? PP\\ P |~|~d|~82ٙ~ P\\P 2ƙ~z 0P\\ P` P\\ PJ / P^|~|~~P12j~  ^XRP\\bP2S2PPP0 bZ"bbbbbZbbPf?P߭UPݭt PݭbX|~FSuPݭ1'<(^PSTU ޭޭԭЬRb eyd1߭=PPQQPPQP|~|~ݭPQQPPQPPbŏbPQ@cPQ`ŏbP@PЭ`d|~|~e|~2ݭ PPP2PR.P|~|~e|~2~ PPP2PRRP^NR|~|~<~ŏQAݬA1AbP2`~  ^NR@SŏQAP`1AQ1QPP --- P>?PP@?PŏQAPP3PAAAP2`cAcA~Ab~ŏP@b^ЬRR#ŏRP@MP2`~R5^MQRŏRP@P`RPRRP^MRŏP@Qa@bQa@@P`SŏP@Q SӕXRRX(h VᅱWXYЬ[Ь Z2[ [m[[|~  |~ |~0,A , |~ я P1$PǑj: PP9Pj1)j1.' `1W::Lt :a<|~*<~_C,1 ).   , P(@((   , E1|~ P6hvpHsm#, Ǐd`2T"P,@i "KfX,} PgSW1ÓQZQWj,j禎 jQWV|~|~V|~<0~?PP@?PŏQAPP3PAAAP2`cAcA~Ab WHAT_LOOK~ŏP@b WHAT_STATUS^ЬRR#ŏRP@ P2`~ SYS$DASSGNR CLEARCONNECT^ QRŏRP@P`RPRRP^ RŏP@QԲ <CONNECT_ACCEPT ( READ_CHAN j READ_AST $ DISCONNECT ZFINDUNIT  CLEARCONNECTC$MAIN$CODE$DATA DAEMON_CHANMBXCHANMBXMESGIOSTATUS AST_IOSTATNCB_DESCdNCBNFB_DESCNFB USER_NAMELINK_CNTHCONNECTSDEVICE$CHAR_STRING_CONSTANTSMBX_NAMEoa@bQa@@P`SŏP@Q S P---zPbZ"bbbbbZbbP%*[ANONYMOUS.SAVE_SETS.NETWHAT]ND.OPT;1+,; ./ 42-0123KPWO56 AӒ7AӒ89GHJsys$share:vaxcrtl/sharesys$system:sys.stb/sel-*[ANONYMOUS.SAVE_SETS.NETWHAT]START_WHAT.COM;1+,./ 4J-0123KPWO56BzCӒ7[CӒ89GHJ $! $ set noon$!$! START_WHAT.COM:$! Procedures starts (or restarts) the network what Daemon:$! and defines and installes necessary logicals and images$!@$! Note: SITE SPECIFIC WHAT logical names should be defined in$! WHATLOG.COM.$!$!I$!***********************************************************************$!'$ what_disk = f$trnlnm("SYS$SYSDEVICE")$ mynode = f$getsyi("NODENAME")$!6$ define/sys/exec/nolog what_dir 'what_disk'[net_what]$!%$! set up site specific logical names$!:$! Define WHAT_xxx logical names to set up specific lists#$! for the WHAT/SELECT=xxx option.$!$!G$ if f$search("WHAT_DIR:WHATLOG.COM").nes."" then @what_dir:whatlog.com$!J$!************************************************************************F$ reqprv = "CMKRNL,ACNT,SYSPRV,DETACH,WORLD,SYSNAM,NETMBX,TMPMBX,OPER"$ old_priv = f$setprV(reqprv)F$ if .not.f$privilege(reqprv) then write sys$output "''f$message(36)'"+$ if .not.f$privilege(reqprv) then goto end$!"$!******** install sharable images$!I$! Since both WHAT and the Daemon access the following RTLs, Ensure that$! they are /SHAREd$!7$! define/nolog/sys/exec what_shr what_dir:what_shr.exe$!$ install = "$install/command"?$ if f$file_attritibutes("SYS$SHARE:PASRTL.EXE","KNOWN") then -$ install remove sys$share:PASRTL@$ if f$file_attritibutes("SYS$SHARE:LIBRTL2.EXE","KNOWN") then -% install remove sys$share:LIBRTL2<$ if f$file_attritibutes("what_dir:what.exe","KNOWN") then -% install remove WHAT_DIR:WHAT.EXE $ install$add sys$share:pasrtl/open/head/share%add sys$share:librtl2/open/head/share2add what_dir:what.exe/open/head/share/priv=(world)$!$! $! Start (or Restart the Daemon)$!$$ default = f$environment("default")$ set def what_dir:$ user = f$user()$ set uic [1,4]$ set mess/nof/nos/noi/not$ stop "Netwhat_daemon"$ wait 00:00:01.00$! $ mcr ncpclear obj netwhat all$ set mess/f/i/s/t$ run sys$system:ncpset obj netwhat NUMBER 252$ run/detached - /uic=[1,4]-4 /priv=(nosame,sysprv,netmbx,tmpmbx,sysnam,world) - /prio=5 what_dir:nd.exe - /process="Netwhat_daemon" - /noaccounting -) /output=what_dir:whatlog_'mynode'.log -& /err=what_dir:whatlog_'mynode'.err - /page=10000 - /file_limit=40 - /ast_limit=30 - /maximum_working=768 - /extent = 1024 - /buffer_lim = 10240 - /enque_limit = 30 - /io_buffer = 50 - /working = 300$ set uic 'user'$ set def 'default'$ end:$ foo = f$setprv(old_priv)'*[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT.CLD;1+, . / 4c -0123KPWO 56qEӒ7^EӒ89GHJ P!*******************************************************************************P!* WHAT *P!* Verb that returns various combinations of user formats from different *P!* nodes. *P!*******************************************************************************define verb what image what_dir:whatO qualifier node, value(required, type=$file, list) ! Get specified nodes^ qualifier select, value(required, type=$file) ! Select a particular group of nodesT qualifier user, value(required, type=$file) ! Select a particular userP qualifier brief, default, negatable ! In show users formatQ qualifier full, negatable ! In where/users formatR qualifier all ! Show all the processesT qualifier status, negatable ! Output status lines onlyc qualifier silent ! Dont output errors talking to the nodesN qualifier total, negatable ! Total up /STATUSes^ qualifier header, default, negatable ! Do we want the header line presentV qualifier output, value(required, type=$file) ! Send output to a file name disallow select and node disallow brief and all disallow brief and full1 disallow total and (full or all or brief): disallow status and (all or brief or full or user)P!*******************************************************************************P!* Note: The /SELECT qualifier will take a given value, and translate the *P!* logical name WHAT_value to get a list of the nodes to get info on. *P!* For instance, WHAT/SELECT=CLUSTER would translate the logical name *P!* WHAT_CLUSTER and talk to all the nodes there. Define WHAT_value *P!* in this manner: *P!* *P!* DEFINE WHAT_cluster node0, node1, node2, ... , nodeN *P!* *P!* Using this technique, one could set up various combinations of *P!* nodes to be search, i.e. One for your cluster, you local network, *P!*  specific work nodes, etc. *P!*******************************************************************************'*[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT.DOC;1+, ./ 4N 8-0123KPWO56`mGӒ7@GӒ89GHJ " WHATK A FAST Cluster and network-wide SHOW USERS (and Much more) type command. Authors:) Pete Portante, (most of the work) Andrew W. Potter David Mulvihill) Rochester Institute of Technology% Distributed and supported by: Andrew W. Potter Systems Programmer) Information Systems and Computing) Rochester Institute of Technology. Rochester NY, 14623 PH (716) 475-6994& Email: awpsys@ritvax.BITNET$ awp8101@ritcv.UUCPKWHAT is a very fast utility that uses DECnet non-transparent communications$to produce three different displays.J WHAT is distributed in Source (PASCAL, VAX C and MACRO 32 needed),G object and executable form. WHAT must be relinked to run under9 VMS V5 Executables are in the subdirectory [.V5]. Relinking:B WHAT may be relinked to run under V5 by setting default to+ the [.source] directory and typing:" $ @BUILD_WHAT LINK Features: $ WHATE Produces a SHOW USERS like display of users on this system& $ WHAT/NODE=(node1[,node2...])G Same as above except it generates the display from all of the specified systemsH /FULL Generates a full display of (somewhat like Unix FINGER)> /ALL Lists ALL processes (only for use with /FULL)$ /USER=(user1,[user2,...])H Qualifies the list to only report on the specified users.G /USER can also translate the logical name WHAT_USER_list< for a list of preferred users. See Help WHAT= /OUTPUT=filename Redirects output from SYS$OUTPUTC /SILENT Directs what to not report an error of failure1 to connect to a remote node.0 /NOHEADER Eliminates the header line. And more- $ WHAT/NODE=(node1[,node2...])/STATUS7 Prints a one line status line for each systemH The above command can be qualified with the following qualifiers= /OUTPUT=filename Redirects output from SYS$OUTPUTC /SILENT Directs what to not report an error of failure1 to connect to a remote node.C /TOTAL Generates a total line for the systems reported: As an alternative to /NODE=(list) users can set upE logical names to list pr~ NET_WHAT.BCK '[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT.DOC;1N\eferred groups of nodes that run WHAT* for use with the /SELECT qualifier EG.) $ define WHAT_CLUSTER FOO,BAR,ZOT: $ what/select=cluster [/any other what qualifiers]$ Will give the same result as! WHAT/NODE=(FOO,BAR,ZOT)= WHAT uses some of the following techniques for speed.D 1) Looks at process state BEFORE calling $getjpi to retrieveD information in P1 space. This allows WHAT to NOT request? that information if doing so would require a inswap.E 2) Does NOT use DECnet to retrieve information from the local= node. For example assume the user is logged on to+ LARRY and he issues the command:- $ WHAT/NODE=(CURLY,LARRY,MOE)C What would connect to the non-transparent object only to0 retrieve the info from CURLY and MOE.C 3) Sends the qualifying information (/USER=userlist) to theC remote node for remote subsetting. This prevents havingC to transmit over the net large data buffers of ALL users- just to filter it all out locally.% Installation:I NOTE: If you wish you may perform the complete installation with INSTALL.COM.A 1)Create a WORLD executable directory somewhere. (Assume Sys$sysdevice:)2 $ CREATE/DIR/prot=w:e/own=system -0 sys$sysdevice:[net_what]F 2) Define an exec mode logical name to point to that directoryC $ define/sys/exec WHAT_DIR sys$sysdevice:[what_dir]< 3) Copy all the files in this directory to WHAT_DIR:B 4) Modify if desired the logical names in WHAT_DIR:WHATLOG> to define site specific node groups for WHAT/SELECTC 5) Apply the CLD WHAT_DIR:WHAT.CLD to the system dcltables.< SET COMMAND/TABLES=SYS$COMMON:[SYSLIB]DCLTABLES -< /OUTPUT=SYS$COMMON:[SYSLIB]DCLTABLES -' WHAT_DIR:WHAT.CLDN Use install to replace the DCLTABLES (need about 300 GBLPAGES free)* $ INSTALL == "$INSTALL/COMMAND"2 $ INSTALL REPLACE SYS$LIBRARY:DCLTABLESC (Or you put the command SET COMMAND WHAT_DIR:WHAT.CLD in2 the users login.com files...Slow...Ugh)J 6) Apply the file WHAT_DIR:WHAT.HLP to your favorite help library.< $ LIBRARY/HELP SYS$HELP:HELPLIB WHAT_DIR:WHAT.HLP9 7) Add to your site specific startup command file9 SYS$MANAGER:SYSTARTUP.COM the following lines:C $ DEFINE/SYS/EXEC WHAT_DIR sys$sysdevice:[net_what]& $ @what_dir:start_what; 8) Start WHAT with the command @WHAT_DIR:START_WHATH Note: All cluster members CAN run WHAT from the same directoryC Now go do the same thing on all other systems with reach to- make it a useful network wide utilityI========================================================================='*[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT.EXE;1+,,.#/ 4#!-0123 KPWO$56uݨӒ7IӒ89GHJ@0DX0205()SXTUDWHAT01 h)Ӓ05-052   . +,  ?! LIBRTL_001+g PASRTL_001:  _NET:::"252=" / ! LNM$FILE_DEVWHAT_USER_   E !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ --- ---SuspendedSwapped CPGMWTCEFPFWLEFLEFHIBHIBSUSSUSFPGCOMCOMCUR -Det- -Net- -Bat- -Disc--Sub- {. !AD !+!+!XL !AF !+!+!AD'.!AD !+!+!XW !AF !AD !AD !AD !AD !AD !AD. !AD !AD !XL !AF !+!+!AD'.!AD !AD !XW !AF !AD !AD !AD !AD !AD !ADs.... N/>/01//./(//6/>/011/>/1(/a11a11a1"11a1./a16/a1>/1/a1N/ 1!1a1)1a11a12NODE 2ނDDDB@3LAV0:43443 43434 `4LNM$FILE_DEVWHAT_l4 |6666y5x6 STATUS (Unavailable) TOTAL Interactive Users, Batch Jobs, Total ProcessesHEADERInteractive UsersTotal number of interactive users = Username Node PID Process Name TerminalInteractive UsersTotal number of interactive users = Username Node Pid Process Name Group Term Login Ste Cpu ProgramProcess Summary Interactive Users, Batch Jobs, Total ProcessesUsername Node Pid Process Name Group Term Login Ste Cpu ProgramStatus Summary from Node on at Node Up Ver Cpu Pages Int Bat Tot Load AveragesSILENTUSEROUTFILESELECTNODEFULLALLSTATUSOUTPUTSYS$OUTPUT^54<&[PPF~yuqm\\VVP@P`(4VP@W(g}ԧԧ "ԧ$ԧ(ԧ,ԧ0\4^^, P8: P1*W4W41cW4P@i[( <؟ذаҞԟПj1)j-1. 1W:: :a|~w<~_, .   , tP(@N(R.(K9K B9  0, ( 1|~/o P6 H , zǏd"P,@i KfX, PgSW1]}QJZ?QWj,jC} jQWV|~|~V.}|~F<0~ Invokes the WHAT utility to report user information on one orC more VMS systems in the network. WHAT with no qualifiers produces< a "SHOW USERS" like display of users on the current system.! WHAT is an RIT developed utility 2 Qualifiers/ALL /ALL? Directs WHAT to include system processes in the display. ThisE qualifier generates the same display format as /FULL. This qualifier. is ignored unless it is specified with /FULL./BRIEF /BRIEF (Default)@ Directs WHAT to produce a SHOW USERS like display. This is the default action for WHAT./FULL /FULLE Directs WHAT to expand the /BRIEF to provide a more detailed list of( user processes on the specified node(s)/HEADER /HEADER (Default) /NOHEADER< Specifies whether or not a header line precedes the report /USERNAME /USERNAME=stringE 1) Directs WHAT to subset the report generated by /BRIEF, /FULL and? /FULL/ALL to include only those processes that belong to a& username beginning with "string".H 2) If the user has defined a logical name "WHAT_USER_string" then WHATG will translate this logical name for a list of users to use in theF subset operation. Logical Names may have up to 127 translations./STATUS /STATUSE Directs WHAT to produce a one line system status report for each of the specified nodes./SILENT /SILENT /NOSILENT (Default)D Directs WHAT to not display the VMS error messages that are caused. by inability to connect to any remote nodes./TOTAL /TOTALB Directs WHAT to report a total line of Processes, Users and Batch< jobs. This qualifier applies only to the /STATUS qualifier./OUTPUT /OUTPUT=filenameI Redirects the report from WHAT to the specified filename. The filename( is required when /OUTPUT is specified./NODE /N0DE=(NODE[,...])? Specifies one or more nodes for WHAT to query. Do NOT specify# the nodename with two colons "::"/SELECT /SELECT=xxxxxD Directs WHAT to translate the logical name WHAT_xxxxx for the listH of nodes to translate. There are a set of default node groups defined= on the system. These may be determined by the DCL command:$ $ SHOW LOGICAL/SYSTEM WHAT_*8 You may define your own groups of interest as follows:' $ DEFINE WHAT_ME VAXA,VAXB,VAXCE The command WHAT/SELECT=ME will report on the nodes VAXA, VAXB and VAXC. 2 Examples 1) $ WHAT/SELECT=RITVAXE Generates a SHOW USERS like display of all users logged in to the RITVAX VAXcluster.$ 2) $ WHAT/NODE=(VAXA,VAXB,VAXIMG)E Generates a SHOW USERS like display of all users logged in to' The nodes VAXA, VAXB and VAXIMG! 3) $ WHAT/SELECT=RITVAX/STATUSB Generates a report of system utilization on all systems in the RITVAX cluster' 4) $ WHAT/FULL/SELECT=RITVAX/USER=BEG Generates a full users report for all users who have a username& beginning with the string "BE" 5) Logical ListsE You may define a list of users for use in the /USER subsetting' operations as a list as follows.# $ define WHAT_USER_MYLIST - ABC1234,- BCDICS, - 999DEPT,- JKL9876( $ WHAT/SELECT=RITVAX/USER=MYLISTD Causes WHAT to look for specified users in WHAT_USER_MYLIST on RITVAX 2 Authors) Pete Portante, (most of the work) Andrew W. Potter David Mulvihill) Rochester Institute of Technology% Distributed and supported by: Andrew W. Potter Systems Programmer) Information Systems and Computing) Rochester Institute of Technology. Rochester NY, 14623 PH (716) 475-6994& Email: awpsys@ritvax.BITNET$ awp8101@ritcv.UUCP1 Any Questions please send Electronic Mail'*[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT.OBJ;1+,A./ 4-0123KPWO56(wӒ7`Y{Ӓ89GHJ/WHAT01 3-Nov-1989 14:38 3-Nov-1989 14:38VAX Pascal V3.9-289P Q Q STATUSQ Q (Unavailable) QTOTALQ Interactive Users, Batch Jobs, Q Total ProcessesHEADERQInteractive UsersQTotal number of interactive users = Username Node PID Process Name TerminalQInteractive UsersQTotal number of interactive users = Username Node Pid Process Name Group Term Login Ste Cpu ProgramProcess SummaryQ Interactive Users, Batch Jobs, Q Total ProcessesUsername Node Pid Process Name Group Term Login Ste Cpu ProgramStatus Summary from Node Q on at Node Up Ver Cpu Pages Int Bat Tot Load AveragesSILENTQUSEROUTFILESELECTQNODEFULLALLQSTATUSQOUTPUTQSYS$OUTPUT^PAS$DATE PAS$TIME< LIB$GETSYIPP LIB$SIGNAL,STAT_RECSTAT_REC3STAT_REC3STAT_REC3STAT_REC3\\VVP@&P`(4VP@STAT_REC3W(g}ԧԧ "ԧ$ԧ(ԧ,ԧ0\4^^, P8: CLI$PRESENTP1WSTAT_REC4W41W4P@STAT_REC3[( <؟ذаҞԟП WHAT_UPTIME 0 thenB writev(temp_string, day:2, '+', boot_string); else temp_string := ' ' + boot_string;* if load_avg[1] < 0 then> writev(load_string, ' (Unavailable) ')i else writev(load_string, load_avg[1]:5:2, ' ', load_avg[2]:5:2, ' ', load_avg[3]:5:2); writeln(outfile, node_name, ' ':3, temp_string, ' ':3, opr_sys:4, ' ':3, cpu_type, ' ':3, freepages:6, ' ':3,n inter_proc:3, ' ',batch_proc:3, ' ', total_proc:3, ' ':3, load_string:17); end; { with }4 if cli$present('TOTAL') = CLI$_PRESENT then begin writeln(outfile);j writeln(outfile, stats.tot_int:1, ' Interactive Users, ', stats.tot_bat:1, ' Batch Jobs, ',E stats.tot_prc:1, ' Total Processes'); end; { then } end { then }( else for loop := 1 to data.num_rec do begin1 infostring := data.data_buf[loop]^;l status := str$trim(infostring, infostring, len); { Trim the returned string }r writeln(outfile, infostring:len); { Print out the shortened string } end; { for }i close(outfile); { Close the output file }end; { printoutput })procedure setupoutput(var outfile: text);varn len: $uword; { Return length of the value }n filename: varying [256] of char; { Filename that is specified }begin filename.length := 256; { Initialy our filename can be 256 chars long }p len := 0; { Initialize the return length }{ if cli$get_value('OUTPUT', filename, len) <> CLI$_ABSENT then { If there is a value on the line, get it } begin} filename.length := len; { Set the length to that which was returned }a open(outfile, filename, new); { Open the file } end { then }r else open(outfile, 'SYS$OUTPUT', new); { Open the terminal we are using }d rewrite(outfile); { Rewrite the file }end; { setupoutput }/procedure getnodes(var nodes: dae_nodes_descr);var len: $uword; stat: integer;# log_name: varying [255] of char;begin log_name.length := 255;{ if cli$get_value('SELECT', log_name, len) <> CLI$_ABSENT then { If there is a value on the line, get it } begin log_name.length := len;& what_trnlnm(nodes, log_name); end { then }2 else if cli$present('NODE') <> CLI$_ABSENT then what_retnodes(nodes) else begin% nodes.num_nodes := 1;= nodes.node_arr[1].length := curr_node.length;9 nodes.node_arr[1].node_name := curr_node; end;end; { getnodes }*procedure getfunction(var func: unsigned);begin if cli$present('FULL') = CLI$_PRESENT then { If FULL is present, then see if all is present }l if cli$present('ALL') = CLI$_PRESENT then { If ALL is present , then } func := DAE_SYSTEM { - we want all system processes in full format } else func := DAE_FULL { We just want the full format of user processes }p else if cli$present('STATUS') = CLI$_PRESENT then { If they want the status then }i func := DAE_STATUS { - just get the status } else func := DAE_BRIEF; { We just want a brief format of user processes }end; { getfunction }Ffunction getinfo(var nodes: dae_nodes_descr; func: unsigned): boolean;var len: $uword;% comm_value: varying [256] of char; users: dae_match_buffer;begin{ if cli$present('SILENT') = CLI$_PRESENT then { If /SILENT, don't signal error messages }& func := uor(DAE_M_SILENT, func); users.length := 0; comm_value.length := 256;B if (cli$get_value('USER', comm_value, len) <> CLI$_ABSENT) then begin" comm_value.length := len;1 what_buildusers(users, comm_value, len); users.length := len; end; { then }. getinfo := dae_getinfo(func, nodes, users);end; { getinfo }[initialize] procedure setup;var stat, loop: integer; syi_func: unsigned; len: $uword;begin date(date_str);q time(time_str); { Get the date and time strings } syi_func := SYI$_NODENAME;r stat := lib$getsyi(syi_func,,curr_node,len); { Get the current node we are on }* if not odd(stat) then lib$signal(stat);b curr_node.length := len; { Get its length } nodes.num_nodes := 0;s stats.num_stats := 0; { Initialize all static variables } stats.tot_int := 0; stats.tot_bat := 0; stats.tot_net := 0; stats.tot_prc := 0;( for loop := 1 to DAE_MAX_NUM_NODES do begin% with nodes.node_arr[loop] do begin length := 0;% node_name := ' '; end; { with nodes }% with stats.stat_arr[loop] do begin% node_name := ' ';% opr_sys := ' ';" cpu_type := ' ';! boot_time.l0 := 0;! boot_time.l1 := 0; login_lim := 0; inter_proc := 0; batch_proc := 0; netwrk_proc := 0; total_proc := 0; load_avg[1] := 0; load_avg[2] := 0; load_avg[3] := 0; freepages := 0; end; { with stats } end; { for }end; { setup }begin getnodes(nodes); getfunction(func); if getinfo(nodes, func) then begin setupoutput(outfile);% outputheader(outfile, func); printoutput(outfile); endend. { what }**[ANONYMOUS.SAVE_SETS.NETWHAT]WHATLOG.COM;1+, ./ 4L-0123KPWO56sPӒ7PӒ89GHJ$!L$! This command procedure is modified by the WHAT manager to define default$! WHAT lookup groups$!$ EXIT !*******$!<$ define/nolog/sys/exec what_ritvax vaxa,vaxb,vaxc,vaxd,vaxn8$ define/nolog/sys/exec what_ritimg vaximg,uvximg,turing&$ define/nolog/sys/exec what_network -C vaxa,vaxb,vaxc,vaxd,vaxn,vaxo,cmkrnl,norad,ritws,glews1,glews2,-? glews3,nomad,larry,moe,vivid,curly,chico,pixee,pluto,omega,-? vaximg,uvximg,turing,uvxmex,weevax,saturn,mews1,puter,bambam$!$ define/sys/exec what_ritlav - WEEVAX,- MOE,- MEWS1,- CHICO,- SATURN,- VIVID,- NOMAD,- OMEGA,- GLEWS3,- PIXEE,- RITWS,- GLEWS1,- PLUTO,- GLEWS2,- CURLY,- CMKRNL,- LARRY2*[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT_BUILDUSERS.MAR;1+, ./ 4i -0123KPWO56 E$SӒ7xMSӒ89GHJP;*******************************************************************************P;* Module to handle logical name translation *P;*******************************************************************************;' .title WHAT_BUILDUSERS;L $lnmdef ; Get logical name constants;S .psect what_buildusers_data, con, lcl, noexe, noshr, pic, rel, wrt;Qtable_name: .ascid /LNM$FILE_DEV/ ; What table to translate logical;Ilog_name: .ascii /WHAT_USER_/ ; Prefix for logical name]incomming: .blkb 256 ; Reserve a mess of storage for incoming name;Nlog_descr: .long 10 ; How long the logical name isK .address log_name ; Where the logical name is;Qequiv_name: .byte 32[255] ; Temp place to store translationNequiv_len: .long 0 ; How long temp translation is;Sindex: .long 0 ; Temporary index into translationsPmax_index: .long 0 ; Maximum number of translationsEretlength: .long 0 ; Dummy return length;Ftrnlnm_list: ; SYS$TRNLNM item listN .word 4 ; The current index is 4 bytesK .word LNM$_INDEX ; We want to get this indexD .address index ; Where the index isE .address retlength ; Dummy return length;N .word 4 ; The maximum index is 4 bytesK .word LNM$_MAX_INDEX ; We want the maximum indexP .address max_index ; Where to put the maximum indexE .address retlength ; Dummy return length;L .word 8 ; How long our string can beO .word LNM$_STRING ; We want the equivalent stringP .address equiv_name ; Where to put the return stringP .address equiv_len ; Where to put the return length;F .long 0 ; End of our item list;;;P;*******************************************************************************P;* What_buildusers *P;* This procedure is intended to translate the logical name "WHAT_string" *P;* string being passed in, and return all the users that are associated with *P;* it in the given buffer. *P;* *P;* Arguments - *P;* USERS - buffer to put the users returned from the logical name *P;* by descriptor *P;* LOG_NAME - logical name string to translate, "WHAT_string" is *P;* what actually gets translated. *P;* by descriptor *P;* LEN - Length return of return string *P;*******************************************************************************;Q .psect what_buildusers_code, con, exe, lcl, shr, nowrt, pic, rel;L .entry what_buildusers, ^m;I movl 4(ap), r0 ; Where the node array isU movl 4(r0), r11 ; Save Address of beginning of stringG movl 8(ap), r10 ; Save the logical nameW movl 12(ap), r9 ; Save the address of the return lengthi addw2 (r10), log_descr ; Add the length of the string to translate to the prefixM movc3 (r10), @4(r10), incomming ; Save the incomming string;F clrl index ; Initialize our index^ clrl max_index ; For cleanliness, clear the maximum index out; $trnlnm_s -O tabnam = table_name, - ; What table to translate underK lognam = log_descr, - ; Where our logical name isH itmlst = trnlnm_list ; Where our item list is blbs r0, 10$@ brw error ; Error, get out;L10$: cmpb #-1, max_index ; Are there any translations bneq 20$J brw error ; No there aren't, get out;H20$: movc3 equiv_len, equiv_name, (r11) ; Save first stringE movb #^a/@/, (r3)+ ; Move in the di vidorE incl index ; Increment our index;loop: $trnlnm_s -O tabnam = table_name, - ; What table to translate underK lognam = log_descr, - ; Where our logical name isH itmlst = trnlnm_list ; Where our item list is! blbc r0, error;G movc3 equiv_len, equiv_name, (r3) ; Save first stringE movb #^a/@/, (r3)+ ; Move in the dividor;V aobleq max_index, index, loop ; Keep looping until index > max_index;H movb #32, -(r3) ; Clear the last dividorR subl3 r11, r3, (r9) ; Save the length we have returnedD movl #1, r0 ; We are successfullH ret ; End of What_buildusers;Oerror: movc3 (r10), @4(r10), (r11) ; Just return user to work withO movw (r10), (r9) ; Save the length of our stringD movl #1, r0 ; We are successfullH ret ; End of What_buildusers; .end2*[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT_BUILDUSERS.OBJ;1+,./ 4 -0123KPWO56JӒ7`ІӒ89GHJ9WHAT_BUILDUSERS0 3-NOV-1989 14:38 VAX MACRO V5.0-8MACRO/NODEBUG WHAT_BUILDUSERS  SYS$TRNLNM . ABS .P$ABS$P]WHAT_BUILDUSERS_DATAP3LNM$FILE_DEVQ &QWHAT_USER_Q  ')1-1&%WHAT_BUILDUSERS_CODEP WHAT_BUILDUSERS& ЬPР[ЬZЬ Yj(j)-5 SYS$TRNLNMP1j-1](%&k@)5 SYS$TRNLNMP'(%&c@-)Đ s[SiP(jkjiP,*[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT_DEFS.PAS;1+, ./ 4-0123KPWO56`(VӒ7hHVӒ89GHJ +[environment('what_defs')]module what_defs;constp SS$_NORMAL = 1; { Normal successful completion }m SS$_ENDOFFILE = 2160; { End of Sort transmissions }r SYI$_NODENAME = 4313; { Function code get current node }type $uword = [word] 0..65535; $uquad = [quad] record l0, l1: unsigned; end;const| DAE_M_CHANNEL = 128; { Mask to return info over a given channel }} DAE_M_STATUS = 64; { Mask to just get the status from the node } DAE_M_USER = 32; { Mask to get the users on the specified list }z DAE_M_NODE = 16; { Mask to return the node in information }v DAE_M_FULL = 8; { Mask to return info in full format }} DAE_M_SILENT = 4; { Mask to shut off signaling of node errors } DAE_M_ALL = 1; { Mask to return all processes in what ever format }m DAE_V_CHANNEL = 7; { Offset into function mask }m DAE_V_STATUS = 6; { Offset into function mask }m DAE_V_USER = 5; { Offset into function mask }m DAE_V_NODE = 4; { Offset into function mask }m DAE_V_FULL = 3; { Offset into function mask }m DAE_V_SILENT = 2; { Offset into function mask }m DAE_V_ALL = 0; { Offset into function mask }} DAE_BRIEF = 0; { Get interactive processes in brief format }| DAE_FULL = 8; { Get interactive processes in full format }t DAE_SYSTEM = 9; { Get all processes in full format }x DAE_STATUS = 64; { Function code to just get the status }r DAE_MAX_USER_LEN = 8; { Maximum length for a user name }} DAE_MAX_USERS = 128; { Maximum number of users we will translate }| DAE_MAX_USER_STR = DAE_MAX_USERS * (DAE_MAX_USER_LEN + 1); { Maximum size in bytes of matching string }} DAE_MAX_NUM_NODES = 128; { Maximum number of nodes we will translate }m DAE_MAX_NODE_LEN = 6; { Maximum length for a node }t DAE_MAX_VER_LEN = 8; { Maximum length of op sys version }n DAE_MAX_CPU_LEN = 4; { Maximum length of cpu type }w DAE_LRL = 80; { Longest record we are going to have }r DAE_MAX_REC = 2560; { Maximum number of data records }type dae_node_len = [byte] 0..DAE_MAX_NODE_LEN; { Byte containing the length of a node string } dae_node_num = [byte] 0..DAE_MAX_NUM_NODES; { Byte containing the number of nodes in record } dae_user_len = [word] 0..DAE_MAX_USER_STR; { Byte containing length of the matching string }o dae_record_buffer = packed array [1..DAE_LRL] of char; { Definition of record buffer }' dae_record_ptr = ^dae_record_buffer;> dae_data = packed array [1..DAE_MAX_REC] of dae_record_ptr; dae_data_buf = record& num_rec: integer;( data_buf: dae_data; end; dae_node_rec = record* length: dae_node_len;K node_name: packed array [1..DAE_MAX_NODE_LEN] of char;" end; { record } dae_nodes_descr = record0 num_nodes: dae_node_num;O node_arr: array [1..DAE_MAX_NUM_NODES] of dae_node_rec;% end; { record } dae_stats_rec = recordL node_name: packed array [1..DAE_MAX_NODE_LEN] of char;I opr_sys: packed array [1..DAE_MAX_VER_LEN] of char;J cpu_type: packed array [1..DAE_MAX_CPU_LEN] of char;( boot_time: $uquad;( login_lim: $uword;) inter_proc: $uword;) batch_proc: $uword;* netwrk_proc: $uword;) total_proc: $uword;< load_avg: packed array [1..3] of real;* freepages: unsigned;# end; { record } dae_stats_descr = record0 num_stats: dae_node_num;( tot_int: $uword;( tot_bat: $uword;( tot_net: $uword;( tot_prc: $uword;P stat_arr: array [1..DAE_MAX_NUM_NODES] of dae_stats_rec;% end; { record }9 dae_match_buffer = varying [DAE_MAX_USER_STR] of char;const CLI$_ABSENT = %X000381F0; CLI$_PRESENT = %X0003FD19;'[asynchronous, external(cli$get_value)]function cli$get_value(L entity_desc: [class_s] packed array [$l1..$u1:integer] of char;H retdesc: [class_s] packed array [$l2..$u2:integer] of char;6 retlength: [reference] $uword := %immed 0" ): integer; external;%[asynchronous, external(cli$present)]function cli$present(K entity_desc: [class_s] packed array [$l1..$u1:integer] of char" ): integer; external;$[asynchronous, external(lib$signal)]:procedure lib$signal(condition_value: unsigned); external;"[asynchronous, external(str$trim)]function str$trim(I new_string: [class_s] packed array [l1..u1:integer] of char;I old_string: [class_s] packed array [l2..u2:integer] of char;= str_len: [reference] $uword): integer; external;$[asynchronous, external(lib$getsyi)]function lib$getsyi(, item_code: [reference] unsigned;8 out_value: [reference] unsigned := %immed 0;H out_string: [class_s] packed array [l1..u1:integer] of char;( out_len: [reference] $uword;3 csid: [reference] unsigned := %immed 0;R node_name: [class_s] packed array [l2..u2:integer] of char := %immed 0! ): integer; external; [external] function dae_getinfo() func: [immediate] unsigned;1 nodes: [reference] dae_nodes_descr;D users: [class_s] packed array [l1..u1:integer] of char# ): boolean; external;![external] procedure what_uptime(, boot_time: [reference] $uquad;I up_string: [class_s] packed array [l1..u1:integer] of char;% len: $uword); external;![external] procedure what_trnlnm(1 nodes: [reference] dae_nodes_descr;G log_name: [class_s] packed array [l1..u1:integer] of char ); external;Q[external] procedure what_retnodes(nodes: [reference] dae_nodes_descr); external;%[external] proce~ NET_WHAT.BCK ,[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT_DEFS.PAS;17dure what_buildusers(E users: [class_s] packed array [l1..u1:integer] of char;I user_name: [class_s] packed array [l2..u2:integer] of char;% len: [reference] $uword ); external;[external] procedure what_sort() data: [reference] dae_data;' num: [immediate] integer;4 func: [immediate] unsigned); external;end. { whatdefs },*[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT_DEFS.PEN;1+,@./ 4-0123KPWO56()wӒ7[wӒ89GHJ i 9KUH 3-Nov-1989 14:38:0901 WHAT_DEFSVAX Pascal V3.9-289E SS$_NORMALF SS$_ENDOFFILEG SYI$_NODENAME H@$UWORD I@@$UQUADL DAE_M_CHANNELM DAE_M_STATUSN DAE_M_USERO DAE_M_NODEP DAE_M_FULLQ DAE_M_SILENTR DAE_M_ALLS DAE_V_CHANNELT DAE_V_STATUSU DAE_V_USERV DAE_V_NODEW DAE_V_FULLX DAE_V_SILENTY DAE_V_ALLZ DAE_BRIEF[DAE_FULL\ DAE_SYSTEM] DAE_STATUS^DAE_MAX_USER_LEN_ DAE_MAX_USERS`DAE_MAX_USER_STRaDAE_MAX_NUM_NODESbDAE_MAX_NODE_LENcDAE_MAX_VER_LENdDAE_MAX_CPU_LENeDAE_LRLf DAE_MAX_REC g@ DAE_NODE_LEN h@ DAE_NODE_NUM i@ DAE_USER_LEN jDAE_RECORD_BUFFER l DAE_RECORD_PTR m@DAE_DATA o @ DAE_DATA_BUF r8 DAE_NODE_REC wDAE_NODES_DESCR | DAE_STATS_REC HDAE_STATS_DESCR $DAE_MATCH_BUFFER CLI$_ABSENT CLI$_PRESENT  CLI$GET_VALUE  CLI$PRESENT  LIB$SIGNAL STR$TRIM  LIB$GETSYI  DAE_GETINFO  WHAT_UPTIME  WHAT_TRNLNM  WHAT_RETNODES WHAT_BUILDUSERS  WHAT_SORT  p   $@J$ IKL0$ IL1  @                @        P      Pk P  j @(l n   $ @(p$ oqNUM_REC$m@ oDATA_BUF$8s$g@rtLENGTH$u0r NODE_NAME 0v $x$h@wy NUM_NODES$zwNODE_ARR r8{ $4} $~0| NODE_NAME 0$@0|OPR_SYS  @$ p|CPU_TYPE   $I@@| BOOT_TIME $H@| LOGIN_LIM$H@| INTER_PROC$H@| BATCH_PROC$H@| NETWRK_PROC$H@| TOTAL_PROC$` |LOAD_AVG `  $ | FREEPAGES $H $h@ NUM_STATS$H@TOT_INT$H@TOT_BAT$H@(TOT_NET$H@8TOT_PRC$HSTAT_ARR | $  $       : CLI$GET_VALUE $ ENTITY_DESC $RETDESC$ $H@@ RETLENGTH$   ; CLI$PRESENT $ ENTITY_DESC$ $ CONDITION_VALUE  =STR$TRIM $ NEW_STRING $ OLD_STRING$ $H@@STR_LEN$  > LIB$GETSYI $@  ITEM_CODE $@  OUT_VALUE $ OUT_STRING  $H@@OUT_LEN$ $@ CSID $ NODE_NAME $  ? DAE_GETINFO $ FUNC $w@NODES $USERS$ $I@@@ BOOT_TIME $ UP_STRING $H@LEN$ $w@NODES $LOG_NAME$ $w@NODES $USERS $ USER_NAME$ $H@@LEN$ $m@@DATA $ NUM $ FUNC>^,Hh8Vr ,Rt&V J z  F f  " D b ~ D n    ( 4 @ L X d p | <\|,Z@p4T0`Dv<lJl@p @pFl <n|$0T`$T*P|$Hr,*[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT_LOOK.MAR;1+, .</ 4r<<-0123KPWO=56`G[\Ӓ7]\Ӓ89GHJXP;*******************************************************************************P;* Title: What_look *P;* *P;* Version: 2-000 *P;* *P;* Facility: System information formating and requests. *P;* *P;* Abstract: This module contains the procedure that requests the process *P;* information from the system and formats it as follows: *P;* *P;* Full Format: *P;* *P;* Username Pid Process Name Group Term Login State Cpu Program *P;* ------------------------------------------------------------------------- *P;* ABC1234X xxxx abcdefghijklmno ABCDEFG ABxxxx: XX:XX ABCDE XXXX K ABCDEFGH *P;* *P;* *P;* Brief Format: *P;* *P;* Username Node PID Process Name Terminal *P;* ABC1234 ABCDEF 2AE008FB abcdefghijklmno ABCxxx: *P;* *P;* Environment: What_look is non-reentrant since it is written in MACRO with- *P;* out useing the stack to store variables. You can pass it an *P;* an address of a channel or buffer descriptor of where to put *P;* information it gathers. It needs WORLD privilege in order to *P;* look at all the processes on the system for their stats. It *P;* does not return any information unless it finds processes *P;* that it can get the information on with out privilege. *P;* *P;* Author: Andrew W. Potter, 198? *P;* *P;* Modified by: Dave P. Mulvihill: 1986 *P;* - Changed output so it can go down a given channel *P;* *P;* Peter A. Portante: February, 1988 *P;* - Broke entire routine down in to smaller modules. *P;* - Rewrote FORTRAN subroutines in MACRO, just for fun *P;* - Changed the language from FORTRAN to MACRO, just for fun *P;* - Removed original internal sort routine. *P;* - Eliminated double looping to search for system processes. *P;* Now the process is totally parsed together on one pass *P;* through the loop and sent to the appropriate place. *P;* - Can either send down given channel or put into a users *P;* buffer. *P;* - Status returns for the system have been moved to another *P;* module. *P;* *P;*******************************************************************************;! .title WHAT_LOOK;L $iodef ; Get the system definitions $ssdef $jpidef $dvidef $syidef;SCH$C_COLPG = 1SCH$C_MWAIT = 2SCH$C_CEF = 3SCH$C_PFW = 4SCH$C_LEF = 5SCH$C_LEFO = 6SCH$C_HIB = 7SCH$C_HIBO = 8SCH$C_SUSP = 9SCH$C_SUSPO = 10SCH$C_FPG = 11SCH$C_COM = 12SCH$C_COMO = 13SCH$C_CUR = 14;FDAE_M_CHANNEL = 128 ; Mask for the channelMDAE_M_NODE = 16 ; Mask for adding in the nodeUDAE_BRIEF = 0 ; Send user processes in brief formatSDAE_SYSTEM = 9 ; Send all processes in full formatTDAE_FULL = 8 ; Send user processes in full format;CINFO_SIZE = 24000 ; 300 80 byte linesCALL_PROC = 0 ; Get all processesPINT_ONLY = 3 ; Get only interactive processes;NSUBPROC = 4 ; We have a subprocess here...;;;Q .psect what_look_data, con, noexe, lcl, pic, noshr, wrt, rd, rel;+; Data storage for building the nodes;dbuffer: .blkb INFO_SIZE ; Size of the information block to hold user stringsFbuffer_desc: .long 0 ; Length of the bufferP .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[\]^_`/8 .ascii /abcdefghijklmnopqrstuvwxyz{|}~/ .byte 32[34]A .byte 161,162,163,32,165,32,167,168,169,170,171? .byte 32[4],176,177,178,179,32,181,182,183,32J .byte 185,186,187,188,189,32,191,192,193,194,195,196,197B .byte 198,199,200,201,202,203,204,205,206,207,32G .byte 209,210,211,212,213,214,215,216,217,218,219,220J .byte 221,32,223,224,225,226,227,228,229,230,231,232,233J .byte 234,235,236,237,238,239,32,241,242,243,244,245,2469 .byte 247,248,249,250,251,252,253,32,32;null_time: .ascii / --- /null_cpu: .ascii / ---/#suspnd_str: .ascii /Suspended/#swapped_str: .ascii /Swapped /;Rchar_state_arr: .ascii /CPG/ ; Character string representationsL .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 / /;bchar_mode_arr: .ascii /-Det- / ; Character string for the different process modes .ascii /-Net- / .ascii /-Bat- / .ascii /-Disc-/ .ascii /-Sub- /;ectrl_brief: .ascid / !AD !+!+!XL !AF !+!+!AD/ ; Skip the nodename, and the groupVctrl_full: .ascid /!AD !+!+!XW !AF !AD !AD !AD !AD !AD !AD/ ; Skip the nodenameWctrl_brief_node: .ascid / !AD !AD !XL !AF !+!+!AD/ ; Skip the the groupActrl_full_node: .ascid /!AD !AD !XW !AF !AD !AD !AD !AD !AD !AD/;Vctrl_list: .address ctrl_brief ; List of the different string formats" .address ctrl_full( .address ctrl_brief_node' .address ctrl_full_node;Vnode: .byte 32[6] ; Where the DECnet node name is storedWstrings_to_blank: ; All these are cleared for cleanlynessDusername: .byte 32[8] ; User name from JPIBaccount: .byte 32[8] ; Account from JPIHterm: .byte 32[16] ; Terminal name returnedKimage: .byte 32[128] ; Image name of the processGprcnam: .byte 32[15] ; Process name returned;Xname_only: .byte 32[17] ; Actuall image name, with out rms stuffXoutstr: .byte 32[256] ; Output string from the SYS$FAO service;Vchar_time: .byte 32[20] ; Character representation of the timeWchar_state: .byte 32[3] ; Character representation of the stateZchar_cpu: .byte 32[4] ; Character representation of the cpu time;%BYTES_TO_BLANK = . - strings_to_blank;Eimage_descr: .long 0 ; Length of the imageD .address image ; Where the image isHterm_descr: .long 0 ; Length of the terminalG .address term ; Where the terminal is;Fowner: .long 0 ; Owner of the processIstate: .long 0 ; State the process is inFcpu_time: .long 0 ; Cpu time for process .long 0Llogin_time: .long 0 ; Login time for the process .long 0Emode: .long 0 ; Mode of the processLchan_buf: .long 0 ; Default to useing a bufferWchan_buf_adr: .long 0 ; Address of where buffer or channel is;Fchar_time_descr: .long 5 ; How long the time isN .address char_time ; Where the time should be putEchar_cpu_descr: .long 4 ; How long we want itW .address char_cpu ; Where the character cpu should be put;Lname_descr: .long 17 ; Maximum length of the nameW .address name_only ; Where the name of the image is storedaoutstr_descr: .long 256 ; Length of the outstr, doubles as its descriptorK .address outstr ; Address out output string\l_ostr: .long 0 ; Length of the outstr, returned by SYS$FAOL;iretlength: .long 0 ; Dummy place to hold some return lengths from SYS$GETJPIAiosblk: .quad 0 ; IO status block;Dfcpu: .long 0 ; Converted cpu time;Xfilter: .byte 0 ; Assume we will filter no processes out; fao_list:^ .long 8 ; How much of the username we want printed outG .address username ; Where the username isF .long 6 ; How long the node isH .address node ; Where the node name isOpid: .long 0 ; Process Identification numbera .long 15 ; How much of the processname we want printed outK .address prcnam ; Where the process name is] .long 7 ; How much of the account we want printed outI .address account ; Where the group name is^ .long 7 ; How much of the terminal we want printed outL .address term ; Where the terminal name isZ .long 5 ; How much of the time we want printed outM .address char_time ; Where the character time ise .long 3 ; How much of the character state we want printed outN .address char_state ; Where the character state isi .long 4 ; How much of the character cpu usage we want printed outR .address char_cpu ; Where the character cpu usage is` .long 17 ; How much of the image name we want printed outC .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;A .long 0 ; End of DVI list;8; SYI item list to get the system wide information;syi_list: .word 6% .word SYI$_NODENAME .address node" .address retlength;A .long 0 ; End of SYI list;B; JPI item list to get information that won't swap a process;Yjpi_wild: .long -1 ; We want a wild card lookup of processes;Sjpi_lookup: .word 4 ; The pid is a longword, four bytes[ .word JPI$_PID ; We want the process identification numberH .address pid ; Where to store the pidE .address retlength ; Dummy return length;U .word 4 ; The state is a longword, four bytesC .word JPI$_STATE ; We want the stateH .address state ; Where to put the stateE .address retlength ; Dummy return length;T .word 4 ; The mode is a longword, four bytesL .word JPI$_MODE ; We want the process's modeG .address mode ; Where to put the modeE .address retlength ; Dummy return length;Q .word 8 ; Length we want for the usernameF .word JPI$_USERNAME ; We want the usernameK .address username ; Where to put the usernameJ .address retlength ; How long our username is;P .word 8 ; Length we want for the accountE .word JPI$_ACCOUNT ; We want the accountJ .address account ; Where to put the accountE .address retlength ; Dummy return length;Q .word 16 ; Length we want for the terminalQ .word JPI$_TERMINAL ; Get the terminal of the processK .address term ; Where to put the terminalE .address term_descr ; Dummy return length;U .word 15 ; Length we want for the process nameH .word JPI$_PRCNAM ; We want a process nameO .address prcnam ; Where to put the process nameE .address retlength ; Dummy return length;^ .long 0 ; End of JPI list that won't swap a process in;D; JPI item list to get information that will swap a process in;Sjpi_p1: .word 128 ; Length we want for the image nameH .word JPI$_IMAGNAME ; We want the image nameM .address image ; Where to put the image nameV .address image_descr ; Where to put the length of the image;Q .word 8 ; Length we want for the CPU timeF .word JPI$_CPUTIM ; We want the CPU timeK .address cpu_time ; Where to put the cpu timeWE .address retlength ; Dummy return length ; S .word 8 ; Length we want for the login time H .word JPI$_LOGINTIM ; We want the login timeM .address login_time ; Where to put the login timecP .address retlength ; Where to put the return length; N .word 4 ; Length we want for the ownerC .word JPI$_OWNER ; We want the owner H .address owner ; Where to put the ownerE .address retlength ; Dummy return length ; ] .long 0 ; End of JPI list that will swap a process in ;; ; P;*******************************************************************************P;* What_look *P;* This procedure is intended to take a function code that specifies a *P;* format of output, and either a channel number or the address of a buffer *P;* to put the information returned in. The function codes currently supported *P;* for either channel or buffer are: *P;* *P;* DAE_BRIEF *P;* DAE_SYSTEM *P;* DAE_FULL *P;* *P;* Arguments: BUFFER or CHANNEL, address of either a buffer to put info into *P;* - or a channel to send the info down. Buffer is passed by *P;* - descriptor. *P;* *P;* FUNCTION, the function code to perform. Only the first byte *P;* - is used. If the high order bit in the byte is set then *P;* - the first argument is interpreted as a channel number, *P;* - else it is interpreted as a buffer descriptor. FUNCTION *P;* - is passed by value. *P;* *P;* USER, address of a descriptor of the user names to search for. *P;* *P;* Register Use: *P;* *P;* r6 - Holds the address of the format strings to be used *P;* r7 - Holds the current address in the print buffer *P;* r8 - Holds the address of the character state array *P;* r9 - Holds the address of the character mode array *P;* r10 - Holds the address of the buffer or channel to dump info to *P;* r11 - Holds the function code we are working with, then it holds the *P;* number of the control string we want *P;* *P;*******************************************************************************; K .psect what_look_code, con, exe, lcl, shr, nowrt, pic, rel ; F .entry what_look, ^m; b moval ctrl_list, r6 ; Put the control list into a memory for later usek moval buffer, r7 ; Holds the address of the current position in print buffer l moval char_state_arr, r8 ; Move the address of the character state for indexing laterl moval char_mode_arr, r9 ; Move the address of the character modes for indexing laterq movl 4(ap), chan_buf_adr ; Move either the address of a channel or address of a descriptorO movzbl 8(ap), r11 ; Move address of function codeCh movl 12(ap), r10 ; Move address of user descriptor so we can work with it;nU mnegl #1, jpi_wild ; We want to search all the processes_;Ed blbs r11, get_all ; If the 0 bit is set, get all the process on systemO movb #INT_ONLY, filter ; Get the interactive ones only \ brb keep_parsing ; Go and skip the swapper and null processes; Nget_all: movb #ALL_PROC, filter ; Get all the system processes; qkeep_parsing: extzv #7, #1, r11, chan_buf ; Extract whether we want to use first arg as a channel of bufferO extzv #3, #2, r11, r11 ; Extract out the format number;Gskip_swap: $getjpiw_s - ; Skip the NULL process,U pidadr = jpi_wild, - ; We want to search all the processesbV itmlst = jpi_lookup ; We want to lookup normal informationJ $getjpiw_s - ; Skip the SWAPPER processU pidadr = jpi_wild, - ; We want to search all the processeshV itmlst = jpi_lookup ; We want to lookup normal information $getsyiw_s -H itmlst = syi_list ; Get the specified info6 movc5 retlength, node, #32, #6, node;s&loop: movc5 #0, #0, #32, -* #BYTES_TO_BLANK, -G strings_to_blank ; Clear out the strings7;2F $getjpiw_s - ; Get ~ NET_WHAT.BCK ,[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT_LOOK.MAR;1r< -the next processU pidadr = jpi_wild, - ; We want to search all the processes2V itmlst = jpi_lookup ; We want to lookup normal information+ cmpl #SS$_NOMOREPROC, r09] bneq cont_loop ; Continue processing if there are still more ; F brw end_loop ; We are done, get out;a[cont_loop: cmpl #SS$_NOPRIV, r0 ; Do we have the privilege to a get process_R beql loop ; Keep going, and get next process;r] cmpb mode, filter ; If the mode is greater than or equal to theeQ blss loop ; - process mode we want, keep it ; K; Compare username returned from SYS$GETJPI to the username passed in; b cmpw (r10), #8 ; If we have less than 8 chars, we will do a cmpc3$ bleq variable_cmp; 7 locc #32, #8, username ; Find end of the string ; subl3 r0, #8, r0 ; Find out how long it is 4 matchc r0, username, (r10), @4(r10)I beql process_it ; If we match, keep going D brw loop ; Else get next dude; Gvariable_cmp: cmpc3 (r10), @4(r10), username ; Are the string equalfI beql process_it ; If we match, keep goingeD brw loop ; Else get next dude;Dbprocess_it: movtc #15, prcnam, #32, table, #15, prcnam ; Clean out the processname string;i tstb termD bneq has_term ; We have a terminal; J brw get_other_info ; We don't have a terminal; Nhas_term: locc #^a/:/, term_descr, term ; Find a colon in device nameW bneq get_phys ; If we found, get physical device nameh; \ movb #^a/:/, (r1) ; Add in a colon, cause we couldn't find oneE incl term_descr ; Increase the length ; get_phys: $getdviw_s -N devnam = term_descr, - ; What name we are looking forJ itmlst = dvi_list ; What information we want;2J cmpb #^a/_/, term ; Do we have an underline?I bneq get_other_info ; If we don't, keep going ;2E decl term_descr ; Decrease its length U movc5 term_descr, term+1, #32, #16, term ; Move the string back oneh;t;:; ^get_other_info: movtc #8, account, #32, table, #8, account ; Clean out the account stringS cmpb #32, account ; Do we have a crap accountb" bneq calc_stateQ movc5 #0,#0,#32,#8,account ; Clean out crap accounts;m]calc_state: mull3 #3, state, r0 ; Get the offset into the state arrayih movc3 #3, -3(r8)[r0], char_state ; Move the character representation of the state;eZ movc3 #5, null_time, char_time ; Default value for character timeY 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_swapn* cmpl state, #SCH$C_COMO# beql we_are_swap * cmpl state, #SCH$C_HIBO bneq not_swap;b<we_are_swap: movc5 #9, swapped_str, #32, #17, name_only# brw have_a_term ; not_swap: $getjpiw_s -R pidadr = pid, - ; Get more info on current processJ itmlst = jpi_p1 ; Here is the info we wantT blbc r0, proc_suspend ; If it failed, process is suspended;tT $asctim_s - ; Convert the login time to a stringL timlen = char_time_descr, - ; How long the string isI timbuf = char_time_descr, - ; Where the buffer isaN timadr = login_time, - ; The time to be convertedG cvtflg = #1 ; We just want the timeoI pushal name_descr ; Where to put the length H pushal name_descr ; Where to put the imageC pushal image_descr ; The image we have L calls #3, g^what_parseimage ; Parse out the image stringA 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 fcpuR calls #2, g^ots$cvt_l_ti ; Convert the cpu time to a string; Hhave_a_term: tstb term ; Did we get a terminal?\ bneq format_strings ; If owner is 0 then just format the strings; L tstl owner ; If we are not a subprocess_ beql get_term ; Get the terminal string with the current modee;nO movl #SUBPROC, mode ; We are a subprocess otherwises;aXget_term: mull3 #6, mode, r0 ; Compute offset of into character arrayh movc5 #6, (r9)[r0], #32, #16, term ; - that contains the mode string for bad terminals;n; ; Sformat_strings: pushal fao_list ; Push our address of our argumentsaZ 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 wantY calls #4, g^sys$faol ; Call the Formatted Ascii Output service R movc5 l_ostr, outstr, #32, #80, (r7) ; Move the formatted stringR movl r3, r7 ; Save new address in print buffer;sN brw loop ; Go back and get next process; ; ; `end_loop: moval buffer, r1 ; Move the address of our buffer for computationq movl chan_buf_adr, r10 ; Move address of channel or buffer into r10, easier to work withiN blbs chan_buf, use_channel ; Do we want to use a channel?R subl3 r1, r7, (r10) ; Compute the length of the bufferr movc5 (r10), buffer, #32, (r10), @4(r10) ; Move all the information to the user specified buffer ret; Ruse_channel: subl3 r1, r7, r6 ; Compute the length of the buffer $qiow_s - J chan = (r10), - ; What channel to write toD func = #IO$_WRITEVBLK,- ; Write out the lineE iosb = iosblk, - ; Status of operationoE p1 = buffer, - ; Where to write from L p2 = r6 ; Length of bytes to put outM movzwl iosblk, r0 ; Return the status condition B ret ; End of What_look;e .endy return length;U .word 4 ; The state is a longword, four bytesC .word JPI$_STATE ; We want the stateH .address state ; Where to put the stateE .address retlength ; Dummy return length;T .word 4 ; The mode is a longword, four bytesL .word JPI$_MODE ; We want the process's modeG,*[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT_LOOK.OBJ;2+,. / 4 -0123KPWO 56Ӓ76Ӓ89GHJ 3 WHAT_LOOK0 3-NOV-1989 14:39 VAX MACRO V5.0-8MACRO/NODEBUG WHAT_LOOK  OTS$CVT_L_TI SYS$ASCTIMSYS$FAOL SYS$GETDVIW SYS$GETJPIW SYS$GETSYIWSYS$QIOWWHAT_PARSEIMAGE . ABS .P$ABS$PPPPP)cWHAT_LOOK_DATAPQ] !'!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ "'  ' --- ---SuspendedSwapped CPGMWTCEFPFWLEFLEFHIBHIBSUSSUSFPGCOMCOMCUR -Det- -Net- -Bat- -Disc--Sub- 2_3 !AD !+!+!XL !AF !+!+!ADQ&Q!U_3!AD !+!+!XW !AF !AD !AD !AD !AD !AD !ADQ'&Q-_3 !AD !AD !XL !AF !+!+!ADQ&Q"_3!AD !AD !XW !AF !AD !AD !AD !AD !AD !ADQ'&Q-._Q___ ' ' ' ' ' ' ' ' ' ' ' `_aa``__`__aaa`_a_b=bbab"ab_b_b_a`b `aabababYWHAT_LOOK_CODEP  WHAT_LOOK&_VW^X_YЬa[Ь Zb[ ,b,b[a[[|~bb SYS$GETJPIW|~bb SYS$GETJPIW|~b SYS$GETSYIW,b_ _, _|~bb SYS$GETJPIWя P1$PǑa,bj: _PP9P_j1)j_1.` ]`_1W::a_ :aa|~yba<~ SYS$GETDVIW__a,a_3 _._ ]_ _ , _aP(@a(^a(^aa aa  a, ^ `1|~b=b SYS$GETJPIWP6aaa SYS$ASCTIMbbaWHAT_PARSEIMAGE, ^ `'da(bb(b OTS$CVT_L_TI_"aaaP,@i _-bbbKfSYS$FAOL,b` PgSW1QaZaQWj,j jQWV|~|~V|~ b<0~^Ӓ89GHJ+.title WHAT_SHAR Sharable messages.facility WHAT,1.severity FATAL:BADLNM /fao=1.severity ERROR2TALKFAIL /fao=1.end+*[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT_MSG.OBJ;1+,./ 4-0123KPWO56@ Ӓ7 Ӓ89GHJ3 WHAT_SHAR0 3-NOV-1989 14:38 3-NOV-1989 14:38VAX-11 Message V04-00k$ABS$ MSG$SECTIONMSG$AAAAAAAAAAAMSG$AAAAAAAAAABMSG$AAAAAAAAAACE WHAT_TALKFAIL  WHAT_BADLNMWHAT$_FACILITYPeP*P'P(@{@t4BADLNM"Error translating logical name !AS.TALKFAILUnable to talk to node !ASWHAT2*[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT_PARSEIMAGE.MAR;1+, . / 4W -0123KPWO 56.`Ӓ7`h`Ӓ89GHJ ' .title WHAT_PARSEIMAGE;W .psect what_parseimage_data, noexe, pic, noshr, lcl, wrt, rd, rel, con;CFSCN$_NAME = 6 ; Code for the nameFFSCN$_VERSION = 8 ; Code for the versionLitemlist: ; Item list for SYS$FILESCAN;Fname_len: .word 0 ; How long the name isBnamecode: .word FSCN$_NAME ; We want the nameCname_adr: .long 1 ; Where the name is;Ivers_len: .word 0 ; How long the version isEverscode: .word FSCN$_VERSION ; We want the versionFvers_adr: .long 1 ; Where the version is;Aend_list: .long 0 ; End of our list;;;P;*******************************************************************************P;* What_parseimage *P;* This procedure is intended to parse out the the name of the image *P;* from imag field returned by SYS$GETJPIW. Known images have $ in front. *P;* For those system managers who like to catch sneaky people passing off the *P;* name programs $.EXE, the real $ which stands for DCL will be pulled back a *P;* character, whereas $.EXE will show up one space over. *P;*******************************************************************************;Q .psect what_parseimage_code, con, exe, lcl, shr, nowrt, pic, rel;L .entry what_parseimage, ^m;O movl 4(ap), r9 ; Descriptor of string to parseP movl 8(ap), r10 ; Descriptor of string to returnK movl 12(ap), r11 ; Length of string returned;N movl 4(r10), r8 ; Get address of string to retI movc5 #0,#0,#32,(r10),(r8) ; Blank out return string; $filescan_s -P srcstr = (r9), - ; Give the address of our stringK valuelst = itemlist ; Item list of what we want;G blbc r0, trim_name ; Error, just put a "$";K tstw name_len ; Was there anything at allN beql known_imag ; No image, just at DCL prompt;I  tstw vers_len ; Have we found a versionK beql known_imag ; If not, we know the image;M movb #^a/ /, (r8)+ ; Move the name to the stringC brb move_name ; Now move the name;Cknown_imag: movb #^a/$/, (r8)+ ; We know the image;$move_name: movl name_adr, r7M movc3 name_len, (r7), (r8) ; Move the name to the string;Jtrim_name: pushl r11 ; Address of return lengthK pushl r10 ; Address of string to trimO pushl r10 ; Address to put trimmed stringA calls #3, g^str$trim ; Trim the string;end: movl #1, r0H ret ; End of What_parseimage; .end2*[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT_PARSEIMAGE.OBJ;2+,./ 4-0123KPWO56FӒ77_Ӓ89GHJ9WHAT_PARSEIMAGE0 3-NOV-1989 14:39 VAX MACRO V5.0-8MACRO/NODEBUG WHAT_PARSEIMAGE STR$TRIM SYS$FILESCAN . ABS .PWHAT_PARSEIMAGE_DATAPeWHAT_PARSEIMAGE_CODEP WHAT_PARSEIMAGE&ЬYЬZЬ [ЪX, jhi SYS$FILESCANP'  $W(gh[ZZSTR$TRIMP0*[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT_RETNODES.MAR;1+, ./ 4U-0123KPWO56'bӒ7HbӒ89GHJ % .title WHAT_RETNODES; $ssdef;U .psect what_retnodes_data, noexe, pic, noshr, lcl, wrt, rd, rel, con;entity_desc: .ascid /NODE/;ret_string: .byte 32[255];retdesc: .long 255# .address ret_string;retlength: .word 0;;;P;*******************************************************************************P;* What_retnodes *P;* This procedure is intended to get all the nodes from the qualifier *P;* 'NODE'. It assembles them into the record NODES. *P;* *P;* Arguments: Nodes - reference, dae_nodes_descr *P;*******************************************************************************;O .psect what_retnodes_code, con, exe, lcl, shr, nowrt, pic, rel;J .entry what_retnodes, ^m;I movl 4(ap), r11 ; Address of total recordO addl3 #1, r11, r10 ; Increment to the first recordK clrl r9 ; Counter of nodes returned;!loop: pushaw retlength pushal retdesc# pushal entity_descK calls #3, g^cli$get_value ; Get the value on the lineC movl r0, r8 ; Save return value;K incl r9 ; Increment number returnedA movb retlength, (r10)+ ; Save its lengthO movc5 retlength, ret_string, #32, #6, (r10) ; Save the stringL movl r3, r10 ; Save new address in record;P cmpl #SS$_NORMAL, r8 ; Have we returned the last one?< bneq loop ; Keep going;J movb r9, (r11) ; Save the number returned@ movl #1, r0 ; Return successF ret ; End of What_retnodes; .end0*[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT_RETNODES.OBJ;1+,./ 4i-0123KPWO56ݏӒ74ƑӒ89GHJ7 WHAT_RETNODES0 3-NOV-1989 14:38 VAX MACRO V5.0-8MACRO/NODEBUG WHAT_RETNODES  CLI$GET_VALUE . ABS .P$ABS$PWHAT_RETNODES_DATA8P3NODEQ&Q  ' NWHAT_RETNODES_CODEP  WHAT_RETNODES&iЬ[[ZY?  CLI$GET_VALUEPXY,  jSZXŐYkP.*[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT_STATUS.MAR;1+, ./ 4f"-0123KPWO56;\ movl 4(ap), r9 ; Save the channel or buffer to send info on\ movl 8(ap), r10 ; Move whether we want a channel of a buffer;V movw @ijoblim, job_lim ; Move maximum number of users allowedQ movw @ijobcnt, int_cnt ; Move number of interactive jobsK movw @bjobcnt, bat_cnt ; Move number of batch jobsM movw @njobcnt, net_cnt ; Move number of network jobsP movw @proccnt, tot_cnt ; Move total number of processesQ movl @freecnt, freepages ; Return the number of free pages;P tstb assigned ; Have we assigned a channel yetL bneq cont ; If we have, continue on...;N $assign_s - ; Assign chan to load function* devnam = device, -( chan = load_chanL movb #1, assigned ; Set that we have been here;Fcont: $qiow_s - ; Talk to the functionN chan = load_chan, - ; Channel for the load averageG func = #IO$_READVBLK, - ; Read the load averageC p1 = load_avg, - ; Where to put themM p2 = #12 ; Length in bytes to put load;T movc5 #0,#0,#32,#CHAR_PART_LEN,node ; Blank out the version string $getsyiw_s -H itmlst = syi_list ; Get the specified info;B movc5 l_ver, version, #32, #MAX_VER_LEN, versionE movc5 l_cpu, cpu_type, #32, #MAX_CPU_LEN , cpu_typeC movc5 l_node, temp_node, #32, #MAX_NODE_LEN, node;+ bbc #7, r10, use_buffer $qiow_s -J chan = (r9), - ; What channel to write toD func = #IO$_WRITEVBLK,- ; Write out the lineE iosb = iosblk, - ; Status of operationE p1 = stat_buf, - ; Where to write fromL p2 = #STAT_LEN ; Length of bytes to put outM movzwl iosblk, r0 ; Return the status conditionE ret ; Possibly successful;1use_buffer: movc3 #STAT_LEN, stat_buf, (r9)C movl #1, r0 ; Always successfulD ret ; End of Wha~ NET_WHAT.BCK .[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT_STATUS.MAR;1f0t_status; .end.*[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT_STATUS.OBJ;2+,./ 4-0123KPWO56Ӓ7 ٺӒ89GHJ5 WHAT_STATUS0 3-NOV-1989 14:39 VAX MACRO V5.0-8MACRO/NODEBUG WHAT_STATUS  IO$_READVBLK IO$_WRITEVBLKSCH$GL_FREECNTSCH$GW_PROCCNT SYS$ASSIGN SYS$GETSYIWSYS$GW_BJOBCNTSYS$GW_IJOBCNTSYS$GW_IJOBLIMSYS$GW_NJOBCNTSYS$QIOW . ABS .PWHAT_STATUS_DATAP$ABS$'PSYS$GW_IJOBLIMSYS$GW_IJOBCNTSYS$GW_BJOBCNTSYS$GW_NJOBCNTSCH$GW_PROCCNTSCH$GL_FREECNT3LAV0:Q&Q QQQ42Qn}D8@*WHAT_STATUS_CODEP  WHAT_STATUS&ЬYЬZLNP RTb%|~& SYS$ASSIGN%|~|~ V|~< IO$_READVBLK&~<&~ SYS$QIOW, 2|~ SYS$GETSYIW,8 8,@ @,}n 2Z-|~|~42|~*< IO$_WRITEVBLK&~;I movl 4(ap), r11 ; Where the node array isG movl 8(ap), r10 ; Save the logical namei addw2 (r10), log_descr ; Add the length of the string to translate to the prefixM movc3 (r10), @4(r10), incomming ; Save the incomming string;F clrl index ; Initialize our index^ clrl max_index ; For cleanliness, clear the maximum index out; $trnlnm_s -O tabnam = table_name, - ; What table to translate underK lognam = log_descr, - ; Where our logical name isH itmlst = trnlnm_list ; Where our item list is blbs r0, 10$@ brw error ; Error, get out;L10$: cmpb #-1, max_index ; Are there any translations bneq 20$J brw end ; No there aren't, get out;F20$: addb3 max_index, #1, (r11)+ ; Save number of nodesO movb equiv_len, (r11)+ ; Save first translation lengthQ movc5 equiv_len, equiv_name, #32, #6, (r11) ; Save first stringP movl r3, r11 ; Save new address in nodes listE incl index ; Increment our index;loop: $t rnlnm_s -O tabnam = table_name, - ; What table to translate underK lognam = log_descr, - ; Where our logical name isH itmlst = trnlnm_list ; Where our item list is! blbc r0, error;O movb equiv_len, (r11)+ ; Save first translation lengthQ movc5 equiv_len, equiv_name, #32, #6, (r11) ; Save first stringP movl r3, r11 ; Save new address in nodes list;V aobleq max_index, index, loop ; Keep looping until index > max_indexD movl #1, r0 ; We are successfull;Dend: ret ; End of What_trnlnm;Ierror: pushl r0 ; Push the error returnedJ pushal log_descr ; What logical name failedS pushl #1 ; How many arguments we are passingO pushl #WHAT_BADLNM ; Failure talking to the daemonB calls #4, g^lib$signal ; Signal the error;? ret ; End of Trnlnm; .end.*[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT_TRNLNM.OBJ;1+,m./ 4? -0123KPWO56Ӓ7Ӓ89GHJ5 WHAT_TRNLNM0 3-NOV-1989 14:38 VAX MACRO V5.0-8MACRO/NODEBUG WHAT_TRNLNM / LIB$SIGNAL SYS$TRNLNM WHAT_BADLNM . ABS .P$ABS$PXWHAT_TRNLNM_DATAP3LNM$FILE_DEVQ &QWHAT_Q '$,(,! WHAT_TRNLNM_CODEP  WHAT_TRNLNM&?Ь[ЬZj(j$(0 SYS$TRNLNMP1{(1m( , ! kS[$0 SYS$TRNLNMP( , ! kS[($PP WHAT_BADLNM LIB$SIGNAL.*[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT_UPTIME.MAR;1+, ./ 4R-0123KPWO56@iiӒ7iӒ89GHJ P;*******************************************************************************P;* What_uptime *P;* This procedure is intended to return a formated string of the current *P;* time a CPU has been up, given its boot time. *P;*******************************************************************************;# .title WHAT_UPTIME;O .psect what_uptime_data, con, lcl, noexe, noshr, pic, rel, wrt;Mepoch: .quad 0 ; Used to make delta positiveMcurr_time: .quad 0 ; Current time program is runNdelta_time: .long 0 ; Storage place for delta timeEup_half: .long 0 ; - after subtraction;M .psect what_uptime_code, con, exe, lcl, shr, nowrt, pic, rel;H .entry what_uptime, ^m;R movl 4(ap), r11 ; Boot time needed to be convertedK movl 8(ap), r10 ; Descriptor of time bufferO movl 12(ap), r9 ; Length of the returned string; $gettim_s -F timadr = curr_time ; Get the current time;" pushal delta_timeQ pushl r11 ; Subtract boot time from currentH pushal curr_time ; - time to find uptime.& calls #3, g^lib$subx;P bbs #31, up_half, 10$ ; If bit 31 set, its is negative;" pushal delta_timeK pushal delta_time ; Subtract the time so thatB pushal epoch ; - it is positive& calls #3, g^lib$subx;K10$: $asctim_s - ; Convert the delta time to< timlen = (r9), - ; - a string) timbuf = (r10), -+ timadr = delta_time;D ret ; End of What_uptime; .end.*[ANONYMOUS.SAVE_SETS.NETWHAT]WHAT_UPTIME.OBJ;1+,./ 4-0123KPWO56 pӒ7``Ӓ89GHJ5 WHAT_UPTIME0 3-NOV-1989 14:38 VAX MACRO V5.0-8MACRO/NODEBUG WHAT_UPTIME ,LIB$SUBX SYS$ASCTIM SYS$GETTIM . ABS .PWHAT_UPTIME_DATAPeWHAT_UPTIME_CODEP  WHAT_UPTIME&Ь[ЬZЬ Y SYS$GETTIM[LIB$SUBXLIB$SUBXji SYS$ASCTIM0E