beta test release of crash 2.0 for SCO Xenix

John F Haugh II jfh at rpp386.cactus.org
Thu Feb 28 02:42:08 AEST 1991


This is the latest version of the crash dump analyzer for SCO Xenix.
It was started in 1988 because SCO doesn't include the crash command.
I have added a few features recently because of discussions in
comp.unix.wizards about snooping around the kernel.  I use this command
to determine what is wedged and why.

As always, constructive comments are appreciated and earn you a place
in the README file.  Flames are ignored for the most part.

Unshar and enjoy!
--
#! /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:
#	README
#	Makefile
#	crash.c
#	interact.c
#	files.c
#	inodes.c
#	mounts.c
#	procs.c
#	texts.c
#	user.c
#	vars.c
#	stats.c
#	bufs.c
#	syms.c
#	devs.c
#	expr.c
#	od.c
#	ttys.c
#	crash.h
# This archive created: Wed Feb 27 09:38:49 1991
# By:	John F Haugh II (River Parishes Programming, Austin TX)
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'README'" '(8001 characters)'
if test -f 'README'
then
	echo shar: "will not over-write existing file 'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
Xcrash(1L)                       Version 2.0                     08/11/88
X
XIntroduction
X
XCrash is a utility for examining kernel tables while the system is
Xrunning, or if there is a facility for taking crash dumps, examining the
Xsystem after it has crashed.  SCO does not provide a crash dump facility
Xat this time, so that functionality is not present.
X
XThe kernel structures which can be examined at present are:
X
X	block buffer headers
X	open file table entries
X	active inode table entries
X	mounted file system table entries
X	process table entries
X	system statistics such as name, version, age
X	active and sticky bit text table entries
X	tty structures
X	system namelist
X	per process user page information
X	tunable parameters
X	arbitrary kernel memory addresses
X
XUsing this information, it is possible to determine what files a given
Xprocess is using, what device they reside on, who owns them and where
Xthe file pointer is currently positioned.  Other information on running
Xprocesses may also be determined.
X
XThis version of crash differs from most other versions, such as that
Xproduced by AT&T for their UNIX(tm) systems, in that swapped user pages
Xmay be printed and the name for swapped processes is given.  Also, not
Xall of the aliases which are listed in the manual page from AT&T are
Xprovided.  A number of commands have been left out, and some of the
Xoptions for the included commands have been omitted as well.
X
XCommands
X
XMost commands take a list of table entries, which if not present
Xdefaults to all elements in the table.
X
XPrint Buffer Headers
XSyntax:	buf, b
X
XPrints the selected block buffer headers.
X
XExample:
X> buf 0 1 2 3 4
X BUF MAJ  MIN    BLOCK FLAGS
X   0 001 0047    20925 read done
X   1 001 0037     2817 read done
X   2 001 0050     2801 read done
X   3 001 0037    15175 read done
X   4 001 0050        6 done
X
XPrint Open File Table Entries
XSyntax: file, f
X
XPrints the selected open file table entries, with cross references
Xto the associated inodes, and the current file pointer.
X
XExample:
X> file 0 1 2 3 4
XSLOT    FLAG          COUNT  INODE      OFFSET
X   0    001 R             1      9           0
X   1    003 RW            3      3          18
X   2    003 RW            7     11       26800
X   3    002  W            2      4         169
X   4    001 R             1      8           0
X
XDisplay Command Summary
XSyntax: help, h, ?
X
XPrints the list of currently available commands and the aliases
Xfor them.
X
XExample:
X> help
Xcommand summary
X
Xbuf (b)        - buffer headers
Xfile (f)       - open files
Xhelp (h,?)     - list commands
Xinode (ino,i)  - active inodes
Xmount (m)      - mounted file systems
Xproc (p)       - active and defunct processes
Xquit (q,^D)    - exit crash
Xstat (s)       - crash statistics, age, time
Xtext (t)       - active and sticky bit text segments
Xuser (u)       - user page information
Xvar (v)        - tunable parameters
X
XDisplay Active Inode Table Entries
XSyntax: inode, ino, i
X
XPrints selected active inode table entries giving device, file
Xsize, permissions, and owners.  Cross referenced from mount and
Xfile tables.
X
XExample:
X> inode 0 2 6 8 20
XSLOT MAJ  MIN INUMB REF LINK  UID  GID     SIZE    MODE SMAJ SMIN FLAGS
X   0 001 0050     2   5   13    0    0      464 d---755    -    -
X   2 001 0050    44   1    1    3    3    13472 f---700    -    - txt
X   6 001 0050   204   1    2    0    0       32 d---777    -    - mnt
X   8 001 0050    87   2    1   10   10        0 c---666 0004 0002
X  20 001 0050   471   1    1    3    3    50102 f---711    -    - acc txt
X
XDisplay Mounted File System Table Entries
XSyntax: mount, m
X
XPrints the system entries for mounted on file systems.  The
Xdevice, mount point, file system sizes and free blocks and inodes
Xare displayed.
X
XExample:
X> mount
XSLOT  MAJ  MIN  INODE  BUF  VOLUME  PACK   BLOCKS INODES  BFREE  IFREE
X   0    1  050      0   10                   7163   1808   1237   1251
X   1    1  037      6  230  usr     rpp386  34000  17024   1320  14238
X   2    1  047      7  245                  22950  15024   5499   9800
X   3    2  064     23  387                   1200    320    210     50
X
XDisplay Process Table Entries
XSyntax: proc, p
X
XPrints selected running and defunct process information.  The process
Xids, user ids, CPU usage, scheduling priority and wait event are
Xdisplayed.  The process name is determined by locating the user page.
X
XExample:
X> proc 0 1 2 3 4
XSLT ST  PID  PPID  PGRP   UID  EUID PRI CPU    EVENT NAME       FLAGS
X  0 s     0     0     0     0     0   0  15    16c5c swapper    incore sched
X  1 s     1     0     0     0     0  30   0     eeac init       incore text
X  2 s  9389     1  9389   100   100  30   0     ef54 csh        incore text
X  3 s    31     1     0     0     0  26   0     5eac logger     swapped
X  4 s    30     1     0     0     0  40   0  6000000 update     incore text
X
XExit Crash Command
XSyntax: quit, q, ^D
X
XExits Crash.
X
XExample:
X> quit
X$
X
XPrint System Statics
XSyntax: stat, s
X
XPrints information regarding system name, operating system release, version,
Xdate of crash, and uptime at time of crash.
X
XExample:
X> stat
X	sysname: XENIX
X	nodename: rpp386
X	release: 2.2.1
X	version: SysV
X	machine: i80386
X	time of crash: Thu Aug 11 11:18:00 1988
X	age of system: 35 days, 23 hrs., 7 mins.
X
XPrint Text Table Entries
XSyntax: text, t
X
XPrints current text table entries.  Cross references to inode number
Xand process table entry and gives the number of processes which are
Xcurrently referencing this table entry.
XExample:
X> text 0 1 2 3 4
XSLOT  INODE  REF  LDREF  PROC  SWAPLO+   SIZE  FLAGS
X   0      2    1      1     1        0      0  write
X   1     20    2      1     9        0      0  write
X   2      5    1      1     4        0      0  write
X   3     10    1      0     0        0      0  write
X   4     21    1      1    10        0      0  write
X
XPrint Per Process User Page Information
XSyntax: user, u
X
XPrints the user page for the current process or a group of processes.
XThe argument is the process table slot.  If omitted, the currently
Xrunning process, which will invariably be crash, user page will be
Xdisplayed.  Information includes user and system times, user and
Xgroup ids, file I/O, system accounting and open file information.
XProvides a list of currently open files by file table entry number.
X
XExample:
X> user
XPER PROCESS USER AREA:
XUSER ID's:	uid: 100, gid: 0, real uid: 100, real gid: 0
XPROCESS TIMES:	user: 16, sys: 22, child user: 0, child sys: 0
XPROCESS MISC:	proc slot: 10, cntrl tty: maj(0) min(0)
XIPC:		locks: unlocked
XFILE I/O:	user addr: 25703640, file offset: 100665344, bytes: 1892,
X		segment: user, umask: 22, ulimit: 2097152
XACCOUNTING:	command: crash, memory: 1987167, type: exec
X		start: Thu Aug 11 11:28:10 1988
XOPEN FILES:	file desc:     0   1   2   3   4   5
X		file slot:    11  13  13  18  19  20
X
XPrint Tunable Parameter Information
XSyntax: var, v
X
XDisplays the tunable parameter values which were used at the time
Xof system generation.  Included are number of open files, processes
Xper user, inodes, mounts, pure text entries and other related
Xinformation.
X
XExample:
X> var
Xbuffers	  512
Xcalls	   30
Xinodes	  100
Xe_inodes  100
Xfiles	  100
Xe_files	  100
Xmounts	    8
Xe_mounts    8
Xprocs	   60
Xe_procs	   16
Xtexts	   40
Xe_texts	   40
Xclists	   64
Xsabufs	   64
Xmaxproc	   30
Xhashbuf	  512
Xhashmask  511
X
XCaveats and Features
X
XThis release of crash is known to run under SCO Xenix 2.2.3.  No other
Xports are presently known of.  For the most part, porting to a different
Xrelease of Xenix should be quite painless.  The principle changes are
Xlikely to be in the user area, process table entries, and system namelist
Xfunctions.
X
XNone of the options are presently implemented.  Commands which have been
Ximplemented have only one format.
X
XMost of the commands are available as command line options.  Use the one
Xletter command alias as the command line option.  The output defaults
Xto what it would be if that one letter alias were issued to crash as a
Xcommand.  Multiple flags may be given.  When in doubt, read the source.
SHAR_EOF
if test 8001 -ne "`wc -c < 'README'`"
then
	echo shar: "error transmitting 'README'" '(should have been 8001 characters)'
fi
fi
echo shar: "extracting 'Makefile'" '(1540 characters)'
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
X# Copyright 1988, John F. Haugh II
X# All rights reserved.
X#
X# Permission is granted to copy and create derivative works for any
X# non-commercial purpose, provided this copyright notice is preserved
X# in all copies of source code, or included in human readable form
X# and conspicuously displayed on all copies of object code or
X# distribution media.
X#
X#	%W%	%U%	%G%
X#
X# Your favorite Bourne Shell and Mine ...
XSHELL=/bin/sh
X# A list of all object files which need to be made
XOBJS =	crash.o interact.o files.o inodes.o mounts.o procs.o texts.o \
X	user.o vars.o stats.o bufs.o syms.o devs.o expr.o od.o ttys.o
X# A list of C files and such for sharchiving
XFILES =	README Makefile \
X	crash.c interact.c files.c inodes.c mounts.c procs.c texts.c \
X	user.c vars.c stats.c bufs.c syms.c devs.c expr.c od.c ttys.c \
X	crash.h
X# C flags, suitable for debugging or production.
XCFLAGS = -c -Ox -g
XGFLAGS = -t -r2
X
Xcrash:	$(OBJS)
X	cc -o crash -g $(OBJS)
X
Xclean:
X	rm -f *.o a.out
X
Xclobber:	clean
X	rm -f crash core
X
Xnuke:	clobber
X	-for file in * ; do \
X		if [ -f s.$$file -a ! -f p.$$file ] ; then \
X			rm -f $$file ;\
X		fi ;\
X	done
X
XREADME:
X	get -p $(GFLAGS) s.README > README
X
Xshar:	$(FILES)
X	shar -a $(FILES) > crash.shar
X
Xcrash.o:	crash.h crash.c
X
Xinteract.o:	interact.c
X
Xfiles.o:	crash.h files.c
X
Xinodes.o:	crash.h inodes.c
X
Xmounts.o:	crash.h mounts.c
X
Xprocs.o:	crash.h procs.c
X
Xstats.o:	crash.h stats.c
X
Xtexts.o:	crash.h texts.c
X
Xuser.o:	crash.h user.c
X
Xvars.o:	crash.h vars.c
X
Xbufs.o:	crash.h bufs.c
X
Xdevs.o:	crash.h devs.c
X
Xttys.o:	crash.h ttys.c
X
SHAR_EOF
if test 1540 -ne "`wc -c < 'Makefile'`"
then
	echo shar: "error transmitting 'Makefile'" '(should have been 1540 characters)'
fi
fi
echo shar: "extracting 'crash.c'" '(4818 characters)'
if test -f 'crash.c'
then
	echo shar: "will not over-write existing file 'crash.c'"
else
sed 's/^X//' << \SHAR_EOF > 'crash.c'
X/*
X * Copyright 1988, 1991, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)crash.c	2.1	07:11:33	2/27/91";
X#endif
X
X#include <sys/param.h>
X#include <sys/sysmacros.h>
X#include <sys/types.h>
X#include <sys/page.h>
X#include <sys/seg.h>
X#include <sys/proc.h>
X#include <sys/signal.h>
X#include <sys/dir.h>
X#include <sys/user.h>
X#include <sys/var.h>
X#include <sys/utsname.h>
X#include <sys/conf.h>
X#include <fcntl.h>
X#include <stdio.h>
X#include "crash.h"
X
Xint	memfd;
Xint	kmemfd;
Xint	swapfd;
X
Xint	bflag;
Xint	fflag;
Xint	iflag;
Xint	mflag;
Xint	pflag;
Xint	sflag;
Xint	tflag;
Xint	uflag;
Xint	vflag;
X
Xint	anyflag;
X
Xstruct	var	v;
Xstruct	file	*files;
Xstruct	inode	*inodes;
Xstruct	text	*texts;
Xstruct	proc	*procs;
Xstruct	mount	*mounts;
Xstruct	buf	*bufs;
Xstruct	buf	*bufstart;
Xstruct	cdevsw	*Cdevsw;
Xstruct	bdevsw	*Bdevsw;
Xint	Cdevcnt;
Xint	Bdevcnt;
Xstruct	user	user;
Xdaddr_t	swplo;
Xstruct	utsname	utsname;
Xtime_t	ktime;
Xtime_t	klbolt;
X
Xstruct	xlist	namelist[] = {
X	{ 0, 0, 0, "_v" },
X	{ 0, 0, 0, "_file" },
X	{ 0, 0, 0, "_inode" },
X	{ 0, 0, 0, "_proc" },
X	{ 0, 0, 0, "_text" },
X	{ 0, 0, 0, "_mount" },
X	{ 0, 0, 0, "_bufstrt" },
X	{ 0, 0, 0, "_swplo" },
X	{ 0, 0, 0, "_time" },
X	{ 0, 0, 0, "_lbolt" },
X	{ 0, 0, 0, "_utsname" },
X	{ 0, 0, 0, "_u" },
X	{ 0, 0, 0, "_cdevcnt" },
X	{ 0, 0, 0, "_cdevsw" },
X	{ 0, 0, 0, "_bdevcnt" },
X	{ 0, 0, 0, "_bdevsw" },
X	{ 0, 0, 0, (char *) 0 }
X};
X
Xusage ()
X{
X	fprintf (stderr, "usage: crash -bfimpstv [ -N namelist ] ");
X	fprintf (stderr, "[ -C corefile ] [ -S swapfile ]\n");
X	exit (1);
X}
X
Xr_read (fd, buf, n)
Xint	fd;
Xchar	*buf;
Xint	n;
X{
X	int	i;
X
X	if ((i = read (fd, buf, n)) == -1) {
X		perror ("error on read");
X		return (-1);
X	} else
X		return (i);
X}
X
Xlong	l_lseek (fd, offs, whence)
Xint	fd;
Xlong	offs;
Xint	whence;
X{
X	long	i;
X	long	lseek ();
X
X	if ((i = lseek (fd, offs, whence)) == -1L) {
X		perror ("error on lseek");
X		return (-1);
X	} else
X		return (i);
X}
X
Xmain (argc, argv)
Xint	argc;
Xchar	**argv;
X{
X	char	newname[10];
X	char	*namefile = "/xenix";
X	char	*corefile = "/dev/mem";
X	char	*kmemfile = "/dev/kmem";
X	char	*swapfile = "/dev/swap";
X	int	c;
X	extern	int	optind;
X	extern	char	*optarg;
X
X	setbuf (stdout, NULL);
X	setbuf (stderr, NULL);
X
X	while ((c = getopt (argc, argv, "bfimpstuvN:C:S:")) != EOF) {
X		switch (c) {
X			case 'b':
X				bflag++;
X				anyflag++;
X				break;
X			case 'C':
X				corefile = optarg;
X				kmemfile = optarg;
X				break;
X			case 'f':
X				fflag++;
X				anyflag++;
X				break;
X			case 'i':
X				iflag++;
X				anyflag++;
X				break;
X			case 'm':
X				mflag++;
X				anyflag++;
X				break;
X			case 'N':
X				namefile = optarg;
X				break;
X			case 'p':
X				pflag++;
X				anyflag++;
X				break;
X			case 's':
X				sflag++;
X				anyflag++;
X				break;
X			case 'S':
X				swapfile = optarg;
X				break;
X			case 't':
X				tflag++;
X				anyflag++;
X				break;
X			case 'u':
X				uflag++;
X				anyflag++;
X				break;
X			case 'v':
X				vflag++;
X				anyflag++;
X				break;
X			default:
X				usage ();
X		}
X	}
X	if (xlist (namefile, namelist) != 0) {
X		perror ("pstat: namelist");
X		exit (1);
X	}
X	if (initsyms (namefile)) {
X		fprintf (stderr, "unable to initialize symbol table\n");
X		exit (1);
X	}
X	if ((memfd = open (corefile, O_RDONLY)) < 0) {
X		perror ("pstat: corefile");
X		exit (1);
X	}
X	if ((kmemfd = open (kmemfile, O_RDONLY)) < 0) {
X		perror ("pstat: kmemfile");
X		exit (1);
X	}
X	if ((swapfd = open (swapfile, O_RDONLY)) < 0) {
X		perror ("pstat: swapfile");
X		exit (1);
X	}
X	l_lseek (kmemfd, namelist[NM_V].xl_value, 0);
X	r_read (kmemfd, &v, sizeof v);
X	l_lseek (kmemfd, namelist[NM_SWPLO].xl_value, 0);
X	r_read (kmemfd, &swplo, sizeof swplo);
X
X	l_lseek (kmemfd, namelist[NM_CDEVCNT].xl_value, 0);
X	r_read (kmemfd, &Cdevcnt, sizeof Cdevcnt);
X	Cdevsw = (struct cdevsw *) malloc (Cdevcnt * sizeof *Cdevsw);
X	l_lseek (kmemfd, namelist[NM_CDEVSW].xl_value, 0);
X	r_read (kmemfd, Cdevsw, Cdevcnt * sizeof *Cdevsw);
X
X	l_lseek (kmemfd, namelist[NM_BDEVCNT].xl_value, 0);
X	r_read (kmemfd, &Bdevcnt, sizeof Bdevcnt);
X	Bdevsw = (struct bdevsw *) malloc (Bdevcnt * sizeof *Bdevsw);
X	l_lseek (kmemfd, namelist[NM_BDEVSW].xl_value, 0);
X	r_read (kmemfd, Bdevsw, Bdevcnt * sizeof *Bdevsw);
X
X	if (bflag)
X		prbufs ((int *) 0, 0);
X
X	if (fflag)
X		prfiles ((int *) 0, 0);
X
X	if (iflag)
X		prinodes ((int *) 0, 0);
X
X	if (mflag) 
X		prmounts ((int *) 0, 0);
X
X	if (pflag)
X		prprocs ((int *) 0, 0);
X
X	if (sflag)
X		prstats ((int *) 0, 0);
X
X	if (tflag)
X		prtexts ((int *) 0, 0);
X
X	if (uflag)
X		prusers ((int *) 0, 0);
X
X	if (vflag)
X		prvars ((int *) 0, 0);
X
X	if (! anyflag) {
X		interact ();
X		exit (0);
X	} else {
X		exit (0);
X	}
X}
SHAR_EOF
if test 4818 -ne "`wc -c < 'crash.c'`"
then
	echo shar: "error transmitting 'crash.c'" '(should have been 4818 characters)'
fi
fi
echo shar: "extracting 'interact.c'" '(5858 characters)'
if test -f 'interact.c'
then
	echo shar: "will not over-write existing file 'interact.c'"
else
sed 's/^X//' << \SHAR_EOF > 'interact.c'
X/*
X * Copyright 1988, 1991, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)interact.c	2.1	09:26:38	2/27/91";
X#endif
X
X#include <stdio.h>
X#include <string.h>
X#include <ctype.h>
X#include <setjmp.h>
X#include <signal.h>
X
Xextern	od ();
Xextern	prbufs ();
Xextern	prbdevs ();
Xextern	prcdevs ();
Xextern	prfiles ();
Xextern	prinodes ();
Xextern	prmounts ();
Xextern	prprocs ();
Xextern	prstats ();
Xextern	prtexts ();
Xextern	prusers ();
Xextern	prvars ();
Xextern	prdataaddr ();
Xextern	prsymbol ();
Xextern	prtextaddr ();
Xextern	prttys ();
Xextern	quit ();
Xextern	help ();
Xextern	int	errno;
X
Xjmp_buf	del;
Xint	delflag;
X
Xstruct	func {
X	void	(*f_func)();
X	char	*f_name;
X	enum { none, numbers, string } f_type;
X};
X
Xstruct	func	commands[] = {
X	{ prbufs, "b", numbers },
X	{ prbdevs, "bd", numbers },
X	{ prbdevs, "bdevsw", numbers },
X	{ prbufs, "buf", numbers },
X	{ prcdevs, "cd", numbers },
X	{ prcdevs, "cdevsw", numbers },
X	{ prdataaddr, "ds", string },
X	{ prfiles, "f", numbers },
X	{ prfiles, "file", numbers },
X	{ help, "h", none },
X	{ help, "help", none },
X	{ prinodes, "i", numbers },
X	{ prinodes, "ino", numbers },
X	{ prinodes, "inode", numbers },
X	{ prmounts, "m", numbers },
X	{ prmounts, "mount", numbers },
X	{ prsymbol, "nm", string },
X	{ od, "od", string },
X	{ prprocs, "p", numbers },
X	{ prprocs, "proc", numbers },
X	{ quit, "q", none },
X	{ quit, "quit", none },
X	{ prstats, "s", none },
X	{ prstats, "stat", none },
X	{ prtexts, "t", numbers },
X	{ prtexts, "text", numbers },
X	{ prtextaddr, "ts", string },
X	{ prttys, "tty", string },
X	{ prusers, "u", numbers },
X	{ prusers, "user", numbers },
X	{ prvars, "v", none },
X	{ prvars, "var", none },
X	{ 0, 0, none }
X};
X
Xhelp ()
X{
X	printf ("command summary\n\n");
X
X	printf ("buf (b)        - buffer headers\n");
X	printf ("file (f)       - open files\n");
X	printf ("help (h,?)     - list commands\n");
X	printf ("inode (ino,i)  - active inodes\n");
X	printf ("mount (m)      - mounted file systems\n");
X	printf ("proc (p)       - active and defunct processes\n");
X	printf ("quit (q,^D)    - exit crash\n");
X	printf ("stat (s)       - crash statistics, age, time\n");
X	printf ("text (t)       - active and sticky bit text segments\n");
X	printf ("user (u)       - user page information\n");
X	printf ("var (v)        - tunable parameters\n");
X}
X
Xquit ()
X{
X	exit (0);
X}
X
Xinterupt (sig)
Xint	sig;
X{
X	delflag = 1;
X	fflush (stdout);
X	fflush (stderr);
X	longjmp (del, sig);
X}
X
Xstatic int
Xnumber (cpp, value)
Xchar	**cpp;
Xint	*value;
X{
X	char	*cp = *cpp;
X	char	*end;
X	char	buf[16];
X	int	i;
X
X	while (*cp && isspace (*cp))
X		cp++;
X
X	for (i = 0;i < 15 && isdigit (*cp);i++, cp++)
X		buf[i] = *cp;
X
X	while (*cp && isspace (*cp))
X		cp++;
X
X	if (cp == *cpp)
X		return -1;
X
X	buf[i] = '\0';
X	i = (int) strtol (buf, &end, 0);
X	if (*end)
X		return -1;
X
X	*value = i;
X	*cpp = cp;
X	return 0;
X}
X
Xstatic int
Xrange (cpp, value, cnt)
Xchar	**cpp;
Xint	**value;
Xint	*cnt;
X{
X	int	min, max;
X	char	*cp = *cpp;
X
X	if (number (&cp, &min)) {
X		*cpp = cp;
X		return -1;
X	}
X	while (*cp && isspace (*cp))
X		cp++;
X
X	if (*cp == ',' || *cp == '\0') {
X		*((*value)++) = min;
X		(*cnt)--;
X		*cpp = cp;
X		return 0;
X	} else if (*cp != '-') {
X		*cpp = cp;
X		return -1;
X	}
X	cp++;
X
X	while (*cp && isspace (*cp))
X		cp++;
X
X	if (number (&cp, &max)) {
X		*cpp = cp;
X		return -1;
X	}
X	while (min <= max && (*cnt) > 0) {
X		*((*value)++) = min++;
X		(*cnt)--;
X	}
X	if ((*cnt) == 0 && min <= max)
X		return -1;
X
X	*cpp = cp;
X	return 0;
X}
X
Xlist (cp, items, max)
Xchar	*cp;
Xint	*items;
Xint	max;
X{
X	int	cnt = max;
X
X	/*
X	 * number lists are of the form
X	 *
X	 *	<list> ::= <range> | <list> ',' <range>
X	 *	<range> ::= <number> '-' <number> | <number>
X	 *	<number> ::= <one or more decimal digits>
X	 */
X
X	while (*cp && cnt > 0) {
X		while (*cp && isspace (*cp))
X			cp++;
X
X		if (range (&cp, &items, &cnt))
X			break;
X
X		if (*cp) {
X			if (*cp == ',')
X				cp++;
X			else
X				break;
X		}
X	}
X	if (*cp) {
X		printf ("error at '%.15s'\n", cp);
X		return -1;
X	}
X	return max - cnt;
X}
X
Xinteract ()
X{
X	int	i;
X	long	l;
X	int	cnt;
X	char	*cp;
X	char	*com;
X	char	*num;
X	char	buf[BUFSIZ];
X	int	items[100];
X
X	while (setjmp (del))		/* catch that first interupt */
X		fprintf (stderr, "\nq to quit\n");
X
X	signal (SIGINT, interupt);	/* and setup the handler */
X
X	while (fprintf (stderr, "> "), gets (buf) != (char *) 0) {
X		while (setjmp (del))
X			goto eh;
X
X		/*
X		 * find first non-white space character and skip if
X		 * a blank line
X		 */
X
X		for (com = buf;*com && (*com == ' ' || *com == '\t');com++)
X			;
X
X		if (*com == '\0')
X			continue;
X
X		/*
X		 * find the entire command word
X		 */
X
X		if (*com == '?') {
X			help ();
X			continue;
X		} else if (*com == '!') {
X			system (com + 1);
X			continue;
X		} else if (*com == '=') {
X			com++;
X			if (expr (&com, &l))
X				goto eh;
X			printf ("%d (%x)\n", l, l);
X			continue;
X		}
X		for (cp = com;*cp >= 'a' && *cp <= 'z';cp++)
X			;
X
X		if (*cp != '\0')
X			*cp++ = '\0';
X
X		for (i = 0;commands[i].f_name != (char *) 0;i++)
X			if (strcmp (commands[i].f_name, com) == 0)
X				break;
X
X		if (commands[i].f_name == (char *) 0)
X			goto eh;
X
X		if (commands[i].f_type == numbers) {
X			while (*cp && isspace (*cp))
X				cp++;
X
X			if ((cnt = list (cp, items, 100)) < 0)
X				goto eh;
X
X			(*commands[i].f_func) (cnt ? items:0, cnt);
X			continue;
X		} else if (commands[i].f_type == string) {
X			while (*cp && isspace (*cp))
X				cp++;
X
X			(*commands[i].f_func) (cp);
X			continue;
X		}
X
X		/*
X		 * common error handler.  get here if an error is found.
X		 */
Xeh:
X		if (delflag) {
X			putc ('\n', stderr);
X			delflag = 0;
X		}
X		fprintf (stderr, "eh?\n");
X		signal (SIGINT, interupt);
X	}
X}
SHAR_EOF
if test 5858 -ne "`wc -c < 'interact.c'`"
then
	echo shar: "error transmitting 'interact.c'" '(should have been 5858 characters)'
fi
fi
echo shar: "extracting 'files.c'" '(1868 characters)'
if test -f 'files.c'
then
	echo shar: "will not over-write existing file 'files.c'"
else
sed 's/^X//' << \SHAR_EOF > 'files.c'
X/*
X * Copyright 1988, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)files.c	1.2	22:55:32	2/21/91";
X#endif
X
X#include <sys/param.h>
X#include <sys/sysmacros.h>
X#include <sys/types.h>
X#include <sys/var.h>
X#include <sys/inode.h>
X#include <sys/file.h>
X#include <sys/page.h>
X#include <sys/seg.h>
X#include <sys/signal.h>
X#include <sys/dir.h>
X#include <sys/user.h>
X#include "crash.h"
X
Xprfiles (items, cnt)
Xint	*items;
Xint	cnt;
X{
X	int	i;
X
X	files = (struct file *) malloc (v.v_file * sizeof (struct file));
X	l_lseek (kmemfd, namelist[NM_FILE].xl_value, 0);
X	r_read (kmemfd, files, sizeof (struct file) * v.v_file);
X
X	printf ("SLOT    FLAG          COUNT  INODE      OFFSET\n");
X	if (cnt == 0) {
X		for (i = 0;i < v.v_file;i++) {
X			if (files[i].f_count == 0 || files[i].f_flag == 0)
X				continue;
X
X			dofile (i);
X		}
X	} else {
X		for (i = 0;i < cnt;i++) {
X			if (items[i] >= v.v_file)
X				printf ("value (%d) out of range\n", items[i]);
X			else
X				dofile (items[i]);
X		}
X	}
X	free ((char *) files);
X}
X
X
Xdofile (i)
Xint	i;
X{
X	printf ("%4d    %03o %c%c%c%c%c%c%c%c  %5d  %5d  %10ld\n",
X		i, files[i].f_flag & FMASK,
X		(files[i].f_flag & FREAD) ? 'R':' ',
X		(files[i].f_flag & FWRITE) ? 'W':' ',
X		(files[i].f_flag & FNDELAY) ? 'N':' ',
X		(files[i].f_flag & FAPPEND) ? 'A':' ',
X		(files[i].f_flag & FSYNC) ? 'S':' ',
X		(files[i].f_flag & FCREAT) ? 'C':' ',
X		(files[i].f_flag & FTRUNC) ? 'T':' ',
X		(files[i].f_flag & FEXCL) ? 'X':' ',
X		files[i].f_count,
X		files[i].f_inode - (struct inode *) namelist[NM_INODE].xl_value,
X		files[i].f_offset);
X}
SHAR_EOF
if test 1868 -ne "`wc -c < 'files.c'`"
then
	echo shar: "error transmitting 'files.c'" '(should have been 1868 characters)'
fi
fi
echo shar: "extracting 'inodes.c'" '(2345 characters)'
if test -f 'inodes.c'
then
	echo shar: "will not over-write existing file 'inodes.c'"
else
sed 's/^X//' << \SHAR_EOF > 'inodes.c'
X/*
X * Copyright 1988, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)inodes.c	1.2	22:55:34	2/21/91";
X#endif
X
X#include <sys/param.h>
X#include <sys/sysmacros.h>
X#include <sys/types.h>
X#include <sys/var.h>
X#include <sys/inode.h>
X#include <a.out.h>
X#include "crash.h"
X
Xprinodes (items, cnt)
Xint	*items;
Xint	cnt;
X{
X	int	i;
X
X	inodes = (struct inode *) malloc (v.v_inode * sizeof (struct inode));
X	l_lseek (kmemfd, namelist[NM_INODE].xl_value, 0);
X	r_read (kmemfd, inodes, sizeof (struct inode) * v.v_inode);
X
X	printf ("SLOT MAJ  MIN INUMB REF LINK  UID  GID     SIZE    MODE SMAJ SMIN FLAGS\n");
X
X	if (cnt == 0) {
X		for (i = 0;i < v.v_inode;i++) {
X			if (inodes[i].i_count == 0)
X				continue;
X
X			doinode (i);
X		}
X	} else {
X		for (i = 0;i < cnt;i++) {
X			if (items[i] >= v.v_inode)
X				printf ("value (%d) out of range\n", items[i]);
X			else
X				doinode (items[i]);
X		}
X	}
X	free ((char *) inodes);
X}
X	
Xdoinode (i)
Xint	i;
X{
X	char	*modes = " pcCd bBf";
X	struct	inode	*ip;
X
X	ip = &inodes[i];
X
X	printf ("%4d %03o %04o %5d %3d %4d%5d%5d %8ld %c%c%c%c%03o",
X		i, major (ip->i_dev), minor (ip->i_dev), ip->i_number,
X		ip->i_count, ip->i_nlink, ip->i_uid, ip->i_gid,
X		ip->i_size,
X		modes[(ip->i_mode & IFMT) >> 12],
X		(ip->i_mode & ISUID) ? 'u':'-',
X		(ip->i_mode & ISGID) ? 'g':'-',
X		(ip->i_mode & ISVTX) ? 't':'-',
X		(ip->i_mode & 0777));
X
X	if (! (((ip->i_mode & IFMT) == IFDIR) ||
X		((ip->i_mode & IFMT) == IFREG) ||
X		((ip->i_mode & IFMT) == IFIFO)))
X		printf (" %04o %04o", major (ip->i_rdev),
X					minor (ip->i_rdev));
X	else
X		printf ("    -    -");	/* special file stuff */
X	if (ip->i_flag & IUPD)		printf (" upd");
X	if (ip->i_flag & IACC)		printf (" acc");
X	if (ip->i_flag & ICHG)		printf (" chg");
X	if (ip->i_flag & IMOUNT)	printf (" mnt");
X	if (ip->i_flag & ITEXT)		printf (" txt");
X	if (ip->i_flag & ILOCK)		printf (" lck");
X#ifdef	ISYN
X	if (ip->i_flag & ISYN)		printf (" syn");
X#endif
X#ifdef	IRMT
X	if (ip->i_flag & IRMT)		printf (" rmt");
X#endif
X	if (ip->i_flag & IWANT)		printf (" wnt");
X
X	printf ("\n");
X}
SHAR_EOF
if test 2345 -ne "`wc -c < 'inodes.c'`"
then
	echo shar: "error transmitting 'inodes.c'" '(should have been 2345 characters)'
fi
fi
echo shar: "extracting 'mounts.c'" '(2319 characters)'
if test -f 'mounts.c'
then
	echo shar: "will not over-write existing file 'mounts.c'"
else
sed 's/^X//' << \SHAR_EOF > 'mounts.c'
X/*
X * Copyright 1988, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)mounts.c	1.2	22:55:36	2/21/91";
X#endif
X
X#include <sys/param.h>
X#include <sys/sysmacros.h>
X#include <sys/types.h>
X#include <sys/var.h>
X#include <sys/inode.h>
X#include <sys/ino.h>
X#include <sys/buf.h>
X#include <sys/filsys.h>
X#include <sys/mount.h>
X#include <a.out.h>
X#include "crash.h"
X
Xprmounts (items, cnt)
Xint	*items;
Xint	cnt;
X{
X	int	i;
X
X	mounts = (struct mount *) malloc (v.v_mount * sizeof (struct mount));
X	l_lseek (kmemfd, namelist[NM_MOUNT].xl_value, 0);
X	r_read (kmemfd, mounts, sizeof (struct mount) * v.v_mount);
X	l_lseek (kmemfd, namelist[NM_BUFFER].xl_value, 0);
X	r_read (kmemfd, &bufstart, sizeof bufstart);
X
X	printf ("SLOT  MAJ  MIN  INODE  BUF  VOLUME  PACK   BLOCKS INODES  BFREE  IFREE\n");
X
X	if (cnt == 0) {
X		for (i = 0;i < v.v_mount;i++) {
X			if (mounts[i].m_flags == 0)
X				continue;
X
X			domount (i);
X		}
X	} else {
X		for (i = 0;i < cnt;i++) {
X			if (items[i] >= v.v_mount)
X				printf ("value (%d) out of range\n", items[i]);
X			else
X				domount (items[i]);
X		}
X	}
X	free ((char *) mounts);
X}
X
Xdomount (i)
Xint	i;
X{
X	struct	filsys	filsys;
X	struct	buf	buf;
X	struct	inode	*ip = (struct inode *) namelist[NM_INODE].xl_value;
X
X	printf ("%4d %4o  %03o %6d %4d",
X		i, major (mounts[i].m_dev), minor (mounts[i].m_dev),
X		mounts[i].m_inodp ?
X			mounts[i].m_inodp - ip : 0,
X		mounts[i].m_bufp ?
X			mounts[i].m_bufp - bufstart : 0);
X
X	/*
X	 * zero before using since unused mount entries don't have
X	 * buffers and such.
X	 */
X
X	memset (&buf, 0, sizeof buf);
X	memset (&filsys, 0, sizeof filsys);
X
X	if (mounts[i].m_flags != 0) {
X		l_lseek (memfd, (long) mounts[i].m_bufp, 0);
X		r_read (memfd, &buf, sizeof buf);
X		l_lseek (memfd, (long) buf.b_paddr, 0);
X		r_read (memfd, &filsys, sizeof filsys);
X	}
X	printf ("  %-6.6s  %-6.6s",
X		filsys.s_fname, filsys.s_fpack);
X
X	printf (" %6ld %6ld %6ld %6ld",
X		filsys.s_fsize, INOPB * filsys.s_isize,
X		(long) filsys.s_tfree, (long) filsys.s_tinode);
X
X	putchar ('\n');
X}
SHAR_EOF
if test 2319 -ne "`wc -c < 'mounts.c'`"
then
	echo shar: "error transmitting 'mounts.c'" '(should have been 2319 characters)'
fi
fi
echo shar: "extracting 'procs.c'" '(2465 characters)'
if test -f 'procs.c'
then
	echo shar: "will not over-write existing file 'procs.c'"
else
sed 's/^X//' << \SHAR_EOF > 'procs.c'
X/*
X * Copyright 1988, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)procs.c	1.2	22:55:38	2/21/91";
X#endif
X
X#include <sys/param.h>
X#include <sys/sysmacros.h>
X#include <sys/types.h>
X#include <sys/var.h>
X#include <sys/text.h>
X#include <sys/page.h>
X#include <sys/seg.h>
X#include <sys/proc.h>
X#include <sys/signal.h>
X#include <sys/dir.h>
X#include <sys/user.h>
X#include "crash.h"
X
X/*
X * prprocs - output the process table
X */
X
Xprprocs (items, cnt)
Xint	*items;
Xint	cnt;
X{
X	struct	proc	*pp;
X	struct	user	user;
X	int	i;
X
X	procs = (struct proc *) malloc (v.v_proc * sizeof (struct proc));
X	lseek (kmemfd, namelist[NM_PROC].xl_value, 0);
X	read (kmemfd, procs, sizeof (struct proc) * v.v_proc);
X
X	printf ("SLT ST  PID  PPID  PGRP   UID  EUID PRI CPU    EVENT NAME       FLAGS\n");
X
X	if (cnt == 0) {
X		for (i = 0;i < v.v_proc;i++) {
X			if (procs[i].p_stat == 0)
X				continue;
X
X			doproc (i);
X		}
X	} else {
X		for (i = 0;i < cnt;i++) {
X			if (items[i] >= v.v_proc)
X				printf ("value (%d) out of range\n", items[i]);
X			else
X				doproc (items[i]);
X		}
X	}
X	free ((char *) procs);
X}
X
Xdoproc (i)
Xint	i;
X{
X	struct	proc	*pp;
X
X	pp = &procs[i];
X
X	printf ("%3d %c %5d %5d %5d %5d %5d %3d %3d", i,
X		" swriztBST"[pp->p_stat], pp->p_pid, pp->p_ppid,
X		pp->p_pgrp, pp->p_uid, pp->p_suid,
X		pp->p_pri & 0377, pp->p_cpu & 0377);
X
X	if (pp->p_wchan)
X		printf (" %8x", pp->p_wchan);
X	else
X		printf ("         ");
X
X	if (pp->p_stat == SZOMB) {
X		printf (" ZOMBIE    ");
X	} else if (pp->p_flag & SSYS) {
X		printf (" swapper   ");
X	} else if (pp->p_stat != 0) {
X		if (findu (pp, i, &user))
X			printf (" %-10.10s", user.u_comm);
X		else
X			printf (" SWAPPED   ");
X	} else {
X		printf ("           ");
X	}
X	if (pp->p_stat == SRUN)		printf (" running");
X	if (pp->p_stat == SZOMB)	printf (" zombie");
X	if (pp->p_flag & SLOAD)		printf (" incore");
X	else				printf (" swapped");
X	if (pp->p_flag & SSYS)		printf (" sched");
X	if (pp->p_flag & SLOCK)		printf (" locked");
X	if (pp->p_flag & STRC)		printf (" traced");
X	if (pp->p_flag & SWTED)		printf (" wanted");
X	if (pp->p_flag & STEXT)		printf (" text");
X	if (pp->p_flag & SSPART)	printf (" part-swap");
X
X	printf ("\n");
X}
SHAR_EOF
if test 2465 -ne "`wc -c < 'procs.c'`"
then
	echo shar: "error transmitting 'procs.c'" '(should have been 2465 characters)'
fi
fi
echo shar: "extracting 'texts.c'" '(1980 characters)'
if test -f 'texts.c'
then
	echo shar: "will not over-write existing file 'texts.c'"
else
sed 's/^X//' << \SHAR_EOF > 'texts.c'
X/*
X * Copyright 1988, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)texts.c	1.2	22:55:40	2/21/91";
X#endif
X
X#include <sys/param.h>
X#include <sys/sysmacros.h>
X#include <sys/types.h>
X#include <sys/var.h>
X#include <sys/inode.h>
X#include <sys/text.h>
X#include <sys/page.h>
X#include <sys/seg.h>
X#include <sys/proc.h>
X#include <a.out.h>
X#include "crash.h"
X
Xprtexts (items, cnt)
Xint	*items;
Xint	cnt;
X{
X	int	i;
X
X	texts = (struct text *) malloc (v.v_text * sizeof (struct text));
X	lseek (kmemfd, namelist[NM_TEXT].xl_value, 0);
X	read (kmemfd, texts, sizeof (struct text) * v.v_text);
X
X	printf ("SLOT  INODE  REF  LDREF  PROC  SWAPLO+   SIZE  FLAGS\n");
X
X	if (cnt == 0) {
X		for (i = 0;i < v.v_text;i++) {
X			if (texts[i].x_count == 0)
X				continue;
X
X			dotext (i);
X		}
X	} else {
X		for (i = 0;i < cnt;i++) {
X			if (items[i] >= v.v_text)
X				printf ("value (%d) out of range\n", items[i]);
X			else
X				dotext (items[i]);
X		}
X	}
X	free ((char *) texts);
X}
X
Xdotext (i)
Xint	i;
X{
X	struct	text	*tp;
X	int	procnum;
X
X	tp = &texts[i];
X
X	if (tp->x_ccount > 0)
X		procnum = tp->x_caddr -
X			(struct proc *) namelist[NM_PROC].xl_value;
X	else
X		procnum = 0;
X
X	printf ("%4d  %5d  %3d  %5d  %4d  %7d  %5d ", i,
X		tp->x_iptr - (struct inode *) namelist[NM_INODE].xl_value,
X		tp->x_count, tp->x_ccount, procnum,
X		tp->x_daddr, tp->x_size);
X
X	if (tp->x_flag & XTRC)		printf (" trace");
X	if (tp->x_flag & XWRIT)		printf (" write");
X	if (tp->x_flag & XLOAD)		printf (" loaded");
X	if (tp->x_flag & XLOCK)		printf (" locked");
X	if (tp->x_flag & XWANT)		printf (" wanted");
X	if (tp->x_flag & XLARGE)	printf (" large");
X	if (tp->x_flag & XFPU)		printf (" fpu");
X
X	printf ("\n");
X}
SHAR_EOF
if test 1980 -ne "`wc -c < 'texts.c'`"
then
	echo shar: "error transmitting 'texts.c'" '(should have been 1980 characters)'
fi
fi
echo shar: "extracting 'user.c'" '(3411 characters)'
if test -f 'user.c'
then
	echo shar: "will not over-write existing file 'user.c'"
else
sed 's/^X//' << \SHAR_EOF > 'user.c'
X/*
X * Copyright 1988, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)user.c	1.2	22:55:41	2/21/91";
X#endif
X
X#include <sys/param.h>
X#include <sys/sysmacros.h>
X#include <sys/types.h>
X#include <sys/page.h>
X#include <sys/seg.h>
X#include <sys/file.h>
X#include <sys/proc.h>
X#include <sys/signal.h>
X#include <sys/dir.h>
X#include <sys/user.h>
X#include <sys/var.h>
X#include <sys/lock.h>
X#include "crash.h"
X
Xfindu (proc, slot, user)
Xstruct	proc	*proc;
Xint	slot;
Xstruct	user	*user;
X{
X	struct	proc	*procs = (struct proc *) namelist[NM_PROC].xl_value;
X	long	swapaddr;
X	int	i;
X
X	if ((proc->p_flag & (SSWAP|SSPART)) || ! (proc->p_flag & SLOAD)) {
X		swapaddr = proc->p_addr[0].te_frameno * NBPC;
X		l_lseek (swapfd, swapaddr, 0);
X		r_read (swapfd, user, sizeof *user);
X	} else {
X		l_lseek (memfd, proc->p_addr[0].te_frameno * NBPC, 0);
X		r_read (memfd, user, sizeof *user);
X	}
X	if (user->u_procp - procs == slot)
X		return (1);
X	else
X		return (0);
X}
X
Xprusers (items, cnt)
Xint	*items;
Xint	cnt;
X{
X	int	i;
X
X	if (cnt == 0) {
X		douser (-1);
X		return (1);
X	}
X	for (i = 0;i < cnt;i++) {
X		if (items[i] >= v.v_proc) {
X			printf ("value (%d) out of range\n", items[i]);
X			continue;
X		} else {
X			douser (items[i]);
X		}
X	}
X}
X
Xdouser (i)
X{
X	struct	file	*fp;
X	struct	proc	proc;
X	struct	proc	*pp;
X	static	char	*segments[] = { "user", "system", "user i" };
X	int	fileno;
X
X	pp = (struct proc *) namelist[NM_PROC].xl_value;
X	fp = (struct file *) namelist[NM_FILE].xl_value;
X
X	if (i >= 0) {
X		l_lseek (kmemfd, (long) &pp[i], 0);
X		r_read (kmemfd, &proc, sizeof proc);
X
X		if (! findu (&proc, i, &user))
X			return (0);
X	} else {
X		l_lseek (kmemfd, namelist[NM_USER].xl_value, 0);
X		r_read (kmemfd, &user, sizeof user);
X	}
X	printf ("PER PROCESS USER AREA:\n");
X	printf ("USER ID's:	uid: %d, gid: %d, real uid: %d, real gid: %d\n",
X		user.u_uid, user.u_gid, user.u_ruid, user.u_rgid);
X	printf ("PROCESS TIMES:	user: %d, sys: %d, child user: %d, child sys: %d\n",
X		user.u_utime, user.u_stime, user.u_cutime, user.u_cstime);
X	printf ("PROCESS MISC:	proc slot: %d, cntrl tty: maj(%d) min(%d)\n",
X		user.u_procp - pp, major (user.u_ttyd), minor (user.u_ttyd));
X	printf ("IPC:		locks:%s%s%s%s%s\n",
X		user.u_lock == UNLOCK ? " unlocked":"",
X		user.u_lock & PROCLOCK ? " proc":"",
X		user.u_lock & TXTLOCK ? " text":"",
X		user.u_lock & DATLOCK ? " data":"",
X		user.u_lock & HUGELOCK ? " huge":"");
X	printf ("FILE I/O:	user addr: %ld, file offset: %ld, bytes: %ld,\n",
X		user.u_baseu, user.u_offset, user.u_count);
X	printf ("		segment: %s, umask: %01o, ulimit: %ld\n",
X		segments[user.u_segflg], user.u_cmask, user.u_limit);
X	printf ("ACCOUNTING:	command: %s, memory: %ld, type: %s\n",
X		user.u_comm, user.u_mem, user.u_acflag ? "fork":"exec");
X	printf ("		start: %s",
X		ctime (&user.u_start));
X
X	printf ("OPEN FILES:	file desc:  ");
X	for (i = 0;i < NOFILE;i++)
X		if (user.u_ofile[i] != (struct file *) 0)
X			printf ("%4d", i);
X	putchar ('\n');
X	
X	printf ("		file slot:  ");
X	for (i = 0;i < NOFILE;i++)
X		if (user.u_ofile[i] != (struct file *) 0)
X			printf ("%4d", user.u_ofile[i] - fp);
X	putchar ('\n');
X
X	return (0);
X}
SHAR_EOF
if test 3411 -ne "`wc -c < 'user.c'`"
then
	echo shar: "error transmitting 'user.c'" '(should have been 3411 characters)'
fi
fi
echo shar: "extracting 'vars.c'" '(1811 characters)'
if test -f 'vars.c'
then
	echo shar: "will not over-write existing file 'vars.c'"
else
sed 's/^X//' << \SHAR_EOF > 'vars.c'
X/*
X * Copyright 1988, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)vars.c	1.2	22:55:43	2/21/91";
X#endif
X
X#include <sys/param.h>
X#include <sys/sysmacros.h>
X#include <sys/types.h>
X#include <sys/file.h>
X#include <sys/inode.h>
X#include <sys/page.h>
X#include <sys/seg.h>
X#include <sys/proc.h>
X#include <sys/text.h>
X#include <sys/mount.h>
X#include <sys/var.h>
X#include <a.out.h>
X#include "crash.h"
X
Xprvars ()
X{
X	printf        ("buffers	  %3d\n",
X		v.v_buf);
X	printf        ("calls	  %3d\n",
X		v.v_call);
X	printf        ("inodes	  %3d\n",
X		v.v_inode);
X	printf        ("e_inodes  %3d\n",
X		v.ve_inode - (struct inode *) namelist[NM_INODE].xl_value);
X	printf        ("files	  %3d\n",
X		v.v_file);
X	printf        ("e_files	  %3d\n",
X		v.ve_file - (struct file *) namelist[NM_FILE].xl_value);
X	printf        ("mounts	  %3d\n",
X		v.v_mount);
X	printf        ("e_mounts  %3d\n",
X		v.ve_mount - (struct mount *) namelist[NM_MOUNT].xl_value);
X	printf        ("procs	  %3d\n",
X		v.v_proc);
X	printf        ("e_procs	  %3d\n",
X		v.ve_proc - (struct proc *) namelist[NM_PROC].xl_value);
X	printf        ("texts	  %3d\n",
X		v.v_text);
X	printf        ("e_texts	  %3d\n",
X		v.ve_text - (struct text *) namelist[NM_TEXT].xl_value);
X	printf        ("clists	  %3d\n",
X		v.v_clist);
X	printf        ("sabufs	  %3d\n",
X		v.v_sabuf);
X	printf        ("maxproc	  %3d\n",
X		v.v_maxup);
X/*
Xswapmap	  105
X*/
X	printf        ("hashbuf	  %3d\n",
X		v.v_hbuf);
X	printf        ("hashmask  %3d\n",
X		v.v_hmask);
X}
SHAR_EOF
if test 1811 -ne "`wc -c < 'vars.c'`"
then
	echo shar: "error transmitting 'vars.c'" '(should have been 1811 characters)'
fi
fi
echo shar: "extracting 'stats.c'" '(1805 characters)'
if test -f 'stats.c'
then
	echo shar: "will not over-write existing file 'stats.c'"
else
sed 's/^X//' << \SHAR_EOF > 'stats.c'
X/*
X * Copyright 1988, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)stats.c	1.2	22:55:39	2/21/91";
X#endif
X
X#include <sys/param.h>
X#include <sys/sysmacros.h>
X#include <sys/types.h>
X#include <sys/utsname.h>
X#include <sys/param.h>
X#include <a.out.h>
X#include <time.h>
X#include "crash.h"
X
X#define	MINUTE	(60L)
X#define	HOUR	(MINUTE*60L)
X#define	DAY	(HOUR*24L)
X
Xprstats ()
X{
X	l_lseek (kmemfd, namelist[NM_UTSNAME].xl_value, 0);
X	r_read (kmemfd, &utsname, sizeof utsname);
X
X	l_lseek (kmemfd, namelist[NM_TIME].xl_value, 0);
X	r_read (kmemfd, &ktime, sizeof ktime);
X
X	l_lseek (kmemfd, namelist[NM_LBOLT].xl_value, 0);
X	r_read (kmemfd, &klbolt, sizeof klbolt);
X
X	printf ("	sysname: %.*s\n",
X		sizeof utsname.sysname, utsname.sysname);
X	printf ("	nodename: %.*s\n",
X		sizeof utsname.nodename, utsname.nodename);
X	printf ("	release: %.*s\n",
X		sizeof utsname.release, utsname.release);
X	printf ("	version: %.*s\n",
X		sizeof utsname.version, utsname.version);
X	printf ("	machine: %.*s\n",
X		sizeof utsname.machine, utsname.machine);
X
X	printf ("	time of crash: %s", ctime (&ktime));
X
X	klbolt /= HZ;			/* convert to seconds */
X
X	printf ("	age of system:");
X
X	if (klbolt >= DAY)
X		printf (" %d %s,", klbolt / DAY,
X			klbolt >= (2*DAY) ? "days":"day");
X
X	klbolt %= DAY;
X
X	if (klbolt >= HOUR)
X		printf (" %d %s,", klbolt / HOUR,
X			klbolt >= (2*HOUR) ? "hrs.":"hr.");
X
X	klbolt %= HOUR;
X	klbolt /= MINUTE;
X
X	printf (" %d %s\n", klbolt,
X		klbolt == 0 || klbolt >= 2 ? "mins.":"min.");
X}
SHAR_EOF
if test 1805 -ne "`wc -c < 'stats.c'`"
then
	echo shar: "error transmitting 'stats.c'" '(should have been 1805 characters)'
fi
fi
echo shar: "extracting 'bufs.c'" '(2101 characters)'
if test -f 'bufs.c'
then
	echo shar: "will not over-write existing file 'bufs.c'"
else
sed 's/^X//' << \SHAR_EOF > 'bufs.c'
X/*
X * Copyright 1988, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)bufs.c	1.2	22:55:28	2/21/91";
X#endif
X
X#include <sys/param.h>
X#include <sys/sysmacros.h>
X#include <sys/types.h>
X#include <sys/var.h>
X#include <sys/inode.h>
X#include <sys/ino.h>
X#include <sys/buf.h>
X#include <a.out.h>
X#include "crash.h"
X
Xprbufs (items, cnt)
Xint	*items;
Xint	cnt;
X{
X	int	i;
X
X	bufs = (struct buf *) malloc (v.v_buf * sizeof (struct buf));
X
X	l_lseek (kmemfd, namelist[NM_BUFFER].xl_value, 0);
X	r_read (kmemfd, &bufstart, sizeof bufstart);
X
X	l_lseek (memfd, bufstart, 0);
X	r_read (memfd, bufs, v.v_buf * sizeof (struct buf));
X
X	printf (" BUF MAJ  MIN    BLOCK FLAGS\n");
X
X	if (cnt == 0) {
X		for (i = 0;i < v.v_buf;i++) {
X			if (bufs[i].b_flags == 0)
X				continue;
X
X			dobuf (i);
X		}
X	} else {
X		for (i = 0;i < cnt;i++) {
X			if (items[i] >= v.v_buf)
X				printf ("value (%d) out of range\n", items[i]);
X			else
X				dobuf (items[i]);
X		}
X	}
X	free ((char *) bufs);
X}
X
Xdobuf (i)
Xint	i;
X{
X	struct	buf	*bp;
X
X	bp = &bufs[i];
X
X	printf ("%4d %03.3o %04.4o %8d",
X		i, major (bp->b_dev) & 0377, minor (bp->b_dev), bp->b_blkno);
X
X	if (bp->b_flags & B_READ)	printf (" read");
X	if (bp->b_flags & B_DONE)	printf (" done");
X	if (bp->b_flags & B_ERROR)	printf (" error");
X	if (bp->b_flags & B_BUSY)	printf (" busy");
X	if (bp->b_flags & B_PHYS)	printf (" phys");
X	if (bp->b_flags & B_MAP)	printf (" map");
X	if (bp->b_flags & B_WANTED)	printf (" wanted");
X	if (bp->b_flags & B_AGE)	printf (" age");
X	if (bp->b_flags & B_ASYNC)	printf (" async");
X	if (bp->b_flags & B_DELWRI)	printf (" delwri");
X	if (bp->b_flags & B_OPEN)	printf (" open");
X	if (bp->b_flags & B_STALE)	printf (" stale");
X	if (bp->b_flags & B_NOCROSS)	printf (" nocross");
X	if (bp->b_flags & B_FLUSH)	printf (" flush");
X
X	putchar ('\n');
X}
SHAR_EOF
if test 2101 -ne "`wc -c < 'bufs.c'`"
then
	echo shar: "error transmitting 'bufs.c'" '(should have been 2101 characters)'
fi
fi
echo shar: "extracting 'syms.c'" '(6139 characters)'
if test -f 'syms.c'
then
	echo shar: "will not over-write existing file 'syms.c'"
else
sed 's/^X//' << \SHAR_EOF > 'syms.c'
X/*
X * Copyright 1991, John F. Haugh II
X * An unpublished work.
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)syms.c	2.1	07:15:42	2/27/91";
X#endif
X
X#include <sys/types.h>
X#include <sys/a.out.h>
X#include <sys/relsym.h>
X#include <stdio.h>
X
Xstruct	xlist3 {
X	unsigned short	xl3_type;
X	unsigned short	xl3_seg;
X	unsigned long	xl3_value;
X};
X
Xstruct	xlist	**symbols;
Xint	nsymbols;
Xint	maxsymbols;
X
Xextern	char	*strdup();
X
Xint
Xinitsyms (file)
Xchar	*file;
X{
X	FILE	*fp;
X	long	segsize;
X	long	pad;
X	struct	xexec	xexec;
X	struct	xext	xext;
X	struct	xseg	xseg;
X	struct	xlist	xlist;
X	char	buf[BUFSIZ];
X	char	*cp;
X
X	if (! (fp = fopen (file, "r"))) {
X		perror (file);
X		return -1;
X	}
X	if (fread (&xexec, sizeof xexec, 1, fp) != 1) {
X		printf ("error reading xexec header\n");
X		return -1;
X	}
X	if (xexec.x_magic != X_MAGIC) {
X		printf ("not a valid x.out header\n");
X		return -1;
X	}
X	if (! (xexec.x_renv & XE_SEG)) {
X		printf ("not a segmented object\n");
X		return -1;
X	}
X	if (fread (&xext, sizeof xext, 1, fp) != 1) {
X		printf ("error reading xext record\n");
X		return -1;
X	}
X	if (fseek (fp, xext.xe_segpos, 0) == -1) {
X		printf ("error seeking to segment table\n");
X		return -1;
X	}
X	while (fread (&xseg, sizeof xseg, 1, fp) == 1 && xext.xe_segsize > 0) {
X		if (xseg.xs_type == XS_TSYMS)
X			break;
X
X		xext.xe_segsize -= sizeof xseg;
X	}
X	if (xext.xe_segsize <= 0) {
X		printf ("error locating symbol table\n");
X		return -1;
X	}
X	if (fseek (fp, xseg.xs_filpos, 0) == -1) {
X		printf ("error seeking to symbol table\n");
X		return -1;
X	}
X	while (ftell (fp) < xseg.xs_filpos + xseg.xs_psize) {
X		if (nsymbols == maxsymbols) {
X			if (nsymbols == 0) {
X				maxsymbols = 10;
X				symbols = (struct xlist **)
X					malloc (maxsymbols * sizeof *symbols);
X			} else {
X				maxsymbols *= 2;
X				symbols = (struct xlist **) realloc (symbols,
X					maxsymbols * sizeof *symbols);
X			}
X		}
X		if (symbols == 0) {
X			printf ("error allocating memory for symbol table\n");
X			return -1;
X		}
X		fread (&xlist, sizeof (struct xlist3), 1, fp);
X		for (cp = buf;*cp++ = getc (fp);)
X			;
X
X		xlist.xl_name = strdup (buf);
X
X		symbols[nsymbols] = (struct xlist *)
X				malloc (sizeof (struct xlist));
X		*(symbols[nsymbols++]) = xlist;
X	}
X	fclose (fp);
X	return 0;
X}
X
Xlong
Xsym2addr (sym, type)
Xchar	*sym;
Xint	type;
X{
X	int	i;
X	int	symbol_type;
X
X	if (symbols == 0)
X		return -1;
X
X	for (i = 0;i < nsymbols;i++) {
X		symbol_type = symbols[i]->xl_type & S_TYPE;
X
X		if (type == 0 && strcmp (sym, symbols[i]->xl_name) == 0)
X			return symbols[i]->xl_value;
X
X		if (type == symbol_type && ! strcmp (sym, symbols[i]->xl_name))
X			return symbols[i]->xl_value;
X	}
X	return -1;
X}
X
Xchar *
Xaddr2sym (addr, diffp, type)
Xlong	addr;
Xlong	*diffp;
Xint	type;
X{
X	int	guess = -1;
X	int	i;
X	int	symbol_type;
X
X	if (symbols == 0)
X		return 0;
X
X	for (i = 0;i < nsymbols;i++) {
X		symbol_type = symbols[i]->xl_type & S_TYPE;
X
X		if (type == 0 && addr >= symbols[i]->xl_value &&
X			(guess == -1 ||
X			 symbols[i]->xl_value > symbols[guess]->xl_value))
X			guess = i;
X
X		if (type == symbol_type && addr >= symbols[i]->xl_value &&
X			(guess == -1 ||
X			 symbols[i]->xl_value > symbols[guess]->xl_value))
X			guess = i;
X	}
X	if (guess == -1)
X		return 0;
X
X	*diffp = addr - symbols[guess]->xl_value;
X	return symbols[guess]->xl_name;
X}
X
Xchar *
Xtext2sym (addr, diffp)
Xlong	addr;
Xlong	*diffp;
X{
X	return addr2sym (addr, diffp, S_TEXT);
X}
X
Xchar *
Xdata2sym (addr, diffp)
Xlong	addr;
Xlong	*diffp;
X{
X	char	*sym1, *sym2;
X	long	diff1, diff2;
X
X	sym1 = addr2sym (addr, &diff1, S_DATA);
X	sym2 = addr2sym (addr, &diff2, S_BSS);
X
X	if (sym1 && sym2) {
X		if (diff1 < diff2) {
X			*diffp = diff1;
X			return sym1;
X		} else {
X			*diffp = diff2;
X			return sym2;
X		}
X	}
X	if (sym1) {
X		*diffp = diff1;
X		return sym1;
X	} else if (sym2) {
X		*diffp = diff2;
X		return sym2;
X	} else
X		return 0;
X}
X
Xprtextaddr (cp)
Xchar	*cp;
X{
X	long	addr;
X	char	*sym;
X	long	diff;
X
X	if (expr (&cp, &addr)) {
X		printf ("error in '%.15s'\n", cp);
X		return;
X	}
X	if (! (sym = text2sym (addr, &diff))) {
X		printf ("no text address for %d (%x)\n", addr, addr);
X		return;
X	}
X	if (diff != 0)
X		printf ("%d (%x) = %s+%d (%x)\n", addr, addr, sym, diff, diff);
X	else
X		printf ("%d (%x) = %s\n", addr, addr, sym);
X}
X
Xprdataaddr (cp)
Xchar	*cp;
X{
X	long	addr;
X	char	*sym;
X	long	diff;
X
X	if (expr (&cp, &addr)) {
X		printf ("error in '%.15s'\n", cp);
X		return;
X	}
X	if (! (sym = data2sym (addr, &diff))) {
X		printf ("no data address for %d (%x)\n", addr, addr);
X		return;
X	}
X	if (diff != 0)
X		printf ("%d (%x) = %s+%d (%x)\n", addr, addr, sym, diff, diff);
X	else
X		printf ("%d (%x) = %s\n", addr, addr, sym);
X}
X
Xprsymbol (cp)
Xchar	*cp;
X{
X	char	buf[BUFSIZ];
X	long	addr;
X	int	type;
X	char	*sym;
X
X	buf[0] = '_';
X	strcpy (buf + 1, cp);
X
X	if ((addr = sym2addr (sym = buf + 1, type = S_TEXT)) == -1 &&
X		(addr = sym2addr (sym = buf, type = S_TEXT)) == -1 &&
X		(addr = sym2addr (sym = buf + 1, type = S_DATA)) == -1 &&
X		(addr = sym2addr (sym = buf, type = S_DATA)) == -1 &&
X		(addr = sym2addr (sym = buf + 1, type = S_BSS)) == -1 &&
X		(addr = sym2addr (sym = buf, type = S_BSS)) == -1) {
X		printf ("%s not found\n", cp);
X		return;
X	}
X	printf ("%s (%s) = %d (%x)\n", sym, type == S_TEXT ? "text":
X		(type == S_DATA ? "data":
X		(type == S_BSS ? "bss":"unknown")), addr, addr);
X}
X
X#ifdef	TEST
Xmain (argc, argv)
Xint	argc;
Xchar	**argv;
X{
X	int	i;
X	long	addr;
X	long	diff;
X	char	*sym;
X	char	buf[BUFSIZ];
X	char	*cp;
X
X	if (initsyms (argv[1]))
X		exit (1);
X
X	printf ("allocated %d slots for %d symbols\n", maxsymbols, nsymbols);
X
X	while (gets (buf)) {
X		if (buf[0] >= '0' && buf[0] <= '9') {
X			cp = buf;
X			if (expr (&cp, &addr)) {
X				printf ("error at '%.15s'\n", cp);
X				continue;
X			}
X			sym = addr2sym (addr, &diff, 0);
X			printf ("name of %s (%x) is %s+%d\n",
X				buf, addr, sym, diff);
X		} else {
X			addr = sym2addr (buf, 0);
X			printf ("address of %s is %d (%x)\n", buf, addr, addr);
X		}
X	}
X}
X#endif
SHAR_EOF
if test 6139 -ne "`wc -c < 'syms.c'`"
then
	echo shar: "error transmitting 'syms.c'" '(should have been 6139 characters)'
fi
fi
echo shar: "extracting 'devs.c'" '(3101 characters)'
if test -f 'devs.c'
then
	echo shar: "will not over-write existing file 'devs.c'"
else
sed 's/^X//' << \SHAR_EOF > 'devs.c'
X/*
X * Copyright 1991, John F. Haugh II
X * An unpublished work.
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)devs.c	2.1	07:14:51	2/27/91";
X#endif
X
X#include <sys/types.h>
X#include <sys/conf.h>
X#include <stdio.h>
X#include "crash.h"
X
Xextern	char	*text2sym();
Xextern	char	*data2sym();
X
Xchar *
Xkgets (off, buf)
Xlong	off;
Xchar	*buf;
X{
X	char	c;
X	char	*orig = buf;
X
X	l_lseek (kmemfd, off, 0);
X	while (r_read (kmemfd, &c, 1) == 1 && (*buf++ = c))
X		;
X
X	if (c)
X		return 0;
X	else
X		return orig;
X}
X
Xpr1cdev (cmajor)
Xint	cmajor;
X{
X	char	*sym;
X	char	buf[BUFSIZ];
X	long	diff;
X
X	if (cmajor < 0 || cmajor >= Cdevcnt) {
X		printf ("value (%d) out of range\n", cmajor);
X		return;
X	}
X	printf ("cdevsw[%d]: ", cmajor);
X
X	if (Cdevsw[cmajor].d_name)
X		printf ("%s ", kgets (Cdevsw[cmajor].d_name, buf));
X	else
X		printf ("(unnamed) ");
X
X	if (sym = text2sym (Cdevsw[cmajor].d_open, &diff))
X		printf ("%s ", sym);
X	else
X		printf ("0x%x ", Cdevsw[cmajor].d_open);
X
X	if (sym = text2sym (Cdevsw[cmajor].d_close, &diff))
X		printf ("%s ", sym);
X	else
X		printf ("0x%x ", Cdevsw[cmajor].d_close);
X
X	if (sym = text2sym (Cdevsw[cmajor].d_read, &diff))
X		printf ("%s ", sym);
X	else
X		printf ("0x%x ", Cdevsw[cmajor].d_read);
X
X	if (sym = text2sym (Cdevsw[cmajor].d_write, &diff))
X		printf ("%s ", sym);
X	else
X		printf ("0x%x ", Cdevsw[cmajor].d_write);
X
X	if (sym = text2sym (Cdevsw[cmajor].d_ioctl, &diff))
X		printf ("%s ", sym);
X	else
X		printf ("0x%x ", Cdevsw[cmajor].d_ioctl);
X
X	if (sym = data2sym (Cdevsw[cmajor].d_ttys, &diff))
X		printf ("%s ", sym);
X	else
X		printf ("0x%x ", Cdevsw[cmajor].d_ttys);
X
X	putchar ('\n');
X}
X
Xprcdevs (list, cnt)
Xint	*list;
Xint	cnt;
X{
X	int	i;
X
X	if (list == 0) {
X		for (i = 0;i < Cdevcnt;i++) {
X			if (Cdevsw[i].d_name == 0)
X				continue;
X
X			pr1cdev (i);
X		}
X	} else 
X		for (i = 0;i < cnt;i++) {
X			pr1cdev (list[i]);
X	}
X}
X
Xpr1bdev (bmajor)
Xint	bmajor;
X{
X	char	*sym;
X	char	buf[BUFSIZ];
X	long	diff;
X
X	if (bmajor < 0 || bmajor >= Bdevcnt) {
X		printf ("value (%d) out of range\n", bmajor);
X		return;
X	}
X	printf ("bdevsw[%d]: ", bmajor);
X
X	if (Bdevsw[bmajor].d_name)
X		printf ("%s ", kgets (Bdevsw[bmajor].d_name, buf));
X	else
X		printf ("(unnamed) ");
X
X	if (sym = text2sym (Bdevsw[bmajor].d_open, &diff))
X		printf ("%s ", sym);
X	else
X		printf ("0x%x ", Bdevsw[bmajor].d_open);
X
X	if (sym = text2sym (Bdevsw[bmajor].d_close, &diff))
X		printf ("%s ", sym);
X	else
X		printf ("0x%x ", Bdevsw[bmajor].d_close);
X
X	if (sym = text2sym (Bdevsw[bmajor].d_strategy, &diff))
X		printf ("%s ", sym);
X	else
X		printf ("0x%x ", Bdevsw[bmajor].d_strategy);
X
X
X	putchar ('\n');
X}
X
Xprbdevs (list, cnt)
Xint	*list;
Xint	cnt;
X{
X	int	i;
X
X	if (list == 0) {
X		for (i = 0;i < Bdevcnt;i++) {
X			if (Bdevsw[i].d_name == 0)
X				continue;
X
X			pr1bdev (i);
X		}
X	} else 
X		for (i = 0;i < cnt;i++) {
X			pr1bdev (list[i]);
X	}
X}
SHAR_EOF
if test 3101 -ne "`wc -c < 'devs.c'`"
then
	echo shar: "error transmitting 'devs.c'" '(should have been 3101 characters)'
fi
fi
echo shar: "extracting 'expr.c'" '(4388 characters)'
if test -f 'expr.c'
then
	echo shar: "will not over-write existing file 'expr.c'"
else
sed 's/^X//' << \SHAR_EOF > 'expr.c'
X/*
X * Copyright 1991, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#ifndef lint
Xstatic	char	sccsid[] = "@(#)expr.c	2.2	09:26:00	2/27/91";
X#endif
X
X#include <ctype.h>
X
X/*
X * number - parse numbers
X */
X
Xstatic int
Xnumber (cpp, result)
Xchar	**cpp;
Xlong	*result;
X{
X	char	*cp = *cpp;
X	char	*ep;
X	char	buf[101];
X	int	i;
X	int	base;
X	long	value;
X
X	if (! isdigit (*cp))
X		return -1;
X
X	if (*cp == '0' && *(cp + 1) == 'x') {
X		base = 16;
X		cp += 2;
X		for (i = 0;*cp && isxdigit (*cp);)
X			buf[i++] = *cp++;
X	} else if (*cp == '0') {
X		base = 8;
X		cp += 1;
X		for (i = 0;*cp && *cp >= '0' && *cp <= '7';)
X			buf[i++] = *cp++;
X	} else {
X		base = 10;
X		for (i = 0;*cp && isdigit (*cp);)
X			buf[i++] = *cp++;
X	}
X	buf[i] = '\0';
X	*result = strtol (buf, &ep, base);
X	if (*ep) {
X		*cpp = *cpp + (ep - buf);
X		return -1;
X	}
X	*cpp = cp;
X	return 0;
X}
X
X/*
X * symbol - lookup symbol names
X */
X
Xstatic int
Xsymbol (cpp, result)
Xchar	**cpp;
Xlong	*result;
X{
X	char	*cp = *cpp;
X	char	buf[101];	/* yes, the longest symbol is 100 characters */
X	int	i;
X
X	buf[0] = '_'; i = 1;
X
X	if (*cp != '_' && ! isalpha (*cp))
X		return -1;
X
X	while (i < 100 && (*cp == '_' || isalpha (*cp) || isdigit (*cp)))
X		buf[i++] = *cp++;
X
X	if (i == 100) {
X		*cpp = cp;
X		return -1;
X	}
X	buf[i++] = '\0';
X
X	if ((*result = sym2addr (buf + 1, 0)) == -1 &&
X			(*result = sym2addr (buf, 0)) == -1)
X		return -1;
X
X	*cpp = cp;
X	return 0;
X}
X
X/*
X * term - parse terms
X *
X *	<term> ::= '(' <expr> ')' | <number> | <symbol> | '-' <number
X */
X
Xstatic int
Xterm (cpp, result)
Xchar	**cpp;
Xlong	*result;
X{
X	char	*cp = *cpp;
X
X	while (*cp && isspace (*cp))
X		cp++;
X
X	if (isdigit (*cp)) {
X		if (number (&cp, result)) {
X			*cpp = cp;
X			return -1;
X		}
X	} else if (*cp == '_' || isalpha (*cp)) {
X		if (symbol (&cp, result)) {
X			*cpp = cp;
X			return -1;
X		}
X	} else if (*cp == '(') {
X		cp++;
X		if (expr (&cp, result)) {
X			*cpp = cp;
X			return -1;
X		}
X		while (*cp && isspace (*cp))
X			cp++;
X
X		if (*cp != ')') {
X			*cpp = cp;
X			return -1;
X		}
X		cp++;
X	} else if (*cp == '-') {
X		cp++;
X		if (number (&cp, result)) {
X			*cpp = cp;
X			return -1;
X		}
X		*result = - *result;
X	} else
X		return -1;
X
X	*cpp = cp;
X	return 0;
X}
X
X/*
X * prod - parse expressions
X *
X *	<prod> ::= <prod> ('*' | '/' | '%' | '&') <term> | <term>
X */
X
Xstatic int
Xprod (cpp, result)
Xchar	**cpp;
Xlong	*result;
X{
X	long	left, right;
X	enum { star, slash, percent, ampersand } op;
X	char	*cp = *cpp;
X
X	while (*cp && isspace (*cp))
X		cp++;
X
X	if (term (&cp, &left)) {
X		*cpp = cp;
X		return -1;
X	}
X	while (*cp) {
X		while (*cp && isspace (*cp))
X			cp++;
X
X		if (! *cp)
X			break;
X
X		switch (*cp) {
X			case '+':
X			case '-':
X			case '|':
X			case '^':
X			case ')':	*cpp = cp;
X					*result = left;
X					return 0;
X			case '*':	op = star; break;
X			case '/':	op = slash; break;
X			case '%':	op = percent; break;
X			case '&':	op = ampersand; break;
X			default:	*cpp = cp;
X					return -1;
X		}
X		cp++;
X		if (term (&cp, &right)) {
X			*cpp = cp;
X			return -1;
X		}
X		switch (op) {
X			case star:	left *= right; break;
X			case slash:	if (right == 0)
X						return -1;
X					left /= right; break;
X			case percent:	if (right == 0)
X						return -1;
X					left %= right; break;
X			case ampersand:	left &= right; break;
X		}
X	}
X	*result = left;
X	*cpp = cp;
X	return 0;
X}
X
X/*
X * expr - parse expressions
X *
X *	<expr> ::= <expr> ('+' | '-' | '|' | '^') <prod> | <prod>
X */
X
Xint
Xexpr (cpp, result)
Xchar	**cpp;
Xlong	*result;
X{
X	long	left, right;
X	enum { plus, minus, pipe, caret } op;
X	char	*cp = *cpp;
X
X	while (*cp && isspace (*cp))
X		cp++;
X
X	if (prod (&cp, &left)) {
X		*cpp = cp;
X		return -1;
X	}
X	while (*cp) {
X		while (*cp && isspace (*cp))
X			cp++;
X
X		if (! *cp)
X			break;
X
X		switch (*cp) {
X			case '+':	op = plus; break;
X			case '-':	op = minus; break;
X			case '|':	op = pipe; break;
X			case '^':	op = caret; break;
X			default:	*cpp = cp;
X					return -1;
X		}
X		cp++;
X		if (prod (&cp, &right)) {
X			*cpp = cp;
X			return -1;
X		}
X		switch (op) {
X			case plus:	left += right; break;
X			case minus:	left -= right; break;
X			case pipe:	left |= right; break;
X			case caret:	left ^= right; break;
X		}
X	}
X	*result = left;
X	*cpp = cp;
X	return 0;
X}
SHAR_EOF
if test 4388 -ne "`wc -c < 'expr.c'`"
then
	echo shar: "error transmitting 'expr.c'" '(should have been 4388 characters)'
fi
fi
echo shar: "extracting 'od.c'" '(3597 characters)'
if test -f 'od.c'
then
	echo shar: "will not over-write existing file 'od.c'"
else
sed 's/^X//' << \SHAR_EOF > 'od.c'
X/*
X * Copyright 1991, John F. Haugh II
X * An unpublished work.
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)od.c	2.1	07:15:25	2/27/91";
X#endif
X
X#define	SKIP_SPACE(cp)	while (*cp && isspace (*cp)) *cp++
X
X#include <sys/types.h>
X#include <ctype.h>
X#include "crash.h"
X
Xod (string)
Xchar	*string;
X{
X	long	base;
X	long	length = 0;
X	char	*cp;
X	char	*fmt = 0;
X	int	i, j;
X	unsigned char	c;
X	unsigned short	s;
X	long	l;
X
X	for (cp = string;*cp && *cp != ',';cp++)
X		;
X
X	if (*cp == ',')
X		*cp++ = '\0';
X
X	if (expr (&string, &base))
X		return -1;
X	else
X		string = cp;
X
X	if (*string) {
X		SKIP_SPACE(string);
X
X		for (cp = string;*cp && *cp != ',';cp++)
X			;
X
X		if (*cp == ',')
X			*cp++ = '\0';
X
X		if (expr (&string, &length))
X			return -1;
X		else
X			string = cp;
X
X		SKIP_SPACE(string);
X		if (*string)
X			fmt = string;
X		else
X			fmt = "x";
X	} else {
X		length = 16;
X		fmt = "x";
X	}
X	if (strlen (fmt) > 1) {
X		while (length > 0) {
X			printf ("%0.8x", base);
X
X			for (cp = fmt;length > 0 && *cp;) {
X				if (l_lseek (memfd, base, 0) == -1)
X					return;
X
X				switch (*cp) {
X					case 'a':
X						printf ("\n%0.8x", base);
X						break;
X					case 'n':
X						printf ("\n        ");
X						break;
X					case 'c':
X					case 'b':
X						if (r_read (memfd, &c, 1) == -1)
X							return;
X						base += 1;
X						length -= 1;
X						if (*fmt == 'b' ||
X							(c <= ' ' || c > '~'))
X							printf (" %0.2x", c);
X						else
X							printf (" '%c", c);
X						break;
X					case 'd':
X					case 'o':
X					case 'x':
X						if (r_read (memfd, &s, 2) == -1)
X							return;
X						base += 2;
X						length -= 2;
X						printf (*cp == 'd' ? " %5u":
X							(*cp == 'o' ? " %6o":
X								" %0.4x"), s);
X						break;
X					case 'D':
X					case 'O':
X					case 'X':
X						if (r_read (memfd, &l, 4) == -1)
X							return;
X						base += 4;
X						length -= 4;
X						printf (*cp == 'D' ? " %9lu":
X							(*cp == 'O' ? " %11lo":
X								" %0.8lx"), l);
X						break;
X					case 'Y':
X						if (r_read (memfd, &l, 4) == -1)
X							return;
X						base += 4;
X						printf (" %.24s", ctime (&l));
X						break;
X				}
X				cp++;
X			}
X			putchar ('\n');
X		}
X	} else {
X		while (length > 0) {
X			printf ("%0.8x", base);
X
X			for (i = 0;i < 16 && length > 0;) {
X				if (l_lseek (memfd, base, 0) == -1)
X					return;
X
X				switch (*fmt) {
X					case 'c':
X					case 'b':
X						if (r_read (memfd, &c, 1) == -1)
X							return;
X						base += 1;
X						i += 1;
X						length -= 1;
X						if (*fmt == 'b' ||
X							(c <= ' ' || c > '~'))
X							printf (" %0.2x", c);
X						else
X							printf (" '%c", c);
X						break;
X					case 'd':
X					case 'o':
X					case 'x':
X						if (r_read (memfd, &s, 2) == -1)
X							return;
X						base += 2;
X						i += 2;
X						length -= 2;
X						printf (*fmt == 'd' ? " %5u":
X							(*fmt == 'o' ? " %6o":
X								" %0.4x"), s);
X						break;
X					case 'D':
X					case 'O':
X					case 'X':
X						if (r_read (memfd, &l, 4) == -1)
X							return;
X						base += 4;
X						i += 4;
X						length -= 4;
X						printf (*fmt == 'D' ? " %9lu":
X							(*fmt == 'O' ? " %11lo":
X								" %0.8lx"), l);
X						break;
X					case 'Y':
X						if (r_read (memfd, &l, 4) == -1)
X							return;
X						base += 4;
X						i += 16;
X						length -= 4;
X						printf (" %.24s", ctime (&l));
X						break;
X				}
X			}
X			putchar ('\n');
X		}
X		if (i != 16)
X			printf ("%0.8x", base);
X	}
X}
SHAR_EOF
if test 3597 -ne "`wc -c < 'od.c'`"
then
	echo shar: "error transmitting 'od.c'" '(should have been 3597 characters)'
fi
fi
echo shar: "extracting 'ttys.c'" '(4724 characters)'
if test -f 'ttys.c'
then
	echo shar: "will not over-write existing file 'ttys.c'"
else
sed 's/^X//' << \SHAR_EOF > 'ttys.c'
X/*
X * Copyright 1991, John F. Haugh II
X * An unpublished work.
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X */
X
X#ifndef	lint
Xstatic	char	sccsid[] = "@(#)ttys.c	2.1	09:26:58	2/27/91";
X#endif
X
X#include <sys/types.h>
X#include <sys/termio.h>
X#include <sys/tty.h>
X#include <ctype.h>
X#include "crash.h"
X
Xstruct	bits {
X	char	*b_name;
X	int	b_value;
X	int	b_mask;
X};
X
Xstruct	bits	ibits[] = {
X	"ignbrk",	IGNBRK,	IGNBRK,
X	"brkint",	BRKINT,	BRKINT,
X	"ignpar",	IGNPAR,	IGNPAR,
X	"parmrk",	PARMRK,	PARMRK,
X	"inpck",	INPCK,	INPCK,
X	"istrip",	ISTRIP,	ISTRIP,
X	"inlcr",	INLCR,	INLCR,
X	"igncr",	IGNCR,	IGNCR,
X	"icrnl",	ICRNL,	ICRNL,
X	"iuclc",	IUCLC,	IUCLC,
X	"ixon",		IXON,	IXON,
X	"ixany",	IXANY,	IXANY,
X	"ixoff",	IXOFF,	IXOFF,
X	0,		0,	0
X};
X
Xstruct	bits	obits[] = {
X	"opost",	OPOST,	OPOST,
X	"olcuc",	OLCUC,	OLCUC,
X	"onlcr",	ONLCR,	ONLCR,
X	"ocrnl",	OCRNL,	OCRNL,
X	"onocr",	ONOCR,	ONOCR,
X	"onlret",	ONLRET,	ONLRET,
X	"ofill",	OFILL,	OFILL,
X	"ofdel",	OFDEL,	OFDEL,
X	"nl1",		NL1,	NLDLY,
X	"cr1",		CR1,	CRDLY,
X	"cr2",		CR2,	CRDLY,
X	"cr3",		CR3,	CRDLY,
X	"tab1",		TAB1,	TABDLY,
X	"tab2",		TAB2,	TABDLY,
X	"tab3",		TAB3,	TABDLY,
X	"bs1",		BS1,	BSDLY,
X	"vt1",		VT1,	VTDLY,
X	"ff1",		FF1,	FFDLY,
X	0,		0,	0
X};
X
Xstruct	bits	cbits[] = {
X	"b50",		B50,	CBAUD,
X	"b75",		B75,	CBAUD,
X	"b110",		B110,	CBAUD,
X	"b134",		B134,	CBAUD,
X	"b150",		B150,	CBAUD,
X	"b200",		B200,	CBAUD,
X	"b300",		B300,	CBAUD,
X	"b600",		B600,	CBAUD,
X	"b1200",	B1200,	CBAUD,
X	"b1800",	B1800,	CBAUD,
X	"b2400",	B2400,	CBAUD,
X	"b4800",	B4800,	CBAUD,
X	"b9600",	B9600,	CBAUD,
X	"exta",		EXTA,	CBAUD,
X	"extb",		EXTB,	CBAUD,
X	"cs6",		CS6,	CSIZE,
X	"cs7",		CS7,	CSIZE,
X	"cs8",		CS8,	CSIZE,
X	"cstopb",	CSTOPB,	CSTOPB,
X	"cread",	CREAD,	CREAD,
X	"parenb",	PARENB,	PARENB,
X	"parodd",	PARODD,	PARODD,
X	"hupcl",	HUPCL,	HUPCL,
X	"clocal",	CLOCAL,	CLOCAL,
X	"loblk",	LOBLK,	LOBLK,
X	"ctsflow",	CTSFLOW,CTSFLOW,
X	"rtsflow",	RTSFLOW,RTSFLOW,
X	0,		0,	0
X};
X
Xstruct	bits	lbits[] = {
X	"isig",		ISIG,	ISIG,
X	"icanon",	ICANON,	ICANON,
X	"xcase",	XCASE,	XCASE,
X	"echo",		ECHO,	ECHO,
X	"echoe",	ECHOE,	ECHOE,
X	"echok",	ECHOK,	ECHOK,
X	"echonl",	ECHONL,	ECHONL,
X	"noflsh",	NOFLSH,	NOFLSH,
X	0,		0,	0
X};
X
Xstruct	bits	state[] = {
X	"timeout",	TIMEOUT,	TIMEOUT,
X	"wopen",	WOPEN,		WOPEN,
X	"isopen",	ISOPEN,		ISOPEN,
X	"tblock",	TBLOCK,		TBLOCK,
X	"carr_on",	CARR_ON,	CARR_ON,
X	"busy",		BUSY,		BUSY,
X	"oaslp",	OASLP,		OASLP,
X	"iaslp",	IASLP,		IASLP,
X	"ttstop",	TTSTOP,		TTSTOP,
X	"extproc",	EXTPROC,	EXTPROC,
X	"tact",		TACT,		TACT,
X	"clesc",	CLESC,		CLESC,
X	"rto",		RTO,		RTO,
X	"ttiow",	TTIOW,		TTIOW,
X	"ttxon",	TTXON,		TTXON,
X	"ttxoff",	TTXOFF,		TTXOFF,
X	0,		0,	0
X};
X
Xstatic void
Xprbits (table, value)
Xstruct	bits	*table;
Xint	value;
X{
X	int	i;
X
X	for (i = 0;table[i].b_name;i++)
X		if (table[i].b_value == (table[i].b_mask & value))
X			printf (" %s", table[i].b_name);
X}
X
Xprttys (string)
Xchar	*string;
X{
X	char	*cp;
X	char	*device;
X	int	items[100];
X	int	cnt;
X	long	addr;
X	long	diff;
X	int	i, j;
X	struct	tty	tty;
X
X	while (*string && isspace (*string))
X		string++;
X
X	device = string;
X
X	while (*string && *string != ',')
X		string++;
X
X	if (*string == ',') {
X		*string++ = '\0';
X		while (*string && isspace (*string))
X			string++;
X	}
X	if (expr (&device, &addr)) {
X		printf ("error in tty address at '%.15s'\n", device);
X		return;
X	}
X	if (! *string) {
X		printf ("no ttys requested\n");
X		return;
X	}
X	if ((cnt = list (string, items, 100)) <= 0)
X		return;
X
X	*string++ = '\0';
X
X	if (device = data2sym (addr, &diff))
X		if (diff % sizeof tty != 0)
X			device = (char *) 0;
X
X	for (i = 0;i < cnt;i++) {
X		if (l_lseek (memfd, addr + items[i] * sizeof tty, 0) == -1 ||
X				r_read (memfd, &tty, sizeof tty) != sizeof tty)
X			return;
X
X		if (i != 0)
X			putchar ('\n');
X
X		if (device)
X			printf ("%s[%d]:\n", device,
X				diff / sizeof tty + items[i]);
X		else
X			printf ("tty[%d]:\n", items[i]);
X
X		printf ("iflag:"); prbits (ibits, tty.t_iflag); putchar ('\n');
X		printf ("oflag:"); prbits (obits, tty.t_oflag); putchar ('\n');
X		printf ("cflag:"); prbits (cbits, tty.t_cflag); putchar ('\n');
X		printf ("lflag:"); prbits (lbits, tty.t_lflag); putchar ('\n');
X		printf ("state:"); prbits (state, tty.t_state); putchar ('\n');
X		printf ("line disc: %d\n", tty.t_line);
X		printf ("pgrp: %d\n", tty.t_pgrp);
X
X		printf ("special characters:");
X		for (j = 0;j < NCC;j++) {
X			if (tty.t_cc[j] <= ' ' && tty.t_cc[j] >= 0)
X				printf (" ^%c", tty.t_cc[j] + '@');
X			else if (tty.t_cc[j] >= '~')
X				printf (" %0.2x", tty.t_cc[j]);
X			else
X				printf (" '%c", tty.t_cc[j]);
X		}
X		putchar ('\n');
X	}
X}
SHAR_EOF
if test 4724 -ne "`wc -c < 'ttys.c'`"
then
	echo shar: "error transmitting 'ttys.c'" '(should have been 4724 characters)'
fi
fi
echo shar: "extracting 'crash.h'" '(1267 characters)'
if test -f 'crash.h'
then
	echo shar: "will not over-write existing file 'crash.h'"
else
sed 's/^X//' << \SHAR_EOF > 'crash.h'
X/*
X * Copyright 1988, 1991, John F. Haugh II
X * All rights reserved.
X *
X * Permission is granted to copy and create derivative works for any
X * non-commercial purpose, provided this copyright notice is preserved
X * in all copies of source code, or included in human readable form
X * and conspicuously displayed on all copies of object code or
X * distribution media.
X *
X *	@(#)crash.h	2.1	07:08:34	2/27/91
X */
X
Xextern	int	memfd;
Xextern	int	kmemfd;
Xextern	int	swapfd;
X
X#define	NM_V	0
X#define	NM_FILE	1
X#define	NM_INODE	2
X#define	NM_PROC	3
X#define	NM_TEXT	4
X#define	NM_MOUNT	5
X#define	NM_BUFFER	6
X#define	NM_SWPLO	7
X#define	NM_TIME		8
X#define	NM_LBOLT	9
X#define	NM_UTSNAME	10
X#define	NM_USER		11
X#define	NM_CDEVCNT	12
X#define	NM_CDEVSW	13
X#define	NM_BDEVCNT	14
X#define	NM_BDEVSW	15
X#define	NM_NAMES	16
X
Xextern	struct	xlist	namelist[];
Xextern	struct	var	v;
Xextern	struct	file	*files;
Xextern	struct	inode	*inodes;
Xextern	struct	text	*texts;
Xextern	struct	proc	*procs;
Xextern	struct	mount	*mounts;
Xextern	struct	buf	*bufs;
Xextern	struct	buf	*bufstart;
Xextern	struct	user	user;
Xextern	daddr_t	swplo;
Xextern	time_t	ktime;
Xextern	time_t	klbolt;
Xextern	struct	utsname	utsname;
Xextern	int	Cdevcnt;
Xextern	int	Bdevcnt;
Xextern	struct	cdevsw	*Cdevsw;
Xextern	struct	bdevsw	*Bdevsw;
SHAR_EOF
if test 1267 -ne "`wc -c < 'crash.h'`"
then
	echo shar: "error transmitting 'crash.h'" '(should have been 1267 characters)'
fi
fi
exit 0
#	End of shell archive
-- 
John F. Haugh II                             UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 832-8832                           Domain: jfh at rpp386.cactus.org
"I've never written a device driver, but I have written a device driver manual"
                -- Robert Hartman, IDE Corp.



More information about the Alt.sources mailing list