home *** CD-ROM | disk | FTP | other *** search
- From: netnews@netcom.UUCP (USENET Administration)
- Newsgroups: alt.sources
- Subject: Public Domain Korn Shell - Part.05 of 7
- Message-ID: <18610@netcom.UUCP>
- Date: 12 Dec 90 11:38:04 GMT
-
- #!/bin/sh
- # This is part 05 of ksh-pd
- # ============= src/c_ksh.c ==============
- if test ! -d 'src'; then
- echo 'x - creating directory src'
- mkdir 'src'
- fi
- if test -f 'src/c_ksh.c' -a X"$1" != X"-c"; then
- echo 'x - skipping src/c_ksh.c (File already exists)'
- else
- echo 'x - extracting src/c_ksh.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'src/c_ksh.c' &&
- X/*
- X * built-in Korn commands: c_*
- X */
- X
- Xstatic char *RCSid = "$Id: c_ksh.c,v 3.2 89/01/23 10:57:38 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 "table.h"
- X
- Xint
- Xc_hash(wp)
- X register char **wp;
- X{
- X register int i;
- X register struct tbl *tp, **p;
- X
- X wp++;
- X if (*wp == NULL) {
- X for (p = tsort(&commands); (tp = *p++) != NULL; )
- X if ((tp->flag&ISSET))
- X printf("%s\n", tp->val.s);
- X return 0;
- X }
- X
- X if (strcmp(*wp, "-r") == 0)
- X flushcom(1);
- X while (*wp != NULL)
- X findcom(*wp++, 1);
- X return 0;
- X}
- X
- Xint
- Xc_print(wp)
- X register char **wp;
- X{
- X int nl = 1;
- X int expand = 1;
- X FILE *f = stdout;
- X
- X for (wp++; *wp != NULL && **wp == '-'; wp++) {
- X register char *s = *wp + 1;
- X if (*s == '\0') {
- X wp++;
- X break;
- X }
- X while (*s) switch (*s++) {
- X case 'n':
- X nl = 0;
- X break;
- X case 'e':
- X expand = 1;
- X break;
- X case 'r':
- X expand = 0;
- X break;
- X case 'u':
- X if (!digit(*s) || (f = shf[*s++-'0']) == NULL)
- X errorf("bad -u argument\n");
- X break;
- X }
- X }
- X
- X while (*wp != NULL) {
- X register char *s = *wp;
- X register int c;
- X while ((c = *s++) != '\0')
- X if (expand && c == '\\') {
- X switch ((c = *s++)) {
- X case 'b': c = '\b'; break;
- X case 'c': nl = 0; continue; /* AT&T brain damage */
- X case 'f': c = '\f'; break;
- X case 'n': c = '\n'; break;
- X case 'r': c = '\r'; break;
- X case 't': c = '\t'; break;
- X case 'v': c = 0x0B; break;
- X case '0': case '1': case '2': case '3':
- X case '4': case '5': case '6': case '7':
- X c = c - '0';
- X if (*s >= '0' && *s <= '7')
- X c = 8*c + *s++ - '0';
- X if (*s >= '0' && *s <= '7')
- X c = 8*c + *s++ - '0';
- X break;
- X case '\\': break;
- X default:
- X putc('\\', f);
- X }
- X putc(c, f);
- X } else
- X putc(c, f);
- X if (*++wp != NULL)
- X putc(' ', f);
- X }
- X if (nl)
- X putc('\n', f);
- X return 0;
- X}
- X
- X/* todo: handle case where id is both lexical and command */
- Xint
- Xc_whence(wp)
- X register char **wp;
- X{
- X register struct tbl *tp;
- X char *id;
- X int vflag = 0;
- X
- X for (wp++; (id = *wp) != NULL && *id == '-'; wp++)
- X if (id[1] == 'v')
- X vflag = 1;
- X
- X while ((id = *wp++) != NULL) {
- X tp = tsearch(&lexicals, id, hash(id));
- X if (tp == NULL)
- X tp = findcom(id, 1);
- X if (vflag)
- X switch ((tp == NULL) ? CNONE : tp->type) {
- X case CNONE:
- X printf("%s is unknown\n", id);
- X break;
- X case CSHELL:
- X printf("%s is a shell builtin\n", id);
- X break;
- X case CFUNC:
- X printf("%s is a function\n", id);
- X fptreef(stdout, "function %s %T\n", id, tp->val.t);
- X break;
- X case CEXEC:
- X printf("%s is %s\n", id,
- X (tp->flag&ISSET) ? tp->val.s : "unknown");
- X break;
- X case CALIAS:
- X printf("%s is the alias '%s'\n", id, tp->val.s);
- X break;
- X case CKEYWD:
- X printf("%s is a shell keyword\n", id);
- X break;
- X default:
- X printf("%s is *GOK*\n", id);
- X break;
- X }
- X else
- X switch ((tp == NULL) ? CNONE : tp->type) {
- X case CNONE:
- X printf("\n");
- X break;
- X case CSHELL:
- X printf("builtin %s\n", id);
- X break;
- X case CFUNC:
- X printf("%s\n", id);
- X break;
- X case CEXEC:
- X printf("%s\n", (tp->flag&ISSET) ? tp->val.s : id);
- X break;
- X case CALIAS:
- X printf("%s\n", tp->val.s);
- X break;
- X case CKEYWD:
- X printf("%s\n", id);
- X break;
- X default:
- X printf("*GOK*\n");
- X break;
- X }
- X }
- X return 0;
- X}
- X
- X/* typeset, export, and readonly */
- Xint
- Xc_typeset(wp)
- X register char **wp;
- X{
- X register char *id;
- X struct block *l = e.loc;
- X register struct tbl *vp, **p;
- X int fset = 0, fclr = 0;
- X int thing = 0, func = 0, local = 0;
- X
- X switch (**wp) {
- X case 'e': /* export */
- X fset |= EXPORT;
- X break;
- X case 'r': /* readonly */
- X fset |= RDONLY;
- X break;
- X case 't': /* typeset */
- X local = 1;
- X break;
- X }
- X
- X for (wp++; (id = *wp) != NULL && (*id == '-' || *id == '+'); wp++) {
- X int flag = 0;
- X thing = *id;
- X while (*++id != '\0') switch (*id) {
- X case 'f':
- X flag |= FUNCT;
- X func = 1;
- X break;
- X case 'i':
- X flag |= INTEGER;
- X break;
- X case 'r':
- X flag |= RDONLY;
- X break;
- X case 'x':
- X flag |= EXPORT;
- X break;
- X case 't':
- X flag |= TRACE;
- X break;
- X default:
- X errorf("unknown flag -%c\n", *id);
- X }
- X if (flag != 0) { /* + or - with options */
- X if (thing == '-')
- X fset |= flag;
- X else
- X fclr |= flag;
- X thing = 0;
- X }
- X }
- X
- X /* list variables and attributes */
- X if (*wp == NULL) {
- X for (l = e.loc; l != NULL; l = l->next) {
- X for (p = tsort((func==0) ? &l->vars : &l->funs);
- X (vp = *p++) != NULL; )
- X if ((vp->flag&ISSET))
- X if (thing == 0 && fclr == 0 && fset == 0) {
- X printf("typeset ");
- X if ((vp->flag&INTEGER))
- X printf("-i ");
- X if ((vp->flag&EXPORT))
- X printf("-x ");
- X if ((vp->flag&RDONLY))
- X printf("-r ");
- X if ((vp->flag&TRACE))
- X printf("-t ");
- X printf("%s\n", vp->name);
- X } else
- X if (thing == '+' ||
- X fclr && (vp->flag&fclr) == fclr) {
- X printf("%s\n", vp->name);
- X } else
- X if (thing == '-' ||
- X fset && (vp->flag&fset) == fset) {
- X if (fset&FUNCT)
- X printf("function %s\n", vp->name);
- X else
- X printf("%s=%s\n", vp->name, strval(vp));
- X }
- X }
- X return (0);
- X }
- X
- X if (local)
- X fset |= LOCAL;
- X for (; *wp != NULL; wp++)
- X#if 0
- X if (func) {
- X } else
- X#endif
- X if (typeset(*wp, fset, fclr) == NULL)
- X errorf("%s: not identifier\n", *wp);
- X return 0;
- X}
- X
- Xint
- Xc_alias(wp)
- X register char **wp;
- X{
- X register struct table *t = &lexicals;
- X register struct tbl *ap, **p;
- X register int i;
- X int rv = 0;
- X
- X if (*++wp != NULL && strcmp(*wp, "-d") == 0) {
- X t = &homedirs;
- X wp++;
- X }
- X
- X if (*wp == NULL)
- X for (p = tsort(t); (ap = *p++) != NULL; )
- X if (ap->type == CALIAS && (ap->flag&DEFINED))
- X printf("%s='%s'\n", ap->name, ap->val.s);
- X
- X for (; *wp != NULL; wp++) {
- X register char *id = *wp;
- X register char *val = strchr(id, '=');
- X
- X if (val == NULL) {
- X ap = tsearch(t, id, hash(id));
- X if (ap != NULL && ap->type == CALIAS && (ap->flag&DEFINED))
- X printf("%s='%s'\n", ap->name, ap->val.s);
- X else
- X rv = 1;
- X } else {
- X *val++ = '\0';
- X ap = tenter(t, id, hash(id));
- X if (ap->type == CKEYWD)
- X errorf("cannot alias keyword\n");
- X if ((ap->flag&ALLOC)) {
- X afree((Void*)ap->val.s, APERM);
- X ap->flag &=~ ALLOC|ISSET;
- X }
- X ap->type = CALIAS;
- X ap->val.s = strsave(val, APERM);
- X ap->flag |= DEFINED|ALLOC|ISSET;
- X }
- X }
- X return rv;
- X}
- X
- Xint
- Xc_unalias(wp)
- X register char **wp;
- X{
- X register struct table *t = &lexicals;
- X register struct tbl *ap;
- X
- X if (*++wp != NULL && strcmp(*wp, "-d") == 0) {
- X t = &homedirs;
- X wp++;
- X }
- X
- X for (; *wp != NULL; wp++) {
- X ap = tsearch(t, *wp, hash(*wp));
- X if (ap == NULL || ap->type != CALIAS)
- X continue;
- X if ((ap->flag&ALLOC))
- X afree((Void*)ap->val.s, APERM);
- X ap->flag &=~ DEFINED|ISSET|ALLOC;
- X }
- X return 0;
- X}
- X
- Xint
- Xc_let(wp)
- X char **wp;
- X{
- X int rv = 1;
- X
- X for (wp++; *wp; wp++)
- X rv = evaluate(*wp) == 0;
- X return rv;
- X}
- X
- Xint
- Xc_jobs(wp)
- X char **wp;
- X{
- X j_jobs();
- X return 0;
- X}
- X
- X#if JOBS
- Xint
- Xc_fgbg(wp)
- X register char **wp;
- X{
- X int bg = strcmp(*wp, "bg") == 0;
- X
- X if (!flag[FMONITOR])
- X errorf("Job control not enabled\n");
- X wp++;
- X j_resume(j_lookup((*wp == NULL) ? "%" : *wp), bg);
- X return 0;
- X}
- X#endif
- X
- Xint
- Xc_kill(wp)
- X register char **wp;
- X{
- X register char *cp;
- X int sig = 15; /* SIGTERM */
- X int rv = 0;
- X
- X if (*++wp == NULL)
- X errorf("Usage: kill [-l] [-signal] {pid|job} ...\n");
- X if (strcmp(*wp, "-l") == 0) {
- X register struct trap *p = sigtraps;
- X for (sig = 0; sig < SIGNALS; sig++, p++)
- X if (p->signal)
- X printf("%2d %8s %s\n", p->signal, p->name, p->mess);
- X return 0;
- X }
- X
- X for (; (cp = *wp) != NULL; wp++)
- X if (*cp == '-') {
- X struct trap *p;
- X p = gettrap(cp+1);
- X if (p == NULL)
- X errorf("bad signal %s\n", cp+1);
- X sig = p->signal;
- X } else
- X if (digit(*cp)) {
- X if (kill(atoi(cp), sig) < 0) {
- X shellf("%s: %s\n", cp, strerror(errno));
- X rv++;
- X }
- X } else
- X if (*cp == '%')
- X j_kill(j_lookup(cp), sig);
- X else
- X errorf("invalid argument\n");
- X return rv;
- X}
- X
- Xint
- Xc_bind(wp)
- X register char **wp;
- X{
- X int macro = 0;
- X register char *cp;
- X
- X for (wp++; (cp = *wp) != NULL && *cp == '-'; wp++)
- X if (cp[1] == 'm')
- X macro = 1;
- X
- X if (*wp == NULL) /* list all */
- X x_bind((char*)NULL, (char*)NULL, 0);
- X
- X for (; *wp != NULL; wp++) {
- X cp = strchr(*wp, '=');
- X if (cp != NULL)
- X *cp++ = 0;
- X x_bind(*wp, cp, macro);
- X }
- X
- X return 0;
- X}
- X
- Xextern c_fc();
- Xextern c_getopts();
- X
- XConst struct builtin kshbuiltins [] = {
- X {"print", c_print},
- X {"getopts", c_getopts},
- X {"=typeset", c_typeset},
- X {"=export", c_typeset},
- X {"=readonly", c_typeset},
- X {"whence", c_whence},
- X {"alias", c_alias},
- X {"unalias", c_unalias},
- X {"hash", c_hash},
- X {"let", c_let},
- X {"fc", c_fc},
- X {"jobs", c_jobs},
- X {"kill", c_kill},
- X#if JOBS
- X {"fg", c_fgbg},
- X {"bg", c_fgbg},
- X#endif
- X#if EDIT
- X {"bind", c_bind},
- X#endif
- X {NULL, NULL}
- X};
- X
- SHAR_EOF
- true || echo 'restore of src/c_ksh.c failed'
- fi
- # ============= src/c_test.c ==============
- if test -f 'src/c_test.c' -a X"$1" != X"-c"; then
- echo 'x - skipping src/c_test.c (File already exists)'
- else
- echo 'x - extracting src/c_test.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'src/c_test.c' &&
- 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 = "$Header: /tmp/egisin/src/RCS/c_test.c,v 3.2 88/12/17 21:39:26 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
- Xint
- Xc_test(wp)
- X char **wp;
- 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 return *t_wp == NULL || !oexpr(t_lex(*t_wp));
- X}
- X
- Xstatic
- Xsyntax()
- X{
- X errorf("test: syntax error\n");
- 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();
- X if (n == LPAREN) {
- X res = oexpr(t_lex(*++t_wp));
- X if (t_lex(*++t_wp) != RPAREN)
- X syntax();
- X return res;
- X }
- X if (n == OPERAND) {
- 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();
- 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 if (t_wp_op->op_type == UNOP) {
- X /* unary expression */
- X if (*++t_wp == NULL && n != FILTT)
- X syntax();
- 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 syntax();
- 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 return EOI;
- 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
- SHAR_EOF
- true || echo 'restore of src/c_test.c failed'
- fi
- # ============= src/getopts.c ==============
- if test -f 'src/getopts.c' -a X"$1" != X"-c"; then
- echo 'x - skipping src/getopts.c (File already exists)'
- else
- echo 'x - extracting src/getopts.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'src/getopts.c' &&
- X/*
- X * Reimplementation of SysVr3 sh builtin command "getopts" for S5R2 shell.
- X *
- X * created by Arnold Robbins
- X * modified by Doug Gwyn
- X * modified for PD ksh by Eric Gisin
- X */
- X
- Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/getopts.c,v 3.2 89/01/14 13:29:26 egisin Exp $";
- X
- X#include <stddef.h>
- X#include <string.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include "sh.h"
- X#include "table.h"
- X
- X/*
- X * The following is derived from getopt() source placed into the public
- X * domain by AT&T (the only time they're known to have done that).
- X *
- X * It has been modified somewhat to fit into the context of the shell.
- X *
- X * -D"FASCIST" if you really want to strictly enforce ALL the
- X * Command Syntax Standard rules (not recommended).
- X */
- X
- X#define GETOPTEOF (-1)
- X#define ERR(S, C) shellf("%s%c\n", (S), (C))
- X
- Xstatic int optind;
- Xstatic char *optarg;
- Xstatic int sp;
- X
- Xstatic int
- Xgetopt(argc, argv, opts)
- X int argc;
- X register char **argv, *opts;
- X{
- X register int c;
- X register char *cp;
- X
- X if (sp == 1)
- X if (optind >= argc ||
- X argv[optind][0] != '-' || argv[optind][1] == '\0')
- X return(GETOPTEOF);
- X else if (strcmp(argv[optind], "--") == 0) {
- X optind++;
- X return(GETOPTEOF);
- X }
- X c = argv[optind][sp];
- X if (c == ':' || (cp=strchr(opts, c)) == NULL) {
- X ERR("illegal option -- ", c);
- X if (argv[optind][++sp] == '\0') {
- X optind++;
- X sp = 1;
- X }
- X optarg = NULL;
- X return('?');
- X }
- X if (*++cp == ':') {
- X#if FASCIST
- X if (sp != 1) {
- X ERR("option must not be grouped -- ", c );
- X optind++;
- X sp = 1;
- X optarg = NULL;
- X return('?');
- X } else
- X#endif
- X if (argv[optind][sp+1] != '\0') {
- X#if FASCIST
- X ERR("option must be followed by whitespace -- ", c );
- X optind++;
- X sp = 1;
- X optarg = NULL;
- X return('?');
- X#else
- X optarg = &argv[optind++][sp+1];
- X#endif
- X } else if (++optind >= argc) {
- X ERR("option requires an argument -- ", c);
- X sp = 1;
- X optarg = NULL;
- X return('?');
- X } else
- X optarg = argv[optind++];
- X sp = 1;
- X } else {
- X if (argv[optind][++sp] == '\0') {
- X sp = 1;
- X optind++;
- X }
- X optarg = NULL;
- X }
- X return(c);
- X}
- X
- X/*
- X * The following were created by Arnold Robbins.
- X */
- X
- X/* resetopts --- magic code for when OPTIND is reset to 1 */
- X
- Xvoid
- Xresetopts ()
- X{
- X optind = 1;
- X sp = 1;
- X}
- X
- Xint
- Xc_getopts(wp)
- X char **wp;
- X{
- X int ret;
- X register int argc;
- X char temp[2];
- X char *optstr; /* list of options */
- X char *name; /* variable to get flag val */
- X
- X if ((optstr = *++wp) == NULL || (name = *++wp) == NULL)
- X errorf("missing arguments\n");
- X
- X for (argc = 1; wp[argc] != NULL; argc++)
- X ;
- X
- X if (argc > 1)
- X ret = getopt(argc, wp, optstr);
- X else
- X ret = getopt(e.loc->argc+1, e.loc->argv, optstr);
- X
- X /*
- X * set the OPTIND variable in any case, to handle "--" skipping
- X */
- X
- X setint(global("OPTIND"), (long)optind);
- X
- X if (ret == GETOPTEOF) /* end of args */
- X return (1);
- X
- X /*
- X * else, got an arg, set the various shell variables
- X */
- X
- X if (optarg != NULL)
- X setstr(global("OPTARG"), optarg);
- X
- X temp[0] = (char) ret;
- X temp[1] = '\0';
- X setstr(global(name), temp);
- X
- X return (0);
- X}
- X
- SHAR_EOF
- true || echo 'restore of src/getopts.c failed'
- fi
- # ============= src/ulimit.c ==============
- if test -f 'src/ulimit.c' -a X"$1" != X"-c"; then
- echo 'x - skipping src/ulimit.c (File already exists)'
- else
- echo 'x - extracting src/ulimit.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'src/ulimit.c' &&
- X/*
- X ulimit -- handle "ulimit" builtin
- X
- X Eric Gisin, September 1988
- X Adapted to PD KornShell. Removed AT&T code.
- X
- X last edit: 06-Jun-1987 D A Gwyn
- X
- X This started out as the BRL UNIX System V system call emulation
- X for 4.nBSD, and was later extended by Doug Kingston to handle
- X the extended 4.nBSD resource limits. It now includes the code
- X that was originally under case SYSULIMIT in source file "xec.c".
- X*/
- X
- Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/ulimit.c,v 3.1 88/11/03 09:18:11 egisin Exp $";
- X
- X#include <stddef.h>
- X#include <errno.h>
- X#include <signal.h>
- X#include <setjmp.h>
- X#if defined(_BSD) || defined(_BSD_SYSV)
- X#include <sys/time.h>
- X#include <sys/resource.h>
- X#else
- X#define RLIMIT_FSIZE 2
- X#endif
- X#include "sh.h"
- X
- Xextern long ulimit();
- X
- Xint
- Xdo_ulimit(a1, a2)
- X char *a1, *a2;
- X{
- X register int c;
- X long i;
- X#if defined(_BSD) || defined(_BSD_SYSV)
- X struct rlimit limit; /* data being gotten/set */
- X int softonly = 0; /* set => soft limit, clear => hard limit */
- X int factor = 1024; /* unit scaling (1K or 1) */
- X#endif
- X int command = RLIMIT_FSIZE;
- X
- X if (a1 && (*a1 == '-')) /* DAG -- Gould added first test */
- X { c = *++a1; /* DAG */
- X#if defined(_BSD) || defined(_BSD_SYSV)
- X if (c >= 'A' && c <= 'Z')
- X {
- X ++softonly;
- X c += 'a' - 'A'; /* DAG -- map to lower-case */
- X }
- X#endif
- X switch(c)
- X {
- X#if defined(_BSD) || defined(_BSD_SYSV)
- X case 'c':
- X command = RLIMIT_CORE;
- X break;
- X case 'd':
- X command = RLIMIT_DATA;
- X break;
- X case 'm':
- X command = RLIMIT_RSS;
- X break;
- X case 's':
- X command = RLIMIT_STACK;
- X break;
- X case 't':
- X factor = 1;
- X command = RLIMIT_CPU;
- X break;
- X#endif /* _BSD || _BSD_SYSV */
- X case 'f':
- X command = RLIMIT_FSIZE;
- X#if _BSD_SYSV
- X factor = 512;
- X#endif
- X break;
- X default:
- X#if _BSD
- X errorf("Usage: %s [-cdmstf] [limit]\n", "ulimit");
- X#else
- X errorf("Usage: %s [-f] [limit]\n", "ulimit");
- X#endif
- X }
- X a1 = a2;
- X }
- X if (a1)
- X {
- X i = 0;
- X while ((c = *a1++) >= '0' && c <= '9')
- X {
- X i = (i * 10) + (long)(c - '0');
- X if (i < 0)
- X goto Error;
- X }
- X if (c || i < 0)
- X goto Error;
- X }
- X#if !(defined(_BSD) || defined(_BSD_SYSV))
- X else
- X {
- X i = -1;
- X command--;
- X }
- X
- X if ((i = ulimit(command, i)) < 0L)
- X goto Error;
- X
- X if (command != RLIMIT_FSIZE)
- X shellf("%ld\n", i);
- X#else /* DPK -- generalized for 4.nBSD: */
- X if (getrlimit(command, &limit))
- X goto Error; /* errno is already set */
- X
- X if (a1)
- X {
- X limit.rlim_cur = i * factor;
- X
- X if (!softonly)
- X limit.rlim_max = limit.rlim_cur;
- X
- X if (setrlimit(command, &limit))
- X goto Error;
- X }
- X else
- X {
- X i = softonly ? limit.rlim_cur : limit.rlim_max;
- X#if _BSD /* DAG -- System V always prints an integer */
- X if (i == RLIM_INFINITY)
- X shellf("unlimited\n");
- X else
- X#endif
- X shellf("%ld\n", i/factor);
- X }
- X#endif /* _BSD || _BSD_SYSV */
- X return 0;
- X
- X Error:
- X errorf("bad ulimit\n");
- X}
- X
- SHAR_EOF
- true || echo 'restore of src/ulimit.c failed'
- fi
- # ============= src/var.c ==============
- if test -f 'src/var.c' -a X"$1" != X"-c"; then
- echo 'x - skipping src/var.c (File already exists)'
- else
- echo 'x - extracting src/var.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'src/var.c' &&
- Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/var.c,v 3.1 88/11/03 09:18:22 egisin Exp $";
- X
- X#include <stddef.h>
- X#include <string.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include <time.h>
- X#include "sh.h"
- X#include "table.h"
- X#include "expand.h"
- X
- X/*
- X * Variables
- X *
- X * WARNING: unreadable code, needs a rewrite
- X *
- X * if (flag&INTEGER), val.i contains integer value, and type contains base.
- X * otherwise, (val.s + type) contains string value.
- X * if (flag&EXPORT), val.s contains "name=value" for E-Z exporting.
- X */
- Xchar null [] = "";
- Xstatic struct tbl vtemp;
- Xstatic void getspec(), setspec();
- Xstatic void export ARGS((struct tbl *, char *val));
- Xstatic int special ARGS ((char *name));
- X
- X/*
- X * create a new block for function calls and simple commands
- X * assume caller has allocated and set up e.loc
- X */
- Xvoid
- Xnewblock()
- X{
- X register struct block *l = e.loc;
- X static char *empty[] = {""};
- X
- X ainit(&l->area);
- X l->argc = 0;
- X l->argv = empty;
- X l->exit = l->error = NULL;
- X tinit(&l->vars, &l->area);
- X tinit(&l->funs, &l->area);
- X}
- X
- X/*
- X * pop a block handling special variables
- X */
- Xvoid
- Xpopblock()
- X{
- X register struct block *l = e.loc;
- X register struct tbl *vp, **vpp = l->vars.tbls;
- X register int i;
- X
- X e.loc = l->next; /* pop block */
- X for (i = l->vars.size; --i >= 0; )
- X if ((vp = *vpp++) != NULL && (vp->flag&SPECIAL))
- X setspec(global(vp->name));
- X afreeall(&l->area);
- X}
- X
- X/*
- X * Search for variable, if not found create globally.
- X */
- Xstruct tbl *
- Xglobal(n)
- X register char *n;
- X{
- X register struct block *l = e.loc;
- X register struct tbl *vp;
- X register int c;
- X unsigned h = hash(n);
- X
- X c = n[0];
- X if (digit(c)) {
- X vp = &vtemp;
- X lastarea = ATEMP;
- X vp->flag = (DEFINED|RDONLY);
- X vp->type = 0;
- X *vp->name = c; /* should strncpy */
- X for (c = 0; digit(*n) && c < 1000; n++)
- X c = c*10 + *n-'0';
- X if (c <= l->argc)
- X setstr(vp, l->argv[c]);
- X return vp;
- X } else
- X if (!letter(c)) {
- X vp = &vtemp;
- X lastarea = ATEMP;
- X vp->flag = (DEFINED|RDONLY);
- X vp->type = 0;
- X *vp->name = c;
- X if (n[1] != '\0')
- X return vp;
- X vp->flag |= ISSET|INTEGER;
- X switch (c) {
- X case '$':
- X vp->val.i = getpid();
- X break;
- X case '!':
- X vp->val.i = async;
- X break;
- X case '?':
- X vp->val.i = exstat;
- X break;
- X case '#':
- X vp->val.i = l->argc;
- X break;
- X case '-':
- X vp->flag &= ~ INTEGER;
- X vp->val.s = getoptions();
- X break;
- X default:
- X vp->flag &= ~(ISSET|INTEGER);
- X }
- X return vp;
- X }
- X for (l = e.loc; l != NULL; l = l->next) {
- X vp = tsearch(&l->vars, n, h);
- X lastarea = &l->area;
- X if (vp != NULL)
- X return vp;
- X if (l->next == NULL)
- X break;
- X }
- X vp = tenter(&l->vars, n, h);
- X vp->flag |= DEFINED;
- X if (special(n))
- X vp->flag |= SPECIAL;
- X return vp;
- X}
- X
- X/*
- X * Search for local variable, if not found create locally.
- X */
- Xstruct tbl *
- Xlocal(n)
- X register char *n;
- X{
- X register struct block *l = e.loc;
- X register struct tbl *vp;
- X unsigned h = hash(n);
- X
- X if (!letter(*n)) {
- X vp = &vtemp;
- X lastarea = ATEMP;
- X vp->flag = (DEFINED|RDONLY);
- X vp->type = 0;
- X return vp;
- X }
- X vp = tenter(&l->vars, n, h);
- X lastarea = &l->area;
- X vp->flag |= DEFINED;
- X if (special(n))
- X vp->flag |= SPECIAL;
- X return vp;
- X}
- X
- X/* get variable string value */
- Xchar *
- Xstrval(vp)
- X register struct tbl *vp;
- X{
- X register char *s;
- X static char strbuf[40];
- X
- X if ((vp->flag&SPECIAL))
- X getspec(vp);
- X if (!(vp->flag&ISSET))
- X return null; /* special to dollar() */
- X if (!(vp->flag&INTEGER)) /* string source */
- X s = vp->val.s + vp->type;
- X else { /* integer source */
- X register unsigned long n;
- X register int base;
- X
- X s = strbuf + sizeof(strbuf);
- X n = (vp->val.i < 0) ? -vp->val.i : vp->val.i;
- X base = (vp->type == 0) ? 10 : vp->type;
- X
- X *--s = '\0';
- X do {
- X *--s = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[n%base];
- X n /= base;
- X } while (n != 0);
- X /* todo: should we output base# ? */
- X if (vp->val.i < 0)
- X *--s = '-';
- X }
- X return s;
- X}
- X
- X/* get variable integer value */
- Xlong
- Xintval(vp)
- X register struct tbl *vp;
- X{
- X register struct tbl *vq;
- X
- X if ((vp->flag&SPECIAL))
- X getspec(vp);
- X if ((vp->flag&INTEGER))
- X return vp->val.i;
- X vq = &vtemp;
- X vq->flag = (INTEGER);
- X vq->type = 0;
- X strint(vq, vp);
- X return vq->val.i;
- X}
- X
- X/* set variable to string value */
- Xvoid
- Xsetstr(vq, s)
- X register struct tbl *vq;
- X char *s;
- X{
- X if (!(vq->flag&INTEGER)) { /* string dest */
- X if ((vq->flag&ALLOC))
- X afree((Void*)vq->val.s, lastarea);
- X vq->flag &= ~ (ISSET|ALLOC);
- X vq->type = 0;
- X if ((vq->flag&EXPORT))
- X export(vq, s);
- X else
- X vq->val.s = strsave(s, lastarea);
- X vq->flag |= ALLOC;
- X } else { /* integer dest */
- X register struct tbl *vp = &vtemp;
- X vp->flag = (DEFINED|ISSET);
- X vp->type = 0;
- X vp->val.s = s;
- X strint(vq, vp);
- X }
- X vq->flag |= ISSET;
- X if ((vq->flag&SPECIAL))
- X setspec(vq);
- X}
- X
- X/* convert variable to integer variable */
- Xstruct tbl *
- Xstrint(vq, vp)
- X register struct tbl *vq, *vp;
- X{
- X register char *s = vp->val.s + vp->type;
- X register int c;
- X int base, neg = 0;
- X
- X vq->flag |= INTEGER;
- X if ((vp->flag&INTEGER)) {
- X vq->val.i = vp->val.i;
- X return vq;
- X }
- X vq->val.i = 0;
- X base = 10;
- X for (c = *s++; c ; c = *s++)
- X if (c == '-') {
- X neg++;
- X } else if (c == '#') {
- X base = vq->type = vq->val.i;
- X vq->val.i = 0;
- X } else if (letnum(c)) {
- X if ('0' <= c && c <= '9')
- X c -= '0';
- X else if ('a' <= c && c <= 'z') /* fuck EBCDIC */
- X c -= 'a'-10;
- X else if ('A' <= c && c <= 'Z')
- X c -= 'A'-10;
- X vq->val.i = (vq->val.i*base) + c;
- X } else
- X break;
- X if (neg)
- X vq->val.i = -vq->val.i;
- X if (vq->type < 2 || vq->type > 36)
- X vq->type = 0; /* default base (10) */
- X return vq;
- X}
- X
- X/* set variable to integer */
- Xvoid
- Xsetint(vq, n)
- X register struct tbl *vq;
- X long n;
- X{
- X if (!(vq->flag&INTEGER)) {
- X register struct tbl *vp = &vtemp;
- X vp->flag = (ISSET|INTEGER);
- X vp->type = 0;
- X vp->val.i = n;
- X setstr(vq, strval(vp)); /* ? */
- X } else
- X vq->val.i = n;
- X vq->flag |= ISSET;
- X if ((vq->flag&SPECIAL))
- X setspec(vq);
- X}
- X
- X/* set variable from enviroment */
- Ximport(thing)
- X char *thing;
- X{
- X register struct tbl *vp;
- X register char *val;
- X
- X val = strchr(thing, '=');
- X if (val == NULL)
- X return 0;
- X *val = '\0';
- X vp = local(thing);
- X *val++ = '=';
- X vp->flag |= DEFINED|ISSET|EXPORT;
- X vp->val.s = thing;
- X vp->type = val - thing;
- X if ((vp->flag&SPECIAL))
- X setspec(vp);
- X return 1;
- X}
- X
- X/*
- X * make vp->val.s be "name=value" for quick exporting.
- X */
- Xstatic void
- Xexport(vp, val)
- X register struct tbl *vp;
- X char *val;
- X{
- X register char *cp, *xp;
- X char *op = (vp->flag&ALLOC) ? vp->val.s : NULL;
- X
- X xp = (char*)alloc(strlen(vp->name) + strlen(val) + 2, lastarea);
- X vp->flag |= ALLOC;
- X vp->val.s = xp;
- X for (cp = vp->name; (*xp = *cp++) != '\0'; xp++)
- X ;
- X *xp++ = '=';
- X vp->type = xp - vp->val.s; /* offset to value */
- X for (cp = val; (*xp++ = *cp++) != '\0'; )
- X ;
- X if (op != NULL)
- X afree((Void*)op, lastarea);
- X}
- X
- X/*
- X * lookup variable (according to (set&LOCAL)),
- X * set its attributes (INTEGER, RDONLY, EXPORT, TRACE),
- X * and optionally set its value if an assignment.
- X */
- Xstruct tbl *
- Xtypeset(var, set, clr)
- X register char *var;
- X int clr, set;
- X{
- X register struct tbl *vp;
- X register char *val;
- X
- X /* check for valid variable name, search for value */
- X val = var;
- X if (!letter(*val))
- X return NULL;
- X for (val++; *val != '\0'; val++)
- X if (*val == '=')
- X break;
- X else if (letnum(*val))
- X ;
- X else
- X return NULL;
- X if (*val == '=')
- X *val = '\0';
- X else
- X val = NULL;
- X vp = (set&LOCAL) ? local(var) : global(var);
- X set &= ~ LOCAL;
- X if (val != NULL)
- X *val++ = '=';
- X
- X if (!(vp->flag&ISSET))
- X vp->flag = vp->flag & ~clr | set;
- X else
- X if (!(vp->flag&INTEGER) && (set&INTEGER)) {
- X /* string to integer */
- X vtemp.flag = (ISSET);
- X vtemp.type = 0;
- X vtemp.val.s = vp->val.s + vp->type;
- X if ((vp->flag&ALLOC))
- X afree((Void*)vp->val.s, lastarea); /* dangerous, used later */
- X vp->flag &= ~ ALLOC;
- X vp->flag |= INTEGER;
- X vp->type = 0;
- X strint(vp, &vtemp);
- X } else
- X if ((clr&INTEGER) && (vp->flag&INTEGER)) {
- X /* integer to string */
- X vtemp.val.s = strval(vp);
- X vp->flag &= ~ INTEGER;
- X setstr(vp, vtemp.val.s);
- X }
- X
- X vp->flag = vp->flag & ~clr | set;
- X
- X if (val != NULL) {
- X if ((vp->flag&RDONLY))
- X errorf("cannot set readonly %s\n", var);
- X if ((vp->flag&INTEGER))
- X /* setstr should be able to handle this */
- X (void)evaluate(var);
- X else
- X setstr(vp, val);
- X }
- X
- X if ((vp->flag&EXPORT) && !(vp->flag&INTEGER) && vp->type == 0)
- X export(vp, (vp->flag&ISSET) ? vp->val.s : null);
- X
- X return vp;
- X}
- X
- Xvoid
- Xunset(vp)
- X register struct tbl *vp;
- X{
- X if ((vp->flag&ALLOC))
- X afree((Void*)vp->val.s, lastarea);
- X vp->flag &= ~ (ALLOC|ISSET);
- X}
- X
- Xint
- Xisassign(s)
- X register char *s;
- X{
- X if (!letter(*s))
- X return (0);
- X for (s++; *s != '='; s++)
- X if (*s == 0 || !letnum(*s))
- X return (0);
- X return (1);
- X}
- X
- X/*
- X * Make the exported environment from the exported names in the dictionary.
- X */
- Xchar **
- Xmakenv()
- X{
- X struct block *l = e.loc;
- X XPtrV env;
- X register struct tbl *vp, **vpp;
- X register int i;
- X
- X XPinit(env, 64);
- X for (l = e.loc; l != NULL; l = l->next)
- X for (vpp = l->vars.tbls, i = l->vars.size; --i >= 0; )
- X if ((vp = *vpp++) != NULL
- X && (vp->flag&(ISSET|EXPORT)) == (ISSET|EXPORT)) {
- X register struct block *l2;
- X register struct tbl *vp2;
- X unsigned h = hash(vp->name);
- X
- X lastarea = &l->area;
- X
- X /* unexport any redefined instances */
- X for (l2 = l->next; l2 != NULL; l2 = l2->next) {
- X vp2 = tsearch(&l2->vars, vp->name, h);
- X if (vp2 != NULL)
- X vp2->flag &= ~ EXPORT;
- X }
- X if ((vp->flag&INTEGER)) {
- X /* integer to string */
- X char *val;
- X val = strval(vp);
- X vp->flag &= ~ INTEGER;
- X setstr(vp, val);
- X }
- X XPput(env, vp->val.s);
- X }
- X XPput(env, NULL);
- X return (char **) XPclose(env);
- X}
- X
- X/*
- X * handle special variables with side effects - PATH, SECONDS.
- X */
- X
- Xstatic int
- Xspecial(name)
- X register char * name;
- X{
- X if (strcmp("PATH", name) == 0)
- X return V_PATH;
- X if (strcmp("IFS", name) == 0)
- X return V_IFS;
- X if (strcmp("SECONDS", name) == 0)
- X return V_SECONDS;
- X if (strcmp("OPTIND", name) == 0)
- X return V_OPTIND;
- X return V_NONE;
- X}
- X
- Xextern time_t time();
- Xstatic time_t seconds; /* time SECONDS last set */
- X
- Xstatic void
- Xgetspec(vp)
- X register struct tbl *vp;
- X{
- X switch (special(vp->name)) {
- X case V_SECONDS:
- X vp->flag &= ~ SPECIAL;
- X setint(vp, time((time_t *)0) - seconds);
- X vp->flag |= SPECIAL;
- X break;
- X }
- X}
- X
- Xstatic void
- Xsetspec(vp)
- X register struct tbl *vp;
- X{
- X switch (special(vp->name)) {
- X case V_PATH:
- X path = strval(vp);
- X flushcom(1); /* clear tracked aliases */
- X break;
- X case V_IFS:
- X setctypes(strval(vp), C_IFS);
- X break;
- X case V_SECONDS:
- X seconds = time((time_t *)0);
- X break;
- X case V_OPTIND:
- X if (intval(vp) == 1)
- X resetopts();
- X break;
- X }
- X}
- X
- SHAR_EOF
- true || echo 'restore of src/var.c failed'
- fi
- # ============= src/table.c ==============
- if test -f 'src/table.c' -a X"$1" != X"-c"; then
- echo 'x - skipping src/table.c (File already exists)'
- else
- echo 'x - extracting src/table.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'src/table.c' &&
- Xstatic char *RCSid = "$Header: /tmp/egisin/src/RCS/table.c,v 3.1 88/11/03 09:17:53 egisin Exp $";
- X
- X/*
- X * dynamic hashed associative table for commands and variables
- X */
- X
- X#include <stddef.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include "sh.h"
- X#include "table.h"
- X
- X#define INIT_TBLS 8 /* initial table size (power of 2) */
- X
- Xstatic struct tstate {
- X int left;
- X struct tbl **next;
- X} tstate;
- X
- Xstatic void texpand();
- X
- Xunsigned int
- Xhash(n)
- X register char * n;
- X{
- X register unsigned int h = 0;
- X
- X while (*n != '\0')
- X h = 2*h + *n++;
- X return h * 32821; /* scatter bits */
- X}
- X
- X#if 0
- Xphash(s) char *s; {
- X printf("%2d: %s\n", hash(s)%32, s);
- X}
- X#endif
- X
- Xvoid
- Xtinit(tp, ap)
- X register struct table *tp;
- X register Area *ap;
- X{
- X tp->areap = ap;
- X tp->size = tp->free = 0;
- X tp->tbls = NULL;
- X}
- X
- Xstatic void
- Xtexpand(tp, nsize)
- X register struct table *tp;
- X int nsize;
- X{
- X register int i;
- X register struct tbl *tblp, **p;
- X register struct tbl **ntblp, **otblp = tp->tbls;
- X int osize = tp->size;
- X
- X ntblp = alloc(sizeofN(struct tbl *, nsize), tp->areap);
- X for (i = 0; i < nsize; i++)
- X ntblp[i] = NULL;
- X tp->size = nsize;
- X tp->free = 8*nsize/10; /* table can get 80% full */
- X tp->tbls = ntblp;
- X if (otblp == NULL)
- X return;
- X for (i = 0; i < osize; i++)
- X if ((tblp = otblp[i]) != NULL)
- X if ((tblp->flag&DEFINED)) {
- X for (p = &ntblp[hash(tblp->name) & tp->size-1];
- X *p != NULL; p--)
- X if (p == ntblp) /* wrap */
- X p += tp->size;
- X *p = tblp;
- X tp->free--;
- X } else {
- X afree((Void*)tblp, tp->areap);
- X }
- X afree((Void*)otblp, tp->areap);
- X}
- X
- Xstruct tbl *
- Xtsearch(tp, n, h)
- X register struct table *tp; /* table */
- X register char *n; /* name to enter */
- X unsigned int h; /* hash(n) */
- X{
- X register struct tbl **pp, *p;
- X
- X if (tp->size == 0)
- X return NULL;
- X
- X /* search for name in hashed table */
- X for (pp = &tp->tbls[h & tp->size-1]; (p = *pp) != NULL; pp--) {
- X if (*p->name == *n && strcmp(p->name, n) == 0
- X && (p->flag&DEFINED))
- X return p;
- X if (pp == tp->tbls) /* wrap */
- X pp += tp->size;
- X }
- X
- X return NULL;
- X}
- X
- Xstruct tbl *
- Xtenter(tp, n, h)
- X register struct table *tp; /* table */
- X register char *n; /* name to enter */
- X unsigned int h; /* hash(n) */
- X{
- X register struct tbl **pp, *p;
- X register char *cp;
- X
- X if (tp->size == 0)
- X texpand(tp, INIT_TBLS);
- X Search:
- X /* search for name in hashed table */
- X for (pp = &tp->tbls[h & tp->size-1]; (p = *pp) != NULL; pp--) {
- X if (*p->name == *n && strcmp(p->name, n) == 0)
- X return p; /* found */
- X if (pp == tp->tbls) /* wrap */
- X pp += tp->size;
- X }
- X
- X if (tp->free <= 0) { /* too full */
- X texpand(tp, 2*tp->size);
- X goto Search;
- X }
- X
- X /* create new tbl entry */
- X for (cp = n; *cp != '\0'; cp++)
- X ;
- X p = (struct tbl *) alloc(offsetof(struct tbl, name[(cp-n)+1]), tp->areap);
- X p->flag = 0;
- X p->type = 0;
- X for (cp = p->name; *n != '\0';)
- X *cp++ = *n++;
- X *cp = '\0';
- X
- X /* enter in tp->tbls */
- X tp->free--;
- X *pp = p;
- X return p;
- X}
- X
- Xvoid
- Xtdelete(p)
- X register struct tbl *p;
- X{
- X p->flag = 0;
- X}
- X
- Xvoid
- Xtwalk(tp)
- X register struct table *tp;
- X{
- X tstate.left = tp->size;
- X tstate.next = tp->tbls;
- X}
- X
- Xstruct tbl *
- Xtnext()
- X{
- X while (--tstate.left >= 0) {
- X struct tbl *p = *tstate.next++;
- X if (p != NULL && (p->flag&DEFINED))
- X return p;
- X }
- X return NULL;
- X}
- X
- Xstatic int
- Xtnamecmp(p1, p2)
- X Void *p1, *p2;
- X{
- X return strcmp(((struct tbl *)p1)->name, ((struct tbl *)p2)->name);
- X}
- X
- Xstruct tbl **
- Xtsort(tp)
- X register struct table *tp;
- X{
- X register int i;
- X register struct tbl **p, **sp, **dp;
- X
- X p = (struct tbl **)alloc(sizeofN(struct tbl *, tp->size+1), ATEMP);
- X sp = tp->tbls; /* source */
- X dp = p; /* dest */
- X for (i = 0; i < tp->size; i++)
- X if ((*dp = *sp++) != NULL && ((*dp)->flag&DEFINED))
- X dp++;
- X i = dp - p;
- X qsortp((Void**)p, (size_t)i, tnamecmp);
- X p[i] = NULL;
- X return p;
- X}
- X
- SHAR_EOF
- true || echo 'restore of src/table.c failed'
- fi
- true || echo 'restore of src/eval.c failed'
- echo End of part 5, continue with part 6
- exit 0
-