home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-02-21 | 79.2 KB | 4,089 lines |
-
- #!/bin/sh
- # this is part 3 of a multipart archive
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file shell/sh2.c continued
- #
- CurArch=3
- if test ! -r s2_seq_.tmp
- then echo "Please unpack part 1 first!"
- exit 1; fi
- ( read Scheck
- if test "$Scheck" != $CurArch
- then echo "Please unpack part $Scheck next!"
- exit 1;
- else exit 0; fi
- ) < s2_seq_.tmp || exit 1
- echo "x - Continuing file shell/sh2.c"
- sed 's/^X//' << 'SHAR_EOF' >> shell/sh2.c
- X {
- X if (iolist == (Word_B *)NULL)
- X return (C_Op *)NULL;
- X
- X (t = (C_Op *)tree (sizeof (C_Op)))->type = TCOM;
- X }
- X
- X break;
- X
- X case '(':
- X t = nested (TPAREN, ')');
- X break;
- X
- X case '{':
- X t = nested (TBRACE, '}');
- X break;
- X
- X case FOR:
- X (t = (C_Op *)tree (sizeof (C_Op)))->type = TFOR;
- X musthave (WORD, 0);
- X startl = TRUE;
- X t->str = yylval.cp;
- X multiline++;
- X t->words = wordlist ();
- X
- X if (((c = yylex (0)) != NL) && (c != ';'))
- X yyerror (syntax_err);
- X
- X t->left = dogroup (0);
- X multiline--;
- X break;
- X
- X case WHILE:
- X case UNTIL:
- X multiline++;
- X t = (C_Op *)tree (sizeof (C_Op));
- X t->type = (c == WHILE) ? TWHILE : TUNTIL;
- X t->left = c_list (FALSE);
- X t->right = dogroup (1);
- X t->words = NULL;
- X multiline--;
- X break;
- X
- X case CASE:
- X (t = (C_Op *)tree (sizeof (C_Op)))->type = TCASE;
- X musthave (WORD, 0);
- X t->str = yylval.cp;
- X startl = TRUE;
- X multiline++;
- X musthave (IN, CONTIN);
- X startl = TRUE;
- X t->left = caselist();
- X musthave (ESAC, 0);
- X multiline--;
- X break;
- X
- X case IF:
- X multiline++;
- X (t = (C_Op *)tree (sizeof (C_Op)))->type = TIF;
- X t->left = c_list (FALSE);
- X t->right = thenpart ();
- X musthave (FI, 0);
- X multiline--;
- X break;
- X }
- X
- X while (synio (0))
- X ;
- X
- X t = namelist (t);
- X iolist = iosave;
- X return t;
- X}
- X
- Xstatic C_Op *dogroup (onlydone)
- Xint onlydone;
- X{
- X register int c;
- X register C_Op *list;
- X
- X if (((c = yylex (CONTIN)) == DONE) && onlydone)
- X return (C_Op *)NULL;
- X
- X if (c != DO)
- X yyerror (syntax_err);
- X
- X list = c_list (FALSE);
- X musthave (DONE, 0);
- X return list;
- X}
- X
- Xstatic C_Op *thenpart ()
- X{
- X register int c;
- X register C_Op *t;
- X
- X if ((c = yylex (0)) != THEN)
- X {
- X peeksym = c;
- X return (C_Op *)NULL;
- X }
- X
- X (t = (C_Op *)tree (sizeof (C_Op)))->type = 0;
- X
- X if ((t->left = c_list (FALSE)) == (C_Op *)NULL)
- X yyerror (syntax_err);
- X
- X t->right = elsepart ();
- X return t;
- X}
- X
- Xstatic C_Op *elsepart ()
- X{
- X register int c;
- X register C_Op *t;
- X
- X switch (c = yylex (0))
- X {
- X case ELSE:
- X if ((t = c_list (FALSE)) == (C_Op *)NULL)
- X yyerror (syntax_err);
- X
- X return t;
- X
- X case ELIF:
- X (t = (C_Op *)tree (sizeof (C_Op)))->type = TELIF;
- X t->left = c_list (FALSE);
- X t->right = thenpart ();
- X return t;
- X
- X default:
- X peeksym = c;
- X return (C_Op *)NULL;
- X }
- X}
- X
- Xstatic C_Op *caselist()
- X{
- X register C_Op *t = (C_Op *)NULL;
- X
- X while ((peeksym = yylex (CONTIN)) != ESAC)
- X t = list (t, casepart ());
- X
- X return t;
- X}
- X
- Xstatic C_Op *casepart ()
- X{
- X register C_Op *t = (C_Op *)tree (sizeof (C_Op));
- X
- X t->type = TPAT;
- X t->words = pattern ();
- X musthave (')', 0);
- X t->left = c_list (FALSE);
- X
- X if ((peeksym = yylex (CONTIN)) != ESAC)
- X musthave (BREAK, CONTIN);
- X
- X return t;
- X}
- X
- Xstatic char **pattern()
- X{
- X register int c, cf;
- X
- X cf = CONTIN;
- X
- X do
- X {
- X musthave (WORD, cf);
- X word (yylval.cp);
- X cf = 0;
- X } while ((c = yylex(0)) == '|');
- X
- X peeksym = c;
- X word (NOWORD);
- X return copyw();
- X}
- X
- Xstatic char **wordlist()
- X{
- X register int c;
- X
- X if ((c = yylex(0)) != IN)
- X {
- X peeksym = c;
- X return (char **)NULL;
- X }
- X
- X startl = FALSE;
- X while ((c = yylex (0)) == WORD)
- X word (yylval.cp);
- X
- X word (NOWORD);
- X peeksym = c;
- X
- X return copyw();
- X}
- X
- X/*
- X * supporting functions
- X */
- X
- Xstatic C_Op *list (t1, t2)
- Xregister C_Op *t1, *t2;
- X{
- X if (t1 == (C_Op *)NULL)
- X return t2;
- X
- X if (t2 == (C_Op *)NULL)
- X return t1;
- X
- X return block (TLIST, t1, t2, NOWORDS);
- X}
- X
- Xstatic C_Op *block (type, t1, t2, wp)
- XC_Op *t1, *t2;
- Xchar **wp;
- X{
- X register C_Op *t = (C_Op *)tree (sizeof (C_Op));
- X
- X t->type = type;
- X t->left = t1;
- X t->right = t2;
- X t->words = wp;
- X return t;
- X}
- X
- Xstatic struct res {
- X char *r_name;
- X int r_val;
- X} restab[] = {
- X { "for", FOR}, {"case", CASE},
- X {"esac", ESAC}, {"while", WHILE},
- X {"do", DO}, {"done", DONE},
- X {"if", IF}, {"in", IN},
- X {"then", THEN}, {"else", ELSE},
- X {"elif", ELIF}, {"until", UNTIL},
- X {"fi", FI},
- X
- X {";;", BREAK}, {"||", LOGOR},
- X {"&&", LOGAND}, {"{", '{'},
- X {"}", '}'},
- X
- X {(char *)NULL, 0}
- X};
- X
- Xstatic int rlookup (n)
- Xregister char *n;
- X{
- X register struct res *rp = restab;
- X
- X while ((rp->r_name != (char *)NULL) && strcmp (rp->r_name, n))
- X rp++;
- X
- X return rp->r_val;
- X}
- X
- Xstatic C_Op *namelist(t)
- Xregister C_Op *t;
- X{
- X if (iolist)
- X {
- X iolist = addword ((char *)NULL, iolist);
- X t->ioact = copyio ();
- X }
- X
- X else
- X t->ioact = (IO_Actions **)NULL;
- X
- X if ((t->type != TCOM) && (t->type != TFUNC))
- X {
- X if ((t->type != TPAREN) && (t->ioact != (IO_Actions **)NULL))
- X {
- X t = block (TPAREN, t, NOBLOCK, NOWORDS);
- X t->ioact = t->left->ioact;
- X t->left->ioact = (IO_Actions **)NULL;
- X }
- X }
- X
- X else
- X {
- X word (NOWORD);
- X t->words = copyw();
- X }
- X
- X return t;
- X}
- X
- Xstatic char **copyw ()
- X{
- X register char **wd = getwords (wdlist);
- X
- X wdlist = (Word_B *)NULL;
- X return wd;
- X}
- X
- Xstatic void word (cp)
- Xchar *cp;
- X{
- X wdlist = addword (cp, wdlist);
- X}
- X
- Xstatic IO_Actions **copyio ()
- X{
- X IO_Actions **iop = (IO_Actions **)getwords (iolist);
- X
- X iolist = (Word_B *)NULL;
- X return iop;
- X}
- X
- Xstatic IO_Actions *io (u, f, cp)
- Xint f, u;
- Xchar *cp;
- X{
- X register IO_Actions *iop = (IO_Actions *)tree (sizeof (IO_Actions));
- X
- X iop->io_unit = u;
- X iop->io_flag = f;
- X iop->io_name = cp;
- X iolist = addword ((char *)iop, iolist);
- X return iop;
- X}
- X
- Xstatic void yyerror (s)
- Xchar *s;
- X{
- X yynerrs++;
- X
- X if (talking && e.iop <= iostack)
- X {
- X multiline = 0;
- X
- X while ((eofc () == 0) && (yylex (0) != NL))
- X ;
- X }
- X
- X print_error (s);
- X fail ();
- X}
- X
- Xstatic int yylex (cf)
- Xint cf;
- X{
- X register int c, c1;
- X bool atstart;
- X
- X if ((c = peeksym) > 0)
- X {
- X peeksym = 0;
- X
- X if (c == NL)
- X startl = TRUE;
- X
- X return c;
- X }
- X
- X e.linep = e.cline;
- X atstart = startl;
- X startl = FALSE;
- X yylval.i = 0;
- X
- Xloop:
- X while ((c = Getc (0)) == SP || c == '\t')
- X ;
- X
- X switch (c)
- X {
- X default:
- X if (isdigit (c))
- X {
- X unget (c1 = Getc(0));
- X
- X if ((c1 == '<') || (c1 == '>'))
- X {
- X iounit = c - '0';
- X goto loop;
- X }
- X
- X *e.linep++ = (char)c;
- X c = c1;
- X }
- X
- X break;
- X
- X case '#':
- X while ((c = Getc(0)) != 0 && (c != NL))
- X ;
- X
- X unget(c);
- X goto loop;
- X
- X case 0:
- X return c;
- X
- X case '$':
- X *e.linep++ = (char)c;
- X
- X if ((c = Getc(0)) == '{')
- X {
- X if ((c = collect (c, '}')) != '\0')
- X return (c);
- X
- X goto pack;
- X }
- X
- X break;
- X
- X case '`':
- X case '\'':
- X case '"':
- X if ((c = collect (c, c)) != '\0')
- X return c;
- X
- X goto pack;
- X
- X case '|':
- X case '&':
- X case ';':
- X if ((c1 = dual (c)) != '\0')
- X {
- X startl = TRUE;
- X return c1;
- X }
- X
- X case '(':
- X case ')':
- X startl = TRUE;
- X return c;
- X
- X case '^':
- X startl = TRUE;
- X return '|';
- X
- X case '>':
- X case '<':
- X diag (c);
- X return c;
- X
- X case NL:
- X gethere ();
- X startl = TRUE;
- X
- X if (multiline || (cf & CONTIN))
- X {
- X if (talking && e.iop <= iostack)
- X {
- X Add_History (FALSE);
- X put_prompt (ps2->value);
- X }
- X
- X if (cf & CONTIN)
- X goto loop;
- X }
- X
- X return(c);
- X }
- X
- X unget (c);
- X
- Xpack:
- X while (((c = Getc (0)) != 0) && (!any ((char)c, "`$ '\"\t;&<>()|^\n")))
- X {
- X if (e.linep >= e.eline)
- X print_error ("sh: word too long\n");
- X
- X else
- X *e.linep++ = (char)c;
- X }
- X
- X unget (c);
- X
- X if (any ((char)c, spcl2))
- X goto loop;
- X
- X *e.linep++ = '\0';
- X
- X if (atstart && (c = rlookup (e.cline)) != 0)
- X {
- X startl = TRUE;
- X return c;
- X }
- X
- X yylval.cp = strsave (e.cline, areanum);
- X return WORD;
- X}
- X
- Xstatic int collect (c, c1)
- Xregister int c, c1;
- X{
- X char *s = "x\n";
- X
- X *e.linep++ = (char)c;
- X
- X while ((c = Getc (c1)) != c1)
- X {
- X if (c == 0)
- X {
- X unget (c);
- X *s = (char)c1;
- X S_puts ("sh: no closing ");
- X yyerror (s);
- X return YYERRCODE;
- X }
- X
- X if (talking && (c == NL) && (e.iop <= iostack))
- X {
- X Add_History (FALSE);
- X put_prompt (ps2->value);
- X }
- X
- X *e.linep++ = (char)c;
- X }
- X
- X *e.linep++ = (char)c;
- X return 0;
- X}
- X
- X/* Check for &&, || and ;; */
- X
- Xstatic int dual (c)
- Xregister int c;
- X{
- X char s[3];
- X register char *cp = s;
- X
- X/* Get the next character and set up double string. Look up in valid
- X * operators. If invalid, unget character
- X */
- X
- X *cp++ = (char)c;
- X *cp++ = (char)Getc (0);
- X *cp = 0;
- X
- X if ((c = rlookup (s)) == 0)
- X unget (*--cp);
- X
- X return c;
- X}
- X
- X/* Process I/O re-direction */
- X
- Xstatic void diag (ec)
- Xregister int ec;
- X{
- X register int c;
- X
- X if (((c = Getc (0)) == '>') || (c == '<'))
- X {
- X if (c != ec)
- X yyerror (syntax_err);
- X
- X yylval.i = (ec == '>') ? IOWRITE | IOCAT : IOHERE;
- X c = Getc(0);
- X }
- X
- X else
- X yylval.i = (ec == '>') ? IOWRITE : IOREAD;
- X
- X if ((c != '&') || (yylval.i == IOHERE))
- X unget (c);
- X
- X else
- X yylval.i |= IODUP;
- X}
- X
- X/* Get a new tree leaf structure */
- X
- Xstatic char *tree (size)
- Xunsigned int size;
- X{
- X register char *t;
- X
- X if ((t = getcell (size)) == (char *)NULL)
- X {
- X S_puts ("sh: command line too complicated\n");
- X fail ();
- X }
- X
- X return t;
- X}
- SHAR_EOF
- echo "File shell/sh2.c is complete"
- chmod 0644 shell/sh2.c || echo "restore of shell/sh2.c fails"
- set `wc -c shell/sh2.c`;Sum=$1
- if test "$Sum" != "15090"
- then echo original size 15090, current size $Sum;fi
- echo "x - extracting shell/sh3.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > shell/sh3.c &&
- X/* MS-DOS SHELL - Parse Tree Executor
- X *
- X * MS-DOS SHELL - Copyright (c) 1990 Data Logic Limited and Charles Forsyth
- X *
- X * This code is based on (in part) the shell program written by Charles
- X * Forsyth and is subject to the following copyright restrictions:
- X *
- X * 1. Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice is duplicated in the
- X * source form and the copyright notice in file sh6.c is displayed
- X * on entry to the program.
- X *
- X * 2. The sources (or parts thereof) or objects generated from the sources
- X * (or parts of sources) cannot be sold under any circumstances.
- X *
- X * $Header: sh3.c 1.1 90/01/25 13:41:24 MS_user Exp $
- X *
- X * $Log: sh3.c $
- X * Revision 1.1 90/01/25 13:41:24 MS_user
- X * Initial revision
- X *
- X */
- X
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <stdio.h>
- X#include <process.h>
- X#include <dos.h>
- X#include <signal.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include <ctype.h>
- X#include <string.h>
- X#include <unistd.h>
- X#include <stdlib.h>
- X#include <fcntl.h>
- X#include <limits.h>
- X
- X#include "sh.h"
- X
- X/* static Function and string declarations */
- X
- Xstatic int forkexec (C_Op *, int, int, int, char **);
- Xstatic bool iosetup (IO_Actions *, int, int);
- Xstatic C_Op **find1case (C_Op *, char *);
- Xstatic C_Op *findcase (C_Op *, char *);
- Xstatic void echo (char **);
- Xstatic void setsig (int, int (*)());
- Xstatic int rexecve (char *, char **, char **, bool);
- Xstatic int Execute_program (char *, char **, char **, bool);
- Xstatic int S_spawnve (char *, char **, char **);
- Xstatic void get_sys_info (void);
- Xstatic void EMS_error (char *, int);
- Xstatic int EMS_Close (void);
- Xstatic int build_command_line (char *, char **, char **);
- Xstatic void Clear_Extended_File (void);
- Xstatic int setstatus (int);
- X
- Xstatic char *AE2big = "arg/env list too big";
- Xstatic char *EMS_emsg = "Warning: EMS Error (%x)\n";
- X /* Extended Command line processing file name */
- Xstatic char *Extend_file = (char *)NULL;
- Xstatic unsigned int SW_EMsize; /* Number of extend memory blks */
- X
- X/*
- X * execute tree recursively
- X */
- X
- Xint execute (t, pin, pout, act)
- Xregister C_Op *t;
- Xint pin;
- Xint pout;
- Xint act;
- X{
- X register C_Op *t1;
- X int i, localpipe;
- X char *cp, **wp;
- X char **Local_Tword;
- X Var_List *vp;
- X Break_C bc;
- X Break_C *S_RList; /* Save link pointers */
- X Break_C *S_BList;
- X Break_C *S_SList;
- X int Local_depth; /* Save local values */
- X int Local_areanum;
- X int rv = 0;
- X
- X/* End of tree ? */
- X
- X if (t == (C_Op *)NULL)
- X return 0;
- X
- X/* Save original and Increment execute function recursive level */
- X
- X Local_depth = Execute_stack_depth++;
- X
- X/* Save original and increment area number */
- X
- X Local_areanum = areanum++;
- X
- X/* Save the exit points from SubShells, functions and for/whiles */
- X
- X S_RList = Return_List;
- X S_BList = Break_List;
- X S_SList = SShell_List;
- X
- X/* Expand any arguments */
- X
- X wp = (Local_Tword = t->words) != (char **)NULL
- X ? eval (Local_Tword, (t->type == TCOM) ? DOALL : DOALL & ~DOKEY)
- X : (char **)NULL;
- X
- X/* Switch on tree node type */
- X
- X switch (t->type)
- X {
- X case TFUNC: /* name () { list; } */
- X Save_Function (t, FALSE);
- X break;
- X
- X/* In the case of a () command string, we need to save and restore the
- X * current environment, directory and traps (can't think of anything else).
- X * For any other, we just restore the current directory. Also, we don't
- X * want changes in the Variable list header saved for SubShells, because
- X * we are effectively back at execute depth zero.
- X */
- X case TPAREN: /* () */
- X if ((rv = Create_NG_VL ()) == -1)
- X break;
- X
- X if (setjmp (bc.brkpt) == 0)
- X {
- X Return_List = (Break_C *)NULL;
- X Break_List = (Break_C *)NULL;
- X bc.nextlev = SShell_List;
- X SShell_List = &bc;
- X rv = forkexec (t, pin, pout, act, wp);
- X }
- X
- X/* Restore the original environment */
- X
- X Return_List = S_RList;
- X Break_List = S_BList;
- X SShell_List = S_SList;
- X Restore_Environment (rv, Local_depth);
- X break;
- X
- X/* After a normal command, we need to restore the original directory. Note
- X * that a cd will have updated the variable $~, so no problem
- X */
- X
- X case TCOM: /* A command process */
- X rv = forkexec (t, pin, pout, act, wp);
- X Restore_Dir ();
- X break;
- X
- X case TPIPE: /* Pipe processing */
- X if ((rv = openpipe ()) < 0)
- X break;
- X
- X/* Create pipe, execute command, reset pipe, execute the other side, close
- X * the pipe and fini
- X */
- X
- X localpipe = remap (rv);
- X execute (t->left, pin, localpipe, 0);
- X lseek (localpipe, 0L, SEEK_SET);
- X rv = execute (t->right, localpipe, pout, 0);
- X closepipe (localpipe);
- X break;
- X
- X case TLIST: /* Entries in a for statement */
- X execute (t->left, pin, pout, 0);
- X rv = execute (t->right, pin, pout, 0);
- X break;
- X
- X case TASYNC: /* Async - not supported */
- X rv = -1;
- X S_puts ("sh: Async commands not supported\n");
- X setstatus (rv);
- X break;
- X
- X case TOR: /* || and && */
- X case TAND:
- X rv = execute (t->left, pin, pout, 0);
- X
- X if (((t1 = t->right) != (C_Op *)NULL) &&
- X ((rv == 0) == (t->type == TAND)))
- X rv = execute (t1, pin, pout, 0);
- X
- X break;
- X
- X case TFOR: /* First part of a for statement*/
- X
- X/* for x do...done - use the parameter values. Need to know how many as
- X * it is not a NULL terminated array
- X */
- X
- X if (wp == (char **)NULL)
- X {
- X wp = dolv + 1;
- X
- X if ((i = dolc) < 0)
- X i = 0;
- X }
- X
- X/* for x in y do...done - find the start of the variables and use them all */
- X
- X else
- X {
- X i = -1;
- X while (*wp++ != (char *)NULL)
- X ;
- X }
- X
- X/* Create the loop variable. */
- X
- X vp = lookup (t->str, TRUE);
- X
- X/* Set up a long jump return point before executing the for function so that
- X * the continue statement is executed, ie we reprocessor the for condition.
- X */
- X
- X while (rv = setjmp (bc.brkpt))
- X {
- X
- X/* Restore the current stack level and clear out any I/O */
- X
- X Restore_Environment (0, Local_depth + 1);
- X Return_List = S_RList;
- X SShell_List = S_SList;
- X
- X/* If this is a break - clear the variable and terminate the while loop and
- X * switch statement
- X */
- X
- X if (rv == BC_BREAK)
- X break;
- X }
- X
- X if (rv == BC_BREAK)
- X break;
- X
- X/* Process the next entry - Add to the break/continue chain */
- X
- X bc.nextlev = Break_List;
- X Break_List = &bc;
- X
- X/* Execute the command tree */
- X
- X for (t1 = t->left; i-- && *wp != NULL;)
- X {
- X setval (vp, *wp++);
- X rv = execute (t1, pin, pout, 0);
- X }
- X
- X/* Remove this tree from the break list */
- X
- X Break_List = S_BList;
- X break;
- X
- X/* While and Until function. Similar to the For function. Set up a
- X * long jump return point before executing the while function so that
- X * the continue statement is executed OK.
- X */
- X
- X case TWHILE: /* WHILE and UNTIL functions */
- X case TUNTIL:
- X while (rv = setjmp (bc.brkpt))
- X {
- X
- X/* Restore the current stack level and clear out any I/O */
- X
- X Restore_Environment (0, Local_depth + 1);
- X Return_List = S_RList;
- X SShell_List = S_SList;
- X
- X/* If this is a break, terminate the while and switch statements */
- X
- X if (rv == BC_BREAK)
- X break;
- X }
- X
- X if (rv == BC_BREAK)
- X break;
- X
- X/* Set up links */
- X
- X bc.nextlev = Break_List;
- X Break_List = &bc;
- X t1 = t->left;
- X
- X while ((execute(t1, pin, pout, 0) == 0) == (t->type == TWHILE))
- X rv = execute (t->right, pin, pout, 0);
- X
- X Break_List = S_BList;
- X break;
- X
- X case TIF: /* IF and ELSE IF functions */
- X case TELIF:
- X rv = !execute (t->left, pin, pout, 0)
- X ? execute (t->right->left, pin, pout, 0)
- X : execute (t->right->right, pin, pout, 0);
- X break;
- X
- X case TCASE: /* CASE function */
- X if ((cp = evalstr (t->str, DOSUB | DOTRIM)) == (char *)NULL)
- X cp = null;
- X
- X if ((t1 = findcase (t->left, cp)) != (C_Op *)NULL)
- X rv = execute (t1, pin, pout, 0);
- X
- X break;
- X
- X case TBRACE: /* {} statement */
- X if ((rv >= 0) && ((t1 = t->left) != (C_Op *)NULL))
- X rv = execute (t1, pin, pout, 0);
- X
- X break;
- X }
- X
- X/* Processing Completed - Restore environment */
- X
- X t->words = Local_Tword;
- X Execute_stack_depth = Local_depth;
- X
- X/* Remove unwanted malloced space */
- X
- X freehere (areanum);
- X freearea (areanum);
- X
- X areanum = Local_areanum;
- X
- X/* Check for interrupts */
- X
- X if (talking && SW_intr)
- X {
- X closeall ();
- X fail ();
- X }
- X
- X/* Check for traps */
- X
- X if ((i = trapset) != 0)
- X {
- X trapset = 0;
- X runtrap (i);
- X }
- X
- X return rv;
- X}
- X
- X/*
- X * Restore the original directory
- X */
- X
- Xvoid Restore_Dir ()
- X{
- X unsigned int dummy;
- X
- X _dos_setdrive (tolower(*C_dir->value) - 'a' + 1, &dummy);
- X
- X if (chdir (&C_dir->value[2]) != 0)
- X {
- X S_puts ("Warning: current directory reset to /\n");
- X chdir ("/");
- X Getcwd ();
- X }
- X}
- X
- X/*
- X * Ok - execute the program, resetting any I/O required
- X */
- X
- Xstatic int forkexec (t, pin, pout, act, wp)
- Xregister C_Op *t;
- Xint pin;
- Xint pout;
- Xint act;
- Xchar **wp;
- X{
- X int rv = -1;
- X int (*shcom)(C_Op *) = (int (*)())NULL;
- X char *cp;
- X IO_Actions **iopp;
- X int resetsig = 0;
- X char **owp = wp;
- X bool spawn = FALSE;
- X Fun_Ops *fop;
- X
- X if (t->type == TCOM)
- X {
- X while ((cp = *wp++) != (char *)NULL)
- X ;
- X
- X cp = *wp;
- X
- X/* strip all initial assignments not correct wrt PATH=yyy command etc */
- X
- X if (FL_TEST ('x'))
- X echo (cp != (char *)NULL ? wp : owp);
- X
- X/* Is it only an assignement? */
- X
- X if ((cp == (char *)NULL) && (t->ioact == (IO_Actions **)NULL))
- X {
- X while (((cp = *owp++) != (char *)NULL) && assign (cp, COPYV))
- X ;
- X
- X return setstatus (0);
- X }
- X
- X/* Check for built in commands */
- X
- X else if (cp != (char *)NULL)
- X shcom = inbuilt (cp);
- X }
- X
- X/* Unix fork simulation? */
- X
- X t->words = wp;
- X if (shcom == NULL && (act & FEXEC) == 0)
- X {
- X spawn = TRUE;
- X
- X if (talking)
- X {
- X#ifdef SIGQUIT
- X signal (SIGQUIT, SIG_IGN);
- X#endif
- X signal (SIGINT, SIG_IGN);
- X resetsig = 1;
- X }
- X }
- X
- X/* Set any variables */
- X
- X while (((cp = *owp++) != (char *)NULL) && assign (cp, COPYV))
- X {
- X if (shcom == NULL)
- X s_vstatus (lookup (cp, TRUE), EXPORT);
- X }
- X
- X/* We cannot close the pipe, because once the exec/spawn has taken place
- X * the processing of the pipe is not yet complete.
- X */
- X
- X if (pin != NOPIPE)
- X {
- X S_dup2 (pin, STDIN_FILENO);
- X lseek (STDIN_FILENO, 0L, SEEK_SET);
- X }
- X
- X if (pout != NOPIPE)
- X {
- X S_dup2 (pout, STDOUT_FILENO);
- X lseek (STDOUT_FILENO, 0L, SEEK_END);
- X }
- X
- X/* Set up any other IO required */
- X
- X if ((iopp = t->ioact) != (IO_Actions **)NULL)
- X {
- X while (*iopp != (IO_Actions *)NULL)
- X {
- X if (iosetup (*iopp++, pin, pout))
- X return rv;
- X }
- X }
- X
- X if (shcom)
- X return restore_std (setstatus ((*shcom)(t)));
- X
- X/* All fids above 10 are autoclosed in the exec file because we have used
- X * the O_NOINHERIT flag. Note I patched open.obj to pass this flag to the
- X * open function.
- X */
- X
- X if (resetsig)
- X {
- X#ifdef SIGQUIT
- X signal (SIGQUIT, SIG_IGN);
- X#endif
- X signal (SIGINT, onintr);
- X }
- X
- X if (t->type == TPAREN)
- X return restore_std (execute (t->left, NOPIPE, NOPIPE, FEXEC));
- X
- X/* Are we just changing the I/O re-direction for the shell ? */
- X
- X if (wp[0] == NULL)
- X {
- X if (spawn)
- X restore_std (0);
- X
- X return 0;
- X }
- X
- X/* No - Check for a function the program. At this point, we need to put
- X * in some processing for return.
- X */
- X
- X if ((fop = Fun_Search (wp[0])) != (Fun_Ops *)NULL)
- X {
- X char **s_dolv = dolv;
- X int s_dolc = dolc;
- X Break_C *s_RList = Return_List;
- X Break_C *s_BList = Break_List;
- X Break_C *s_SList = SShell_List;
- X int LS_depth = Execute_stack_depth;
- X Break_C bc;
- X
- X/* Set up $0..$n for the function */
- X
- X dolv = wp;
- X for (dolc = 0; dolv[dolc] != (char *)NULL; ++dolc);
- X setval (lookup ("#", TRUE), putn (dolc));
- X
- X if (setjmp (bc.brkpt) == 0)
- X {
- X Break_List = (Break_C *)NULL;
- X bc.nextlev = Return_List;
- X Return_List = &bc;
- X rv = execute (fop->tree->left, NOPIPE, NOPIPE, FEXEC);
- X }
- X
- X/* A return has been executed - Unlike, while and for, we just need to
- X * restore the local execute stack level and the return will restore
- X * the correct I/O.
- X */
- X
- X else
- X rv = getn (lookup ("?", FALSE)->value);
- X
- X/* Restore the old $0, and previous return address */
- X
- X Break_List = s_BList;
- X Return_List = s_RList;
- X SShell_List = s_SList;
- X dolv = s_dolv;
- X dolc = s_dolc;
- X Restore_Environment (rv, LS_depth);
- X setval (lookup ("#", TRUE), putn (dolc));
- X return rv;
- X }
- X
- X/* Ok - execute the program */
- X
- X return restore_std (rexecve (wp[0], wp, makenv (), spawn));
- X}
- X
- X/*
- X * Restore Local Environment
- X */
- X
- Xvoid Restore_Environment (retval, stack)
- Xint retval;
- Xint stack;
- X{
- X Execute_stack_depth = stack;
- X Delete_G_VL ();
- X Restore_Dir ();
- X restore_std (setstatus (retval));
- X}
- X
- X/*
- X * Set up I/O redirection. 0< 1> are ignored as required within pipelines.
- X */
- X
- Xstatic bool iosetup (iop, pipein, pipeout)
- Xregister IO_Actions *iop;
- Xint pipein;
- Xint pipeout;
- X{
- X register int u;
- X char *cp, *msg;
- X
- X if (iop->io_unit == IODEFAULT) /* take default */
- X iop->io_unit = (iop->io_flag & (IOREAD | IOHERE)) ? STDIN_FILENO
- X : STDOUT_FILENO;
- X
- X/* Check for pipes */
- X
- X if ((pipein != NOPIPE) && (iop->io_unit == STDIN_FILENO))
- X return FALSE;
- X
- X if ((pipeout != NOPIPE) && (iop->io_unit == STDOUT_FILENO))
- X return FALSE;
- X
- X msg = (iop->io_flag & (IOREAD | IOHERE)) ? "open" : "create";
- X
- X if ((iop->io_flag & IOHERE) == 0)
- X {
- X if ((cp = evalstr (iop->io_name, DOSUB | DOTRIM)) == (char *)NULL)
- X return TRUE;
- X }
- X
- X if (iop->io_flag & IODUP)
- X {
- X if ((cp[1]) || !isdigit (*cp) && *cp != '-')
- X {
- X print_error ("%s: illegal >& argument\n", cp);
- X return TRUE;
- X }
- X
- X if (*cp == '-')
- X iop->io_flag = IOCLOSE;
- X
- X iop->io_flag &= ~(IOREAD | IOWRITE);
- X }
- X
- X/* Open the file in the appropriate mode */
- X
- X switch (iop->io_flag)
- X {
- X case IOREAD: /* < */
- X u = S_open (FALSE, cp, O_RDONLY);
- X break;
- X
- X case IOHERE: /* << */
- X case IOHERE | IOXHERE:
- X u = herein (iop->io_name, iop->io_flag & IOXHERE);
- X cp = "here file";
- X break;
- X
- X case IOWRITE | IOCAT: /* >> */
- X if (check_rsh (cp))
- X return TRUE;
- X
- X if ((u = S_open (FALSE, cp, O_WRONLY | O_TEXT)) >= 0)
- X {
- X lseek (u, 0L, SEEK_END);
- X break;
- X }
- X
- X case IOWRITE: /* > */
- X if (check_rsh (cp))
- X return TRUE;
- X
- X u = S_open (FALSE, cp, O_CMASK, 0666);
- X break;
- X
- X case IODUP: /* >& */
- X if (check_rsh (cp))
- X return TRUE;
- X
- X u = S_dup2 (*cp - '0', iop->io_unit);
- X break;
- X
- X case IOCLOSE: /* >- */
- X if ((iop->io_unit >= STDIN_FILENO) &&
- X (iop->io_unit <= STDERR_FILENO))
- X S_dup2 (-1, iop->io_unit);
- X
- X S_close (iop->io_unit, TRUE);
- X return FALSE;
- X }
- X
- X if (u < 0)
- X {
- X print_warn ("%s: cannot %s\n", cp, msg);
- X return TRUE;
- X }
- X
- X else if (u != iop->io_unit)
- X {
- X S_dup2 (u, iop->io_unit);
- X S_close (u, TRUE);
- X }
- X
- X return FALSE;
- X}
- X
- X/*
- X * -x flag - echo command to be executed
- X */
- X
- Xstatic void echo (wp)
- Xregister char **wp;
- X{
- X register int i;
- X
- X S_putc ('+');
- X
- X for (i = 0; wp[i] != (char *)NULL; i++)
- X {
- X S_putc (SP);
- X S_puts (wp[i]);
- X }
- X
- X S_putc (NL);
- X}
- X
- Xstatic C_Op **find1case (t, w)
- XC_Op *t;
- Xchar *w;
- X{
- X register C_Op *t1;
- X C_Op **tp;
- X register char **wp, *cp;
- X
- X if (t == (C_Op *)NULL)
- X return (C_Op **)NULL;
- X
- X if (t->type == TLIST)
- X {
- X if ((tp = find1case (t->left, w)) != (C_Op *)NULL)
- X return tp;
- X
- X t1 = t->right; /* TPAT */
- X }
- X
- X else
- X t1 = t;
- X
- X for (wp = t1->words; *wp != (char *)NULL;)
- X {
- X if ((cp = evalstr (*(wp++), DOSUB)) && gmatch (w, cp, FALSE))
- X return &t1->left;
- X }
- X
- X return (C_Op **)NULL;
- X}
- X
- Xstatic C_Op *findcase (t, w)
- XC_Op *t;
- Xchar *w;
- X{
- X register C_Op **tp;
- X
- X return ((tp = find1case (t, w)) != (C_Op **)NULL) ? *tp : (C_Op *)NULL;
- X}
- X
- X/*
- X * Set up the status on exit from a command
- X */
- X
- Xstatic int setstatus (s)
- Xregister int s;
- X{
- X exstat = s;
- X setval (lookup ("?", TRUE), putn (s));
- X return s;
- X}
- X
- X/*
- X * PATH-searching interface to execve. If getenv ("PATH") were kept
- X * up-to-date, execvp might be used.
- X */
- X
- Xstatic int rexecve (c, v, envp, d_flag)
- Xchar *c;
- Xchar **v;
- Xchar **envp;
- Xbool d_flag;
- X{
- X register char *sp;
- X int res;
- X char *em;
- X bool eloop;
- X
- X/* If the environment is null - It is too big - error */
- X
- X if (envp == (char **)NULL)
- X em = AE2big;
- X
- X else
- X {
- X sp = any ('/', c) ? null : path->value;
- X
- X do
- X {
- X sp = path_append (sp, c, e.linep);
- X
- X if ((res = Execute_program (e.linep, v, envp, d_flag)) != -1)
- X return res;
- X
- X eloop = TRUE;
- X
- X switch (errno)
- X {
- X
- X/* No entry for the file - if the file exists, execute it as a shell
- X * script
- X */
- X case ENOENT:
- X if ((res = O_for_execute (e.linep)) >= 0)
- X {
- X S_close (res, TRUE);
- X *v = e.linep;
- X em = *--v;
- X *v = e.linep;
- X res = Execute_program (lookup (shell, FALSE)->value,
- X v, envp, d_flag);
- X *v = em;
- X
- X if (res != -1)
- X return res;
- X
- X em = "no Shell";
- X }
- X
- X else
- X em = "not found";
- X
- X eloop = FALSE;
- X break;
- X
- X case ENOEXEC:
- X em = "program corrupt";
- X break;
- X
- X case ENOMEM:
- X em = "program too big";
- X break;
- X
- X case E2BIG:
- X em = AE2big;
- X break;
- X
- X default:
- X em = "cannot execute";
- X eloop = FALSE;
- X break;
- X }
- X } while ((sp != (char *)NULL) && !eloop);
- X }
- X
- X print_warn ("%s: %s\n", c, em);
- X
- X if (!d_flag)
- X exit (-1);
- X
- X return -1;
- X}
- X
- X/*
- X * Run the command produced by generator `f' applied to stream `arg'.
- X */
- X
- Xint run (argp, f)
- XIO_Args *argp;
- Xint (*f)(IO_State *);
- X{
- X Word_B *swdlist = wdlist;
- X Word_B *siolist = iolist;
- X jmp_buf ev, rt;
- X int *ofail = failpt;
- X int rv = -1;
- X Break_C *S_RList = Return_List; /* Save loval links */
- X Break_C *S_BList = Break_List;
- X Break_C *S_SList = SShell_List;
- X Break_C bc;
- X int LS_depth = Execute_stack_depth;
- X C_Op *outtree;
- X
- X/* Create a new environment in which to run */
- X
- X if (Create_NG_VL () == -1)
- X return -1;
- X
- X/* Create a new save area */
- X
- X areanum++;
- X
- X/* Execute the command */
- X
- X if (newenv (setjmp (errpt = ev)) == FALSE)
- X {
- X Return_List = (Break_C *)NULL;
- X Break_List = (Break_C *)NULL;
- X wdlist = (Word_B *)NULL;
- X iolist = (Word_B *)NULL;
- X
- X pushio (argp, f);
- X e.iobase = e.iop;
- X yynerrs = 0;
- X
- X
- X if ((setjmp (failpt = rt) == 0) &&
- X ((outtree = yyparse ()) != (C_Op *)NULL))
- X {
- X if (setjmp (bc.brkpt) == 0)
- X {
- X bc.nextlev = SShell_List;
- X SShell_List = &bc;
- X rv = execute (outtree, NOPIPE, NOPIPE, 0);
- X }
- X
- X else
- X rv = getn (lookup ("?", FALSE)->value);
- X }
- X
- X quitenv ();
- X }
- X
- X/* Restore the environment */
- X
- X Return_List = S_RList;
- X Break_List = S_BList;
- X SShell_List = S_SList;
- X wdlist = swdlist;
- X iolist = siolist;
- X failpt = ofail;
- X
- X Restore_Environment (rv, LS_depth);
- X
- X freearea (areanum--);
- X return rv;
- X}
- X
- X/* Exec or spawn the program ? */
- X
- Xstatic int Execute_program (path, parms, envp, d_flag)
- Xchar *path;
- Xchar **parms;
- Xchar **envp;
- Xbool d_flag;
- X{
- X return setstatus ((!d_flag) ? execve (path, parms, envp)
- X : S_spawnve (path, parms, envp));
- X}
- X
- X/* Set up to spawn a process */
- X
- Xstatic int S_spawnve (path, parms, envp)
- Xchar *path;
- Xchar **parms;
- Xchar **envp;
- X{
- X unsigned int c_cur = (unsigned int)(_psp - 1);
- X unsigned int size = 0;
- X char *ep, *ep1;
- X int res, serrno;
- X struct MCB_list *mp = (struct MCB_list *)((unsigned long)c_cur << 16L);
- X
- X
- X/* Check to see if the file exists */
- X
- X strcpy (path_line, path);
- X
- X if ((ep = strrchr (path_line, '/')) == (char *)NULL)
- X ep = path_line;
- X
- X/* If no dot in name - check for .exe and .com files */
- X
- X if ((ep1 = strchr (ep, '.')) == (char *)NULL)
- X {
- X ep1 = ep + strlen (ep);
- X strcpy (ep1, ".exe");
- X
- X if ((res = access (path_line, F_OK)) != 0)
- X {
- X strcpy (ep1, ".com");
- X res = access (path_line, F_OK);
- X }
- X
- X if (res != 0)
- X return -1;
- X }
- X
- X else if ((stricmp (ep1, ".exe") != 0) && (stricmp (ep1, ".com") != 0))
- X {
- X errno = ENOEXEC;
- X return -1;
- X }
- X
- X else if (access (path_line, F_OK) != 0)
- X return -1;
- X
- X/* Process the command line. If no swapping, we have executed the program */
- X
- X res = build_command_line (path_line, parms, envp);
- X
- X if ((Swap_Mode == SWAP_OFF) || res)
- X return res;
- X
- X/* Find the length of the swap area */
- X
- X while ((mp = (struct MCB_list *)((unsigned long)c_cur << 16L))->MCB_type
- X == MCB_CON)
- X {
- X if ((mp->MCB_pid != _psp) && (mp->MCB_pid != 0) &&
- X (mp->MCB_type != MCB_END))
- X {
- X Clear_Extended_File ();
- X print_error ("Fatal: Memory chain corrupt\n");
- X return -1;
- X }
- X
- X c_cur += (mp->MCB_len + 1);
- X size += mp->MCB_len + 1;
- X }
- X
- X/*
- X * Convert swap size from paragraphs to 16K blocks.
- X */
- X
- X if (size == 0)
- X size = mp->MCB_len + 1;
- X
- X SW_Blocks = (size / 0x0400) + 1;
- X
- X/* OK Now we've set up the FCB's, command line and opened the swap file.
- X * Get some sys info for the swapper and execute my little assembler
- X * function to swap us out
- X */
- X
- X get_sys_info ();
- X
- X/* Ok - 3 methods of swapping */
- X
- X/* If expanded memory - try that */
- X
- X if (Swap_Mode & SWAP_EXPAND)
- X {
- X int cr;
- X SW_Mode = 3; /* Set Expanded memory swap */
- X
- X res = SA_spawn (envp);
- X cr = EMS_Close (); /* Close EMS */
- X
- X if ((res != -2) && cr) /* Report Close error ? */
- X {
- X res = -2;
- X errno = cr;
- X }
- X
- X if (res == -2)
- X EMS_error ("Expanded memory swap failed (%x)\n", errno);
- X
- X else
- X {
- X Clear_Extended_File ();
- X return res;
- X }
- X
- X/* Failed - disabled */
- X
- X Swap_Mode &= (~SWAP_EXPAND);
- X }
- X
- X if (Swap_Mode & SWAP_EXTEND)
- X {
- X SW_Mode = 2; /* Set Extended memory swap */
- X
- X if ((SW_EMsize <= SW_Blocks) ||
- X ((SW_EMstart - 0x100000L +
- X ((long)(SW_Blocks - SW_EMsize) * 16L * 1024L)) < 0L))
- X print_warn ("Not enough Extended memory for swap\n");
- X
- X else if ((res = SA_spawn (envp)) == -2)
- X print_warn ("Extended memory swap failed (%x)\n", errno);
- X
- X else
- X {
- X Clear_Extended_File ();
- X return res;
- X }
- X
- X/* Failed - disabled */
- X
- X Swap_Mode &= (~SWAP_EXTEND);
- X }
- X
- X/* Try the disk if available */
- X
- X if (Swap_Mode & SWAP_DISK)
- X {
- X if ((SW_fp = S_open (TRUE, g_tempname (), O_SMASK, 0600)) < 0)
- X {
- X print_error ("No Swap files\n");
- X errno = ENOSPC;
- X return -1;
- X }
- X
- X SW_Mode = 1; /* Set Disk file swap */
- X
- X/* Execute the program */
- X
- X res = SA_spawn (envp);
- X
- X Clear_Extended_File ();
- X
- X if (res == -2)
- X {
- X print_warn ("Swap file write failed\n");
- X errno = ENOSPC;
- X res = -1;
- X }
- X
- X/* Close the swap file and return the result */
- X
- X serrno = errno;
- X S_close (SW_fp, TRUE);
- X errno = serrno;
- X return res;
- X }
- X
- X/* No swapping available - give up */
- X
- X Clear_Extended_File ();
- X print_error ("All Swapping methods failed\n");
- X errno = ENOSPC;
- X return -1;
- X}
- X
- X/* Get some system info */
- X
- Xstatic void get_sys_info ()
- X{
- X union REGS or;
- X struct SREGS sr;
- X char *sp;
- X
- X/* Save the interrupt 0 address */
- X
- X or.x.ax = 0x3500;
- X intdosx (&or, &or, &sr);
- X
- X SW_I0_V_BX = or.x.bx;
- X SW_I0_V_ES = sr.es;
- X
- X/* Save the interrupt 23 address */
- X
- X or.x.ax = 0x3523;
- X intdosx (&or, &or, &sr);
- X
- X SW_I23_V_BX = or.x.bx;
- X SW_I23_V_ES = sr.es;
- X
- X/* Get max Extended memory pages, and convert to 16K blocks. If Extended
- X * memory swapping disabled, set to zero
- X */
- X
- X or.x.ax = 0x8800;
- X int86 (0x15, &or, &or);
- X SW_EMsize = (Swap_Mode & SWAP_EXTEND) ? or.x.ax / 16 : 0;
- X
- X/* Check for the Expand Memory System */
- X
- X if (!(Swap_Mode & SWAP_EXPAND))
- X return;
- X
- X SW_fp = -1; /* Set EMS handler not defined */
- X
- X or.x.ax = 0x3567;
- X intdosx (&or, &or, &sr);
- X
- X sp = (char *)((unsigned long)(sr.es) << 16L | 10L);
- X
- X/* If not there - disable */
- X
- X if (memcmp ("EMMXXXX0", sp, 8) != 0)
- X {
- X EMS_error ("Warning: EMS not available\n", 0);
- X return;
- X }
- X
- X or.h.ah = 0x40; /* Check status */
- X int86 (0x67, &or, &or);
- X
- X if (or.h.ah != 0)
- X {
- X EMS_error (EMS_emsg, or.h.ah);
- X return;
- X }
- X
- X/* Check version greater than 3.2 */
- X
- X or.h.ah = 0x46;
- X int86 (0x67, &or, &or);
- X
- X if ((or.h.ah != 0) || (or.h.al < 0x32))
- X {
- X EMS_error (EMS_emsg, or.h.ah);
- X return;
- X }
- X
- X/* get page frame address */
- X
- X or.h.ah = 0x41;
- X int86 (0x67, &or, &or);
- X
- X if (or.h.ah != 0)
- X {
- X EMS_error (EMS_emsg, or.h.ah);
- X return;
- X }
- X
- X SW_EMSFrame = or.x.bx; /* Save the page frame */
- X
- X/* Get the number of pages required */
- X
- X or.h.ah = 0x43;
- X or.x.bx = SW_Blocks;
- X int86 (0x67, &or, &or);
- X
- X if (or.h.ah != 0)
- X {
- X EMS_error (EMS_emsg, or.h.ah);
- X return;
- X }
- X
- X/* Save the EMS Handler */
- X
- X SW_fp = or.x.dx;
- X
- X/* save EMS page map */
- X
- X or.h.ah = 0x47;
- X or.x.dx = SW_fp;
- X int86 (0x67, &or, &or);
- X
- X if (or.h.ah != 0)
- X {
- X EMS_error (EMS_emsg, or.h.ah);
- X return;
- X }
- X}
- X
- X/* Print EMS error message */
- X
- Xstatic void EMS_error (s, v)
- Xchar *s;
- Xint v;
- X{
- X print_warn (s, v);
- X Swap_Mode &= ~(SWAP_EXPAND);
- X EMS_Close ();
- X}
- X
- X
- X/* If the handler is defined - close it */
- X
- Xstatic int EMS_Close ()
- X{
- X union REGS or;
- X int res = 0;
- X
- X if (SW_fp == -1)
- X return 0;
- X
- X/* Restore EMS page */
- X
- X or.h.ah = 0x48;
- X or.x.dx = SW_fp;
- X int86 (0x67, &or, &or);
- X
- X if (or.h.ah != 0)
- X res = or.h.al;
- X
- X or.h.ah = 0x45;
- X or.x.dx = SW_fp;
- X int86 (0x67, &or, &or);
- X
- X SW_fp = -1;
- X return (res) ? res : or.h.ah;
- X}
- X
- X/* Set up command line. If the EXTENDED_LINE variable is set, we create
- X * a temporary file, write the argument list (one entry per line) to the
- X * this file and set the command line to @<filename>. If NOSWAPPING, we
- X * execute the program because I have to modify the argument line
- X */
- X
- Xint build_command_line (path, argv, envp)
- Xchar *path;
- Xchar **argv;
- Xchar **envp;
- X{
- X char **pl = argv;
- X char *fname;
- X int res, fd;
- X char *pname;
- X FILE *fp;
- X char nbuffer[NAME_MAX + 2];
- X bool found;
- X char *ep;
- X char *new_args[3];
- X
- X/* Find the start of the program name */
- X
- X if ((pname = strrchr (path, '/')) == (char *)NULL)
- X pname = path;
- X
- X else
- X ++pname;
- X
- X/* Translate process name to MSDOS format */
- X
- X Convert_Slashes (path);
- X strupr (path);
- X
- X/* Extended command line processing */
- X
- X Extend_file == (char *)NULL; /* Set no file */
- X
- X if ((*(pl++) != (char *)NULL) &&
- X ((fname = lookup ("EXTENDED_LINE", FALSE)->value) != null) &&
- X ((fp = fopen (fname, "rt")) != (FILE *)NULL))
- X {
- X
- X/* Loop through the file look for the current program */
- X
- X found = FALSE;
- X
- X while (fgets (nbuffer, NAME_MAX + 1, fp) != (char *)NULL)
- X {
- X if ((ep = strchr (nbuffer, '\n')) != (char *)NULL)
- X *ep = 0;
- X
- X if (stricmp (nbuffer, pname) == 0)
- X {
- X found = TRUE;
- X break;
- X }
- X }
- X
- X fclose (fp);
- X
- X/* Check parameters don't contain a re-direction parameter */
- X
- X if (found)
- X {
- X char **pl1 = pl;
- X
- X while (*pl1 != (char *)NULL)
- X {
- X if (**(pl1++) == '@')
- X {
- X found = FALSE;
- X break;
- X }
- X }
- X }
- X
- X/* If we find it - create a temporary file and write the stuff */
- X
- X if ((found) &&
- X ((fd = S_open (FALSE, Extend_file = g_tempname (), O_CMASK,
- X 0600)) >= 0))
- X {
- X
- X/* Copy to end of list */
- X
- X while (*pl != (char *)NULL)
- X {
- X if (((res = strlen (*pl)) && (write (fd, *pl, res) != res)) ||
- X (write (fd, "\n", 1) != 1))
- X {
- X close (fd);
- X unlink (Extend_file);
- X Extend_file == (char *)NULL;
- X errno = ENOSPC;
- X return -1;
- X }
- X
- X ++pl;
- X }
- X
- X/* Completed write OK */
- X
- X close (fd);
- X
- X/* Set up cmd_line[1] to contain the filename */
- X
- X memset (cmd_line, 0, CMD_LINE_MAX);
- X cmd_line[1] = '@';
- X strcpy (&cmd_line[2], Extend_file);
- X cmd_line[0] = (char)(strlen (Extend_file) + 1);
- X
- X/* Correctly terminate cmd_line in no swap mode */
- X
- X if (Swap_Mode != SWAP_OFF)
- X cmd_line[cmd_line[0] + 1] = '\r';
- X
- X/* If the name in the file is in upper case - use \ for separators */
- X
- X if (isupper (*nbuffer))
- X Convert_Slashes (&cmd_line[2]);
- X
- X/* OK we are ready to execute */
- X
- X if (Swap_Mode == SWAP_OFF)
- X {
- X new_args[0] = *argv;
- X new_args[1] = &cmd_line[1];
- X new_args[2] = (char *)NULL;
- X return spawnve (P_WAIT, path, new_args, envp);
- X }
- X
- X else
- X return 0;
- X }
- X }
- X
- X/* Check length of Parameter list */
- X
- X res = 0;
- X cmd_line[0] = 0;
- X cmd_line[1] = '\r';
- X ep = cmd_line;
- X
- X/* Skip the first parameter and get the length of the rest */
- X
- X if (*argv != (char *)NULL)
- X {
- X while (*pl != (char *)NULL)
- X {
- X if ((res += (strlen (*pl) + 1)) >= CMD_LINE_MAX)
- X {
- X errno = E2BIG;
- X return -1;
- X }
- X
- X strcat (strcat (ep, " "), *(pl++));
- X }
- X
- X if (res)
- X cmd_line[res--] = '\r';
- X }
- X
- X/* Terminate the line and insert the line length */
- X
- X cmd_line[0] = (char)res;
- X
- X/* If swapping disabled - just execute it */
- X
- X return (Swap_Mode == SWAP_OFF) ? spawnve (P_WAIT, path, argv, envp) : 0;
- X}
- X
- X/* Clear Extended command line file */
- X
- Xstatic void Clear_Extended_File ()
- X{
- X if (Extend_file != (char *)NULL)
- X unlink (Extend_file);
- X
- X Extend_file = (char *)NULL;
- X}
- SHAR_EOF
- chmod 0644 shell/sh3.c || echo "restore of shell/sh3.c fails"
- set `wc -c shell/sh3.c`;Sum=$1
- if test "$Sum" != "28726"
- then echo original size 28726, current size $Sum;fi
- echo "x - extracting shell/sh4.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > shell/sh4.c &&
- X/* MS-DOS SHELL - 'word' Interpretator
- X *
- X * MS-DOS SHELL - Copyright (c) 1990 Data Logic Limited and Charles Forsyth
- X *
- X * This code is based on (in part) the shell program written by Charles
- X * Forsyth and is subject to the following copyright restrictions:
- X *
- X * 1. Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice is duplicated in the
- X * source form and the copyright notice in file sh6.c is displayed
- X * on entry to the program.
- X *
- X * 2. The sources (or parts thereof) or objects generated from the sources
- X * (or parts of sources) cannot be sold under any circumstances.
- X *
- X * $Header: sh4.c 1.1 90/01/25 13:41:38 MS_user Exp $
- X *
- X * $Log: sh4.c $
- X * Revision 1.1 90/01/25 13:41:38 MS_user
- X * Initial revision
- X *
- X */
- X
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <signal.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include <dirent.h>
- X#include <string.h>
- X#include <stdlib.h>
- X#include <unistd.h>
- X#include <ctype.h>
- X#include <bios.h>
- X#include <dos.h>
- X#include "sh.h"
- X
- X/*
- X * ${}, `command`, blank interpretation, quoting and file name expansion
- X */
- X
- X#define NSTART 16 /* default number of words to */
- X /* allow for initially */
- Xstatic Word_B *C_EList; /* For expand functions */
- Xstatic Word_B *New_Elist;
- Xstatic char *spcl = "[?*";
- Xstatic char *spcl1 = "\"'";
- X
- Xstatic void globname (char *, char *);
- Xstatic bool expand (char *, Word_B **, int);
- Xstatic char dollar (int);
- Xstatic bool grave (int);
- Xstatic Word_B *Expand_globs (char *, Word_B *);
- Xstatic bool anyspcl (Word_B *);
- Xstatic char *blank (int);
- Xstatic char *generate (char *, char *, char *, char *);
- Xstatic char *unquote (char *);
- Xstatic Word_B *newword (int);
- Xstatic bool anys (char *, char *);
- Xstatic char *anys_p (char *, char *);
- Xstatic void Glob_MDrives (char *, char *);
- Xstatic char *Check_Multi_Drive (char *);
- X
- X/*
- X * Expand all words to their full potential
- X */
- X
- Xchar **eval(ap, f)
- Xregister char **ap;
- X{
- X Word_B *wb = (Word_B *)NULL;
- X char **wp = (char **)NULL;
- X char **wf = (char **)NULL;
- X jmp_buf ev;
- X
- X if (newenv (setjmp (errpt = ev)) == FALSE)
- X {
- X while ((*ap != (char *)NULL) && isassign (*ap))
- X expand (*(ap++), &wb, f & ~DOGLOB);
- X
- X if (FL_TEST ('k'))
- X {
- X for (wf = ap; *wf != (char *)NULL; wf++)
- X {
- X if (isassign (*wf))
- X expand (*wf, &wb, f & ~DOGLOB);
- X }
- X }
- X
- X/* Now expand the words */
- X
- X for (wb = addword ((char *)NULL, wb); *ap; ap++)
- X {
- X if (!FL_TEST ('k') || !isassign(*ap))
- X expand (*ap, &wb, f & ~DOKEY);
- X }
- X
- X/* Get the word list */
- X
- X wp = getwords (wb = addword ((char *)NULL, wb));
- X quitenv ();
- X }
- X
- X else
- X gflg = 1;
- X
- X return gflg ? (char **)NULL : wp;
- X}
- X
- X/*
- X * Make the exported environment from the exported names in the dictionary.
- X * Keyword assignments will already have been done. Convert to MSDOS
- X * format if flag set and m enabled
- X */
- X
- Xchar **makenv ()
- X{
- X register Word_B *wb = (Word_B *)NULL;
- X register Var_List *vp;
- X char *cp, *sp;
- X int len = 0;
- X
- X for (vp = vlist; vp != (Var_List *)NULL; vp = vp->next)
- X {
- X if (vp->status & EXPORT)
- X {
- X if ((len += (strlen (vp->name) + 1)) >= 0x7f00)
- X return (char **)NULL;
- X
- X wb = addword (vp->name, wb);
- X
- X/* If MSDOS mode, we need to copy the variable, convert / to \ and put
- X * the copy in the environment list instead
- X */
- X
- X if (FL_TEST ('m') && (vp->status & C_MSDOS))
- X {
- X cp = space (strlen (sp = wb->w_words[wb->w_nword - 1]) + 1);
- X wb->w_words[wb->w_nword - 1] = cp;
- X Convert_Slashes (strcpy (cp, sp));
- X }
- X }
- X }
- X
- X return getwords (wb = addword ((char *)NULL, wb));
- X}
- X
- Xchar *evalstr(cp, f)
- Xregister char *cp;
- Xint f;
- X{
- X Word_B *wb = (Word_B *)NULL;
- X
- X if (expand (cp, &wb, f))
- X {
- X if ((wb == (Word_B *)NULL) || (wb->w_nword == 0) ||
- X ((cp = wb->w_words[0]) == (char *)NULL))
- X cp = null;
- X
- X DELETE (wb);
- X }
- X
- X else
- X cp = (char *)NULL;
- X
- X return cp;
- X}
- X
- X/* Expand special characters and variables */
- X
- Xstatic bool expand (cp, wbp, f)
- Xregister char *cp;
- Xregister Word_B **wbp;
- X{
- X jmp_buf ev;
- X
- X gflg = 0;
- X
- X if (cp == (char *)NULL)
- X return FALSE;
- X
- X/* If there are no special characters and no separators, nothing to do,
- X * just save the word
- X */
- X
- X if (!anys (spcl2, cp) && !anys (ifs->value, cp) &&
- X ((f & DOGLOB) == 0 || !anys (spcl, cp)))
- X {
- X cp = strsave (cp, areanum);
- X
- X if (f & DOTRIM)
- X unquote (cp);
- X
- X *wbp = addword (cp, *wbp);
- X return TRUE;
- X }
- X
- X/* Set up to read the word back in */
- X
- X if (newenv (setjmp (errpt = ev)) == FALSE)
- X {
- X PUSHIO (aword, cp, strchar);
- X e.iobase = e.iop;
- X
- X while ((cp = blank (f)) && gflg == 0)
- X {
- X e.linep = cp;
- X cp = strsave (cp, areanum);
- X
- X/* Global expansion disabled ? */
- X
- X if (((f & DOGLOB) == 0) || FL_TEST ('f'))
- X {
- X if (f & DOTRIM)
- X unquote(cp);
- X
- X *wbp = addword (cp, *wbp);
- X }
- X
- X else
- X *wbp = Expand_globs (cp, *wbp);
- X }
- X
- X quitenv ();
- X }
- X
- X else
- X gflg = 1;
- X
- X return (gflg == 0) ? TRUE : FALSE;
- X}
- X
- X/*
- X * Blank interpretation and quoting
- X */
- X
- Xstatic char *blank(f)
- X{
- X register int c, c1;
- X register char *sp = e.linep;
- X int scanequals = f & DOKEY;
- X int foundequals = 0;
- X
- Xloop:
- X switch (c = subgetc ('"', foundequals))
- X {
- X case 0:
- X if (sp == e.linep)
- X return (char *)NULL;
- X
- X *e.linep++ = 0;
- X return sp;
- X
- X default:
- X if ((f & DOBLANK) && any ((char)c, ifs->value))
- X goto loop;
- X
- X break;
- X
- X case '"':
- X case '\'':
- X scanequals = 0;
- X if (INSUB())
- X break;
- X
- X for (c1 = c; (c = subgetc ((char)c1, 1)) != c1;)
- X {
- X if (c == 0)
- X break;
- X
- X if ((c == '\'') || !any ((char)c, "$`\""))
- X c |= QUOTE;
- X
- X *e.linep++ = (char)c;
- X }
- X
- X c = 0;
- X }
- X
- X unget(c);
- X
- X if (!isalpha (c))
- X scanequals = 0;
- X
- X while (1)
- X {
- X if (((c = subgetc ('"', foundequals)) == 0) ||
- X (f & DOBLANK) && any ((char)c, ifs->value) ||
- X !INSUB() && any ((char)c, spcl1))
- X {
- X scanequals = 0;
- X unget (c);
- X
- X if (any ((char)c, spcl1))
- X goto loop;
- X
- X break;
- X }
- X
- X if (scanequals)
- X {
- X if (c == '=')
- X {
- X foundequals = 1;
- X scanequals = 0;
- X }
- X
- X else if (!isalnum (c))
- X scanequals = 0;
- X }
- X
- X *e.linep++ = (char)c;
- X }
- X
- X *e.linep++ = 0;
- X return sp;
- X}
- X
- X/*
- X * Get characters, substituting for ` and $
- X */
- X
- Xint subgetc (ec, quoted)
- Xregister char ec;
- Xint quoted;
- X{
- X register char c;
- X
- Xagain:
- X c = (char)Getc (ec);
- X
- X if (!INSUB() && ec != '\'')
- X {
- X if (c == '`')
- X {
- X if (grave (quoted) == 0)
- X return 0;
- X
- X e.iop->task = XGRAVE;
- X goto again;
- X }
- X
- X if (c == '$' && (c = dollar (quoted)) == 0)
- X {
- X e.iop->task = XDOLL;
- X goto again;
- X }
- X }
- X
- X return c;
- X}
- X
- X/*
- X * Prepare to generate the string returned by ${} substitution.
- X */
- X
- Xstatic char dollar (quoted)
- Xint quoted;
- X{
- X IO_State *oiop;
- X char *dolp, otask;
- X register char *s, c, *cp;
- X Var_List *vp;
- X bool colon_f = FALSE;
- X
- X c = (char)readc ();
- X s = e.linep;
- X
- X/* Bracketed or not ? */
- X
- X if (c != '{')
- X {
- X
- X/* Get the string, while it is a alpha character */
- X
- X *e.linep++ = c;
- X
- X if (isalpha (c))
- X {
- X while (((c = (char)readc ()) != 0) && isalnum (c))
- X {
- X if (e.linep < e.eline)
- X *e.linep++ = c;
- X }
- X
- X unget(c);
- X }
- X
- X c = 0;
- X }
- X
- X/* Bracketed - special case */
- X
- X else
- X {
- X oiop = e.iop;
- X otask = e.iop->task;
- X e.iop->task = XOTHER;
- X
- X while (((c = (char)subgetc ('"', 0)) != 0) && (c != '}') && (c != NL))
- X {
- X if (e.linep < e.eline)
- X *e.linep++ = c;
- X }
- X
- X if (oiop == e.iop)
- X e.iop->task = otask;
- X
- X/* Check terminate correctly */
- X
- X if (c != '}')
- X {
- X print_error ("sh: unclosed ${\n");
- X gflg++;
- X return c;
- X }
- X }
- X
- X/* Check line length */
- X
- X if (e.linep >= e.eline)
- X {
- X print_error ("sh: string in ${} too long\n");
- X gflg++;
- X e.linep -= 10;
- X }
- X
- X *e.linep = 0;
- X
- X/* Scan for =-+? in string */
- X
- X if (*s)
- X {
- X for (cp = s + 1; *cp; cp++)
- X {
- X
- X/* Check for end character other than null (=-+?) */
- X
- X if (any (*cp, "=-+?"))
- X {
- X c = *cp;
- X
- X/* Check for case of :[=-+?]. If found - set flag */
- X
- X if (*(cp - 1) == ':')
- X {
- X colon_f = TRUE;
- X *(cp - 1) = 0;
- X }
- X
- X *(cp++) = 0;
- X break;
- X }
- X }
- X }
- X
- X/* Check for * and @ processing */
- X
- X if (s[1] == 0 && (*s == '*' || *s == '@'))
- X {
- X if (dolc > 1)
- X {
- X e.linep = s;
- X PUSHIO (awordlist, dolv + 1, dol_char);
- X e.iop->dflag = (char)(!quoted ? DSA_NULL
- X : ((*s == '*') ? DSA_STAR : DSA_AMP));
- X return 0;
- X }
- X
- X/* trap the nasty ${=} */
- X
- X else
- X {
- X s[0] = '1';
- X s[1] = 0;
- X }
- X }
- X
- X/* Find the current value
- X *
- X * $~xxx variables are used by the Shell internally and cannot be accessed
- X * by the user.
- X */
- X
- X if (*s == '~')
- X dolp = null;
- X
- X else if ((dolp = (vp = lookup (s, FALSE))->value) == null)
- X {
- X switch (c)
- X {
- X case '=':
- X if (isdigit (*s))
- X {
- X print_error ("sh: cannot use ${...=...} with $n\n");
- X gflg++;
- X break;
- X }
- X
- X setval ((vp = lookup (s, TRUE)), cp);
- X dolp = vp->value;
- X break;
- X
- X case '-':
- X dolp = strsave (cp, areanum);
- X break;
- X
- X case '?':
- X if (*cp == 0)
- X cp = "parameter null or not set";
- X
- X print_error ("%s: %s\n", s, cp);
- X
- X gflg++;
- X break;
- X }
- X }
- X
- X else if (c == '+')
- X dolp = strsave (cp, areanum);
- X
- X/* Check for unset values */
- X
- X if (FL_TEST ('u') && dolp == null)
- X {
- X print_error ("sh: unset variable %s\n", s);
- X gflg++;
- X }
- X
- X e.linep = s;
- X PUSHIO (aword, dolp, quoted ? qstrchar : strchar);
- X return 0;
- X}
- X
- X/*
- X * Run the command in `...` and read its output.
- X */
- X
- Xstatic bool grave (quoted)
- Xint quoted;
- X{
- X char *cp, *sp;
- X int localpipe, rv;
- X jmp_buf ev, rt;
- X C_Op *outtree;
- X Break_C bc;
- X
- X/* Save area */
- X
- X long s_flags = flags;
- X Word_B *s_wdlist = wdlist;
- X Word_B *s_iolist = iolist;
- X Break_C *S_RList = Return_List; /* Save loval links */
- X Break_C *S_BList = Break_List;
- X Break_C *S_SList = SShell_List;
- X int *s_fail = failpt;
- X int s_execflg = execflg;
- X int Local_depth;
- X
- X/* Check there is an ending grave */
- X
- X if ((cp = strchr (e.iop->argp->aword, '`')) == (char *)NULL)
- X {
- X print_error ("sh: no closing `\n");
- X return FALSE;
- X }
- X
- X/* Create the pipe to read the output from the command string */
- X
- X if ((localpipe = openpipe ()) < 0)
- X return FALSE;
- X
- X/* Terminate string and initialise save area */
- X
- X *cp = 0;
- X
- X/* Create a new environment */
- X
- X S_dup2 (localpipe, 1);
- X
- X FL_CLEAR ('e');
- X FL_CLEAR ('v');
- X FL_CLEAR ('n');
- X
- X sp = strsave (e.iop->argp->aword, areanum++);
- X unquote (sp);
- X
- X/* Set up new environment */
- X
- X Local_depth = Execute_stack_depth++;
- X rv = Create_NG_VL ();
- X
- X if ((rv != -1) && (newenv (setjmp (errpt = ev)) == FALSE))
- X {
- X Return_List = (Break_C *)NULL;
- X Break_List = (Break_C *)NULL;
- X wdlist = (Word_B *)NULL;
- X wdlist = (Word_B *)NULL;
- X iolist = (Word_B *)NULL;
- X
- X PUSHIO (aword, sp, nlchar);
- X e.cline = space (LINE_MAX);
- X e.eline = e.cline + LINE_MAX - 5;
- X e.linep = e.cline;
- X e.iobase = e.iop;
- X
- X/* Clear interrupt, error, multiline, parse and execute flags. */
- X
- X SW_intr = 0;
- X yynerrs = 0;
- X multiline = 0;
- X inparse = 0;
- X execflg = 1;
- X
- X/* Parse the line and execute it */
- X
- X if ((setjmp (failpt = rt) == 0) &&
- X ((outtree = yyparse ()) != (C_Op *)NULL))
- X {
- X if (setjmp (bc.brkpt) == 0)
- X {
- X bc.nextlev = SShell_List;
- X SShell_List = &bc;
- X execute (outtree, NOPIPE, NOPIPE, 0);
- X }
- X }
- X
- X quitenv ();
- X }
- X
- X/* Fail - close pipe and delete it */
- X
- X else
- X {
- X S_Delete (localpipe);
- X S_close (localpipe, TRUE);
- X }
- X
- X/* Restore environment */
- X
- X Restore_Environment (0, Local_depth);
- X
- X/* Free old space */
- X
- X freehere (areanum);
- X freearea (areanum--); /* free old space */
- X
- X/* Ok - completed processing - restore environment and read the pipe */
- X
- X execflg = s_execflg;
- X flags = s_flags;
- X wdlist = s_wdlist;
- X iolist = s_iolist;
- X failpt = s_fail;
- X Return_List = S_RList;
- X Break_List = S_BList;
- X SShell_List = S_SList;
- X
- X/* Move pipe to start so we can read it */
- X
- X *(cp++) = '`';
- X lseek (localpipe, 0L, SEEK_SET);
- X e.iop->argp->aword = cp;
- X PUSHIO (afile, remap (localpipe), quoted ? qgravechar: gravechar);
- X return TRUE;
- X}
- X
- X/*
- X * Remove Quotes from a string
- X */
- X
- Xstatic char *unquote (as)
- Xregister char *as;
- X{
- X register char *s;
- X
- X if ((s = as) != (char *)NULL)
- X {
- X while (*s)
- X *(s++) &= ~QUOTE;
- X }
- X
- X return as;
- X}
- X
- X/*
- X * Expand *, [] and ?
- X */
- X
- Xstatic Word_B *Expand_globs (cp, wb)
- Xchar *cp;
- XWord_B *wb;
- X{
- X register int i = 0;
- X register char *pp;
- X
- X/* Ignore null strings */
- X
- X if (cp == (char *)NULL)
- X return wb;
- X
- X/* Any special characters */
- X
- X for (pp = cp; *pp; pp++)
- X {
- X if (any (*pp, spcl))
- X i++;
- X
- X else if (!any (*pp & ~QUOTE, spcl))
- X *pp &= ~QUOTE;
- X }
- X
- X/* No - just add the word to the selected block */
- X
- X if (i == 0)
- X return addword (unquote (cp), wb);
- X
- X/* OK - we have to expand the word whilst any words in cl have special
- X * characters in them
- X */
- X
- X for (C_EList = addword (strsave (cp, areanum), (Word_B *)NULL);
- X anyspcl (C_EList); C_EList = New_Elist)
- X {
- X
- X/* Get a new block for this pass of the expansion */
- X
- X New_Elist = newword (C_EList->w_nword * 2);
- X
- X/* For each word, expand it */
- X
- X for (i = 0; i < C_EList->w_nword; i++)
- X {
- X if ((pp = anys_p (C_EList->w_words[i], spcl)) != (char *)NULL)
- X Glob_MDrives (C_EList->w_words[i], pp);
- X
- X else
- X New_Elist = addword (strsave (C_EList->w_words[i], areanum),
- X New_Elist);
- X }
- X
- X/* The current list is now the previous list, so delete it */
- X
- X for (i = 0; i < C_EList->w_nword; i++)
- X DELETE (C_EList->w_words[i]);
- X
- X DELETE (C_EList);
- X }
- X
- X for (i = 0; i < C_EList->w_nword; i++)
- X unquote (C_EList->w_words[i]);
- X
- X qsort (C_EList->w_words, C_EList->w_nword, sizeof (char *), sort_compare);
- X
- X/* Did we find any files matching the specification. Yes - add them to
- X * the block
- X */
- X
- X if (C_EList->w_nword)
- X {
- X for (i = 0; i < C_EList->w_nword; i++)
- X wb = addword (C_EList->w_words[i], wb);
- X
- X DELETE (C_EList);
- X return wb;
- X }
- X
- X/* No - add the original word */
- X
- X else
- X return addword (unquote (cp), wb);
- X}
- X
- X/*
- X * Read a directory for matches against the specified name
- X */
- X
- Xstatic void globname (we, pp)
- Xchar *we; /* Start */
- Xregister char *pp; /* First special character */
- X{
- X register char *np, *cp;
- X char *name, *gp, *dp;
- X DIR *dn;
- X struct dirent *d_ce;
- X char dname[NAME_MAX + 1];
- X struct stat dbuf;
- X
- X/* Find the previous directory separator */
- X
- X for (np = we; np != pp; pp--)
- X {
- X if (pp[-1] == '/')
- X break;
- X }
- X
- X/* If we don't find it, check for a drive */
- X
- X if ((np == pp) && (strlen (we) > 2) && (we[1] == ':'))
- X pp += 2;
- X
- X/* Save copy of directory name */
- X
- X for (dp = cp = space ((int)(pp - np) + 3); np < pp;)
- X *cp++ = *np++;
- X
- X *cp++ = '.';
- X *cp = '\0';
- X
- X/* Save copy of pattern for this directory. NP is left pointing to the
- X * rest of the string for any subdirectories
- X */
- X
- X for (gp = cp = space (strlen (pp) + 1); *np && *np != '/';)
- X *cp++ = *np++;
- X
- X *cp = '\0';
- X
- X/* Open the directory */
- X
- X if ((dn = opendir (dp)) == (DIR *)NULL)
- X {
- X DELETE (dp);
- X DELETE (gp);
- X return;
- X }
- X
- X/* Scan for matches */
- X
- X while ((d_ce = readdir (dn)) != (struct dirent *)NULL)
- X {
- X if ((*(strcpy (dname, d_ce->d_name)) == '.') && (*gp != '.'))
- X continue;
- X
- X for (cp = dname; *cp; cp++)
- X {
- X if (any (*cp, spcl))
- X *cp |= QUOTE;
- X }
- X
- X/* Check for a match */
- X
- X if (gmatch (dname, gp, TRUE))
- X {
- X
- X/* If there are no special characters in the new full name, the file must
- X * exist
- X */
- X
- X name = generate (we, pp, dname, np);
- X
- X if (*np && !anys (np, spcl))
- X {
- X if (stat (name, &dbuf))
- X {
- X DELETE (name);
- X continue;
- X }
- X }
- X
- X/* Ok save the name */
- X
- X New_Elist = addword (name, New_Elist);
- X }
- X }
- X
- X closedir (dn);
- X DELETE (dp);
- X DELETE (gp);
- X}
- X
- X/*
- X * generate a pathname as below. start..end1 / middle end. The slashes come
- X * for free
- X */
- X
- Xstatic char *generate (start1, end1, middle, end)
- Xchar *start1;
- Xregister char *end1;
- Xchar *middle, *end;
- X{
- X register char *op;
- X int clen = (int)(end1 - start1);
- X
- X op = space (clen + strlen (middle) + strlen (end) + 2);
- X
- X strncpy (op, start1, clen);
- X strcat (strcpy (&op[clen], middle), end);
- X return op;
- X}
- X
- X/*
- X * Scan a Word Block for special characters
- X */
- X
- Xstatic bool anyspcl (wb)
- Xregister Word_B *wb;
- X{
- X register int i;
- X register char **wd = wb->w_words;
- X
- X for (i = 0; i < wb->w_nword; i++)
- X {
- X if (anys (spcl, *wd++))
- X return TRUE;
- X }
- X
- X return FALSE;
- X}
- X
- X/*
- X * Create a new Word Block
- X */
- X
- Xstatic Word_B *newword (nw)
- Xregister int nw;
- X{
- X register Word_B *wb;
- X
- X wb = (Word_B *) space (sizeof (Word_B) + nw * sizeof (char *));
- X wb->w_bsize = nw;
- X wb->w_nword = 0;
- X
- X return wb;
- X}
- X
- X/*
- X * Add a new word to a Word Block or list
- X */
- X
- XWord_B *addword (wd, wb)
- Xchar *wd;
- Xregister Word_B *wb;
- X{
- X register Word_B *wb2;
- X register int nw;
- X
- X if (wb == (Word_B *)NULL)
- X wb = newword (NSTART);
- X
- X/* Do we require more space ? */
- X
- X if ((nw = wb->w_nword) >= wb->w_bsize)
- X {
- X wb2 = newword (nw * 2);
- X memcpy ((char *)wb2->w_words, (char *)wb->w_words, nw*sizeof(char *));
- X wb2->w_nword = nw;
- X DELETE (wb);
- X wb = wb2;
- X }
- X
- X/* Add to the list */
- X
- X wb->w_words[wb->w_nword++] = wd;
- X return wb;
- X}
- X
- X/*
- X * Convert a word block structure into a array of strings
- X */
- X
- Xchar **getwords(wb)
- Xregister Word_B *wb;
- X{
- X register char **wd;
- X register nb;
- X
- X/* If the word block is empty or does not exist, return no list */
- X
- X if (wb == (Word_B **)NULL)
- X return (char *)NULL;
- X
- X if (wb->w_nword == 0)
- X {
- X DELETE (wb);
- X return (char *)NULL;
- X }
- X
- X/* Get some space for the array and set it up */
- X
- X wd = (char **)space (nb = sizeof (char *) * wb->w_nword);
- X
- X memcpy ((char *)wd, (char *)wb->w_words, nb);
- X DELETE (wb); /* perhaps should done by caller */
- X return wd;
- X}
- X
- X/*
- X * Is any character from s1 in s2? Return a boolean.
- X */
- X
- Xstatic bool anys (s1, s2)
- Xregister char *s1, *s2;
- X{
- X while (*s1)
- X {
- X if (any (*(s1++), s2))
- X return TRUE;
- X }
- X
- X return FALSE;
- X}
- X
- X/*
- X * Is any character from s1 in s2? Yes - return a pointer to that
- X * character.
- X */
- X
- Xstatic char *anys_p (s1, s2)
- Xregister char *s1, *s2;
- X{
- X while (*s1)
- X {
- X if (any (*(s1++), s2))
- X return --s1;
- X }
- X
- X return (char *)NULL;
- X}
- X
- X/*
- X * Expansion - check for multiple drive request
- X *
- X * If there is a multi-drive expansion (*:, ?: or []:), we have to check
- X * out each existing drive and then expand. So we check for a multi-drive
- X * condition and then for each existing drive, we check that pattern
- X * against the drive and then expand the rest of the pattern.
- X *
- X * Otherwise, we just expand the pattern.
- X */
- X
- Xstatic void Glob_MDrives (pattern, start)
- Xchar *pattern;
- Xchar *start;
- X{
- X unsigned int c_drive; /* Current drive */
- X unsigned int m_drive; /* Max drive */
- X unsigned int s_drive; /* Selected drive */
- X unsigned int x_drive, y_drive; /* Dummies */
- X char *multi; /* Multi-drive flag */
- X static char *t_drive = "x";
- X char *new_pattern;
- X
- X/* Search all drives ? */
- X
- X if ((multi = Check_Multi_Drive (pattern)) != (char *)NULL)
- X {
- X _dos_getdrive (&c_drive); /* Get number of drives */
- X _dos_setdrive (c_drive, &m_drive);
- X new_pattern = space (strlen (multi) + 2);
- X
- X strcpy (new_pattern + 1, multi);
- X *multi = 0;
- X
- X for (s_drive = 1; s_drive <= m_drive; ++s_drive)
- X {
- X _dos_setdrive (s_drive, &x_drive);
- X _dos_getdrive (&y_drive);
- X _dos_setdrive (c_drive, &x_drive);
- X
- X/* Check to see if the second diskette drive is really there */
- X
- X if (((_bios_equiplist () & 0x00c0) == 0x0000) && (s_drive == 2))
- X continue;
- X
- X/* If the drive exists and is in our list - process it */
- X
- X *t_drive = (char)(s_drive + 'a' - 1);
- X
- X if ((y_drive == s_drive) && gmatch (t_drive, pattern, TRUE))
- X {
- X *new_pattern = *t_drive;
- X globname (new_pattern, &new_pattern[2]);
- X }
- X }
- X
- X/* Restore and delete space */
- X
- X *multi = ':';
- X DELETE (new_pattern);
- X }
- X
- X/* No drive specifier - just check it out */
- X
- X else
- X globname (pattern, start);
- X}
- X
- X/*
- X * Check for multi_drive prefix - *:, ?: or []:
- X *
- X * Return NULL or the address of the colon character
- X */
- X
- Xstatic char *Check_Multi_Drive (pattern)
- Xchar *pattern;
- X{
- X if (strlen (pattern) < 3)
- X return (char *)NULL;
- X
- X if (((*pattern == '*') || (*pattern == '?')) && (pattern[1] == ':'))
- X return pattern + 1;
- X
- X if (*pattern != '[')
- X return (char *)NULL;
- X
- X while (*pattern && (*pattern != ']'))
- X {
- X if ((*pattern == '\\') && (*(pattern + 1)))
- X ++pattern;
- X
- X ++pattern;
- X }
- X
- X return (*pattern && (*(pattern + 1) == ':')) ? pattern + 1 : (char *)NULL;
- X}
- SHAR_EOF
- chmod 0644 shell/sh4.c || echo "restore of shell/sh4.c fails"
- set `wc -c shell/sh4.c`;Sum=$1
- if test "$Sum" != "20630"
- then echo original size 20630, current size $Sum;fi
- echo "x - extracting shell/sh5.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > shell/sh5.c &&
- X/* MS-DOS SHELL - Main I/O Functions
- X *
- X * MS-DOS SHELL - Copyright (c) 1990 Data Logic Limited and Charles Forsyth
- X *
- X * This code is based on (in part) the shell program written by Charles
- X * Forsyth and is subject to the following copyright restrictions:
- X *
- X * 1. Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice is duplicated in the
- X * source form and the copyright notice in file sh6.c is displayed
- X * on entry to the program.
- X *
- X * 2. The sources (or parts thereof) or objects generated from the sources
- X * (or parts of sources) cannot be sold under any circumstances.
- X *
- X * $Header: sh5.c 1.1 90/01/25 13:41:50 MS_user Exp $
- X *
- X * $Log: sh5.c $
- X * Revision 1.1 90/01/25 13:41:50 MS_user
- X * Initial revision
- X *
- X */
- X
- X#include <sys/types.h>
- X#include <stdio.h>
- X#include <signal.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include <stdlib.h>
- X#include <string.h>
- X#include <fcntl.h>
- X#include <io.h>
- X#include <limits.h>
- X#include <unistd.h>
- X#include "sh.h"
- X
- X/*
- X * shell IO
- X */
- X
- Xstatic IO_Buf sharedbuf = {AFID_NOBUF};
- Xstatic IO_Buf mainbuf = {AFID_NOBUF};
- Xstatic unsigned int bufid = AFID_ID; /* buffer id counter */
- X /* list of hear docs while parsing */
- Xstatic Here_D *inhere = (Here_D *)NULL;
- X /* list of active here documents */
- Xstatic Here_D *acthere = (Here_D *)NULL;
- X
- Xstatic int dol1_char (IO_State *);
- Xstatic void readhere (char **, char *, int);
- Xstatic int herechar (IO_State *);
- X
- Xint Getc (ec)
- Xregister int ec;
- X{
- X register int c;
- X
- X if (e.linep > e.eline)
- X {
- X while (((c = readc ()) != NL) && c)
- X ;
- X
- X print_error ("sh: input line too long\n");
- X gflg++;
- X return c;
- X }
- X
- X c = readc();
- X if ((ec != '\'') && (ec != '`') && (e.iop->task != XGRAVE))
- X {
- X if (c == '\\')
- X {
- X if (((c = readc ()) == NL) && (ec != '\"'))
- X return Getc (ec);
- X
- X c |= QUOTE;
- X }
- X }
- X
- X return c;
- X}
- X
- Xvoid unget (c)
- Xint c;
- X{
- X if (e.iop >= e.iobase)
- X e.iop->peekc = c;
- X}
- X
- Xint eofc ()
- X{
- X return (e.iop < e.iobase) || ((e.iop->peekc == 0) && (e.iop->prev == 0));
- X}
- X
- X/* Read the next character */
- X
- Xint readc ()
- X{
- X register int c;
- X char s_dflag = e.iop->dflag;
- X
- X/* The dflag is transfered from the higher level to the lower level at end
- X * of input at the higher level. This is part of the implementation of
- X * $* and $@ processing.
- X */
- X
- X for (; e.iop >= e.iobase; e.iop--)
- X {
- X
- X/* Set up the current dflag */
- X
- X e.iop->dflag = s_dflag;
- X
- X/* If there is an unget character, use it */
- X
- X if ((c = e.iop->peekc) != '\0')
- X {
- X e.iop->peekc = 0;
- X return c;
- X }
- X
- X/* Some special processing for multi-line commands */
- X
- X else
- X {
- X if (e.iop->prev != 0)
- X {
- X
- X/* Get the next character from the IO function */
- X
- X if ((c = (*e.iop->iofn)(e.iop)) != '\0')
- X {
- X
- X/* End of current level, but continue at this level as another read
- X * function has been put on the stack
- X */
- X
- X if (c == -1)
- X {
- X e.iop++;
- X continue;
- X }
- X
- X/* If we are at the bottom - echo the character */
- X
- X if ((e.iop == iostack) && (FL_TEST ('v')))
- X S_putc ((char)c);
- X
- X/* Return the current character */
- X
- X return (e.iop->prev = (char)c);
- X }
- X
- X else if (e.iop->task == XIO && e.iop->prev != NL)
- X {
- X e.iop->prev = 0;
- X
- X if ((e.iop == iostack) && (FL_TEST ('v')))
- X S_putc (NL);
- X
- X return NL;
- X }
- X
- X else
- X s_dflag = e.iop->dflag;
- X }
- X
- X if (e.iop->task == XIO)
- X {
- X if (multiline)
- X return e.iop->prev = 0;
- X
- X if (talking && e.iop == iostack + 1)
- X put_prompt (ps1->value);
- X }
- X }
- X }
- X
- X if (e.iop >= iostack)
- X return 0;
- X
- X leave();
- X /* NOTREACHED */
- X}
- X
- X/* Add an Input channel to the input stack */
- X
- Xvoid pushio (argp, fn)
- XIO_Args *argp;
- Xint (*fn)(IO_State *);
- X{
- X if (++e.iop >= &iostack[NPUSH])
- X {
- X e.iop--;
- X print_error ("sh: Shell input nested too deeply\n");
- X gflg++;
- X return;
- X }
- X
- X e.iop->iofn = fn;
- X
- X if (argp->afid != AFID_NOBUF)
- X e.iop->argp = argp;
- X
- X else
- X {
- X e.iop->argp = ioargstack + (e.iop - iostack);
- X *e.iop->argp = *argp;
- X e.iop->argp->afbuf = e.iop == &iostack[0] ? &mainbuf : &sharedbuf;
- X
- X if ((isatty (e.iop->argp->afile) == 0) &&
- X ((e.iop == &iostack[0]) ||
- X (lseek (e.iop->argp->afile, 0L, 1) != -1L)))
- X {
- X if (++bufid == AFID_NOBUF)
- X bufid = AFID_ID;
- X
- X e.iop->argp->afid = bufid;
- X }
- X }
- X
- X e.iop->prev = ~NL;
- X e.iop->peekc = 0;
- X e.iop->xchar = 0;
- X e.iop->nlcount = 0;
- X
- X if ((fn == filechar) || (fn == linechar))
- X e.iop->task = XIO;
- X
- X else if ((fn == gravechar) || (fn == qgravechar))
- X e.iop->task = XGRAVE;
- X
- X else
- X e.iop->task = XOTHER;
- X}
- X
- X/*
- X * Input generating functions
- X */
- X
- X/*
- X * Produce the characters of a string, then a newline, then EOF.
- X */
- Xint nlchar (iop)
- Xregister IO_State *iop;
- X{
- X register int c;
- X
- X if (iop->argp->aword == (char *)NULL)
- X return 0;
- X
- X if ((c = *iop->argp->aword++) == 0)
- X {
- X iop->argp->aword = (char *)NULL;
- X return NL;
- X }
- X
- X return c;
- X}
- X
- X/*
- X * Given a list of words, produce the characters
- X * in them, with a space after each word.
- X */
- X
- Xint wdchar (iop)
- Xregister IO_State *iop;
- X{
- X register char c;
- X register char **wl;
- X
- X if ((wl = iop->argp->awordlist) == (char **)NULL)
- X return 0;
- X
- X if (*wl != (char *)NULL)
- X {
- X if ((c = *(*wl)++) != 0)
- X return (c & 0177);
- X
- X iop->argp->awordlist++;
- X return SP;
- X }
- X
- X iop->argp->awordlist = (char **)NULL;
- X return NL;
- X}
- X
- X/*
- X * Return the characters of a list of words, producing a space between them.
- X */
- X
- Xint dol_char (iop)
- XIO_State *iop;
- X{
- X register char *wp;
- X char cflag;
- X
- X if ((wp = *(iop->argp->awordlist)++) != (char *)NULL)
- X {
- X if (*iop->argp->awordlist == (char *)NULL)
- X iop->dflag |= DSA_END;
- X
- X cflag = iop->dflag;
- X PUSHIO (aword, wp, dol1_char);
- X e.iop->dflag = cflag;
- X return -1;
- X }
- X
- X return 0;
- X}
- X
- X/* Return next character from the word with a space at the end */
- X
- Xstatic int dol1_char (iop)
- XIO_State *iop;
- X{
- X register int c;
- X
- X if ((iop->dflag & DSA_MODE) == DSA_AMP)
- X {
- X if (!(iop->dflag & DSA_START))
- X iop->dflag |= DSA_START;
- X
- X/* Has the previous word ended */
- X
- X else if (iop->dflag & DSA_START1)
- X {
- X iop->dflag &= ~DSA_START1;
- X return '"';
- X }
- X }
- X
- X if (iop->argp->aword == (char *)NULL)
- X return 0;
- X
- X if ((c = *iop->argp->aword) == '\0')
- X {
- X if ((iop->dflag & DSA_MODE) != DSA_AMP)
- X {
- X iop->argp->aword = (char *)NULL;
- X return (iop->dflag & DSA_END) ? 0 : SP;
- X }
- X
- X if (!(iop->dflag & DSA_END1))
- X {
- X iop->dflag |= DSA_END1;
- X return '"';
- X }
- X
- X iop->argp->aword = (char *)NULL;
- X iop->dflag &= ~DSA_END1;
- X iop->dflag |= DSA_START1;
- X return (iop->dflag & DSA_END) ? 0 : SP;
- X }
- X
- X iop->argp->aword++;
- X if ((iop->dflag != DSA_NULL) && any ((char)c, ifs->value))
- X c |= QUOTE;
- X
- X return c;
- X}
- X
- X/*
- X * Produce the characters from a single word (string).
- X */
- X
- Xint strchar (iop)
- XIO_State *iop;
- X{
- X register int c;
- X
- X return ((iop->argp->aword == (char *)NULL) ||
- X ((c = *(iop->argp->aword++)) == 0)) ? 0 : c;
- X}
- X
- X/*
- X * Produce quoted characters from a single word (string).
- X */
- X
- Xint qstrchar (iop)
- XIO_State *iop;
- X{
- X register int c;
- X
- X return ((iop->argp->aword == (char *)NULL) ||
- X ((c = *(iop->argp->aword++)) == 0)) ? 0 : (c | QUOTE);
- X}
- X
- X/*
- X * Return the characters from a file.
- X */
- X
- Xint filechar (iop)
- XIO_State *iop;
- X{
- X register IO_Args *ap = iop->argp;
- X register int i;
- X char c;
- X IO_Buf *bp = ap->afbuf;
- X
- X if (ap->afid != AFID_NOBUF)
- X {
- X if ((i = (ap->afid != bp->id)) || (bp->bufp == bp->ebufp))
- X {
- X if (i)
- X lseek (ap->afile, ap->afpos, SEEK_SET);
- X
- X if ((i = read (ap->afile, bp->buf, sizeof (bp->buf))) <= 0)
- X {
- X if (ap->afile > STDERR_FILENO)
- X S_close (ap->afile, TRUE);
- X
- X return 0;
- X }
- X
- X bp->id = ap->afid;
- X bp->ebufp = (bp->bufp = bp->buf) + i;
- X }
- X
- X ap->afpos++;
- X
- X return *bp->bufp++ & 0177;
- X }
- X
- X/* If this is the terminal, there is special input processing */
- X
- X else if ((ap->afile == 0) && isatty (ap->afile))
- X return Get_stdin (ap);
- X
- X if ((i = read (ap->afile, &c, sizeof(c))) == sizeof (c))
- X return (int)c & 0177;
- X
- X if (ap->afile > STDERR_FILENO)
- X S_close (ap->afile, TRUE);
- X
- X return 0;
- X}
- X
- X/*
- X * Return the characters from a here temp file.
- X */
- X
- Xstatic int herechar (iop)
- Xregister IO_State *iop;
- X{
- X char c;
- X
- X if (read (iop->argp->afile, &c, sizeof(c)) != sizeof(c))
- X {
- X S_close (iop->argp->afile, TRUE);
- X c = 0;
- X }
- X
- X return c;
- X}
- X
- X/*
- X * Return the characters produced by a process (`...`).
- X * Quote them if required, and remove any trailing newline characters.
- X */
- X
- Xint gravechar (iop)
- XIO_State *iop;
- X{
- X register int c;
- X
- X if ((c = qgravechar (iop) & ~QUOTE) == NL)
- X c = SP;
- X
- X return c;
- X}
- X
- X/*
- X * Process input from a `...` string
- X */
- X
- Xint qgravechar (iop)
- XIO_State *iop;
- X{
- X register int c;
- X
- X if (iop->xchar)
- X {
- X if (iop->nlcount)
- X {
- X iop->nlcount--;
- X return (NL | QUOTE);
- X }
- X
- X c = iop->xchar;
- X iop->xchar = 0;
- X }
- X
- X else if ((c = filechar (iop)) == NL)
- X {
- X iop->nlcount = 1;
- X
- X while ((c = filechar (iop)) == NL)
- X iop->nlcount++;
- X
- X iop->xchar = (char)c;
- X
- X if (c == 0)
- X return(c);
- X
- X iop->nlcount--;
- X c = NL;
- X }
- X
- X return (c != 0) ? (c | QUOTE): 0;
- X}
- X
- X/*
- X * Return a single command (usually the first line) from a file.
- X */
- X
- Xint linechar (iop)
- XIO_State *iop;
- X{
- X register int c;
- X
- X if ((c = filechar (iop)) == NL)
- X {
- X if (!multiline)
- X {
- X if (iop->argp->afile > STDERR_FILENO)
- X S_close (iop->argp->afile, TRUE);
- X
- X iop->argp->afile = -1; /* illegal value */
- X }
- X }
- X
- X return c;
- X}
- X
- Xvoid closeall ()
- X{
- X register int u;
- X
- X for (u = NUFILE; u < NOFILE;)
- X S_close (u++, TRUE);
- X}
- X
- X/*
- X * remap fd into Shell's fd space
- X */
- X
- Xint remap (fd)
- Xregister int fd;
- X{
- X register int i;
- X register int n_io = 0;
- X int map[NOFILE];
- X int o_fd = fd;
- X
- X if (fd < e.iofd)
- X {
- X do
- X {
- X map[n_io++] = fd;
- X fd = dup (fd);
- X
- X } while ((fd >= 0) && (fd < e.iofd));
- X
- X for (i = 0; i < n_io; i++)
- X close (map[i]);
- X
- X S_Remap (o_fd, fd);
- X S_close (o_fd, TRUE);
- X
- X if (fd < 0)
- X print_error ("sh: too many files open\n");
- X }
- X
- X return fd;
- X}
- X
- X/*
- X * here documents
- X */
- X
- Xvoid markhere (s, iop)
- Xregister char *s;
- XIO_Actions *iop;
- X{
- X register Here_D *h, *lh;
- X
- X if ((h = (Here_D *) space(sizeof(Here_D))) == (Here_D *)NULL)
- X return;
- X
- X if ((h->h_tag = evalstr (s, DOSUB)) == (char *)NULL)
- X return;
- X
- X h->h_iop = iop;
- X iop->io_name = (char *)NULL;
- X h->h_next = (Here_D *)NULL;
- X
- X if (inhere == (Here_D *)NULL)
- X inhere = h;
- X
- X else
- X {
- X for (lh = inhere; lh != (Here_D *)NULL; lh = lh->h_next)
- X {
- X if (lh->h_next == (Here_D *)NULL)
- X {
- X lh->h_next = h;
- X break;
- X }
- X }
- X }
- X
- X iop->io_flag |= IOHERE|IOXHERE;
- X
- X for (s = h->h_tag; *s; s++)
- X {
- X if (*s & QUOTE)
- X {
- X iop->io_flag &= ~ IOXHERE;
- X *s &= ~ QUOTE;
- X }
- X }
- X
- X h->h_dosub = iop->io_flag & IOXHERE;
- X}
- X
- Xvoid gethere ()
- X{
- X register Here_D *h, *hp;
- X
- X/* Scan here files first leaving inhere list in place */
- X
- X for (hp = h = inhere; h != (Here_D *)NULL; hp = h, h = h->h_next)
- X readhere (&h->h_iop->io_name, h->h_tag, h->h_dosub ? 0 : '\'');
- X
- X/* Make inhere list active - keep list intact for scraphere */
- X
- X if (hp != (Here_D *)NULL)
- X {
- X hp->h_next = acthere;
- X acthere = inhere;
- X inhere = (Here_D *)NULL;
- X }
- X}
- X
- Xstatic void readhere (name, s, ec)
- Xchar **name;
- Xregister char *s;
- X{
- X int tf;
- X register int c;
- X jmp_buf ev;
- X char *line;
- X char *next;
- X
- X *name = strsave (g_tempname (), areanum);
- X
- X if ((tf = S_open (FALSE, *name, O_CMASK | O_NOINHERIT, 0600)) < 0)
- X return;
- X
- X if (newenv (setjmp (errpt = ev)) == TRUE)
- X S_Delete (tf);
- X
- X else
- X {
- X line = space (LINE_MAX + 1);
- X pushio (e.iop->argp, e.iop->iofn);
- X e.iobase = e.iop;
- X
- X while (1)
- X {
- X if (talking && e.iop <= iostack)
- X put_prompt (ps2->value);
- X
- X next = line;
- X while ((c = Getc (ec)) != NL && c)
- X {
- X if (ec == '\'')
- X c &= ~ QUOTE;
- X
- X if (next >= &line[LINE_MAX])
- X {
- X c = 0;
- X break;
- X }
- X
- X *next++ = (char)c;
- X }
- X
- X *next = 0;
- X if (strcmp (s, line) == 0 || c == 0)
- X break;
- X
- X *next++ = NL;
- X write (tf, line, (int)(next-line));
- X }
- X
- X if (c == 0)
- X print_error ("here document `%s' unclosed\n", s);
- X
- X quitenv ();
- X }
- X
- X S_close (tf, TRUE);
- X}
- X
- X/*
- X * open here temp file.
- X * If unquoted here, expand here temp file into second temp file.
- X */
- X
- Xint herein (hname, xdoll)
- Xchar *hname;
- Xint xdoll;
- X{
- X register int hf, tf;
- X
- X if (hname == (char *)NULL)
- X return -1;
- X
- X if ((hf = S_open (FALSE, hname, O_RDONLY)) < 0)
- X return -1;
- X
- X if (xdoll)
- X {
- X char c;
- X char *tname = g_tempname();
- X jmp_buf ev;
- X
- X if ((tf = S_open (FALSE, tname, O_CMASK | O_NOINHERIT, 0600)) < 0)
- X return -1;
- X
- X if (newenv (setjmp (errpt = ev)) == FALSE)
- X {
- X PUSHIO (afile, hf, herechar);
- X e.iobase = e.iop;
- X
- X while ((c = (char)subgetc(0, 0)) != 0)
- X {
- X c &= ~ QUOTE;
- X write (tf, &c, sizeof c);
- X }
- X
- X quitenv ();
- X }
- X
- X else
- X S_Delete (tf);
- X
- X S_close (tf, TRUE);
- X return S_open (TRUE, tname, O_RDONLY);
- X }
- X
- X else
- X return hf;
- X}
- X
- Xvoid scraphere()
- X{
- X register Here_D *h;
- X
- X for (h = inhere; h != (Here_D *)NULL; h = h->h_next)
- X {
- X if ((h->h_iop != (IO_Actions *)NULL) &&
- X (h->h_iop->io_name != (char *)NULL))
- X unlink (h->h_iop->io_name);
- X }
- X
- X inhere = (Here_D *)NULL;
- X}
- X
- X/* unlink here temp files before a freearea (area) */
- X
- Xvoid freehere (area)
- Xint area;
- X{
- X register Here_D *h;
- X register Here_D *hl = (Here_D *)NULL;
- X
- X for (h = acthere; h != (Here_D *)NULL; hl = h, h = h->h_next)
- X {
- X if (getarea ((char *)h) >= area)
- X {
- X if (h->h_iop->io_name != (char *)NULL)
- X unlink (h->h_iop->io_name);
- X
- X if (hl == (Here_D *)NULL)
- X acthere = h->h_next;
- X
- X else
- X hl->h_next = h->h_next;
- X }
- X }
- X}
- X
- Xchar *g_tempname ()
- X{
- X static char tmpfile[FFNAME_MAX];
- X char *tmpdir; /* Points to directory prefix of pipe */
- X static int temp_count = 0;
- X
- X/* Find out where we should put temporary files */
- X
- X if ((tmpdir = lookup ("TMPDIR", FALSE)->value) == null)
- X tmpdir = lookup ("TMP", FALSE)->value;
- X
- X/* Get a unique temporary file name */
- X
- X while (1)
- X {
- X sprintf (tmpfile, "%s/sht%.5u.tmp", tmpdir, temp_count++);
- X
- X if (access (tmpfile, F_OK) != 0)
- X break;
- X }
- X
- X return tmpfile;
- X}
- SHAR_EOF
- chmod 0644 shell/sh5.c || echo "restore of shell/sh5.c fails"
- set `wc -c shell/sh5.c`;Sum=$1
- if test "$Sum" != "14249"
- then echo original size 14249, current size $Sum;fi
- echo "x - extracting shell/sh6.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > shell/sh6.c &&
- X/* MS-DOS SHELL - Data Declarations
- X *
- X * MS-DOS SHELL - Copyright (c) 1990 Data Logic Limited and Charles Forsyth
- X *
- X * This code is based on (in part) the shell program written by Charles
- X * Forsyth and is subject to the following copyright restrictions:
- X *
- X * 1. Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice is duplicated in the
- X * source form and the copyright notice in file sh6.c is displayed
- X * on entry to the program.
- X *
- X * 2. The sources (or parts thereof) or objects generated from the sources
- X * (or parts of sources) cannot be sold under any circumstances.
- X *
- X * $Header: sh6.c 1.1 90/01/25 13:42:04 MS_user Exp $
- X *
- X * $Log: sh6.c $
- X * Revision 1.1 90/01/25 13:42:04 MS_user
- X * Initial revision
- X *
- X */
- X
- X#include <sys/types.h>
- X#include <stddef.h>
- X#include <signal.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include <stdlib.h>
- X#include <limits.h>
- X#include <unistd.h>
- X#include "sh.h"
- X
- Xchar *Copy_Right1 = "MS-DOS SH Version 1.4\341 (DOS %d.%d)\n";
- Xchar *Copy_Right2 = "Copyright (c) Data Logic Ltd and Charles Forsyth 1990\n";
- Xchar **dolv; /* Parameter array */
- Xint dolc; /* Number of entries in parameter array */
- Xint exstat; /* Exit status */
- Xchar gflg;
- Xint fn_area_number = -1; /* Next function area number */
- Xint talking; /* interactive (talking-type wireless) */
- Xint execflg; /* Exec mode */
- Xint multiline; /* \n changed to ; */
- Xint Current_Event = 0; /* Current history event */
- Xint *failpt; /* Current fail point jump address */
- Xint *errpt; /* Current error point jump address */
- X /* Swap mode */
- Xint Swap_Mode = SWAP_EXPAND | SWAP_DISK;
- XBreak_C *Break_List; /* Break list for FOR/WHILE */
- XBreak_C *Return_List; /* Return list for RETURN */
- XBreak_C *SShell_List; /* SubShell list for EXIT */
- Xbool level0 = FALSE; /* Level Zero flag */
- Xbool r_flag = FALSE; /* Restricted shell */
- X /* History processing enabled flag */
- Xbool History_Enabled = FALSE;
- XFun_Ops *fun_list = (Fun_Ops *)NULL; /* Function list */
- XSave_IO *SSave_IO; /* Save IO array */
- Xint NSave_IO_E = 0; /* Number of entries in Save IO array */
- Xint MSave_IO_E = 0; /* Max Number of entries in SSave_IO */
- XS_SubShell *SubShells; /* Save Vars array */
- Xint NSubShells = 0; /* Number of entries in SubShells */
- Xint MSubShells = 0; /* Max Number of entries in SubShells */
- X
- XWord_B *wdlist; /* Current Word List */
- XWord_B *iolist; /* Current IO List */
- Xlong ourtrap = 0L; /* Signal detected */
- Xint trapset; /* Trap pending */
- Xint yynerrs; /* yacc errors detected */
- Xint Execute_stack_depth; /* execute function recursion */
- X /* depth */
- XVar_List *vlist = (Var_List *)NULL; /* dictionary */
- SHAR_EOF
- echo "End of part 3"
- echo "File shell/sh6.c is continued in part 4"
- echo "4" > s2_seq_.tmp
- exit 0
-
- --
- Regards,
-
- Ian Stewartson
- Data Logic Ltd.
-
-
-