robert@hslrswi.UUCP (Robert Ward) (07/11/85)
Send comments, suggestions, bug reports, bug fixes, etc. to - Robert Ward, Hasler AG, Abt. 34, Belpstrasse 23, CH-3000 Bern 14, Switzerland. (... mcvax!cernvax!hslrswi!robert). ******************************************************************************* This is a sh(1) archive. In order to extract the contents of this shar, use an editor to place the contents of this file from the dotted line onwards into a second, temporary file. Then run sh on that second file. --------------------------------- C U T --- H E R E --------------------------- #! /bin/sh echo Extracting printproc.c cat > printproc.c << '---END-OF-printproc.c---' # include "sps.h" # include "flags.h" # include <h/text.h> /* PRINTPROC - Pretty print a process according to the switches. */ printproc ( p, md ) register struct process *p ; int md ; { register char *chp ; register struct text *tp ; register struct hashtab *hp ; char chbuf[10] ; time_t time ; time_t chtime ; # ifdef BSD42 time_t utime ; time_t uchtime ; # endif extern short Lastuid, Lastpgrp ; extern struct flags Flg ; char *waitingfor() ; struct hashtab *hashuid() ; double percentmem() ; /* List tty name and foreground/background/detached information */ printf( "%2.2s%c", p->pr_tty->l_name, !p->pr_p.p_pgrp ? ' ' : # ifdef SDETACH p->pr_p.p_flag & SDETACH ? '_' : # endif p->pr_p.p_pgrp == p->pr_tty->l_pgrp ? '.' : ' ' ) ; hp = hashuid( p->pr_p.p_uid ) ; if ( !md ) { /* If a top-level process, list the user name */ if ( hp ) printf( "%-8.8s ", hp->h_uname ) ; else printf( "user%-4.4d ", p->pr_p.p_uid ) ; } else { /* Usually list an asterisk for a child process */ md = md > 8 ? 8 : md ; printf( "%*s%c", md, "", p->pr_p.p_pgrp == Lastpgrp ? '|' : '*' ) ; /* But beware of setuid processes */ md = 8 - md ; if ( p->pr_p.p_uid == Lastuid ) printf( "%-*.*s", md, md, "" ) ; else if ( hp ) printf( "%-*.*s", md, md, hp->h_uname ) ; else { md -= 4 ; printf( "user%-*.*d", md, md, p->pr_p.p_uid ) ; } } Lastuid = p->pr_p.p_uid ; Lastpgrp = p->pr_p.p_pgrp ; if ( Flg.flg_d ) { /* List disc I/O and paging information */ if ( !p->pr_upag || p->pr_p.p_stat == SZOMB ) { prcmd( p, 49, -63 ) ; return ; } printf( "%2d %8d+%8d %4d %8d %8D ", p->pr_files, # ifdef BSD42 p->pr_rself.ru_majflt, p->pr_rself.ru_minflt, p->pr_rself.ru_nswap, p->pr_rself.ru_inblock + p->pr_rself.ru_oublock, KBYTES( p->pr_rself.ru_idrss + p->pr_rself.ru_isrss + p->pr_rself.ru_ixrss ) ) ; # else p->pr_vself.vm_majflt, p->pr_vself.vm_minflt, p->pr_vself.vm_nswap, p->pr_vself.vm_inblk + p->pr_vself.vm_oublk, KBYTES( (p->pr_vself.vm_idsrss + p->pr_vself.vm_ixrss) / Info.i_hz ) ) ; # endif prcmd( p, 5, -63 ) ; return ; } if ( !Flg.flg_v ) { /* Not verbose so just list command arguments */ prcmd( p, 5, -19 ) ; return ; } /* Arrive here if being verbose ; list cpu information */ switch ( p->pr_p.p_stat ) { case SSLEEP : case SWAIT : case SIDL : /* Determine why a process should be in a wait state */ chp = waitingfor( p ) ; break ; case SRUN : chp = "run" ; break ; case SZOMB : chp = "exit" ; break ; case SSTOP : chp = "stop" ; break ; } /* If the process is loaded, list the status information in capitals */ printf( "%-6.6s ", p->pr_p.p_flag & SLOAD ? (capitals( chp, chbuf ), chbuf) : chp ) ; /* List process flags */ printf( "%c%c%c", p->pr_p.p_flag & SSYS ? 'U' : p->pr_p.p_flag & STRC ? 'T' : ' ', p->pr_p.p_flag & SVFORK ? 'V' : p->pr_p.p_flag & SPHYSIO ? 'I' : ' ', p->pr_p.p_flag & SUANOM ? 'A' : ' ' ) ; /* List process niceness */ if ( p->pr_p.p_nice != NZERO ) printf( "%3d ", p->pr_p.p_nice - NZERO ) ; else printf( " " ) ; if ( p->pr_p.p_stat == SZOMB ) { prcmd( p, 41, -69 ) ; return ; } /* List process and text virtual sizes */ printf( "%4d", KBYTES( p->pr_p.p_dsize + p->pr_p.p_ssize ) ) ; if ( tp = p->pr_p.p_textp ) printf( "+%3d ", KBYTES( tp->x_size ) ) ; else printf( " " ) ; /* List process and text real sizes */ printf( "%4d", KBYTES( p->pr_p.p_rssize ) ) ; if ( tp ) printf( "+%3d %2.0f ", KBYTES( tp->x_rssize ), percentmem( p ) ); else printf( " " ) ; /* List information obtained from the upage. This includes the process times and command arguments. */ if ( !p->pr_upag ) { prcmd( p, 20, -69 ) ; return ; } /* List process time information */ # ifdef BSD42 time = Flg.flg_q ? p->pr_rself.ru_utime.tv_sec : p->pr_rself.ru_utime.tv_sec + p->pr_rself.ru_stime.tv_sec ; utime = Flg.flg_q ? p->pr_rself.ru_utime.tv_usec : p->pr_rself.ru_utime.tv_usec + p->pr_rself.ru_stime.tv_usec ; chtime = Flg.flg_q ? p->pr_rchild.ru_utime.tv_sec : p->pr_rchild.ru_utime.tv_sec + p->pr_rchild.ru_stime.tv_sec ; uchtime = Flg.flg_q ? p->pr_rchild.ru_utime.tv_usec : p->pr_rchild.ru_utime.tv_usec + p->pr_rchild.ru_stime.tv_usec ; prcpu( time, utime ) ; if ( chtime != 0L ) { printf( "+" ) ; prcpu( chtime, uchtime ) ; } # else time = Flg.flg_q ? p->pr_vself.vm_utime : p->pr_vself.vm_utime + p->pr_vself.vm_stime ; chtime = Flg.flg_q ? p->pr_vchild.vm_utime : p->pr_vchild.vm_utime + p->pr_vchild.vm_stime ; prcpu( time ) ; if ( chtime != 0L ) { printf( "+" ) ; prcpu( chtime ) ; } # endif else printf( " " ) ; # ifdef BSD42 if ( time || utime ) # else if ( time ) # endif printf( " %2.0f ", p->pr_p.p_pctcpu * 100.0 ) ; else printf( " " ) ; /* Finally, list the process command arguments. */ prcmd( p, 5, -69 ) ; } /* CAPITALS - Converts letters in `chp' to upper-case in buffer `buf'. */ capitals ( chp, buf ) register char *chp ; register char *buf ; { while ( *buf = *chp++ ) { if ( 'a' <= *buf && *buf <= 'z' ) *buf -= 'a' - 'A' ; buf++ ; } } ---END-OF-printproc.c--- echo Extracting prsummary.c cat > prsummary.c << '---END-OF-prsummary.c---' # include "sps.h" /* PRSUMMARY - Print the summarising information */ prsummary () { extern struct summary Summary ; printf( "%D (%Dk) processes, %D (%Dk) busy, %D (%Dk) loaded, %D (%Dk) swapped\n", Summary.sm_ntotal, KBYTES( Summary.sm_ktotal ), Summary.sm_nbusy, KBYTES( Summary.sm_kbusy ), Summary.sm_nloaded, KBYTES( Summary.sm_kloaded ), Summary.sm_nswapped, KBYTES( Summary.sm_kswapped ) ) ; Summary.sm_ntotal = 0L ; Summary.sm_ktotal = 0L ; Summary.sm_nbusy = 0L ; Summary.sm_kbusy = 0L ; Summary.sm_nloaded = 0L ; Summary.sm_kloaded = 0L ; Summary.sm_nswapped = 0L ; Summary.sm_kswapped = 0L ; } ---END-OF-prsummary.c--- echo Extracting readstatus.c cat > readstatus.c << '---END-OF-readstatus.c---' # include "sps.h" # include <h/text.h> /* READSTATUS - Reads the kernel memory for current processes and texts */ readstatus ( process, text ) register struct process *process ; struct text *text ; { register struct proc *p ; register struct proc *p0 ; register struct process *pr ; extern struct info Info ; extern int Flkmem ; char *getcore() ; /* Read current text information */ memseek( Flkmem, (long)Info.i_text0 ) ; if ( read( Flkmem, (char*)text, Info.i_ntext * sizeof( struct text ) ) != Info.i_ntext * sizeof( struct text ) ) prexit( "sps - Can't read system text table\n" ) ; /* Read current process information */ p0 = (struct proc*)getcore( sizeof( struct proc )*Info.i_nproc ) ; memseek( Flkmem, (long)Info.i_proc0 ) ; if ( read( Flkmem, (char*)p0, Info.i_nproc * sizeof( struct proc ) ) != Info.i_nproc * sizeof( struct proc ) ) prexit( "sps - Can't read system process table\n" ) ; /* Copy process information into our own array */ for ( p = p0, pr = process ; pr < &process[ Info.i_nproc ] ; p++, pr++ ) pr->pr_p = *p ; free( (char*)p0 ) ; } ---END-OF-readstatus.c--- echo Extracting selectproc.c cat > selectproc.c << '---END-OF-selectproc.c---' # include "sps.h" # include "flags.h" /* ** SELECTPROC - Given a process structure, this procedure decides whether ** the process is a candidate for printing. */ selectproc ( p, process, thisuid ) register struct process *p ; register struct process *process ; int thisuid ; { register union flaglist *fp ; register struct process *pp ; extern struct flags Flg ; /* Flg.flg_AZ is an internal flag set if one of flags `A' to `Z' was specified. If this is not set, a process is listed only if it or one of its ancestors belongs to the invoking user. */ if ( !Flg.flg_AZ ) for ( pp = p ; pp > &process[1] ; pp = pp->pr_pptr ) if ( thisuid == pp->pr_p.p_uid ) return ( 1 ) ; if ( Flg.flg_A ) return ( 1 ) ; if ( Flg.flg_P ) for ( fp = Flg.flg_Plist ; fp->f_pid >= 0 ; fp++ ) if ( fp->f_pid == p->pr_p.p_pid ) return ( 1 ) ; if ( Flg.flg_U ) for ( pp = p ; pp > &process[1] ; pp = pp->pr_pptr ) for ( fp = Flg.flg_Ulist ; fp->f_uid >= 0 ; fp++ ) if ( fp->f_uid == pp->pr_p.p_uid ) return ( 1 ) ; switch ( p->pr_p.p_stat ) { case SRUN : if ( Flg.flg_B ) return ( 1 ) ; break ; case SSLEEP : if ( Flg.flg_B && p->pr_p.p_pri < PZERO && p->pr_p.p_pid > MSPID ) return ( 1 ) ; case SWAIT : case SIDL : if ( Flg.flg_W ) return ( 1 ) ; break ; case SSTOP : if ( Flg.flg_S ) return ( 1 ) ; break ; case SZOMB : if ( Flg.flg_Z ) return ( 1 ) ; break ; default : break ; } return ( 0 ) ; } ---END-OF-selectproc.c--- echo Extracting selecttty.c cat > selecttty.c << '---END-OF-selecttty.c---' # include "sps.h" # include "flags.h" /* SELECTTTY - Decides whether this process is interesting for its tty */ selecttty ( p ) register struct process *p ; { register union flaglist *fp ; extern struct flags Flg ; for ( fp = Flg.flg_Tlist ; fp->f_ttyline ; fp++ ) if ( fp->f_ttyline == p->pr_tty ) return ( 1 ) ; return ( 0 ) ; } ---END-OF-selecttty.c--- echo Extracting sps.h cat > sps.h << '---END-OF-sps.h---' # include <h/param.h> # include <h/dir.h> # include <h/user.h> # include <h/proc.h> /* ** Maximum # of users to be considered. (Should probably be ** approximately double the # of users in /etc/passwd.) */ # define MAXUSERID 100 /* Maximum # ttys to be considered ... */ # define MAXTTYS 50 /* Maximum user name length ... */ # define UNAMELEN 8 /* Maximum process-id not to be considered busy ... */ # define MSPID 2 /* # of wait states defined in the `struct info' ... */ # define NWAITSTATE 35 /* Convert clicks to kbytes ... */ # define KBYTES( size ) ((size) >> (10 - PGSHIFT)) /* Standard files to be examined ... */ # define FILE_MEM "/dev/mem" /* System physical memory */ # define FILE_KMEM "/dev/kmem" /* Kernel virtual memory */ # define FILE_SWAP "/dev/drum" /* Swap/paging device */ # define FILE_DEV "/dev" /* Directory of tty entries */ # define FILE_SYMBOL "/vmunix" /* Symbol file for nlist() */ # define FILE_INFO "/etc/spsinfo" /* Sps information file */ /* Structure to hold necessary information concerning a tty ... */ struct ttyline { struct tty *l_addr ; /* Ptr to tty struct in kmem */ unsigned short l_pgrp ; /* Tty process group */ char l_name[2] ; /* Tty character name */ dev_t l_dev ; /* Tty device # */ } ; /* Structure holding a single hash table entry ... */ struct hashtab { unsigned short h_uid ; /* Uid of user entry */ char h_uname[ UNAMELEN ] ; /* Corresponding name */ } ; /* ** Format of the standard information file maintained by sps. ** This structure is filled in at initialisation time and then is read back ** in whenever sps is invoked. ** Note that the pointer variables in this structure refer to ** kernel virtual addresses, not addresses within sps. ** These variable are typed as such so that pointer arithmetic ** on the kernel addresses will work correctly. */ struct info { /* Kernel values determining process, tty and upage info ... */ struct proc *i_proc0 ; /* address of process table */ int i_nproc ; /* length of process table */ struct text *i_text0 ; /* address of text table */ int i_ntext ; /* length of text table */ struct inode *i_inode0 ; /* address of inode table */ int i_ninode ; /* length of inode table */ struct buf *i_swbuf0 ; /* address of swap buffers */ int i_nswbuf ; /* # swap buffers */ struct buf *i_buf0 ; /* address of i/o buffers */ int i_nbuf ; /* # i/o buffers */ int i_ecmx ; /* max physical memory address*/ struct pte *i_usrptmap ; /* page table map */ struct pte *i_usrpt ; /* page table map */ struct cdevsw *i_cdevsw ; /* device switch to find ttys */ # ifdef BSD42 struct quota *i_quota0 ; /* disc quota structures */ int i_nquota ; /* # quota structures */ int i_dmmin ; /* The start of the disc map */ int i_dmmax ; /* The end of the disc map */ struct mbuf *i_mbutl ; /* Start of mbuf area */ # else int i_hz ; /* Clock rate */ # endif # ifdef CHAOS caddr_t i_Chconntab ; /* Chaos connection table */ # endif /* Kernel addresses are associated with process wait states ... */ caddr_t i_waitstate[ NWAITSTATE ] ; /* User names, stored in a hash table ... */ struct hashtab i_hnames[ MAXUSERID ] ; /* Tty device info ... */ struct ttyline i_ttyline[ MAXTTYS ] ; } ; /* ** The symbol structure cross-references values read from the kernel with ** their place in the info structure, and if such a value is associated with ** a process wait state or not. */ struct symbol { char *s_kname ; /* Kernel symbol name */ char s_indirect ; /* Value requires indirection */ caddr_t *s_info ; /* Corresponding info address */ char *s_wait ; /* Reason for wait, if any */ } ; /* The `user' structure obtained from /dev/mem or /dev/swap ... */ union userstate { struct user u_us ; char u_pg[ UPAGES ][ NBPG ] ; } ; /* Information concerning each process filled from /dev/kmem ... */ struct process { struct proc pr_p ; /* struct proc from /dev/kmem */ struct process *pr_plink ; /* Normalised ptrs from above */ struct process *pr_sibling ; /* Ptr to sibling process */ struct process *pr_child ; /* Ptr to child process */ struct process *pr_pptr ; /* Ptr to parent process */ # ifdef BSD42 struct rusage pr_rself ; /* Read from upage for self */ struct rusage pr_rchild ; /* ... and the children */ # else struct vtimes pr_vself ; /* Read from upage for self */ struct vtimes pr_vchild ; /* ... and the children */ # endif int pr_files ; /* # open files */ struct ttyline *pr_tty ; /* Associated tty information */ char *pr_cmd ; /* Command args, from upage */ int pr_upag:1 ; /* Upage was obtained */ int pr_csaved:1 ; /* Cmd args saved by malloc() */ } ; /* Structure to hold summarising information ... */ struct summary { long sm_ntotal ; /* Total # processes */ long sm_ktotal ; /* Total virtual memory */ long sm_nbusy ; /* # busy processes */ long sm_kbusy ; /* Busy virtual memory */ long sm_nloaded ; /* # loaded processes */ long sm_kloaded ; /* Active resident memory */ long sm_nswapped ; /* # swapped processes */ long sm_kswapped ; /* Size totally swapped out */ } ; ---END-OF-sps.h--- echo Extracting termwidth.c cat > termwidth.c << '---END-OF-termwidth.c---' /* ** TERMWIDTH - Sets the external variable `Termwidth' to the # of columns ** on the terminal. */ termwidth () { register char *termtype ; register int twidth ; char buf[ 1025 ] ; extern unsigned Termwidth ; char *getenv() ; Termwidth = 80 ; if ( !(termtype = getenv( "TERM" )) ) return ; if ( tgetent( buf, termtype ) != 1 ) return ; twidth = tgetnum( "co" ) ; if ( twidth > 40 ) Termwidth = twidth ; } ---END-OF-termwidth.c--- echo Extracting ttystatus.c cat > ttystatus.c << '---END-OF-ttystatus.c---' # include "sps.h" # include "flags.h" # include <stdio.h> # include <h/tty.h> # ifdef CHAOS # include <chunix/chsys.h> # include <chaos/chaos.h> # endif /* ** TTYSTATUS - Reads the kernel memory for tty structures of active processes. ** The addresses of the associated struct ttys of /dev/kmem are kept in the ** info structure. Here we use those addresses to access the structures. ** Actually, we are mostly interested just in the process group of each tty. */ ttystatus () { register struct ttyline *lp ; struct tty tty ; extern struct flags Flg ; extern struct info Info ; extern int Flkmem ; if ( Flg.flg_y ) printf( "Ty Dev Addr Rawq Canq Outq Pgrp\n" ) ; lp = Info.i_ttyline ; # ifdef CHAOS while ( lp->l_name[0] && lp->l_name[0] != 'C' ) # else while ( lp->l_name[0] ) # endif { memseek( Flkmem, (long)lp->l_addr ) ; if ( read( Flkmem, (char*)&tty, sizeof( struct tty ) ) != sizeof( struct tty ) ) { fprintf( stderr, "sps - Can't read struct tty for tty%.2s\n", lp->l_name ) ; lp->l_pgrp = 0 ; lp++ ; continue ; } lp->l_pgrp = tty.t_pgrp ; prtty( lp, &tty ) ; lp++ ; } # ifdef CHAOS chaosttys( lp ) ; # endif } /* PRTTY - Print out the tty structure */ prtty ( lp, tty ) register struct ttyline *lp ; register struct tty *tty ; { extern struct flags Flg ; if ( !Flg.flg_y ) return ; printf( "%-2.2s %2d,%2d 0x%08x %4d %4d %4d %5d\n", lp->l_name, major( lp->l_dev ), minor( lp->l_dev ), lp->l_addr, tty->t_rawq.c_cc, tty->t_canq.c_cc, tty->t_outq.c_cc, tty->t_pgrp ) ; } # ifdef CHAOS /* CHAOSTTYS - Finds ttys attached to the Chaos net */ chaosttys ( lp ) register struct ttyline *lp ; { register struct connection **cnp ; register int i ; struct tty tty ; struct connection *conntab[CHNCONNS] ; struct connection conn ; extern struct info Info ; extern int Flkmem ; memseek( Flkmem, (long)Info.i_Chconntab ) ; (void)read( Flkmem, (char*)conntab, sizeof( conntab ) ) ; for ( i = 0, cnp = conntab ; cnp < &conntab[CHNCONNS] ; i++, cnp++ ) { if ( !*cnp ) continue ; memseek( Flkmem, (long)*cnp ) ; (void)read( Flkmem, (char*)&conn, sizeof( struct connection ) ); if ( !(conn.cn_flags & CHTTY) ) continue ; memseek( Flkmem, (long)conn.cn_ttyp ) ; (void)read( Flkmem, (char*)&tty, sizeof( struct tty ) ) ; if ( lp >= &Info.i_ttyline[MAXTTYS] ) prexit( "sps - Too many chaos ttys\n" ) ; lp->l_addr = conn.cn_ttyp ; lp->l_pgrp = tty.t_pgrp ; lp->l_dev = tty.t_dev ; lp->l_name[0] = 'C' ; lp->l_name[1] = i < 10 ? '0'+i : i-10 <= 'z'-'a' ? i-10+'a' : i-10-('z'-'a')+'A' ; prtty( lp, &tty ) ; lp++ ; } } # endif ---END-OF-ttystatus.c--- echo Extracting waitingfor.c cat > waitingfor.c << '---END-OF-waitingfor.c---' # include "sps.h" # include <h/tty.h> # include <h/text.h> # include <h/inode.h> # include <h/buf.h> # ifdef BSD42 # include <h/quota.h> # include <h/mbuf.h> # include <h/socket.h> # include <h/socketvar.h> # endif /* 1 if `w' is in the address range defined by `a1' and `a2' ... */ # define INRANGE( w, a1, a2 ) \ ( (caddr_t)(a1) <= (w) && (w) < (caddr_t)(a2) ) /* WAITINGFOR - Determine what a process is waiting for and describe it. */ char *waitingfor ( p ) struct process *p ; { register caddr_t w ; register struct ttyline *lp ; register struct symbol *s ; register char *cp ; # ifdef BSD42 struct socket sc ; # endif static char wbuf[ 8 ] ; extern struct info Info ; extern struct symbol Symbollist[] ; char *sprintf() ; w = p->pr_p.p_wchan ; if ( !w ) return ( "null" ) ; /* Waiting for a child process, alternatively in a vfork() ? */ if ( INRANGE( w, Info.i_proc0, &Info.i_proc0[ Info.i_nproc ] ) ) return ( p->pr_p.p_flag & SNOVM ? "vfork" : "child" ) ; /* Waiting for a page to be brought in ? */ if ( INRANGE( w, Info.i_swbuf0, &Info.i_swbuf0[ Info.i_nswbuf ] ) ) return ( "swap" ) ; /* Waiting for discio through a block device to complete ? */ if ( INRANGE( w, Info.i_buf0, &Info.i_buf0[ Info.i_nbuf ] ) ) /* SHOULD ACTUALLY READ AS "blkio" BUT "discio" IS WHAT IS GENERALLY MEANT HERE. */ return ( "discio" ) ; /* Waiting for a text page to be brought in ? */ if ( INRANGE( w, Info.i_text0, &Info.i_text0[ Info.i_ntext ] ) ) return ( "swtext" ) ; # ifdef BSD42 /* Waiting for an event associated with the quota system ? */ if ( INRANGE( w, Info.i_quota0, &Info.i_quota0[ Info.i_nquota ] ) ) return ( "quota" ) ; # endif /* Waiting for tty I/O ? If so, find which tty it is */ for ( lp = Info.i_ttyline ; lp->l_name[0] ; lp++ ) if ( INRANGE( w, &lp->l_addr[0], &lp->l_addr[1] ) ) { switch ( w - (int)lp->l_addr ) { case (int)&((struct tty*)0)->t_rawq : /* Read from a tty or slave pty */ cp = "rtty??" ; break ; case (int)&((struct tty*)0)->t_outq : /* Write to a tty or slave pty */ cp = "wtty??" ; break ; case (int)&((struct tty*)0)->t_state : /* Tty not open */ cp = "otty??" ; break ; case (int)&((struct tty*)0)->t_outq.c_cf : /* Read from a controller pty */ cp = "rpty??" ; break ; case (int)&((struct tty*)0)->t_rawq.c_cf : /* Write to a controller pty */ cp = "wpty??" ; break ; default : cp = "?tty??" ; break ; } cp[4] = lp->l_name[0] ; cp[5] = lp->l_name[1] ; return ( cp ) ; } /* Waiting for an inode ? */ if ( INRANGE( w, Info.i_inode0, &Info.i_inode0[ Info.i_ninode ] ) ) switch ( ((int)w - (int)Info.i_inode0) % sizeof( struct inode )) { # ifdef BSD42 case (int)&((struct inode*)0)->i_exlockc : /* Exclusive lock on this inode */ return ( "exlock" ) ; case (int)&((struct inode*)0)->i_shlockc : /* Shared lock on this inode */ return ( "shlock" ) ; # else case 1 : return ( "wpipe" ) ; case 2 : return ( "rpipe" ) ; case (int)&((struct inode*)0)->i_un.i_group.g_datq : return ( "rmux" ) ; # endif default : /* Inode probably locked */ return ( "inode" ) ; } # ifdef BSD42 /* Waiting for a structure inside an mbuf ? If so, try to find why */ if ( INRANGE( w, Info.i_mbutl, &Info.i_mbutl[ NMBCLUSTERS * CLBYTES / sizeof( struct mbuf ) ] ) ) switch ( ((int)w - (int)Info.i_mbutl) % sizeof( struct mbuf ) - (int)&((struct mbuf*)0)->m_dat[0] ) { case (int)&((struct socket*)0)->so_timeo : /* Socket timeout event */ return ( "socket" ) ; case (int)&((struct socket*)0)->so_rcv.sb_cc : /* Read from an empty socket. Here we actually attempt to determine whether the socket structure in question really does refer to a socket, or whether it is in fact a pipe in disguise. */ return ( getsocket( (struct socket*)(w - (int)&((struct socket*)0)->so_rcv.sb_cc), &sc ) && sc.so_type == SOCK_STREAM && !sc.so_rcv.sb_hiwat && !sc.so_rcv.sb_mbmax && (sc.so_state & (SS_ISCONNECTED|SS_CANTRCVMORE)) ? "rpipe" : "rsockt" ) ; case (int)&((struct socket*)0)->so_snd.sb_cc : /* Write to a full socket. Again, we try to determine whether or not this is a real socket or a pipe. */ return ( getsocket( (struct socket*)(w - (int)&((struct socket*)0)->so_snd.sb_cc), &sc ) && sc.so_type == SOCK_STREAM && sc.so_rcv.sb_hiwat == 2048 && sc.so_rcv.sb_mbmax == 4096 && (sc.so_state & (SS_ISCONNECTED|SS_CANTSENDMORE)) ? "wpipe" : "wsockt" ) ; default : /* Other mbuf event */ return ( "mbuf" ) ; } # endif /* Look in the symbol table for known wait addresses. */ for ( s = Symbollist ; s->s_kname ; s++ ) if ( s->s_wait && w == *s->s_info ) return ( s->s_wait ) ; /* No reason for the wait state has been found. Return the wait channel as a hexadecimal address. */ (void)sprintf( wbuf, "x%05x", w - 0x80000000 ) ; return ( wbuf ) ; } # ifdef BSD42 /* ** GETSOCKET - Reads a `struct socket' from the kernel virtual memory address ** identified by `ks' into the buffer `s'. */ getsocket ( ks, s ) struct socket *ks ; struct socket *s ; { extern int Flkmem ; memseek( Flkmem, (long)ks ) ; return ( read( Flkmem, (char*)s, sizeof( struct socket ) ) == sizeof( struct socket ) ) ; } # endif ---END-OF-waitingfor.c---