home *** CD-ROM | disk | FTP | other *** search
- From: netnews@netcom.UUCP (USENET Administration)
- Newsgroups: alt.sources
- Subject: Public Domain Korn Shell - Part.02 of 7
- Message-ID: <18607@netcom.UUCP>
- Date: 12 Dec 90 11:35:35 GMT
-
- #!/bin/sh
- # This is part 02 of ksh-pd
- # ============= src/lex.h ==============
- if test ! -d 'src'; then
- echo 'x - creating directory src'
- mkdir 'src'
- fi
- if test -f 'src/lex.h' -a X"$1" != X"-c"; then
- echo 'x - skipping src/lex.h (File already exists)'
- else
- echo 'x - extracting src/lex.h (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'src/lex.h' &&
- X/*
- X * Source input, lexer and parser
- X */
- X
- X/* $Header: /tmp/egisin/src/RCS/lex.h,v 3.2 88/12/17 21:40:07 egisin Exp $ */
- X
- X#define IDENT 64
- X
- Xtypedef struct source Source;
- Xstruct source {
- X char *str; /* input pointer */
- X int type; /* input type */
- X union {
- X char **strv; /* string [] */
- X FILE *file; /* file */
- X struct tbl *tblp; /* alias */
- X } u;
- X int line; /* line number */
- X char *file; /* input file name */
- X int echo; /* echo input to shlout */
- X Source *next; /* stacked source */
- X};
- X
- X/* Source.type values */
- X#define SEOF 0 /* input EOF */
- X#define STTY 1 /* terminal input */
- X#define SFILE 2 /* file input */
- X#define SSTRING 4 /* string */
- X#define SWSTR 3 /* string without \n */
- X#define SWORDS 5 /* string[] */
- X#define SWORDSEP 8 /* string[] seperator */
- X#define SALIAS 6 /* alias expansion */
- X#define SHIST 7 /* history expansion */
- X
- XSource *pushs ARGS((int stype)); /* push Source */
- Xstruct op *compile ARGS((Source *s)); /* compile tree */
- X
- X/*
- X * states while lexing word
- X */
- X#define SBASE 0 /* outside any lexical constructs */
- X#define SWORD 6 /* implicit quoting for substitute() */
- X#define SSQUOTE 1 /* inside '' */
- X#define SDQUOTE 2 /* inside "" */
- X#define SBRACE 3 /* inside ${} */
- X#define SPAREN 4 /* inside $() */
- X#define SBQUOTE 5 /* inside `` */
- X
- XExtern int multiline; /* \n changed to ; */
- X
- Xtypedef union {
- X int i;
- X char *cp;
- X char **wp;
- X struct op *o;
- X struct ioword *iop;
- X} YYSTYPE;
- X
- X#define LWORD 256
- X#define LOGAND 257
- X#define LOGOR 258
- X#define BREAK 259
- X#define IF 260
- X#define THEN 261
- X#define ELSE 262
- X#define ELIF 263
- X#define FI 264
- X#define CASE 265
- X#define ESAC 266
- X#define FOR 267
- X#define WHILE 268
- X#define UNTIL 269
- X#define DO 270
- X#define DONE 271
- X#define IN 272
- X#define FUNCTION 273
- X#define TIME 274
- X#define REDIR 275
- X#define MPAREN 276 /* () */
- X#define YYERRCODE 300
- X
- X/* flags to yylex */
- X#define CONTIN BIT(0) /* skip new lines to complete command */
- X#define ONEWORD BIT(1) /* single word for substitute() */
- X#define ALIAS BIT(2) /* recognize alias */
- X#define KEYWORD BIT(3) /* recognize keywords */
- X
- X#define SYNTAXERR zzerr()
- X#define HERES 10 /* max << in line */
- X
- XExtern char line [LINE+1]; /* input line */
- XExtern Source *source; /* yyparse/yylex source */
- XExtern YYSTYPE yylval; /* result from yylex */
- XExtern int yynerrs;
- XExtern struct ioword *heres [HERES], **herep;
- XExtern char ident [IDENT+1];
- X
- Xextern int yylex ARGS((int flags));
- Xextern void yyerror ARGS((Const char *msg));
- X
- X#define HISTORY 100 /* size of saved history */
- X
- Xextern char *history [HISTORY]; /* saved commands */
- Xextern char **histptr; /* last history item */
- Xextern int histpush; /* number of pushed fc commands */
- X
- SHAR_EOF
- true || echo 'restore of src/lex.h failed'
- fi
- # ============= src/tree.h ==============
- if test -f 'src/tree.h' -a X"$1" != X"-c"; then
- echo 'x - skipping src/tree.h (File already exists)'
- else
- echo 'x - extracting src/tree.h (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'src/tree.h' &&
- X/*
- X * command trees for compile/execute
- X */
- X
- X/* $Header: /tmp/egisin/src/RCS/tree.h,v 3.2 88/12/17 21:40:31 egisin Exp $ */
- X
- X#define NOBLOCK ((struct op *)NULL)
- X#define NOWORD ((char *)NULL)
- X#define NOWORDS ((char **)NULL)
- X
- X/*
- X * Description of a command or an operation on commands.
- X */
- Xstruct op {
- X int type; /* operation type, see below */
- X char **args; /* arguments to a command */
- X char **vars; /* variable assignments */
- X struct ioword **ioact; /* IO actions (eg, < > >>) */
- X struct op *left, *right; /* descendents */
- X char *str; /* identifier for case and for (use vars[0]) */
- X};
- X
- X/* Tree.type values */
- X#define TEOF 0
- X#define TCOM 1 /* command */
- X#define TPAREN 2 /* (c-list) */
- X#define TPIPE 3 /* a | b */
- X#define TLIST 4 /* a [&;] b */
- X#define TOR 5 /* || */
- X#define TAND 6 /* && */
- X#define TFOR 7
- X#define TCASE 9
- X#define TIF 10
- X#define TWHILE 11
- X#define TUNTIL 12
- X#define TELIF 13
- X#define TPAT 14 /* pattern in case */
- X#define TBRACE 15 /* {c-list} */
- X#define TASYNC 16 /* c & */
- X#define TFUNCT 17 /* function name { command; } */
- X#define TTIME 18 /* time pipeline */
- X#define TEXEC 19 /* fork/exec eval'd TCOM */
- X
- X/*
- X * prefix codes for words in command tree
- X */
- X#define EOS 0 /* end of string */
- X#define CHAR 1 /* unquoted character */
- X#define QCHAR 2 /* quoted character */
- X#define COMSUB 3 /* $() substitution (0 terminated) */
- X#define OQUOTE 4 /* opening " or ' */
- X#define CQUOTE 5 /* closing " or ' */
- X#define OSUBST 6 /* opening ${ substitution */
- X#define CSUBST 7 /* closing } of above */
- X
- X/*
- X * IO redirection
- X */
- Xstruct ioword {
- X short unit; /* unit affected */
- X short flag; /* action (below) */
- X char *name; /* file name */
- X};
- X
- X/* ioword.flag - type of redirection */
- X#define IOTYPE 0xF /* type: bits 0:3 */
- X#define IOREAD 0x1 /* < */
- X#define IOWRITE 0x2 /* > */
- X#define IORDWR 0x3 /* <>: todo */
- X#define IOHERE 0x4 /* << (here file) */
- X#define IOCAT 0x5 /* >> */
- X#define IODUP 0x6 /* <&/>& */
- X#define IOEVAL BIT(4) /* expand in << */
- X#define IOSKIP BIT(5) /* <<-, skip ^\t* */
- X#define IOCLOB BIT(6) /* >!, override -o noclob */
- X
- X/* values for E_LOOP longjmp */
- X#define LBREAK 1
- X#define LCONTIN 2
- X
- X/* execute/exchild flags */
- X#define XEXEC BIT(0) /* execute without forking */
- X#define XFORK BIT(5) /* fork before executing */
- X#define XBGND BIT(1) /* command & */
- X#define XPIPEI BIT(2) /* input is pipe */
- X#define XPIPEO BIT(3) /* output is pipe */
- X#define XPIPE (XPIPEI|XPIPEO) /* member of pipe */
- X#define XXCOM BIT(4) /* dup2 xcomfd to 1 */
- X
- X/*
- X * flags to control expansion of words
- X */
- X#define DOBLANK BIT(1) /* perform blank interpretation */
- X#define DOGLOB BIT(2) /* expand [?* */
- X#define DOPAT BIT(3) /* quote *?[ */
- X#define DOTILDE BIT(5) /* expand ~ */
- X
- X/* job.c: job control primatives */
- Xint execute ARGS((struct op *, int flags)); /* execute tree */
- Xint exchild ARGS((struct op *, int flags)); /* execute tree as child */
- Xint waitfor ARGS((int job)); /* wait for job completion */
- Xint waitlast ARGS((void)); /* wait for last job */
- X
- X/* eval.c: word expansion */
- Xchar **eval ARGS((char **wv, int flag)); /* expand words */
- Xchar *evalstr ARGS((char *wp, int flags)); /* expand word */
- Xchar *substitute ARGS((Const char *s, int flags)); /* compile and expand string */
- X
- X/* tree.c: command trees */
- Xvoid ptree ARGS((struct op *t, FILE *f)); /* print tree */
- Xchar *wdscan ARGS((char *wp, int c)); /* scan word for prefix */
- Xchar *wdcopy ARGS((char *wp, Area *)); /* copy word */
- Xstruct op *tcopy ARGS((struct op *t, Area *)); /* copy tree */
- Xvoid tfree ARGS((struct op *t, Area *)); /* free tree */
- X
- SHAR_EOF
- true || echo 'restore of src/tree.h failed'
- fi
- # ============= src/tty.h ==============
- if test -f 'src/tty.h' -a X"$1" != X"-c"; then
- echo 'x - skipping src/tty.h (File already exists)'
- else
- echo 'x - extracting src/tty.h (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'src/tty.h' &&
- X/*
- X tty.h -- centralized definitions for a variety of terminal interfaces
- X
- X created by DPK, Oct. 1986
- X
- X last edit: 30-Jul-1987 D A Gwyn
- X*/
- X
- X#if _BSD_SYSV /* BRL UNIX System V emulation */
- X#include <termio.h> /* includes <sys/_ioctl.h> */
- X#ifndef NTTYDISC
- X#define TIOCGETD _IOR( 't', 0, int )
- X#define TIOCSETD _IOW( 't', 1, int )
- X#define NTTYDISC 2
- X#endif
- X#ifndef TIOCSTI
- X#define TIOCSTI _IOW( 't', 114, char )
- X#endif
- X#ifndef TIOCSPGRP
- X#define TIOCSPGRP _IOW( 't', 118, int )
- X#endif
- X#else /* !_BSD_SYSV */
- X#if _BSD
- X#include <sys/ioctl.h>
- X#else
- X#include <termio.h>
- X#endif
- X#endif /* _BSD_SYSV */
- SHAR_EOF
- true || echo 'restore of src/tty.h failed'
- fi
- # ============= src/version.c ==============
- if test -f 'src/version.c' -a X"$1" != X"-c"; then
- echo 'x - skipping src/version.c (File already exists)'
- else
- echo 'x - extracting src/version.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'src/version.c' &&
- X/*
- X * value of $KSH_VERSION
- X */
- X
- Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/version.c,v 3.2 88/12/14 20:10:41 egisin Exp $";
- X
- X#include <stddef.h>
- X#include <setjmp.h>
- X#include "sh.h"
- X
- Xchar ksh_version [] =
- X "KSH_VERSION=@(#) PD alpha $Revision: 3.2 $ $Date: 88/12/14 20:10:41 $";
- X
- X/***
- X$Log: version.c,v $
- XRevision 3.2 88/12/14 20:10:41 egisin
- Xmany fixes
- X
- XRevision 3.1 88/11/03 09:18:36 egisin
- Xalpha distribution
- X
- XRevision 1.3 88/10/20 17:34:03 egisin
- Xadded @(#) to ksh_version
- X
- XRevision 1.2 88/09/27 19:01:58 egisin
- Xfix version.c
- X
- XRevision 1.1 88/09/27 18:59:06 egisin
- XInitial revision
- X***/
- X
- SHAR_EOF
- true || echo 'restore of src/version.c failed'
- fi
- # ============= src/main.c ==============
- if test -f 'src/main.c' -a X"$1" != X"-c"; then
- echo 'x - skipping src/main.c (File already exists)'
- else
- echo 'x - extracting src/main.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'src/main.c' &&
- X/*
- X * startup, main loop, enviroments and error handling
- X */
- X
- Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/main.c,v 3.2 88/12/17 19:56:54 egisin Exp $";
- X
- X#define Extern /* define Externs in sh.h */
- X
- X#include <stddef.h>
- X#include <stdlib.h>
- X#include <stdio.h>
- X#include <string.h>
- X#include <unistd.h>
- X#include <fcntl.h>
- X#include <signal.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include "sh.h"
- X#include "lex.h"
- X#include "tree.h"
- X#include "table.h"
- X
- X/*
- X * global data
- X */
- X
- XArea aperm;
- X
- Xstatic void reclaim ARGS((void));
- X
- X/*
- X * shell initialization
- X */
- X
- Xstatic char initifs [] = "IFS= \t\n"; /* must be R/W */
- X
- Xstatic Const char initsubs [] =
- X "${SHELL:=/bin/sh} ${PATH:=/bin:/usr/bin:.} ${HOME:=/} ${PS1:=$ } ${PS2:=> }";
- X
- Xstatic Const char *initcoms [] = {
- X "cd", ".", NULL, /* set up $PWD */
- X "typeset", "-x", "SHELL", "PATH", "HOME", NULL,
- X "typeset", "-r", "PWD", "OLDPWD", NULL,
- X "typeset", "-i", "SECONDS=0", "OPTIND", NULL,
- X "alias",
- X "integer=typeset -i", "pwd=print -r \"$PWD\"",
- X "history=fc -l", "r=fc -s", "nohup=nohup ",
- X "login=exec login", "newgrp=exec newgrp",
- X "type=whence -v", "functions=typeset -f",
- X "echo=print", "true=:", "false=let", "[=\\[", NULL,
- X NULL
- X};
- X
- Xmain(argc, argv, envp)
- X int argc;
- X register char **argv;
- X char **envp;
- X{
- X register int i;
- X register char *arg;
- X int cflag = 0, qflag = 0;
- X char *name;
- X register Source *s;
- X register struct block *l = &globals;
- X register char **wp0, **wp;
- X extern char ksh_version [];
- X
- X ainit(&aperm); /* initialize permanent Area */
- X
- X /* set up base enviroment */
- X e.type = E_NONE;
- X ainit(&e.area);
- X e.loc = l;
- X e.savefd = NULL;
- X e.oenv = NULL;
- X
- X initctypes();
- X
- X /* open file streams for fd's 0,1,2 */
- X fopenshf(0); fopenshf(1); fopenshf(2);
- X
- X /* set up variable and command dictionaries */
- X newblock(); /* set up global l->vars and l->funs */
- X tinit(&commands, APERM);
- X tinit(&builtins, APERM);
- X tinit(&lexicals, APERM);
- X tinit(&homedirs, APERM);
- X
- X /* import enviroment */
- X if (envp != NULL)
- X for (wp = envp; *wp != NULL; wp++)
- X import(*wp);
- X
- X typeset(initifs, 0, 0); /* for security */
- X typeset(ksh_version, 0, 0); /* RDONLY */
- X
- X /* define shell keywords */
- X keywords();
- X
- X /* define built-in commands */
- X for (i = 0; shbuiltins[i].name != NULL; i++)
- X builtin(shbuiltins[i].name, shbuiltins[i].func);
- X for (i = 0; kshbuiltins[i].name != NULL; i++)
- X builtin(kshbuiltins[i].name, kshbuiltins[i].func);
- X
- X /* assign default shell variable values */
- X substitute(initsubs, 0);
- X /* execute initialization statements */
- X for (wp0 = (char**) initcoms; *wp0 != NULL; wp0 = wp+1) {
- X /* copy because the alias initializers are readonly */
- X for (wp = wp0; *wp != NULL; wp++)
- X *wp = strsave(*wp, ATEMP);
- X shcomexec(wp0);
- X }
- X afreeall(ATEMP);
- X
- X if (geteuid() == 0)
- X setstr(global("PS1"), "# ");
- X
- X s = pushs(SFILE);
- X s->u.file = stdin;
- X cflag = 0;
- X name = *argv++;
- X
- X /* what a bloody mess */
- X if (--argc >= 1) {
- X if (argv[0][0] == '-' && argv[0][1] != '\0') {
- X for (arg = argv[0]+1; *arg; arg++)
- X switch (*arg) {
- X case 'c':
- X cflag = 1;
- X if (--argc > 0) {
- X s->type = SSTRING;
- X s->str = *++argv;
- X }
- X break;
- X
- X case 'q':
- X qflag = 1;
- X break;
- X
- X default:
- X if (*arg>='a' && *arg<='z')
- X flag[FLAG(*arg)]++;
- X }
- X } else {
- X argv--;
- X argc++;
- X }
- X if (s->type == SFILE && --argc > 0) {
- X if ((s->u.file = fopen(*++argv, "r")) == NULL)
- X errorf("%s: cannot open\n", *argv);
- X s->file = *argv;
- X fileno(s->u.file) = savefd(fileno(s->u.file));
- X setvbuf(s->u.file, (char *)NULL, _IOFBF, BUFSIZ);
- X }
- X }
- X
- X if (s->type == SFILE) {
- X if (fileno(s->u.file) == 0)
- X flag[FSTDIN] = 1;
- X if (isatty(0) && isatty(1) && !cflag)
- X flag[FTALKING] = 1;
- X if (flag[FTALKING] && flag[FSTDIN])
- X s->type = STTY;
- X }
- X if (s->type == STTY) {
- X ttyfd = fcntl(0, F_DUPFD, FDBASE);
- X (void) fcntl(ttyfd, F_SETFD, FD_CLEXEC);
- X#if EDIT
- X x_init();
- X#endif
- X }
- X
- X /* initialize job control */
- X j_init();
- X
- X if (!qflag)
- X ignoresig(SIGQUIT);
- X
- X l->argv = argv;
- X l->argc = argc;
- X l->argv[0] = name;
- X resetopts();
- X
- X if (name[0] == '-') {
- X flag[FTALKING] = 1;
- X (void) include("/etc/profile");
- X (void) include(".profile");
- X }
- X
- X /* include $ENV */
- X arg = substitute(strval(global("ENV")), DOTILDE);
- X if (*arg != '\0')
- X (void) include(arg);
- X
- X if (flag[FTALKING]) {
- X signal(SIGTERM, trapsig);
- X ignoresig(SIGINT);
- X } else
- X flag[FHASHALL] = 1;
- X
- X#if JOBS /* todo: could go before includes? */
- X if (s->type == STTY) {
- X flag[FMONITOR] = 1;
- X j_change();
- X }
- X#endif
- X
- X argc = shell(s);
- X leave(argc);
- X}
- X
- Xint
- Xinclude(name)
- X register char *name;
- X{
- X register FILE *f;
- X register Source *s;
- X
- X if (strcmp(name, "-") != 0) {
- X f = fopen(name, "r");
- X if (f == NULL)
- X return 0;
- X /* todo: the savefd doesn't get popped */
- X fileno(f) = savefd(fileno(f)); /* questionable */
- X setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
- X } else
- X f = stdin;
- X s = pushs(SFILE);
- X s->u.file = f;
- X s->file = name;
- X /*return*/ shell(s);
- X if (f != stdin)
- X fclose(f);
- X return 1;
- X}
- X
- Xint
- Xcommand(comm)
- X register char *comm;
- X{
- X register Source *s;
- X
- X s = pushs(SSTRING);
- X s->str = comm;
- X return shell(s);
- X}
- X
- X/*
- X * run the commands from the input source, returning status.
- X */
- Xint
- Xshell(s)
- X Source *s; /* input source */
- X{
- X struct op *t;
- X Volatile int attempts = 13;
- X
- X newenv(E_PARSE);
- X e.interactive = 1;
- X exstat = 0;
- X if (setjmp(e.jbuf)) {
- X /*shellf("<unwind>");*/
- X if (trap) /* pending SIGINT */
- X shellf("\n");
- X sigtraps[SIGINT].set = 0;
- X }
- X
- X while (1) {
- X if (trap)
- X runtraps();
- X if (flag[FTALKING])
- X signal(SIGINT, trapsig);
- X
- X if (s->next == NULL)
- X s->echo = flag[FVERBOSE];
- X
- X j_notify();
- X
- X if (s->type == STTY)
- X prompt = substitute(strval(global("PS1")), 0);
- X
- X t = compile(s);
- X if (t != NULL && t->type == TEOF)
- X if (s->type == STTY && flag[FIGNEOF] && --attempts > 0)
- X shellf("Use `exit'\n");
- X else
- X break;
- X flushshf(2); /* flush -v output */
- X
- X if (!flag[FNOEXEC] || s->type == STTY)
- X execute(t, 0);
- X
- X reclaim();
- X }
- X Error:
- X quitenv();
- X return exstat;
- X}
- X
- Xvoid
- Xleave(rv)
- X int rv;
- X{
- X if (e.type == E_TCOM && e.oenv != NULL) /* exec'd command */
- X unwind();
- X runtrap(&sigtraps[0]);
- X j_exit();
- X exit(rv);
- X /* NOTREACHED */
- X}
- X
- Xerror()
- X{
- X if (flag[FERREXIT] || !flag[FTALKING])
- X leave(1);
- X unwind();
- X}
- X
- X/* return to closest error handler or shell(), exit if none found */
- Xunwind()
- X{
- X while (1)
- X switch (e.type) {
- X case E_NONE:
- X leave(1);
- X /* NOTREACHED */
- X case E_PARSE:
- X longjmp(e.jbuf, 1);
- X /* NOTREACHED */
- X case E_ERRH:
- X longjmp(e.jbuf, 1);
- X /* NOTREACHED */
- X default:
- X quitenv();
- X break;
- X }
- X}
- X
- Xnewenv(type)
- X{
- X register struct env *ep;
- X
- X ep = (struct env *) alloc(sizeof(*ep), ATEMP);
- X *ep = e;
- X ainit(&e.area);
- X e.type = type;
- X e.oenv = ep;
- X e.savefd = NULL;
- X e.temps = NULL;
- X}
- X
- Xquitenv()
- X{
- X register struct env *ep;
- X register int fd;
- X
- X if ((ep = e.oenv) == NULL)
- X exit(exstat); /* exit child */
- X if (e.loc != ep->loc)
- X popblock();
- X if (e.savefd != NULL)
- X for (fd = 0; fd < NUFILE; fd++)
- X restfd(fd, e.savefd[fd]);
- X reclaim();
- X e = *ep;
- X}
- X
- X/* remove temp files and free ATEMP Area */
- Xstatic void
- Xreclaim()
- X{
- X register struct temp *tp;
- X
- X for (tp = e.temps; tp != NULL; tp = tp->next)
- X remove(tp->name);
- X e.temps = NULL;
- X afreeall(&e.area);
- X}
- X
- Xvoid
- Xaerror(ap, msg)
- X Area *ap;
- X Const char *msg;
- X{
- X errorf("alloc internal error: %s\n", msg);
- X}
- X
- SHAR_EOF
- true || echo 'restore of src/main.c failed'
- fi
- # ============= src/misc.c ==============
- if test -f 'src/misc.c' -a X"$1" != X"-c"; then
- echo 'x - skipping src/misc.c (File already exists)'
- else
- echo 'x - extracting src/misc.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'src/misc.c' &&
- X/*
- X * Miscellaneous functions
- X */
- X
- Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/misc.c,v 3.1 88/11/03 09:17:14 egisin Exp $";
- X
- X#include <stddef.h>
- X#include <limits.h>
- X#include <string.h>
- X#include <signal.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include "sh.h"
- X#include "expand.h"
- X
- Xchar ctypes [UCHAR_MAX]; /* type bits for unsigned char */
- X
- X/*
- X * Fast character classes
- X */
- Xvoid
- Xsetctypes(s, t)
- X register Const char *s;
- X register int t;
- X{
- X register int i;
- X
- X if ((t&C_IFS)) {
- X for (i = 0; i < UCHAR_MAX; i++)
- X ctypes[i] &=~ C_IFS;
- X ctypes[0] |= C_IFS; /* include \0 in C_IFS */
- X }
- X ctypes[(unsigned char) *s++] |= t; /* allow leading \0 in string */
- X while (*s != 0)
- X ctypes[(unsigned char) *s++] |= t;
- X}
- X
- Xvoid
- Xinitctypes()
- X{
- X register int c;
- X
- X for (c = 'a'; c <= 'z'; c++)
- X ctypes[c] |= C_ALPHA;
- X for (c = 'A'; c <= 'Z'; c++)
- X ctypes[c] |= C_ALPHA;
- X ctypes['_'] |= C_ALPHA;
- X setctypes("0123456789", C_DIGIT);
- X setctypes("\0 \t\n|&;<>()", C_LEX1);
- X setctypes("*@#!$-?", C_VAR1);
- X setctypes("=-+?#%", C_SUBOP);
- X}
- X
- X/* convert unsigned long to base N string */
- X
- Xchar *
- Xulton(n, base)
- X register unsigned long n;
- X int base;
- X{
- X register char *p;
- X static char buf [20];
- X
- X p = &buf[sizeof(buf)];
- X *--p = '\0';
- X do {
- X *--p = "0123456789ABCDEF"[n%base];
- X n /= base;
- X } while (n != 0);
- X return p;
- X}
- X
- Xchar *
- Xstrsave(s, ap)
- X register char *s;
- X Area *ap;
- X{
- X return strcpy((char*) alloc((size_t)strlen(s)+1, ap), s);
- X}
- X
- Xstatic struct option {
- X char *name;
- X int flag;
- X} options[] = {
- X {"allexport", FEXPORT},
- X {"bgnice", FBGNICE},
- X#if EDIT
- X {"emacs", FEMACS},
- X#endif
- X {"errexit", FERREXIT},
- X {"hashall", FHASHALL},
- X {"ignoreeof", FIGNEOF},
- X {"interactive", FTALKING},
- X {"keyword", FKEYWORD},
- X {"markdirs", FMARKDIRS},
- X {"monitor", FMONITOR},
- X {"noexec", FNOEXEC},
- X {"noglob", FNOGLOB},
- X {"nounset", FNOUNSET},
- X {"privileged", FPRIVILEGED},
- X {"stdin", FSTDIN},
- X {"trackall", FHASHALL},
- X {"verbose", FVERBOSE},
- X {"xtrace", FXTRACE},
- X {NULL, 0}
- X};
- X
- X/*
- X * translate -o option into F* constant
- X */
- Xint
- Xoption(n)
- X Const char *n;
- X{
- X register struct option *op;
- X
- X for (op = options; op->name != NULL; op++)
- X if (strcmp(op->name, n) == 0)
- X return op->flag;
- X return 0;
- X}
- X
- Xchar *
- Xgetoptions()
- X{
- X register int c;
- X char m [26+1];
- X register char *cp = m;
- X
- X for (c = 'a'; c <= 'z'; c++)
- X if (flag[FLAG(c)])
- X *cp++ = (char) c;
- X *cp = 0;
- X return strsave(m, ATEMP);
- X}
- X
- Xvoid
- Xprintoptions()
- X{
- X register struct option *op;
- X
- X for (op = options; op->name != NULL; op++)
- X if (flag[op->flag])
- X shellf("%s ", op->name);
- X shellf("\n");
- X}
- X
- X/* atoi with error detection */
- X
- Xgetn(as)
- X char *as;
- X{
- X register char *s;
- X register int n;
- X
- X s = as;
- X if (*s == '-')
- X s++;
- X for (n = 0; digit(*s); s++)
- X n = (n*10) + (*s-'0');
- X if (*s)
- X errorf("%s: bad number\n", as);
- X return (*as == '-') ? -n : n;
- X}
- X
- X/*
- X * stripped down strerror for kill and exec
- X */
- Xchar *
- Xstrerror(i)
- X int i;
- X{
- X switch (i) {
- X case EINVAL:
- X return "Invalid argument";
- X case EACCES:
- X return "Permission denied";
- X case ESRCH:
- X return "No such process";
- X case EPERM:
- X return "Not owner";
- X case ENOENT:
- X return "No such file or directory";
- X case ENOTDIR:
- X return "Not a directory";
- X case ENOEXEC:
- X return "Exec format error";
- X case ENOMEM:
- X return "Not enough memory";
- X case E2BIG:
- X return "Argument list too long";
- X default:
- X return "Unknown system error";
- X }
- X}
- X
- Xxpexpand(xp)
- X register XPtrV *xp;
- X{
- X int n = XPsize(*xp);
- X Void **vp;
- X register Void **dvp, **svp;
- X
- X vp = alloc(sizeofN(Void*, n*2), ATEMP);
- X for (svp = xp->beg, dvp = vp; svp < xp->cur; )
- X *dvp++ = *svp++;
- X afree((Void*) xp->beg, ATEMP);
- X xp->beg = vp;
- X xp->cur = vp + n;
- X xp->end = vp + n*2;
- X}
- X
- X/* -------- gmatch.c -------- */
- X
- X/*
- X * int gmatch(string, pattern)
- X * char *string, *pattern;
- X *
- X * Match a pattern as in sh(1).
- X * pattern character are prefixed with MAGIC by expand.
- X */
- X
- X#define NOT '!' /* might use ^ */
- X
- Xstatic char *cclass ARGS((char *, int c));
- X
- Xint
- Xgmatch(s, p)
- X register char *s, *p;
- X{
- X register int sc, pc;
- X
- X if (s == NULL || p == NULL)
- X return 0;
- X while ((pc = *p++) != 0) {
- X sc = *s++;
- X if (pc == MAGIC)
- X switch (*p++) {
- X case '[':
- X if ((p = cclass(p, sc)) == NULL)
- X return (0);
- X break;
- X
- X case '?':
- X if (sc == 0)
- X return (0);
- X break;
- X
- X case '*':
- X s--;
- X do {
- X if (*p == '\0' || gmatch(s, p))
- X return (1);
- X } while (*s++ != '\0');
- X return (0);
- X
- X }
- X else
- X if (sc != pc)
- X return 0;
- X }
- X return (*s == 0);
- X}
- X
- Xstatic char *
- Xcclass(p, sub)
- X register char *p;
- X register int sub;
- X{
- X register int c, d, not, found = 0;
- X
- X if ((not = *p == NOT))
- X p++;
- X do {
- X if (*p == '\0')
- X return NULL;
- X c = *p;
- X if (p[1] == '-' && p[2] != ']') {
- X d = p[2];
- X p++;
- X } else
- X d = c;
- X if (c == sub || c <= sub && sub <= d)
- X found = 1;
- X } while (*++p != ']');
- X
- X return (found != not) ? p+1 : NULL;
- X}
- X
- X/* -------- qsort.c -------- */
- X
- X/*
- X * quick sort of array of generic pointers to objects.
- X */
- X
- Xvoid
- Xqsortp(base, n, f)
- X Void **base; /* base address */
- X size_t n; /* elements */
- X int (*f)(); /* compare function */
- X{
- X qsort1(base, base + n, f);
- X}
- X
- X#define swap2(a, b) {\
- X register Void *t; t = *(a); *(a) = *(b); *(b) = t;\
- X}
- X#define swap3(a, b, c) {\
- X register Void *t; t = *(a); *(a) = *(c); *(c) = *(b); *(b) = t;\
- X}
- X
- Xqsort1(base, lim, f)
- X Void **base, **lim;
- X int (*f)();
- X{
- X register Void **i, **j;
- X register Void **lptr, **hptr;
- X size_t n;
- X int c;
- X
- X top:
- X n = (lim - base) / 2;
- X if (n == 0)
- X return;
- X hptr = lptr = base+n;
- X i = base;
- X j = lim - 1;
- X
- X for (;;) {
- X if (i < lptr) {
- X if ((c = (*f)(*i, *lptr)) == 0) {
- X lptr --;
- X swap2(i, lptr);
- X continue;
- X }
- X if (c < 0) {
- X i += 1;
- X continue;
- X }
- X }
- X
- X begin:
- X if (j > hptr) {
- X if ((c = (*f)(*hptr, *j)) == 0) {
- X hptr ++;
- X swap2(hptr, j);
- X goto begin;
- X }
- X if (c > 0) {
- X if (i == lptr) {
- X hptr ++;
- X swap3(i, hptr, j);
- X i = lptr += 1;
- X goto begin;
- X }
- X swap2(i, j);
- X j -= 1;
- X i += 1;
- X continue;
- X }
- X j -= 1;
- X goto begin;
- X }
- X
- X if (i == lptr) {
- X if (lptr-base >= lim-hptr) {
- X qsort1(hptr+1, lim, f);
- X lim = lptr;
- X } else {
- X qsort1(base, lptr, f);
- X base = hptr+1;
- X }
- X goto top;
- X }
- X
- X lptr -= 1;
- X swap3(j, lptr, i);
- X j = hptr -= 1;
- X }
- X}
- X
- Xint
- Xxstrcmp(p1, p2)
- X Void *p1, *p2;
- X{
- X return (strcmp((char *)p1, (char *)p2));
- X}
- X
- SHAR_EOF
- true || echo 'restore of src/misc.c failed'
- fi
- # ============= src/trap.c ==============
- if test -f 'src/trap.c' -a X"$1" != X"-c"; then
- echo 'x - skipping src/trap.c (File already exists)'
- else
- echo 'x - extracting src/trap.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'src/trap.c' &&
- X/*
- X * signal handling
- X */
- X
- Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/trap.c,v 3.1 88/11/03 09:18:00 egisin Exp $";
- X
- X#include <stddef.h>
- X#include <string.h>
- X#include <errno.h>
- X#include <signal.h>
- X#include <setjmp.h>
- X#include "sh.h"
- X
- XTrap sigtraps [SIGNALS] = {
- X {0, "EXIT", "Signal 0"}, /* todo: belongs in e.loc->exit */
- X {SIGHUP, "HUP", "Hangup"},
- X {SIGINT, "INT", "Interrupt"},
- X {SIGQUIT, "QUIT", "Quit"},
- X {SIGILL, "ILL", "Illegal instruction"},
- X {SIGTRAP, "TRAP", "Trace trap"},
- X {SIGIOT, "IOT", "Abort"},
- X {SIGEMT, "EMT", "EMT trap"},
- X {SIGFPE, "FPE", "Floating exception"},
- X {SIGKILL, "KILL", "Killed"},
- X {SIGBUS, "BUS", "Bus error"},
- X {SIGSEGV, "SEGV", "Memory fault"},
- X {SIGSYS, "SYS", "Bad system call"},
- X {SIGPIPE, "PIPE", "Broken pipe"},
- X {SIGALRM, "ALRM", "Alarm clock"},
- X {SIGTERM, "TERM", "Terminated"},
- X#if JOBS /* todo: need to be more portable */
- X {SIGURG, "URG", "Urgent condition"}, /* BSDism */
- X {SIGSTOP, "STOP", "Stop (signal)"},
- X {SIGTSTP, "TSTP", "Stop"},
- X {SIGCONT, "CONT", "Continue"},
- X {SIGCHLD, "CHLD", "Waiting children"},
- X {SIGTTIN, "TTIN", "Stop (tty input)"},
- X {SIGTTOU, "TTOU", "Stop (tty output)"},
- X#endif
- X};
- X
- XTrap *
- Xgettrap(name)
- X char *name;
- X{
- X int i;
- X register Trap *p;
- X
- X if (digit(*name)) {
- X i = getn(name);
- X return (0 <= i && i < SIGNALS) ? &sigtraps[getn(name)] : NULL;
- X }
- X#if 0
- X if (strcmp("ERR", name) == 0)
- X return &e.loc->err;
- X if (strcmp("EXIT", name) == 0)
- X return &e.loc->exit;
- X#endif
- X for (p = sigtraps, i = SIGNALS; --i >= 0; p++)
- X if (strcmp(p->name, name) == 0)
- X return p;
- X return NULL;
- X}
- X
- X/*
- X * trap signal handler
- X */
- Xvoid
- Xtrapsig(i)
- X int i;
- X{
- X trap = sigtraps[i].set = 1;
- X if (i == SIGINT && e.type == E_PARSE)
- X /* dangerous but necessary to deal with BSD silly signals */
- X longjmp(e.jbuf, 1);
- X (void) signal(i, trapsig); /* todo: use sigact */
- X}
- X
- X/*
- X * run any pending traps
- X */
- Xruntraps()
- X{
- X int i;
- X register Trap *p;
- X
- X for (p = sigtraps, i = SIGNALS; --i >= 0; p++)
- X if (p->set)
- X runtrap(p);
- X trap = 0;
- X}
- X
- Xruntrap(p)
- X Trap *p;
- X{
- X char *trapstr;
- X
- X p->set = 0;
- X if ((trapstr = p->trap) == NULL)
- X if (p->signal == SIGINT)
- X unwind(); /* return to shell() */
- X else
- X return;
- X if (p->signal == 0) /* ??? */
- X p->trap = 0;
- X command(trapstr);
- X}
- X
- X/* restore signals for children */
- Xcleartraps()
- X{
- X int i;
- X register Trap *p;
- X
- X for (i = SIGNALS, p = sigtraps; --i >= 0; p++) {
- X p->set = 0;
- X if (p->ourtrap && signal(p->signal, SIG_IGN) != SIG_IGN)
- X (void) signal(p->signal, SIG_DFL);
- X }
- X}
- X
- Xignoresig(i)
- X int i;
- X{
- X if (signal(i, SIG_IGN) != SIG_IGN)
- X sigtraps[i].sig_dfl = 1;
- X}
- X
- Xrestoresigs()
- X{
- X int i;
- X register Trap *p;
- X
- X for (p = sigtraps, i = SIGNALS; --i >= 0; p++)
- X if (p->sig_dfl) {
- X p->sig_dfl = 0;
- X (void) signal(p->signal, SIG_DFL);
- X }
- X}
- X
- SHAR_EOF
- true || echo 'restore of src/trap.c failed'
- fi
- # ============= src/alloc.c ==============
- if test -f 'src/alloc.c' -a X"$1" != X"-c"; then
- echo 'x - skipping src/alloc.c (File already exists)'
- else
- echo 'x - extracting src/alloc.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'src/alloc.c' &&
- X/*
- X * area-based allocation built on malloc/free
- X */
- X
- Xstatic char *RCSid = "$Header";
- X
- X#include <stddef.h>
- X#include <stdlib.h>
- X#include <setjmp.h>
- X#include "sh.h"
- X
- X#define ICELLS 100 /* number of Cells in small Block */
- X
- Xtypedef union Cell Cell;
- Xtypedef struct Block Block;
- X
- X/*
- X * The Cells in a Block are organized as a set of objects.
- X * Each object (pointed to by dp) begins with a size in (dp-1)->size,
- X * followed with "size" data Cells. Free objects are
- X * linked together via dp->next.
- X */
- X
- Xunion Cell {
- X size_t size;
- X Cell *next;
- X struct {int _;} junk; /* alignment */
- X};
- X
- Xstruct Block {
- X Block *next; /* list of Blocks in Area */
- X Cell *free; /* object free list */
- X Cell *last; /* &b.cell[size] */
- X Cell cell [1]; /* [size] Cells for allocation */
- X};
- X
- XBlock aempty = {&aempty, aempty.cell, aempty.cell};
- X
- X/* create empty Area */
- XArea *
- Xainit(ap)
- X register Area *ap;
- X{
- X ap->free = &aempty;
- X return ap;
- X}
- X
- X/* free all object in Area */
- Xvoid
- Xafreeall(ap)
- X register Area *ap;
- X{
- X register Block *bp;
- X
- X if (ap->free == NULL || ap->free == &aempty)
- X return;
- X for (bp = ap->free; ; bp = bp->next) {
- X free((Void*)bp);
- X if (bp->next == ap->free)
- X break;
- X }
- X ap->free = &aempty;
- X}
- X
- X/* allocate object from Area */
- XVoid *
- Xalloc(size, ap)
- X size_t size;
- X register Area *ap;
- X{
- X int cells, split;
- X register Block *bp;
- X register Cell *dp, *fp, *fpp;
- X
- X if (size <= 0) {
- X aerror(ap, "allocate bad size");
- X return NULL;
- X }
- X cells = (unsigned)(size - 1) / sizeof(Cell) + 1;
- X
- X /* find Cell large enough */
- X for (bp = ap->free; ; bp = bp->next) {
- X for (fpp = NULL, fp = bp->free;
- X fp != bp->last; fpp = fp, fp = fpp->next)
- X if ((fp-1)->size >= cells)
- X goto Found;
- X
- X /* wrapped around Block list, create new Block */
- X if (bp == ap->free) {
- X bp = malloc(offsetof(Block, cell[ICELLS + cells]));
- X if (bp == NULL) {
- X aerror(ap, "cannot allocate");
- X return NULL;
- X }
- X if (ap->free == &aempty)
- X bp->next = bp;
- X else {
- X bp->next = ap->free->next;
- X ap->free->next = bp;
- X }
- X bp->last = bp->cell + ICELLS + cells;
- X fp = bp->free = bp->cell + 1; /* initial free list */
- X (fp-1)->size = ICELLS + cells - 1;
- X fp->next = bp->last;
- X fpp = NULL;
- X break;
- X }
- X }
- X Found:
- X ap->free = bp;
- X dp = fp; /* allocated object */
- X split = (dp-1)->size - cells;
- X if (split < 0)
- X aerror(ap, "allocated object too small");
- X if (--split <= 0) { /* allocate all */
- X fp = fp->next;
- X } else { /* allocate head, free tail */
- X (fp-1)->size = cells;
- X fp += cells + 1;
- X (fp-1)->size = split;
- X fp->next = dp->next;
- X }
- X if (fpp == NULL)
- X bp->free = fp;
- X else
- X fpp->next = fp;
- X return (Void*) dp;
- X}
- X
- X/* change size of object */
- X/* todo: allow expansion */
- XVoid *
- Xaresize(ptr, size, ap)
- X register Void *ptr;
- X size_t size;
- X register Area *ap;
- X{
- X int cells, split;
- X register Cell *dp = (Cell*)ptr;
- X
- X if (size <= 0) {
- X aerror(ap, "allocate bad size");
- X return NULL;
- X }
- X cells = (unsigned)(size - 1) / sizeof(Cell) + 1;
- X
- X split = (dp-1)->size - cells;
- X if (split < 0)
- X aerror(ap, "cannot resize larger");
- X if (--split <= 0) /* cannot split */
- X ;
- X else { /* shrink head, free tail */
- X (dp-1)->size = cells;
- X dp += cells + 1;
- X (dp-1)->size = split;
- X afree((Void*)dp, ap);
- X }
- X
- X return (Void*) ptr;
- X}
- X
- Xvoid
- Xafree(ptr, ap)
- X Void *ptr;
- X register Area *ap;
- X{
- X register Block *bp;
- X register Cell *fp, *fpp;
- X register Cell *dp = (Cell*)ptr;
- X
- X /* find Block containing Cell */
- X for (bp = ap->free; ; bp = bp->next) {
- X if (bp->cell <= dp && dp < bp->last)
- X break;
- X if (bp->next == ap->free) {
- X aerror(ap, "freeing with invalid area");
- X return;
- X }
- X }
- X
- X /* find position in free list */
- X for (fpp = NULL, fp = bp->free; fp < dp; fpp = fp, fp = fpp->next)
- X ;
- X
- X if (fp == dp) {
- X aerror(ap, "freeing free object");
- X return;
- X }
- X
- X /* join object with next */
- X if (dp + (dp-1)->size == fp-1) { /* adjacent */
- X (dp-1)->size += (fp-1)->size + 1;
- X dp->next = fp->next;
- X } else /* non-adjacent */
- X dp->next = fp;
- X
- X /* join previous with object */
- X if (fpp == NULL)
- X bp->free = dp;
- X else if (fpp + (fpp-1)->size == dp-1) { /* adjacent */
- X (fpp-1)->size += (dp-1)->size + 1;
- X fpp->next = dp->next;
- X } else /* non-adjacent */
- X fpp->next = dp;
- X}
- X
- X
- X#if TEST_ALLOC
- X
- XArea a;
- X
- Xmain(int argc, char **argv) {
- X int i;
- X char *p [9];
- X
- X ainit(&a);
- X for (i = 0; i < 9; i++) {
- X p[i] = alloc(124, &a);
- X printf("alloc: %x\n", p[i]);
- X }
- X for (i = 1; i < argc; i++)
- X afree(p[atoi(argv[i])], &a);
- X afreeall(&a);
- X return 0;
- X}
- X
- Xvoid aerror(Area *ap, const char *msg) {
- X abort();
- X}
- X
- X#endif
- X
- SHAR_EOF
- true || echo 'restore of src/alloc.c failed'
- fi
- # ============= src/io.c ==============
- if test -f 'src/io.c' -a X"$1" != X"-c"; then
- echo 'x - skipping src/io.c (File already exists)'
- else
- echo 'x - extracting src/io.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'src/io.c' &&
- X/*
- X * shell buffered IO and formatted output
- X */
- X
- Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/io.c,v 3.3 88/11/25 10:55:52 egisin Exp $";
- X
- X#include <stddef.h>
- X#include <stdlib.h>
- X#include <stdio.h>
- X#include <errno.h>
- X#include <unistd.h>
- X#include <fcntl.h>
- X#include <signal.h>
- X#include <setjmp.h>
- X#if __STDC__
- X#include <stdarg.h>
- X#else
- X#include <varargs.h>
- X#endif
- X#include "sh.h"
- X
- X#if 0
- X/* fputc with ^ escaping */
- Xstatic void
- Xfzotc(c, f)
- X register int c;
- X register FILE *f;
- X{
- X if ((c&0x60) == 0) { /* C0|C1 */
- X putc((c&0x80) ? '$' : '^', f);
- X putc((c&0x7F|0x40), f);
- X } else if ((c&0x7F) == 0x7F) { /* DEL */
- X putc((c&0x80) ? '$' : '^', f);
- X putc('?', f);
- X } else
- X putc(c, f);
- X}
- X#endif
- X
- X/*
- X * formatted output functions
- X */
- X
- X/* shellf(...); error() */
- Xint
- X#if __STDC__
- Xerrorf(Const char *fmt, ...) {
- X#else
- Xerrorf(va_alist) va_dcl
- X{
- X char *fmt;
- X#endif
- X va_list va;
- X
- X#if __STDC__
- X va_start(va, fmt);
- X#else
- X va_start(va);
- X fmt = va_arg(va, char *);
- X#endif
- X vfprintf(shlout, fmt, va);
- X va_end(va);
- X /*fflush(shlout);*/
- X error();
- X}
- X
- X/* printf to shlout (stderr) */
- Xint
- X#if __STDC__
- Xshellf(Const char *fmt, ...) {
- X#else
- Xshellf(va_alist) va_dcl
- X{
- X char *fmt;
- X#endif
- X va_list va;
- X
- X#if __STDC__
- X va_start(va, fmt);
- X#else
- X va_start(va);
- X fmt = va_arg(va, char *);
- X#endif
- X vfprintf(shlout, fmt, va);
- X va_end(va);
- X return 0;
- X}
- X
- X/*
- X * We have a stdio stream for any open shell file descriptors (0-9)
- X */
- XFILE * shf [NUFILE]; /* map shell fd to FILE * */
- X
- X/* open stream for shell fd */
- Xvoid
- Xfopenshf(fd)
- X int fd;
- X{
- X if (shf[fd] != NULL)
- X return;
- X if (fd <= 2)
- X _iob[fd]._flag = 0; /* re-use stdin, stdout, stderr */
- X shf[fd] = fdopen(fd, "r+");
- X if (shf[fd] == NULL)
- X return;
- X setvbuf(shf[fd], (char*)NULL, _IOFBF, (size_t)BUFSIZ);
- X}
- X
- X/* flush stream assoc with fd */
- X/* this must invalidate input and output buffers */
- Xvoid
- Xflushshf(fd)
- X int fd;
- X{
- X if (shf[fd] != NULL) {
- X fseek(shf[fd], 0L, 1); /* V7 derived */
- X fflush(shf[fd]); /* standard C */
- X }
- X}
- X
- X/*
- X * move fd from user space (0<=fd<10) to shell space (fd>=10)
- X */
- Xint
- Xsavefd(fd)
- X int fd;
- X{
- X int nfd;
- X
- X if (fd < FDBASE) {
- X flushshf(fd);
- X nfd = fcntl(fd, F_DUPFD, FDBASE);
- X if (nfd < 0)
- X if (errno == EBADF)
- X return -1;
- X else
- X errorf("too many files open in shell\n");
- X (void) fcntl(nfd, F_SETFD, FD_CLEXEC);
- X close(fd);
- X } else
- X nfd = fd;
- X return nfd;
- X}
- X
- Xvoid
- Xrestfd(fd, ofd)
- X int fd, ofd;
- X{
- X if (ofd == 0) /* not saved (e.savefd) */
- X return;
- X flushshf(fd);
- X close(fd);
- X if (ofd < 0) /* original fd closed */
- X return;
- X (void) fcntl(ofd, F_DUPFD, fd);
- X close(ofd);
- X}
- X
- Xvoid
- Xopenpipe(pv)
- X register int *pv;
- X{
- X if (pipe(pv) < 0)
- X errorf("can't create pipe - try again\n");
- X pv[0] = savefd(pv[0]);
- X pv[1] = savefd(pv[1]);
- X}
- X
- Xvoid
- Xclosepipe(pv)
- X register int *pv;
- X{
- X close(pv[0]);
- X close(pv[1]);
- X}
- X
- X/*
- X * temporary files
- X */
- X
- Xstruct temp *
- Xmaketemp(ap)
- X Area *ap;
- X{
- X register struct temp *tp;
- X static unsigned int inc = 0;
- X char path [PATH];
- X
- X sprintf(path, "/tmp/sh%05u%02u", (unsigned)getpid(), inc++);
- X /* we could create the thing now with 600 mode */
- X tp = (struct temp *) alloc(sizeof(struct temp), ap);
- X tp->next = NULL;
- X tp->name = strsave(path, ap);
- X return tp;
- X}
- SHAR_EOF
- true || echo 'restore of src/io.c failed'
- fi
- # ============= src/syn.c ==============
- if test -f 'src/syn.c' -a X"$1" != X"-c"; then
- echo 'x - skipping src/syn.c (File already exists)'
- else
- echo 'x - extracting src/syn.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'src/syn.c' &&
- X/*
- X * shell parser (C version)
- X */
- X
- Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/syn.c,v 3.2 88/12/17 21:18:59 egisin Exp $";
- X
- X#include <stddef.h>
- X#include <stdio.h>
- X#include <string.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include "sh.h"
- X#include "lex.h"
- X#include "tree.h"
- X#include "table.h"
- X#include "expand.h"
- X
- Xstatic void zzerr();
- Xstatic struct op *block(), *newtp();
- Xstatic struct op *pipeline(), *andor(), *command();
- Xstatic struct op *nested(), *c_list();
- Xstatic struct op *dogroup(), *thenpart(), *casepart(), *caselist();
- Xstatic struct op *elsepart();
- Xstatic char **wordlist();
- Xstatic void musthave();
- Xstatic struct ioword *synio(), *io();
- X
- Xstatic struct op *outtree; /* yyparse output */
- X
- Xstatic int reject; /* token(cf) gets symbol again */
- Xstatic int symbol; /* yylex value */
- X
- X#define REJECT (reject = 1)
- X#define ACCEPT (reject = 0)
- X#define token(cf) \
- X ((reject) ? (ACCEPT, symbol) : (symbol = yylex(cf)))
- X#define tpeek(cf) \
- X ((reject) ? (symbol) : (REJECT, symbol = yylex(cf)))
- X
- Xint
- Xyyparse()
- X{
- X ACCEPT;
- X yynerrs = 0;
- X if ((tpeek(KEYWORD|ALIAS)) == 0) { /* EOF */
- X outtree = newtp(TEOF);
- X return 0;
- X }
- X outtree = c_list();
- X musthave('\n', 0);
- X return (yynerrs != 0);
- X}
- X
- Xstatic struct op *
- Xpipeline(cf)
- X int cf;
- X{
- X register struct op *t, *p, *tl = NULL;
- X register int c;
- X
- X t = command(cf);
- X if (t != NULL) {
- X while ((c = token(0)) == '|') {
- X if ((p = command(CONTIN)) == NULL)
- X SYNTAXERR;
- X if (tl == NULL)
- X t = tl = block(TPIPE, t, p, NOWORDS);
- X else
- X tl = tl->right = block(TPIPE, tl->right, p, NOWORDS);
- X /*t = block(TPIPE, t, p, NOWORDS);*/
- X }
- X REJECT;
- X }
- X return (t);
- X}
- X
- Xstatic struct op *
- Xandor()
- X{
- X register struct op *t, *p;
- X register int c;
- X
- X t = pipeline(0);
- X if (t != NULL) {
- X while ((c = token(0)) == LOGAND || c == LOGOR) {
- X if ((p = pipeline(CONTIN)) == NULL)
- X SYNTAXERR;
- X t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS);
- X }
- X REJECT;
- X }
- X return (t);
- X}
- X
- Xstatic struct op *
- Xc_list()
- X{
- X register struct op *t, *p, *tl = NULL;
- X register int c;
- X
- X t = andor();
- X if (t != NULL) {
- X while ((c = token(0)) == ';' || c == '&' ||
- X multiline && c == '\n') {
- X if (c == '&')
- X t = block(TASYNC, t, NOBLOCK, NOWORDS);
- X if ((p = andor()) == NULL)
- X return (t);
- X if (tl == NULL)
- X t = tl = block(TLIST, t, p, NOWORDS);
- X else
- X tl = tl->right = block(TLIST, tl->right, p, NOWORDS);
- X }
- X REJECT;
- X }
- X return (t);
- X}
- X
- Xstatic struct ioword *
- Xsynio(cf)
- X int cf;
- X{
- X register struct ioword *iop;
- X
- X if (tpeek(cf) != REDIR)
- X return NULL;
- X ACCEPT;
- X iop = yylval.iop;
- X musthave(LWORD, 0);
- X iop->name = yylval.cp;
- X if ((iop->flag&IOTYPE) == IOHERE) {
- X if (*ident != 0) /* unquoted */
- X iop->flag |= IOEVAL;
- X if (herep >= &heres[HERES])
- X errorf("too many <<'s\n");
- X *herep++ = iop;
- X }
- X return iop;
- X}
- X
- Xstatic void
- Xmusthave(c, cf)
- X int c, cf;
- X{
- X if ((token(cf)) != c)
- X SYNTAXERR;
- X}
- X
- Xstatic struct op *
- Xnested(type, mark)
- X int type, mark;
- X{
- X register struct op *t;
- X
- X multiline++;
- X t = c_list();
- X musthave(mark, KEYWORD);
- X multiline--;
- X return (block(type, t, NOBLOCK, NOWORDS));
- X}
- X
- Xstatic struct op *
- Xcommand(cf)
- X int cf;
- X{
- X register struct op *t;
- X register int c, iopn = 0;
- X struct ioword *iop, **iops;
- X XPtrV args, vars;
- X
- X iops = (struct ioword **) alloc(sizeofN(struct ioword *, NUFILE+1), ATEMP);
- X XPinit(args, 16);
- X XPinit(vars, 16);
- X
- X if (multiline)
- X cf = CONTIN;
- X cf |= KEYWORD|ALIAS;
- X
- X while ((iop = synio(cf)) != NULL) {
- X if (iopn >= NUFILE)
- X yyerror("too many redirections");
- X iops[iopn++] = iop;
- X cf &=~ CONTIN;
- X }
- X
- X switch (c = token(cf)) {
- X case 0:
- X yyerror("unexpected EOF");
- X return NULL;
- X
- X default:
- X REJECT;
- X if (iopn == 0)
- X return NULL; /* empty line */
- X t = newtp(TCOM);
- X break;
- X
- X case LWORD:
- X REJECT;
- X t = newtp(TCOM);
- X while (1)
- X switch (tpeek(0)) {
- X case REDIR:
- X if (iopn >= NUFILE)
- X yyerror("too many redirections");
- X iops[iopn++] = synio(0);
- X break;
- X
- X case LWORD:
- X ACCEPT;
- X if ((XPsize(args) == 0 || flag[FKEYWORD])
- X && strchr(ident+1, '='))
- X {XPput(vars, yylval.cp);}
- X else
- X {XPput(args, yylval.cp);}
- X break;
- X
- X case MPAREN:
- X ACCEPT;
- X if (XPsize(args) != 1)
- X SYNTAXERR;
- X if (*ident == 0)
- X yyerror("invalid function name\n");
- X t = newtp(TFUNCT);
- X t->str = strsave(ident, ATEMP);
- X musthave('{', CONTIN|KEYWORD);
- X t->left = nested(TBRACE, '}');
- X return t;
- X
- X default:
- X goto Leave;
- X }
- X Leave:
- X break;
- X
- X case '(':
- X t = nested(TPAREN, ')');
- X break;
- X
- X case '{':
- X t = nested(TBRACE, '}');
- X break;
- X
- X case FOR:
- X t = newtp(TFOR);
- X musthave(LWORD, 0);
- X t->str = strsave(ident, ATEMP);
- X multiline++;
- X t->vars = wordlist();
- X t->left = dogroup(0);
- X multiline--;
- X break;
- X
- X case WHILE:
- X case UNTIL:
- X multiline++;
- X t = newtp((c == WHILE) ? TWHILE: TUNTIL);
- X t->left = c_list();
- X t->right = dogroup(1);
- X multiline--;
- X break;
- X
- X case CASE:
- X t = newtp(TCASE);
- X musthave(LWORD, 0);
- X t->str = yylval.cp;
- X multiline++;
- X musthave(IN, KEYWORD|CONTIN);
- X t->left = caselist();
- X musthave(ESAC, KEYWORD);
- X multiline--;
- X break;
- X
- X case IF:
- X multiline++;
- X t = newtp(TIF);
- X t->left = c_list();
- X t->right = thenpart();
- X musthave(FI, KEYWORD);
- X multiline--;
- X break;
- X
- X case TIME:
- X t = pipeline(CONTIN);
- X t = block(TTIME, t, NOBLOCK, NOWORDS);
- X break;
- X
- X case FUNCTION:
- X t = newtp(TFUNCT);
- X musthave(LWORD, 0);
- X t->str = strsave(ident, ATEMP);
- X musthave('{', CONTIN|KEYWORD);
- X t->left = nested(TBRACE, '}');
- X break;
- X }
- X
- X while ((iop = synio(0)) != NULL) {
- X if (iopn >= NUFILE)
- X yyerror("too many redirections");
- X iops[iopn++] = iop;
- X }
- X
- X if (iopn == 0) {
- X afree((Void*) iops, ATEMP);
- X t->ioact = NULL;
- X } else {
- X iops[iopn++] = NULL;
- X aresize((Void*) iops, sizeofN(struct ioword *, iopn), ATEMP);
- X t->ioact = iops;
- X }
- X
- X if (t->type == TCOM) {
- X XPput(args, NULL);
- X t->args = (char **) XPclose(args);
- X XPput(vars, NULL);
- X t->vars = (char **) XPclose(vars);
- X } else {
- X XPfree(args);
- X XPfree(vars);
- X }
- X
- X return t;
- X}
- X
- Xstatic struct op *
- Xdogroup(onlydone)
- X int onlydone;
- X{
- X register int c;
- X register struct op *list;
- X
- X c = token(CONTIN|KEYWORD);
- X if (c == DONE && onlydone)
- X return NULL;
- X if (c != DO)
- X SYNTAXERR;
- X list = c_list();
- X musthave(DONE, KEYWORD);
- X return list;
- X}
- X
- Xstatic struct op *
- Xthenpart()
- X{
- X register int c;
- X register struct op *t;
- X
- X if ((c = token(0)) != THEN) {
- X REJECT;
- X return NULL;
- X }
- X t = newtp(0);
- X t->left = c_list();
- X if (t->left == NULL)
- X SYNTAXERR;
- X t->right = elsepart();
- X return (t);
- X}
- X
- Xstatic struct op *
- Xelsepart()
- X{
- X register int c;
- X register struct op *t;
- X
- X switch (c = token(0)) {
- X case ELSE:
- X if ((t = c_list()) == NULL)
- X SYNTAXERR;
- X return (t);
- X
- X case ELIF:
- X t = newtp(TELIF);
- X t->left = c_list();
- X t->right = thenpart();
- X return (t);
- X
- X default:
- X REJECT;
- X return NULL;
- X }
- X}
- X
- Xstatic struct op *
- Xcaselist()
- X{
- X register struct op *t, *tl;
- X
- X t = tl = NULL;
- X while ((tpeek(CONTIN|KEYWORD)) != ESAC) {
- X struct op *tc = casepart();
- X if (tl == NULL)
- X t = tl = tc, tl->right = NULL;
- X else
- X tl->right = tc, tl = tc;
- X }
- X return (t);
- X}
- X
- Xstatic struct op *
- Xcasepart()
- X{
- X register struct op *t;
- X register int c, cf;
- X XPtrV ptns;
- X
- X XPinit(ptns, 16);
- X t = newtp(TPAT);
- X cf = CONTIN|KEYWORD;
- X c = token(cf);
- X if (c != '(')
- X REJECT;
- X else
- X cf = 0;
- X do {
- X musthave(LWORD, cf);
- X XPput(ptns, yylval.cp);
- X cf = 0;
- X } while ((c = token(0)) == '|');
- X REJECT;
- X XPput(ptns, NULL);
- X t->vars = (char **) XPclose(ptns);
- X musthave(')', 0);
- X
- X t->left = c_list();
- X if ((tpeek(CONTIN|KEYWORD)) != ESAC)
- X musthave(BREAK, CONTIN|KEYWORD);
- X return (t);
- X}
- X
- Xstatic char **
- Xwordlist()
- X{
- X register int c;
- X XPtrV args;
- X
- X XPinit(args, 16);
- X if ((c = token(CONTIN|KEYWORD)) != IN) {
- X REJECT;
- X return NULL;
- X }
- X while ((c = token(0)) == LWORD)
- X XPput(args, yylval.cp);
- X if (c != '\n' && c != ';')
- X SYNTAXERR;
- X if (XPsize(args) == 0) {
- X XPfree(args);
- X return NULL;
- X } else {
- X XPput(args, NULL);
- X return (char **) XPclose(args);
- X }
- X}
- X
- X/*
- X * supporting functions
- X */
- X
- Xstatic struct op *
- Xblock(type, t1, t2, wp)
- X struct op *t1, *t2;
- X char **wp;
- X{
- X register struct op *t;
- X
- X t = newtp(type);
- X t->left = t1;
- X t->right = t2;
- X t->vars = wp;
- X return (t);
- X}
- X
- XConst struct res {
- X char *name;
- X int val;
- X} restab[] = {
- X "for", FOR,
- X "case", CASE,
- X "esac", ESAC,
- X "while", WHILE,
- X "do", DO,
- X "done", DONE,
- X "if", IF,
- X "in", IN,
- X "then", THEN,
- X "else", ELSE,
- X "elif", ELIF,
- X "until", UNTIL,
- X "fi", FI,
- X "function", FUNCTION,
- X "time", TIME,
- X "{", '{',
- X "}", '}',
- X 0
- X};
- X
- Xkeywords()
- X{
- X register struct res Const *rp;
- X register struct tbl *p;
- X
- X for (rp = restab; rp->name; rp++) {
- X p = tenter(&lexicals, rp->name, hash(rp->name));
- X p->flag |= DEFINED|ISSET;
- X p->type = CKEYWD;
- X p->val.i = rp->val;
- X }
- X}
- X
- Xstatic struct op *
- Xnewtp(type)
- X int type;
- X{
- X register struct op *t;
- X
- X t = (struct op *) alloc(sizeof(*t), ATEMP);
- X t->type = type;
- X t->args = t->vars = NULL;
- X t->ioact = NULL;
- X t->left = t->right = NULL;
- X t->str = NULL;
- X return (t);
- X}
- X
- Xstatic void
- Xzzerr()
- X{
- X yyerror("syntax error");
- X}
- X
- Xstruct op *
- Xcompile(s)
- X Source *s;
- X{
- X yynerrs = 0;
- X multiline = 0;
- X herep = heres;
- X source = s;
- X if (yyparse())
- X unwind();
- X if (s->type == STTY || s->type == SFILE)
- X s->str = null; /* line is not preserved */
- X return outtree;
- X}
- X
- SHAR_EOF
- true || echo 'restore of src/syn.c failed'
- fi
- true || echo 'restore of src/lex.c failed'
- echo End of part 2, continue with part 3
- exit 0
-