home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-07-02 | 24.7 KB | 1,355 lines |
- Newsgroups: comp.sources.misc
- organization: ZYX Sweden AB, Stockholm, Sweden
- subject: v13i098: tps - show process tree using 'ps'.
- from: arndt@zyx.ZYX.SE (Arndt Jonasson)
- Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 13, Issue 98
- Submitted-by: arndt@zyx.ZYX.SE (Arndt Jonasson)
- Archive-name: tps/part01
-
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- #
- # Wrapped by Arndt Jonasson <arndt@coca> on Fri Jun 29 11:53:32 1990
- #
- # This archive contains:
- # README makefile options.c options.h
- # tps.1 tps.c
- #
-
- LANG=""; export LANG
- PATH=/bin:/usr/bin:$PATH; export PATH
-
- echo x - README
- cat >README <<'@EOF'
- 29 June 1990 - Arndt Jonasson - arndt@zyx.se
-
- This is version 1.0 of 'tps', a program that invokes the 'ps' command
- and rearranges its output into a more legible format.
-
-
- Files:
-
- README this file
- makefile commands for building the program
- tps.c 'tps' source code
- tps.1 manual page
- options.h header file for option parsing
- options.c option parser source code
-
-
- To build the program, if your system is one of the following:
-
- Hewlett-Packard's HP-UX (series 9000/300 or 9000/800)
- DEC's Ultrix (DecStation 3100)
- Apollo's Domain/OS
- SUN's SunOS
- Sony's NeWS
-
- just type the command 'make'.
-
- If your system is not one of those, but has the 'ps' program, it may
- work anyway, or you may have to do some changes to tps.c first. If you
- port 'tps' to another system, please send your changes back to me.
-
-
- The option parser is usable independently of 'tps', but, alas, there
- is no manual page yet.
- @EOF
-
- chmod 664 README
-
- echo x - makefile
- cat >makefile <<'@EOF'
-
- tps: tps.o options.o
- cc -o tps tps.o options.o -ltermcap
-
- tps.o: tps.c options.h
- cc -c tps.c
-
- options.o: options.c options.h
- cc -c options.c
-
-
- clean:
- -rm tps options.o tps.o
- @EOF
-
- chmod 664 makefile
-
- echo x - options.c
- cat >options.c <<'@EOF'
- /*
- options.c - created 28 Mar 88.
-
- Command line option parser, version 1.0 (29 June 1990)
-
- Author: Arndt Jonasson, Zyx Sweden
- arndt@zyx.SE (...<backbone>!mcsun!sunic!zyx!arndt)
-
- No manual page yet.
- */
-
- #include "options.h"
-
- extern void exit (); /* '#define void' if your compiler doesn't */
- /* have it.*/
-
- char *O_programname = NULL;
-
- static char *usage_string = NULL;
- static int option_error;
-
- static fatal (msg)
- char *msg;
- {
- fprintf (stderr, "option parsing failure: %s\n", msg);
- exit (1);
- }
-
- static char *basename (str)
- char *str;
- {
- char *p1, *p2;
- extern char *strchr ();
-
- p2 = str;
- while ((p1 = strchr (p2, '/')) != NULL)
- {
- if (p1[1] == '\0')
- {
- p1[0] = '\0';
- return p2;
- }
- p2 = p1 + 1;
- }
- return p2;
- }
-
- static char *match (prefix, str)
- char *prefix, *str;
- {
- int n = strlen (prefix);
-
- if (strncmp (prefix, str, n) == 0)
- return str + n;
- else
- return NULL;
- }
-
- O_usage ()
- {
- if (usage_string != NULL)
- {
- if (O_programname == NULL)
- fprintf (stderr, "valid options: %s\n", usage_string);
- else
- fprintf (stderr, "usage: %s %s\n", O_programname, usage_string);
- }
- else
- {
- if (O_programname != NULL)
- fprintf (stderr, "%s: ", O_programname);
- fprintf (stderr, "invalid usage\n");
- }
-
- exit (1);
- }
-
- int O_atoi (str)
- char *str;
- {
- char c;
- int base = 10;
- int res = 0;
- int negative = 1;
-
- /*
- No check for overflow.
- */
-
- c = str[0];
-
- if (*str == '-')
- {
- negative = -1;
- str++;
- }
-
- if (*str == '0')
- {
- if (*++str == 'x')
- {
- str++;
- base = 16;
- }
- else
- base = 8;
- }
-
- if (*str == '\0' && (negative != -1 || base != 8)) /* kludgie */
- {
- option_error = 1;
- return 0;
- }
-
- for (;;)
- {
- switch (c = *str++)
- {
- case '8':
- case '9':
- if (base == 8)
- {
- option_error = 1;
- return 0;
- }
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- res = base * res + c - '0';
- break;
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- if (base == 16)
- res = base * res + c - 'a' + 10;
- else
- {
- option_error = 1;
- return 0;
- }
- break;
- case '\0':
- return (negative * res);
- /* NOTREACHED */
- break;
- default:
- option_error = 1;
- return 0;
- }
- }
- }
-
- double O_atof (s)
- char *s;
- {
- /*
- No error-checking currently.
- */
- extern double atof ();
-
- return atof (s);
- }
-
- char *O_strid (s)
- char *s;
- {
- return s;
- }
-
- char O_chrid (s)
- char *s;
- {
- return s[0];
- }
-
- static get_it (p, arg, c)
- Option *p;
- char *arg;
- char c;
- {
- option_error = 0;
-
- switch ((p->flags & 037))
- {
- case O_INT:
- *p->ip = (*p->ipf) (arg);
- if (option_error)
- {
- fprintf (stderr,
- "Invalid integer '%s' given to the -%c option\n", arg, c);
- O_usage ();
- }
- break;
- case O_STR:
- *p->cp = (*p->cpf) (arg);
- break;
- case O_DBL:
- *p->dp = (*p->dpf) (arg);
- if (option_error)
- {
- fprintf (stderr,
- "Invalid floating-point number '%s' given to the -%c option\n", arg, c);
- O_usage ();
- }
- break;
- case O_CHR:
- *p->tp = (*p->tpf) (arg);
- break;
- case O_MUL:
- (*p->table_p)[p->data++] = arg;
- break;
- default:
- fatal ("invalid option type");
- }
- }
-
- int O_parse_options (desc, argc, argv)
- Option *desc;
- int argc;
- char **argv;
- {
- static char *empty_table[] = {NULL};
- int first_char, multiple_error, multiple_add, hyphen_is_arg;
- int min, max, i, remaining;
- Option *p, *default_p = NULL;
- char *cp, *dir, *arg;
- char c;
-
- multiple_error = 1;
- multiple_add = 0;
- hyphen_is_arg = 1;
- min = 0;
- max = -1;
-
- for (p = desc; p->flags != O_END; p++)
- {
- p->data = 0;
-
- if (p->flags == O_DIR)
- {
- dir = p->directive;
- if (cp = match ("usage: ", dir))
- usage_string = cp;
- else if (cp = match ("multiple: ", dir))
- {
- multiple_error = (strcmp ("error", cp) == 0);
- multiple_add = (strcmp ("add", cp) == 0);
- }
- else if (cp = match ("remaining: ", dir))
- {
- int n;
- char dummy;
-
- n = sscanf (cp, "%d%c%d", &min, &dummy, &max);
- if (n == 1)
- max = min;
- else if (n == 2)
- max = -1;
- }
- else
- fatal ("unknown option directive");
- }
- else if (p->flags == O_MUL)
- *p->table_p = (char **) malloc (argc * sizeof (char *));
- else if (p->flags == O_INT && p->c == '\0')
- {
- p->c = -1;
- default_p = p;
- }
- else if (p->flags == O_FLG && p->c == '\0')
- hyphen_is_arg = 0;
-
- if (p->flags == O_FLG)
- *p->ip = 0;
- }
-
- O_programname = basename (argv[0]);
-
- for (i = 1; i < argc; i++)
- {
- arg = argv[i];
- if (arg[0] != '-' || (arg[1] == '\0' && hyphen_is_arg))
- break;
-
- first_char = 1;
-
- while ((c = *++arg) != '\0' || first_char)
- {
- for (p = desc; p->flags != O_END; p++)
- if (p->c == c)
- {
- if (p->flags & 040)
- {
- fprintf (stderr, "The -%c option was given twice\n", c);
- O_usage ();
- }
-
- if (multiple_error && p->flags != O_MUL)
- p->flags |= 040;
-
- if ((p->flags & 037) == O_FLG)
- {
-
- if (multiple_add)
- *(p->ip) += 1;
- else
- *(p->ip) = 1;
- if (c == '\0')
- goto next_argument;
- else
- goto next_character;
- }
-
- arg += 1;
- if (arg[0] == '\0')
- {
- if (++i == argc)
- {
- fprintf (stderr,
- "The -%c option requires an argument\n", c);
- O_usage ();
- }
- arg = argv[i];
- }
- get_it (p, arg, c);
- goto next_argument;
- }
- if ((p = default_p) != NULL && first_char)
- {
- *p->ip = (*p->ipf) (arg);
- if (!option_error)
- goto next_argument;
- }
- fprintf (stderr, "There is no -%c option\n", c);
- O_usage ();
-
- /* NOTREACHED*/
-
- next_character:
- first_char = 0;
- }
- next_argument: ;
- }
-
- for (p = desc; p->flags != O_END; p++)
- if ((p->flags & 037) == O_MUL)
- {
- if (p->data == 0)
- (*p->table_p = empty_table);
- else
- {
- (*p->table_p)[p->data++] = NULL;
- *p->table_p = (char **) realloc (*p->table_p,
- p->data * sizeof (char *));
- }
- }
-
- remaining = argc - i;
- if (remaining < min || max != -1 && remaining > max)
- {
- if (max == -1)
- fprintf (stderr, "At least %d non-option argument%s required\n",
- min, min == 1 ? " is" : "s are");
- else if (max == 0)
- fprintf (stderr, "No non-option arguments are allowed\n");
- else if (min == max)
- fprintf (stderr, "Exactly %d non-option argument%s required\n",
- min, min == 1 ? " is" : "s are");
- else
- fprintf (stderr, "%d to %d non-option arguments are required\n",
- min, max);
- O_usage ();
- }
- return i;
- }
- @EOF
-
- chmod 664 options.c
-
- echo x - options.h
- cat >options.h <<'@EOF'
- /*
- options.h - created 28 Mar 88.
-
- Command line option parser, version 1.0 (29 June 1990)
-
- Author: Arndt Jonasson, Zyx Sweden
- arndt@zyx.SE (...<backbone>!mcsun!sunic!zyx!arndt)
-
- No manual page yet.
- */
-
- #include <stdio.h>
-
- typedef struct
- {
- char c;
- int flags;
- char **cp;
- char *(*cpf) ();
- int *ip;
- int (*ipf) ();
- double *dp;
- double (*dpf) ();
- char *tp;
- char (*tpf) ();
- char ***table_p;
- char *directive;
- int data;
- } Option;
-
- extern int O_atoi ();
- extern double O_atof ();
- extern char O_chrid ();
-
- extern char *O_strid ();
- extern char *O_programname;
-
- #define O_FLG 0
- #define O_INT 1
- #define O_STR 2
- #define O_DBL 3
- #define O_END 4
- #define O_DIR 5
- #define O_CHR 6
- #define O_MUL 7
-
-
- #define O_flg(c, ip) {c, O_FLG, 0, 0, &ip, 0, 0, 0, 0, 0, 0, 0}
- #define O_int(c, ip) {c, O_INT, 0, 0, &ip, O_atoi, 0, 0, 0, 0, 0, 0}
- #define O_str(c, cp) {c, O_STR, &cp, O_strid, 0, 0, 0, 0, 0, 0, 0, 0}
- #define O_dbl(c, dp) {c, O_DBL, 0, 0, 0, 0, &dp, O_atof, 0, 0, 0, 0}
- #define O_end {-1, O_END, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
- #define O_directive(str) {-1, O_DIR, 0, 0, 0, 0, 0, 0, 0, 0, 0, str}
- #define O_chr(c, cp) {c, O_CHR, 0, 0, 0, 0, 0, 0, &cp, O_chrid, 0, 0}
- #define O_mul(c, cpp) {c, O_MUL, 0, 0, 0, 0, 0, 0, 0, 0, &cpp, 0}
-
- #define O_Empty '\0'
-
- #define usage() O_usage ()
- @EOF
-
- chmod 664 options.h
-
- echo x - tps.1
- cat >tps.1 <<'@EOF'
- .TH TPS 1 local ""
- .SH NAME
- tps - tree-structured process status
- .SH SYNOPSIS
- .B tps
- [-wat] [-u
- .I user]
- [-i
- .I n]
- [-c
- .I time]
- .SH DESCRIPTION
- .I tps
- runs
- .B ps
- in an inferior fork and filters its output to present a more legible
- view of the currently running processes. One output line consists of
- the process pid, the name of its owner, its controlling terminal (optional)
- and the command line arguments of the process. If a process has any
- children, these are displayed directly following their father, with
- their pids indented.
-
- If the command line arguments for one process don't fit in one display line,
- they wrap to the next line, indicating this with a plus sign in front
- of the continuation line. The width of the screen is taken from the
- .B terminfo/termcap
- database. If the width cannot be found, 80 is assumed.
-
- The criterion for displaying a process is the following: for each process,
- if itself, any child or any ancestor is owned by the
- .IR "current user" ,
- it is displayed. In other words, all processes belonging to the user will
- be displayed, and additionally all children to any of those, whether owned
- by the user or not (thus including invocations of
- .BR su(1) ,
- and all parent processes (which will always include the
- .B init
- process (pid 1) and the
- .B swapper
- process (pid 0).
-
- By default, the
- .I current user
- is the user running the program.
- .B tps
- can be told to use any other user, or to display all running processes.
-
- .PP
- The options have the following meanings:
- .TP 11
- .BR -t
- Show the controlling tty of the process, if it has one.
- .TP
- .BR -w
- If the process is sleeping, show the symbolic name of the address that
- the process is waiting for. This options is currently only implemented
- in HP-UX.
- .TP
- .BR -a
- Show all running processes, not just the process tree of one user.
- .TP
- .BI -u " user"
- Show the process tree of processes belonging to
- .IR user .
- If this option is not given, the process tree of the user invoking
- the program will be given (as defined by the environment variable
- LOGNAME, or the
- .IR "real user id" ,
- in that order).
- .TP
- .BI -i " n"
- This changes the default indentation of child processes from 2 to
- .IR n .
- .TP
- .BI -c " time"
- When this option is specified,
- .B ps
- is invoked twice, with the interval
- .I time
- seconds. The processes common to both invocations are displayed (subject
- to the usual selection by user described above), and the difference in
- run time, if not zero, is printed in front of the command line arguments.
- .SH FILES
- /bin/ps
- .SH ENVIRONMENT
- .TP 11
- TERM
- The name of the terminfo/termcap database entry. Used for obtaining the
- screen width.
- .TP
- LOGNAME
- The
- .I current user
- to use when the
- .B \-u
- option hasn't been given.
- .SH NOTES
- .B tps
- has currently been ported to Hewlett-Packard's HP-UX, DEC's Ultrix,
- Apollo's Domain/OS, SUN's SunOS, and Sony's NeWS.
- .SH SEE ALSO
- ps(1), terminfo(4), terminfo(5), termcap(3).
- .SH BUGS
- When the -w is given, the display of the command line arguments may be
- messed up.
- .SH AUTHOR
- Arndt Jonasson, ZYX Sweden (email address: arndt@zyx.se)
- @EOF
-
- chmod 664 tps.1
-
- echo x - tps.c
- cat >tps.c <<'@EOF'
- /*
- tps.c -- Tree-structured ps program. It works by reading in the output
- of a 'ps' command and reordering it so that the parent-son relation-
- ships of the processes are displayed.
-
- The maximum width of the terminal is honored. Link with -ltermcap
- (or -ltermlib).
-
- Author: Arndt Jonasson, Zyx.
- */
-
- /*
- Do error checking in various placesf (sscanf, malloc..)
- Fix vararg for pfield.
-
- Foo! Linking curses adds 60K to the code size.
-
- New ideas:
- Make 'tps -u root' only show root-owned processes.
- -p pid: show only the subtree with the pid p in it.
- */
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <pwd.h>
-
- #include "options.h"
-
- extern char *getenv ();
- extern struct passwd *getpwuid ();
-
- #ifdef hpux
- #define MAX_PROC 200
- #define PS_COM "ps -efl"
- #else
- #ifdef apollo
- #define MAX_PROC 200
- #define PS_COM "ps -ef"
- #else
- #ifdef pyr
- #define MAX_PROC 536
- #define PS_COM "ps -agxlw"
- #else
- #define MAX_PROC 100
- #define PS_COM "ps -agxlw"
- #endif
- #endif
- #endif
-
- #define LEFT 1
- #define RIGHT 2
- #define CENTER 4
- #define LAST 8
-
- #define LINMAX 400
-
- #ifdef hpux
-
- #if 0
- #define OWNER 0
- #define PID 9
- #define PPID 15
- #define JUNK1 21
- #define TTY 33
- #define JUNK2 (TTY+8)
- #define CPU 41
- #define INFO 47
- #else
- #define OWNER 6
- #define PID 14
- #define PPID 20
- #define JUNK1 26
- #define WAITCH 47
- #define TTY 65
- #define JUNK2 (TTY+8)
- #define CPU 73
- #define INFO 79
- #endif
-
- #else
-
- #ifdef apollo
- #define OWNER 0
- #define PID 9
- #define PPID 15
- #define JUNK1 21
- #define TTY 33
- #define JUNK2 (TTY+9)
- #define CPU 42
- #define INFO 48
- #else
-
- #ifdef ultrix
- #define OWNER 0
- #define PID 4
- #define PPID 10
- #define JUNK1 16
- #define INFO 60
- #define TTY 50
- #define CPU 54
- #define JUNK2 54
- #else
-
- #ifdef sun
- #define OWNER 7
- #define PID 12
- #define PPID 18
- #define JUNK1 24
- #define INFO 70
- #define TTY 61
- #define CPU 65
- #define JUNK2 65
- #else
-
- #define OWNER 7
- #define PID 12
- #define PPID 18
- #define JUNK1 24
- #ifdef pyr
- #define INFO 73
- #define TTY 63
- #define JUNK2 (TTY+4)
- #else
- #ifdef sony
- #define INFO 75
- #define TTY 65
- #define JUNK2 (TTY+4)
- #define CPU 69
- #else
- #define INFO 69
- #define TTY 60
- #define JUNK2 (TTY+4)
- #endif
- #endif
- #endif
- #endif
- #endif
- #endif
-
- struct process
- {
- int pid, ppid;
- char *owner, *info, *tty;
- int printed;
- int cputime;
- long channel;
- };
-
- struct process *proc[MAX_PROC];
- int maxproc = 0;
-
- int hmax, hpos;
- int maxlevel = 0;
- int show_tty = 0;
- int indentation = 2;
- int show_all = 0;
- int cpu_diff = 0;
- char *my_name = 0;
-
- #ifdef WAITCH
- typedef struct
- {
- long adr;
- char name[20];
- } Symbol;
-
- int show_waitchan = 0;
- Symbol *table;
- int symbol_n;
- #endif
-
- char *newstr (str)
- char *str;
- {
- char *cp;
- while (*str++ == ' ');
- str--;
- cp = (char *) malloc (strlen (str) + 1);
- strcpy (cp, str);
- return cp;
- }
-
- newline ()
- {
- hpos = 0;
- printf ("\n");
- }
-
- #ifdef WAITCH
- Symbol *lookup (adr)
- long adr;
- {
- int i1 = 0, i2 = symbol_n;
- int i;
-
- for (;;)
- {
- i = (i1 + i2) / 2;
- if (table[i].adr == adr)
- return &table[i];
- else if (table[i].adr > adr)
- i2 = i;
- else
- i1 = i;
- if (i1 > i2 - 2)
- break;
- }
- if (table[i].adr > adr)
- i -= 1;
- return &table[i];
- }
-
- slurp_channel_data ()
- {
- int d;
- struct stat s_buf;
-
- maybe_rebuild_tps_data ();
-
- d = open ("/tmp/tps_data", O_RDONLY);
- fstat (d, &s_buf);
- table = (Symbol *) malloc (s_buf.st_size);
- read (d, table, s_buf.st_size);
- symbol_n = s_buf.st_size / sizeof (Symbol);
- }
-
- char *addr_to_name (a)
- long a;
- {
- static char buf[80];
- long diff;
- Symbol *sym;
-
- if (a == 0)
- return "";
-
- sym = lookup (a);
-
- if (sym == &table[symbol_n - 1])
- return "?";
-
- diff = a - sym->adr;
- if (diff > 0x100000)
- return "?";
-
- if (diff == 0)
- sprintf (buf, "%s", sym->name);
- else
- sprintf (buf, "%s+%#x", sym->name, diff);
-
- if (buf[0] == '_')
- return buf+1;
- else
- return buf;
- }
-
- maybe_rebuild_tps_data ()
- {
- int s;
- FILE *fi, *fo;
- char buf[80];
- long adr;
- char type[5], name[80];
- Symbol block;
- struct stat b1, b2;
-
- s = stat ("/hp-ux", &b1);
- s = stat ("/tmp/tps_data", &b2);
- if (s == 0 && b1.st_mtime <= b2.st_mtime)
- return;
-
- fprintf (stderr, "Rebuilding kernel symbol table ...\n");
-
- #ifdef hp9000s800
- s = system ("nm -vp /hp-ux >/tmp/tps_data_x");
- #else
- s = system ("nm -n /hp-ux >/tmp/tps_data_x");
- #endif
- fi = fopen ("/tmp/tps_data_x", "r");
- fo = fopen ("/tmp/tps_data", "w");
-
- for (;;)
- {
- fgets (buf, 80, fi);
- if (feof (fi))
- break;
- #ifdef hp9000s800
- sscanf (buf, "%x %s %s\n", &adr, type, name);
- #else
- sscanf (buf, "0x%x %s %s\n", &adr, type, name);
- #endif
- block.adr = adr;
- strcpy (block.name, name);
- fwrite ((char *) &block, sizeof (block), 1, fo);
- }
- fclose (fi);
- fclose (fo);
- }
- #endif /* WAITCH */
-
- pfield (len, align, format, a1, a2, a3, a4, a5)
- int len, align;
- char *format;
- {
- char *text;
- char buf[200];
- int l, i, pre, post, o_hpos;
-
- o_hpos = hpos;
- hpos += len;
- if (hpos > hmax)
- {
- len -= hpos - hmax;
- hpos = hmax;
- }
-
- sprintf (buf, format, a1, a2, a3, a4, a5);
- l = strlen (buf);
-
- if (align & LEFT)
- {
- pre = 0;
- post = len - l;
- }
- else if (align & RIGHT)
- {
- pre = len - l;
- post = 0;
- }
- else if (align & CENTER)
- {
- pre = len - l;
- post = pre >> 1;
- pre = pre - post;
- }
-
- text = buf;
-
- for (;;)
- {
- for (i = 0; i < pre; i++) putchar (' ');
- if (len < l)
- {
- printf ("%.*s", len, text);
- newline ();
- for (i = 0; i < o_hpos - 2; i++) putchar (' ');
- putchar ('+'); putchar (' ');
- text += len;
- l -= len;
- }
- else
- {
- printf ("%.*s", l, text);
- hpos = o_hpos + len;
- break;
- }
- }
-
- if (!(align & LAST))
- for (i = 0; i < post; i++) putchar (' ');
- }
-
- int maxlev (n, level, me_above)
- int n, level, me_above;
- {
- int i;
- int pid = proc[n]->pid;
- int me_below = 0;
-
- if (level > maxlevel) maxlevel = level;
-
- if (strcmp (proc[n]->owner, my_name) == 0)
- me_above = 1;
-
- for (i = 0; i < maxproc; i++)
- if (proc[i]->ppid == pid && proc[i]->pid != 0)
- {
- if (maxlev (i, level + 1, me_above))
- me_below = 1;
- }
-
- me_above |= me_below;
- if (!me_above && !show_all)
- proc[n]->printed = 1;
- return me_above;
- }
-
- print_pp (n, level)
- int n, level;
- {
- int i;
- int pid = proc[n]->pid;
-
- if (proc[n]->printed) return;
-
- print_p (n, level);
-
- for (i = 0; i<maxproc; i++)
- if (proc[i]->ppid == pid)
- print_pp (i, level+1);
- }
-
- #ifdef hpux
- #define TTY_WIDTH 10
- #else
- #define TTY_WIDTH 5
- #endif
-
- print_p (n, level)
- int n, level;
- {
- proc[n]->printed = 1;
-
- pfield (indentation * maxlevel + 6,
- LEFT,
- "%*.*s%d",
- indentation * level,
- indentation * level,
- " ",
- proc[n]->pid);
- pfield (7, LEFT, "%s", proc[n]->owner);
- if (show_tty)
- pfield (TTY_WIDTH, LEFT, "%s", proc[n]->tty);
- #ifdef WAITCH
- if (show_waitchan)
- pfield (25, LEFT, "%s ", addr_to_name (proc[n]->channel));
- #endif
- if (cpu_diff > 0)
- {
- if (proc[n]->cputime < 0)
- pfield (3, LEFT, "%d", -proc[n]->cputime);
- else
- pfield (3, LEFT, "");
- }
- pfield (100, LEFT+LAST, "%s", proc[n]->info);
- newline ();
- }
-
- int to_seconds (str)
- char *str;
- {
- int min, sec, n;
-
- n = sscanf (str, "%d:%d", &min, &sec);
- if (n == 2)
- return 60*min+sec;
- else
- return atoi (str);
- }
-
- sort ()
- {
- int i, j, k, pid;
- struct process *sav;
-
- for (i = 0; i<maxproc; i++)
- {
- pid = 100000;
-
- for (j = i; j<maxproc; j++)
- {
- if (proc[j]->pid < pid)
- {
- k = j;
- pid = proc[j]->pid;
- }
- }
- sav = proc[i];
- proc[i] = proc[k];
- proc[k] = sav;
- }
- }
-
- #define warning(x, arg) sprintf (wbuf, x, arg), warn (wbuf)
-
- warn (msg)
- char *msg;
- {
- fprintf (stderr, "tps: %s, assuming width 80\n", msg);
- }
-
- int find_width ()
- {
- char wbuf[200];
- char buffer[1024];
- char *name;
- int s;
- int width = 80;
-
- name = getenv ("TERM");
- if (name == 0)
- warning ("terminal type not set", 0);
- else
- {
- s = tgetent (buffer, name);
- switch (s)
- {
- case 1:
- s = tgetnum ("co");
- if (s == -1)
- warning ("width not given for type \"%s\"", name);
- else
- width = s;
- break;
- case -1:
- warning ("can't access terminal database", 0);
- break;
- case 0:
- warning ("can't find type %s in the terminal database", name);
- break;
- default:
- warning ("weird return value from tgetent (%d)", s);
- break;
- }
- }
- return width;
- }
-
- #ifdef ultrix
- zap_flags (buf)
- char *buf;
- {
- char c;
- char *p=buf, *q;
-
- while (*p++ != ' ');
- q = buf;
- while ((c = *p++) != '\0')
- *q++ = c;
- *q = '\0';
- }
- #endif
-
- main (argc, argv)
- int argc;
- char *argv[];
- {
- FILE *f;
- char buf[LINMAX];
- struct process *p;
- int i, pid;
-
- static Option desc[] = {
- O_flg ('t', show_tty),
- O_flg ('a', show_all),
- #ifdef WAITCH
- O_flg ('w', show_waitchan),
- #endif
- O_int ('i', indentation),
- O_int ('c', cpu_diff),
- O_str ('u', my_name),
- O_directive ("remaining: 0"),
- #ifdef WAITCH
- O_directive
- ("usage: [-wat] [-u user] [-i indentation] [-c time]"),
- #else
- O_directive
- ("usage: [-at] [-u user] [-i indentation] [-c time]"),
- #endif
- O_end,
- };
-
- O_parse_options (desc, argc, argv);
-
- if (indentation < 1)
- indentation = 1;
-
- if (my_name == 0)
- my_name = getenv ("LOGNAME");
- if (my_name == 0)
- my_name = getpwuid (getuid ())->pw_name;
- if (my_name == 0)
- {
- fprintf (stderr, "%s: couldn't obtain user name\n", O_programname);
- my_name = "";
- }
- else
- my_name = newstr (my_name);
-
- hpos = 0;
- hmax = find_width () - 1;
-
- #ifdef WAITCH
- if (show_waitchan)
- slurp_channel_data ();
- #endif
-
- sprintf (buf, "exec %s", PS_COM);
- f = popen (buf, "r");
- if (f == 0)
- {
- fprintf (stderr, "%s: couldn't run ps\n", O_programname);
- exit (1);
- }
-
- fgets (buf, LINMAX, f);
-
- for (;;)
- {
- fgets (buf, LINMAX, f);
- if (feof (f)) break;
-
- #ifdef ultrix
- zap_flags (buf);
- #endif
-
- buf[strlen (buf) - 1] = 0;
-
- buf[PID-1] = 0;
- buf[PPID-1] = 0;
- buf[JUNK1-1] = 0;
- buf[JUNK2-1] = 0;
- #ifdef WAITCH
- buf[WAITCH+9] = 0;
- #endif
-
- p = (struct process *) malloc (sizeof (struct process));
- #ifdef hpux
- p->owner = newstr (&buf[OWNER]);
- #else
- #ifdef apollo
- p->owner = newstr (&buf[OWNER]);
- #else
- {
- int uid;
- uid = atoi (&buf[OWNER]);
- p->owner = newstr (getpwuid (uid)->pw_name);
- }
- #endif
- #endif
- p->pid = atoi (&buf[PID]);
- p->ppid = atoi (&buf[PPID]);
-
- p->tty = newstr(&buf[TTY]);
- if (*p->tty == '?')
- *p->tty = '\0';
-
- p->info = newstr (&buf[INFO]);
- p->printed = 0;
-
- #ifdef CPU
- p->cputime = to_seconds (&buf[CPU]);
- #endif
- #ifdef WAITCH
- if (sscanf (&buf[WAITCH], "%x", &p->channel) != 1)
- p->channel = 0;
- #endif
-
- #if 0
- if (p->pid != 1 && p->ppid == 1 && strncmp(p->info, "/etc/init", 9) == 0)
- continue;
- else
- proc[maxproc++] = p;
- #else
- proc[maxproc++] = p;
- #endif
- }
- pclose (f);
-
- #ifdef CPU
- if (cpu_diff > 0)
- {
- sleep (cpu_diff);
-
- sprintf (buf, "exec %s", PS_COM);
- f = popen (buf, "r");
- if (f == 0)
- {
- fprintf (stderr, "%s: couldn't run ps\n", O_programname);
- exit (1);
- }
-
- fgets (buf, LINMAX, f);
- for (;;)
- {
- fgets (buf, LINMAX, f);
- if (feof (f)) break;
- #ifdef ultrix
- zap_flags (buf);
- #endif
- pid = atoi (&buf[PID]);
- for (i = 0; i < maxproc; i++)
- if (proc[i]->pid == pid)
- proc[i]->cputime -= to_seconds (&buf[CPU]);
- }
- pclose (f);
- }
- #endif
-
- sort ();
- (void) maxlev (0, 0, 0);
-
- for (i = 0; i < maxproc; i++)
- print_pp (i, 0);
- return 0;
- }
- @EOF
-
- chmod 664 tps.c
-
- exit 0
-
-