home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3301 / pff.c
Encoding:
C/C++ Source or Header  |  1991-05-07  |  27.2 KB  |  1,185 lines

  1. /* History:
  2. 5/3/91 DJB various changes
  3. 5/1/91 DJB baseline public domain
  4. */
  5. /* XXX: Should allow for process gids... */
  6.  
  7. #include <stdio.h>
  8. #include "structfile.h"
  9. #include "structtext.h"
  10. #include "structucred.h"
  11. #include "structuser.h"
  12. #include "structproc.h" /*XXX: must be after structuser for BSD-Tahoe dorks*/
  13. #include "structxnode.h"
  14. #include "printfflag.h"
  15. #include "printftype.h"
  16. #include "printpstat.h"
  17. #include "printrlimits.h"
  18. #include "printrusage.h"
  19. #include "printucred.h"
  20. #include "getdevicename.h"
  21. #include "getfcred.h"
  22. #include "getnode.h"
  23. #include "getopt.h"
  24. #include "getpcred.h"
  25. #include "getsocket.h"
  26. #include "getuser.h"
  27. #include "getvmseg.h"
  28. #include "confhaveppid.h"
  29. #include "confhaveusigintr.h"
  30. #include "confmajorminor.h"
  31. #include "confnfs.h"
  32. #include "confodofe.h"
  33. #include "confopalf.h"
  34. #include "confpsess.h"
  35. #include "confregion.h"
  36. #include "conftext.h"
  37. #include "confttyvp.h"
  38. #include "confuofile.h"
  39. #include "filetable.h"
  40. #include "proctable.h"
  41. #include "revnamei.h"
  42. #include "portname.h"
  43. #include "username.h"
  44. #include "mallocfree.h"
  45. #include "numeric.h"
  46. #include "mntops.h"
  47. #include "strerr.h"
  48. #include "kmem.h"
  49. #include <signal.h>
  50. #ifndef ITIMER_REAL
  51. #include <sys/time.h>
  52. #endif
  53. #ifndef RLIM_NLIMITS
  54. #include <sys/resource.h>
  55. #endif
  56. #include <sys/stat.h>
  57.  
  58. #define STYLE_BRIEF 0
  59. #define STYLE_DEFAULT 1
  60. #define STYLE_LONG 2
  61. #define STYLE_UIDLONG 3
  62. #define STYLE_FULL 4
  63. #define STYLE_TINY 5
  64. #define STYLE_PIDS 6
  65. #define STYLE_NAME 7
  66.  
  67. #define two(i) (1 << i) /* table if necessary */
  68.  
  69. char progname[] = "pff";
  70.  
  71. static int flagall = 0;
  72.  
  73. main(argc,argv)
  74. int argc;
  75. char *argv[];
  76. {
  77.  struct proc *pt;
  78.  struct file *ft;
  79.  struct nodebuf buf;
  80.  struct socketbuf sbuf;
  81.  int i;
  82.  int style;
  83.  int opt;
  84.  struct stat st;
  85.  struct mounted *mt;
  86.  struct statlist *fsstats;
  87.  int security;
  88.  int uid;
  89.  int ppflags;
  90.  int offlags;
  91.  int pnflags;
  92.  
  93. #ifdef SECURITY
  94.  security = 1;
  95. #else
  96.  security = 0;
  97. #endif
  98.  uid = getuid();
  99.  if (!uid)
  100.    security = 0;
  101.  if (getgid() == getegid())
  102.    security = 0;
  103.  
  104.  getnodeinit();
  105.  seginit();
  106.  get_mntlist();
  107.  proctableinit();
  108.  filetableinit();
  109.  pt = getproctable();
  110.  if (!pt)
  111.   { fprintf(stderr,"%s: cannot get process table: %s\n",
  112.       progname,strerr(proctablestrerr)); exit(1); }
  113.  ft = getfiletable();
  114.  if (!ft)
  115.   { fprintf(stderr,"%s: cannot get file table: %s\n",
  116.       progname,strerr(filetablestrerr)); exit(1); }
  117.  
  118.  style = STYLE_DEFAULT;
  119.  while ((opt = getopt(argc,argv,"as:f:d:i:u:p:xX")) != EOF)
  120.    switch(opt)
  121.     {
  122.      case 'a': flagall = 1; break; /*XXX: inverse?*/
  123.      case 's': switch(*optarg)
  124.         {
  125.          case 'd': style = STYLE_DEFAULT; break;
  126.          case 'f': style = STYLE_FULL; break;
  127.          case 'b': style = STYLE_BRIEF; break;
  128.          case 'p': style = STYLE_PIDS; break;
  129.          case 'u': style = STYLE_UIDLONG; break;
  130.          case 'l': style = STYLE_LONG; break;
  131.          case 't': style = STYLE_TINY; break;
  132.          case 'n': style = STYLE_NAME; break;
  133.          case 'A': style = STYLE_BRIEF; break; /* <censored>: deprecated */
  134.          case 'D': style = STYLE_TINY; break; /* Dupuy: deprecated */
  135.          case 'F': style = STYLE_LONG; break; /* Fstat: deprecated */
  136.          case 'h': fprintf(stderr,
  137. "full\nuidlong\nlong\nname\ndefault\nbrief\ntiny\npids\n"); exit(1);
  138.          case 'H': fprintf(stderr,"\
  139. full: all information available, in a relatively unstructured format\n\
  140. uidlong: like long, but prints users by name where possible\n\
  141. long: like default, but includes file reference count, offset, credentials\n\
  142. name: like default, but prints filenames instead of device/inode\n\
  143. default: like short, but includes file descriptor type and flags\n\
  144. brief: one open file per line, basic information\n\
  145. tiny: all open files for one process per line\n\
  146. pids: process ids only\n\
  147. "
  148.                ); exit(1);
  149.          default: ; /*XXX*/
  150.         }
  151.            break;
  152.      case 'p': if (!numeric(optarg))
  153.         {
  154.          fprintf(stderr,"%s: fatal: pid %s not numeric\n"
  155.            ,progname,optarg);
  156.          exit(1);
  157.         }
  158.            procaddpid(atoi(optarg)); flagall = 1;
  159.            break;
  160.      case 'u': if (username2uid(optarg,&i) == -1)
  161.         {
  162.          fprintf(stderr,"%s: fatal: username %s not found\n"
  163.            ,progname,optarg);
  164.          exit(1);
  165.         }
  166.            procadduid(i); flagall = 1;
  167.            break;
  168.      case 'f': if (stat(optarg,&st) == -1)
  169.         {
  170.          fprintf(stderr,"%s: fatal: cannot stat %s: %s\n"
  171.            ,progname,optarg,strerr(strerrno));
  172.          exit(1);
  173.         }
  174.            /* XXX: keep track of filename? */
  175.            /* XXX: print filename? */
  176.            if (((st.st_mode & S_IFMT) == S_IFBLK)
  177.          ||((st.st_mode & S_IFMT) == S_IFCHR))
  178.         {
  179.          buf.flagdev = NODE_ID_DEV;
  180.          buf.id.dev.maj = major(st.st_rdev);
  181.          buf.id.dev.min = minor(st.st_rdev);
  182.         }
  183.            else
  184.         {
  185.              buf.flagdev = NODE_ID_INO;
  186.              buf.id.ino.inum = st.st_ino;
  187.              buf.id.ino.dev = st.st_dev;
  188.         }
  189.            validadd(&buf);
  190.            break;
  191.      case 'd': mt = getmntname(optarg);
  192.            if (!mt)
  193.         {
  194.          fprintf(stderr,"%s: fatal: cannot find mount of %s\n"
  195.            ,progname,optarg);
  196.          exit(1);
  197.         }
  198.            for (fsstats = stats;fsstats;fsstats = fsstats->next)
  199.          if (!strncmp(mt->filesystem,fsstats->fsname,MNTMAXSTR))
  200.           {
  201.                buf.flagdev = NODE_ID_INO;
  202.                buf.id.ino.inum = 0;
  203.                buf.id.ino.dev = fsstats->device;
  204.                validadd(&buf);
  205.            break;
  206.           }
  207.            break;
  208.      case 'i': sbuf.fsw = FSW_INET;
  209.            if (portname2port(optarg,&sbuf.fu.inet.lp) == -1)
  210.         {
  211.          fprintf(stderr,"%s: fatal: port %s not found\n"
  212.            ,progname,optarg);
  213.          exit(1);
  214.         }
  215.            validsadd(&sbuf);
  216.            break;
  217.      case 'x': if (!uid) security = 1; break;
  218.      case 'X': if (!uid) security = 0; break;
  219.      case '?': exit(1); /*XXX*/
  220.     }
  221.  argc -= optind; argv += optind;
  222.  
  223.  for (;*argv;++argv)
  224.   {
  225.    int guess;
  226.    /* ambiguity time */
  227.    guess = 1;
  228.    if (((*argv)[0] == '/') || ((*argv)[0] == '.'))
  229.      guess = 1;
  230.    else if (argv[0][0] == '#')
  231.     {
  232.      guess = 2;
  233.      ++*argv;
  234.     }
  235.    else if (numeric(*argv))
  236.      guess = 2;
  237.    /* XXX: any other choices? */
  238.  
  239.    if (guess == 1)
  240.     {
  241.      i = 0; /* becomes 1 if we shouldn't warn about failing getmntname */
  242.      if (stat(*argv,&st) == -1)
  243.        fprintf(stderr,"%s: warning: cannot stat %s: %s\n"
  244.        ,progname,*argv,strerr(strerrno));
  245.      else
  246.       {
  247.        i = 1;
  248.        if (((st.st_mode & S_IFMT) == S_IFBLK)
  249.          ||((st.st_mode & S_IFMT) == S_IFCHR))
  250.         {
  251.          buf.flagdev = NODE_ID_DEV;
  252.          buf.id.dev.maj = major(st.st_rdev);
  253.          buf.id.dev.min = minor(st.st_rdev);
  254.         }
  255.        else
  256.         {
  257.          buf.flagdev = NODE_ID_INO;
  258.          buf.id.ino.inum = st.st_ino;
  259.          buf.id.ino.dev = st.st_dev;
  260.         }
  261.        validadd(&buf);
  262.       }
  263.      mt = getmntname(*argv);
  264.      if (!mt)
  265.       {
  266.        if (!i)
  267.          fprintf(stderr,"%s: warning: cannot find mount of %s\n"
  268.        ,progname,*argv);
  269.       }
  270.      else
  271.       {
  272.        for (fsstats = stats;fsstats;fsstats = fsstats->next)
  273.          if (!strncmp(mt->filesystem,fsstats->fsname,MNTMAXSTR))
  274.           {
  275.            buf.flagdev = NODE_ID_INO;
  276.            buf.id.ino.inum = 0;
  277.            buf.id.ino.dev = fsstats->device;
  278.            validadd(&buf);
  279.            break;
  280.           }
  281.       }
  282.     }
  283.    else if (guess == 2)
  284.     {
  285.      flagall = 1;
  286.      if (!numeric(*argv))
  287.       {
  288.        /* this can never happen with the current guess structure */
  289.        fprintf(stderr,"%s: fatal: pid %s not numeric\n",progname,*argv);
  290.        exit(1);
  291.       }
  292.      procaddpid(atoi(*argv));
  293.     }
  294.   }
  295.  
  296.  ppflags = 8064;
  297.  offlags = 64;
  298.  pnflags = 0;
  299.  
  300.  /* XXX: use 128 for fd creds by name? */
  301.  
  302.  switch(style)
  303.   {
  304.    case STYLE_BRIEF:
  305.      puts("         CMD   PID   UID   FD TYPE      INODE    FS");
  306.      ppflags += 1;
  307.      offlags += 0;
  308.      pnflags += 0;
  309.      break;
  310.    case STYLE_DEFAULT:
  311.      puts("         CMD   PID   UID   FD D FLAGS     TYPE      INODE    FS");
  312.      ppflags += 1;
  313.      offlags += 16 + 4;
  314.      pnflags += 0;
  315.      break;
  316.    case STYLE_LONG:
  317.      puts("              CMD   PID   UID   FD   REF D     OFFSET FLAGS     CRED        TYPE      INODE    FS");
  318.      ppflags += 16384 + 1;
  319.      offlags += 16 + 4 + 2 + 8 + 32;
  320.      pnflags += 0;
  321.      break;
  322.    case STYLE_UIDLONG:
  323.      puts("              CMD   PID USERNAME   FD   REF D     OFFSET FLAGS     CRED        TYPE      INODE    FS");
  324.      ppflags += 32768 + 1;
  325.      offlags += 16 + 4 + 2 + 8 + 32;
  326.      pnflags += 0;
  327.      break;
  328.    case STYLE_FULL:
  329.      ppflags += 8192 + 126;
  330.      offlags += 16 + 4 + 2 + 8 + 32;
  331.      pnflags += 0;
  332.      break;
  333.    case STYLE_TINY:
  334.      puts("              CMD   PID USERNAME OFILES");
  335.      ppflags += 8192 + 32768 + 65536 + 131072 + 262144 + 1048576 + 1;
  336.      offlags += 16 + 4 + 2 + 8 + 32;
  337.      pnflags += 0;
  338.      break;
  339.    case STYLE_NAME:
  340.      puts("         CMD   PID   UID   FD D FLAGS     TYP FILENAME");
  341.      ppflags += 1;
  342.      offlags += 16 + 4;
  343.      pnflags += 6;
  344.      break;
  345.    case STYLE_PIDS:
  346.    default: /* default should never happen */
  347.      style = STYLE_PIDS;
  348.      ppflags += 524288;
  349.      offlags += 16 + 4 + 2 + 8 + 32;
  350.      pnflags += 2;
  351.      break;
  352.   }
  353.  
  354.  for (i = 0;i < mynproc;++i)
  355.    if (pt[i].p_pid) /*XXX*/
  356.      if (!security || (uid == pt[i].p_uid))
  357.        if (procmatch(&(pt[i])))
  358.          printproc(&(pt[i]),&(myproc[i]),ft,ppflags,offlags,pnflags);
  359.  if (style == STYLE_PIDS)
  360.    putchar('\n');
  361.  exit(0);
  362. }
  363.  
  364. /* flags:
  365. 1 put process identification before each fd line
  366.     16384 allow 17 chars rather than 12 for command name
  367. 2 print basic process information
  368. 4 print process status
  369. 8 print process resource usage
  370. 16 print process limits
  371. 32 print process credentials
  372. 64 print process signal handling
  373. 128 show text segment as fd, when it exists
  374. 256 show controlling tty as fd, when it exists
  375. 512 show cwd as fd
  376. 1024 show root dir as fd, when it exists
  377. 2048 show all open file descriptors
  378. 4096 show all mmap segments
  379. 8192 print extra newline
  380. 32768 show uids as usernames wherever possible
  381. 65536 don't space-fill fd labels (like cwd, 0, 1, 2, etc.)
  382. 131072 don't actually print fd descriptions with newline
  383. 262144 print preliminary prefd at most once before all fds
  384. 524288 print just pid, return as fast as possible XXX: how interact w/others?
  385. 1048576 under 1 + 8192 + 262144, don't print newline unless prefd has been used
  386. */
  387.  
  388. printproc(p,preal,ft,flags,offlags,pnflags)
  389. struct proc *p;
  390. struct proc *preal;
  391. struct file *ft;
  392. int flags;
  393. int offlags;
  394. int pnflags;
  395. {
  396. #ifdef OPALF
  397.  static struct file *(fof[NOFILE]);
  398. #endif
  399. #ifdef ODOFE
  400.  static struct ofile_ext oe;
  401. #endif
  402.  static struct nodebuf buf;
  403.  static struct socketbuf sbuf;
  404.  static char prefd[80];
  405.  struct user *u;
  406.  struct ucred *uc;
  407.  int i;
  408.  
  409.  /* printf("xstat %d ",p->p_xstat); */
  410.  /* printf("pri %d %d ",p->p_usrpri,p->p_pri); */
  411.  /* printf("time %d %d %d",p->p_slptime,p->p_time,(int) p->p_pctcpu); */
  412.  /* XXX: handle pctcpu? */
  413.  /* char *p_wchan */
  414.  /* XXX: u_timer[] */
  415.  /* XXX: u_start, on machines that have it */
  416.  /*XXX:p_tsize,p_dsize,p_ssize,p_rssize, p_maxrss===u.u_limit[MAXRSS],p_swrss*/
  417.  
  418.  if (p->p_stat == 0)
  419.    return;
  420.  if (p->p_stat == SZOMB)
  421.    return;
  422. #ifdef SIDL
  423.  if (p->p_stat == SIDL)
  424.    return;
  425. #endif
  426.  
  427.  u = getuser(p);
  428.  if (!u)
  429.   {
  430. #ifdef notdef /* sigh */
  431.    fprintf(stderr,"%s: warning: getuser failed on proc %d: %s\n"
  432.      ,progname
  433.      ,p->p_pid
  434.      ,strerr(getuserstrerr)
  435.      );
  436. #endif
  437.    return;
  438.   }
  439.  if (u->u_procp != preal)
  440.   {
  441.    /* XXX: warn? */
  442.    return;
  443.   }
  444.  
  445.  uc = getpcred(p,u);
  446.  if (!uc)
  447.    return;
  448.  
  449.  if (flags & 1)
  450.   {
  451.    sprintf(prefd
  452.      ,((flags & 16384) ? "%17.17s %5d %s " : "%12.12s %5d %s ")
  453.      ,u->u_comm
  454.      ,p->p_pid
  455.      ,printucred(uc,1,2,0,(flags & 32768) ? 1 : 0) /* XXX: should use names here */
  456.     );
  457.   }
  458.  
  459.  if (flags & 2)
  460.   {
  461.    printf("proc %8x ",preal);
  462.    printf("pid %d ",p->p_pid);
  463. #ifdef HAVE_PPID
  464.    printf("ppid %d ",p->p_ppid);
  465. #endif
  466.    printf("pgrp %d ",p->p_pgrp); /* XXX: p_sgid under POSIX */
  467.    printf("uid %d",p->p_suid);
  468.    if (p->p_uid != p->p_suid) printf("/%d",p->p_uid);
  469.    printf(" nice %d ",p->p_nice);
  470.    printf("umask %o ",u->u_cmask);
  471.    puts(u->u_comm);
  472.   }
  473.  
  474.  if (flags & 4)
  475.    printf("status: %s\n",printpstat(p));
  476.  
  477.  if (flags & 8)
  478.   {
  479.    printf("self: %s\n",printrusage(&(u->u_ru)));
  480.    printf("kids: %s\n",printrusage(&(u->u_cru)));
  481.   }
  482.  if (flags & 16)
  483.    printf("rlimits: %s\n",printrlimits(u->u_rlimit));
  484.  
  485.  if (flags & 32)
  486.   {
  487.    if (uc) printf("cred: %s\n",printucred(uc,0,0,1,(flags & 32768) ? 1 : 0));
  488.   }
  489.  
  490.  if (flags & 64)
  491.   {
  492.    printf("signals:");
  493.    for (i = 0;i < NSIG;++i)
  494.     {
  495.      if (!(i % 8)) putchar(' ');
  496.      if (u->u_signal[i] == SIG_DFL) putchar('d');
  497.      else if (u->u_signal[i] == SIG_IGN) putchar('i');
  498.      else putchar('C');
  499. #ifdef HAVE_USIGINTR
  500.      if (u->u_sigintr & two(i))
  501.        if (p->p_sigmask & two(i)) putchar(';'); else putchar(',');
  502.      else
  503. #endif
  504.        if (p->p_sigmask & two(i)) putchar(':'); else putchar('.');
  505.      /* any other flags to include? */
  506.     }
  507.    putchar('\n');
  508.   }
  509.  
  510. #ifdef REGION
  511.  if (flags & 128)
  512.   {
  513.    /* XXX: This is totally, absolutely undocumented to work. */
  514.    struct vm_vspace vs;
  515.    struct vm_object vo;
  516.    int i;
  517.    for (i = 0;i < sizeof(vs.vs_regiontab) / sizeof(vs.vs_regiontab[0]);++i)
  518.     {
  519.      kmemcpy(&vs,p->p_vspace,sizeof(vs));
  520.      kmemcpy(&vo,vs.vs_regiontab[i].re_object,sizeof(vo));
  521.      if (vo.ob_vp && validnode(vo.ob_vp,&buf,0))
  522.       {
  523.        if (flags & 524288)
  524.     {
  525.      printf("%d ",p->p_pid);
  526.      return;
  527.     }
  528.        if (flags & 1)
  529.          fputs(prefd,stdout);
  530.        if (flags & 262144)
  531.      prefd[0] = 0;
  532.        printf("text ");
  533.        if (!(flags & 131072))
  534.     {
  535.          spacenode(offlags);
  536.          printbuf(&buf,pnflags);
  537.     }
  538.        break;
  539.       }
  540.     }
  541.   }
  542. #else
  543. #ifdef TEXT
  544.  if (flags & 128)
  545.   {
  546.    struct text text;
  547.    kmemcpy(&text,p->p_textp,sizeof(text));
  548.    if (validnode(text.x_Xptr,&buf,0))
  549.     {
  550.      if (flags & 524288)
  551.       {
  552.        printf("%d ",p->p_pid);
  553.        return;
  554.       }
  555.      if (flags & 1)
  556.        fputs(prefd,stdout);
  557.      if (flags & 262144)
  558.        prefd[0] = 0;
  559.      printf("text ");
  560.      if (!(flags & 131072))
  561.       {
  562.        spacenode(offlags);
  563.        printbuf(&buf,pnflags);
  564.       }
  565.     }
  566.   }
  567. #endif
  568. #endif
  569.  
  570.  if (flags & 256)
  571.   {
  572. #ifdef TTYVP
  573. #ifdef PSESS
  574.    static struct sess pse;
  575.    kmemcpy(&pse,p->p_sessp,sizeof(pse));
  576.    if (pse.s_vp && validnode(pse.s_vp,&buf,0))
  577. #else
  578.    if (u->u_ttyvp && validnode(u->u_ttyvp,&buf,0))
  579. #endif
  580.     {
  581.      if (flags & 524288)
  582.       {
  583.        printf("%d ",p->p_pid);
  584.        return;
  585.       }
  586.      if (flags & 1)
  587.        fputs(prefd,stdout);
  588.      if (flags & 262144)
  589.        prefd[0] = 0;
  590.      printf("ctty ");
  591.      if (!(flags & 131072))
  592.       {
  593.        spacenode(offlags);
  594.        printbuf(&buf,pnflags);
  595.       }
  596.     }
  597. #else
  598.    if (u->u_ttyd)
  599.     {
  600.      char *s;
  601.      s = getttydevname(u->u_ttyd);
  602.      if (s)
  603.       {
  604.        buf.type = "chr"; /*XXX: breaks virtype encapsulation */
  605.        buf.flagdev = NODE_ID_DEV;
  606.        buf.id.dev.maj = 0; /*XXX*/
  607.        buf.id.dev.min = 0; /*XXX*/
  608.        buf.id.dev.name = s;
  609.        if (validnode(0,&buf,1)) /* XXX: does this work? */
  610.     {
  611.          if (flags & 524288)
  612.           {
  613.            printf("%d ",p->p_pid);
  614.            return;
  615.           }
  616.          if (flags & 1)
  617.            fputs(prefd,stdout);
  618.      if (flags & 262144)
  619.        prefd[0] = 0;
  620.          printf("ctty ");
  621.      if (!(flags & 131072))
  622.       {
  623.            spacenode(offlags);
  624.            printbuf(&buf,pnflags);
  625.       }
  626.     }
  627.       }
  628.     }
  629. #endif
  630.   }
  631.  
  632.  if (flags & 512)
  633.    if (u->u_cdir && validnode(u->u_cdir,&buf,0))
  634.     {
  635.      if (flags & 524288)
  636.       {
  637.        printf("%d ",p->p_pid);
  638.        return;
  639.       }
  640.      if (flags & 1)
  641.        fputs(prefd,stdout);
  642.      if (flags & 262144)
  643.        prefd[0] = 0;
  644.      if (flags & 65536)
  645.        printf("cwd ");
  646.      else
  647.        printf(" cwd ");
  648.      if (!(flags & 131072))
  649.       {
  650.        spacenode(offlags);
  651.        printbuf(&buf,pnflags);
  652.       }
  653.     }
  654.  if (flags & 1024)
  655.    if (u->u_rdir && validnode(u->u_rdir,&buf,0))
  656.     {
  657.      if (flags & 524288)
  658.       {
  659.        printf("%d ",p->p_pid);
  660.        return;
  661.       }
  662.      if (flags & 1)
  663.        fputs(prefd,stdout);
  664.      if (flags & 262144)
  665.        prefd[0] = 0;
  666.      printf("rdir ");
  667.      if (!(flags & 131072))
  668.       {
  669.        spacenode(offlags);
  670.        printbuf(&buf,pnflags);
  671.       }
  672.     }
  673.  
  674.  if (flags & 2048)
  675.   {
  676. #ifdef OPALF
  677.    if (u->u_lastfile >= NOFILE) /* XXX: ever? */
  678.      kmemcpy(fof,u->u_ofile,sizeof(struct file *) * NOFILE);
  679.    else
  680.      kmemcpy(fof,u->u_ofile,sizeof(struct file *) * (u->u_lastfile + 1));
  681.    u->u_ofile = fof; /* ensures that we're dealing with a pointer */
  682. #endif
  683. #ifdef ODOFE
  684.    if (u->u_ofile_ext)
  685.     {
  686.      kmemcpy(&oe,u->u_ofile_ext,sizeof(oe));
  687.      u->u_nofile = oe.oe_nofile;
  688.     }
  689. #endif
  690.    for (i = 0;i < NUOFILE(u);++i)
  691.     {
  692. #ifdef ODOFE
  693.      if (u->u_ofile_ext)
  694.        kmemcpy(u->u_lofile,oe.oe_ofile + i,sizeof(struct ofile));
  695.        /* XXX: this is slow as molasses */
  696.      else
  697.        u->u_lofile[0] = u->u_lofile[i]; /* XXX: structure copying */
  698. #endif
  699.      if (UOFILE(u,i))
  700.        if (ft[UOFILE(u,i) - myfile].f_data)
  701.     {
  702.      switch(ft[UOFILE(u,i) - myfile].f_type)
  703.       {
  704.        case DTYPE_INODE:
  705.          if (!validnode(ft[UOFILE(u,i) - myfile].f_data,&buf,0))
  706.            continue;
  707.          break;
  708.        case DTYPE_SOCKET:
  709.          if (!validsocket(ft[UOFILE(u,i) - myfile].f_data,&sbuf))
  710.            continue;
  711.          break;
  712.        default: /* including SPU, PROCESS */
  713.          if (!validother(ft[UOFILE(u,i) - myfile].f_data))
  714.            continue;
  715.       }
  716.          if (flags & 524288)
  717.           {
  718.            printf("%d ",p->p_pid);
  719.            return;
  720.           }
  721.      if (flags & 1)
  722.        fputs(prefd,stdout);
  723.      if (flags & 262144)
  724.        prefd[0] = 0;
  725.      if (flags & 65536)
  726.            printf("%d ",i);
  727.      else
  728.            printf("%4d ",i);
  729.      if (!(flags & 131072))
  730.            printfile(ft + (UOFILE(u,i) - myfile),offlags,pnflags,&buf,&sbuf);
  731.         }
  732.     }
  733.   }
  734.  
  735.  if (flags & 4096)
  736.   {
  737.    struct vnode **segvns;
  738.    segvns = getvmseg(p);
  739.    for (i = 0;segvns[i] && (i < vmsegmax);++i)
  740.     {
  741.      if (validnode(segvns[i],&buf,0))
  742.       {
  743.        if (flags & 524288)
  744.         {
  745.          printf("%d ",p->p_pid);
  746.          return;
  747.         }
  748.        if (flags & 1)
  749.          fputs(prefd,stdout);
  750.        if (flags & 262144)
  751.      prefd[0] = 0;
  752.        printf("mmap ");
  753.        if (!(flags & 131072))
  754.     {
  755.          spacenode(offlags);
  756.          printbuf(&buf,pnflags);
  757.     }
  758.       }
  759.     }
  760.   }
  761.  
  762.  if (flags & 8192)
  763.    if (!prefd[0] || !(flags & 1) || !(flags & 1048576) || !(flags & 262144))
  764.      putchar('\n');
  765. }
  766.  
  767. /* offlags:
  768. 1 print file data location, 9 chars
  769. 2 print reference count, 6 chars
  770. 4 print file type, 2 chars
  771. 8 print file offset, 11 chars
  772. 16 print file flags, 9 chars
  773. 32 print file credentials as uids, 12 chars (or 18 chars with usernames)
  774. 64 print extended file information, free format
  775. 128 use usernames rather than uids
  776. */
  777.  
  778. int printfile(f,offlags,pnflags,buf,sbuf)
  779. struct file *f;
  780. int offlags;
  781. int pnflags;
  782. struct nodebuf *buf;
  783. struct socketbuf *sbuf; /*XXX*/
  784. {
  785.  struct ucred *uc;
  786.  /* XXX: f_ops? f_msgcount? */
  787.  if (offlags & 1)
  788.    printf("%8x ",f->f_data);
  789.  if (offlags & 2)
  790.    printf("%5d ",(int) f->f_count);
  791.  if (offlags & 4)
  792.    printf("%s ",printftype(f)); /* could also do numeric */
  793.  if (offlags & 8)
  794.    printf("%10lu ",(unsigned long) f->f_offset);
  795.  if (offlags & 16)
  796.    printf("%s ",printfflag(f,4)); /* XXX: could also use 1,2,3 */
  797.  if (offlags & 32)
  798.   {
  799.    uc = getfcred(f);
  800.    if (uc) printf("%s ",printucred(uc,1,0,0,(offlags & 128) ? 1 : 0));
  801.   }
  802.  if (offlags & 64)
  803.    if (f->f_type == DTYPE_SOCKET)
  804.      printsbuf(sbuf);
  805.    else if (f->f_type == DTYPE_INODE)
  806.      printbuf(buf,pnflags);
  807. #ifdef DTYPE_SPU
  808.    else if (f->f_type == DTYPE_SPU)
  809.      printf("(spu io)");
  810. #endif
  811. #ifdef DTYPE_PROCESS
  812.    else if (f->f_type == DTYPE_PROCESS)
  813.     {
  814.      static struct proc p;
  815.      kmemcpy(&p,f->f_data,sizeof(p));
  816.      printf("(process %d)",p.p_pid);
  817.     }
  818. #endif
  819.    /* XXX: other types? */
  820.    else
  821.      printf("unk type %d %8x\n",f->f_type,f->f_data);
  822.  else
  823.    putchar('\n');
  824. }
  825.  
  826. int spacenode(offlags) /*XXX this whole routine */
  827. int offlags;
  828. {
  829.  if (offlags & 1)
  830.    printf("%8s ","");
  831.  if (offlags & 2)
  832.    printf("%5s ","");
  833.  if (offlags & 4)
  834.    printf("I "); /*XXX*/
  835.  if (offlags & 8)
  836.    printf("%10s ","");
  837.  if (offlags & 16)
  838.    printf("%s ","---------"); /*XXX*/
  839.  if (offlags & 32)
  840.    printf("%s ",(offlags & 128) ? "                 " : "           "); /*XXX*/
  841. }
  842.  
  843. printbuf(buf,pnflags)
  844. struct nodebuf *buf;
  845. int pnflags;
  846. {
  847.  printf("%s",buf->type);
  848.  switch(buf->flagdev)
  849.   {
  850.    case NODE_ID_FIFO:
  851.      printf(" (named pipe)\n");
  852.      break;
  853.    case NODE_ID_FIFOINO:
  854.      printf(" (named pipe)");
  855.    case NODE_ID_INO:
  856.      if (!(pnflags & 4))
  857.       {
  858.        printf((pnflags & 1) ? " inode %d" : " ino %7d",buf->id.ino.inum);
  859.        if (buf->id.ino.name)
  860.          if ((pnflags & 1))
  861.            printf(" %s fs %x (%s)",buf->id.ino.flagnfs ? "nfs" : "local"
  862.          ,buf->id.ino.dev,buf->id.ino.name);
  863.          else
  864.        printf(" %5x (%s)",buf->id.ino.dev,buf->id.ino.name);
  865.        else
  866.          if ((pnflags & 1))
  867.        printf(" block dev %x",buf->id.ino.dev);
  868.          else
  869.        printf(" %5x",buf->id.ino.dev);
  870.       }
  871.      if (pnflags & 2)
  872.       {
  873.        putchar(' '); if (!(pnflags & 4)) putchar('(');
  874.        revnamei((unsigned long) buf->id.ino.inum,(unsigned long) buf->id.ino.dev);
  875.        if (!(pnflags & 4)) putchar(')');
  876.        /* XXX: should do the printing right here */
  877.       }
  878.      putchar('\n');
  879.      break;
  880.    case NODE_ID_DEV:
  881.      if (pnflags & 4)
  882.       {
  883.        if (buf->id.dev.name)
  884.          printf(" %s\n",buf->id.dev.name);
  885.        else
  886.          printf(" dev (%d,%d)\n",buf->id.dev.maj,buf->id.dev.min);
  887.       }
  888.      else
  889.       {
  890.        if (buf->id.dev.name)
  891.          printf(" dev (%s)\n",buf->id.dev.name);
  892.        else
  893.          printf(" dev (%d,%d)\n",buf->id.dev.maj,buf->id.dev.min);
  894.       }
  895.      break;
  896.    default:
  897.      printf(" \n"); /*XXX*/
  898.   }
  899.  return;
  900. }
  901.  
  902. printsbuf(sbuf)
  903. struct socketbuf *sbuf;
  904. {
  905.  printf("(");
  906.  
  907.  if (sbuf->strsockt) printf("%s ",sbuf->strsockt);
  908.  else printf("unknown socket type %d ",sbuf->socktype);
  909.  
  910.  if (sbuf->flagaccept) printf("accept ");
  911.  if (sbuf->flagreuse) printf("reuse ");
  912.  if (sbuf->flaghead) printf("head ");
  913.  
  914.  if (sbuf->famname) printf("%s",sbuf->famname);
  915.  else printf("unknown family %d",sbuf->family);
  916.  
  917.  switch(sbuf->fsw)
  918.   {
  919.    case FSW_UNK:
  920.      break;
  921.    case FSW_INET:
  922.      if (sbuf->fu.inet.strpro) printf(" %s ",sbuf->fu.inet.strpro);
  923.      else printf(" protocol %d ",sbuf->fu.inet.proto);
  924.      if (sbuf->fu.inet.r0 || sbuf->fu.inet.r1 || sbuf->fu.inet.r2 || sbuf->fu.inet.r3)
  925.        printf("%u.%u.%u.%u",sbuf->fu.inet.r0,sbuf->fu.inet.r1,sbuf->fu.inet.r2,sbuf->fu.inet.r3);
  926.      else printf("*");
  927.      if (sbuf->fu.inet.rp) printf(":%d",sbuf->fu.inet.rp);
  928.      else printf(":*");
  929.      if (sbuf->fu.inet.l0 || sbuf->fu.inet.l1 || sbuf->fu.inet.l2 || sbuf->fu.inet.l3)
  930.        printf(" %u.%u.%u.%u",sbuf->fu.inet.l0,sbuf->fu.inet.l1,sbuf->fu.inet.l2,sbuf->fu.inet.l3);
  931.        /* XXX: always print local host as uname? */
  932.      else printf(" *");
  933.      if (sbuf->fu.inet.lp) printf(":%d",sbuf->fu.inet.lp);
  934.      else printf(":*");
  935.      break;
  936.    case FSW_UNIX:
  937.      printf(" unpcb %x inode %x conn %x",sbuf->fu.un.unpcb,sbuf->fu.un.node,sbuf->fu.un.conn);
  938.      /* XXX: print that vnode? print that unpcb? */
  939.      printf("%s",sbuf->fu.un.path);
  940.      break;
  941.    default:
  942.      break; /*XXX*/
  943.   }
  944.  
  945.  printf(")\n");
  946. }
  947.  
  948. struct validlist
  949.  {
  950.   struct validlist *next;
  951.   int type; /* 1 for node, 2 for socket */
  952.   union
  953.    {
  954.     struct nodebuf n;
  955.     struct socketbuf s;
  956.    }
  957.   v;
  958.  }
  959. ;
  960.  
  961. static struct validlist *validhead = 0;
  962.  
  963. int validsmatch(v,sbuf)
  964. struct socketbuf *v;
  965. struct socketbuf *sbuf;
  966. {
  967.  /* XXX: many more match types are possible */
  968.  /* socktype, family, fsw */
  969.  
  970.  if (v->fsw == FSW_UNK) /* no sockets at all */
  971.    return 0;
  972.  if (sbuf->fsw != v->fsw) /* must match nonzero fsw */
  973.    return 0;
  974.  if (v->fsw == FSW_INET)
  975.    if (v->fu.inet.lp && (v->fu.inet.lp != sbuf->fu.inet.lp))
  976.      return 0;
  977.  return 1;
  978. }
  979.  
  980. int validmatch(v,buf)
  981. struct nodebuf *v;
  982. struct nodebuf *buf;
  983. {
  984.  if (v->flagdev == NODE_ID_DEV)
  985.    if (buf->flagdev == NODE_ID_DEV)
  986.      return (v->id.dev.maj == buf->id.dev.maj) && (v->id.dev.min == buf->id.dev.min);
  987.    else
  988.      return 0;
  989.  if ((buf->flagdev == NODE_ID_INO) || (buf->flagdev == NODE_ID_FIFOINO))
  990.   {
  991.    /* It would be wrong to check NFS here: stat doesn't indicate NFS. */
  992.    if (v->id.ino.inum)
  993.      if (v->id.ino.inum != buf->id.ino.inum)
  994.        return 0;
  995.    if (v->id.ino.dev != buf->id.ino.dev)
  996.      return 0;
  997.    return 1;
  998.   }
  999.  return 0;
  1000. }
  1001.  
  1002. static struct socketbuf sockcache[256];
  1003. static int sockcacheok[256]; /* had better be initialized to 0 */
  1004. static char *sockcachepos[256];
  1005.  
  1006. int cachegetsocket(sock,buf)
  1007. char *sock;
  1008. struct socketbuf *buf;
  1009. {
  1010.  int hash;
  1011.  hash = ((char *) &sock)[0] + ((char *) &sock)[3];
  1012.    /* XXX: major XXX: we had better have 4-byte addresses here */
  1013.  hash = hash & 255; /* okay, at least this is in the right range */
  1014.  if (sockcacheok[hash])
  1015.    if (sockcachepos[hash] == sock)
  1016.     {
  1017.      *buf = sockcache[hash]; /* XXX: structure copying */
  1018.      return 0;
  1019.     }
  1020.  if (getsocket(sock,buf) == -1)
  1021.    return -1;
  1022.  sockcache[hash] = *buf; /* XXX: structure copying */
  1023.  sockcacheok[hash] = 1;
  1024.  sockcachepos[hash] = sock;
  1025.  return 0;
  1026. }
  1027.  
  1028. int validsocket(sock,sbuf)
  1029. char *sock;
  1030. struct socketbuf *sbuf;
  1031. {
  1032.  struct validlist *v;
  1033.  if (getsocket(sock,sbuf) == -1)
  1034.    return 0;
  1035.  if (!validhead)
  1036.    return flagall;
  1037.  for (v = validhead;v;v = v->next)
  1038.    if (v->type == 2)
  1039.      if (validsmatch(&(v->v.s),sbuf))
  1040.        return 1;
  1041.  return 0;
  1042. }
  1043.  
  1044. static struct nodebuf nodecache[256];
  1045. static int nodecacheok[256]; /* had better be initialized to 0 */
  1046. static char *nodecachepos[256];
  1047.  
  1048. int cachegetnode(node,buf)
  1049. char *node;
  1050. struct nodebuf *buf;
  1051. {
  1052.  int hash;
  1053.  hash = ((char *) &node)[0] + ((char *) &node)[3];
  1054.    /* XXX: major XXX: we had better have 4-byte addresses here */
  1055.  hash = hash & 255; /* okay, at least this is in the right range */
  1056.  if (nodecacheok[hash])
  1057.    if (nodecachepos[hash] == node)
  1058.     {
  1059.      *buf = nodecache[hash]; /* XXX: structure copying */
  1060.      return 0;
  1061.     }
  1062.  if (getnode(node,buf) == -1)
  1063.    return -1;
  1064.  nodecache[hash] = *buf; /* XXX: structure copying */
  1065.  nodecacheok[hash] = 1;
  1066.  nodecachepos[hash] = node;
  1067.  return 0;
  1068. }
  1069.  
  1070. int validnode(node,buf,gndone)
  1071. char *node;
  1072. struct nodebuf *buf;
  1073. int gndone;
  1074. {
  1075.  struct validlist *v;
  1076.  if (!gndone)
  1077.    if (cachegetnode(node,buf) == -1)
  1078.      return 0;
  1079.  if (!validhead)
  1080.    return flagall;
  1081.  for (v = validhead;v;v = v->next)
  1082.    if (v->type == 1)
  1083.      if (validmatch(&(v->v.n),buf))
  1084.        return 1;
  1085.  return 0;
  1086. }
  1087.  
  1088. int validsadd(sbuf)
  1089. struct socketbuf *sbuf;
  1090. {
  1091.  struct validlist *v;
  1092.  v = (struct validlist *) malloc(sizeof(struct validlist));
  1093.  if (!v)
  1094.    return -1;
  1095.  v->next = validhead;
  1096.  v->type = 2;
  1097.  v->v.s = *sbuf; /* XXX: requires struct copying */
  1098.  validhead = v;
  1099.  return 0;
  1100. }
  1101.  
  1102. int validadd(buf)
  1103. struct nodebuf *buf;
  1104. {
  1105.  struct validlist *v;
  1106.  v = (struct validlist *) malloc(sizeof(struct validlist));
  1107.  if (!v)
  1108.    return -1;
  1109.  v->next = validhead;
  1110.  v->type = 1;
  1111.  v->v.n = *buf; /* XXX: requires struct copying */
  1112.  validhead = v;
  1113.  return 0;
  1114. }
  1115.  
  1116. int validother(node)
  1117. char *node;
  1118. {
  1119.  if (validhead)
  1120.    return 0;
  1121.  return flagall;
  1122. }
  1123.  
  1124. struct proclist
  1125.  {
  1126.   struct proclist *next;
  1127.   int type; /* 1 for pid, 2 for uid */
  1128.   union
  1129.    {
  1130.     int pid;
  1131.     int uid;
  1132.    }
  1133.   u;
  1134.  }
  1135. ;
  1136.  
  1137. static struct proclist *prochead = 0;
  1138.  
  1139. int procmatch(proc)
  1140. struct proc *proc;
  1141. {
  1142.  struct proclist *p;
  1143.  if (!prochead)
  1144.    return 1;
  1145.  for (p = prochead;p;p = p->next)
  1146.   {
  1147.    if (p->type == 1)
  1148.      if (proc->p_pid == p->u.pid)
  1149.        return 1;
  1150.    if (p->type == 2)
  1151.      if (proc->p_uid == p->u.uid)
  1152.        return 1;
  1153.    /*XXX: more types? */
  1154.   }
  1155.  return 0;
  1156. }
  1157.  
  1158. int procaddpid(pid)
  1159. int pid;
  1160. {
  1161.  struct proclist *p;
  1162.  p = (struct proclist *) malloc(sizeof(struct proclist));
  1163.  if (!p)
  1164.    return -1;
  1165.  p->next = prochead;
  1166.  p->type = 1;
  1167.  p->u.pid = pid;
  1168.  prochead = p;
  1169.  return 0;
  1170. }
  1171.  
  1172. int procadduid(uid)
  1173. int uid;
  1174. {
  1175.  struct proclist *p;
  1176.  p = (struct proclist *) malloc(sizeof(struct proclist));
  1177.  if (!p)
  1178.    return -1;
  1179.  p->next = prochead;
  1180.  p->type = 2;
  1181.  p->u.uid = uid;
  1182.  prochead = p;
  1183.  return 0;
  1184. }
  1185.