home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume25
/
pdksh
/
part05
< prev
next >
Wrap
Text File
|
1991-11-12
|
56KB
|
2,815 lines
Newsgroups: comp.sources.misc
From: sjg@zen.void.oz.au (Simon J. Gerraty)
Subject: v25i051: pdksh - Public Domain Korn Shell, v4, Part05/09
Message-ID: <1991Nov13.031141.16071@sparky.imd.sterling.com>
X-Md4-Signature: caab833c4db7863094df7fd7ea6c1d2f
Date: Wed, 13 Nov 1991 03:11:41 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: sjg@zen.void.oz.au (Simon J. Gerraty)
Posting-number: Volume 25, Issue 51
Archive-name: pdksh/part05
Environment: UNIX
#! /bin/sh
# 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: sh/c_sh.c sh/c_test.c sh/edit.c sh/history.c sh/main.c
# sh/tree.c std/stdc/stdio.c
# Wrapped by kent@sparky on Tue Nov 12 20:44:33 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 5 (of 9)."'
if test -f 'sh/c_sh.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'sh/c_sh.c'\"
else
echo shar: Extracting \"'sh/c_sh.c'\" \(8560 characters\)
sed "s/^X//" >'sh/c_sh.c' <<'END_OF_FILE'
X/*
X * built-in Bourne commands
X */
X
X#ifndef lint
Xstatic char *RCSid = "Id: /u/egisin/sh/src/RCS/c_sh.c,v 3.1 88/11/03 09:14:31 egisin Exp $";
Xstatic char *sccs_id = "@(#)c_sh.c 1.3 91/11/09 15:35:24 (sjg)";
X#endif
X
X#include <stddef.h>
X#include <stdio.h>
X#include <string.h>
X#include <errno.h>
X#include <signal.h>
X#include <setjmp.h>
X#include <sys/times.h>
X#include <unistd.h> /* getcwd */
X#include "sh.h"
X#include "lex.h"
X#include "tree.h"
X#include "table.h"
X
Xstatic char *clocktos();
X
Xint
Xc_label(wp)
X char **wp;
X{
X return 0;
X}
X
Xint
Xc_shift(wp)
X register char **wp;
X{
X register struct block *l = e.loc;
X register int n;
X
X n = wp[1] ? evaluate(wp[1]) : 1;
X if (l->argc < n) {
X errorf("nothing to shift\n");
X return (1);
X }
X l->argv[n] = l->argv[0];
X l->argv += n;
X l->argc -= n;
X return 0;
X}
X
Xint
Xc_umask(wp)
X register char **wp;
X{
X register int i;
X register char *cp;
X
X if ((cp = wp[1]) == NULL) {
X i = umask(0);
X umask(i);
X printf("%#3.3o\n", i); /* should this be shell output? */
X } else {
X for (i = 0; *cp>='0' && *cp<='7'; cp++)
X i = i*8 + (*cp-'0');
X umask(i);
X }
X return 0;
X}
X
Xint
Xc_dot(wp)
X char **wp;
X{
X char *file, *cp;
X
X if ((cp = wp[1]) == NULL)
X return 0;
X file = search(cp, path, 0);
X if (file == NULL)
X errorf("%s: not found\n", cp);
X if (include(file))
X return exstat;
X return -1;
X}
X
Xint
Xc_wait(wp)
X char **wp;
X{
X register char *cp;
X
X wp++;
X cp = *wp;
X if (cp == NULL) cp = "%";
X /* todo: print status ? */
X return waitfor(j_lookup(cp));
X}
X
Xint
Xc_read(wp)
X register char **wp;
X{
X register int c = 0;
X FILE *f = stdin;
X int expand = 1;
X register char *cp;
X
X for (wp++; (cp = *wp) != NULL && *cp++ == '-'; wp++) {
X while (*cp) switch (*cp++) {
X case 'e':
X expand = 1;
X break;
X case 'r':
X expand = 0;
X break;
X case 'u':
X if (!digit(*cp) || (f = shf[*cp++-'0']) == NULL)
X errorf("bad -u argument\n");
X break;
X }
X }
X
X if (*wp == NULL)
X errorf("missing name\n");
X if ((cp = strchr(*wp, '?')) != NULL) {
X *cp = 0;
X if (flag[FTALKING]) {
X shellf("%s ", cp+1);
X fflush(shlout);
X }
X }
X
X for (; *wp != NULL; wp++) {
X for (cp = line; cp <= line+LINE; ) {
X if (c == '\n')
X break;
X c = getc(f);
X if (c == EOF)
X return 1;
X if (expand && c == '\\') {
X c = getc(f);
X if (c == '\n')
X c = 0;
X else
X *cp++ = c;
X continue;
X }
X if (c == '\n' || wp[1] && ctype(c, C_IFS))
X break;
X *cp++ = c;
X }
X *cp = 0;
X setstr(global(*wp), line);
X }
X return 0;
X}
X
Xint
Xc_eval(wp)
X register char **wp;
X{
X register struct source *s;
X
X s = pushs(SWORDS);
X s->u.strv = wp+1;
X return shell(s);
X}
X
Xvoid setsig ARGS((struct trap *p, handler_t f));
X
Xint
Xc_trap(wp)
X register char **wp;
X{
X int i;
X char *s;
X register struct trap *p;
X
X wp++;
X if (*wp == NULL) {
X for (p = sigtraps, i = SIGNALS; --i >= 0; p++) {
X if (p->trap != NULL)
X shellf("%s: %s\n", p->name, p->trap);
X }
X return 0;
X }
X
X s = (gettrap(*wp) == NULL) ? *wp++ : NULL; /* get command */
X if (s != NULL && s[0] == '-' && s[1] == '\0')
X s = NULL;
X
X /* set/clear traps */
X while (*wp != NULL) {
X p = gettrap(*wp++);
X if (p == NULL)
X errorf("trap: bad signal %s\n", wp[-1]);
X if (p->trap != NULL)
X afree((Void*)p->trap, APERM);
X p->trap = NULL;
X if (s != NULL) {
X if (strlen(s) != 0) {
X p->trap = strsave(s, APERM);
X setsig(p, trapsig);
X } else
X setsig(p, (handler_t)SIG_IGN);
X } else
X /* todo: restore to orginal value */
X setsig(p,
X (p->signal==SIGINT || p->signal==SIGQUIT) && flag[FTALKING]
X ? (handler_t)SIG_IGN : (handler_t)SIG_DFL);
X }
X return 0;
X}
X
Xvoid
Xsetsig(p, f)
X register struct trap *p;
X void (*f)();
X{
X if (p->signal == 0)
X return;
X if (signal(p->signal, SIG_IGN) != SIG_IGN || p->ourtrap) {
X p->ourtrap = 1;
X signal(p->signal, f);
X }
X}
X
Xint
Xc_return(wp)
X char **wp;
X{
X wp++;
X if (*wp != NULL)
X exstat = getn(*wp);
X quitenv(); /* pop E_TCOM */
X while (e.type == E_LOOP || e.type == E_EXEC)
X quitenv();
X if (e.type == E_FUNC)
X longjmp(e.jbuf, 1);
X leave(exstat);
X}
X
Xint
Xc_brkcont(wp)
X register char **wp;
X{
X int quit;
X
X quit = wp[1] == NULL ? 1 : getn(wp[1]);
X quitenv(); /* pop E_TCOM */
X while (e.type == E_LOOP || e.type == E_EXEC) {
X if (e.type == E_LOOP && --quit <= 0)
X longjmp(e.jbuf, (*wp[0] == 'b') ? LBREAK : LCONTIN);
X quitenv();
X }
X errorf("cannot %s\n", wp[0]);
X}
X
X
X/* 91-05-27 <sjg>
X * we are supposed to not exit first try
X * if there are stopped jobs.
X */
Xint
Xc_exit(wp)
X char **wp;
X{
X register char *cp;
X static int extry = 0;
X
X#ifdef JOBS
X if (extry++ == 0)
X {
X if (flag[FMONITOR] && j_stopped()) /* todo: only once */
X {
X errorf("There are stopped jobs\n");
X return 1;
X }
X }
X#endif
X e.oenv = NULL;
X if ((cp = wp[1]) != NULL)
X exstat = getn(cp);
X leave(exstat);
X}
X
Xint
Xc_set(wp)
X register char **wp;
X{
X struct block *l = e.loc;
X register struct tbl *vp, **p;
X register char **owp = wp;
X register char *cp;
X int old_fmonitor = flag[FMONITOR];
X
X if ((cp = *++wp) == NULL) {
X static char * Const args [] = {"set", "-", NULL};
X extern int c_typeset ARGS((char **args));
X return c_typeset(args);
X }
X
X for (; (cp = *wp) != NULL && (*cp == '-' || *cp == '+');) {
X int i, n = *cp++ == '-'; /* set or clear flag */
X wp++;
X if (*cp == '\0') {
X if (n)
X flag[FXTRACE] = flag[FVERBOSE] = 0;
X break;
X }
X if (*cp == '-')
X goto setargs;
X for (; *cp != '\0'; cp++)
X if (*cp == 'o') {
X if (*wp == NULL) {
X printoptions();
X return 0;
X }
X i = option(*wp++);
X if (i == 0)
X shellf("%s: unknown option\n", *--wp);
X flag[i] = n;
X if (i == FEMACS && n)
X flag[FVI] = 0;
X else if (i == FVI && n)
X flag[FEMACS] = 0;
X } else if (*cp>='a' && *cp<='z')
X flag[FLAG(*cp)] = n;
X else
X errorf("%c: bad flag\n", *cp);
X if (flag[FTALKING])
X flag[FERREXIT] = 0;
X }
X
X#ifdef JOBS
X if (old_fmonitor != flag[FMONITOR])
X j_change();
X#endif
X
X /* set $# and $* */
X if (*wp != NULL) {
X setargs:
X owp = --wp;
X wp[0] = l->argv[0]; /* save $0 */
X while (*++wp != NULL)
X *wp = strsave(*wp, &l->area);
X l->argc = wp - owp - 1;
X l->argv = (char **) alloc(sizeofN(char *, l->argc+2), &l->area);
X for (wp = l->argv; (*wp++ = *owp++) != NULL; )
X ;
X resetopts();
X }
X return 0;
X}
X
Xint
Xc_unset(wp)
X register char **wp;
X{
X register char *id;
X int flagf = 0;
X
X for (wp++; (id = *wp) != NULL && *id == '-'; wp++)
X if (*++id == 'f')
X flagf++;
X for (; (id = *wp) != NULL; wp++)
X if (!flagf) { /* unset variable */
X unset(global(id));
X } else { /* unset function */
X define(id, (struct op *)NULL);
X }
X return 0;
X}
X
Xint
Xc_ulimit(wp)
X register char **wp;
X{
X extern int do_ulimit();
X
X return do_ulimit(wp[1], wp[2]);
X}
X
Xint
Xc_times(wp)
X char **wp;
X{
X struct tms all;
X
X (void) times(&all);
X printf("Shell: ");
X printf("%8s user ", clocktos(all.tms_utime));
X printf("%8s system\n", clocktos(all.tms_stime));
X printf("Kids: ");
X printf("%8s user ", clocktos(all.tms_cutime));
X printf("%8s system\n", clocktos(all.tms_cstime));
X
X return 0;
X}
X
X/*
X * time pipeline (really a statement, not a built-in comman)
X */
Xint
Xtimex(t, f)
X struct op *t;
X int f;
X{
X int rv;
X struct tms t0, t1;
X clock_t t0t, t1t;
X extern clock_t j_utime, j_stime; /* computed by j_wait */
X
X j_utime = j_stime = 0;
X t0t = times(&t0);
X rv = execute(t->left, f);
X t1t = times(&t1);
X
X shellf("%8s real ", clocktos(t1t - t0t));
X shellf("%8s user ",
X clocktos(t1.tms_utime - t0.tms_utime + j_utime));
X shellf("%8s system ",
X clocktos(t1.tms_stime - t0.tms_stime + j_stime));
X shellf("\n");
X
X return rv;
X}
X
Xstatic char *
Xclocktos(t)
X clock_t t;
X{
X static char temp[20];
X register int i;
X register char *cp = temp + sizeof(temp);
X
X#if CLK_TCK != 100 /* convert to 1/100'ths */
X t = (t < 1000000000/CLK_TCK) ?
X (t * 100) / CLK_TCK : (t / CLK_TCK) * 100;
X#endif
X
X *--cp = '\0';
X *--cp = 's';
X for (i = -2; i <= 0 || t > 0; i++) {
X if (i == 0)
X *--cp = '.';
X *--cp = '0' + (char)(t%10);
X t /= 10;
X }
X return cp;
X}
X
X/* dummy function, special case in comexec() */
Xint
Xc_exec(wp)
X char ** wp;
X{
X return 0;
X}
X
X/* dummy function, special case in comexec() */
Xint
Xc_builtin(wp)
X char ** wp;
X{
X return 0;
X}
X
Xextern int c_test(); /* in test.c */
X
XConst struct builtin shbuiltins [] = {
X {"=:", c_label},
X {"=.", c_dot},
X {"[", c_test},
X {"=builtin", c_builtin},
X {"=exec", c_exec},
X {"=shift", c_shift},
X {"=wait", c_wait},
X {"read", c_read},
X {"=eval", c_eval},
X {"=trap", c_trap},
X {"=break", c_brkcont},
X {"=continue", c_brkcont},
X {"=exit", c_exit},
X {"=return", c_return},
X {"=set", c_set},
X {"unset", c_unset},
X {"umask", c_umask},
X {"test", c_test},
X {"=times", c_times},
X {"ulimit", c_ulimit},
X {NULL, NULL}
X};
X
END_OF_FILE
if test 8560 -ne `wc -c <'sh/c_sh.c'`; then
echo shar: \"'sh/c_sh.c'\" unpacked with wrong size!
fi
# end of 'sh/c_sh.c'
fi
if test -f 'sh/c_test.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'sh/c_test.c'\"
else
echo shar: Extracting \"'sh/c_test.c'\" \(7284 characters\)
sed "s/^X//" >'sh/c_test.c' <<'END_OF_FILE'
X/*
X * test(1); version 7-like -- author Erik Baalbergen
X * modified by Eric Gisin to be used as built-in.
X * modified by Arnold Robbins to add SVR3 compatibility
X * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket).
X */
X
Xstatic char *RCSid = "$Id: c_test.c,v 3.3 89/03/27 15:47:25 egisin Exp $";
X
X#include <stddef.h>
X#include <string.h>
X#include <signal.h>
X#include <errno.h>
X#include <setjmp.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include "sh.h"
X
X/* test(1) accepts the following grammar:
X oexpr ::= aexpr | aexpr "-o" oexpr ;
X aexpr ::= nexpr | nexpr "-a" aexpr ;
X nexpr ::= primary ! "!" primary
X primary ::= unary-operator operand
X | operand binary-operator operand
X | operand
X | "(" oexpr ")"
X ;
X unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"|
X "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S";
X
X binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"|
X "-nt"|"-ot"|"-ef";
X operand ::= <any legal UNIX file name>
X*/
X
X#define EOI 0
X#define FILRD 1
X#define FILWR 2
X#define FILREG 3
X#define FILID 4
X#define FILGZ 5
X#define FILTT 6
X#define STZER 7
X#define STNZE 8
X#define STEQL 9
X#define STNEQ 10
X#define INTEQ 11
X#define INTNE 12
X#define INTGE 13
X#define INTGT 14
X#define INTLE 15
X#define INTLT 16
X#define UNOT 17
X#define BAND 18
X#define BOR 19
X#define LPAREN 20
X#define RPAREN 21
X#define OPERAND 22
X#define FILEX 23
X#define FILCDEV 24
X#define FILBDEV 25
X#define FILFIFO 26
X#define FILSETU 27
X#define FILSETG 28
X#define FILSTCK 29
X#define FILSYM 30
X#define FILNT 31
X#define FILOT 32
X#define FILEQ 33
X#define FILSOCK 34
X#define FILUID 35
X#define FILGID 36
X#define OPTION 37
X
X#define UNOP 1
X#define BINOP 2
X#define BUNOP 3
X#define BBINOP 4
X#define PAREN 5
X
Xstruct t_op {
X char *op_text;
X short op_num, op_type;
X} Const ops [] = {
X {"-r", FILRD, UNOP},
X {"-w", FILWR, UNOP},
X {"-x", FILEX, UNOP},
X {"-f", FILREG, UNOP},
X {"-d", FILID, UNOP},
X {"-c", FILCDEV,UNOP},
X {"-b", FILBDEV,UNOP},
X {"-p", FILFIFO,UNOP},
X {"-u", FILSETU,UNOP},
X {"-g", FILSETG,UNOP},
X {"-k", FILSTCK,UNOP},
X {"-s", FILGZ, UNOP},
X {"-t", FILTT, UNOP},
X {"-z", STZER, UNOP},
X {"-n", STNZE, UNOP},
X#if 0 /* conficts with binary -o */
X {"-o", OPTION, UNOP},
X#endif
X {"-U", FILUID, UNOP},
X {"-G", FILGID, UNOP},
X {"-L", FILSYM, UNOP},
X {"-S", FILSOCK,UNOP},
X {"=", STEQL, BINOP},
X {"!=", STNEQ, BINOP},
X {"-eq", INTEQ, BINOP},
X {"-ne", INTNE, BINOP},
X {"-ge", INTGE, BINOP},
X {"-gt", INTGT, BINOP},
X {"-le", INTLE, BINOP},
X {"-lt", INTLT, BINOP},
X {"-nt", FILNT, BINOP},
X {"-ot", FILOT, BINOP},
X {"-ef", FILEQ, BINOP},
X {"!", UNOT, BUNOP},
X {"-a", BAND, BBINOP},
X {"-o", BOR, BBINOP},
X {"(", LPAREN, PAREN},
X {")", RPAREN, PAREN},
X {0, 0, 0}
X};
X
Xchar **t_wp;
Xstruct t_op Const *t_wp_op;
X
Xstatic void syntax();
X
Xint
Xc_test(wp)
X char **wp;
X{
X int res;
X
X t_wp = wp+1;
X if (strcmp(wp[0], "[") == 0) {
X while (*wp != NULL)
X wp++;
X if (strcmp(*--wp, "]") != 0)
X errorf("[: missing ]\n");
X *wp = NULL;
X }
X res = *t_wp == NULL || !oexpr(t_lex(*t_wp));
X
X if (*t_wp != NULL && *++t_wp != NULL)
X syntax(*t_wp, "unknown operand");
X
X return res;
X}
X
Xstatic void
Xsyntax(op, msg)
X char *op;
X char *msg;
X{
X if (op && *op)
X errorf("test: %s: %s\n", op, msg);
X else
X errorf("test: %s\n", msg);
X}
X
Xoexpr(n)
X{
X int res;
X
X res = aexpr(n);
X if (t_lex(*++t_wp) == BOR)
X return oexpr(t_lex(*++t_wp)) || res;
X t_wp--;
X return res;
X}
X
Xaexpr(n)
X{
X int res;
X
X res = nexpr(n);
X if (t_lex(*++t_wp) == BAND)
X return aexpr(t_lex(*++t_wp)) && res;
X t_wp--;
X return res;
X}
X
Xnexpr(n)
X int n; /* token */
X{
X if (n == UNOT)
X return !nexpr(t_lex(*++t_wp));
X return primary(n);
X}
X
Xprimary(n)
X int n; /* token */
X{
X register char *opnd1, *opnd2;
X int res;
X
X if (n == EOI)
X syntax(NULL, "argument expected");
X if (n == LPAREN) {
X res = oexpr(t_lex(*++t_wp));
X if (t_lex(*++t_wp) != RPAREN)
X syntax(NULL, "closing paren expected");
X return res;
X }
X if (t_wp_op && t_wp_op->op_type == UNOP) {
X /* unary expression */
X if (*++t_wp == NULL && n != FILTT)
X syntax(t_wp_op->op_text, "argument expected");
X switch (n) {
X case OPTION:
X return flag[option(*t_wp)];
X case STZER:
X return strlen(*t_wp) == 0;
X case STNZE:
X return strlen(*t_wp) != 0;
X case FILTT:
X if (!digit(**t_wp))
X return filstat("0", n);
X default: /* all other FIL* */
X return filstat(*t_wp, n);
X }
X }
X opnd1 = *t_wp;
X (void) t_lex(*++t_wp);
X if (t_wp_op && t_wp_op->op_type == BINOP) {
X struct t_op Const *op = t_wp_op;
X
X if ((opnd2 = *++t_wp) == (char *)0)
X syntax(op->op_text, "argument expected");
X
X switch (op->op_num) {
X case STEQL:
X return strcmp(opnd1, opnd2) == 0;
X case STNEQ:
X return strcmp(opnd1, opnd2) != 0;
X case INTEQ:
X return evaluate(opnd1) == evaluate(opnd2);
X case INTNE:
X return evaluate(opnd1) != evaluate(opnd2);
X case INTGE:
X return evaluate(opnd1) >= evaluate(opnd2);
X case INTGT:
X return evaluate(opnd1) > evaluate(opnd2);
X case INTLE:
X return evaluate(opnd1) <= evaluate(opnd2);
X case INTLT:
X return evaluate(opnd1) < evaluate(opnd2);
X case FILNT:
X return newerf (opnd1, opnd2);
X case FILOT:
X return olderf (opnd1, opnd2);
X case FILEQ:
X return equalf (opnd1, opnd2);
X }
X }
X t_wp--;
X return strlen(opnd1) > 0;
X}
X
Xfilstat(nm, mode)
X char *nm;
X{
X struct stat s;
X
X switch (mode) {
X case FILRD:
X return eaccess(nm, 4) == 0;
X case FILWR:
X return eaccess(nm, 2) == 0;
X case FILEX:
X return eaccess(nm, 1) == 0;
X case FILREG:
X return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFREG;
X case FILID:
X return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFDIR;
X case FILCDEV:
X return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFCHR;
X case FILBDEV:
X return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFBLK;
X case FILFIFO:
X#ifdef S_IFIFO
X return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFIFO;
X#else
X return 0;
X#endif
X case FILSETU:
X return stat(nm, &s) == 0 && (s.st_mode & S_ISUID) == S_ISUID;
X case FILSETG:
X return stat(nm, &s) == 0 && (s.st_mode & S_ISGID) == S_ISGID;
X case FILSTCK:
X return stat(nm, &s) == 0 && (s.st_mode & S_ISVTX) == S_ISVTX;
X case FILGZ:
X return stat(nm, &s) == 0 && s.st_size > 0L;
X case FILTT:
X return isatty(getn(nm));
X case FILUID:
X return stat(nm, &s) == 0 && s.st_uid == geteuid();
X case FILGID:
X return stat(nm, &s) == 0 && s.st_gid == getegid();
X#ifdef S_IFLNK
X case FILSYM:
X return lstat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFLNK;
X#endif
X#ifdef S_IFSOCK
X case FILSOCK:
X return stat(nm, &s) == 0 && (s.st_mode & S_IFMT) == S_IFSOCK;
X#endif
X default:
X return 1;
X }
X}
X
Xint
Xt_lex(s)
X register char *s;
X{
X register struct t_op Const *op = ops;
X
X if (s == 0) {
X t_wp_op = (struct t_op *)0;
X return EOI;
X }
X while (op->op_text) {
X if (strcmp(s, op->op_text) == 0) {
X t_wp_op = op;
X return op->op_num;
X }
X op++;
X }
X t_wp_op = (struct t_op *)0;
X return OPERAND;
X}
X
Xnewerf (f1, f2)
Xchar *f1, *f2;
X{
X struct stat b1, b2;
X
X return (stat (f1, &b1) == 0 &&
X stat (f2, &b2) == 0 &&
X b1.st_mtime > b2.st_mtime);
X}
X
Xolderf (f1, f2)
Xchar *f1, *f2;
X{
X struct stat b1, b2;
X
X return (stat (f1, &b1) == 0 &&
X stat (f2, &b2) == 0 &&
X b1.st_mtime < b2.st_mtime);
X}
X
Xequalf (f1, f2)
Xchar *f1, *f2;
X{
X struct stat b1, b2;
X
X return (stat (f1, &b1) == 0 &&
X stat (f2, &b2) == 0 &&
X b1.st_dev == b2.st_dev &&
X b1.st_ino == b2.st_ino);
X}
X
END_OF_FILE
if test 7284 -ne `wc -c <'sh/c_test.c'`; then
echo shar: \"'sh/c_test.c'\" unpacked with wrong size!
fi
# end of 'sh/c_test.c'
fi
if test -f 'sh/edit.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'sh/edit.c'\"
else
echo shar: Extracting \"'sh/edit.c'\" \(7903 characters\)
sed "s/^X//" >'sh/edit.c' <<'END_OF_FILE'
X/*
X * Command line editing - common code
X */
X
X#include "config.h"
X#if defined(EMACS) || defined(VI)
X
X#ifndef lint
Xstatic char *RCSid = "$Id: edit.c,v 3.2 89/03/27 15:47:34 egisin Exp $";
Xstatic char *sccs_id = "@(#)edit.c 1.4 91/11/09 15:35:07 (sjg)";
X#endif
X
X#include <stddef.h>
X#include <stdlib.h>
X#include <string.h>
X#include <stdio.h>
X#include <unistd.h>
X#include <signal.h>
X#include <fcntl.h>
X#include <errno.h>
X#include <setjmp.h>
X#include "sh.h"
X#include "lex.h"
X#include "tty.h"
X#define EXTERN
X#include "edit.h"
X#undef EXTERN
X
X#ifdef _CRAY2
Xextern unsigned sleep();
X#endif
X
X#if 0
Xint x_do_init = 1; /* set up tty modes */
Xint x_cols = 80; /* todo: $COLUMNS */
Xint ed_erase = -1, ed_kill = -1, ed_werase = -1, ed_intr = -1, ed_quit = -1;
X#endif
X
Xstatic int x_noecho = 0;
X
X/*
X * read an edited command line
X */
Xint
Xx_read(fd, buf, len)
X int fd; /* not used */
X char *buf;
X size_t len;
X{
X static int setup_done = 0;
X char c;
X int i;
X
X if (setup_done != 42)
X {
X setup_done = 42; /* these get done once only */
X x_do_init = 1;
X x_cols = 80;
X x_col = 0;
X ed_erase = -1, ed_kill = -1, ed_werase = -1, ed_intr = -1, ed_quit = -1;
X x_adj_ok = 1;
X x_adj_done = 0;
X }
X if (x_do_init)
X x_init();
X
X if (x_noecho)
X return(read(ttyfd, buf, len));
X
X (void)x_mode(TRUE);
X#ifdef EMACS
X if (flag[FEMACS])
X i = x_emacs(buf, len);
X else
X#endif
X#ifdef VI
X if (flag[FVI])
X i = x_vi(buf, len);
X else
X#endif
X i = -1; /* internal error */
X (void) x_mode(FALSE);
X /* XXX -- doesn't get them all */
X if (i > 4 && strncmp(buf, "stty", 4) == 0)
X x_do_init = 1;
X if (i < 0 && errno == EINTR)
X trapsig(SIGINT);
X return i;
X}
X
X/* tty I/O */
X
Xint
Xx_getc()
X{
X char c;
X
X if (read(ttyfd, &c, 1) != 1)
X return -1;
X return c & 0x7F;
X}
X
Xvoid
Xx_flush()
X{
X fflush(stdout);
X}
X
X
X/* NAME:
X * x_adjust - redraw the line adjusting starting point etc.
X *
X * DESCRIPTION:
X * This function is called when we have exceeded the bounds
X * of the edit window. It increments x_adj_done so that
X * functions like x_ins and x_delete know that we have been
X * called and can skip the x_bs() stuff which has already
X * been done by x_redraw.
X *
X * RETURN VALUE:
X * None
X */
X
Xvoid
Xx_adjust()
X{
X x_adj_done++; /* flag the fact that we were called. */
X /*
X * we had a promblem if the prompt length > x_cols / 2
X */
X if ((xbp = xcp - (x_displen / 2)) < xbuf)
X xbp = xbuf;
X xlp_valid = FALSE;
X x_redraw(x_cols);
X x_flush();
X}
X
Xvoid
Xx_putc(c)
X int c;
X{
X if (c == '\r' || c == '\n')
X x_col = 0;
X if (x_col < x_cols)
X {
X putc(c, stdout);
X switch(c)
X {
X case BEL:
X break;
X case '\r':
X case '\n':
X break;
X case '\b':
X x_col--;
X break;
X default:
X x_col++;
X break;
X }
X }
X if (x_adj_ok && (x_col < 0 || x_col >= (x_cols - 2)))
X {
X x_adjust();
X }
X}
X
X#ifdef DEBUG
Xint
Xx_debug_info()
X{
X x_flush();
X printf("\nksh debug:\n");
X printf("\tx_col == %d,\t\tx_cols == %d,\tx_displen == %d\n",
X x_col, x_cols, x_displen);
X printf("\txcp == 0x%lx,\txep == 0x%lx\n", (long) xcp, (long) xep);
X printf("\txbp == 0x%lx,\txbuf == 0x%lx\n", (long) xbp, (long) xbuf);
X printf("\txlp == 0x%lx\n", (long) xlp);
X printf("\txlp == 0x%lx\n", (long) x_lastcp());
X printf("\n");
X x_redraw(-1);
X return 0;
X}
X#endif
X
Xvoid
Xx_puts(s)
X register char *s;
X{
X register int adj = x_adj_done;
X
X while (*s && adj == x_adj_done)
X x_putc(*s++);
X}
X
X#ifdef _BSD
Xstatic struct sgttyb cb, cborig;
X#ifdef TIOCGATC
Xstatic struct ttychars lchars, lcharsorig;
X#else
Xstatic struct tchars tchars, tcharsorig;
Xstatic struct ltchars ltchars, ltcharsorig;
X#endif
X#else
Xstatic struct termio cb, cborig;
X#endif
X
X/* initialize editing mode */
Xvoid
Xx_init()
X{
X x_do_init = 0;
X#ifdef _BSD
X (void)ioctl(ttyfd, TIOCGETP, &cborig);
X if ((cborig.sg_flags & ECHO) == 0)
X x_noecho = 1;
X cb = cborig;
X ed_erase = cb.sg_erase;
X ed_kill = cb.sg_kill;
X cb.sg_flags &= ~ECHO;
X cb.sg_flags |= CBREAK;
X#ifdef TIOCGATC
X (void)ioctl(ttyfd, TIOCGATC, &lcharsorig);
X lchars = lcharsorig;
X ed_werase = lchars.tc_werasc;
X lchars.tc_suspc = -1;
X lchars.tc_dsuspc = -1;
X lchars.tc_lnextc = -1;
X lchars.tc_statc = -1;
X lchars.tc_intrc = -1;
X lchars.tc_quitc = -1;
X lchars.tc_rprntc = -1;
X#else
X (void)ioctl(ttyfd, TIOCGETC, &tcharsorig);
X (void)ioctl(ttyfd, TIOCGLTC, <charsorig);
X tchars = tcharsorig;
X ltchars = ltcharsorig;
X ed_werase = ltchars.t_werasc;
X ltchars = ltcharsorig;
X ltchars.t_suspc = -1;
X ltchars.t_dsuspc = -1;
X ltchars.t_lnextc = -1;
X tchars.t_intrc = -1;
X tchars.t_quitc = -1;
X ltchars.t_rprntc = -1;
X#endif
X#else /* !_BSD */
X (void)ioctl(ttyfd, TCGETA, &cborig);
X if ((cborig.c_lflag & ECHO) == 0)
X x_noecho = 1;
X cb = cborig;
X ed_erase = cb.c_cc[VERASE]; /* TODO */
X ed_kill = cb.c_cc[VKILL]; /* TODO */
X ed_intr = cb.c_cc[VINTR];
X ed_quit = cb.c_cc[VQUIT];
X#ifdef _CRAY2 /* brain-damaged terminal handler */
X cb.c_lflag &= ~(ICANON|ECHO);
X /* rely on print routine to map '\n' to CR,LF */
X#else
X cb.c_iflag &= ~(INLCR|ICRNL);
X#ifdef _BSD_SYSV /* need to force CBREAK instead of RAW (need CRMOD on output) */
X cb.c_lflag &= ~(ICANON|ECHO);
X#else
X#ifdef SWTCH /* need CBREAK to handle swtch char */
X cb.c_lflag &= ~(ICANON|ECHO);
X cb.c_lflag |= ISIG;
X cb.c_cc[VINTR] = 0377;
X cb.c_cc[VQUIT] = 0377;
X#else
X cb.c_lflag &= ~(ISIG|ICANON|ECHO);
X#endif
X#endif
X cb.c_cc[VTIME] = 0;
X cb.c_cc[VMIN] = 1;
X#endif /* _CRAY2 */
X#endif
X#ifdef EMACS
X x_emacs_keys(ed_erase, ed_kill, ed_werase, ed_intr, ed_quit);
X#endif
X}
X
Xstatic bool_t x_cur_mode = FALSE;
X
X/* set/clear tty cbreak mode */
X
X#ifdef _BSD
Xbool_t
Xx_mode(onoff)
X bool_t onoff;
X{
X bool_t prev;
X
X if (x_cur_mode == onoff) return x_cur_mode;
X prev = x_cur_mode;
X x_cur_mode = onoff;
X if (onoff) {
X (void)ioctl(ttyfd, TIOCSETN, &cb);
X#ifdef TIOCGATC
X (void)ioctl(ttyfd, TIOCSATC, &lchars);
X#else
X (void)ioctl(ttyfd, TIOCSETC, &tchars);
X (void)ioctl(ttyfd, TIOCSLTC, <chars);
X#endif
X }
X else {
X (void)ioctl(ttyfd, TIOCSETN, &cborig);
X#ifdef TIOCGATC
X (void)ioctl(ttyfd, TIOCSATC, &lcharsorig);
X#else
X (void)ioctl(ttyfd, TIOCSETC, &tcharsorig);
X (void)ioctl(ttyfd, TIOCSLTC, <charsorig);
X#endif
X }
X return prev;
X}
X
X#else /* !_BSD */
X
Xbool_t
Xx_mode(onoff)
Xbool_t onoff;
X{
X bool_t prev;
X
X if (x_cur_mode == onoff) return x_cur_mode;
X prev = x_cur_mode;
X x_cur_mode = onoff;
X
X if (onoff) {
X#ifndef TCSETAW /* e.g. Cray-2 */
X /* first wait for output to drain */
X#ifdef TCSBRK
X (void)ioctl(ttyfd, TCSBRK, 1);
X#else /* the following kludge is minimally intrusive, but sometimes fails */
X (void)sleep((unsigned)1); /* fake it */
X#endif
X#endif
X#if defined(_BSD_SYSV) || !defined(TCSETAW)
X/* _BSD_SYSV needs to force TIOCSETN instead of TIOCSETP (preserve type-ahead) */
X (void)ioctl(ttyfd, TCSETA, &cb);
X#else
X (void)ioctl(ttyfd, TCSETAW, &cb);
X#endif
X }
X else {
X#ifndef TCSETAW /* e.g. Cray-2 */
X /* first wait for output to drain */
X#ifdef TCSBRK
X (void)ioctl(ttyfd, TCSBRK, 1);
X#else
X/* doesn't seem to be necessary when leaving xmode */
X/* (void)sleep((unsigned)1); /* fake it */
X#endif
X#endif
X#if defined(_BSD_SYSV) || !defined(TCSETAW)
X/* _BSD_SYSV needs to force TIOCSETN instead of TIOCSETP (preserve type-ahead) */
X (void)ioctl(ttyfd, TCSETA, &cborig);
X#else
X (void)ioctl(ttyfd, TCSETAW, &cborig);
X#endif
X }
X return prev;
X}
X#endif /* _BSD */
X
X
X/* NAME:
X * promptlen - calculate the length of PS1 etc.
X *
X * DESCRIPTION:
X * This function is based on a fix from guy@demon.co.uk
X * It fixes a bug in that if PS1 contains '!', the length
X * given by strlen() is probably wrong.
X *
X * RETURN VALUE:
X * length
X */
X
Xint
Xpromptlen(cp)
X register char *cp;
X{
X register int count = 0;
X
X while (*cp)
X {
X if ( *cp++ != '!' )
X count++;
X else
X if ( *cp == '!' )
X {
X cp++;
X count++;
X }
X else
X {
X register int i = source->line;
X
X do
X {
X count ++;
X }
X while( ( i /= 10 ) > 0 );
X }
X }
X return count;
X}
X
X#endif
END_OF_FILE
if test 7903 -ne `wc -c <'sh/edit.c'`; then
echo shar: \"'sh/edit.c'\" unpacked with wrong size!
fi
# end of 'sh/edit.c'
fi
if test -f 'sh/history.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'sh/history.c'\"
else
echo shar: Extracting \"'sh/history.c'\" \(7391 characters\)
sed "s/^X//" >'sh/history.c' <<'END_OF_FILE'
X/*
X * command history
X *
X * only implements in-memory history.
X */
X
Xstatic char *RCSid = "$Id: history.c,v 3.3 89/01/27 00:08:27 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
Xchar *histrpl();
Xchar **current;
Xint curpos;
X
Xc_fc(wp)
X register char **wp;
X{
X register char *id;
X FILE *f;
X struct temp *tf;
X register char **hp;
X char **hbeg, **hend;
X char *p, *cmd = NULL;
X int lflag = 0, nflag = 0, sflag = 0, rflag = 0, gflag = 0;
X int done = 0;
X void histbackup();
X
X for (wp++; (id = *wp) != NULL && *id++ == '-' && !done; wp++)
X while (*id && !done) {
X switch (*id++) {
X case 'l':
X lflag++;
X break;
X case 'n':
X nflag++;
X break;
X case 'r':
X rflag++;
X break;
X case 'g':
X gflag++;
X break;
X case 'e':
X if (++wp && (p = *wp)) {
X if (p[0] == '-' && !p[1]) {
X sflag++;
X } else {
X cmd = alloc((size_t)(strlen(p)+4),ATEMP);
X strcpy(cmd, p);
X strcat(cmd, " $_");
X }
X } else
X errorf("argument expected\n");
X id = "";
X break;
X default:
X wp--;
X done++;
X break;
X }
X }
X
X if (sflag) {
X char *pat = NULL, *rep = NULL;
X
X hp = histptr - 1;
X while ((id = *wp++) != NULL) {
X /* todo: multiple substitutions */
X if ((p = strchr(id, '=')) != NULL) {
X pat = id;
X rep = p;
X *rep++ = '\0';
X } else
X hp = histget(id);
X }
X
X if (hp == NULL || hp < history)
X errorf("cannot find history\n");
X if (pat == NULL)
X strcpy(line, *hp);
X else
X histrpl(*hp, pat, rep, gflag);
X histbackup();
X histsave(line);
X histpush--;
X line[0] = '\0';
X return 0;
X }
X
X if (*wp != NULL) {
X hbeg = histget(*wp++); /* first */
X if (*wp != NULL)
X hend = histget(*wp++); /* last */
X else if (lflag)
X hend = histptr;
X else
X hend = hbeg;
X } else {
X if (lflag)
X hbeg = histptr - 16, hend = histptr;
X else
X hbeg = hend = histptr - 1;
X if (hbeg < history)
X hbeg = history;
X }
X if (hbeg == NULL || hend == NULL)
X errorf("can't find history\n");
X
X if (lflag)
X f = stdout;
X else {
X nflag++;
X tf = maketemp(ATEMP);
X tf->next = e.temps; e.temps = tf;
X f = fopen(tf->name, "w");
X if (f == NULL)
X errorf("cannot create temp file %s", tf->name);
X setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
X }
X
X for (hp = (rflag ? hend : hbeg); rflag ? (hp >= hbeg) : (hp <= hend);
X rflag ? hp-- : hp++) {
X if (!nflag)
X fprintf(f, "%3d: ", source->line - (int)(histptr-hp));
X fprintf(f, "%s\n", *hp);
X }
X
X if (lflag)
X return 0;
X else
X fclose(f);
X
X setstr(local("_"), tf->name);
X if (cmd) {
X command(cmd); /* edit temp file */
X afree(cmd, ATEMP);
X } else
X command("${FCEDIT:-/bin/ed} $_");
X
X f = fopen(tf->name, "r");
X if (f == NULL)
X errorf("cannot open temp file %s\n", tf->name);
X setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
X /* we push the editted lines onto the history list */
X while (fgets(line, sizeof(line), f) != NULL) {
X histsave(line);
X histpush--;
X }
X line[0] = '\0';
X fclose(f);
X
X return 0;
X}
X
X/******************************/
X/* Back up over last histsave */
X/******************************/
Xvoid
Xhistbackup()
X{
X static int last_line = -1;
X
X if (histptr > history && last_line != source->line) {
X source->line--;
X afree((Void*)*histptr, APERM);
X histptr--;
X last_line = source->line;
X }
X}
X
X/*
X * save command in history
X */
Xvoid
Xhistsave(cmd)
X char *cmd;
X{
X register char **hp = histptr;
X char *cp;
X
X if (++hp >= history + HISTORY) { /* remove oldest command */
X afree((Void*)*history, APERM);
X for (hp = history; hp < history + HISTORY - 1; hp++)
X hp[0] = hp[1];
X }
X *hp = strsave(cmd, APERM);
X if ((cp = strchr(*hp, '\n')) != NULL)
X *cp = '\0';
X histptr = hp;
X}
X
X/*
X * get pointer to history given pattern
X * pattern is a number or string
X */
Xchar **
Xhistget(str)
X char *str;
X{
X register char **hp = NULL;
X
X if (*str == '-')
X hp = histptr + getn(str);
X else
X if (digit(*str))
X hp = histptr + (getn(str) - source->line);
X else
X if (*str == '?') { /* unanchored match */
X for (hp = histptr-1; hp >= history; hp--)
X if (strstr(*hp, str+1) != NULL)
X break;
X } else { /* anchored match */
X for (hp = histptr; hp >= history; hp--)
X if (strncmp(*hp, str, strlen(str)) == 0)
X break;
X }
X
X return (history <= hp && hp <= histptr) ? hp : NULL;
X}
X
Xchar *
Xhistrpl(s, pat, rep, global)
X char *s;
X char *pat, *rep;
X int global;
X{
X char *s1, *p, *last = NULL;
X int len = strlen(pat);
X
X if (strlen(s) - strlen(pat) + strlen(rep) >= LINE)
X errorf("substitution too long\n");
X line[0] = '\0';
X p = line;
X while (s1 = strstr(s, pat)) {
X strncpy(p, s, s1 - s); /* first part */
X strcpy(p + (s1 - s), rep); /* replacement */
X s = s1 + len;
X last = s1;
X p = strchr(p, 0);
X if (!global)
X s = "";
X }
X if (last)
X strcpy(p, last + len); /* last part */
X else
X errorf("substitution failed\n");
X return line;
X}
X
X#if 0
X
X/* History file management routines (by DPK@BRL) */
X
Xvoid
Xhist_init()
X{
X register struct namnod *n;
X int fd;
X
X if (hist_fd >= 0 || (flags&oneflg))
X return;
X if ((n = findnam(histname)) == (struct namnod *)0
X || n->namval == (char *)0)
X return;
X if ((fd = open(n->namval, O_RDWR)) >= 0) {
X hist_load(fd);
X (void)fcntl(fd, F_SETFL, O_APPEND);
X }
X hist_fd = fd;
X}
X
Xvoid
Xhist_finish()
X{
X if (hist_fd >= 0)
X (void)close(hist_fd);
X hist_fd = -1;
X}
X
Xvoid
Xhist_record(buf, len)
Xchar *buf;
Xint len;
X{
X if (hist_fd >= 0)
X (void)write(hist_fd, buf, (unsigned)len);
X}
X
Xvoid
Xhist_load(fd)
Xint fd;
X{
X extern long lseek();
X struct stat sb;
X char *x;
X register char *cmdp, *end;
X register int len;
X register int i;
X
X if (fstat(fd, &sb) < 0 || sb.st_size <= 0)
X return;
X if (x = alloc((unsigned)(sb.st_size+1))) {
X (void)lseek(fd, 0L, 0);
X if ((len = read(fd, x, (unsigned)sb.st_size)) <= 0) {
X free((struct blk *)x);
X return;
X }
X x[len] = 0;
X end = x;
X for (;;) {
X while(*end == NL)
X end++; /* Skip NL */
X if (*end == 0)
X break;
X cmdp = end;
X while(*end && *end != NL)
X end++; /* Goto NL */
X if (*end == 0)
X break;
X if ((len = (end - cmdp)) < 2)
X continue;
X if (len >= BUFSIZ)
X len = BUFSIZ - 1; /* Protection */
X i = curhist % NHISTORY;
X if(histbuf[i])
X free((struct blk *)histbuf[i]);
X histbuf[i] = alloc((unsigned)(len+1));
X (void)strncpy(histbuf[i], cmdp, len);
X histbuf[i][len] = 0;
X curhist++;
X histpc=curhist;
X }
X free((struct blk *)x);
X }
X return;
X}
X
X#endif
X
X/*
X * Return the current position.
X */
Xchar **
Xhistpos()
X{
X return current;
X}
X
Xint
XhistN()
X{
X return curpos;
X}
X
Xint
Xhistnum(n)
X{
X int last = histptr - history;
X
X if (n < 0 || n >= last) {
X current = histptr;
X curpos = last;
X return last;
X } else {
X current = &history[n];
X curpos = n;
X return n;
X }
X}
X
X/*
X * This will become unecessary if histget is modified to allow
X * searching from positions other than the end, and in either
X * direction.
X */
Xchar *
Xfindhist(start, fwd, str)
X int start;
X int fwd;
X char *str;
X{
X char **hp = NULL;
X int pos = start;
X char *line, *last;
X
X /* XXX check that we are valid after this */
X if (fwd)
X pos++;
X else
X pos--;
X histnum(pos);
X line = *histpos();
X do {
X last = line;
X if (strstr(line, str) != 0) {
X /* keep position current */
X return (line);
X }
X if (fwd)
X pos++;
X else
X pos--;
X histnum(pos);
X line = *histpos();
X } while (line && *line && line != last && pos>0);
X
X histnum(start);
X if (pos <= 0)
X return (char*)-1; /* TODO */
X return NULL;
X}
END_OF_FILE
if test 7391 -ne `wc -c <'sh/history.c'`; then
echo shar: \"'sh/history.c'\" unpacked with wrong size!
fi
# end of 'sh/history.c'
fi
if test -f 'sh/main.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'sh/main.c'\"
else
echo shar: Extracting \"'sh/main.c'\" \(8586 characters\)
sed "s/^X//" >'sh/main.c' <<'END_OF_FILE'
X/*
X * startup, main loop, enviroments and error handling
X */
X
X#ifndef lint
Xstatic char *RCSid = "$Id: main.c,v 3.3 89/03/27 15:51:39 egisin Exp $";
Xstatic char *sccs_id = "@(#)main.c 1.3 91/11/09 15:34:27 (sjg)";
X#endif
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 <time.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#ifdef sun /* sun's don't have a real /bin */
X "${SHELL:=/bin/sh} ${PATH:=/usr/bin:/usr/ucb:.} ${HOME:=/} ${PS1:=$ } ${PS2:=> } ${MAILCHECK:=600}";
X#else
X "${SHELL:=/bin/sh} ${PATH:=/bin:/usr/bin:.} ${HOME:=/} ${PS1:=$ } ${PS2:=> } ${MAILCHECK:=600}";
X#endif
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=1", NULL,
X "alias",
X "integer=typeset -i", "pwd=print -r \"$PWD\"",
X "history=fc -l", "r=fc -e -", "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
X#ifdef USE_TRACE
X/*
X * use SIGUSR1 to bump up Trace_level
X * use SIGUSR2 to clear Trace_level
X */
Xvoid
Xset_TraceLev(sig)
X int sig;
X{
X switch(sig)
X {
X case SIGUSR1:
X Trace_level++;
X break;
X case SIGUSR2:
X Trace_level = 0;
X break;
X }
X if (sig > 0)
X (void) signal(sig, set_TraceLev);
X return;
X}
X#endif
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, fflag = 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 extern time_t time();
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 kshpid = getpid();
X typeset(initifs, 0, 0); /* for security */
X typeset(ksh_version, 0, 0); /* RDONLY */
X
X#ifdef USE_TRACE
X (void) signal(SIGUSR1, set_TraceLev);
X (void) signal(SIGUSR2, set_TraceLev);
X _TRACE(0, ("Traces enabled.")); /* allow _TRACE to setup */
X#endif
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 setint(typeset("PPID", INTEGER, 0), (long) getppid());
X typeset("PPID", RDONLY, 0);
X setint(typeset("RANDOM", INTEGER, 0), (long) time((time_t *)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 && !flag[FSTDIN]) {
X if ((s->u.file = fopen(*++argv, "r")) == NULL)
X errorf("%s: cannot open\n", *argv);
X fflag = 1;
X s->file = name = *argv;
X argc--;
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 && !fflag)
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#ifdef EMACS
X x_init_emacs();
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#ifdef 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 Volatile int wastty;
X Volatile int reading = 0;
X extern void mcheck();
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 if (reading && s->type == STTY && s->line)
X s->line--;
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 ((wastty = (s->type == STTY)) || s->type == SHIST) {
X prompt = substitute(strval(global("PS1")), 0);
X mcheck();
X }
X
X reading = 1;
X t = compile(s);
X reading = 0;
X j_reap();
X if (t != NULL && t->type == TEOF)
X if (wastty && flag[FIGNEOF] && --attempts > 0) {
X shellf("Use `exit'\n");
X s->type = STTY;
X continue;
X }
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
END_OF_FILE
if test 8586 -ne `wc -c <'sh/main.c'`; then
echo shar: \"'sh/main.c'\" unpacked with wrong size!
fi
# end of 'sh/main.c'
fi
if test -f 'sh/tree.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'sh/tree.c'\"
else
echo shar: Extracting \"'sh/tree.c'\" \(9120 characters\)
sed "s/^X//" >'sh/tree.c' <<'END_OF_FILE'
X/*
X * command tree climbing
X */
X
Xstatic char *RCSid = "$Id: tree.c,v 3.2 89/03/27 15:52:13 egisin Exp $";
X
X#include <stddef.h>
X#include <string.h>
X#include <stdio.h>
X#include <errno.h>
X#include <setjmp.h>
X#include <varargs.h>
X#include "sh.h"
X#include "tree.h"
X
X#define FSTRING (FILE*)NULL
X
Xstatic int tputc ARGS((int c, FILE *f));
Xstatic void tputC ARGS((int c, FILE *f));
Xstatic void tputS ARGS((char *wp, FILE *f));
X
X/*
X * print a command tree
X */
X
Xvoid
Xptree(t, f)
X register struct op *t;
X register FILE *f;
X{
X register char **w;
X struct ioword **ioact;
X struct op *t1;
X
X Chain:
X if (t == NULL)
X return;
X switch (t->type) {
X case TCOM:
X for (w = t->vars; *w != NULL; )
X fptreef(f, "%S ", *w++);
X for (w = t->args; *w != NULL; )
X fptreef(f, "%S ", *w++);
X break;
X case TEXEC:
X t = t->left;
X goto Chain;
X case TPAREN:
X fptreef(f, "(%T)", t->left);
X break;
X case TPIPE:
X fptreef(f, "%T| ", t->left);
X t = t->right;
X goto Chain;
X case TLIST:
X fptreef(f, "%T", t->left);
X fptreef(f, "%;");
X t = t->right;
X goto Chain;
X case TOR:
X case TAND:
X fptreef(f, "%T", t->left);
X fptreef(f, "%s %T", (t->type==TOR) ? "||" : "&&", t->right);
X break;
X case TFOR:
X fptreef(f, "for %s ", t->str);
X if (t->vars != NULL) {
X fptreef(f, "in ");
X for (w = t->vars; *w; )
X fptreef(f, "%S ", *w++);
X fptreef(f, "%;");
X }
X fptreef(f, "do %T", t->left);
X fptreef(f, "%;done ");
X break;
X case TCASE:
X fptreef(f, "case %S in%;", t->str);
X for (t1 = t->left; t1 != NULL; t1 = t1->right) {
X fptreef(f, "(");
X for (w = t1->vars; *w != NULL; w++) {
X fptreef(f, "%S", *w);
X fptreef(f, "%c", (w[1] != NULL) ? '|' : ')');
X }
X fptreef(f, " %T;;%;", t1->left);
X }
X fptreef(f, "esac ");
X break;
X case TIF:
X fptreef(f, "if %T", t->left);
X fptreef(f, "%;");
X t = t->right;
X if (t->left != NULL) {
X fptreef(f, "then %T", t->left);
X fptreef(f, "%;");
X }
X if (t->right != NULL) {
X fptreef(f, "else %T", t->right);
X fptreef(f, "%;");
X }
X fptreef(f, "fi ");
X break;
X case TWHILE:
X case TUNTIL:
X fptreef(f, "%s %T",
X (t->type==TWHILE) ? "while" : "until",
X t->left);
X fptreef(f, "%;do %T", t->right);
X fptreef(f, "%;done ");
X break;
X case TBRACE:
X fptreef(f, "{%;%T", t->left);
X fptreef(f, "%;} ");
X break;
X case TASYNC:
X fptreef(f, "%T&", t->left);
X break;
X case TFUNCT:
X fptreef(f, "function %s %T", t->str, t->left);
X break;
X case TTIME:
X fptreef(f, "time %T", t->left);
X break;
X default:
X fptreef(f, "<botch>");
X break;
X }
X if ((ioact = t->ioact) != NULL)
X while (*ioact != NULL)
X pioact(f, *ioact++);
X}
X
Xpioact(f, iop)
X register FILE *f;
X register struct ioword *iop;
X{
X register int flag = iop->flag;
X if (iop->unit > 1)
X fptreef(f, "%c", '0' + iop->unit );
X
X switch(flag&IOTYPE) {
X case IOREAD:
X fptreef(f, "< ");
X break;
X case IOHERE:
X if (flag&IOSKIP)
X fptreef(f, "<<- ");
X else
X fptreef(f, "<< ");
X if (!(flag&IOEVAL))
X fptreef(f, "'");
X break;
X case IOCAT:
X fptreef(f, ">> ");
X break;
X case IOWRITE:
X if (flag&IOCLOB)
X fptreef(f, ">! ");
X else
X fptreef(f, "> ");
X break;
X case IODUP: /* Needs help */
X if (iop->unit == 0)
X fptreef(f, "<&");
X else
X fptreef(f, ">&");
X break;
X }
X
X if ((flag&IOTYPE) == IOHERE) {
X if (flag&IOEVAL)
X fptreef(f, "%s ", iop->name);
X else
X fptreef(f, "%s' ", iop->name);
X } else {
X fptreef(f, "%S ", iop->name);
X }
X}
X
X
X/*
X * variants of fputc, fputs for ptreef and snptreef
X */
X
Xstatic char *snpf_s; /* snptreef string */
Xstatic int snpf_n; /* snptreef length */
X
Xstatic int
Xtputc(c, f)
X int c;
X register FILE *f;
X{
X if (f != NULL)
X putc(c, f);
X else
X if (--snpf_n >= 0)
X *snpf_s++ = c;
X return c;
X}
X
Xstatic void
XtputC(c, f)
X register int c;
X register FILE *f;
X{
X if ((c&0x60) == 0) { /* C0|C1 */
X tputc((c&0x80) ? '$' : '^', f);
X tputc((c&0x7F|0x40), f);
X } else if ((c&0x7F) == 0x7F) { /* DEL */
X tputc((c&0x80) ? '$' : '^', f);
X tputc('?', f);
X } else
X tputc(c, f);
X}
X
Xstatic void
XtputS(wp, f)
X register char *wp;
X register FILE *f;
X{
X register int c, quoted=0;
X
X while (1)
X switch ((c = *wp++)) {
X case EOS:
X return;
X case CHAR:
X tputC(*wp++, f);
X break;
X case QCHAR:
X if (!quoted)
X tputc('\\', f);
X tputC(*wp++, f);
X break;
X case OQUOTE:
X quoted = 1;
X tputc('"', f);
X break;
X case CQUOTE:
X quoted = 0;
X tputc('"', f);
X break;
X case OSUBST:
X tputc('$', f);
X tputc('{', f);
X while ((c = *wp++) != 0)
X tputc(c, f);
X if (*wp != CSUBST)
X tputC(*wp++, f);
X break;
X case CSUBST:
X tputc('}', f);
X break;
X case COMSUB:
X tputc('$', f);
X tputc('(', f);
X while (*wp != 0)
X tputC(*wp++, f);
X tputc(')', f);
X break;
X }
X}
X
X/* TODO: use varargs properly */
X
X/* VARARGS */ int
Xfptreef(f, va_alist) va_dcl
X register FILE *f;
X{
X va_list va;
X char *fmt;
X
X va_start(va);
X fmt = va_arg(va, char *);
X vfptreef(f, fmt, va);
X va_end(va);
X return 0;
X}
X
X/* VARARGS */ int
Xsnptreef(s, n, va_alist) va_dcl
X char *s;
X int n;
X{
X va_list va;
X char *fmt;
X
X snpf_s = s;
X snpf_n = n;
X va_start(va);
X fmt = va_arg(va, char *);
X vfptreef(FSTRING, fmt, va);
X tputc('\0', FSTRING);
X va_end(va);
X return 0;
X}
X
Xvfptreef(f, fmt, va)
X register FILE *f;
X register char *fmt;
X register va_list va;
X{
X register int c;
X
X while ((c = *fmt++))
X if (c == '%') {
X register long n;
X register char *p;
X int neg;
X
X switch ((c = *fmt++)) {
X case 'c':
X tputc(va_arg(va, int), f);
X break;
X case 's':
X p = va_arg(va, char *);
X while (*p)
X tputc(*p++, f);
X break;
X case 'S': /* word */
X p = va_arg(va, char *);
X tputS(p, f);
X break;
X case 'd': case 'u': /* decimal */
X n = (c == 'd') ? va_arg(va, int) : va_arg(va, unsigned int);
X neg = c=='d' && n<0;
X p = ulton((neg) ? -n : n, 10);
X if (neg)
X *--p = '-';
X while (*p)
X tputc(*p++, f);
X break;
X case 'T': /* format tree */
X ptree(va_arg(va, struct op *), f);
X break;
X case ';': /* newline or ; */
X p = (f == FSTRING) ? "; " : "\n";
X while (*p)
X tputc(*p++, f);
X break;
X default:
X tputc(c, f);
X break;
X }
X } else
X tputc(c, f);
X}
X
X/*
X * copy tree (for function definition)
X */
X
Xstatic struct ioword **iocopy();
X
Xstruct op *
Xtcopy(t, ap)
X register struct op *t;
X Area *ap;
X{
X register struct op *r;
X register char **tw, **rw;
X
X if (t == NULL)
X return NULL;
X
X r = (struct op *) alloc(sizeof(struct op), ap);
X
X r->type = t->type;
X
X /* this will copy function and for identifiers quite accidently */
X r->str = (t->str == NULL) ? NULL : wdcopy(t->str, ap);
X
X if (t->vars == NULL)
X r->vars = NULL;
X else {
X for (tw = t->vars; *tw++ != NULL; )
X ;
X rw = r->vars = (char **)
X alloc((int)(tw - t->vars) * sizeof(*tw), ap);
X for (tw = t->vars; *tw != NULL; )
X *rw++ = wdcopy(*tw++, ap);
X *rw = NULL;
X }
X
X if (t->args == NULL)
X r->args = NULL;
X else {
X for (tw = t->args; *tw++ != NULL; )
X ;
X rw = r->args = (char **)
X alloc((int)(tw - t->args) * sizeof(*tw), ap);
X for (tw = t->args; *tw != NULL; )
X *rw++ = wdcopy(*tw++, ap);
X *rw = NULL;
X }
X
X r->ioact = (t->ioact == NULL) ? NULL : iocopy(t->ioact, ap);
X
X r->left = tcopy(t->left, ap);
X r->right = tcopy(t->right, ap);
X
X return r;
X}
X
Xchar *
Xwdcopy(wp, ap)
X char *wp;
X Area *ap;
X{
X size_t len = wdscan(wp, EOS) - wp;
X return memcpy(alloc(len, ap), wp, len);
X}
X
X/* return the position of prefix c in wp plus 1 */
Xchar *
Xwdscan(wp, c)
X register char *wp;
X register int c;
X{
X register int nest = 0;
X
X while (1)
X switch (*wp++) {
X case EOS:
X return wp;
X case CHAR:
X case QCHAR:
X wp++;
X break;
X case OQUOTE:
X case CQUOTE:
X break;
X case OSUBST:
X nest++;
X while (*wp++ != 0)
X ;
X if (*wp != CSUBST)
X wp++;
X break;
X case CSUBST:
X if (c == CSUBST && nest == 0)
X return wp;
X nest--;
X break;
X case COMSUB:
X while (*wp++ != 0)
X ;
X break;
X }
X}
X
Xstatic struct ioword **
Xiocopy(iow, ap)
X register struct ioword **iow;
X Area *ap;
X{
X register struct ioword **ior;
X register int i;
X
X for (ior = iow; *ior++ != NULL; )
X ;
X ior = (struct ioword **) alloc((int)(ior - iow) * sizeof(*ior), ap);
X
X for (i = 0; iow[i] != NULL; i++) {
X register struct ioword *p, *q;
X
X p = iow[i];
X q = (struct ioword *) alloc(sizeof(*p), ap);
X ior[i] = q;
X *q = *p;
X if (p->name != NULL)
X q->name = wdcopy(p->name, ap);
X }
X ior[i] = NULL;
X
X return ior;
X}
X
X/*
X * free tree (for function definition)
X */
X
Xstatic void iofree();
X
Xvoid
Xtfree(t, ap)
X register struct op *t;
X Area *ap;
X{
X register char **w;
X
X if (t == NULL)
X return;
X
X if (t->str != NULL)
X afree((Void*)t->str, ap);
X
X if (t->vars != NULL) {
X for (w = t->vars; *w != NULL; w++)
X afree((Void*)*w, ap);
X afree((Void*)t->vars, ap);
X }
X
X if (t->args != NULL) {
X for (w = t->args; *w != NULL; w++)
X afree((Void*)*w, ap);
X afree((Void*)t->args, ap);
X }
X
X if (t->ioact != NULL)
X iofree(t->ioact, ap);
X
X tfree(t->left, ap);
X tfree(t->right, ap);
X
X afree((Void*)t, ap);
X}
X
Xstatic void
Xiofree(iow, ap)
X struct ioword **iow;
X Area *ap;
X{
X register struct ioword **iop;
X register struct ioword *p;
X
X for (iop = iow; (p = *iop++) != NULL; ) {
X if (p->name != NULL)
X afree((Void*)p->name, ap);
X afree((Void*)p, ap);
X }
X}
X
END_OF_FILE
if test 9120 -ne `wc -c <'sh/tree.c'`; then
echo shar: \"'sh/tree.c'\" unpacked with wrong size!
fi
# end of 'sh/tree.c'
fi
if test -f 'std/stdc/stdio.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'std/stdc/stdio.c'\"
else
echo shar: Extracting \"'std/stdc/stdio.c'\" \(301 characters\)
sed "s/^X//" >'std/stdc/stdio.c' <<'END_OF_FILE'
X/*
X * Emulation of misc. ANSI C stdio functions
X */
X
X/* $Header */
X
X#include <stdio.h>
X
X#if 1
Xint
Xremove(name)
X Const char *name;
X{
X return unlink(name);
X}
X#endif
X
X#if _V7
Xint
Xrename(oname, nname)
X Const char *oname, *nname;
X{
X return link(oname, nname) == 0 && unlink(oname) == 0 ? 0 : -1;
X}
X#endif
X
END_OF_FILE
if test 301 -ne `wc -c <'std/stdc/stdio.c'`; then
echo shar: \"'std/stdc/stdio.c'\" unpacked with wrong size!
fi
# end of 'std/stdc/stdio.c'
fi
echo shar: End of archive 5 \(of 9\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 9 archives.
rm -f ark[1-9]isdone ark[1-9][0-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.