home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume5 / pt.bsd / ptree.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-02-03  |  8.7 KB  |  315 lines

  1. static    char    *Sccsid = "(File: %M%  Ver: %I%  Update: %G% %U%)";
  2. /*+F***********************************************************************
  3. *
  4. * File name:    ptree.c
  5. *
  6. * Author:    Paul Lew, General Systems Group, Inc. Salem, NH
  7. * Created at:    05/22/88  16:10 PM
  8. * Last update:    05/24/88  08:54 PM  (Edition: 26)
  9. *
  10. * Description:    This program will parse output of 'ps' command and display
  11. *        the output with process indented under their parents for
  12. *        the easy identification.
  13. *    
  14. * Environment:    4.2 BSD Unix (Pyramid OSx 4.1)
  15. *
  16. * Usage:    ptree [HPacgxt#]
  17. *
  18. * Update History:
  19. *
  20. *      Date        Description                    By
  21. *    --------    ------------------------------------------------    ---
  22. *    05/22/88    Initial version                        Lew
  23. *
  24. * Routines included:
  25. *
  26. *    build_offset    build offset from 1st line of ps output    
  27. *    save_addr    return addr of Save array with pid = pid    
  28. *    add_child    add child to parent, if exists, add to end of sibling
  29. *    print_result    display result
  30. *    print_process    print a given process sub-tree
  31. *    dump_save    dump save structure for debugging
  32. *    procarg        return command argument for ps command
  33. *    usage        display help message
  34. *
  35. * Build:    cc -o ptree ptree.c <CR>
  36. *
  37. **-F**********************************************************************/
  38.  
  39. #include    <stdio.h>
  40. #include    <pwd.h>
  41.  
  42. #define    YES        1
  43. #define    NO        0
  44.  
  45. #define    MAXLINE        200
  46.  
  47. struct    save    {
  48.     struct    save    *so_parent;    /* pointer to parent */
  49.     struct    save    *so_sibling;    /* pointer to 1st sibling */
  50.     struct    save    *so_child;    /* pointer to 1st child */
  51.     int        so_uid;        /* user ID */
  52.     char        so_name[9];    /* user name */
  53.     int        so_pid;        /* pid */
  54.     int        so_ppid;    /* parent pid */
  55.     char        *so_buffer;    /* pointer to ps output */
  56.     } Save [MAXLINE];
  57.  
  58. char    *Version = "Version 1.0  05/24/88  00:51 AM";
  59. char    *Author = "Paul Lew, lew@gsg.uucp";
  60.  
  61. int    Line;                /* # of output line from ps */
  62. int    Print_me = NO;            /* if NO, dont print my processes */
  63. int    Print_pid = NO;            /* if YES, output PID */
  64. char    Command [80];
  65. int    My_pid;                /* my process id */
  66.  
  67. int    Uid_offset;
  68. int    Pid_offset;
  69. int    Ppid_offset;
  70. int    End_ppid;
  71. int    Stat_offset;
  72. int    Tyy_offset;
  73. int    Command_offset;
  74.  
  75. struct    save    *save_addr ();
  76. char        *procarg ();
  77.  
  78. extern    FILE    *popen ();
  79. extern    char    *malloc (), *calloc ();
  80.  
  81. /*-------------------------------------------------------------05/23/88-+
  82. |                                    |
  83. |      M a i n     R o u t i n e     S t a r t s     H e r e        |
  84. |                                    |
  85. +----------------------------------------------------------------------*/
  86. main (argc, argv)
  87. int    argc;
  88. char    **argv;
  89.     {
  90.     FILE            *pfd;    /* file descriptor for popen() */
  91.     char            *p;    /* temp pointer to malloced buffer */
  92.     register int        i;    /* loop index */
  93.     register struct    save    *svp;
  94.  
  95.     p = procarg (argc, argv);
  96.     sprintf (Command, "ps lw%s", p);
  97.     if ((pfd = popen (Command, "r")) == NULL) {
  98.         fprintf (stderr, "can not execture ps\n");
  99.         exit (1);
  100.         }
  101.     for (Line=0; Line<MAXLINE; Line++) {
  102.         p = malloc (BUFSIZ);
  103.         if (p == NULL) {
  104.             perror ("malloc");
  105.             exit (1);
  106.             }
  107.         if (fgets (p, BUFSIZ, pfd) == NULL) break;
  108.         Save[Line].so_buffer = p;
  109.         if (Line == 0) build_offset (p);
  110.         else            /* prevent CP data being processed */
  111.             p[End_ppid] = '\0';
  112.         }
  113.     pclose (pfd);
  114.     for (i=1; i<Line; i++) {
  115.         struct    passwd    *pwp;
  116.         svp = &Save[i];
  117.         svp->so_pid  = atoi (&svp->so_buffer[Pid_offset]);
  118.         svp->so_ppid = atoi (&svp->so_buffer[Ppid_offset]);
  119.         svp->so_uid  = atoi (&svp->so_buffer[Uid_offset]);
  120.         pwp = getpwuid (svp->so_uid);
  121.         strncpy (svp->so_name, pwp->pw_name, 8);
  122.         }
  123.     for (i=1; i<Line; i++) {
  124.         struct    save    *p;
  125.         svp = &Save[i];
  126.         svp->so_parent = p = save_addr (svp->so_ppid);
  127.         if (p) {
  128.             add_child (p, svp);
  129.             }
  130.         }
  131.     print_result ();
  132. #ifdef    DEBUG
  133.     dump_save ();    
  134. #endif
  135.     exit (0);
  136.     }
  137.  
  138. /*-------------------------------------------------------------05/23/88-+
  139. |                                    |
  140. |     build_offset : build offset from 1st line of ps output        |
  141. |                                    |
  142. +----------------------------------------------------------------------*/
  143. build_offset (buf)
  144. char    *buf;                /* header line */
  145.     {
  146.     char        *p = buf;
  147.     for (p=buf; *p != '\0'; p++) {
  148.         if      (strncmp ("UID",    p, 3) == 0) Uid_offset     = p-buf;
  149.         else if (strncmp ("  PID ", p, 6) == 0) Pid_offset     = p-buf;
  150.         else if (strncmp (" PPID ", p, 6) == 0) Ppid_offset    = p-buf;
  151.         else if (strncmp ("STAT",   p, 4) == 0) Stat_offset    = p-buf;
  152.         else if (strncmp ("TTY",    p, 3) == 0) Tyy_offset     = p-buf;
  153.         else if (strncmp ("COMMAND",p, 7) == 0) Command_offset = p-buf;
  154.         }
  155.     End_ppid = Ppid_offset + 5;
  156.     }
  157.  
  158. /*-------------------------------------------------------------05/23/88-+
  159. |                                    |
  160. |       save_addr : return addr of Save array with pid = pid        |
  161. |                                    |
  162. +----------------------------------------------------------------------*/
  163. struct    save    *
  164. save_addr (pid)
  165. int    pid;
  166.     {
  167.     register int    i;
  168.     for (i=1; i<Line; i++) {
  169.         if (Save[i].so_pid == pid) return (&Save[i]);
  170.         }
  171.     return (NULL);            /* not found */
  172.     }
  173.  
  174. /*-------------------------------------------------------------05/23/88-+
  175. |                                    |
  176. |  add_child : add child to parent, if exists, add to end of sibling    |
  177. |                                    |
  178. +----------------------------------------------------------------------*/
  179. add_child (parent, child)
  180. struct    save    *parent;
  181. struct    save    *child;
  182.     {
  183.     if (parent->so_child == NULL) {
  184.         parent->so_child = child;
  185.         }
  186.     else    {
  187.         struct    save    *tp = parent->so_child;
  188.         while (tp->so_sibling != NULL) tp = tp->so_sibling;
  189.         tp->so_sibling = child;
  190.         }
  191.     child->so_sibling = NULL;
  192.     }
  193.  
  194. /*-------------------------------------------------------------05/23/88-+
  195. |                                    |
  196. |              print_result : display result            |
  197. |                                    |
  198. +----------------------------------------------------------------------*/
  199. print_result ()
  200.     {
  201.     register int    i;
  202.     struct    save    *svp;
  203.  
  204.     My_pid = getpid ();
  205.     printf ("%s    USER %s", Print_pid ? "  PID " : "",
  206.         &Save[0].so_buffer[Stat_offset]);
  207.     for (i=1; i<Line; i++) {
  208.         svp = &Save[i];
  209.         if (svp->so_parent != NULL) {
  210.             if (svp->so_pid != 0)
  211.               continue;
  212.             }
  213.         print_process (0, svp);
  214.         }
  215.     }
  216.  
  217. /*-------------------------------------------------------------05/23/88-+
  218. |                                    |
  219. |          print_process : print a given process sub-tree        |
  220. |                                    |
  221. +----------------------------------------------------------------------*/
  222. print_process (level, svp)
  223. int        level;
  224. struct    save    *svp;
  225.     {
  226.     struct    save    *tp;
  227.     register int    i;
  228.  
  229.     if (!Print_me && svp->so_pid == My_pid) return;
  230.     if (Print_pid) printf ("%5d ", svp->so_pid);
  231.     printf ("%8s %.*s", svp->so_name, Command_offset - Stat_offset,
  232.         &svp->so_buffer[Stat_offset]);
  233.     for (i=0; i<level; i++) printf ("|  ");
  234.     printf ("%s", &svp->so_buffer[Command_offset]);
  235.     if ((tp = svp->so_child) != NULL) {
  236.         while (tp != NULL) {
  237.             if (tp != svp)        /* avoid infinit recursion */
  238.                 print_process (level+1, tp);
  239.             tp = tp->so_sibling;
  240.             }
  241.         }
  242.     }
  243.  
  244. /*-------------------------------------------------------------05/23/88-+
  245. |                                    |
  246. |          dump_save : dump save structure for debugging        |
  247. |                                    |
  248. +----------------------------------------------------------------------*/
  249. #ifdef    DEBUG
  250. dump_save ()
  251.     {
  252.     register int        i;
  253.     register struct    save    *tp;
  254.  
  255.     for (i=1; i<Line; i++) {
  256.         tp = &Save[i];
  257.         printf ("parent=%08x(x) ", tp->so_parent);
  258.         printf ("sibling=%08x(x) ", tp->so_sibling);
  259.         printf ("child=%08x(x) ", tp->so_child);
  260.         printf ("PID=%05d PPID=%05d\n", tp->so_pid, tp->so_ppid);
  261.         }
  262.     printf ("command: [%s]\n", Command);
  263.     }
  264. #endif
  265.  
  266. /*------------------------------------------------------------05/24/88--+
  267. |                                    |
  268. |       procarg : return command argument for ps command        |
  269. |                                    |
  270. +----------------------------------------------------------------------*/
  271. char    *
  272. procarg (argc, argv)
  273. int    argc;
  274. char    **argv;
  275.     {
  276.     static    char    buf [20] = "";
  277.     register char    c;
  278.     register char    *p = argv[1];
  279.     int        i = 0;
  280.  
  281.     if (argc == 1) return (buf);
  282.     while ((c = *p++) != '\0') {
  283.         switch (c) {
  284.             case 'P':    Print_me = YES;        break;
  285.             case 'p':    Print_pid = YES;    break;
  286.             case 'H':    usage (argv[0]);    exit (0);
  287.             case 'a': case 'c': case 'e': case 'g':
  288.             case 'x':    buf[i++] = c;        break;
  289.             case 't':    strcpy (&buf[i], p-1);    return (buf);
  290.             default:    usage (argv[0]); exit (1);
  291.             }
  292.         }
  293.     buf [i] = '\0';
  294.     return (buf);
  295.     }
  296.  
  297. /*-------------------------------------------------------------07/01/86-+
  298. |                                    |
  299. |            usage : display help message            |
  300. |                                    |
  301. +----------------------------------------------------------------------*/
  302. static usage (pname)
  303. char    *pname;            /* program name */
  304.     {
  305.     fprintf (stderr, "%s  %s  %s\n", pname, Version, Author);
  306.     fprintf (stderr, "Usage: %s [acepgtxHP]\n", pname);
  307.     fprintf (stderr, "where options:\n");
  308.     fprintf (stderr, "  H              display this help message\n");
  309.     fprintf (stderr, "  P              print processes created by me\n");
  310.     fprintf (stderr, "  p              output PID\n");
  311.     fprintf (stderr, "  a,c,e,g,t,x    will be passed to ps, if t is\n");
  312.     fprintf (stderr, "                 specified, all the rest char in\n");
  313.     fprintf (stderr, "                 the argument will be copied\n");
  314.     }
  315.