[comp.sources.misc] v20i013: rc - A Plan 9 shell reimplementation, Part04/04

byron@archone.tamu.edu (Byron Rakitzis) (05/22/91)

Submitted-by: Byron Rakitzis <byron@archone.tamu.edu>
Posting-number: Volume 20, Issue 13
Archive-name: rc/part04

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# Contents:  COPYRIGHT Makefile builtins.h except.c except.h exec.c
#   exec.h footobar.h glob.h glom.h heredoc.h input.h lex.h list.c
#   list.h main.c match.c match.h mksignal nalloc.c nalloc.h node.h
#   open.c open.h parse.h rc.h redir.h status.c status.h stddef.h
#   stdlib.h string.h tree.h unistd.h utils.h version.c walk.h
# Wrapped by kent@sparky on Wed May 22 01:21:49 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo '          "shar: End of archive 4 (of 4)."'
if test -f 'COPYRIGHT' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'COPYRIGHT'\"
else
  echo shar: Extracting \"'COPYRIGHT'\" \(1106 characters\)
  sed "s/^X//" >'COPYRIGHT' <<'END_OF_FILE'
X/*
X * Copyright 1991 Byron Rakitzis.  All rights reserved.
X *
X * This software is not subject to any license of the American Telephone
X * and Telegraph Company or of the Regents of the University of California.
X *
X * Permission is granted to anyone to use this software for any purpose on
X * any computer system, and to alter it and redistribute it freely, subject
X * to the following restrictions:
X *
X * 1. The author is not responsible for the consequences of use of this
X *    software, no matter how awful, even if they arise from flaws in it.
X *
X * 2. The origin of this software must not be misrepresented, either by
X *    explicit claim or by omission.  Since few users ever read sources,
X *    credits must appear in the documentation.
X *
X * 3. Altered versions must be plainly marked as such, and must not be
X *    misrepresented as being the original software.  Since few users
X *    ever read sources, credits must appear in the documentation.
X *
X * 4. This notice may not be removed or altered.
X *
X *    [this copyright notice is adapted from Henry Spencer's
X *    "awf" copyright notice.]
X */
END_OF_FILE
  if test 1106 -ne `wc -c <'COPYRIGHT'`; then
    echo shar: \"'COPYRIGHT'\" unpacked with wrong size!
  fi
  # end of 'COPYRIGHT'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
  echo shar: Extracting \"'Makefile'\" \(1518 characters\)
  sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# Makefile for rc.
X#
X# Define the macro NODIRENT if your system has <sys/dir.h> but not <dirent.h>.
X# Define the macro NONMPIPES if your system does not support named pipes.
X# Define the macro NOJOB if your system does not support job control.
X# Define the macro NOLIMITS if your system does not support Berkeley limits.
X# Define the macro READLINE if you want rc to call GNU readline instead of read(2).
X
X# Get rid of default CFLAGS on braindamaged make's.
XCFLAGS=
X
X# Use an ANSI compiler (or at least one that groks prototypes and void *):
XCC=gcc -g -O
X
X# On an sgi running IRIX 3.3.1 I used:
X#CC=cc -g -O
X#
X# On the NeXT I used
X#CC=cc -g -O -DNODIRENT
X#
X# On a VAX running BSD 4.2
X#CC=gcc -g -O -DNODIRENT
X
X# Use bison if you will, but yacc generates a smaller y.tab.c, and the speed
X# of the parser is largely irrelevant in a shell.
XYACC=yacc
X
XOBJS =  builtins.o except.o exec.o fn.o footobar.o glob.o glom.o hash.o heredoc.o \
X	input.o lex.o list.o main.o match.o nalloc.o open.o redir.o sigmsgs.o status.o \
X	tree.o utils.o var.o version.o walk.o which.o y.tab.o
X
X# If rc is compiled with GNU readline, you must supply the correct arguments to
X# ld on this line. Typically this would be something like:
X#
X#	$(CC) -o rc $(OBJS) -lreadline -ltermcap
X
Xrc: $(OBJS)
X	$(CC) -o rc $(OBJS)
X
Xsigmsgs.c : mksignal
X	sh mksignal /usr/include/sys/signal.h
X
Xy.tab.c: parse.y
X	$(YACC) -d parse.y
X
Xclean:
X	rm -f *.o *.tab.[ch] sigmsgs.[ch]
X
X# dependencies:
X
Xsigmsgs.h : sigmsgs.c
Xlex.o y.tab.o: y.tab.c
Xfn.c status.c: sigmsgs.h
END_OF_FILE
  if test 1518 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
  fi
  # end of 'Makefile'
fi
if test -f 'builtins.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'builtins.h'\"
else
  echo shar: Extracting \"'builtins.h'\" \(162 characters\)
  sed "s/^X//" >'builtins.h' <<'END_OF_FILE'
Xtypedef void builtin_t(char **);
X
Xextern builtin_t *isbuiltin(char *);
Xextern void b_exec(char **), funcall(char **), b_dot(char **);
Xextern char *which(char *);
END_OF_FILE
  if test 162 -ne `wc -c <'builtins.h'`; then
    echo shar: \"'builtins.h'\" unpacked with wrong size!
  fi
  # end of 'builtins.h'
fi
if test -f 'except.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'except.c'\"
else
  echo shar: Extracting \"'except.c'\" \(2296 characters\)
  sed "s/^X//" >'except.c' <<'END_OF_FILE'
X#include <setjmp.h>
X#include <stdarg.h>
X#include "rc.h"
X#include "utils.h"
X#include "except.h"
X#include "status.h"
X#include "hash.h"
X#include "input.h"
X#include "nalloc.h"
X
X/*
X   a return goes back stack frames to the last return. A break does not. A signal
X   goes to the last interactive level.
X*/
X
Xstatic Estack *estack;
X
X/* add an exception to the input stack. */
X
Xvoid except(enum except e, jmp_buf jb, Estack *ex) {
X	ex->prev = estack;
X	estack = ex;
X
X	switch (estack->e = e) {
X	case ARENA:
X		estack->b = newblock();
X		break;
X	case ERROR: case BREAK: case RETURN:
X		estack->interactive = interactive;
X		estack->jb = (jmp_buf *) jb;
X		break;
X	case STAR:
X		break;
X	}
X}
X
X/* remove an exception, restore last interactive value */
X
Xvoid unexcept(void) {
X	if (estack->e == ERROR)
X		interactive = estack->interactive;
X	else if (estack->e == ARENA)
X		restoreblock(estack->b);
X	estack = estack->prev;
X}
X
X/*
X   Raise an exception. The rules are pretty complicated: you can return from a loop inside a
X   function, but you can't break from a function inside of a loop. On errors, rc_raise() goes back
X   to the LAST INTERACTIVE stack frame. If no such frame exists, then rc_raise() exits the shell.
X   This is what happens, say, when there is a syntax error in a noninteractive shell script. While
X   traversing the exception stack backwards, rc_raise() also removes input sources (closing
X   file-descriptors, etc.) and pops instances of $* that have been pushed onto the variable stack
X   (e.g., for a function call).
X*/
X
Xvoid rc_raise(enum except e) {
X	if (e == ERROR && rc_pid != getpid())
X			exit(1); /* child processes exit on an error/signal */
X
X	for (; estack != NULL; estack = estack->prev)
X		if (estack->e != e) {
X			if (e == BREAK && estack->e != ARENA)
X				rc_error("break outside of loop");
X			else if (e == RETURN && estack->e == ERROR) /* can return from loops inside functions */
X				rc_error("return outside of function");
X			if (estack->e == STAR)
X				varrm("*", TRUE);
X			else if (estack->e == ARENA)
X				restoreblock(estack->b);
X		} else {
X			if (e == ERROR && !estack->interactive) {
X				popinput();
X			} else {
X				jmp_buf *j = estack->jb;
X
X				interactive = estack->interactive;
X				estack = estack->prev;
X				longjmp(*j, 1);
X			}
X		}
X	rc_exit(1); /* top of exception stack */
X}
END_OF_FILE
  if test 2296 -ne `wc -c <'except.c'`; then
    echo shar: \"'except.c'\" unpacked with wrong size!
  fi
  # end of 'except.c'
fi
if test -f 'except.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'except.h'\"
else
  echo shar: Extracting \"'except.h'\" \(295 characters\)
  sed "s/^X//" >'except.h' <<'END_OF_FILE'
Xenum except { ERROR, BREAK, RETURN, STAR, ARENA };
Xtypedef struct Estack Estack;
X
Xstruct Estack {
X	enum except e;
X	boolean interactive;
X	jmp_buf *jb;
X	Block *b;
X	Estack *prev;
X};
X
Xextern void rc_raise(enum except);
Xextern void except(enum except, jmp_buf, Estack *);
Xextern void unexcept(void);
END_OF_FILE
  if test 295 -ne `wc -c <'except.h'`; then
    echo shar: \"'except.h'\" unpacked with wrong size!
  fi
  # end of 'except.h'
fi
if test -f 'exec.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'exec.c'\"
else
  echo shar: Extracting \"'exec.c'\" \(2186 characters\)
  sed "s/^X//" >'exec.c' <<'END_OF_FILE'
X/*
X   exec.c: exec() takes an argument list and does the appropriate thing
X   (calls a builtin, calls a function, etc.)
X*/
X
X#include <setjmp.h>
X#include <signal.h>
X#include "rc.h"
X#include "utils.h"
X#include "exec.h"
X#include "status.h"
X#include "hash.h"
X#include "builtins.h"
X#include "footobar.h"
X#include "except.h"
X#include "redir.h"
X
Xvoid exec(List *s, boolean parent) {
X	char **av, **ev;
X	int pid, stat;
X	builtin_t *b;
X	char *path = NULL;
X	void (*handler)(int);
X	boolean forked;
X
X	av = list2array(s, dashex);
X	ev = makeenv();
X
Xagain:	if (*av == NULL	|| isabsolute(*av)) /* null command or absolute pathname */
X		b = NULL;
X	else if (fnlookup(*av) != NULL)
X		b = funcall;
X	else
X		b = isbuiltin(*av);
X
X	if (b == b_exec) {
X		parent = FALSE;
X		b(av++);
X		if (*av == NULL)
X			return; /* return on null exec */
X		goto again;	/* go back and evaluate the type of command to be executed */
X	}
X
X	if (b == NULL) {
X		path = which(*av);
X		if (path == NULL && *av != NULL) { /* perform null commands for redirections */
X			fprint(2,"%s not found\n",*av);
X			set(FALSE);
X			redirq = NULL;
X			empty_fifoq();
X			if (parent)
X				return;
X			rc_exit(1);
X		}
X	}
X
X	/* if parent & the redirq is nonnull, builtin or not it has to fork. */
X
X	if (parent && (b == NULL || redirq != NULL)) {
X		pid = fork();
X		forked = TRUE;
X	} else {
X		pid = 0;
X		forked = FALSE;
X	}
X
X	switch (pid) {
X	case -1:
X		uerror("fork");
X		rc_error(NULL);
X		/* NOTREACHED */
X	case 0:
X		if (forked)
X			setsigdefaults();
X		doredirs();
X
X		/* null commands performed for redirections */
X		if (*av == NULL || b != NULL) {
X			if (b != NULL)
X				b(av);
X			empty_fifoq();
X			if (!forked && parent)
X				return;
X			rc_exit(getstatus());
X		}
X		execve(path, (const char **) av, (const char **) ev); /* bogus, huh? */
X		uerror(*av);
X		rc_exit(1);
X		/* NOTREACHED */
X	default:
X		if ((handler = signal(SIGINT, SIG_IGN)) != sig)
X			signal(SIGINT, handler); /* don't ignore interrupts in noninteractive mode */
X		while (pid != wait(&stat))
X			if (pid < 0)
X				uerror("wait");
X		signal(SIGINT, handler);
X		redirq = NULL;
X		empty_fifoq();
X		setstatus(stat);
X		if (stat == SIGINT) /* interrupted? let the handler deal with it. */
X			rc_raise(ERROR);
X	}
X}
END_OF_FILE
  if test 2186 -ne `wc -c <'exec.c'`; then
    echo shar: \"'exec.c'\" unpacked with wrong size!
  fi
  # end of 'exec.c'
fi
if test -f 'exec.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'exec.h'\"
else
  echo shar: Extracting \"'exec.h'\" \(104 characters\)
  sed "s/^X//" >'exec.h' <<'END_OF_FILE'
Xstruct Rq {
X	Node *r;
X	struct Rq *n;
X};
X
Xextern void exec(List *, boolean);
Xextern void doredirs(void);
END_OF_FILE
  if test 104 -ne `wc -c <'exec.h'`; then
    echo shar: \"'exec.h'\" unpacked with wrong size!
  fi
  # end of 'exec.h'
fi
if test -f 'footobar.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'footobar.h'\"
else
  echo shar: Extracting \"'footobar.h'\" \(258 characters\)
  sed "s/^X//" >'footobar.h' <<'END_OF_FILE'
Xextern char *fun2str(char *, Node *);
Xextern char *ptree(Node *);
Xextern char *list2str(char *, List *);
Xextern char **list2array(List *, boolean);
Xextern char *get_name(char *);
Xextern List *parse_var(char *, char *);
Xextern Node *parse_fn(char *, char *);
END_OF_FILE
  if test 258 -ne `wc -c <'footobar.h'`; then
    echo shar: \"'footobar.h'\" unpacked with wrong size!
  fi
  # end of 'footobar.h'
fi
if test -f 'glob.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'glob.h'\"
else
  echo shar: Extracting \"'glob.h'\" \(66 characters\)
  sed "s/^X//" >'glob.h' <<'END_OF_FILE'
Xextern boolean lmatch(List *, List *);
Xextern List *glob(List *);
END_OF_FILE
  if test 66 -ne `wc -c <'glob.h'`; then
    echo shar: \"'glob.h'\" unpacked with wrong size!
  fi
  # end of 'glob.h'
fi
if test -f 'glom.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'glom.h'\"
else
  echo shar: Extracting \"'glom.h'\" \(275 characters\)
  sed "s/^X//" >'glom.h' <<'END_OF_FILE'
Xextern void assign(List *, List *, boolean);
Xextern void qredir(Node *);
Xextern List *append(List *, List*);
Xextern List *flatten(List *);
Xextern List *glom(Node *);
Xextern List *concat(List *, List *);
Xextern List *varsub(List *, List *);
Xextern List *word(char *, char *);
END_OF_FILE
  if test 275 -ne `wc -c <'glom.h'`; then
    echo shar: \"'glom.h'\" unpacked with wrong size!
  fi
  # end of 'glom.h'
fi
if test -f 'heredoc.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'heredoc.h'\"
else
  echo shar: Extracting \"'heredoc.h'\" \(99 characters\)
  sed "s/^X//" >'heredoc.h' <<'END_OF_FILE'
Xextern void heredoc(int);
Xextern void qdoc(Node *, Node *);
X
Xtypedef struct Hq Hq;
X
Xextern Hq *hq;
END_OF_FILE
  if test 99 -ne `wc -c <'heredoc.h'`; then
    echo shar: \"'heredoc.h'\" unpacked with wrong size!
  fi
  # end of 'heredoc.h'
fi
if test -f 'input.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'input.h'\"
else
  echo shar: Extracting \"'input.h'\" \(373 characters\)
  sed "s/^X//" >'input.h' <<'END_OF_FILE'
Xenum inputtype { FD, STRING };
X
X#define EOF (-1)
X
Xextern void initinput(void);
Xextern Node *parseline(char *);
Xextern int gchar(void);
Xextern void ugchar(int);
Xextern Node *doit(boolean);
Xextern void flushu(void);
Xextern void pushinput(int /*enum inputtype*/,...);
Xextern void popinput(void);
Xextern int last;
X
Xextern boolean rcrc;
Xextern char *histstr;
Xextern int histfd;
END_OF_FILE
  if test 373 -ne `wc -c <'input.h'`; then
    echo shar: \"'input.h'\" unpacked with wrong size!
  fi
  # end of 'input.h'
fi
if test -f 'lex.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'lex.h'\"
else
  echo shar: Extracting \"'lex.h'\" \(502 characters\)
  sed "s/^X//" >'lex.h' <<'END_OF_FILE'
Xenum redirtype {
X	FROM, CREATE, APPEND, HEREDOC, HERESTRING
X};
X
Xtypedef struct Pipe {
X	int left,right;
X} Pipe;
X
Xtypedef struct Dup {
X	enum redirtype type;
X	int left,right;
X} Dup;
X
Xtypedef struct Redir {
X	enum redirtype type;
X	int fd;
X} Redir;
X
Xtypedef struct Word {
X	char *w;
X	char *m;
X} Word;
X
Xextern int yylex(void);
Xextern void inityy(void);
Xextern void skipnl(void);
Xextern void yyerror(const char *);
Xextern void scanerror(char *);
Xextern void print_prompt2(void);
X
Xextern const char nw[], dnw[];
END_OF_FILE
  if test 502 -ne `wc -c <'lex.h'`; then
    echo shar: \"'lex.h'\" unpacked with wrong size!
  fi
  # end of 'lex.h'
fi
if test -f 'list.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'list.c'\"
else
  echo shar: Extracting \"'list.c'\" \(984 characters\)
  sed "s/^X//" >'list.c' <<'END_OF_FILE'
X/* list.c: routines for manipulating the List type */
X
X#include "rc.h"
X#include "utils.h"
X#include "list.h"
X
X/*
X   These list routines assign meta values of null to the resulting lists;
X   it is impossible to glob with the value of a variable unless this value
X   is rescanned with eval---therefore it is safe to throw away the meta-ness
X   of the list.
X*/
X
X/* free a list from malloc space */
X
Xvoid listfree(List *p) {
X	if (p == NULL)
X		return;
X	listfree(p->n);
X	efree(p->w);
X	efree(p);
X}
X
X/* copy of list in malloc space (for storing a variable) */
X
XList *listcpy(List *s) {
X	List *r;
X
X	if (s == NULL)
X		return NULL;
X
X	r = enew(List);
X	r->w = ecpy(s->w);
X	r->m = NULL;
X	r->n = listcpy(s->n);
X
X	return r;
X}
X
X/* length of list */
X
XSIZE_T listlen(List *s) {
X	SIZE_T size;
X
X	for (size = 0; s != NULL; s = s->n)
X		size += strlen(s->w) + 1;
X
X	return size;
X}
X
X/* number of elements in list */
X
Xint listnel(List *s) {
X	int nel;
X
X	for (nel = 0; s != NULL; s = s->n)
X		nel++;
X
X	return nel;
X}
END_OF_FILE
  if test 984 -ne `wc -c <'list.c'`; then
    echo shar: \"'list.c'\" unpacked with wrong size!
  fi
  # end of 'list.c'
fi
if test -f 'list.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'list.h'\"
else
  echo shar: Extracting \"'list.h'\" \(119 characters\)
  sed "s/^X//" >'list.h' <<'END_OF_FILE'
Xextern void listfree(List *);
Xextern List *listcpy(List *);
Xextern SIZE_T listlen(List *);
Xextern int listnel(List *);
END_OF_FILE
  if test 119 -ne `wc -c <'list.h'`; then
    echo shar: \"'list.h'\" unpacked with wrong size!
  fi
  # end of 'list.h'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.c'\"
else
  echo shar: Extracting \"'main.c'\" \(2456 characters\)
  sed "s/^X//" >'main.c' <<'END_OF_FILE'
X/* main.c: handles initialization of rc and command line options */
X
X#include <stdarg.h>
X#include "rc.h"
X#include "utils.h"
X#include "input.h"
X#include "nalloc.h"
X#include "hash.h"
X#include "lex.h"
X#include "open.h"
X#include "tree.h"
X#include "glom.h"
X#include "builtins.h"
X#include "parse.h"
X
Xboolean dashdee, dashee, dashvee, dashex, dashell, dasheye, interactive;
Xint rc_pid;
X
X#define REALLYNULL ((void *) 0) /* used to terminate a vararg list with NULL */
X
Xstatic void assigndefault(char *,...);
X
Xvoid main(int argc, char *argv[], char *envp[]) {
X	extern int getopt(int, char **, char *);
X	extern int optind;
X	extern char *optarg;
X	char *dashsee[2], pid[8], *dollarzero, *null[1];
X	int c;
X
X	dashee = dashell = dashvee = dashex = dashdee = FALSE;
X	dashsee[0] = dashsee[1] = NULL;
X	dollarzero = argv[0];
X
X	dashell = (*argv[0] == '-'); /* Unix tradition */
X
X	while ((c = getopt(argc, argv, "leivdxc:")) != -1)
X		switch (c) {
X		case 'l':
X			dashell = TRUE;
X			break;
X		case 'e':
X			dashee = TRUE;
X			break;
X		case 'i':
X			dasheye = interactive = TRUE;
X			break;
X		case 'v':
X			dashvee = TRUE;
X			break;
X		case 'x':
X			dashex = TRUE;
X			break;
X		case 'd':
X			dashdee = TRUE;
X			break;
X		case 'c':
X			dashsee[0] = optarg;
X			goto quitopts;
X		case '?':
X			exit(1);
X		}
X
Xquitopts:
X	argv += optind;
X
X	/* use isatty() iff -i is not set, and iff the input is not from a script or -c flag */
X	if (!dasheye && dashsee[0] == NULL && *argv == NULL)
X		interactive = isatty(0);
X
X	inithandler();
X	inithash();
X	initparse();
X	assigndefault("prompt", "; ", "", REALLYNULL);
X	assigndefault("path", ".", "/bin", "/usr/bin", "/usr/ucb", REALLYNULL);
X	assigndefault("ifs", " ", "\t", "\n", REALLYNULL);
X	assigndefault("pid", sprint(pid, "%d", rc_pid = getpid()), REALLYNULL);
X	initenv(envp);
X	initinput();
X	null[0] = NULL;
X	starassign(dollarzero, null, FALSE); /* assign $0 to $* */
X
X	if (dashsee[0] != NULL) {	/* input from the -c flag? */
X		if (*argv != NULL)
X			starassign(dollarzero, argv, FALSE);
X		pushinput(STRING, dashsee);
X	} else if (*argv != NULL) {	/* else from a file? */
X		b_dot(--argv);
X		rc_exit(0);
X	} else {			/* else stdin */
X		pushinput(FD, 0);
X	}
X
X	doit(TRUE);
X	rc_exit(0);
X}
X
Xstatic void assigndefault(char *name,...) {
X	va_list ap;
X	List *l;
X	char *v;
X
X	va_start(ap, name);
X
X	for (l = NULL; (v = va_arg(ap, char *)) != NULL;)
X		l = append(l, word(v, NULL));
X
X	varassign(name, l, FALSE);
X
X	if (streq(name,"path"))
X		alias(name, l, FALSE);
X
X	va_end(ap);
X}
END_OF_FILE
  if test 2456 -ne `wc -c <'main.c'`; then
    echo shar: \"'main.c'\" unpacked with wrong size!
  fi
  # end of 'main.c'
fi
if test -f 'match.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'match.c'\"
else
  echo shar: Extracting \"'match.c'\" \(1992 characters\)
  sed "s/^X//" >'match.c' <<'END_OF_FILE'
X/* match.c: pattern matching routines */
X
X#include "rc.h"
X#include "utils.h"
X#include "match.h"
X
Xstatic int rangematch(char *, char);
X
X/*
X   match() matches a single pattern against a single string.
X*/
X
Xboolean match(char *p, char *m, char *s) {
X	int i = 0;
X	int j;
X
X	if (m == NULL)
X		return streq(p, s);
X
X	while(1) {
X		if (p[i] == '\0')
X			return *s == '\0';
X		else if (m[i]) {
X			switch (p[i++]) {
X			case '?':
X				if (*s++ == '\0')
X					return FALSE;
X				break;
X			case '*':
X				/* collapse multiple stars */
X				while (p[i] == '*' && m[i] == 1)
X					i++;
X
X				/* star at end of pattern? */
X				if (p[i] == '\0')
X					return TRUE;
X
X				while (*s != '\0')
X					if (match(p + i, m + i, s++))
X						return TRUE;
X				return FALSE;
X			case '[':
X				if (*s == '\0' || ((j = rangematch(p + i, *s++)) < 0))
X					return FALSE;
X				i += j;
X				break;
X			default:
X				fprint(2,"%c is not a metacharacter\n", p[i-1]);
X				return FALSE;
X			}
X		} else if (p[i++] != *s++) {
X				return FALSE;
X		}
X	}
X}
X
X/*
X   From the ed(1) man pages (on ranges):
X
X	The `-' is treated as an ordinary character if it occurs first
X	(or first after an initial ^) or last in the string.
X
X	The right square bracket does not terminate the enclosed string
X	if it is the first character (after an initial `^', if any), in
X	the bracketed string.
X
X   rangematch() matches a single character against a class, and returns
X   an integer offset to the end of the range on success, or -1 on
X   failure.
X*/
X
Xstatic int rangematch(char *p, char c) {
X	char *orig = p;
X	boolean neg = (*p == '~');
X	boolean matched = FALSE;
X
X	if (neg)
X		p++;
X
X	if (*p == ']') {
X		p++;
X		matched = (c == ']');
X	}
X
X	for (; *p != ']'; p++) {
X		if (*p == '\0')
X			return -1;	/* bad syntax */
X		if (p[1] == '-' && p[2] != ']') { /* check for [..-..] but ignore [..-] */
X			if (c >= *p)
X				matched |= (c <= p[2]);
X			p += 2;
X		} else {
X			matched |= (*p == c);
X		}
X	}
X
X	if (matched ^ neg)
X		return p - orig + 1; /* skip the right-bracket */
X	else
X		return -1;
X}
X
END_OF_FILE
  if test 1992 -ne `wc -c <'match.c'`; then
    echo shar: \"'match.c'\" unpacked with wrong size!
  fi
  # end of 'match.c'
fi
if test -f 'match.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'match.h'\"
else
  echo shar: Extracting \"'match.h'\" \(46 characters\)
  sed "s/^X//" >'match.h' <<'END_OF_FILE'
Xextern boolean match(char *, char *, char *);
END_OF_FILE
  if test 46 -ne `wc -c <'match.h'`; then
    echo shar: \"'match.h'\" unpacked with wrong size!
  fi
  # end of 'match.h'
fi
if test -f 'mksignal' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mksignal'\"
else
  echo shar: Extracting \"'mksignal'\" \(1683 characters\)
  sed "s/^X//" >'mksignal' <<'END_OF_FILE'
X#!/bin/sh
X# generate rc's internal signal table from signal.h
X
Xexec > sigmsgs.c
X
Xecho 'char *signals[][2] = {'
X
Xsed '	s/\/\*[ 	]*//
X	s/[ 	]*\*\///
X	s/([@*+!]) //
X	s/[ 	]*([a-zA-Z,->& ]*)[ 	]*//
X	s/[ 	]*signal$//' $1 |
Xawk '
X	BEGIN {
X		# assign to nomesg["SIGNAME"] to suppress a long message
X		nomesg["SIGINT"] = 1
X		nomesg["SIGPIPE"] = 1
X		# assign to mesg["SIGNAME"] to override a message
X		mesg["SIGHUP"] = "hangup"
X		mesg["SIGKILL"] = "killed"
X		mesg["SIGQUIT"] = "quit"
X		mesg["SIGTERM"] = "terminated"
X		mesg["SIGURG"] = "urgent condition on i/o channel"
X		mesg["SIGSTOP"] = "stop signal not from tty"
X		mesg["SIGTSTP"] = "stopped"
X		mesg["SIGCONT"] = "continue"
X		mesg["SIGCHLD"] = "child stop or exit"
X		mesg["SIGTTIN"] = "background tty read"
X		mesg["SIGTTOU"] = "background tty write"
X		# assign to ignore["SIGNAME"] to explicitly ignore a named signal
X		ignore["SIGMAX"] = 1
X	}
X	$1 == "#define" && $2 == "NSIG" && $3 ~ /^[0-9]+$/ { nsig = $3 }
X	$1 == "#define" && $2 ~ /^SIG/ && $3 ~ /^[0-9]+$/ && sig[$3] == "" && ignore[$2] == 0 {
X		sig[$3] = $2
X		if ($3 > max)
X			max = $3
X		if (mesg[$2] == "" && nomesg[$2] == 0) {
X			str = $4
X			for (i = 5; i <= NF; i++)
X				str = str " " $i
X			mesg[$2] = str
X		}
X	}
X	END {
X		if (nsig == 0)
X			nsig = max + 1
X		printf "	!!,		!!,\n"
X		for (i = 1; i < nsig; i++) {
X			if (sig[i] == "")
X				printf "	!!,		!!,\n"
X			else
X				printf "	!%s!,	!%s!,\n", sig[i], mesg[sig[i]]
X		}
X	}
X' |
Xtr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ!' 'abcdefghijklmnopqrstuvwxyz"'
X
Xecho '};'
X
Xexec > sigmsgs.h
X
Xecho 'extern char *signals[][2];'
X
Xgrep '^	' sigmsgs.c |		# the thing in quotes is ^<tab>
Xawk '
X		{ sum = sum + 1; }
X	END	{ print "#define NUMOFSIGNALS", sum }
X'
END_OF_FILE
  if test 1683 -ne `wc -c <'mksignal'`; then
    echo shar: \"'mksignal'\" unpacked with wrong size!
  fi
  # end of 'mksignal'
fi
if test -f 'nalloc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'nalloc.c'\"
else
  echo shar: Extracting \"'nalloc.c'\" \(2218 characters\)
  sed "s/^X//" >'nalloc.c' <<'END_OF_FILE'
X/* nalloc.c: a simple single-arena allocator for command-line-lifetime allocation */
X
X#include "rc.h"
X#include "utils.h"
X#include "nalloc.h"
X
Xstatic struct Block {
X	SIZE_T used;
X	SIZE_T size;
X	char *mem;
X	Block *n;
X} *fl, *ul;
X
X/* alignto() works only with power of 2 blocks and assumes 2's complement arithmetic */
X#define alignto(m, n)   ((m + n - 1) & ~(n - 1))
X#define BLOCKSIZE 4096
X
X/* gets a block from malloc space and places it at the head of the used-list */
X
Xstatic void getblock(SIZE_T n) {
X	Block *r, *p;
X
X	for (r = fl, p = NULL; r != NULL; p = r, r = r->n)
X		if (n <= r->size)
X			break;
X
X	if (r != NULL) {
X		if (p != NULL)
X			p->n = r->n;
X		else
X			fl = r->n;
X	} else {
X		r = enew(Block);
X		r->mem = ealloc(alignto(n, BLOCKSIZE));
X		r->size = alignto(n, BLOCKSIZE);
X	}
X
X	r->used = 0;
X	r->n = ul;
X	ul = r;
X}
X
X/*
X   A fast single-arena allocator. Looks at the current block, and if there is not enough room,
X   it goes to getblock() for more. "ul" stands for "used list", and the head of the list is the
X   current block.
X*/
X
Xvoid *nalloc(SIZE_T n) {
X	char *ret;
X
X        n = alignto(n, sizeof (ALIGN_T));
X
X	if (ul == NULL || n + ul->used >= ul->size)
X		getblock(n);
X
X	ret = ul->mem + ul->used;
X	ul->used += n;
X	return ret;
X}
X
X/*
X   Frees memory from nalloc space by putting it on the freelist. Returns free blocks to the
X   system, retaining at least MAXMEM bytes worth of blocks for nalloc.
X*/
X
X#define MAXMEM 500000
X
Xvoid nfree() {
X	Block *r;
X	SIZE_T count;
X
X	if (ul == NULL)
X		return;
X
X	for (r = ul; r->n != NULL; r = r->n)
X		;
X
X	r->n = fl;
X	fl = ul;
X	ul = NULL;
X
X	for (r = fl, count = r->size; r->n != NULL; r = r->n, count += r->size) {
X		if (count >= MAXMEM) {
X			Block *tmp = r;
X
X			r = r->n;
X			tmp->n = NULL;		/* terminate the freelist */
X
X			while (r != NULL) {	/* free memory off the tail of the freelist */
X				tmp = r->n;
X				efree(r->mem);
X				efree(r);
X				r = tmp;
X			}
X		return;
X		}
X	}
X}
X
X/*
X   "allocates" a new arena by zeroing out the old one. Up to the calling routine to keep
X   the old value of the block around.
X*/
X
XBlock *newblock() {
X	Block *ret = ul;
X
X	ul = NULL;
X	return ret;
X}
X
X/* "restores" an arena to its saved value. */
X
Xvoid restoreblock(Block *b) {
X	nfree();
X	ul = b;
X}
END_OF_FILE
  if test 2218 -ne `wc -c <'nalloc.c'`; then
    echo shar: \"'nalloc.c'\" unpacked with wrong size!
  fi
  # end of 'nalloc.c'
fi
if test -f 'nalloc.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'nalloc.h'\"
else
  echo shar: Extracting \"'nalloc.h'\" \(323 characters\)
  sed "s/^X//" >'nalloc.h' <<'END_OF_FILE'
Xextern Block *newblock(void);
Xextern void *nalloc(SIZE_T);
Xextern void nfree(void);
Xextern void restoreblock(Block *);
X
X#undef offsetof
X#define offsetof(t, m) ((SIZE_T) &((t *)0)->m)
X
X/* memory allocation abbreviation */
X#define nnew(x) ((x *) nalloc(sizeof(x)))
X#define ncpy(x) (strcpy((char *) nalloc(strlen(x) + 1), x))
END_OF_FILE
  if test 323 -ne `wc -c <'nalloc.h'`; then
    echo shar: \"'nalloc.h'\" unpacked with wrong size!
  fi
  # end of 'nalloc.h'
fi
if test -f 'node.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'node.h'\"
else
  echo shar: Extracting \"'node.h'\" \(356 characters\)
  sed "s/^X//" >'node.h' <<'END_OF_FILE'
Xenum nodetype {
X	rANDAND, ASSIGN, BACKQ, rBANG, BODY, NOWAIT, BRACE, CONCAT,
X	rCOUNT, rELSE, rFLAT, rDUP, EPILOG, NEWFN, FORIN, rIF,
X	rOROR, rPIPE, PRE, rREDIR, RMFN, ARGS, rSUBSHELL,
X	rSWITCH, MATCH, VAR, VARSUB, rWHILE, rWORD, LAPPEND, NMPIPE
X};
X
Xtypedef struct Node Node;
X
Xstruct Node {
X	enum nodetype type;
X	union { char *s; int i; Node *p; } u[3];
X};
END_OF_FILE
  if test 356 -ne `wc -c <'node.h'`; then
    echo shar: \"'node.h'\" unpacked with wrong size!
  fi
  # end of 'node.h'
fi
if test -f 'open.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'open.c'\"
else
  echo shar: Extracting \"'open.c'\" \(772 characters\)
  sed "s/^X//" >'open.c' <<'END_OF_FILE'
X/* open.c: to insulate <fcntl.h> from the rest of rc. */
X
X#include <fcntl.h>
X#include "lex.h"
X#include "open.h"
X
X/* prototype for open() follows. comment out if necessary */
X
X/*extern int open(const char *, int,...);*/
Xextern void rc_error(const char *);
X
X/*
X   Opens a file with the necessary flags. Assumes the following
X   declaration for enum redirtype:
X
X	enum redirtype {
X		FROM, CREATE, APPEND, HEREDOC, HERESTRING
X	};
X*/
X
Xstatic const int mode_masks[] = {
X	/* read */	O_RDONLY,
X	/* create */	O_TRUNC | O_CREAT | O_WRONLY,
X	/* append */	O_APPEND | O_CREAT | O_WRONLY
X};
X
Xint rc_open(const char *name, enum redirtype m) {
X	if ((unsigned int) m >= (sizeof(mode_masks)/sizeof(int)))
X		rc_error("bad mode passed to rc_open");
X
X	return open(name, mode_masks[m], 0644);
X}
END_OF_FILE
  if test 772 -ne `wc -c <'open.c'`; then
    echo shar: \"'open.c'\" unpacked with wrong size!
  fi
  # end of 'open.c'
fi
if test -f 'open.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'open.h'\"
else
  echo shar: Extracting \"'open.h'\" \(50 characters\)
  sed "s/^X//" >'open.h' <<'END_OF_FILE'
Xextern int rc_open(const char *, enum redirtype);
END_OF_FILE
  if test 50 -ne `wc -c <'open.h'`; then
    echo shar: \"'open.h'\" unpacked with wrong size!
  fi
  # end of 'open.h'
fi
if test -f 'parse.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'parse.h'\"
else
  echo shar: Extracting \"'parse.h'\" \(79 characters\)
  sed "s/^X//" >'parse.h' <<'END_OF_FILE'
Xextern Node *parsetree;
Xextern int yyparse(void);
Xextern void initparse(void);
END_OF_FILE
  if test 79 -ne `wc -c <'parse.h'`; then
    echo shar: \"'parse.h'\" unpacked with wrong size!
  fi
  # end of 'parse.h'
fi
if test -f 'rc.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'rc.h'\"
else
  echo shar: Extracting \"'rc.h'\" \(603 characters\)
  sed "s/^X//" >'rc.h' <<'END_OF_FILE'
X#include "stddef.h"
X#include "stdlib.h"
X#include "string.h"
X#include "unistd.h"
X
X#include "node.h"
X
X/* braindamaged IBM header files #define true and false */
X#undef FALSE
X#undef TRUE
X
Xenum bool { FALSE, TRUE };
X
Xtypedef enum bool boolean;
Xtypedef struct Rq Rq;
Xtypedef struct Block Block;
Xtypedef struct List List;
X
Xstruct List {
X	char *w;
X	char *m;
X	List *n;
X};
X
Xextern char *prompt, *prompt2;
Xextern Rq *redirq;
Xextern boolean dashdee, dashee, dashvee, dashex, dashell, dasheye, interactive;
Xextern int rc_pid;
Xextern int lineno;
Xextern List *fifoq;
X
X#define arraysize(a) ((int)sizeof(a)/sizeof(*a))
END_OF_FILE
  if test 603 -ne `wc -c <'rc.h'`; then
    echo shar: \"'rc.h'\" unpacked with wrong size!
  fi
  # end of 'rc.h'
fi
if test -f 'redir.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'redir.h'\"
else
  echo shar: Extracting \"'redir.h'\" \(28 characters\)
  sed "s/^X//" >'redir.h' <<'END_OF_FILE'
Xextern void doredirs(void);
END_OF_FILE
  if test 28 -ne `wc -c <'redir.h'`; then
    echo shar: \"'redir.h'\" unpacked with wrong size!
  fi
  # end of 'redir.h'
fi
if test -f 'status.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'status.c'\"
else
  echo shar: Extracting \"'status.c'\" \(2375 characters\)
  sed "s/^X//" >'status.c' <<'END_OF_FILE'
X/* status.c: functions for printing fancy status messages in rc */
X
X#include "rc.h"
X#include "utils.h"
X#include "status.h"
X#include "nalloc.h"
X#include "walk.h"
X#include "sigmsgs.h"
X
X/* status == the wait() value of the last command in the pipeline, or the last command */
X
Xstatic int statuses[512];
Xstatic int pipelength = 1;
X
X/*
X   Test to see if rc's status is true. According to td, status is true if and only if every
X   pipe-member has an exit status of zero.
X*/
X
Xint istrue(void) {
X	int i;
X
X	for (i = 0; i < pipelength; i++)
X		if (statuses[i] != 0)
X			return FALSE;
X	return TRUE;
X}
X
X/*
X   Return the status as an integer. A status which has low-bits set is a signal number,
X   whereas a status with high bits set is a value set from exit().
X*/
X
Xint getstatus(void) {
X	int s = statuses[0];
X
X	return s & 0xff ? s & 0x7f : (s >> 8) & 0xff;
X}
X
Xvoid set(boolean code) {
X	setstatus((!code) << 8); /* exit status 1 == 0x100 */
X}
X
X/* take a pipeline and store the exit statuses. Check to see whether any of the children dumped core */
X
Xvoid setpipestatus(int stats[], int num) {
X	int i;
X
X	for (i = 0; i < (pipelength = num); i++) {
X		statprint(stats[i]);
X		statuses[i] = stats[i];
X	}
X}
X
X/* set a simple status, as opposed to a pipeline */
X
Xvoid setstatus(int i) {
X	pipelength = 1;
X	statuses[0] = i;
X	statprint(i);
X}
X
X/* print a message if termination was with a signal, and if the child dumped core. exit on error if -e is set */
X
Xvoid statprint(int i) {
X	if (i & 0xff) {
X		char *msg = ((i & 0x7f) < NUMOFSIGNALS ? signals[i & 0x7f][1] : "");
X
X		if (i & 0x80) {
X			if (*msg == '\0')
X				fprint(2,"core dumped\n");
X			else
X				fprint(2,"%s--core dumped\n",msg);
X		} else if (*msg != '\0')
X			fprint(2,"%s\n",msg);
X	}
X
X	if (i != 0 && dashee && !cond)
X		rc_exit(getstatus());
X}
X
X/* prepare a list to be passed back. Used whenever $status is dereferenced */
X
XList *sgetstatus(void) {
X	List *r;
X	int i;
X
X	for (r = NULL, i = 0; i < pipelength; i++) {
X		char buf[16];
X		List *q = nnew(List);
X		int s = statuses[i];
X		int t;
X
X		q->n = r;
X		r = q;
X
X		if ((t = s & 0x7f) != 0) {
X			if (t < NUMOFSIGNALS && *signals[t][0] != '\0')
X				sprint(buf, "%s", signals[t][0]);
X			else
X				sprint(buf,"-%d", t); /* unknown signals are negated */
X			if (s & 0x80)
X				strcat(buf, "+core");
X		} else {
X			sprint(buf, "%d", (s >> 8) & 0xff);
X		}
X
X		r->w = ncpy(buf);
X		r->m = NULL;
X	}
X
X	return r;
X}
END_OF_FILE
  if test 2375 -ne `wc -c <'status.c'`; then
    echo shar: \"'status.c'\" unpacked with wrong size!
  fi
  # end of 'status.c'
fi
if test -f 'status.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'status.h'\"
else
  echo shar: Extracting \"'status.h'\" \(206 characters\)
  sed "s/^X//" >'status.h' <<'END_OF_FILE'
Xextern int istrue(void);
Xextern int getstatus(void);
Xextern void set(boolean);
Xextern void setstatus(int);
Xextern List *sgetstatus(void);
Xextern void setpipestatus(int [], int);
Xextern void statprint(int);
END_OF_FILE
  if test 206 -ne `wc -c <'status.h'`; then
    echo shar: \"'status.h'\" unpacked with wrong size!
  fi
  # end of 'status.h'
fi
if test -f 'stddef.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stddef.h'\"
else
  echo shar: Extracting \"'stddef.h'\" \(758 characters\)
  sed "s/^X//" >'stddef.h' <<'END_OF_FILE'
X/* stddef.h
X	This file provides a definition for size_t and align_t that
X	should work for your system. If it does not, it is up to you to
X	make it the right thing. The problem is that I cannot rely upon
X	<sys/params.h> to do the right thing on machines which don't
X	yet have ansi header files. Note that on many RISC machines,
X	align_t must be at least 32 bits wide, and sparc doubles are
X	aligned on 64 bit boundaries, but of course, rc does not use
X	doubles in its code, so the "typedef long ALIGN_T" is good
X	enough in the sparc's case. Also for performance reasons on a
X	VAX one would probably want align_t to be 32 bits wide.
X*/
Xtypedef long ALIGN_T;
Xtypedef unsigned int SIZE_T;
Xtypedef short int MODE_T;
Xtypedef int PID_T;
X
X#undef NULL
X#define NULL 0
END_OF_FILE
  if test 758 -ne `wc -c <'stddef.h'`; then
    echo shar: \"'stddef.h'\" unpacked with wrong size!
  fi
  # end of 'stddef.h'
fi
if test -f 'stdlib.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stdlib.h'\"
else
  echo shar: Extracting \"'stdlib.h'\" \(462 characters\)
  sed "s/^X//" >'stdlib.h' <<'END_OF_FILE'
X/*
X   stdlib.h function prototypes as taken from Appendix B of K&R 2.
X   Unused functions are:
X	atof(), atoi(), atol(), strtod(), strtol(), strtoul(), rand(),
X	srand(), calloc(), abort(), atexit(), system(), getenv(), bsearch(),
X	abs(), labs(), div() and ldiv()
X*/
X
Xextern void *malloc(SIZE_T);
Xextern void *realloc(void *, SIZE_T);
Xextern void free(void *);
Xextern void exit(int);
Xextern void qsort(void *, SIZE_T, SIZE_T, int (*)(const void *, const void *));
END_OF_FILE
  if test 462 -ne `wc -c <'stdlib.h'`; then
    echo shar: \"'stdlib.h'\" unpacked with wrong size!
  fi
  # end of 'stdlib.h'
fi
if test -f 'string.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'string.h'\"
else
  echo shar: Extracting \"'string.h'\" \(475 characters\)
  sed "s/^X//" >'string.h' <<'END_OF_FILE'
Xextern int strncmp(const char *, const char *, SIZE_T);
Xextern int strcmp(const char *, const char *);
Xextern SIZE_T strlen(const char *);
Xextern char *strchr(const char *, int);
Xextern char *strcpy(char *, const char *);
Xextern char *strncpy(char *, const char *, SIZE_T);
Xextern char *strcat(char *, const char *);
Xextern char *strncat(char *, const char *, SIZE_T);
Xextern void *memcpy(void *, const void *, SIZE_T);
X
X#define streq(x,y) (*(x) == *(y) && strcmp(x,y) == 0)
END_OF_FILE
  if test 475 -ne `wc -c <'string.h'`; then
    echo shar: \"'string.h'\" unpacked with wrong size!
  fi
  # end of 'string.h'
fi
if test -f 'tree.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tree.h'\"
else
  echo shar: Extracting \"'tree.h'\" \(132 characters\)
  sed "s/^X//" >'tree.h' <<'END_OF_FILE'
Xextern Node *newnode(int /*enum nodetype*/ t,...);
Xextern Node *treecpy(Node *s, void *(*)(SIZE_T));
Xextern void treefree(Node *s);
END_OF_FILE
  if test 132 -ne `wc -c <'tree.h'`; then
    echo shar: \"'tree.h'\" unpacked with wrong size!
  fi
  # end of 'tree.h'
fi
if test -f 'unistd.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'unistd.h'\"
else
  echo shar: Extracting \"'unistd.h'\" \(490 characters\)
  sed "s/^X//" >'unistd.h' <<'END_OF_FILE'
Xextern PID_T fork(void);
Xextern PID_T getpid(void);
Xextern int chdir(const char *);
Xextern int close(int);
Xextern int dup2(int, int);
Xextern int execve(const char *, const char **, const char **);
Xextern int isatty(int);
Xextern int mknod(const char *, int, int);
Xextern int pipe(int *);
Xextern int read(int, void *, unsigned int);
Xextern int setpgrp(int, PID_T);
Xextern int unlink(const char *);
Xextern int write(int, const void *, unsigned int);
Xextern int wait(int *);
X
Xextern int errno;
END_OF_FILE
  if test 490 -ne `wc -c <'unistd.h'`; then
    echo shar: \"'unistd.h'\" unpacked with wrong size!
  fi
  # end of 'unistd.h'
fi
if test -f 'utils.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'utils.h'\"
else
  echo shar: Extracting \"'utils.h'\" \(854 characters\)
  sed "s/^X//" >'utils.h' <<'END_OF_FILE'
Xextern char *strprint(char *, int, int);
Xextern char *sprint(char *, char *,...);
Xextern int isabsolute(char *); /* not boolean because y.tab.c includes utils.h */
Xextern int a2u(char *);
Xextern int o2u(char *);
Xextern int starstrcmp(const void *, const void *);
Xextern void *ealloc(SIZE_T);
Xextern void *erealloc(void *, SIZE_T);
Xextern void efree(void *);
Xextern void fprint(int, char *,...);
Xextern void empty_fifoq(void);
Xextern void rc_error(char *);
Xextern void rc_exit(int); /* prototyped here, but defined in fn.c */
Xextern void sig(int);
Xextern void clear(char *, SIZE_T);
Xextern void uerror(char *);
Xextern void writeall(int, char *, SIZE_T);
Xextern SIZE_T strarraylen(char **);
X
X/* memory allocation abbreviations */
X#define enew(x) ((x *) ealloc(sizeof(x)))
X#define ecpy(x) strcpy((char *) ealloc(strlen(x) + 1),x)
X
X#define FPRINT_SIZE 16384
END_OF_FILE
  if test 854 -ne `wc -c <'utils.h'`; then
    echo shar: \"'utils.h'\" unpacked with wrong size!
  fi
  # end of 'utils.h'
fi
if test -f 'version.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'version.c'\"
else
  echo shar: Extracting \"'version.c'\" \(63 characters\)
  sed "s/^X//" >'version.c' <<'END_OF_FILE'
Xstatic volatile const char *id = "rc version 1.0, 5/20/91.\n";
END_OF_FILE
  if test 63 -ne `wc -c <'version.c'`; then
    echo shar: \"'version.c'\" unpacked with wrong size!
  fi
  # end of 'version.c'
fi
if test -f 'walk.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'walk.h'\"
else
  echo shar: Extracting \"'walk.h'\" \(59 characters\)
  sed "s/^X//" >'walk.h' <<'END_OF_FILE'
Xextern boolean walk(Node *, boolean);
Xextern boolean cond;
END_OF_FILE
  if test 59 -ne `wc -c <'walk.h'`; then
    echo shar: \"'walk.h'\" unpacked with wrong size!
  fi
  # end of 'walk.h'
fi
echo shar: End of archive 4 \(of 4\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 4 archives.
    rm -f ark[1-9]isdone
else
    echo You still must unpack the following archives:
    echo "        " ${MISSING}
fi
exit 0
exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.