home *** CD-ROM | disk | FTP | other *** search
- static char *Sccsid = "(File: %M% Ver: %I% Update: %G% %U%)";
- /*+F***********************************************************************
- *
- * File name: ptree.c
- *
- * Author: Paul Lew, General Systems Group, Inc. Salem, NH
- * Created at: 05/22/88 16:10 PM
- * Last update: 05/24/88 08:54 PM (Edition: 26)
- *
- * Description: This program will parse output of 'ps' command and display
- * the output with process indented under their parents for
- * the easy identification.
- *
- * Environment: 4.2 BSD Unix (Pyramid OSx 4.1)
- *
- * Usage: ptree [HPacgxt#]
- *
- * Update History:
- *
- * Date Description By
- * -------- ------------------------------------------------ ---
- * 05/22/88 Initial version Lew
- *
- * Routines included:
- *
- * build_offset build offset from 1st line of ps output
- * save_addr return addr of Save array with pid = pid
- * add_child add child to parent, if exists, add to end of sibling
- * print_result display result
- * print_process print a given process sub-tree
- * dump_save dump save structure for debugging
- * procarg return command argument for ps command
- * usage display help message
- *
- * Build: cc -o ptree ptree.c <CR>
- *
- **-F**********************************************************************/
-
- #include <stdio.h>
- #include <pwd.h>
-
- #define YES 1
- #define NO 0
-
- #define MAXLINE 200
-
- struct save {
- struct save *so_parent; /* pointer to parent */
- struct save *so_sibling; /* pointer to 1st sibling */
- struct save *so_child; /* pointer to 1st child */
- int so_uid; /* user ID */
- char so_name[9]; /* user name */
- int so_pid; /* pid */
- int so_ppid; /* parent pid */
- char *so_buffer; /* pointer to ps output */
- } Save [MAXLINE];
-
- char *Version = "Version 1.0 05/24/88 00:51 AM";
- char *Author = "Paul Lew, lew@gsg.uucp";
-
- int Line; /* # of output line from ps */
- int Print_me = NO; /* if NO, dont print my processes */
- int Print_pid = NO; /* if YES, output PID */
- char Command [80];
- int My_pid; /* my process id */
-
- int Uid_offset;
- int Pid_offset;
- int Ppid_offset;
- int End_ppid;
- int Stat_offset;
- int Tyy_offset;
- int Command_offset;
-
- struct save *save_addr ();
- char *procarg ();
-
- extern FILE *popen ();
- extern char *malloc (), *calloc ();
-
- /*-------------------------------------------------------------05/23/88-+
- | |
- | M a i n R o u t i n e S t a r t s H e r e |
- | |
- +----------------------------------------------------------------------*/
- main (argc, argv)
- int argc;
- char **argv;
- {
- FILE *pfd; /* file descriptor for popen() */
- char *p; /* temp pointer to malloced buffer */
- register int i; /* loop index */
- register struct save *svp;
-
- p = procarg (argc, argv);
- sprintf (Command, "ps lw%s", p);
- if ((pfd = popen (Command, "r")) == NULL) {
- fprintf (stderr, "can not execture ps\n");
- exit (1);
- }
- for (Line=0; Line<MAXLINE; Line++) {
- p = malloc (BUFSIZ);
- if (p == NULL) {
- perror ("malloc");
- exit (1);
- }
- if (fgets (p, BUFSIZ, pfd) == NULL) break;
- Save[Line].so_buffer = p;
- if (Line == 0) build_offset (p);
- else /* prevent CP data being processed */
- p[End_ppid] = '\0';
- }
- pclose (pfd);
- for (i=1; i<Line; i++) {
- struct passwd *pwp;
- svp = &Save[i];
- svp->so_pid = atoi (&svp->so_buffer[Pid_offset]);
- svp->so_ppid = atoi (&svp->so_buffer[Ppid_offset]);
- svp->so_uid = atoi (&svp->so_buffer[Uid_offset]);
- pwp = getpwuid (svp->so_uid);
- strncpy (svp->so_name, pwp->pw_name, 8);
- }
- for (i=1; i<Line; i++) {
- struct save *p;
- svp = &Save[i];
- svp->so_parent = p = save_addr (svp->so_ppid);
- if (p) {
- add_child (p, svp);
- }
- }
- print_result ();
- #ifdef DEBUG
- dump_save ();
- #endif
- exit (0);
- }
-
- /*-------------------------------------------------------------05/23/88-+
- | |
- | build_offset : build offset from 1st line of ps output |
- | |
- +----------------------------------------------------------------------*/
- build_offset (buf)
- char *buf; /* header line */
- {
- char *p = buf;
- for (p=buf; *p != '\0'; p++) {
- if (strncmp ("UID", p, 3) == 0) Uid_offset = p-buf;
- else if (strncmp (" PID ", p, 6) == 0) Pid_offset = p-buf;
- else if (strncmp (" PPID ", p, 6) == 0) Ppid_offset = p-buf;
- else if (strncmp ("STAT", p, 4) == 0) Stat_offset = p-buf;
- else if (strncmp ("TTY", p, 3) == 0) Tyy_offset = p-buf;
- else if (strncmp ("COMMAND",p, 7) == 0) Command_offset = p-buf;
- }
- End_ppid = Ppid_offset + 5;
- }
-
- /*-------------------------------------------------------------05/23/88-+
- | |
- | save_addr : return addr of Save array with pid = pid |
- | |
- +----------------------------------------------------------------------*/
- struct save *
- save_addr (pid)
- int pid;
- {
- register int i;
- for (i=1; i<Line; i++) {
- if (Save[i].so_pid == pid) return (&Save[i]);
- }
- return (NULL); /* not found */
- }
-
- /*-------------------------------------------------------------05/23/88-+
- | |
- | add_child : add child to parent, if exists, add to end of sibling |
- | |
- +----------------------------------------------------------------------*/
- add_child (parent, child)
- struct save *parent;
- struct save *child;
- {
- if (parent->so_child == NULL) {
- parent->so_child = child;
- }
- else {
- struct save *tp = parent->so_child;
- while (tp->so_sibling != NULL) tp = tp->so_sibling;
- tp->so_sibling = child;
- }
- child->so_sibling = NULL;
- }
-
- /*-------------------------------------------------------------05/23/88-+
- | |
- | print_result : display result |
- | |
- +----------------------------------------------------------------------*/
- print_result ()
- {
- register int i;
- struct save *svp;
-
- My_pid = getpid ();
- printf ("%s USER %s", Print_pid ? " PID " : "",
- &Save[0].so_buffer[Stat_offset]);
- for (i=1; i<Line; i++) {
- svp = &Save[i];
- if (svp->so_parent != NULL) {
- if (svp->so_pid != 0)
- continue;
- }
- print_process (0, svp);
- }
- }
-
- /*-------------------------------------------------------------05/23/88-+
- | |
- | print_process : print a given process sub-tree |
- | |
- +----------------------------------------------------------------------*/
- print_process (level, svp)
- int level;
- struct save *svp;
- {
- struct save *tp;
- register int i;
-
- if (!Print_me && svp->so_pid == My_pid) return;
- if (Print_pid) printf ("%5d ", svp->so_pid);
- printf ("%8s %.*s", svp->so_name, Command_offset - Stat_offset,
- &svp->so_buffer[Stat_offset]);
- for (i=0; i<level; i++) printf ("| ");
- printf ("%s", &svp->so_buffer[Command_offset]);
- if ((tp = svp->so_child) != NULL) {
- while (tp != NULL) {
- if (tp != svp) /* avoid infinit recursion */
- print_process (level+1, tp);
- tp = tp->so_sibling;
- }
- }
- }
-
- /*-------------------------------------------------------------05/23/88-+
- | |
- | dump_save : dump save structure for debugging |
- | |
- +----------------------------------------------------------------------*/
- #ifdef DEBUG
- dump_save ()
- {
- register int i;
- register struct save *tp;
-
- for (i=1; i<Line; i++) {
- tp = &Save[i];
- printf ("parent=%08x(x) ", tp->so_parent);
- printf ("sibling=%08x(x) ", tp->so_sibling);
- printf ("child=%08x(x) ", tp->so_child);
- printf ("PID=%05d PPID=%05d\n", tp->so_pid, tp->so_ppid);
- }
- printf ("command: [%s]\n", Command);
- }
- #endif
-
- /*------------------------------------------------------------05/24/88--+
- | |
- | procarg : return command argument for ps command |
- | |
- +----------------------------------------------------------------------*/
- char *
- procarg (argc, argv)
- int argc;
- char **argv;
- {
- static char buf [20] = "";
- register char c;
- register char *p = argv[1];
- int i = 0;
-
- if (argc == 1) return (buf);
- while ((c = *p++) != '\0') {
- switch (c) {
- case 'P': Print_me = YES; break;
- case 'p': Print_pid = YES; break;
- case 'H': usage (argv[0]); exit (0);
- case 'a': case 'c': case 'e': case 'g':
- case 'x': buf[i++] = c; break;
- case 't': strcpy (&buf[i], p-1); return (buf);
- default: usage (argv[0]); exit (1);
- }
- }
- buf [i] = '\0';
- return (buf);
- }
-
- /*-------------------------------------------------------------07/01/86-+
- | |
- | usage : display help message |
- | |
- +----------------------------------------------------------------------*/
- static usage (pname)
- char *pname; /* program name */
- {
- fprintf (stderr, "%s %s %s\n", pname, Version, Author);
- fprintf (stderr, "Usage: %s [acepgtxHP]\n", pname);
- fprintf (stderr, "where options:\n");
- fprintf (stderr, " H display this help message\n");
- fprintf (stderr, " P print processes created by me\n");
- fprintf (stderr, " p output PID\n");
- fprintf (stderr, " a,c,e,g,t,x will be passed to ps, if t is\n");
- fprintf (stderr, " specified, all the rest char in\n");
- fprintf (stderr, " the argument will be copied\n");
- }
-