v20i013: rc - A Plan 9 shell reimplementation, Part04/04
Byron Rakitzis
byron at archone.tamu.edu
Thu May 23 01:43:44 AEST 1991
Submitted-by: Byron Rakitzis <byron at 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 at 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 at 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 at 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 at uunet.uu.net.
More information about the Comp.sources.misc
mailing list