v05i084: submission to comp.sources.misc
Paul Lew
lew at gsg.UUCP
Mon Dec 19 10:18:22 AEST 1988
Posting-number: Volume 5, Issue 84
Submitted-by: "Paul Lew" <lew at gsg.UUCP>
Archive-name: pt.bsd
Newsgroups: comp.sources.misc
Keywords: ps BSD process tree
Message-ID: <290 at gsg.UUCP>
Date: 16 Dec 88 17:39:57 GMT
Organization: General Systems Group, Inc., Salem, NH
Lines: 511
ptree,pt: BSD ps backend filter to display process tree
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# README
# ptree.c
# Kill
# This archive created: Fri Dec 16 12:22:07 1988
export PATH; PATH=/bin:$PATH
echo shar: extracting "'README'" '(2009 characters)'
if test -f 'README'
then
echo shar: will not over-write existing file "'README'"
else
sed 's/^ X//' << \SHAR_EOF > 'README'
X Ptree Version 1.0 05/24/88
X
XIntroduction:
X
X ptree is a backend filter for BSD 'ps' command. It reads the
X output from ps and produces process tree graph on the standard
X output with each process indented under its parent. This program
X was inspired by the 'utree' program for system V from Brandon
X Allbery. The following is an example:
X
X $ ptree ag | grep -v getty
X USER STAT TTY TIME COMMAND
X lew I i14 0:09 -Tcsh (Tcsh)
X lew I i14 0:31 | emacs
X lew I p0 0:00 | | /usr/local/emacs/etc/loadst -n 60
X alice I i17 0:03 -csh (csh)
X lew I i18 0:08 -Tcsh (Tcsh)
X lew S i18 0:09 | screen -e?]
X lew I p1 0:06 | | -bin/Tcsh (Tcsh)
X lew S p2 0:07 | | -bin/Tcsh (Tcsh)
X domino S i26 0:05 -csh (csh)
X domino S i26 0:00 | lprint -f /usr/local/bin/lprint -n BigBucks
X domino S i26 0:00 | | dcat -d 3 -b 128
X mxt I i27 0:02 -csh (csh)
X mxt I i27 0:03 | mail -f
X mxt I i27 0:00 | | sh -c /usr/ucb/more
X mxt I i27 0:00 | | | /usr/ucb/more
X
X This is not 'yet another setuid program'. You dont have to be the
X root to use it. This is the main reason to write it as a filter.
X May be BSD can incorporate this into real 'ps' on future release.
X
X Kill is a script which uses 'sf' (shell form in comp.sources.unix)
X to allow one to send signals to processes by context.
X
XManual:
X
X There is no man page to it, type: 'pt H' will give you simple help
X message. If you know how 'ps' works then you dont need a manual,
X if you dont, this might not be useful to you.
X
XBuild:
X
X cc -o ptree ptree.c
X ln ptree pt
X
XCopyright:
X
X No copyright, complete in public domain. Do whatever you like with
X it. If you can make money from it, great for you.
X
X----------------------------------------------------------------------
XPaul Lew {olivea,harvard,decvax}!gsg!lew (UUCP)
XGeneral Systems Group, 5 Manor Parkway, Salem, NH 03079 (603) 893-1000
SHAR_EOF
if test 2009 -ne "`wc -c < 'README'`"
then
echo shar: error transmitting "'README'" '(should have been 2009 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'ptree.c'" '(8883 characters)'
if test -f 'ptree.c'
then
echo shar: will not over-write existing file "'ptree.c'"
else
sed 's/^ X//' << \SHAR_EOF > 'ptree.c'
Xstatic char *Sccsid = "(File: %M% Ver: %I% Update: %G% %U%)";
X/*+F***********************************************************************
X*
X* File name: ptree.c
X*
X* Author: Paul Lew, General Systems Group, Inc. Salem, NH
X* Created at: 05/22/88 16:10 PM
X* Last update: 05/24/88 08:54 PM (Edition: 26)
X*
X* Description: This program will parse output of 'ps' command and display
X* the output with process indented under their parents for
X* the easy identification.
X*
X* Environment: 4.2 BSD Unix (Pyramid OSx 4.1)
X*
X* Usage: ptree [HPacgxt#]
X*
X* Update History:
X*
X* Date Description By
X* -------- ------------------------------------------------ ---
X* 05/22/88 Initial version Lew
X*
X* Routines included:
X*
X* build_offset build offset from 1st line of ps output
X* save_addr return addr of Save array with pid = pid
X* add_child add child to parent, if exists, add to end of sibling
X* print_result display result
X* print_process print a given process sub-tree
X* dump_save dump save structure for debugging
X* procarg return command argument for ps command
X* usage display help message
X*
X* Build: cc -o ptree ptree.c <CR>
X*
X**-F**********************************************************************/
X
X#include <stdio.h>
X#include <pwd.h>
X
X#define YES 1
X#define NO 0
X
X#define MAXLINE 200
X
Xstruct save {
X struct save *so_parent; /* pointer to parent */
X struct save *so_sibling; /* pointer to 1st sibling */
X struct save *so_child; /* pointer to 1st child */
X int so_uid; /* user ID */
X char so_name[9]; /* user name */
X int so_pid; /* pid */
X int so_ppid; /* parent pid */
X char *so_buffer; /* pointer to ps output */
X } Save [MAXLINE];
X
Xchar *Version = "Version 1.0 05/24/88 00:51 AM";
Xchar *Author = "Paul Lew, lew at gsg.uucp";
X
Xint Line; /* # of output line from ps */
Xint Print_me = NO; /* if NO, dont print my processes */
Xint Print_pid = NO; /* if YES, output PID */
Xchar Command [80];
Xint My_pid; /* my process id */
X
Xint Uid_offset;
Xint Pid_offset;
Xint Ppid_offset;
Xint End_ppid;
Xint Stat_offset;
Xint Tyy_offset;
Xint Command_offset;
X
Xstruct save *save_addr ();
Xchar *procarg ();
X
Xextern FILE *popen ();
Xextern char *malloc (), *calloc ();
X
X/*-------------------------------------------------------------05/23/88-+
X| |
X| M a i n R o u t i n e S t a r t s H e r e |
X| |
X+----------------------------------------------------------------------*/
Xmain (argc, argv)
Xint argc;
Xchar **argv;
X {
X FILE *pfd; /* file descriptor for popen() */
X char *p; /* temp pointer to malloced buffer */
X register int i; /* loop index */
X register struct save *svp;
X
X p = procarg (argc, argv);
X sprintf (Command, "ps lw%s", p);
X if ((pfd = popen (Command, "r")) == NULL) {
X fprintf (stderr, "can not execture ps\n");
X exit (1);
X }
X for (Line=0; Line<MAXLINE; Line++) {
X p = malloc (BUFSIZ);
X if (p == NULL) {
X perror ("malloc");
X exit (1);
X }
X if (fgets (p, BUFSIZ, pfd) == NULL) break;
X Save[Line].so_buffer = p;
X if (Line == 0) build_offset (p);
X else /* prevent CP data being processed */
X p[End_ppid] = '\0';
X }
X pclose (pfd);
X for (i=1; i<Line; i++) {
X struct passwd *pwp;
X svp = &Save[i];
X svp->so_pid = atoi (&svp->so_buffer[Pid_offset]);
X svp->so_ppid = atoi (&svp->so_buffer[Ppid_offset]);
X svp->so_uid = atoi (&svp->so_buffer[Uid_offset]);
X pwp = getpwuid (svp->so_uid);
X strncpy (svp->so_name, pwp->pw_name, 8);
X }
X for (i=1; i<Line; i++) {
X struct save *p;
X svp = &Save[i];
X svp->so_parent = p = save_addr (svp->so_ppid);
X if (p) {
X add_child (p, svp);
X }
X }
X print_result ();
X#ifdef DEBUG
X dump_save ();
X#endif
X exit (0);
X }
X
X/*-------------------------------------------------------------05/23/88-+
X| |
X| build_offset : build offset from 1st line of ps output |
X| |
X+----------------------------------------------------------------------*/
Xbuild_offset (buf)
Xchar *buf; /* header line */
X {
X char *p = buf;
X for (p=buf; *p != '\0'; p++) {
X if (strncmp ("UID", p, 3) == 0) Uid_offset = p-buf;
X else if (strncmp (" PID ", p, 6) == 0) Pid_offset = p-buf;
X else if (strncmp (" PPID ", p, 6) == 0) Ppid_offset = p-buf;
X else if (strncmp ("STAT", p, 4) == 0) Stat_offset = p-buf;
X else if (strncmp ("TTY", p, 3) == 0) Tyy_offset = p-buf;
X else if (strncmp ("COMMAND",p, 7) == 0) Command_offset = p-buf;
X }
X End_ppid = Ppid_offset + 5;
X }
X
X/*-------------------------------------------------------------05/23/88-+
X| |
X| save_addr : return addr of Save array with pid = pid |
X| |
X+----------------------------------------------------------------------*/
Xstruct save *
Xsave_addr (pid)
Xint pid;
X {
X register int i;
X for (i=1; i<Line; i++) {
X if (Save[i].so_pid == pid) return (&Save[i]);
X }
X return (NULL); /* not found */
X }
X
X/*-------------------------------------------------------------05/23/88-+
X| |
X| add_child : add child to parent, if exists, add to end of sibling |
X| |
X+----------------------------------------------------------------------*/
Xadd_child (parent, child)
Xstruct save *parent;
Xstruct save *child;
X {
X if (parent->so_child == NULL) {
X parent->so_child = child;
X }
X else {
X struct save *tp = parent->so_child;
X while (tp->so_sibling != NULL) tp = tp->so_sibling;
X tp->so_sibling = child;
X }
X child->so_sibling = NULL;
X }
X
X/*-------------------------------------------------------------05/23/88-+
X| |
X| print_result : display result |
X| |
X+----------------------------------------------------------------------*/
Xprint_result ()
X {
X register int i;
X struct save *svp;
X
X My_pid = getpid ();
X printf ("%s USER %s", Print_pid ? " PID " : "",
X &Save[0].so_buffer[Stat_offset]);
X for (i=1; i<Line; i++) {
X svp = &Save[i];
X if (svp->so_parent != NULL) {
X if (svp->so_pid != 0)
X continue;
X }
X print_process (0, svp);
X }
X }
X
X/*-------------------------------------------------------------05/23/88-+
X| |
X| print_process : print a given process sub-tree |
X| |
X+----------------------------------------------------------------------*/
Xprint_process (level, svp)
Xint level;
Xstruct save *svp;
X {
X struct save *tp;
X register int i;
X
X if (!Print_me && svp->so_pid == My_pid) return;
X if (Print_pid) printf ("%5d ", svp->so_pid);
X printf ("%8s %.*s", svp->so_name, Command_offset - Stat_offset,
X &svp->so_buffer[Stat_offset]);
X for (i=0; i<level; i++) printf ("| ");
X printf ("%s", &svp->so_buffer[Command_offset]);
X if ((tp = svp->so_child) != NULL) {
X while (tp != NULL) {
X if (tp != svp) /* avoid infinit recursion */
X print_process (level+1, tp);
X tp = tp->so_sibling;
X }
X }
X }
X
X/*-------------------------------------------------------------05/23/88-+
X| |
X| dump_save : dump save structure for debugging |
X| |
X+----------------------------------------------------------------------*/
X#ifdef DEBUG
Xdump_save ()
X {
X register int i;
X register struct save *tp;
X
X for (i=1; i<Line; i++) {
X tp = &Save[i];
X printf ("parent=%08x(x) ", tp->so_parent);
X printf ("sibling=%08x(x) ", tp->so_sibling);
X printf ("child=%08x(x) ", tp->so_child);
X printf ("PID=%05d PPID=%05d\n", tp->so_pid, tp->so_ppid);
X }
X printf ("command: [%s]\n", Command);
X }
X#endif
X
X/*------------------------------------------------------------05/24/88--+
X| |
X| procarg : return command argument for ps command |
X| |
X+----------------------------------------------------------------------*/
Xchar *
Xprocarg (argc, argv)
Xint argc;
Xchar **argv;
X {
X static char buf [20] = "";
X register char c;
X register char *p = argv[1];
X int i = 0;
X
X if (argc == 1) return (buf);
X while ((c = *p++) != '\0') {
X switch (c) {
X case 'P': Print_me = YES; break;
X case 'p': Print_pid = YES; break;
X case 'H': usage (argv[0]); exit (0);
X case 'a': case 'c': case 'e': case 'g':
X case 'x': buf[i++] = c; break;
X case 't': strcpy (&buf[i], p-1); return (buf);
X default: usage (argv[0]); exit (1);
X }
X }
X buf [i] = '\0';
X return (buf);
X }
X
X/*-------------------------------------------------------------07/01/86-+
X| |
X| usage : display help message |
X| |
X+----------------------------------------------------------------------*/
Xstatic usage (pname)
Xchar *pname; /* program name */
X {
X fprintf (stderr, "%s %s %s\n", pname, Version, Author);
X fprintf (stderr, "Usage: %s [acepgtxHP]\n", pname);
X fprintf (stderr, "where options:\n");
X fprintf (stderr, " H display this help message\n");
X fprintf (stderr, " P print processes created by me\n");
X fprintf (stderr, " p output PID\n");
X fprintf (stderr, " a,c,e,g,t,x will be passed to ps, if t is\n");
X fprintf (stderr, " specified, all the rest char in\n");
X fprintf (stderr, " the argument will be copied\n");
X }
SHAR_EOF
if test 8883 -ne "`wc -c < 'ptree.c'`"
then
echo shar: error transmitting "'ptree.c'" '(should have been 8883 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Kill'" '(2925 characters)'
if test -f 'Kill'
then
echo shar: will not over-write existing file "'Kill'"
else
sed 's/^ X//' << \SHAR_EOF > 'Kill'
X#! /bin/csh -f
X#
X#- Kill - kill process with shell form interface
X#-
X#- This program will use shell form to display current user's
X#- process generated by ptree command. You can tab to the
X#- desired process and select proper signal to be sent to the
X#- process. Press return will trigger the action.
X#-
X# Author: Paul Lew, General Systems Group, Inc.
X# Created at: 05/12/88 07:56 PM
X# Last update: 07/26/88 10:56 AM (Edition: 32)
X#
X#- Usage: Kill [string]
X#- where option:
X#- string if specified, will do 'ptree ax | grep string'
X#- and display only matched process.
X#
Xset tmpfile = "/tmp/tmpfile.$$"
Xset sofile = "/tmp/sofile.$$"
Xset ptfile = "/tmp/ptfile.$$"
X#---------------------------------------------------------------#
X# Display help if requested by user #
X#---------------------------------------------------------------#
Xswitch ( "$1" )
X case -H[xX]:
X set echo; set verbose; shift
X breaksw
X case -H*:
X show_help `which $0` $1
X goto end
X default:
X endsw
X#---------------------------------------------------------------#
X# Process Arguments #
X#---------------------------------------------------------------#
Xset greparg = '.'
Xset ptflag = 'x'
Xif ( "$1" != '' ) then
X set greparg = $1
X set ptflag = 'ax'
X endif
X#---------------------------------------------------------------#
X# Create sf description file #
X#---------------------------------------------------------------#
Xpt p$ptflag > $tmpfile
Xtr '~' '?' < $tmpfile | sed -n \
X -e '1s/COMMAND/SIGNAL &/p;1d' \
X -e '/Kill/d' \
X -e "/$greparg/"'{;s/^\(..............................\)\(.*\)$/\1~~~~~~ \2/p;}' \
X > $ptfile
Xsed 's/^......//' $ptfile | colrm 80 > $tmpfile
X@ lcount = `cat $tmpfile | wc -l`
X@ lcount--
Xif ( $lcount == 0 ) then
X echo "...Pattern $greparg not found in pt list, aborted..."
X goto end
X endif
Xcat << cat_eof >> $tmpfile
X
X[TAB (next process), SPACE (next signal), - (no signal), RETURN (execute)]
X
Xcat_eof
X@ i = 0
Xset sig = "/- /HUP/INT/QUIT/ILL/TRAP/ABRT/EMT/FPE/KILL/BUS/SEGV/SYS"
Xset sig = "$sig/PIPE/ALRM/TERM/URG/STOP/TSTP/CONT/CHLD/TTIN/TTOU/IO/XCPU"
Xset sig = "$sig/XFSZ/VTALRM/PROF/USR1/USR2/PWR/LOST/"
Xwhile ( $i < $lcount )
X @ i++
X echo ".v=var$i.s=$sig." >> $tmpfile
X end
X#---------------------------------------------------------------#
X# run sf to get user input #
X#---------------------------------------------------------------#
Xsf -u -o $sofile < $tmpfile
Xif ( ! -e $sofile ) goto end
Xsource $sofile
X@ i = 0
Xwhile ( $i < $lcount )
X @ i++
X set var = `eval echo \$var$i`
X if ( "$var" != '-' ) then
X @ line = $i + 1
X kill -$var `sed -n "$line"'s/^ *\([0-9]*\).*$/\1/p' $ptfile`
X endif
X end
X#---------------------------------------------------------------#
X# Clean up and exit here... #
X#---------------------------------------------------------------#
Xend:
X /bin/rm -f $tmpfile $sofile $ptfile
X unset tmpfile sofile ptfile i lcount var line greparg ptflag
SHAR_EOF
if test 2925 -ne "`wc -c < 'Kill'`"
then
echo shar: error transmitting "'Kill'" '(should have been 2925 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0
More information about the Comp.sources.misc
mailing list