home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / sps3 / part03 < prev    next >
Encoding:
Text File  |  1992-05-08  |  43.1 KB  |  1,526 lines

  1. Newsgroups: comp.sources.unix
  2. From: robert@olsen.ch (Robert Ward)
  3. Subject: v26i026: sps3 - show process status, Part03/03
  4. Sender: unix-sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: robert@olsen.ch (Robert Ward)
  8. Posting-Number: Volume 26, Issue 26
  9. Archive-Name: sps3/part03
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 3 (of 3)."
  18. # Contents:  getcmd.c printproc.c sps.1 waitingfor.c
  19. # Wrapped by vixie@cognition.pa.dec.com on Sat May  9 22:30:50 1992
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'getcmd.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'getcmd.c'\"
  23. else
  24. echo shar: Extracting \"'getcmd.c'\" \(7639 characters\)
  25. sed "s/^X//" >'getcmd.c' <<'END_OF_FILE'
  26. X# ifndef lint
  27. static char SccsId[] =  "@(#)getcmd.c    1.8\t6/26/91" ;
  28. X# endif
  29. X
  30. X# include       "sps.h"
  31. X# include       "flags.h"
  32. X# ifdef KVM
  33. X#  include      <kvm.h>
  34. X#  include      <ctype.h>
  35. X# else
  36. X#  include      <h/vm.h>
  37. X#  ifdef BSD42
  38. X#   include    <machine/pte.h>
  39. X#  else BSD42
  40. X#   include      <h/pte.h>
  41. X#  endif BSD42
  42. X# endif KVM
  43. X
  44. X/*
  45. X** GETCMD - Returns a character string read from a process' upage.
  46. X** This character string should represent the arguments to the current process.
  47. X*/
  48. char    *getcmd ( p )
  49. X
  50. register struct process         *p ;
  51. X
  52. X{
  53. X# ifdef KVM
  54. X    char                    **ap ;
  55. X    char                    *cp ;
  56. X    char                    *sp ;
  57. X    int            spsize ;
  58. X    char                    **argv ;
  59. X    char                    **env ;
  60. X    extern kvm_t            *Flkvm ;
  61. X# else
  62. X    register int            *ip ;
  63. X    register char           *cp ;
  64. X    register char           *cp0 ;
  65. X    struct dblock           db ;
  66. X    struct pte              ptetbl[ UPAGES + CLSIZE ] ;
  67. X    extern int              Flmem, Flswap ;
  68. X# endif
  69. X    unsigned                nbad ;
  70. X    union
  71. X    {
  72. X        char            a_argc[ CLSIZE * NBPG ] ;
  73. X        int             a_argi[ CLSIZE * NBPG / sizeof( int ) ] ;
  74. X    } argbuf ;
  75. X    extern struct flags     Flg ;
  76. X    extern union userstate  User ;
  77. X    char                    *strcat(), *strncpy(), *strsave() ;
  78. X
  79. X    p->pr_csaved = 0 ;
  80. X    p->pr_upag = 0 ;
  81. X    if ( p->pr_p.p_stat == SZOMB )
  82. X        return ( "** Exit **" ) ;
  83. X# ifdef ULTRIX40
  84. X    if ( !(p->pr_p.p_sched & SLOAD) && Flg.flg_o )
  85. X# else
  86. X    if ( !(p->pr_p.p_flag & SLOAD) && Flg.flg_o )
  87. X# endif
  88. X        return ( "** Swapped out **" ) ;
  89. X    /* Find the process' upage */
  90. X# ifdef KVM
  91. X    if ( !getupage( p ) )           
  92. X# else
  93. X    if ( !getupage( p, ptetbl ) )           
  94. X# endif
  95. X        return ( "** No upage **" ) ;
  96. X    p->pr_upag = 1 ;
  97. X    /* Is this a system process ? */
  98. X# ifdef ULTRIX40
  99. X    if ( p->pr_p.p_type & SSYS )            
  100. X# else
  101. X    if ( p->pr_p.p_flag & SSYS )            
  102. X# endif
  103. X        switch ( p->pr_p.p_pid )
  104. X        {
  105. X            case 0 :
  106. X                return ( "Unix Swapper" ) ;
  107. X            case 2 :
  108. X                return ( "Unix Pager" ) ;
  109. X# ifdef SUNOS40
  110. X            case 3 :
  111. X            case 4 :
  112. X                return ( "Unix Idle" ) ;
  113. X# endif
  114. X            default :
  115. X                break ;
  116. X        }
  117. X# ifdef ULTRIX40
  118. X    /* Reading the command arguments doesn't work on the DEC 3100 so
  119. X       we resort to this kludge until one day it does. */
  120. X    if ( 1 )
  121. X# else ULTRIX40
  122. X    if ( Flg.flg_c )
  123. X# endif ULTRIX40
  124. X    {
  125. X        p->pr_csaved = 1 ;
  126. X        (void)strncpy( argbuf.a_argc, User.u_us.u_comm,
  127. X            sizeof( User.u_us.u_comm ) ) ;
  128. X        argbuf.a_argc[ sizeof ( User.u_us.u_comm ) ] = '\0' ;
  129. X        return ( strsave( argbuf.a_argc ) ) ;
  130. X    }
  131. X    
  132. X
  133. X# ifdef KVM
  134. X    spsize = sizeof( argbuf ) - 2 ;
  135. X    if ( kvm_getcmd( Flkvm, &p->pr_p, &User.u_us, &argv,
  136. X        Flg.flg_e ? &env : (char ***)NULL ) < 0 || argv == NULL )
  137. X            goto getsysargs ;
  138. X    p->pr_csaved = 1 ;
  139. X    sp = argbuf.a_argc ;
  140. X    nbad = 0 ;
  141. X    ap = argv ;
  142. X    while ( ap && *ap )
  143. X    {
  144. X        /* Copy one string from argv or env */
  145. X        cp = *ap++ ;
  146. X        while ( cp && *cp )
  147. X            if ( isprint( *cp ) )
  148. X                /* Be careful not to overrun allocated array.
  149. X                   Fix provided by Matti E Aarnio
  150. X                   <mea@nic.funet.fi> */
  151. X                if ( --spsize > 0 )
  152. X                    *sp++ = *cp++ ;
  153. X                else
  154. X                    ++cp ;
  155. X            else
  156. X            {
  157. X                /* Replace control characters with ?'s */
  158. X                if ( ++nbad > 5 )
  159. X                {
  160. X                    if ( --spsize > 0 )
  161. X                          *sp++ = ' ' ;
  162. X                      break ;
  163. X                  }
  164. X                if ( --spsize > 0 )
  165. X                    *sp++ = '?' ;
  166. X                cp++ ;
  167. X            }
  168. X        if (--spsize > 0)
  169. X            *sp++ = ' ' ;
  170. X        /* Check if at end of argv and user wants to see env */
  171. X        if ( ap && *ap == 0 && Flg.flg_e && argv != 0 )
  172. X        {
  173. X            free( (char *) argv ) ;
  174. X            argv = NULL ;
  175. X            ap = env ;
  176. X            if ( ap == NULL )
  177. X                break ;
  178. X        }
  179. X    }
  180. X     if ( Flg.flg_e )
  181. X                free( (char*)env ) ;
  182. X    while ( *--sp == ' ' )
  183. X        *sp = '\0' ;
  184. X    return ( strsave( argbuf.a_argc ) ) ;
  185. X# else
  186. X    /* Fix by Alexander Dupuy <dupuy@amsterdam.columbia.edu> */
  187. X    /* Check for lack of stack, jack! (Sun 3.0 biod's) */
  188. X    if (User.u_us.u_ssize == 0)
  189. X        goto getsysargs ;
  190. X    /* Look at the top of the upage to locate the command arguments.
  191. X       The page is loaded if the process itself is loaded and the pte
  192. X       contains is marked as valid. */
  193. X# ifdef ULTRIX40
  194. X    if ( (p->pr_p.p_sched & SLOAD)
  195. X# else
  196. X    if ( (p->pr_p.p_flag & SLOAD)
  197. X# endif
  198. X    && !ptetbl[0].pg_fod && ptetbl[0].pg_pfnum )
  199. X    {       /* If the page is loaded, read the arguments from
  200. X           physical memory. */
  201. X        memseek( Flmem, (long)ctob( ptetbl[0].pg_pfnum ) ) ;
  202. X        if ( read( Flmem, argbuf.a_argc, CLSIZE*NBPG ) != CLSIZE*NBPG )
  203. X            return ( "** Memory read error **" ) ;
  204. X    }
  205. X    else                            
  206. X    {       /* Otherwise the page is on the swap device */
  207. X# ifdef ULTRIX40
  208. X        vstodb( 0, ctod( CLSIZE ),&p->pr_p.p_smap, &db, 1 ) ;
  209. X# else
  210. X        vstodb( 0, ctod( CLSIZE ), &User.u_us.u_smap, &db, 1 ) ;
  211. X# endif
  212. X#  ifdef BSD42
  213. X        swseek( (long)dtob( db.db_base ) ) ;
  214. X#  else
  215. X        swseek( (long)ctob( db.db_base ) ) ;
  216. X#  endif
  217. X        if ( Flg.flg_o )
  218. X            return ( "** Swapped page **" ) ;
  219. X        if ( read( Flswap, (char *)argbuf.a_argc, CLSIZE*NBPG )
  220. X        != CLSIZE*NBPG )
  221. X            return ( "** Swap device read error **" ) ;
  222. X    }
  223. X    /* Look down until the end of command arguments is found. */
  224. X    ip = &argbuf.a_argi[ CLSIZE*NBPG / sizeof( int ) ] ;
  225. X    ip -= 2 ;
  226. X    while ( *--ip )
  227. X        if ( ip == &argbuf.a_argi[0] )
  228. X            goto getsysargs ;
  229. X    p->pr_csaved = 1 ;
  230. X    /* Process the command arguments, looking for nulls and unprintable
  231. X       characters. */
  232. X    cp0 = (char*)(ip + 1) ;
  233. X    if ( !*cp0 )                    
  234. X        cp0++ ;                 
  235. X    if ( *cp0 )
  236. X    {
  237. X        nbad = 0 ;                      
  238. X        for ( cp = cp0 ; cp < &argbuf.a_argc[ CLSIZE*NBPG ] ; cp++ )
  239. X        {
  240. X            *cp &= 0177 ;
  241. X            if ( !*cp )             
  242. X            {       /* Replace nulls with spaces */
  243. X                *cp = ' ' ;
  244. X                continue ;
  245. X            }
  246. X            if ( *cp < ' ' || *cp == 0177 )
  247. X            {       /* Replace control characters with ?'s */
  248. X                if ( ++nbad > 5 )
  249. X                {
  250. X                    *cp++ = ' ' ;
  251. X                    break ;
  252. X                }
  253. X                *cp = '?' ;
  254. X                continue ;
  255. X            }
  256. X            if ( !Flg.flg_e && *cp == '=' )
  257. X            {       /* Break on an `=' if we are not interested
  258. X                   in the environment strings. */
  259. X                *cp = '\0' ;
  260. X                while ( cp > cp0 && *--cp != ' ' )
  261. X                    *cp = '\0' ;
  262. X                break ;
  263. X            }
  264. X        }
  265. X        while ( *--cp == ' ' )
  266. X            *cp = '\0' ;
  267. X        return ( strsave( cp0 ) ) ;
  268. X    }
  269. X# endif KVM
  270. getsysargs :
  271. X    /* If the command arguments cannot be accessed from the user's memory
  272. X       space, get the command name from the system's idea of what the
  273. X       name should be. */
  274. X    p->pr_csaved = 1 ;
  275. X    argbuf.a_argc[0] = '(' ;
  276. X    (void)strncpy( &argbuf.a_argc[1], User.u_us.u_comm,
  277. X        sizeof( User.u_us.u_comm ) ) ;
  278. X    argbuf.a_argc[ sizeof ( User.u_us.u_comm ) + 1 ] = '\0' ;
  279. X    (void)strcat( &argbuf.a_argc[0], ")" ) ;
  280. X    return ( strsave( argbuf.a_argc ) ) ;
  281. X}
  282. X
  283. X# ifndef KVM
  284. X/*
  285. X** VSTODB - Given a base/size pair in virtual swap area,
  286. X** return a physical base/size pair which is the
  287. X** (largest) initial, physically contiguous block.
  288. X/* This code is stolen from the kernel file /sys/sys/vm_drum.c.
  289. X*/
  290. vstodb ( vsbase, vssize, dmp, dbp, rev )
  291. X
  292. register int                    vsbase ;
  293. register int                    vssize;
  294. struct dmap                     *dmp ;
  295. register struct dblock          *dbp ;
  296. int                             rev ;
  297. X
  298. X{
  299. X    register int            blk ;
  300. X    register swblk_t        *ip ;
  301. X# ifdef BSD42
  302. X    extern struct info      Info ;
  303. X# endif
  304. X# ifndef ULTRIX40
  305. X# ifdef BSD42
  306. X    blk = Info.i_dmmin ;
  307. X# else
  308. X    blk = DMMIN ;
  309. X# endif
  310. X    ip = dmp->dm_map ;
  311. X    while ( vsbase >= blk )
  312. X    {
  313. X        vsbase -= blk ;
  314. X# ifdef BSD42
  315. X        if ( blk < Info.i_dmmax )
  316. X# else
  317. X        if ( blk < DMMAX )
  318. X# endif
  319. X            blk *= 2 ;
  320. X        ip++ ;
  321. X    }
  322. X# else ULTRIX40
  323. X    blk = Info.i_swapfrag ;
  324. X    ip =  dmp->dm_map ;
  325. X    ip += (vsbase/blk) ;
  326. X        vsbase %= blk;
  327. X# endif ULTRIX40
  328. X
  329. X    dbp->db_size = vssize < blk - vsbase ? vssize : blk - vsbase ;
  330. X    dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
  331. X}
  332. X# endif
  333. END_OF_FILE
  334. if test 7639 -ne `wc -c <'getcmd.c'`; then
  335.     echo shar: \"'getcmd.c'\" unpacked with wrong size!
  336. fi
  337. # end of 'getcmd.c'
  338. fi
  339. if test -f 'printproc.c' -a "${1}" != "-c" ; then 
  340.   echo shar: Will not clobber existing file \"'printproc.c'\"
  341. else
  342. echo shar: Extracting \"'printproc.c'\" \(7216 characters\)
  343. sed "s/^X//" >'printproc.c' <<'END_OF_FILE'
  344. X# ifndef lint
  345. static char SccsId[] =  "@(#)printproc.c    1.4\t12/4/91" ;
  346. X# endif
  347. X
  348. X# include       "sps.h"
  349. X# include       "flags.h"
  350. X# ifndef SUNOS40
  351. X# include       <h/text.h>
  352. X# endif
  353. X
  354. X# ifdef SUNOS40
  355. X#  ifdef OLDSTATS
  356. X#   define OFFSET 8
  357. X#  else
  358. X#   define OFFSET 3
  359. X#  endif
  360. X# else
  361. X#   define OFFSET 0
  362. X# endif
  363. X
  364. X/* PRINTPROC - Pretty print a process according to the switches. */
  365. printproc ( p, md )
  366. X
  367. register struct process         *p ;            
  368. int                             md ;            
  369. X
  370. X{
  371. X    register char           *chp ;
  372. X# ifndef SUNOS40
  373. X    register struct text    *tp ;
  374. X# endif
  375. X    register struct hashtab *hp ;
  376. X    char                    chbuf[10] ;
  377. X    time_t                  time ;
  378. X    time_t                  chtime ;
  379. X# ifdef BSD42
  380. X    time_t                  utime ;
  381. X    time_t                  uchtime ;
  382. X# endif
  383. X    extern short            Lastuid, Lastpgrp ;
  384. X    extern struct flags     Flg ;
  385. X    char                    *waitingfor() ;
  386. X    struct hashtab          *hashuid() ;
  387. X    double                  percentmem() ;
  388. X
  389. X    /* List tty name and foreground/background/detached information */
  390. X    printf( "%2.2s%c", p->pr_tty->l_name,
  391. X# ifdef SDETACH
  392. X        !p->pr_p.p_pgrp ? ' ' : p->pr_p.p_flag & SDETACH ? '_' :
  393. X        p->pr_p.p_pgrp == p->pr_tty->l_pgrp ? '.' : ' ' ) ;
  394. X# else
  395. X        !p->pr_p.p_pgrp || p->pr_p.p_pgrp != p->pr_tty->l_pgrp ?
  396. X# ifdef SPGLDR
  397. X        p->pr_p.p_flag & SPGLDR ? '-' :
  398. X# endif
  399. X           ' ' :
  400. X# ifdef SPGLDR
  401. X        p->pr_p.p_flag & SPGLDR ? '+' :
  402. X# endif
  403. X           '.' ) ;
  404. X# endif
  405. X    hp = hashuid( (int)p->pr_p.p_uid ) ;
  406. X    if ( !md  )                             
  407. X    {       /* If a top-level process, list the user name */
  408. X        if ( hp )
  409. X            printf( "%-8.8s ", hp->h_uname ) ;
  410. X        else
  411. X            printf( "user%-4.4d ", p->pr_p.p_uid ) ;
  412. X    }
  413. X    else                                    
  414. X    {       /* Usually list an asterisk for a child process */
  415. X        md = md > 8 ? 8 : md ;
  416. X        printf( "%*s%c", md, "",
  417. X            p->pr_p.p_pgrp == Lastpgrp ? '|' : '*' ) ;      
  418. X        /* But beware of setuid processes */
  419. X        md = 8 - md ;
  420. X        if ( p->pr_p.p_uid == Lastuid )
  421. X            printf( "%-*.*s", md, md, "" ) ;
  422. X        else if ( hp )
  423. X            printf( "%-*.*s", md, md, hp->h_uname ) ;
  424. X        else
  425. X        {
  426. X            md -= 4 ;
  427. X            printf( "user%-*.*d", md, md, p->pr_p.p_uid ) ;
  428. X        }
  429. X    }
  430. X    Lastuid = p->pr_p.p_uid ;
  431. X    Lastpgrp = p->pr_p.p_pgrp ;
  432. X    if ( Flg.flg_d )                        
  433. X    {       /* List disc I/O and paging information */
  434. X        if ( !p->pr_upag || p->pr_p.p_stat == SZOMB )
  435. X        {
  436. X            prcmd( p, 49, -63 ) ;
  437. X            return ;
  438. X        }
  439. X        printf( "%2d %8d+%8d %4d %8d %8D ",
  440. X            p->pr_files,
  441. X# ifdef BSD42
  442. X            p->pr_rself.ru_majflt,
  443. X            p->pr_rself.ru_minflt,
  444. X            p->pr_rself.ru_nswap,
  445. X            p->pr_rself.ru_inblock + p->pr_rself.ru_oublock,
  446. X            KBYTES( p->pr_rself.ru_idrss + p->pr_rself.ru_isrss
  447. X                + p->pr_rself.ru_ixrss ) ) ;
  448. X# else
  449. X            p->pr_vself.vm_majflt,
  450. X            p->pr_vself.vm_minflt,
  451. X            p->pr_vself.vm_nswap,
  452. X            p->pr_vself.vm_inblk + p->pr_vself.vm_oublk,
  453. X            KBYTES( (p->pr_vself.vm_idsrss
  454. X                + p->pr_vself.vm_ixrss) / Info.i_hz ) ) ;
  455. X# endif
  456. X        prcmd( p, 5, -63 ) ;
  457. X        return ;
  458. X    }
  459. X    if ( !Flg.flg_v )                       
  460. X    {       /* Not verbose so just list command arguments */
  461. X        prcmd( p, 5, -19 ) ;
  462. X        return ;
  463. X    }
  464. X    /* Arrive here if being verbose ; list cpu information */
  465. X    switch ( p->pr_p.p_stat )               
  466. X    {                                       
  467. X        case SSLEEP :
  468. X        case SWAIT :
  469. X        case SIDL :
  470. X            /* Determine why a process should be in a wait state */
  471. X            chp = waitingfor( p ) ;
  472. X            break ;
  473. X        case SRUN :
  474. X            chp = "run" ;
  475. X            break ;
  476. X        case SZOMB :
  477. X            chp = "exit" ;
  478. X            break ;
  479. X        case SSTOP :
  480. X            chp = "stop" ;
  481. X            break ;
  482. X    }
  483. X    /* If the process is loaded, list the status information in capitals */
  484. X# ifdef ULTRIX40
  485. X    printf( "%-6.6s ", p->pr_p.p_sched & SLOAD ?
  486. X# else
  487. X    printf( "%-6.6s ", p->pr_p.p_flag & SLOAD ?
  488. X# endif
  489. X        (capitals( chp, chbuf ), chbuf) : chp ) ;
  490. X    /* List process flags */
  491. X# ifdef ULTRIX40
  492. X    printf( "%c%c%c", p->pr_p.p_type & SSYS ? 'U' :
  493. X        p->pr_p.p_trace & STRC ? 'T' : ' ',
  494. X        p->pr_p.p_vm & SVFORK ? 'V' :
  495. X        p->pr_p.p_vm & SPHYSIO ? 'I' : ' ',
  496. X        p->pr_p.p_vm & SUANOM ? 'A' :
  497. X        p->pr_p.p_vm & SSEQL ? 'S' : ' ' ) ;
  498. X# else
  499. X    printf( "%c%c%c", p->pr_p.p_flag & SSYS ? 'U' :
  500. X        p->pr_p.p_flag & STRC ? 'T' : ' ',
  501. X        p->pr_p.p_flag & SVFORK ? 'V' :
  502. X        p->pr_p.p_flag & SPHYSIO ? 'I' : ' ',
  503. X        p->pr_p.p_flag & SUANOM ? 'A' :
  504. X        p->pr_p.p_flag & SSEQL ? 'S' : ' ' ) ;
  505. X# endif
  506. X    /* List process niceness */
  507. X    if ( p->pr_p.p_nice != NZERO )          
  508. X        printf( "%3d ", p->pr_p.p_nice - NZERO ) ;
  509. X    else
  510. X        printf( "    " ) ;
  511. X    if ( p->pr_p.p_stat == SZOMB )
  512. X    {
  513. X        prcmd( p, 41 - OFFSET, OFFSET - 69 ) ;
  514. X        return ;
  515. X    }                                       
  516. X# ifdef SUNOS40
  517. X#  ifdef OLDSTATS
  518. X    /* List process virtual and real sizes */
  519. X    printf( "%4d", KBYTES( p->pr_p.p_dsize + p->pr_p.p_ssize ) ) ;
  520. X#  else
  521. X    /* List process private and shared virtual and real sizes */
  522. X        printf("%4d", KBYTES( p->pr_private ) ) ;
  523. X        printf("+%4d", KBYTES( p->pr_shared ) ) ;
  524. X#  endif
  525. X    printf( " %4d", KBYTES( p->pr_p.p_rssize ) ) ;
  526. X# else
  527. X    /* List process and text virtual sizes */
  528. X    printf( "%4d", KBYTES( p->pr_p.p_dsize + p->pr_p.p_ssize ) ) ;
  529. X    if ( tp = p->pr_p.p_textp )
  530. X        printf( "+%3d ", KBYTES( tp->x_size ) ) ;
  531. X    else
  532. X        printf( "     " ) ;
  533. X    /* List process and text real sizes */
  534. X    printf( "%4d", KBYTES( p->pr_p.p_rssize ) ) ;
  535. X    if ( tp )
  536. X        printf( "+%3d", KBYTES( tp->x_rssize ) ) ;
  537. X    else
  538. X        printf( "    " ) ;
  539. X# endif
  540. X    printf( " %2.0f ", percentmem( p ) ) ;
  541. X    /* List information obtained from the upage. This includes the process
  542. X       times and command arguments. */
  543. X    if ( !p->pr_upag )
  544. X    {
  545. X        prcmd( p, 20, OFFSET - 69 ) ;
  546. X        return ;
  547. X    }                                       
  548. X    /* List process time information */
  549. X# ifdef BSD42
  550. X    time   = Flg.flg_q ? p->pr_rself.ru_utime.tv_sec :
  551. X         p->pr_rself.ru_utime.tv_sec + p->pr_rself.ru_stime.tv_sec ;
  552. X    utime  = Flg.flg_q ? p->pr_rself.ru_utime.tv_usec :
  553. X         p->pr_rself.ru_utime.tv_usec + p->pr_rself.ru_stime.tv_usec ;
  554. X    chtime = Flg.flg_q ? p->pr_rchild.ru_utime.tv_sec :
  555. X         p->pr_rchild.ru_utime.tv_sec + p->pr_rchild.ru_stime.tv_sec ;
  556. X    uchtime = Flg.flg_q ? p->pr_rchild.ru_utime.tv_usec :
  557. X         p->pr_rchild.ru_utime.tv_usec + p->pr_rchild.ru_stime.tv_usec ;
  558. X    prcpu( time, utime ) ;
  559. X    if ( chtime != 0L )
  560. X    {
  561. X        printf( "+" ) ;
  562. X        prcpu( chtime, uchtime ) ;
  563. X    }
  564. X# else
  565. X    time   = Flg.flg_q ? p->pr_vself.vm_utime :
  566. X         p->pr_vself.vm_utime + p->pr_vself.vm_stime ;
  567. X    chtime = Flg.flg_q ? p->pr_vchild.vm_utime :
  568. X         p->pr_vchild.vm_utime + p->pr_vchild.vm_stime ;
  569. X    prcpu( time ) ;
  570. X    if ( chtime != 0L )
  571. X    {
  572. X        printf( "+" ) ;
  573. X        prcpu( chtime ) ;
  574. X    }
  575. X# endif
  576. X    else
  577. X        printf( "      " ) ;
  578. X# ifdef BSD42
  579. X    if ( time || utime )
  580. X# else
  581. X    if ( time )
  582. X# endif
  583. X# ifdef SUN
  584. X        printf( " %2.0f ", (double)p->pr_p.p_pctcpu * 100.0/FSCALE ) ;
  585. X# else
  586. X#  ifdef ULTRIX40
  587. X        printf( " %2.0f ", p->pr_p.p_pctcpu ) ;
  588. X#  else
  589. X        printf( " %2.0f ", p->pr_p.p_pctcpu * 100.0 ) ;
  590. X#  endif ULTRIX40
  591. X# endif SUN
  592. X    else
  593. X        printf( "    " ) ;
  594. X    /* Finally, list the process command arguments. */
  595. X    prcmd( p, 5, OFFSET - 69 ) ;                    
  596. X}
  597. X
  598. X/* CAPITALS - Converts letters in `chp' to upper-case in buffer `buf'. */
  599. capitals ( chp, buf )
  600. X
  601. register char                   *chp ;
  602. register char                   *buf ;
  603. X
  604. X{
  605. X    while ( *buf = *chp++ )
  606. X    {
  607. X        if ( 'a' <= *buf && *buf <= 'z' )
  608. X            *buf -= 'a' - 'A' ;
  609. X        buf++ ;
  610. X    }
  611. X}
  612. END_OF_FILE
  613. if test 7216 -ne `wc -c <'printproc.c'`; then
  614.     echo shar: \"'printproc.c'\" unpacked with wrong size!
  615. fi
  616. # end of 'printproc.c'
  617. fi
  618. if test -f 'sps.1' -a "${1}" != "-c" ; then 
  619.   echo shar: Will not clobber existing file \"'sps.1'\"
  620. else
  621. echo shar: Extracting \"'sps.1'\" \(15346 characters\)
  622. sed "s/^X//" >'sps.1' <<'END_OF_FILE'
  623. X.if n .pl 66
  624. X.TH SPS 1
  625. X.SH NAME
  626. sps \ \ \-\ \ \ show process status
  627. X.SH SYNOPSIS
  628. X\fBsps\ \fP \ [ \fB\-cdefgijkoqrslvwyABDFNPSTUWZ\fP ]\ \ [
  629. X\fIprocess\ .\ .\ .\ | tty\ .\ .\ .\ | user\ .\ .\ .\fP ]
  630. X.SH DESCRIPTION
  631. X\fISps\fP reports information concerning system processes.
  632. It shows the current state of any process by
  633. listing information such as ownership, CPU time usage, memory usage
  634. and disc activity.
  635. X.PP
  636. X\fISps\fP should be used in preference to \fIps\fP(1)
  637. because it is faster and the output is more comprehensive and more
  638. comprehensible.
  639. X.SH OPTIONS
  640. By default, \fIsps\fP prints basic information about one's own processes.
  641. The various options described below select other processes or make
  642. X\fIsps\fP more verbose.
  643. X.PP
  644. Upper case options select processes to be described.
  645. Lower case options specify the format of the output.
  646. XFor instance, the options \fBBv\fP specify that \fIsps\fP
  647. should list ``busy'' processes in a verbose format.
  648. Unless there is any conflict, lower case options may be used
  649. instead of upper case options, and vice versa.
  650. X.PP
  651. The following options specify the format of the listed output \-
  652. X.TP 8
  653. X\fB\-c\fP
  654. Use the system's idea of the command, rather than getting the arguments
  655. from user space.  While somewhat less informative, this is faster and
  656. more reliable.
  657. X.TP
  658. X\fB\-d\fP
  659. List output reflecting how each process affects the
  660. disc and paging activity of the system.
  661. X.TP
  662. X\fB\-e\fP
  663. List the environment passed to each process.
  664. X.TP
  665. X\fB\-f\fP
  666. Include the process\-id of the parent of each process.
  667. X.TP
  668. X\fB\-g\fP
  669. Include the process group of each process.
  670. X.TP
  671. X\fB\-o\fP
  672. Avoid looking at the swap device (\fB/dev/drum\fP). This tends to make \fIsps\fP
  673. run faster, although no information concerning swapped processes
  674. can be obtained.
  675. X.TP
  676. X\fB\-q\fP
  677. By default, \fIsps\fP
  678. lists the sum of the user plus system times under the
  679. X\fITime\fP and \fIChild\fP fields.  This option forces \fIsps\fP
  680. to list only the user times.
  681. X.TP
  682. X\fB\-r\fP
  683. Repeat the output indefinitely.
  684. If the next argument is numeric, \fIsps\fP repeats the output with that
  685. many seconds delay between each repetition.
  686. Otherwise the output is repeated with no delay.
  687. X.TP
  688. X\fB\-l\fP
  689. X.br
  690. X.ns
  691. X.TP
  692. X\fB\-v\fP
  693. List additional information in a verbose format. See below.
  694. X.TP
  695. X\fB\-w\fP
  696. List output in a wide format.  This option forces \fIsps\fP
  697. to print all the command arguments, even if doing so extends the output
  698. beyond one line.
  699. X.TP
  700. X\fB\-y\fP
  701. Show the status of each terminal line.
  702. X.PP
  703. The following options specify which processes are to be described \-
  704. X.TP 8
  705. X\fB\-A\fP
  706. List all processes.
  707. X.TP
  708. X\fB\-B\fP
  709. List busy processes.  A process is considered to be busy
  710. if it is immediately runnable or awaiting a fast event such as disc I/O.
  711. X.TP
  712. X\fB\-D\fP
  713. List detached processes.
  714. X.TP
  715. X\fB\-F\fP
  716. List foreground processes.
  717. X.TP
  718. X\fB\-N\fP
  719. Show no processes at all. Only the summary line is printed.
  720. X.TP
  721. X\fB\-P\fP
  722. List only processes whose identifiers are specified in the following arguments.
  723. X.TP
  724. X\fB\-S\fP
  725. List stopped processes.
  726. X.TP
  727. X\fB\-T\fP
  728. List only processes attached to the following specified terminals.
  729. X.TP
  730. X\fB\-U\fP
  731. List only processes belonging to the following specified users.
  732. X.TP
  733. X\fB\-W\fP
  734. List waiting processes.
  735. X.TP
  736. X\fB\-Z\fP
  737. List zomby (exiting) processes.
  738. X.PP
  739. The following are miscellaneous options \-
  740. X.TP 8
  741. X\fB\-i\fP
  742. Initialise \fIsps\fP.
  743. This is necessary if new users are added to the password file,
  744. or if a new version of UNIX is installed.
  745. Sps builds a new information file summarising pertinent information
  746. read from the password file (\fB/etc/passwd\fP), the executable kernel image
  747. X(\fB/vmunix\fP) and the directory of tty devices (\fB/dev\fP).
  748. See also the \fB\-j\fP and \fB\-s\fP options.
  749. X.TP
  750. X\fB\-j\fP
  751. Specify an information file other than the default (\fB/etc/spsinfo\fP).
  752. The next argument is taken to be the name of a suitable information file.
  753. If the \fB\-i\fP flag is also specified, \fIsps\fP builds a
  754. new information file with the given name.
  755. Otherwise, \fBsps\fP reads previously created summarising information
  756. from that file.
  757. X.TP
  758. X\fB\-k\fP
  759. Use a specific disc file rather than the default physical
  760. memory (\fB/dev/mem\fP)
  761. and kernel virtual memory (\fB/dev/kmem\fP) files. The next argument is taken
  762. to be the name of a suitable memory dump file.
  763. This flag automatically sets the \fB\-o\fP flag.
  764. X.TP
  765. X\fB\-s\fP
  766. This option is used in conjunction with the \fB\-i\fP option.
  767. The next argument is taken to be the name of a suitable kernel executable
  768. file, rather than the default (\fB/vmunix\fP).
  769. X\fISps\fP looks at the symbol table of this file to determine
  770. the virtual addresses of various kernel structures.
  771. X.SH OUTPUT
  772. X\fISps\fP produces output in the following fields \-
  773. X.TP 8
  774. X\fITy\fP
  775. The terminal identifier to which the process is attached.
  776. X.IP
  777. If this is followed by an underscore, the process is detached.
  778. If it is followed by a period, the process is running in the foreground.
  779. Otherwise the process is running in the background but is still
  780. attached to a terminal.
  781. X.TP
  782. X\fIUser\fP
  783. The symbolic name of the process' effective user-id (see \fIexec\fP(2)
  784. and \fIsetuid\fP(2)).
  785. This name is defined by the system password file (\fB/etc/passwd\fP)
  786. when \fIsps\fP was last initialised.
  787. Otherwise, an asterisk (\fB*\fP) or vertical bar (\fB|\fP) appearing in this
  788. column denotes that the process is an immediate relative of the
  789. preceding process.
  790. A bar is listed, rather than an asterisk, if both processes belong
  791. to the same process group.
  792. A user name is listed only if the effective user-id
  793. differs from that of the preceding process or if it is a top-level
  794. process (immediate offspring of process 1).
  795. X.TP
  796. X\fIProc#\fP
  797. The unique process identifier.
  798. X.TP
  799. X\fIPpid#\fP
  800. The process-id of the process' parent.
  801. X.TP
  802. X\fIPgrp#\fP
  803. The process group to which the process belongs.
  804. X.TP
  805. X\fICommand\fP
  806. The command arguments obtained from the process' own address space.
  807. X(If the command name appears in parentheses, \fIsps\fP
  808. was unable to locate the arguments in user space and so reports
  809. the system's idea of the command name.)
  810. X.PP
  811. The following additional fields are listed when \fIsps\fP
  812. is invoked with one of the \fB\-l\fP or \fB\-v\fP options \-
  813. X.TP 8
  814. X\fIStatus\fP
  815. The process' current state.
  816. If this field is listed in upper-case letters, the process is currently
  817. loaded in real memory space ; otherwise it has been swapped out.
  818. The status field may contain one of the following descriptions \-
  819. X.RS 8
  820. X.TP 16
  821. X\fIrun\fP
  822. The process can be run immediately.
  823. X.TP
  824. X\fIstop\fP
  825. The process is stopped. See \fIsigvec\fP(2).
  826. X.TP
  827. X\fIexit\fP
  828. The process is a zomby.
  829. X.RE
  830. X.IP
  831. Any other entry in the status field indicates the process is
  832. waiting for some external event to occur.
  833. This is usually for one of the reasons listed below.
  834. X(If \fIsps\fP does not know why a process is waiting, it lists
  835. the hexadecimal address of the process' wait channel,
  836. with the initial 80000000 trimmed off.)
  837. A process may be waiting for one of the following reasons \-
  838. X.RS 8
  839. X.TP 16
  840. X\fIchild\fP
  841. The process is waiting for a child to terminate. See \fIwait\fP(2).
  842. X.TP
  843. X\fIpause\fP
  844. Waiting for a signal to be received. See \fIsigpause\fP(2).
  845. X.TP
  846. X\fIswap\fP
  847. Waiting for a page to be swapped in.
  848. X.TP
  849. X\fIrswbuf\fP
  850. Waiting for a read from the swap device \fB/dev/drum.\fP
  851. X.TP
  852. X\fIdiscio\fP
  853. Waiting for a disc read or write operation.
  854. X(Actually, this means that the process is waiting for an operation
  855. through the kernel's I/O buffering mechanism to complete, but \fIdiscio\fP
  856. is what is generally meant here).
  857. X.TP
  858. X\fIrpipe\fP
  859. X.br
  860. X.ns
  861. X.TP
  862. X\fIwpipe\fP
  863. Waiting for a read from an empty pipe.  Alternatively, the process
  864. is waiting to write to a full pipe. See \fIpipe\fP(2).
  865. X.TP
  866. X\fIrsockt\fP
  867. X.br
  868. X.ns
  869. X.TP
  870. X\fIwsockt\fP
  871. Waiting for a read from an empty socket.
  872. Alternatively, the process is waiting to write to a full socket (4.[2\-]bsd only).
  873. X.TP
  874. X\fIaccept\fP
  875. Waiting to accept a stream-based socket connection (4.[2\-]bsd only).
  876. See \fIaccept\fP(2).
  877. X.TP
  878. X\fIconnct\fP
  879. Waiting to establish a connection through a stream-based socket to a
  880. remote process (4.[2\-]bsd only). See \fIconnect\fP(2).
  881. X.TP
  882. X\fIsocket\fP
  883. Waiting for some other time-out event on a socket (4.[2\-]bsd only).
  884. X.TP
  885. X\fIselect\fP
  886. Blocked by a \fIselect\fP(2) system call (4.[2\-]bsd only).
  887. X.TP
  888. X\fIrmux\fP
  889. Waiting for a read from a multiplexor file (4.1bsd only).
  890. X.TP
  891. X\fIinode\fP
  892. Waiting for an inode to be allocated or unlocked.
  893. X.TP
  894. X\fIexlock\fP
  895. X.br
  896. X.ns
  897. X.TP
  898. X\fIshlock\fP
  899. Waiting for a file to become unlocked. See \fIflock\fP(2).
  900. X.TP
  901. X\fIrtty??\fP
  902. X.br
  903. X.ns
  904. X.TP
  905. X\fIwtty??\fP
  906. X.br
  907. X.ns
  908. X.TP
  909. X\fIotty??\fP
  910. Waiting for a read or write to the specified terminal, or for the terminal
  911. to be switched on. See \fItty\fP(4).
  912. Alternatively, waiting for a read or write to the
  913. specified slave pty device. See \fIpty\fP(4).
  914. X.TP
  915. X\fIitty??\fP
  916. X.br
  917. X.ns
  918. Under SunOS, waiting perform I/O to an iconified window.
  919. X.TP
  920. X\fIrpty??\fP
  921. X.br
  922. X.ns
  923. X.TP
  924. X\fIwpty??\fP
  925. Waiting for a read or write to the specified master pty device.
  926. See \fIpty\fP(4).
  927. X.TP
  928. X\fIptrace\fP
  929. This is a parent process tracing its child.
  930. X.TP
  931. X\fIvfork\fP
  932. This is a vforking parent process waiting for its child to relinquish
  933. memory resources. See \fIvfork\fP(2).
  934. X.TP
  935. X\fIfloppy\fP
  936. X.br
  937. X.ns
  938. X.TP
  939. X\fIprintr\fP
  940. X.br
  941. X.ns
  942. X.TP
  943. X\fIr??buf\fP
  944. Waiting for the specified device to complete an I/O operation.
  945. X.RE
  946. X.TP 8
  947. X\fIFl\fP
  948. XFlags associated with the current state of the process.
  949. These flags may be any of the following \-
  950. X.RS 8
  951. X.TP 16
  952. X\fIU\fP
  953. The process is a UNIX system process.
  954. X.TP
  955. X\fIT\fP
  956. The process is being traced or debugged.
  957. X.TP
  958. X\fIV\fP
  959. The process is a child currently being vforked. See \fIvfork\fP(2).
  960. X.TP
  961. X\fII\fP
  962. The process is undergoing physical I/O.
  963. X.TP
  964. X\fIA\fP
  965. The system has detected, or the user has warned of
  966. anomalous paging behaviour. See \fIvadvise\fP(2).
  967. X.RE
  968. X.TP 8
  969. X\fINice\fP
  970. The ``niceness'' of the process. See \fInice\fP(2).
  971. X.TP
  972. X\fIVirtual\fP
  973. The virtual memory size of the process in kilobytes.
  974. The first figure indicates the sum of the data and stack segments,
  975. the second figure that of the text segment.
  976. X.TP
  977. X\fIResident\fP
  978. The resident memory size of the process in kilobytes, representing
  979. the real memory devoted to the process.
  980. X.TP
  981. X\fI%M\fP
  982. The percentage of available real memory allocated to this process.
  983. X.TP
  984. X\fITime\fP
  985. The total CPU time accumulated by this process.
  986. X(This is the sum of the system plus user times, unless the \fB\-q\fP
  987. flag is specified in which case only the user time is listed.)
  988. X.TP
  989. X\fIChild\fP
  990. The total CPU time accumulated by the process' children.
  991. X(This is the sum of the system plus user times, unless the \fB\-q\fP
  992. flag is specified.)
  993. X.TP
  994. X\fI%C\fP
  995. The percentage of available CPU time devoted to the process.
  996. This figure is a decaying average, computed over the past second.
  997. X.PP
  998. The following fields are listed when \fIsps\fP is invoked with the
  999. X\fB\-d\fP option \-
  1000. X.TP 8
  1001. X\fIFiles\fP
  1002. The number of open files for this process.
  1003. X.TP
  1004. X\fIPageFaults\fP
  1005. The number of major and minor page faults incurred by the process.
  1006. X.TP
  1007. X\fISwap\fP
  1008. The number of swaps incurred by the process.
  1009. X.TP
  1010. X\fIBlockI/O\fP
  1011. The number of block read or write operations performed
  1012. on behalf of the process.
  1013. X.TP
  1014. X\fIKbytesecs\fP
  1015. The integral of real memory usage over time.
  1016. Thus, if a process uses 60 kilobytes of real memory for 3 seconds,
  1017. this figure is incremented by 180.
  1018. X.PP
  1019. The following fields are listed when \fIsps\fP is invoked with the
  1020. X\fB\-y\fP option \-
  1021. X.TP 8
  1022. X\fIDev\fP
  1023. The major and minor device numbers of the terminal.
  1024. X.TP
  1025. X\fIAddr\fP
  1026. The virtual address of the associated \fBstruct tty\fP in \fB/dev/kmem\fP.
  1027. X.TP
  1028. X\fIRawq\fP
  1029. X.br
  1030. X.ns
  1031. X.TP
  1032. X\fICanq\fP
  1033. X.br
  1034. X.ns
  1035. X.TP
  1036. X\fIOutq\fP
  1037. The number of characters in the terminal I/O queues.
  1038. These refer to the raw input queue, the canonical input queue
  1039. and the output queue.
  1040. X.TP
  1041. X\fIPgrp\fP
  1042. The process group associated with the terminal.
  1043. X.PP
  1044. After listing the requested output, \fIsps\fP prints a summary line.
  1045. This indicates the number and total virtual memory size of all processes,
  1046. the number and total virtual size of busy processes,
  1047. the number and real memory size of loaded processes
  1048. and the number and real size of swapped processes.
  1049. X.SH DIAGNOSTICS
  1050. X\fISps\fP reports a self-explanatory message if it is given an
  1051. invalid argument list.
  1052. The program also complains if it cannot find necessary system information.
  1053. X.PP
  1054. At initialisation, \fIsps\fP complains if it cannot find the addresses of
  1055. requisite system structures in the kernel symbol file.
  1056. This is usually the case because the system is rarely configured to support
  1057. all known devices.
  1058. X\fISps\fP also complains if more than one user shares the same user-id
  1059. in the password file (\fB/etc/passwd\fP).
  1060. X.SH EXAMPLES
  1061. X\fBsps vb\fP
  1062. X.PP
  1063. X\fISps\fP describes all busy processes in a verbose manner.
  1064. X.PP
  1065. X\fBsps dtg 9 h1 co\fP
  1066. X.PP
  1067. X\fISps\fP lists processes associated with terminals \fB9\fP,
  1068. X\fBh1\fP and the \fBconsole\fP.
  1069. The output reflects the disc activity caused by these processes.
  1070. The process group of each process is also included in the output.
  1071. X.PP
  1072. X\fBsps weu robert fred \-r 2\fP
  1073. X.PP
  1074. X\fISps\fP reports processes belonging to the specified users.
  1075. It lists the environment as well as all the command arguments in a wide format.
  1076. The output is produced indefinitely, with a delay of two seconds between
  1077. each listing.
  1078. X.PP
  1079. X\fBsps is /vmunix.new\fP
  1080. X.PP
  1081. X\fISps\fP is initialised. It reads its symbol information from the
  1082. specified file.
  1083. X.SH FILES
  1084. X.ta 2.5i
  1085. X.nf
  1086. X\fB/dev/console\fP    Console
  1087. X\fB/dev/tty??\fP    Terminal and pty devices
  1088. X\fB/dev/kmem\fP    Kernel virtual memory
  1089. X\fB/dev/mem\fP    Physical memory
  1090. X\fB/dev/drum\fP    Paging and swap device
  1091. X\fB/etc/passwd\fP    Password file
  1092. X\fB/etc/spsinfo\fP    Information file
  1093. X\fB/vmunix\fP    Symbol file of \fB/dev/kmem\fP addresses
  1094. X\fB/etc/termcap\fP    To determine the output terminal width
  1095. X.fi
  1096. X.ta
  1097. X.SH SEE ALSO
  1098. X\fIiostat\fP(1), \fIkill\fP(1), \fIps\fP(1),
  1099. X\fIvmstat\fP(1), \fIexec\fP(2),
  1100. X\fIflock\fP(2), \fInice\fP(2), \fIpause\fP(2), \fIselect\fP(2), \fIsetuid\fP(2),
  1101. X\fIsigvec\fP(2), \fIvadvise\fP(2), \fIvfork\fP(2), \fIwait\fP(2),
  1102. X\fIpty\fP(4),\fItty\fP(4), \fIpstat\fP(8).
  1103. X.SH AUTHORS
  1104. Several. In particular, J. E. Kulp and J. Robert Ward,
  1105. X\fB<robert@olsen.uucp>\fP.
  1106. X.LP
  1107. NFS changes incorporated by Alexander Dupuy,
  1108. X\fB<dupuy@amsterdam.columbia.edu>\fP
  1109. X.LP
  1110. SunOS 4.0 implementation by Alexander Dupuy and
  1111. Charlie Kim \fB<cck@cunixc.cc.columbia.edu>\fP.
  1112. X.LP
  1113. Ultrix 2.\fIx\fP additions incorporated by Rob Lehman at CUUCA.
  1114. X.LP
  1115. SunOS 4.1 additions incorporated by Sakari Jalovaara, \fB<sja@sirius.hut.fi>\fP.
  1116. X.LP
  1117. Ultrix 4.0 additions incorporated by Stefano Diomedi,
  1118. X\fB<sdiomedi@tecsiel.it>\fP.
  1119. X.LP
  1120. Currently maintained by J. Robert Ward, \fB<robert@olsen.uu.ch>\fP
  1121. X.SH BUGS
  1122. Because the system is continually changing, the information reported by
  1123. X\fIsps\fP is only an approximation to reality.
  1124. If invoked by root, \fIsps\fP renices itself to \-20 in an attempt to run as
  1125. fast as possible.
  1126. X.PP
  1127. X\fISps\fP recognises the sizes and addresses of internal kernel
  1128. tables whenever it is invoked. However, it must be recompiled
  1129. if major modifications are made to the kernel.
  1130. X.PP
  1131. X\fISps\fP does not list all the detailed information shown by \fIps\fP(1).
  1132. Nor are all the options supported by \fIps\fP(1) available from \fIsps\fP.
  1133. X.PP
  1134. X\fISps\fP does not understand all the possible
  1135. reasons why a process may be sleeping.
  1136. X.PP
  1137. The code of \fIsps\fP is inherently machine-dependent and non-portable.
  1138. X.PP
  1139. The number of options to \fIsps\fP is ridiculous.
  1140. END_OF_FILE
  1141. if test 15346 -ne `wc -c <'sps.1'`; then
  1142.     echo shar: \"'sps.1'\" unpacked with wrong size!
  1143. fi
  1144. # end of 'sps.1'
  1145. fi
  1146. if test -f 'waitingfor.c' -a "${1}" != "-c" ; then 
  1147.   echo shar: Will not clobber existing file \"'waitingfor.c'\"
  1148. else
  1149. echo shar: Extracting \"'waitingfor.c'\" \(10012 characters\)
  1150. sed "s/^X//" >'waitingfor.c' <<'END_OF_FILE'
  1151. X# ifndef lint
  1152. static char SccsId[] =  "@(#)waitingfor.c    1.7\t12/4/91" ;
  1153. X# endif
  1154. X
  1155. X# include        "sps.h"
  1156. X# ifndef SUNOS40
  1157. X# include        <h/text.h>
  1158. X# endif SUNOS40
  1159. X
  1160. X# ifdef NFS
  1161. X#  ifdef ULTRIX40
  1162. X#   include        <h/gnode.h>
  1163. X#   include        <h/inode.h>
  1164. X#  else ULTRIX40
  1165. X#   include        <h/vnode.h>
  1166. X#   include        <ufs/inode.h>
  1167. X# endif ULTRIX40
  1168. X# else
  1169. X#  include        <h/inode.h>
  1170. X# endif NFS
  1171. X
  1172. X# include        <h/ioctl.h>
  1173. X# ifdef SUNOS40
  1174. X#  include        <h/stream.h>
  1175. X#  include        <h/tty.h>
  1176. X#  include        <h/ptyvar.h>
  1177. X# else SUNOS40
  1178. X#  include        <h/tty.h>
  1179. X# endif SUNOS40
  1180. X
  1181. X# include        <h/buf.h>
  1182. X# ifdef BSD42
  1183. X#  ifdef NFS
  1184. X#   ifndef NOQUOTA
  1185. X#    ifdef ULTRIX40
  1186. X#     include        <h/quota.h>
  1187. X#    else
  1188. X#     include        <ufs/quota.h>
  1189. X#    endif ULTRIX40
  1190. X#   endif NOQUOTA
  1191. X#  else NFS
  1192. X#   include        <h/quota.h>
  1193. X#  endif NFS
  1194. X# include        <h/mbuf.h>
  1195. X# include        <h/socket.h>
  1196. X# include        <h/socketvar.h>
  1197. X# endif BSD42
  1198. X
  1199. X/* 1 if `w' is in the address range defined by `a1' and `a2' ... */
  1200. X# define        INRANGE( w, a1, a2 ) \
  1201. X            ( (caddr_t)(a1) <= (w) && (w) < (caddr_t)(a2) )
  1202. X
  1203. X/* NFS changes incorporated by Alexander Dupuy <dupuy@amsterdam.columbia.edu> */
  1204. X
  1205. X/* WAITINGFOR - Determine what a process is waiting for and describe it. */
  1206. char    *waitingfor ( p )
  1207. X
  1208. struct process                  *p ;
  1209. X
  1210. X{
  1211. X    register caddr_t        w ;
  1212. X    register struct ttyline *lp ;
  1213. X    register struct symbol  *s ;
  1214. X    register char           *cp ;
  1215. X# ifdef BSD42
  1216. X    struct socket           sc ;
  1217. X# endif
  1218. X    int            rc ;
  1219. X    static char             wbuf[ 8 ] ;
  1220. X    extern struct info      Info ;
  1221. X    extern struct symbol    Symbollist[] ;
  1222. X    char                    *sprintf() ;
  1223. X# ifdef SUNOS40
  1224. X    char                    *gettty() ;
  1225. X# endif
  1226. X
  1227. X    w = p->pr_p.p_wchan ;
  1228. X    if ( !w )
  1229. X        return ( "null" ) ;
  1230. X    /* Waiting for a child process, alternatively in a vfork() ? */
  1231. X    if ( INRANGE( w, Info.i_proc0, &Info.i_proc0[ Info.i_nproc ] ) )
  1232. X# ifdef ULTRIX40
  1233. X        return ( p->pr_p.p_vm & SNOVM ? "vfork" : "child" ) ;
  1234. X# else
  1235. X        return ( p->pr_p.p_flag & SNOVM ? "vfork" : "child" ) ;
  1236. X# endif ULTRIX40
  1237. X# ifndef SUNOS40
  1238. X    /* Waiting for a page to be brought in ? */
  1239. X    if ( INRANGE( w, Info.i_swbuf0, &Info.i_swbuf0[ Info.i_nswbuf ] ) )
  1240. X        return ( "swap" ) ;
  1241. X    /* Waiting for discio through a block device to complete ? */
  1242. X    if ( INRANGE( w, Info.i_buf0, &Info.i_buf0[ Info.i_nbuf ] ) )
  1243. X        /* SHOULD ACTUALLY READ AS "blkio" BUT "discio" IS WHAT
  1244. X           IS GENERALLY MEANT HERE. */
  1245. X        return ( "discio" ) ;
  1246. X    /* Waiting for a text page to be brought in ? */
  1247. X    if ( INRANGE( w, Info.i_text0, &Info.i_text0[ Info.i_ntext ] ) )
  1248. X        return ( "swtext" ) ;
  1249. X# endif SUNOS40
  1250. X
  1251. X# ifdef BSD42
  1252. X#  ifndef NOQUOTA
  1253. X    /* Waiting for an event associated with the quota system ? */
  1254. X    if ( INRANGE( w, Info.i_quota0, &Info.i_quota0[ Info.i_nquota ] ) )
  1255. X        return ( "quota" ) ;
  1256. X#  endif NOQUOTA
  1257. X# endif BSD42
  1258. X
  1259. X# ifndef SUNOS41
  1260. X         /* Sorry, I don't know how to do this...
  1261. X          * I kinda think that SunOS 4.1 allocates inode
  1262. X          * buffer entries dynamically.  Maybe it could be
  1263. X          * possible to read in all "struct file"s and
  1264. X          * compare each file.f_data to the wait channel.    ++sja
  1265. X          */
  1266. X    /* Waiting for an inode ? */
  1267. X    if ( INRANGE( w, Info.i_inode0, &Info.i_inode0[ Info.i_ninode ] ) )
  1268. X#  ifdef ULTRIX20
  1269. X        switch ( ((int)w - (int)Info.i_inode0) % sizeof( struct gnode ))
  1270. X#  else
  1271. X        switch ( ((int)w - (int)Info.i_inode0) % sizeof( struct inode ))
  1272. X#  endif ULTRIX20
  1273. X        {
  1274. X#  ifdef BSD42
  1275. X#   ifdef NFS
  1276. X            case (int)&((struct inode*)0)->i_vnode.v_exlockc :
  1277. X                /* Exclusive lock on this inode */
  1278. X                return ( "exlock" ) ;
  1279. X            case (int)&((struct inode*)0)->i_vnode.v_shlockc :
  1280. X                /* Shared lock on this inode */
  1281. X                return ( "shlock" ) ;
  1282. X#   else NFS
  1283. X#    ifdef ULTRIX20
  1284. X#     ifndef ULTRIX40
  1285. X            /* Compile this code with gcc if you want to run it
  1286. X               properly.  The DEC compiler can't handle this. */
  1287. X            case (int)&((struct gnode*)0)->g_exlockc :
  1288. X                /* Exclusive lock on this inode */
  1289. X                return ( "exlock" ) ;
  1290. X            case (int)&((struct gnode*)0)->g_shlockc :
  1291. X                /* Shared lock on this inode */
  1292. X                return ( "shlock" ) ;
  1293. X            case (int)&((struct gnode*)0)->g_frcnt :
  1294. X                /* Open fifo with no readers */
  1295. X                return ( "wfifo" ) ;
  1296. X            case (int)&((struct gnode*)0)->g_fwcnt :
  1297. X                /* Open fifo with no writers */
  1298. X                return ( "rfifo" ) ;
  1299. X#     endif ULTRIX40
  1300. X#    else ULTRIX20
  1301. X            case (int)&((struct inode*)0)->i_exlockc :
  1302. X                /* Exclusive lock on this inode */
  1303. X                return ( "exlock" ) ;
  1304. X            case (int)&((struct inode*)0)->i_shlockc :
  1305. X                /* Shared lock on this inode */
  1306. X                return ( "shlock" ) ;
  1307. X#    endif ULTRIX20
  1308. X#   endif NFS
  1309. X#  else BSD42 
  1310. X            case 1 :
  1311. X                return ( "wpipe" ) ;
  1312. X            case 2 :
  1313. X                return ( "rpipe" ) ;
  1314. X            case (int)&((struct inode*)0)->i_un.i_group.g_datq :
  1315. X                return ( "rmux" ) ;
  1316. X#  endif BSD42
  1317. X            default :
  1318. X                /* Inode probably locked */
  1319. X                return ( "inode" ) ;
  1320. X        }
  1321. X# endif SUNOS41
  1322. X
  1323. X# if defined(BSD42) && (defined(SUNOS40) || defined(NMBCLUSTERS))
  1324. X    /* Waiting for a structure inside an mbuf ? If so, try to find why */
  1325. X#  ifdef SUNOS40
  1326. X    if ( INRANGE( w, Info.i_mbutl,
  1327. X    &Info.i_mbutl[ MBPOOLBYTES / sizeof( struct mbuf ) ] ) )
  1328. X#  else
  1329. X    if ( INRANGE( w, Info.i_mbutl,
  1330. X    &Info.i_mbutl[ NMBCLUSTERS * CLBYTES / sizeof( struct mbuf ) ] ) )
  1331. X#  endif SUNOS40
  1332. X        switch ( ((int)w - (int)Info.i_mbutl) % sizeof( struct mbuf )
  1333. X            - (int)&((struct mbuf*)0)->m_dat[0] )
  1334. X        {
  1335. X            case (int)&((struct socket*)0)->so_timeo :
  1336. X                /* Socket timeout event - Guess why */
  1337. X                rc = getsocket( (struct socket*)(w
  1338. X                    - (int)&((struct socket*)0)->so_timeo),
  1339. X                        &sc ) ;
  1340. X                return ( rc && (sc.so_state & SS_ISCONNECTING)
  1341. X                    ? "connct" 
  1342. X                    : rc && ((sc.so_options & SO_ACCEPTCONN)
  1343. X                      && !sc.so_qlen)
  1344. X                    ? "accept" : "socket" ) ;
  1345. X            case (int)&((struct socket*)0)->so_rcv.sb_cc :
  1346. X                /* Read from an empty socket. Here we actually
  1347. X                   attempt to determine whether the socket
  1348. X                   structure in question really does refer to
  1349. X                   a socket, or whether it is in fact a pipe
  1350. X                   in disguise. */
  1351. X                return ( getsocket( (struct socket*)(w
  1352. X                    - (int)&((struct socket*)0)->so_rcv.sb_cc),
  1353. X                        &sc )
  1354. X                    && sc.so_type == SOCK_STREAM
  1355. X#  ifdef BSD43
  1356. X                    && ((sc.so_state
  1357. X                        & (SS_ISCONNECTED|SS_CANTSENDMORE))
  1358. X                        == (SS_ISCONNECTED|SS_CANTSENDMORE))
  1359. X#  else
  1360. X                    && !sc.so_rcv.sb_hiwat
  1361. X                    && !sc.so_rcv.sb_mbmax
  1362. X                    && (sc.so_state
  1363. X                        & (SS_ISCONNECTED|SS_CANTRCVMORE))
  1364. X#  endif BSD43
  1365. X                    ? "rpipe" : "rsockt" ) ;
  1366. X            case (int)&((struct socket*)0)->so_snd.sb_cc :
  1367. X                /* Write to a full socket. Again, we try
  1368. X                   to determine whether or not this is a
  1369. X                   real socket or a pipe. */
  1370. X                return ( getsocket( (struct socket*)(w
  1371. X                    - (int)&((struct socket*)0)->so_snd.sb_cc),
  1372. X                        &sc )
  1373. X#  ifdef BSD43
  1374. X                    && sc.so_type == SOCK_STREAM
  1375. X                    && ((sc.so_state
  1376. X                        & (SS_ISCONNECTED|SS_CANTRCVMORE))
  1377. X                        == (SS_ISCONNECTED|SS_CANTRCVMORE))
  1378. X#  else
  1379. X                    && sc.so_rcv.sb_hiwat == 2048
  1380. X                    && sc.so_rcv.sb_mbmax == 4096
  1381. X                    && (sc.so_state
  1382. X                        & (SS_ISCONNECTED|SS_CANTSENDMORE))
  1383. X#  endif BSD43
  1384. X                    ? "wpipe" : "wsockt" ) ;
  1385. X            default :
  1386. X                /* Other mbuf event */
  1387. X                return ( "mbuf" ) ;
  1388. X        }
  1389. X# endif BSD42
  1390. X
  1391. X# ifdef SUNOS41
  1392. X    if  ( w == (caddr_t)p->pr_p.p_uarea )
  1393. X        return ( "pause" ) ;
  1394. X# endif SUNOS41
  1395. X    /* Look in the symbol table for known wait addresses. */
  1396. X    for ( s = Symbollist ; s->s_kname ; s++ )
  1397. X        if ( s->s_wait && w == *s->s_info )
  1398. X            return ( s->s_wait ) ;
  1399. X
  1400. X# ifdef SUNOS40
  1401. X    /* Have to check for ptys in a funny sort of way */
  1402. X    if ( INRANGE( w, Info.i_ptybase, &Info.i_ptybase[ Info.i_npty ] ) )
  1403. X    {
  1404. X        switch ( ((int)w - (int)Info.i_ptybase) % sizeof( struct pty ) )
  1405. X        {
  1406. X            case (int)&((struct pty*)0)->pt_flags :
  1407. X                cp = "opty??" ;
  1408. X                break ;
  1409. X            case (int)&((struct pty*)0)->pt_ttycommon.t_writeq :
  1410. X                cp = "spty??" ;
  1411. X                break ;
  1412. X            default :
  1413. X                cp = "?pty??" ;
  1414. X        }
  1415. X        /* by the conventional naming, anyhow */
  1416. X        cp[4] = 'p' + (((int)w - (int)Info.i_ptybase)
  1417. X            / sizeof( struct pty )) / 16 ;
  1418. X        if ( ( cp[5] = '0' + (((int) w - (int)Info.i_ptybase)
  1419. X            / sizeof( struct pty )) % 16 ) > '9' )
  1420. X            cp[5] += 'a' - '9' - 1 ;
  1421. X        return( cp ) ;
  1422. X    }
  1423. X    /* Check for ttys last, since there may be a lot of them. */
  1424. X    if ( p->pr_tty != 0 )
  1425. X        if ( cp = gettty( p->pr_tty, w ) )
  1426. X            return( cp ) ;
  1427. X    for ( lp = Info.i_ttyline ; lp->l_name[0] ; lp++ )
  1428. X        if ( cp = gettty( lp, w ) )
  1429. X            return( cp ) ;
  1430. X# else SUNOS40
  1431. X    /* Waiting for tty I/O ? If so, find which tty it is */
  1432. X    for ( lp = Info.i_ttyline ; lp->l_name[0] ; lp++ )
  1433. X        if ( INRANGE( w, &lp->l_addr[0], &lp->l_addr[1] ) )
  1434. X        {
  1435. X#  ifdef ULTRIX40
  1436. X            /* Cretinous DEC compiler can't handle case
  1437. X               constructs like the following ... */
  1438. X            cp = "?tty??" ;
  1439. X#  else ULTRIX40
  1440. X            switch ( (int)w - (int)lp->l_addr )
  1441. X            {
  1442. X                case (int)&((struct tty*)0)->t_rawq :
  1443. X                    /* Read from a tty or slave pty */
  1444. X                    cp = "rtty??" ;
  1445. X                    break ;
  1446. X                case (int)&((struct tty*)0)->t_outq :
  1447. X                    /* Write to a tty or slave pty */
  1448. X                    cp = "wtty??" ;
  1449. X                    break ;
  1450. X                case (int)&((struct tty*)0)->t_canq :
  1451. X                    /* Waiting for icon to be opened */
  1452. X                    cp = "itty??" ;
  1453. X                    break ;
  1454. X                case (int)&((struct tty*)0)->t_state :
  1455. X                    /* Tty not open */
  1456. X                    cp = "otty??" ;
  1457. X                    break ;
  1458. X                case (int)&((struct tty*)0)->t_outq.c_cf :
  1459. X                    /* Read from a controller pty */
  1460. X                    cp = "rpty??" ;
  1461. X                    break ;
  1462. X                case (int)&((struct tty*)0)->t_rawq.c_cf :
  1463. X                    /* Write to a controller pty */
  1464. X                    cp = "wpty??" ;
  1465. X                    break ;
  1466. X                default :
  1467. X                    cp = "?tty??" ;
  1468. X                    break ;
  1469. X            }
  1470. X#  endif ULTRIX40
  1471. X            cp[4] = lp->l_name[0] ;
  1472. X            cp[5] = lp->l_name[1] ;
  1473. X            return ( cp ) ;
  1474. X        }
  1475. X# endif SUNOS40
  1476. X
  1477. X    /* No reason for the wait state has been found.
  1478. X       Return the wait channel as a hexadecimal address. */
  1479. X# ifdef SUN
  1480. X    (void)sprintf( wbuf, "x%05x", w - KERNELBASE ) ;
  1481. X# else
  1482. X    (void)sprintf( wbuf, "x%05x", w - 0x80000000 ) ;
  1483. X# endif
  1484. X    return ( wbuf ) ;
  1485. X}
  1486. X
  1487. X
  1488. X# ifdef BSD42
  1489. X/*
  1490. X** GETSOCKET - Reads a `struct socket' from the kernel virtual memory address
  1491. X** identified by `ks' into the buffer `s'.
  1492. X*/
  1493. getsocket ( ks, s )
  1494. X
  1495. struct socket                   *ks ;
  1496. struct socket                   *s ;
  1497. X
  1498. X{
  1499. X    return ( getkmem( (long)ks, (char*)s, sizeof( struct socket ) )
  1500. X        == sizeof( struct socket ) ) ;
  1501. X}
  1502. X# endif BSD42
  1503. END_OF_FILE
  1504. if test 10012 -ne `wc -c <'waitingfor.c'`; then
  1505.     echo shar: \"'waitingfor.c'\" unpacked with wrong size!
  1506. fi
  1507. # end of 'waitingfor.c'
  1508. fi
  1509. echo shar: End of archive 3 \(of 3\).
  1510. cp /dev/null ark3isdone
  1511. MISSING=""
  1512. for I in 1 2 3 ; do
  1513.     if test ! -f ark${I}isdone ; then
  1514.     MISSING="${MISSING} ${I}"
  1515.     fi
  1516. done
  1517. if test "${MISSING}" = "" ; then
  1518.     echo You have unpacked all 3 archives.
  1519.     rm -f ark[1-9]isdone
  1520. else
  1521.     echo You still need to unpack the following archives:
  1522.     echo "        " ${MISSING}
  1523. fi
  1524. ##  End of shell archive.
  1525. exit 0
  1526.