.Title - Names - a program to look at system users... ;+ ; ;This program uses the $GETJPI system service to print out ;useful information about current users.. ; ; Kevin Carosso 28-Feb-1981 ; ; Harvey Mudd College ;- .Library /SLIB:LIB.MLB/ .Library /TOOLS:TTYIO.MLB/ _TTYIODEF ;Define I/O macros $PCBDEF ;Define PCB stuff... $JPIDEF ;Define our item codes... $TPADEF ;LIB$TPARSE parser definitions .Page ;Item is a macro to produce a list of items that we would ;like GETJPI to retrieve for us. In addition the macro is ;responsible for setting values to offsets in the information ;return block for us to retrieve what we want. ;The information block looks like this: ; ; Item with a length Item without a length ; ; +------------------+ +------------------+ ;len_addr:| Length (2 bytes) | ret_addr1:| Item1 (4 bytes) | ; |------------------| |------------------| ;ret_addr:| Item (1st byte) | ret_addr2:| Item2 (4 bytes) | ; |------------------| |------------------| ; | Item (2nd byte) | ret_addr3:| Item3 (4 bytes) | ; +------------------+ +------------------+ ; ;The addresses returned to RET_ADDR and LEN_ADDR are ;offsets into the block. .Macro Item bufflen=4,item_code,ret_addr,len_addr .'item_code == itemnum ;;Number of this item itemnum == itemnum + 1 ;;Total number of items .word bufflen .word JPI$_'item_code .if NOT_BLANK len_addr ;;If we have a lengthy ;;item. len_addr = offset offset = offset + 2 ret_addr = offset .long info + ret_addr .long info + len_addr .if_false ;;Else we do: ret_addr = offset .long info + ret_addr .long 0 .endc offset = offset + bufflen .endm ;Macro to check for error returns from procedure calls .Macro Check ?l blbs r0,l jmp error l: .endm .Page .SBTTL Data - Data definitions we need. .Psect Info, wrt, noexe, quad ; The format of the item list is quite important. All the ; items that are listed in the first batch of macro calls ; are those that are used to determine whether or not we ; will eventually want to display the job. The second ; block is reserved for those items that may require an ; outswapped job to be brought back in. I do it this way ; so that we don't have to wait for a job to be swapped ; in if we don't want to bother looking at him. wildpid:.long -1 ;This will get info on all current jobs itemnum == 0 offset = 0 itemlist: ;List of items we want from $GETJPI item 7,TERMINAL,termnum,term_len item ,UIC,uicnum item ,PID,procid item 15,PRCNAM,procnam,proc_len item ,STATE,status item ,PRI,prio item ,PRIB,basprio item 12,USERNAME,usrnam,usr_len ;Note well: This is last item ,STS,sts_flags ; displayable item ,OWNER,owner_pid ; item!!! .long 0 ;a zero tags end of list. sloitems: item 64,IMAGNAME,image,image_len ;This one is handled special .long 0 ;a zero tags end of list. info: .blkb offset ;Job info returned here. jobmax = 256 ;Max number of job slots we support joblist:.blkl jobmax ;Block for pointers to each job's ;information block. blksiz: .long offset ;Size of an information block devnam: .ascid /TT/ ;Generic terminal name devchr: .long 12 ;Buffer for terminal info .address devbuff devbuff:.blkl 3 iosb: .quad ;IO status block for GETJPI's return status. .PAGE .Sbttl Text - Text data we need. .Psect Text, wrt, noexe, quad ;Common descriptor block for all text outdesc:.long 256 ;Max line length .long string string: .blkb 256 ;Block for string .byte 0 ;Zero terminator if we need it. ;Now for our FAO control strings: ;First the output header with the job count. users: .ascid /!UL interactive job!%S out of !UL total job!%S, !%D/ nojobs: .asciz / No jobs as specified./ ;If no info is found batch: .word 7 ; Length of string .ascii /(batch)/ ; Batch job indicator. subprc: .word 7 ; Length of string .ascii /(subpr)/ ; Subprocess indicator. intusr: .blkl totusr: .blkl dtime: .quad 0 ;Use current system date and time linlen: .byte 80 ;Terminal's line length. paglen: .byte 24 ;Terminal's page length. space: .ascii / / cr=13 lf=10 nul=0 crlf: .asciz ;Carriage return linefeed sequence ;Table for upper to lower case translation. uclc: .byte 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 .byte 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 .ascii \ !"#$%&'()*+,-./0123456789:;<=>?@\ .ascii /abcdefghijklmnopqrstuvwxyz/ .ascii /[\]^_`/ .ascii /abcdefghijklmnopqrstuvwxyz/ .ascii /{|}~/ .byte ^A/./ ;Table to get rid of nasty control characters. nocont: .byte ^A/./[32] .ascii \ !"#$%&'()*+,-./0123456789:;<=>?@\ .ascii /ABCDEFGHIJKLMNOPQRSTUVWXYZ/ .ascii /[\]^_`/ .ascii /abcdefghijklmnopqrstuvwxyz/ .ascii /{|}~/ .byte ^A/./ .Page ;Now for the information column headers. Each header is ;stored as two counted ascii strings, of identical length. ;The two strings correspond to, respectively, the first and ;second rows of the header. hd_TERMINAL: .ascic / / .byte nul .ascic / Term / .byte nul .ascic /-------/ .byte nul hd_UIC: .ascic / / .byte nul .ascic / UIC / .byte nul .ascic /---------/ .byte nul fao_UIC: .ascid /[!3OW,!3OW]/ ;Control string for UIC hd_IMAGNAME: .ascic / Image / .byte nul .ascic / name / .byte nul .ascic /--------------/ .byte nul alt_IMAGNAME: .ascic / -unavailable-/ ;Alternate just in case. .byte nul full_IMAGNAME: .blkb 65 ;Buffer for full name hd_PID: .ascic / / .byte nul .ascic / PID / .byte nul .ascic /--------/ .byte nul fao_PID: .ascid /!XL/ ;FAO control string. hd_OWNER: .ascic / Owner / .byte nul .ascic / PID / .byte nul .ascic /--------/ .byte nul fao_OWNER: .ascid /!XL/ ;FAO control string. hd_PRCNAM: .ascic / Process / .byte nul .ascic / name / .byte nul .ascic /---------------/ .byte nul hd_STATE: .ascic / / .byte nul .ascic /State/ .byte nul .ascic /-----/ .byte nul hd_PRI: .ascic /Current/ .byte nul .ascic / prio / .byte nul .ascic /-------/ .byte nul fao_pri: .ascid / !2UL / ;A descriptor for current priority hd_PRIB: .ascic /Base/ .byte nul .ascic /prio/ .byte nul .ascic /----/ .byte nul fao_prib: .ascid / !2UL / ;A descriptor for base priority hd_USERNAME: .ascic / / .byte nul .ascic / Username / .byte nul .ascic /------------/ .byte nul ;Now a table of states: statnum = 15 ;Total number of known states. statab: .ascii 'col ' .ascii 'pg ' .ascii 'mwait' .ascii 'cef ' .ascii 'pfw ' .ascii 'lef ' .ascii 'lefo ' .ascii 'hib ' .ascii 'hibo ' .ascii 'susp ' .ascii 'suspo' .ascii 'fpg ' .ascii 'com ' .ascii 'como ' .ascii 'cur ' .Page .Sbttl Pointers - Blocks of pointers for item-specific things. .Psect Pointers, noexe, quad ;Pointers to column headers. Note, the pointers must be ;in the same order as the items appeared in the $GETJPI ;item list. headers:.address hd_TERMINAL .address hd_UIC .address hd_PID .address hd_PRCNAM .address hd_STATE .address hd_PRI .address hd_PRIB .address hd_USERNAME .long 0 ;Nothing for STS flags. .address hd_OWNER .address hd_IMAGNAME ;Pointers to the various comparison routines for different types of sorts. ;NSORT is called to sort our data prior to output. In the call we specify ;the comparison routine it is to use according to what we key from. comps: .address comp_TERMINAL .address comp_UIC .address comp_PID .address comp_PRCNAM .address comp_STATE .address comp_PRI .address comp_PRIB .address comp_USERNAME .long 0 .address comp_OWNER .address comp_IMAGNAME .Page .SBTTL Main program .Psect Code, nowrt, exe, long .Entry names,^M<> pushal outdesc ;No length return. pushl #00 ;No default prompting. pushal outdesc ;Return command line here calls #3,LIB$GET_FOREIGN ;and go get it. movq outdesc,- TPARSE_block + TPA$L_STRINGCNT ;Get ready to parse it pushal Nam_key ;The keyword table pushal Nam_state ;The state table pushal TPARSE_block ;The TPARSE block calls #3,LIB$TPARSE ;and go parse it check clrl r10 ;r10 will count displayable items clrq r7 ;We'll use r7 and r8 for counters moval joblist,r6 ;R6 will contain job info pointer. moval info,r9 ;R9 points to info block getinf: $getjpi_s efn=#1, pidadr=wildpid,- itmlst=itemlist, iosb=iosb blbs r0,chkinf ;If successful go wait for completion cmpw r0,#SS$_SUSPENDED ;If only suspended, then go ahead beql chkinf cmpw r0,#SS$_NONEXPR ;If nonexistant, skip it. beql getinf cmpw r0,#SS$_NOMOREPROC ;If we're done let's go output it bneq 1$ ;Skip if ok brw sort ;otherwise go output it 1$: brw error ;anything else we error ;Now we fall through a series of filters to determine whether ;or not we wanna bother to display this job: chkinf: incl r7 ;Increment job count tstw Term_len(r9) ;See if he had terminal beql 10$ incl r8 ;if so count it 10$: caseb CP_sys,#1,#1 ;Check the "SYS" switch 1$: .word System - 1$ ; -here if we want System job .word Nosys - 1$ ; -here if we want non-system brb CK_type ; -fall through for all jobs System: cmpw Uicnum+2(r9),#^O10 ;Is it a system number? bleq CK_type ;if so go on brw Getinf ;else toss this one Nosys: cmpw Uicnum+2(r9),#^O10 ;Is it a non-system number? bgtr CK_type ;if so go on brw Getinf ;else toss it CK_type:tstw Term_len(r9) ;Terminal job? beql 10$ ;if not skip on bbs #0,CP_type,cmpstr ;If we wanna see it then keep brw Getinf ;else toss it away. 10$: bbc #PCB$V_BATCH,- sts_flags(r9), 20$ ;Skip if not a batch job movc3 #9,batch,Term_len(r9) ; Move in 'batch' indicator. bbs #1,CP_type, cmpstr ;If we wanna see it then keep brw Getinf ;else toss it 20$: tstl owner_pid(r9) ;Is it a subprocess? beql 30$ ;if not skip on movc3 #9,subprc,Term_len(r9) ; Move in 'Subpr' indicator. bbs #2,CP_type, cmpstr ;If we wanna see it then keep brw Getinf ;So, must be detached job 30$: bbs #3,CP_type, cmpstr ;If we wanna see it then keep brw Getinf ;else toss it ; Finally, check if we have a list of special interest jobs. ; These may be either terminal or username specific. The ; two types are indistinguishable. Just check the character ; strings against terminal and username. cmpstr: tstb strptrs ;See if we have any specials beql wait ;skip if not clrl r4 ;r4 is index into descriptors 1$: movaq strptrs[r4],r11 ;Get the descriptor tstl (r11) ;If no more then we toss it bneq 10$ ;else skip brw Getinf 10$: cmpc3 (r11),@4(r11),- termnum(r9) ;See if we want this one as terminal beql wait ;if so go on cmpc5 (r11),@4(r11),#^A/ /,- usr_len(r9),usrnam(r9) ;try matching the username then beql wait incl r4 ;if not then try next one. brb 1$ ; Here to get additional, possibly time consuming, information: wait: movl #.Imagname,r0 ; First of these items 1$: moval outinf[r0],r1 ; Calculate offset. tstb (r1) ; See if we want it beql 2$ ; If not, skip over it cmpb (r1),#-1 ; See if end of list bneq 3$ ; If not, then we need the item brb saveit ; if end then don't need. 2$: incl r0 ; Look at the next item brb 1$ 3$: $getjpi_s efn=#1, pidadr=ProcID(r9),- itmlst=sloitems, iosb=iosb $waitfr_s efn=#1 ;Wait for AST check movzwl iosb,r0 ;Get status blbs r0,saveit ;If no error, continue cmpw r0,#SS$_SUSPENDED ;If it's suspended then bneq 10$ movw #-1,image_len(r9) ;a negative length means print ;alternate message. movzwl #SS$_NORMAL, r0 ;Clear out error brb saveit ;and continue 10$: cmpw r0,#SS$_NONEXPR ;If nonexistant, skip it. bneq 20$ brw Getinf 20$: brw error ;anything else we error. saveit: incl r10 ;Count the number to display pushal (r6) ;Job slot to receive pointer pushal blksiz ;and the size of block we need. calls #2, LIB$GET_VM ;Grab a block check movc3 #offset, info,- @(r6)+ ;Move our block out there brw getinf ;and get next process. ;Now we write out information ;First get terminal characteristics. sort: $GETDEV_S devnam, devchr,- devchr ;Get primary characteristics. check cvtwb devbuff+6,linlen ;Get the terminal's width tstb cp_header ; See if he wants the header beql ckjob ; skip if not ; Write out our little job count header. movl r7, totusr ;Get total job count bneq 10$ ; See if we have the info brw ckjob ; otherwise skip it 10$: movl r8, intusr ;Get interactive job count movl #256,outdesc ;Reset max line length in descriptor. $FAO_s ctrstr=users, outbuf=outdesc,- p1=intusr, p2=totusr, p3=dtime check locc #^A".", outdesc, string ;Find the period in date-time movb #0,(r1) ;Terminate string here outstr string ;and write it out outstr crlf ;followed by a ; Make sure we have jobs to list ckjob: tstl r10 ;See if we got any jobs at all bneq 10$ ;if so then skip outstr crlf ;Space it with a crlf outstr nojobs ;Write our message outstr crlf ;and another crlf brw error ;and exit. 10$: ; Now to sort them: movzbl cp_sortkey,r0 ;Get the sort key we want pushl r10 ;Save the number in list pushl comps[r0] ;and pass appropriate comp routine. pushal 4(sp) ;and save pointer to it pushal joblist ;and the job list. calls #3,Nsort ;Call the sorter ;Sort output fields. pushl #itemnum ;Temp location for number of fields. pushal comp_field ;Addr of comparison routine. addl3 #4,sp,-(sp) ;Addr of temp location for itemnum pushal outinf ;and finally the field table. calls #3,Nsort ;Call the sorter. tstl (sp)+ ;and clean up the stack. ;Now we output the appropriate column headers. tstb cp_header ;See if he wants the headers bneq 20$ ;If so continue brw disply ;otherwise quit to next section 20$: moval outinf,r5 ;Get the first item in info header clrb r2 ;Counter for pass (two lines allowed) wrthdr: movl r5,r6 ;Get pointer to item fields nxtlin: movb linlen,r8 ;r8 to be character counter outstr crlf ;A nice crlf getfld: movzbl 1(r6),r7 ;Pick up the information item code tstb r7 ;See if end of fields blss endfld tstb (r6) ;See if we write it beql nxtfld ;if not, go get next one movl headers[r7],r7 ;Pick up the address of the string beql nxtfld ;If no string, then skip. tstb r2 ;See which line we are doing beql 10$ ;and skip if first. movzbl (r7)+,r1 ;Otherwise move on to second line addl2 r1,r7 ;like so. incl r7 cmpb r2,#1 ;If second then skip beql 10$ movzbl (r7)+,r1 ;Otherwise move on to third line addl2 r1,r7 ;like so. incl r7 ;Now to write the column headers, as many as fit nicely on a line. ;If we need, we continue on the next line. 10$: decb r8 ;Remember the initial extra space. cmpb (r7),r8 ;See if we can fit it on the line blequ 20$ ;if so then start a new line. brw endfld ;and do second line. 20$: outchr space ;First write a space before each one. outstr 1(r7) ;Write the item header subb2 (r7),r8 ;and subtract from remainder of line. nxtfld: addl2 #4,r6 ;Skip to next field in list brw getfld endfld: cmpb r2,#1 ;See which line of header bgtr 10$ ;If first then we incb r2 ;increment pass counter brw wrthdr ;and go do next line of header. 10$: tstb 1(r6) ;See how we ended the line blss disply ;and quit to next section if complete. clrb r2 ;Otherwise clear out pass counter movl r6,r5 ;Save what item we're on. outstr crlf ;Write an extra blank line brw nxtlin ;and continue. ;Now we write out whatever we need for each info block. disply: moval joblist,r9 ;r9 points at job slot wrtinf: movl (r9)+,r10 ;r10 points at job information bneq 10$ ;If we have a job here, skip brw egress ;otherwise exit. 10$: outstr crlf ;First we want a carriage return. moval outinf,r6 ;Get the first item in info header movb linlen,r8 ;r8 to be character counter getitm: movzbl 1(r6),r7 ;Pick up the information item code tstb (r6) ;See if we write it beql nxtinf ;if not, go get next one ;Now we process the information for output according to the ;item code in r7 caseb r7,#.terminal,#<.imagname-.terminal> 1$: .word wr_terminal-1$ ;Terminal name. .word wr_uic-1$ ;Process' UIC .word wr_pid-1$ ;Process ID .word wr_prcnam-1$ ;Process name .word wr_state-1$ ;Current state .word wr_pri-1$ ;Process current priority .word wr_prib-1$ ;Process base priority .word wr_username-1$ ;Username .word wrtinf-1$ ;can't be STS .word wr_owner-1$ ;Subprocess owner PID .word wr_imagname-1$ ;Image name brb wrtinf ;Anything else is end of list. writit: cmpb r11,r8 ;See if we can fit it on the line blssu 20$ ;if so then skip outstr crlf ;otherwise put a crlf in. movb linlen,r8 ;Reset line length 20$: decb r8 ;Remember leading space subb2 r11,r8 ;and subtract from remainder of line. outchr space ;First write a space before each one. tstl r7 ;If pointer is non-zero, then bneq 40$ ;write it normally, 30$: outchr space ;otherwise we fill field with spaces. sobgtr r11,30$ brb nxtinf ;Skip past string output. 40$: outstr (r7) ;Write the item nxtinf: addl2 #4,r6 ;Skip to next field in list brw getitm egress: outstr crlf ;a crlf to end it all movw #SS$_NORMAL,r0 ;Normal completion ret ;For now we just leave ;Error handler if someone died. error: ret .Page .Sbttl Write routines - Get strings for each info item. ;These are the output formatting routines for the information ;that we will be typing. ;We return a pointer to the zero terminated character string in ;R7. The length of the string is in r11. ;Note: If we have no info, we return a 0 in r7. wr_terminal: clrl r7 ;Clear out pointer to string movzbl hd_terminal,r11 ;Get the field size tstw term_len(r10) ;See if we have a terminal to write beql 10$ moval hd_terminal+1,r7 ;If so get the string movc5 term_len(r10),termnum(r10),- #^A/ /,r11,(r7) 10$: brw writit ;and go write it out wr_uic: movzbl hd_uic,r11 ;Get field size moval hd_uic+1,r7 ;and address for string. movzwl r11,outdesc ;Set field size in the descriptor movzwl uicnum+2(r10),r0 ;Get group number movzwl uicnum(r10),r1 ;and member $FAO_S ctrstr=fao_uic,- outbuf=outdesc,- outlen=outdesc,- p1=r0,- ;Convert longword to string p2=r1 movc5 outdesc,string,#^A/ /,- r11,(r7) ;Go get it brw writit ;and go write it out wr_imagname: movzbl hd_imagname,r11 ;Get the field size moval hd_imagname+1,r7 ;and the address for string. tstw image_len(r10) ;First see if we need alt message bgeq 1$ movzbw alt_imagname,r0 ;If so get the length moval alt_imagname+1,r7 ;and the "-swapped-" message. brw writit ;and go write it out. 1$: tstb 2(r6) ;Full or Short image? beql wr_F_imagname locc #^A/]/,image_len(r10),image(r10);We trunc to short form bneq 10$ ;Skip of we found one locc #^A/>/,image_len(r10),image(r10) ;else try this guy. bneq 10$ ;Skip if this was it moval image(r10),r1 ;If still not found, use from start. movzwl image_len(r10),r0 ;Also use full length of string. bneq 10$ ;Make sure not zero-length clrl r7 ;If it is, assume no info brw writit ;and return 10$: addl3 #1,r1,r2 ;Set to 1st char in filename and save decl r0 ;and dec remainder of string by 1 locc #^A/;/,r0,(r2) ;Find the semicolon in ver number subl2 r2,r1 ;Stuff filename length into r1 decl r11 ;Decrement length by one movtc r1,(r2),#^A/ /,uclc,r11,1(r7) ;Finally, we get the filename. tstb 1(r1) ;See if has version number beql 12$ ;skip if not movb #^A/ /,(r7) ;else was not installed. brb 15$ 12$: movb #^A/*/,(r7) ;If it is installed, indicate 15$: bbc #6,1(r7),20$ ;Skip if its not alpha bicb2 #^X20,1(r7) ;convert first char to upcase 20$: brw writit ;and go write it out wr_F_imagname: wr_pid: movzbl hd_pid,r11 ;Get the field size moval hd_pid+1,r7 ;and the string address. movzwl r11,outdesc ;Set field size in the descriptor $FAO_S ctrstr=fao_pid,- outbuf=outdesc,- outlen=outdesc,- p1=procid(r10) ;Convert longword to string movc5 outdesc,string,#^A/ /,- r11,(r7) ;Go get it brw writit ;and go write it out wr_owner: movzbl hd_owner,r11 ;Get the field size moval hd_owner+1,r7 ;and the string address. movzwl r11,outdesc ;Set field size in the descriptor tstl owner_PID(r10) ;Check if he has an owner bneq 10$ ;If so skip on movc5 #0,(r7),#^A/ /,- r11,(r7) ;Fill with spaces if none brw writit 10$: $FAO_S ctrstr=fao_owner,- outbuf=outdesc,- outlen=outdesc,- p1=owner_PID(r10) ;Convert longword to string movc5 outdesc,string,#^A/ /,- r11,(r7) ;Go get it brw writit ;and go write it out wr_prcnam: movzbl hd_prcnam,r11 ;Get field size moval hd_prcnam+1,r7 ;and address for name string. movtc proc_len(r10),procnam(r10),- #^A/ /,nocont,r11,(r7) ;Now grab the string itself brw writit ;and go write it out wr_state: movzbl hd_state,r11 ;Get the field size clrl r7 ;In case we don't have a known one. cmpl status(r10),#statnum ;See if we know this state bgequ 10$ ;if not we return moval hd_state+1,r7 ;Buffer address. mull3 status(r10),#5,r2 ;Calculate address for state string movc5 #5,statab(r2),#^A/ /,r11,(r7) ;and go get it. 10$: brw writit ;Go write it out wr_pri: movzbl hd_pri,r11 ;Get field size moval hd_pri+1,r7 ;and address for string. movzwl r11,outdesc ;Set field size in the descriptor $FAO_S ctrstr=fao_pri,- outbuf=outdesc,- outlen=outdesc,- p1=prio(r10) ;Convert longword to string movc5 outdesc,string,#^A/ /,- r11,(r7) ;Go get it brw writit ;and go write it out wr_prib: movzbl hd_prib,r11 ;Get field size moval hd_prib+1,r7 ;and address for string. movzwl r11,outdesc ;Set field size in the descriptor $FAO_S ctrstr=fao_prib,- outbuf=outdesc,- outlen=outdesc,- p1=basprio(r10) ;Convert longword to string movc5 outdesc,string,#^A/ /,- r11,(r7) ;Go get it brw writit ;and go write it out wr_username: movzbl hd_username,r11 ;Get field size moval hd_username+1,r7 ;and address for string. movc5 usr_len(r10),usrnam(r10),- #^A/ /,r11,(r7) ;Move in the string brw writit ;and go write it out .Page .Sbttl Comparisons - Comparison routines for different sort keys. ;Now for the special comparison routines for different sorts.. ;First for sort on terminal name: .Entry comp_TERMINAL,^M movl @4(ap),r2 ;First arg movl @8(ap),r3 ;and second... cmpc5 TERM_LEN(r2),TERMNUM(r2),- #00,TERM_LEN(r3),TERMNUM(r3) bleq 10$ ;Return true if less or equal clrl r0 ;else false ret 10$: movl #-1,r0 ;Return a true. ret ;Sort on UIC: .Entry comp_UIC,^M clrl r0 ;Assume false movl @4(ap),r2 ;First arg movl @8(ap),r3 ;second arg. cmpl UICNUM(r2),UICNUM(r3) ;Compare them bgtru 10$ ;skip to return if not LEQ mcoml r0,r0 ;otherwise return true 10$: ret ;Sort on IMAGNAME: .Entry comp_IMAGNAME,^M ;Sort on PID: .Entry comp_PID,^M clrl r0 ;Assume false movl @4(ap),r2 ;First arg movl @8(ap),r3 ;second arg. cmpl PROCID(r2),PROCID(r3) ;Compare them bgtru 10$ ;skip to return if not LEQ mcoml r0,r0 ;otherwise return true 10$: ret ;Sort on Owner PID: .Entry comp_OWNER,^M clrl r0 ;Assume false movl @4(ap),r2 ;First arg movl @8(ap),r3 ;second arg. cmpl owner_PID(r2),- owner_PID(r3) ;Compare them bgtru 10$ ;skip to return if not LEQ mcoml r0,r0 ;otherwise return true 10$: ret ;Sort on Process Name: .Entry comp_PRCNAM,^M movl @4(ap),r2 ;First arg movl @8(ap),r3 ;and second... cmpc5 PROC_LEN(r2),PROCNAM(r2),- #00,PROC_LEN(r3),PROCNAM(r3) bleq 10$ ;Return true if less or equal clrl r0 ;else false ret 10$: movl #-1,r0 ;Return a true. ret ;Sort on STATE: .Entry comp_STATE,^M clrl r0 ;Assume false movl @4(ap),r2 ;First arg movl @8(ap),r3 ;second arg. cmpl STATUS(r2),STATUS(r3) ;Compare them bgtru 10$ ;skip to return if not LEQ mcoml r0,r0 ;otherwise return true 10$: ret ;Sort on PRIO: .Entry comp_PRI,^M clrl r0 ;Assume false movl @4(ap),r2 ;First arg movl @8(ap),r3 ;second arg. cmpw PRIO(r2),PRIO(r3) ;Compare them bgtru 10$ ;skip to return if not LEQ mcoml r0,r0 ;otherwise return true 10$: ret ;Sort on BASPRIO: .Entry comp_PRIB,^M clrl r0 ;Assume false movl @4(ap),r2 ;First arg movl @8(ap),r3 ;second arg. cmpw BASPRIO(r2),BASPRIO(r3) ;Compare them bgtru 10$ ;skip to return if not LEQ mcoml r0,r0 ;otherwise return true 10$: ret ;Sort on USERNAME: .Entry comp_USERNAME,^M movl @4(ap),r2 ;First arg movl @8(ap),r3 ;and second... cmpc5 USR_LEN(r2),USRNAM(r2),- #00,USR_LEN(r3),USRNAM(r3) bleq 10$ ;Return true if less or equal clrl r0 ;else false ret 10$: movl #-1,r0 ;Return a true. ret ;Sort output fields by low order byte only... .Entry comp_field,^M<> clrl r0 ;Set up for FALSE return cmpb @4(ap),@8(ap) ;Compare them bgtru 10$ ;Return false if greater mcoml r0,r0 ;otherwise true 10$: ret .end names