home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-02-21 | 79.0 KB | 4,234 lines |
-
- #!/bin/sh
- # this is part 4 of a multipart archive
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file shell/sh6.c continued
- #
- CurArch=4
- 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/sh6.c"
- sed 's/^X//' << 'SHAR_EOF' >> shell/sh6.c
- XVar_List *path; /* search path for commands */
- XVar_List *ps1; /* Prompt 1 */
- XVar_List *ps2; /* Prompt 2 */
- XVar_List *C_dir; /* Current directory */
- Xchar *last_prompt; /* Last prompt output */
- XVar_List *ifs; /* Inter-field separator */
- Xchar *home = "HOME";
- Xchar *shell = "SHELL";
- Xchar *history_file = "HISTFILE";
- Xchar *hsymbol = "#";
- Xchar *msymbol = "-";
- Xchar *spcl2 = "$`'\"";
- X
- X /* I/O stacks */
- XIO_Args ioargstack[NPUSH];
- XIO_State iostack[NPUSH];
- X
- X /* Temporary I/O argument */
- XIO_Args temparg = {
- X (char *)NULL, /* Word */
- X (char **)NULL, /* Word list */
- X 0, /* File descriptor */
- X AFID_NOBUF, /* Buffer id */
- X 0L, /* File position */
- X (IO_Buf *)NULL /* Buffer */
- X};
- X
- Xint areanum; /* Current allocation area */
- Xint inparse; /* In parser flag */
- Xlong flags = 0L; /* Command line flags */
- Xchar *null = "";
- X
- X /* Current environment */
- XEnviron e = {
- X (char *)NULL, /* Current line buffer */
- X (char *)NULL, /* Current pointer in line */
- X (char *)NULL, /* End of line pointer */
- X iostack, /* I/O Stack pointers */
- X iostack - 1,
- X (int *)NULL,
- X FDBASE, /* Base file handler */
- X (Environ *)NULL /* Previous Env pointer */
- X};
- SHAR_EOF
- echo "File shell/sh6.c is complete"
- chmod 0644 shell/sh6.c || echo "restore of shell/sh6.c fails"
- set `wc -c shell/sh6.c`;Sum=$1
- if test "$Sum" != "3994"
- then echo original size 3994, current size $Sum;fi
- echo "x - extracting shell/sh7.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > shell/sh7.c &&
- X/* MS-DOS SHELL - Internal Command Processing
- 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: sh7.c 1.1 90/01/29 17:46:25 MS_user Exp $
- X *
- X * $Log: sh7.c $
- X * Revision 1.1 90/01/29 17:46:25 MS_user
- X * Initial revision
- X *
- 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#include <stdarg.h>
- X#include "sh.h"
- X
- X#define SECS 60L
- X#define MINS 3600L
- X#define IS_OCTAL(a) (((a) >= '0') && ((a) <= '7'))
- X
- X/* Definitions for test */
- X
- X#define END_OF_INPUT 0
- X#define FILE_READABLE 1
- X#define FILE_WRITABLE 2
- X#define FILE_REGULAR 3
- X#define FILE_DIRECTORY 4
- X#define FILE_NONZERO 5
- X#define FILE_TERMINAL 6
- X#define STRING_ZERO 7
- X#define STRING_NONZERO 8
- X#define STRING_EQUAL 9
- X#define STRING_NOTEQUAL 10
- X#define NUMBER_EQUAL 11
- X#define NUMBER_NOTEQUAL 12
- X#define NUMBER_EQ_GREAT 13
- X#define NUMBER_GREATER 14
- X#define NUMBER_EQ_LESS 15
- X#define NUMBER_LESS 16
- X#define UNARY_NOT 17
- X#define BINARY_AND 18
- X#define BINARY_OR 19
- X#define LPAREN 20
- X#define RPAREN 21
- X#define OPERAND 22
- X#define FILE_EXECUTABLE 23
- X#define FILE_USER 24
- X#define FILE_GROUP 25
- X#define FILE_TEXT 26
- X#define FILE_BLOCK 27
- X#define FILE_CHARACTER 28
- X#define FILE_FIFO 29
- X
- X#define UNARY_OP 1
- X#define BINARY_OP 2
- X#define B_UNARY_OP 3
- X#define B_BINARY_OP 4
- X#define PAREN 5
- X
- Xstatic struct test_op {
- X char *op_text;
- X short op_num;
- X short op_type;
- X} test_ops[] = {
- X {"-r", FILE_READABLE, UNARY_OP},
- X {"-w", FILE_WRITABLE, UNARY_OP},
- X {"-x", FILE_EXECUTABLE, UNARY_OP},
- X {"-f", FILE_REGULAR, UNARY_OP},
- X {"-d", FILE_DIRECTORY, UNARY_OP},
- X {"-s", FILE_NONZERO, UNARY_OP},
- X {"-t", FILE_TERMINAL, UNARY_OP},
- X {"-z", STRING_ZERO, UNARY_OP},
- X {"-n", STRING_NONZERO, UNARY_OP},
- X {"=", STRING_EQUAL, BINARY_OP},
- X {"!=", STRING_NOTEQUAL, BINARY_OP},
- X {"-eq", NUMBER_EQUAL, BINARY_OP},
- X {"-ne", NUMBER_NOTEQUAL, BINARY_OP},
- X {"-ge", NUMBER_EQ_GREAT, BINARY_OP},
- X {"-gt", NUMBER_GREATER, BINARY_OP},
- X {"-le", NUMBER_EQ_LESS, BINARY_OP},
- X {"-lt", NUMBER_LESS, BINARY_OP},
- X {"!", UNARY_NOT, B_UNARY_OP},
- X {"-a", BINARY_AND, B_BINARY_OP},
- X {"-o", BINARY_OR, B_BINARY_OP},
- X {"(", LPAREN, PAREN},
- X {")", RPAREN, PAREN},
- X#ifdef S_IFCHR
- X {"-c", FILE_CHARACTER, UNARY_OP},
- X#endif
- X#ifdef S_IFBLK
- X {"-b", FILE_BLOCK, UNARY_OP},
- X#endif
- X#ifdef S_ISUID
- X {"-u", FILE_USER, UNARY_OP},
- X#endif
- X#ifdef S_ISGID
- X {"-g", FILE_GROUP, UNARY_OP},
- X#endif
- X#ifdef S_ISVTX
- X {"-k", FILE_TEXT, UNARY_OP},
- X#endif
- X#ifdef S_IFIFO
- X {"-p", FILE_FIFO, UNARY_OP},
- X#endif
- X {(char *)NULL, NULL, NULL}
- X};
- X
- Xstatic int expr (int);
- Xstatic int bexpr (int);
- Xstatic int primary (int);
- Xstatic int lex (char *);
- Xstatic long num (char *);
- Xstatic void syntax (void);
- Xstatic int dolabel (C_Op *);
- Xstatic int dochdir (C_Op *);
- Xstatic int dodrive (C_Op *);
- Xstatic int doshift (C_Op *);
- Xstatic int doumask (C_Op *);
- Xstatic int dodot (C_Op *);
- Xstatic int doecho (C_Op *);
- Xstatic int dogetopt (C_Op *);
- Xstatic int dopwd (C_Op *);
- Xstatic int doswap (C_Op *);
- Xstatic int dounset (C_Op *);
- Xstatic int dotype (C_Op *);
- Xstatic int dotest (C_Op *);
- Xstatic int dover (C_Op *);
- Xstatic int doread (C_Op *);
- Xstatic int doeval (C_Op *);
- Xstatic int dotrap (C_Op *);
- Xstatic int getsig (char *);
- Xstatic int dobreak (C_Op *);
- Xstatic int docontinue (C_Op *);
- Xstatic int brkcontin (char *, int);
- Xstatic int doexit (C_Op *);
- Xstatic int doexec (C_Op *);
- Xstatic int doreturn (C_Op *);
- Xstatic int doexport (C_Op *);
- Xstatic int domsdos (C_Op *);
- Xstatic int doreadonly (C_Op *);
- Xstatic int doset (C_Op *);
- Xstatic int dohistory (C_Op *);
- Xstatic void setsig (int, int (*)());
- Xstatic int rdexp (char **, int, char *);
- Xstatic void v1_putsn (char *, int);
- X
- Xstatic char **test_alist;
- Xstatic struct test_op *test_op;
- Xstatic jmp_buf test_jmp;
- X
- X/*
- X * built-in commands: doX
- X */
- X
- Xstatic int dolabel (t)
- XC_Op *t;
- X{
- X return 0;
- X}
- X
- X/*
- X * Getopt - split arguments. getopts pattern args
- X */
- X
- Xstatic int dogetopt (t)
- Xregister C_Op *t;
- X{
- X int argc;
- X char **argv = t->words;
- X int c;
- X
- X/* Count arguments */
- X
- X optind = 1; /* Reset the optind flag */
- X opterr = 1; /* Reset the error flag */
- X
- X for (argc = 0; t->words[argc] != (char *)NULL; argc++);
- X
- X if (argc < 2)
- X {
- X S_puts ("usage: getopt legal-args $*\n");
- X return 2;
- X }
- X
- X argc -= 2;
- X argv += 2;
- X
- X/* Scan each argument */
- X
- X while ((c = getopt (argc, argv, t->words[1])) != EOF)
- X {
- X if (c == '?')
- X return 2;
- X
- X v1printf ("-%c ", c);
- X
- X/* Check for addition parameter */
- X
- X if (*(strchr (t->words[1], c) + 1) == ':')
- X {
- X v1_puts (optarg);
- X v1_putc (SP);
- X }
- X }
- X
- X v1_puts ("-- ");
- X argv += optind;
- X
- X while (optind++ < argc)
- X {
- X v1_puts (*argv++);
- X v1_putc ((char)((optind == argc) ? NL : SP));
- X }
- X
- X return 0;
- X}
- X
- X/*
- X * Echo the parameters
- X */
- X
- Xstatic int doecho (t)
- Xregister C_Op *t;
- X{
- X int n = 1;
- X int no_eol = 0; /* No EOL */
- X char *ip; /* Input pointer */
- X int c_val; /* Current character */
- X char c;
- X bool end_s;
- X char *cp = e.linep;
- X /* Always leave room for NL */
- X char *ep = &e.linep[LINE_MAX - 3];
- X
- X while ((ip = t->words[n++]) != (char *)NULL)
- X {
- X if ((n == 2) && (strcmp (ip, "-n") == 0))
- X {
- X no_eol++;
- X continue;
- X }
- X
- X/* Process the string */
- X
- X end_s = FALSE;
- X
- X do
- X {
- X
- X/* Any special character processing ? */
- X
- X if ((c = *(ip++)) == '\\')
- X {
- X if ((c_val = Process_Escape (&ip)) == -1)
- X {
- X no_eol = 1;
- X continue;
- X }
- X
- X c = (char)c_val;
- X }
- X
- X/* End of string - check to see if a space if required */
- X
- X else if (c == 0)
- X {
- X end_s = TRUE;
- X
- X if (t->words[n] != (char *)NULL)
- X c = SP;
- X
- X else
- X continue;
- X }
- X
- X/* Output the character */
- X
- X if (cp < ep)
- X *(cp++) = c;
- X
- X else
- X {
- X v1_putsn (e.linep, (int)(cp - e.linep));
- X cp = e.linep;
- X }
- X
- X } while (!end_s);
- X }
- X
- X/* Is EOL required ? */
- X
- X if (!no_eol)
- X *(cp++) = NL;
- X
- X/* Flush buffer */
- X
- X if ((n = (int)(cp - e.linep)))
- X v1_putsn (e.linep, n);
- X
- X return 0;
- X}
- X
- X/*
- X * Process_Escape - Convert an escaped character to a binary value.
- X *
- X * Returns the binary value and updates the string pointer.
- X */
- X
- Xint Process_Escape (cp)
- Xchar **cp; /* Pointer to character */
- X{
- X int c_val = **cp; /* Current character */
- X
- X if (c_val)
- X (*cp)++;
- X
- X/* Process escaped characters */
- X
- X switch (c_val)
- X {
- X case 'b': /* Backspace */
- X return 0x08;
- X
- X case 'f': /* Form Feed */
- X return 0x0c;
- X
- X case 'v': /* Vertical Tab */
- X return 0x0b;
- X
- X case 'n': /* New Line */
- X return 0x0a;
- X
- X case 'r': /* Carriage return */
- X return 0x0d;
- X
- X case 't': /* Forward tab */
- X return 0x09;
- X
- X case '\\': /* Backslash */
- X return '\\';
- X
- X case 'c': /* no eol */
- X return -1;
- X }
- X
- X/* Check for an octal string */
- X
- X if ((c_val >= 0) && (c_val < 8))
- X {
- X while ((IS_OCTAL (**cp)))
- X c_val = (c_val * 8) + *((*cp)++) - '0';
- X
- X return c_val;
- X }
- X
- X return c_val;
- X}
- X
- X/*
- X * Display the current version
- X */
- X
- Xstatic int dover (t)
- XC_Op *t;
- X{
- X v1printf (Copy_Right1, _osmajor, _osminor);
- X v1a_puts (Copy_Right2);
- X return 0;
- X}
- X
- Xstatic char *swap_device[] = {"disk", "extend", "expand"};
- X
- X/*
- X * Modify swapping information: swap options
- X */
- X
- Xstatic int doswap (t)
- Xregister C_Op *t;
- X{
- X register int n = 1;
- X char *cp;
- X
- X/* Display current values ? */
- X
- X if (t->words[1] == (char *)NULL)
- X {
- X if (Swap_Mode == SWAP_OFF)
- X v1a_puts ("Swapping disabled");
- X
- X else
- X {
- X register int j;
- X
- X v1_puts ("Swap devices: ");
- X
- X for (j = 0, n = 1; j < 3; ++j, n <<= 1)
- X {
- X if (Swap_Mode & n)
- X {
- X v1printf ("%s ", swap_device[j]);
- X
- X if (n == SWAP_EXTEND)
- X v1printf ("(0x%.6lx) ", SW_EMstart);
- X }
- X }
- X
- X v1_putc (NL);
- X }
- X
- X return 0;
- X }
- X
- X/* Set up new values */
- X
- X Swap_Mode = SWAP_OFF;
- X
- X while ((cp = t->words[n++]) != (char *)NULL)
- X {
- X if (strcmp (cp, "off") == 0)
- X Swap_Mode = SWAP_OFF;
- X
- X else if (strcmp (cp, "on") == 0)
- X Swap_Mode = SWAP_DISK | SWAP_EXPAND | SWAP_EXTEND;
- X
- X/* Scan for valid arguments */
- X
- X else
- X {
- X register int j, k;
- X
- X for (j = 0, k = 1; j < 3; ++j, k <<= 1)
- X {
- X if (strcmp (cp, swap_device[j]) == 0)
- X {
- X Swap_Mode |= k;
- X
- X/* If extended memory, they can specify the start address as a hex number */
- X
- X if (k == SWAP_EXTEND)
- X {
- X char *sp;
- X long start;
- X
- X/* Check for not changed */
- X
- X if ((sp = t->words[n]) == (char *)NULL)
- X break;
- X
- X/* Convert hex number */
- X
- X start = strtol (sp, &sp, 16);
- X
- X/* If not completely a hex number, ignore */
- X
- X if (*sp)
- X break;
- X
- X/* Set used and saved new value */
- X
- X SW_EMstart = start;
- X ++n;
- X
- X if ((SW_EMstart < 0x100000L) ||
- X (SW_EMstart > 0xf00000L))
- X SW_EMstart = 0x100000L;
- X
- X v1printf ("Extend memory start set to 0x%.6lx\n",
- X SW_EMstart);
- X }
- X
- X break;
- X }
- X }
- X }
- X }
- X
- X return 0;
- X}
- X
- X/*
- X * Output the current path: pwd
- X */
- X
- Xstatic int dopwd (t)
- Xregister C_Op *t;
- X{
- X v1a_puts (C_dir->value);
- X return 0;
- X}
- X
- X/*
- X * Unset a variable: unset <flag..> <variable name...>
- X */
- X
- Xstatic int dounset (t)
- Xregister C_Op *t;
- X{
- X register int n = 1;
- X
- X while (t->words[n] != (char *)NULL)
- X unset (t->words[n++], FALSE);
- X
- X return 0;
- X}
- X
- X/* Delete a variable or function. If all is set, system variables can be
- X * deleted. This is used to delete the trap functions
- X */
- X
- Xvoid unset (cp, all)
- Xregister char *cp;
- Xbool all;
- X{
- X register Var_List *vp;
- X register Var_List *pvp;
- X
- X/* Unset a flag */
- X
- X if (*cp == '-')
- X {
- X while (*(++cp) != 0)
- X {
- X if (islower (*cp))
- X FL_CLEAR (*cp);
- X }
- X
- X setdash ();
- X return;
- X }
- X
- X/* Ok - unset a variable and not a local value */
- X
- X if (!all && !(isalpha (*cp)))
- X return;
- X
- X/* Check in list */
- X
- X pvp = (Var_List *)NULL;
- X
- X for (vp = vlist; (vp != (Var_List *)NULL) && !eqname (vp->name, cp);
- X vp = vp->next)
- X pvp = vp;
- X
- X/* If not found, delete the function if it exists */
- X
- X if (vp == (Var_List *)NULL)
- X {
- X Fun_Ops *fp;
- X
- X if ((fp = Fun_Search (cp)) != (Fun_Ops *)NULL)
- X Save_Function (fp->tree, TRUE);
- X
- X return;
- X }
- X
- X/* Error if read-only */
- X
- X if (vp->status & (RONLY | PONLY))
- X {
- X if ((cp = strchr (vp->name, '=')) != (char *)NULL)
- X *cp = 0;
- X
- X S_puts (vp->name);
- X
- X if (cp != (char *)NULL)
- X *cp = '=';
- X
- X S_puts ((vp->status & PONLY) ? ": cannot unset\n" : " is read-only\n");
- X return;
- X }
- X
- X/* Delete it */
- X
- X if (vp->status & GETCELL)
- X DELETE (vp->name);
- X
- X if (pvp == (Var_List *)NULL)
- X vlist = vp->next;
- X
- X else
- X pvp->next = vp->next;
- X
- X DELETE (vp);
- X}
- X
- X/*
- X * Execute a test: test <arguments>
- X */
- X
- Xstatic int dotest (t)
- Xregister C_Op *t;
- X{
- X int st = 0;
- X
- X if (*(test_alist = &t->words[1]) == (char *)NULL)
- X return 1;
- X
- X/* If [ <arguments> ] form, check for end ] and remove it */
- X
- X if (strcmp (t->words[0], "[") == 0)
- X {
- X while (t->words[++st] != (char *)NULL)
- X ;
- X
- X if (strcmp (t->words[--st], "]") != 0)
- X {
- X print_error ("test: missing ']'\n");
- X return 1;
- X }
- X
- X else
- X t->words[st] = (char *)NULL;
- X }
- X
- X/* Set abort address */
- X
- X if (setjmp (test_jmp))
- X return 1;
- X
- X st = !expr (lex (*test_alist));
- X
- X if (*(++test_alist) != (char *)NULL)
- X syntax ();
- X
- X return (st);
- X}
- X
- Xstatic int expr (n)
- Xint n;
- X{
- X int res;
- X
- X if (n == END_OF_INPUT)
- X syntax ();
- X
- X res = bexpr (n);
- X
- X if (lex (*(++test_alist)) == BINARY_OR)
- X return expr (lex (*(++test_alist))) || res;
- X
- X test_alist--;
- X return res;
- X}
- X
- Xstatic int bexpr (n)
- Xint n;
- X{
- X int res;
- X
- X if (n == END_OF_INPUT)
- X syntax ();
- X
- X res = primary (n);
- X if (lex (*(++test_alist)) == BINARY_AND)
- X return bexpr (lex (*(++test_alist))) && res;
- X
- X test_alist--;
- X return res;
- X}
- X
- Xstatic int primary (n)
- Xint n;
- X{
- X register char *opnd1, *opnd2;
- X struct stat s;
- X int res;
- X
- X if (n == END_OF_INPUT)
- X syntax ();
- X
- X if (n == UNARY_NOT)
- X return !expr (lex (*(++test_alist)));
- X
- X if (n == LPAREN)
- X {
- X res = expr (lex (*(++test_alist)));
- X
- X if (lex (*(++test_alist)) != RPAREN)
- X syntax ();
- X
- X return res;
- X }
- X
- X if (n == OPERAND)
- X {
- X opnd1 = *test_alist;
- X (void) lex (*(++test_alist));
- X
- X if ((test_op != (C_Op *)NULL) && test_op->op_type == BINARY_OP)
- X {
- X struct test_op *op = test_op;
- X
- X if ((opnd2 = *(++test_alist)) == (char *)NULL)
- X syntax ();
- X
- X switch (op->op_num)
- X {
- X case STRING_EQUAL:
- X return strcmp (opnd1, opnd2) == 0;
- X
- X case STRING_NOTEQUAL:
- X return strcmp (opnd1, opnd2) != 0;
- X
- X case NUMBER_EQUAL:
- X return num (opnd1) == num (opnd2);
- X
- X case NUMBER_NOTEQUAL:
- X return num (opnd1) != num (opnd2);
- X
- X case NUMBER_EQ_GREAT:
- X return num (opnd1) >= num (opnd2);
- X
- X case NUMBER_GREATER:
- X return num (opnd1) > num (opnd2);
- X
- X case NUMBER_EQ_LESS:
- X return num (opnd1) <= num (opnd2);
- X
- X case NUMBER_LESS:
- X return num (opnd1) < num (opnd2);
- X }
- X }
- X
- X test_alist--;
- X return strlen (opnd1) > 0;
- X }
- X
- X/* unary expression */
- X
- X if (test_op->op_type != UNARY_OP || *++test_alist == 0)
- X syntax ();
- X
- X switch (n)
- X {
- X case STRING_ZERO:
- X return strlen (*test_alist) == 0;
- X
- X case STRING_NONZERO:
- X return strlen (*test_alist) != 0;
- X
- X case FILE_READABLE:
- X return access (*test_alist, R_OK) == 0;
- X
- X case FILE_WRITABLE:
- X return access (*test_alist, W_OK) == 0;
- X
- X case FILE_EXECUTABLE:
- X return access (*test_alist, X_OK) == 0;
- X
- X case FILE_REGULAR:
- X return stat (*test_alist, &s) == 0 && S_ISREG(s.st_mode);
- X
- X case FILE_DIRECTORY:
- X return stat (*test_alist, &s) == 0 && S_ISDIR(s.st_mode);
- X
- X case FILE_NONZERO:
- X return stat (*test_alist, &s) == 0 && (s.st_size > 0L);
- X
- X case FILE_TERMINAL:
- X return isatty ((int)num (*test_alist));
- X
- X#ifdef S_ISUID
- X case FILE_USER:
- X return stat (*test_alist, &s) == 0 && (s.st_mode & S_ISUID);
- X#endif
- X
- X#ifdef S_ISGID
- X case FILE_GROUP:
- X return stat (*test_alist, &s) == 0 && (s.st_mode & S_ISGID);
- X#endif
- X
- X#ifdef S_ISVTX
- X case FILE_TEXT:
- X return stat (*test_alist, &s) == 0 && (s.st_mode & S_ISVTX);
- X#endif
- X
- X#ifdef S_IFBLK
- X case FILE_BLOCK:
- X return stat (*test_alist, &s) == 0 && S_ISBLK(s.st_mode);
- X#endif
- X
- X#ifdef S_IFCHR
- X case FILE_CHARACTER:
- X return stat (*test_alist, &s) == 0 && S_ISCHR(s.st_mode);
- X#endif
- X
- X#ifdef S_IFIFO
- X case FILE_FIFO:
- X return stat (*test_alist, &s) == 0 && S_ISFIFO(s.st_mode);
- X#endif
- X }
- X}
- X
- Xstatic int lex (s)
- Xregister char *s;
- X{
- X register struct test_op *op = test_ops;
- X
- X if (s == (char *)NULL)
- X return END_OF_INPUT;
- X
- X while (op->op_text)
- X {
- X if (strcmp (s, op->op_text) == 0)
- X {
- X test_op = op;
- X return op->op_num;
- X }
- X
- X op++;
- X }
- X
- X test_op = (struct test_op *)NULL;
- X return OPERAND;
- X}
- X
- X/*
- X * Get a long numeric value
- X */
- X
- Xstatic long num (s)
- Xregister char *s;
- X{
- X char *ep;
- X long l = strtol (s, &ep, 10);
- X
- X if (!*s || *ep)
- X syntax ();
- X
- X return l;
- X}
- X
- X/*
- X * test syntax error - abort
- X */
- X
- Xstatic void syntax ()
- X{
- X print_error ("test: syntax error\n");
- X longjmp (test_jmp, 1);
- X}
- X
- X/*
- X * Select a new drive: x:
- X *
- X * Select the drive, get the current directory and check that we have
- X * actually selected the drive
- X */
- X
- Xstatic int dodrive (t)
- Xregister C_Op *t;
- X{
- X unsigned int cdrive;
- X unsigned int ndrive = tolower (**t->words) - 'a' + 1;
- X
- X _dos_setdrive (ndrive, &cdrive);
- X Getcwd ();
- X _dos_getdrive (&cdrive);
- X return (ndrive == cdrive) ? 0 : 1;
- X}
- X
- X/*
- X * Select a new directory: cd
- X */
- X
- Xstatic int dochdir (t)
- Xregister C_Op *t;
- X{
- X char *p;
- X char *nd;
- X register char *cp;
- X int first = 0;
- X unsigned int dummy;
- X unsigned int cdrive;
- X
- X/* If restricted shell - illegal */
- X
- X if (check_rsh ("cd"))
- X return 1;
- X
- X/* Use default ? */
- X
- X if (((p = t->words[1]) == (char *)NULL) &&
- X ((p = lookup (home, FALSE)->value) == null))
- X {
- X print_error ("cd: no home directory\n");
- X return 1;
- X }
- X
- X/* Save the current drive */
- X
- X _dos_getdrive (&cdrive);
- X
- X/* Scan for the directory. If there is not a / or : at start, use the
- X * CDPATH variable
- X */
- X
- X cp = (*p == '/') ? null : lookup ("CDPATH", FALSE)->value;
- X cp = (*(p + 1) == ':') ? null : cp;
- X
- X do
- X {
- X cp = path_append (cp, p, e.linep);
- X
- X/* Check for new disk drive */
- X
- X nd = e.linep;
- X
- X if (*(nd+ 1) == ':')
- X {
- X _dos_setdrive (tolower (*nd) - 'a' + 1, &dummy);
- X nd += 2;
- X }
- X
- X/* Was the change successful? */
- X
- X if ((!*nd) || (chdir (nd) == 0))
- X {
- X
- X/* OK - reset the current directory (in the shell) and display the new
- X * path if appropriate
- X */
- X
- X Getcwd ();
- X
- X if (first || (strchr (p, '/') != (char *)NULL))
- X dopwd (t);
- X
- X return 0;
- X }
- X
- X first = 1;
- X
- X } while (cp != (char *)NULL);
- X
- X/* Restore our original drive and restore directory info */
- X
- X _dos_setdrive (cdrive, &dummy);
- X Getcwd ();
- X
- X print_error ("%s: bad directory\n", p);
- X return 1;
- X}
- X
- X/*
- X * Extract the next path from a string and build a new path from the
- X * extracted path and a file name
- X */
- Xchar *path_append (s1, s2, si)
- Xregister char *s1; /* Path string */
- Xregister char *s2; /* File name string */
- Xchar *si; /* Output path */
- X{
- X register char *s;
- X
- X s = si;
- X
- X while (*s1 && *s1 != ';')
- X *s++ = *s1++;
- X
- X if ((si != s) && (*(s - 1) != '/'))
- X *s++ = '/';
- X
- X *s = '\0';
- X
- X if (s2 != (char *)NULL)
- X strcpy (s, s2);
- X
- X return (*s1 ? ++s1 : (char *)NULL);
- X}
- X
- X/*
- X * Execute a shift command: shift <n>
- X */
- X
- Xstatic int doshift (t)
- Xregister C_Op *t;
- X{
- X register int n;
- X
- X n = (t->words[1] != (char *)NULL) ? getn (t->words[1]) : 1;
- X
- X if (dolc < n)
- X {
- X print_error ("sh: nothing to shift\n");
- X return 1;
- X }
- X
- X dolv[n] = dolv[0];
- X dolv += n;
- X dolc -= n;
- X setval (lookup ("#", TRUE), putn (dolc));
- X return 0;
- X}
- X
- X/*
- X * Execute a umask command: umask <n>
- X */
- X
- Xstatic int doumask (t)
- Xregister C_Op *t;
- X{
- X register int i;
- X register char *cp;
- X
- X if ((cp = t->words[1]) == (char *)NULL)
- X {
- X i = umask (0);
- X umask (i);
- X v1printf ("%o\n", i);
- X }
- X
- X else
- X {
- X i = 0;
- X while (IS_OCTAL (*cp))
- X i = i * 8 + (*(cp++) - '0');
- X
- X umask (i);
- X }
- X
- X return 0;
- X}
- X
- X/*
- X * Execute an exec command: exec <arguments>
- X */
- X
- Xstatic int doexec (t)
- Xregister C_Op *t;
- X{
- X register int i;
- X jmp_buf ex;
- X int *ofail;
- X
- X t->ioact = (IO_Actions **)NULL;
- X
- X for (i = 0; (t->words[i] = t->words[i + 1]) != (char *)NULL; i++)
- X ;
- X
- X if (i == 0)
- X return 0;
- X
- X execflg = 1;
- X ofail = failpt;
- X
- X/* Set execute function recursive level to zero */
- X
- X Execute_stack_depth = 0;
- X
- X if (setjmp (failpt = ex) == 0)
- X execute (t, NOPIPE, NOPIPE, FEXEC);
- X
- X failpt = ofail;
- X execflg = 0;
- X return 1;
- X}
- X
- X/*
- X * Execute a script in the current shell
- X */
- X
- Xstatic int dodot (t)
- XC_Op *t;
- X{
- X register int i;
- X register char *sp;
- X char *cp;
- X
- X if ((cp = t->words[1]) == (char *)NULL)
- X return 0;
- X
- X sp = any ('/', cp) ? null : path->value;
- X
- X do
- X {
- X sp = path_append (sp, cp, e.linep);
- X
- X if ((i = O_for_execute (e.linep)) >= 0)
- X {
- X exstat = 0;
- X next (remap (i));
- X return exstat;
- X }
- X } while (sp != (char *)NULL);
- X
- X print_error ("%s: not found\n", cp);
- X return 1;
- X}
- X
- X/*
- X * Read from standard input into a variable list
- X */
- X
- Xstatic int doread (t)
- XC_Op *t;
- X{
- X register char *cp, **wp;
- X register int nb;
- X
- X if (t->words[1] == (char *)NULL)
- X {
- X print_error ("Usage: read name ...\n");
- X return 1;
- X }
- X
- X for (wp = t->words + 1; *wp != (char *)NULL; wp++)
- X {
- X for (cp = e.linep; cp < e.eline - 1; cp++)
- X {
- X if (((nb = read (STDIN_FILENO, cp, 1)) != 1) || (*cp == NL) ||
- X ((wp[1] != (char *)NULL) && any (*cp, ifs->value)))
- X
- X break;
- X }
- X
- X *cp = 0;
- X
- X if (nb <= 0)
- X break;
- X
- X setval (lookup (*wp, TRUE), e.linep);
- X }
- X
- X return (nb <= 0);
- X}
- X
- X/*
- X * Evaluate an expression
- X */
- X
- Xstatic int doeval (t)
- Xregister C_Op *t;
- X{
- X return RUN (awordlist, t->words + 1, wdchar);
- X}
- X
- X/*
- X * Execute a trap
- X */
- X
- Xstatic int dotrap (t)
- Xregister C_Op *t;
- X{
- X register int n, i;
- X register int resetsig;
- X char tval[10];
- X char *cp;
- X
- X
- X if (t->words[1] == (char *)NULL)
- X {
- X
- X/* Display trap - look up each trap and print those we find */
- X
- X for (i = 0; i < NSIG; i++)
- X {
- X sprintf (tval, "~%d", i);
- X
- X if ((cp = lookup (tval, FALSE)->value) != null)
- X {
- X v1printf ("%u: ", i);
- X v1a_puts (cp);
- X }
- X }
- X
- X return 0;
- X }
- X
- X resetsig = isdigit (*t->words[1]); /* Reset signal? */
- X
- X for (i = resetsig ? 1 : 2; t->words[i] != (char *)NULL; ++i)
- X {
- X
- X/* Generate the variable name */
- X
- X sprintf (tval, "~%d", (n = getsig (t->words[i])));
- X
- X if (n == -1)
- X return 1;
- X
- X unset (tval, TRUE);
- X
- X/* Re-define signal processing */
- X
- X if (!resetsig)
- X {
- X if (*t->words[1] != '\0')
- X {
- X setval (lookup (tval, TRUE), t->words[1]);
- X setsig (n, sig);
- X }
- X
- X else
- X setsig (n, SIG_IGN);
- X }
- X
- X/* Clear signal processing */
- X
- X else if (talking)
- X {
- X if (n == SIGINT)
- X setsig (n, onintr);
- X
- X else
- X#ifdef SIGQUIT
- X setsig (n, n == SIGQUIT ? SIG_IGN : SIG_DFL);
- X#else
- X setsig (n, SIG_DFL);
- X#endif
- X }
- X
- X else
- X setsig (n, SIG_DFL);
- X }
- X
- X return 0;
- X}
- X
- X/*
- X * Get a signal number
- X */
- X
- Xstatic int getsig (s)
- Xchar *s;
- X{
- X register int n;
- X
- X if (((n = getn (s)) < 0) || (n >= NSIG))
- X {
- X print_error ("trap: bad signal number\n");
- X n = -1;
- X }
- X
- X return n;
- X}
- X
- X/*
- X * Set up a signal function
- X */
- X
- Xstatic void setsig (n, f)
- Xregister int n;
- Xint (*f)();
- X{
- X if (n == 0)
- X return;
- X
- X if ((signal (n, SIG_IGN) != SIG_IGN) || (ourtrap & (1L << n)))
- X {
- X ourtrap |= (1L << n);
- X signal (n, f);
- X }
- X}
- X
- X/* Convert a string to a number */
- X
- Xint getn (as)
- Xchar *as;
- X{
- X char *s;
- X int n = (int)strtol (as, &s, 10);
- X
- X if (*s)
- X print_error ("%s: bad number\n", as);
- X
- X return n;
- X}
- X
- X/*
- X * BREAK and CONTINUE processing
- X */
- X
- Xstatic int dobreak (t)
- XC_Op *t;
- X{
- X return brkcontin (t->words[1], BC_BREAK);
- X}
- X
- Xstatic int docontinue (t)
- XC_Op *t;
- X{
- X return brkcontin (t->words[1], BC_CONTINUE);
- X}
- X
- Xstatic int brkcontin (cp, val)
- Xregister char *cp;
- Xint val;
- X{
- X register Break_C *Break_Loc;
- X register int nl;
- X
- X if ((nl = (cp == (char *)NULL) ? 1 : getn (cp)) <= 0)
- X nl = 999;
- X
- X do
- X {
- X if ((Break_Loc = Break_List) == (Break_C *)NULL)
- X break;
- X
- X Break_List = Break_Loc->nextlev;
- X
- X } while (--nl);
- X
- X if (nl)
- X {
- X print_error ("sh: bad break/continue level\n");
- X return 1;
- X }
- X
- X longjmp (Break_Loc->brkpt, val);
- X
- X/* NOTREACHED */
- X}
- X
- X/*
- X * Exit function
- X */
- X
- Xstatic int doexit (t)
- XC_Op *t;
- X{
- X Break_C *SShell_Loc = SShell_List;
- X
- X execflg = 0;
- X
- X/* Set up error codes */
- X
- X if (t->words[1] != (char *)NULL)
- X {
- X exstat = getn (t->words[1]);
- X setval (lookup ("?", TRUE), t->words[1]);
- X }
- X
- X/* Are we in a subshell. Yes - do a longjmp instead of an exit */
- X
- X if (SShell_Loc != (Break_C *)NULL)
- X {
- X SShell_List = SShell_Loc->nextlev;
- X longjmp (SShell_Loc->brkpt, 1);
- X }
- X
- X leave ();
- X return 1;
- X}
- X
- X/*
- X * Function return - set exit value and return via a long jmp
- X */
- X
- Xstatic int doreturn (t)
- XC_Op *t;
- X{
- X Break_C *Return_Loc = Return_List;
- X
- X if (t->words[1] != (char *)NULL)
- X setval (lookup ("?", TRUE), t->words[1]);
- X
- X/* If the return address is defined - return to it. Otherwise, return
- X * the value
- X */
- X
- X if (Return_Loc != (Break_C *)NULL)
- X {
- X Return_List = Return_Loc->nextlev;
- X longjmp (Return_Loc->brkpt, 1);
- X }
- X
- X return getn (t->words[1]);
- X}
- X
- X/*
- X * MSDOS, EXPORT and READONLY functions
- X */
- X
- Xstatic int doexport (t)
- XC_Op *t;
- X{
- X return rdexp (t->words + 1, EXPORT, "export ");
- X}
- X
- Xstatic int doreadonly (t)
- XC_Op *t;
- X{
- X return rdexp (t->words + 1, RONLY, "readonly ");
- X}
- X
- Xstatic int domsdos (t)
- XC_Op *t;
- X{
- X return rdexp (t->words + 1, C_MSDOS, "msdos ");
- X}
- X
- Xstatic int rdexp (wp, key, tstring)
- Xregister char **wp;
- Xint key;
- Xchar *tstring;
- X{
- X char *cp;
- X bool valid;
- X
- X if (*wp != (char *)NULL)
- X {
- X for (; *wp != (char *)NULL; wp++)
- X {
- X cp = *wp;
- X valid = TRUE;
- X
- X/* Check for a valid name */
- X
- X if (!isalpha (*(cp++)))
- X valid = FALSE;
- X
- X else
- X {
- X while (*cp)
- X {
- X if (!isalnum (*(cp++)))
- X {
- X valid = FALSE;
- X break;
- X }
- X }
- X }
- X
- X/* If valid - update, otherwise print a message */
- X
- X if (valid)
- X s_vstatus (lookup (*wp, TRUE), key);
- X
- X else
- X print_error ("%s: bad identifier\n", *wp);
- X }
- X }
- X
- X else
- X {
- X register Var_List *vp;
- X
- X for (vp = vlist; vp != (Var_List *) NULL; vp = vp->next)
- X {
- X if ((vp->status & key) && isalpha (*vp->name))
- X {
- X v1_puts (tstring);
- X v1_putsn (vp->name, (int)(findeq (vp->name) - vp->name));
- X v1_putc (NL);
- X }
- X }
- X }
- X
- X return 0;
- X}
- X
- X/*
- X * Sort Compare function for displaying variables
- X */
- X
- Xint sort_compare (s1, s2)
- Xchar **s1;
- Xchar **s2;
- X{
- X return strcmp (*s1, *s2);
- X}
- X
- X/*
- X * Set function
- X */
- X
- Xstatic int doset (t)
- Xregister C_Op *t;
- X{
- X register Var_List *vp;
- X register char *cp;
- X register int n, j;
- X Fun_Ops *fp;
- X char sign;
- X char **list;
- X
- X/* Display ? */
- X
- X if ((cp = t->words[1]) == (char *)NULL)
- X {
- X
- X/* Count the number of entries to print */
- X
- X for (n = 0, vp = vlist; vp != (Var_List *)NULL; vp = vp->next)
- X {
- X if (isalnum (*vp->name))
- X n++;
- X }
- X
- X/* Build a local array of name */
- X
- X list = (char **)space (sizeof (char *) * n);
- X
- X for (n = 0, vp = vlist; vp != (Var_List *)NULL; vp = vp->next)
- X {
- X if (isalnum (*vp->name))
- X {
- X if (list == (char **)NULL)
- X v1a_puts (vp->name);
- X
- X else
- X list[n++] = vp->name;
- X }
- X }
- X
- X/* Sort them and then print */
- X
- X if (list != (char **)NULL)
- X {
- X qsort (list, n, sizeof (char *), sort_compare);
- X
- X for (j = 0; j < n; j++)
- X v1a_puts (list[j]);
- X
- X DELETE (list);
- X }
- X
- X/* Print the list of functions */
- X
- X for (fp = fun_list; fp != (Fun_Ops *)NULL; fp = fp->next)
- X Print_ExTree (fp->tree);
- X
- X return 0;
- X }
- X
- X/* Set/Unset a flag ? */
- X
- X if (((sign = *cp) == '-') || (*cp == '+'))
- X {
- X for (n = 0; (t->words[n] = t->words[n + 1]) != (char *)NULL; n++)
- X ;
- X
- X for (; *cp; cp++)
- X {
- X if (*cp == 'r')
- X {
- X print_error ("set: -r bad option\n");
- X return 1;
- X }
- X
- X if (*cp == 'e')
- X {
- X if (!talking)
- X {
- X if (sign == '-')
- X FL_SET ('e');
- X
- X else
- X FL_CLEAR ('e');
- X }
- X }
- X
- X else if (islower (*cp))
- X {
- X if (sign == '-')
- X FL_SET (*cp);
- X
- X else
- X FL_CLEAR (*cp);
- X }
- X }
- X
- X setdash ();
- X }
- X
- X/* Set up parameters ? */
- X
- X if (t->words[1])
- X {
- X t->words[0] = dolv[0];
- X
- X for (n = 1; t->words[n] != (char *)NULL; n++)
- X setarea ((char *)t->words[n], 0);
- X
- X dolc = n-1;
- X dolv = t->words;
- X setval (lookup ("#", TRUE), putn (dolc));
- X setarea ((char *)(dolv - 1), 0);
- X }
- X
- X return 0;
- X}
- X
- X/*
- X * History functions - display, initialise, enable, disable
- X */
- X
- Xstatic int dohistory (t)
- XC_Op *t;
- X{
- X char *cp;
- X
- X if (!talking)
- X return 1;
- X
- X if ((cp = t->words[1]) == (char *)NULL)
- X Display_History ();
- X
- X else if (strcmp (cp, "-i") == 0)
- X Clear_History ();
- X
- X else if (strcmp (cp, "-d") == 0)
- X History_Enabled = FALSE;
- X
- X else if (strcmp (cp, "-e") == 0)
- X History_Enabled = TRUE;
- X
- X return 0;
- X}
- X
- X/*
- X * Type fucntion: For each name, indicate how it would be interpreted
- X */
- X
- Xstatic char *type_ext[] = {
- X "", ".exe", ".com", ".sh"
- X};
- X
- Xstatic int dotype (t)
- Xregister C_Op *t;
- X{
- X register char *sp; /* Path pointers */
- X char *cp;
- X char *ep;
- X char *xp; /* In file name pointers */
- X char *xp1;
- X int n = 1; /* Argument count */
- X int i, fp;
- X bool found; /* Found flag */
- X
- X while ((cp = t->words[n++]) != (char *)NULL)
- X {
- X sp = any ('/', cp) ? null : path->value;
- X found = FALSE;
- X
- X do
- X {
- X sp = path_append (sp, cp, e.linep);
- X ep = &e.linep[strlen (e.linep)];
- X
- X/* Get start of file name */
- X
- X if ((xp1 = strrchr (e.linep, '/')) == (char *)NULL)
- X xp1 = e.linep;
- X
- X else
- X ++xp1;
- X
- X/* Look up all 4 types */
- X
- X for (i = 0; (i < 4) && !found; i++)
- X {
- X strcpy (ep, type_ext[i]);
- X
- X if (access (e.linep, F_OK) == 0)
- X {
- X
- X/* If no extension or .sh extension, check for shell script */
- X
- X if (((xp = strchr (xp1, '.')) == (char *)NULL) ||
- X (stricmp (xp, ".sh") == 0))
- X {
- X if ((fp = Check_Script (e.linep)) < 0)
- X continue;
- X
- X S_close (fp, TRUE);
- X }
- X
- X else if ((stricmp (xp, ".exe") != 0) &&
- X (stricmp (xp, ".com") != 0))
- X continue;
- X
- X print_error ("%s is %s\n", cp, e.linep);
- X found = TRUE;
- X }
- X }
- X } while ((sp != (char *)NULL) && !found);
- X
- X if (!found)
- X print_error ("%s not found\n", cp);
- X }
- X
- X return 0;
- X}
- X
- X/* Table of internal commands */
- X
- Xstatic struct builtin builtin[] = {
- X ".", dodot,
- X ":", dolabel,
- X "[", dotest,
- X "break", dobreak,
- X "cd", dochdir,
- X "continue", docontinue,
- X "echo", doecho,
- X "eval", doeval,
- X "exec", doexec,
- X "exit", doexit,
- X "export", doexport,
- X "getopt", dogetopt,
- X "history", dohistory,
- X "msdos", domsdos,
- X "pwd", dopwd,
- X "read", doread,
- X "readonly", doreadonly,
- X "return", doreturn,
- X "set", doset,
- X "shift", doshift,
- X "swap", doswap,
- X "test", dotest,
- X "trap", dotrap,
- X "type", dotype,
- X "umask", doumask,
- X "unset", dounset,
- X "ver", dover,
- X (char *)NULL,
- X};
- X
- X/*
- X * Look up a built in command
- X */
- X
- Xint (*inbuilt (s))()
- Xregister char *s;
- X{
- X register struct builtin *bp;
- X
- X if ((strlen (s) == 2) && isalpha (*s) && (*s != '_') && (*(s + 1) == ':'))
- X return dodrive;
- X
- X for (bp = builtin; bp->command != (char *)NULL; bp++)
- X {
- X if (stricmp (bp->command, s) == 0)
- X return bp->fn;
- X }
- X
- X return NULL;
- X}
- X
- X/* Write to stdout functions - printf, fputs, fputc, and a special */
- X
- X/*
- X * Equivalent of printf without using streams
- X */
- X
- Xvoid v1printf (fmt)
- Xchar *fmt;
- X{
- X va_list ap;
- X char x[100];
- X
- X va_start (ap, fmt);
- X vsprintf (x, fmt, ap);
- X v1_puts (x);
- X va_end (ap);
- X}
- X
- X/*
- X * Write string to STDOUT
- X */
- X
- Xvoid v1_puts (s)
- Xchar *s;
- X{
- X write (STDOUT_FILENO, s, strlen (s));
- X}
- X
- X/*
- X * Write string to STDOUT with a NL at end
- X */
- X
- Xvoid v1a_puts (s)
- Xchar *s;
- X{
- X char c = NL;
- X
- X write (STDOUT_FILENO, s, strlen (s));
- X write (STDOUT_FILENO, &c, 1);
- X}
- X
- X/*
- X * Write n characters to STDOUT
- X */
- X
- Xstatic void v1_putsn (s, n)
- Xchar *s;
- Xint n;
- X{
- X write (STDOUT_FILENO, s, n);
- X}
- X
- X/*
- X * Write 1 character to STDOUT
- X */
- X
- Xvoid v1_putc (c)
- Xchar c;
- X{
- X write (STDOUT_FILENO, &c, 1);
- X}
- SHAR_EOF
- chmod 0644 shell/sh7.c || echo "restore of shell/sh7.c fails"
- set `wc -c shell/sh7.c`;Sum=$1
- if test "$Sum" != "30980"
- then echo original size 30980, current size $Sum;fi
- echo "x - extracting shell/sh8.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > shell/sh8.c &&
- X/* MS-DOS SHELL - Unix File I/O Emulation
- X *
- X * MS-DOS SHELL - Copyright (c) 1990 Data Logic Limited
- X *
- X * This code 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: sh8.c 1.1 90/01/29 17:46:37 MS_user Exp $
- X *
- X * $Log: sh8.c $
- X * Revision 1.1 90/01/29 17:46:37 MS_user
- X * Initial revision
- X *
- X *
- X */
- X
- X#include <sys/types.h>
- X#include <signal.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include <stdlib.h>
- X#include <fcntl.h>
- X#include <io.h>
- X#include <stdarg.h>
- X#include <string.h>
- X#include <unistd.h>
- X#include <limits.h>
- X#include "sh.h"
- X
- X#define F_START 4
- X
- Xstatic char *nopipe = "can't create pipe - try again\n";
- X
- X/* List of open files to allow us to simulate the Unix open and unlink
- X * operation for temporary files
- X */
- X
- Xtypedef struct flist {
- X struct flist *fl_next; /* Next link */
- X char *fl_name; /* File name */
- X bool fl_close; /* Delete on close flag */
- X int fl_size; /* Size of fl_fd array */
- X int fl_count; /* Number of entries in array */
- X int fl_mode; /* File open mode */
- X int *fl_fd; /* File ID array (for dup) */
- X} s_flist;
- X
- Xstatic s_flist *list_start = (s_flist *)NULL;
- Xstatic s_flist *find_entry (int);
- X
- X/*
- X * Open a file and add it to the Open file list. Errors are the same as
- X * for a normal open.
- X */
- X
- Xint S_open (d_flag, name, mode)
- Xbool d_flag;
- Xchar *name;
- Xint mode;
- X{
- X va_list ap;
- X int pmask;
- X s_flist *fp = (struct s_flist *)NULL;
- X int *f_list = (int *)NULL;
- X char *f_name = (char *)NULL;
- X
- X/* Check the permission mask if it exists */
- X
- X va_start (ap, mode);
- X pmask = va_arg (ap, int);
- X va_end (ap);
- X
- X/* Grap some space. If it fails, free space and return an error */
- X
- X if (((fp = (s_flist *) space (sizeof (s_flist))) == (s_flist *)NULL) ||
- X ((f_list = (int *) space (sizeof (int) * F_START)) == (int *)NULL) ||
- X ((f_name = strsave (name, 0)) == null))
- X {
- X if (f_list == (int *)NULL)
- X DELETE (f_list);
- X
- X if (fp == (s_flist *)NULL)
- X DELETE (fp);
- X
- X errno = ENOMEM;
- X return -1;
- X }
- X
- X/* Set up the structure */
- X
- X fp->fl_name = strcpy (f_name, name);
- X fp->fl_close = d_flag;
- X fp->fl_size = F_START;
- X fp->fl_count = 1;
- X fp->fl_fd = f_list;
- X fp->fl_mode = mode;
- X
- X/* Open the file */
- X
- X if ((fp->fl_fd[0] = open (name, mode, pmask)) < 0)
- X {
- X pmask = errno;
- X DELETE (f_name);
- X DELETE (f_list);
- X DELETE (fp);
- X errno = pmask;
- X return -1;
- X }
- X
- X/* Make sure everything is in area 0 */
- X
- X setarea ((char *)fp, 0);
- X setarea ((char *)f_list, 0);
- X
- X/* List into the list */
- X
- X fp->fl_next = list_start;
- X list_start = fp;
- X
- X/* Return the file descriptor */
- X
- X return fp->fl_fd[0];
- X}
- X
- X/*
- X * Scan the File list for the appropriate entry for the specified ID
- X */
- X
- Xstatic s_flist *find_entry (fid)
- Xint fid;
- X{
- X s_flist *fp = list_start;
- X int i;
- X
- X while (fp != (s_flist *)NULL)
- X {
- X for (i = 0; i < fp->fl_count; i++)
- X {
- X if (fp->fl_fd[i] == fid)
- X return fp;
- X }
- X
- X fp = fp->fl_next;
- X }
- X
- X return (s_flist *)NULL;
- X}
- X
- X/* Close the file
- X *
- X * We need a version of close that does everything but close for dup2 as
- X * new file id is closed. If c_flag is TRUE, close the file as well.
- X */
- X
- Xint S_close (fid, c_flag)
- Xint fid;
- Xbool c_flag;
- X{
- X s_flist *fp = find_entry (fid);
- X s_flist *last = (s_flist *)NULL;
- X s_flist *fp1 = list_start;
- X int i, serrno;
- X bool release = TRUE;
- X bool delete = FALSE;
- X char *fname;
- X
- X/* Find the entry for this ID */
- X
- X if (fp != (s_flist *)NULL)
- X {
- X for (i = 0; i < fp->fl_count; i++)
- X {
- X if (fp->fl_fd[i] == fid)
- X fp->fl_fd[i] = -1;
- X
- X if (fp->fl_fd[i] != -1)
- X release = FALSE;
- X }
- X
- X/* Are all the Fids closed ? */
- X
- X if (release)
- X {
- X fname = fp->fl_name;
- X delete = fp->fl_close;
- X DELETE (fp->fl_fd);
- X
- X/* Scan the list and remove the entry */
- X
- X while (fp1 != (s_flist *)NULL)
- X {
- X if (fp1 != fp)
- X {
- X last = fp1;
- X fp1 = fp1->fl_next;
- X continue;
- X }
- X
- X if (last == (s_flist *)NULL)
- X list_start = fp->fl_next;
- X
- X else
- X last->fl_next = fp->fl_next;
- X
- X break;
- X }
- X
- X/* OK - delete the area */
- X
- X DELETE (fp);
- X }
- X }
- X
- X/* Close the file anyway */
- X
- X if (c_flag)
- X {
- X i = close (fid);
- X serrno = errno;
- X }
- X
- X/* Delete the file ? */
- X
- X if (delete)
- X {
- X unlink (fname);
- X DELETE (fname);
- X }
- X
- X/* Restore results and error code */
- X
- X errno = serrno;
- X return i;
- X}
- X
- X/*
- X * Duplicate file handler. Add the new handler to the ID array for this
- X * file.
- X */
- X
- Xint S_dup (old_fid)
- Xint old_fid;
- X{
- X int new_fid;
- X
- X if ((new_fid = dup (old_fid)) >= 0)
- X S_Remap (old_fid, new_fid);
- X
- X return new_fid;
- X}
- X
- X/*
- X * Add the ID to the ID array for this file
- X */
- X
- Xvoid S_Remap (old_fid, new_fid)
- Xint old_fid, new_fid;
- X{
- X s_flist *fp = find_entry (old_fid);
- X int *flist;
- X int i;
- X
- X if (fp == (s_flist *)NULL)
- X return;
- X
- X/* Is there an empty slot ? */
- X
- X for (i = 0; i < fp->fl_count; i++)
- X {
- X if (fp->fl_fd[i] == -1)
- X {
- X fp->fl_fd[i] = new_fid;
- X return;
- X }
- X }
- X
- X/* Is there any room at the end ? No - grap somemore space and effect a
- X * re-alloc. What to do if the re-alloc fails - should really get here.
- X * Safty check only??
- X */
- X
- X if (fp->fl_count == fp->fl_size)
- X {
- X if ((flist = (int *) space ((fp->fl_size + F_START) * sizeof (int)))
- X == (int *)NULL)
- X return;
- X
- X memcpy ((char *)flist, (char *)fp->fl_fd, sizeof (int) * fp->fl_size);
- X DELETE (fp->fl_fd);
- X
- X fp->fl_fd = flist;
- X fp->fl_size += F_START;
- X }
- X
- X fp->fl_fd[fp->fl_count++] = new_fid;
- X}
- X
- X/*
- X * Set Delete on Close flag
- X */
- X
- Xvoid S_Delete (fid)
- Xint fid;
- X{
- X s_flist *fp = find_entry (fid);
- X
- X if (fp != (s_flist *)NULL)
- X fp->fl_close = TRUE;
- X}
- X
- X/*
- X * Duplicate file handler onto specific handler
- X */
- X
- Xint S_dup2 (old_fid, new_fid)
- Xint old_fid;
- Xint new_fid;
- X{
- X int res = 0;
- X int i;
- X Save_IO *sp;
- X
- X/* If duping onto stdin, stdout or stderr, Search the Save IO stack for an
- X * entry matching us
- X */
- X
- X if ((new_fid >= STDIN_FILENO) && (new_fid <= STDERR_FILENO))
- X {
- X for (sp = SSave_IO, i = 0; (i < NSave_IO_E) &&
- X (SSave_IO[i].depth < Execute_stack_depth);
- X i++);
- X
- X/* If depth is greater the Execute_stack_depth - we should panic as this
- X * should not happen. However, for the moment, I'll ignore it
- X */
- X
- X/* If there an entry for this depth ? */
- X
- X if (i == NSave_IO_E)
- X {
- X
- X/* Do we need more space? */
- X
- X if (NSave_IO_E == MSave_IO_E)
- X {
- X sp = (Save_IO *)space ((MSave_IO_E + SSAVE_IO_SIZE) * sizeof (Save_IO));
- X
- X/* Check for error */
- X
- X if (sp == (Save_IO *)NULL)
- X {
- X errno = ENOMEM;
- X return -1;
- X }
- X
- X/* Save original data */
- X
- X if (MSave_IO_E != 0)
- X {
- X memcpy (sp, SSave_IO, sizeof (Save_IO) * MSave_IO_E);
- X DELETE (SSave_IO);
- X }
- X
- X setarea ((char *)sp, 1);
- X SSave_IO = sp;
- X MSave_IO_E += SSAVE_IO_SIZE;
- X }
- X
- X/* Initialise the new entry */
- X
- X sp = &SSave_IO[NSave_IO_E++];
- X sp->depth = Execute_stack_depth;
- X sp->fp[STDIN_FILENO] = -1;
- X sp->fp[STDOUT_FILENO] = -1;
- X sp->fp[STDERR_FILENO] = -1;
- X }
- X
- X if (sp->fp[new_fid] == -1)
- X sp->fp[new_fid] = remap (new_fid);
- X }
- X
- X/* OK - Dup the descriptor */
- X
- X if ((old_fid != -1) && ((res = dup2 (old_fid, new_fid)) >= 0))
- X {
- X S_close (new_fid, FALSE);
- X S_Remap (old_fid, new_fid);
- X }
- X
- X return res;
- X}
- X
- X/*
- X * Restore the Stdin, Stdout and Stderr to original values
- X */
- X
- Xint restore_std (rv)
- Xint rv;
- X{
- X int j, i;
- X Save_IO *sp;
- X
- X/* Start at the top and remove any entries above the current execute stack
- X * depth
- X */
- X
- X for (j = NSave_IO_E; j > 0; j--)
- X {
- X sp = &SSave_IO[j - 1];
- X
- X if (sp->depth < Execute_stack_depth)
- X break;
- X
- X/* Reduce number of entries */
- X
- X --NSave_IO_E;
- X
- X/* Close and restore any files */
- X
- X for (i = STDIN_FILENO; i <= STDERR_FILENO; i++)
- X {
- X if (sp->fp[i] != -1)
- X {
- X S_close (i, TRUE);
- X dup2 (sp->fp[i], i);
- X S_close (sp->fp[i], TRUE);
- X }
- X }
- X }
- X
- X return rv;
- X}
- X
- X/*
- X * Create a Pipe
- X */
- X
- Xint openpipe ()
- X{
- X register int i;
- X
- X if ((i = S_open (TRUE, g_tempname (), O_PMASK, 0600)) < 0)
- X print_error (nopipe);
- X
- X return i;
- X}
- X
- X/*
- X * Close a pipe
- X */
- X
- Xvoid closepipe (pv)
- Xregister int pv;
- X{
- X if (pv != -1)
- X S_close (pv, TRUE);
- X}
- X
- X/*
- X * Write a character to STDERR
- X */
- X
- Xvoid S_putc (c)
- Xint c;
- X{
- X write (STDERR_FILENO, (char *)&c, 1);
- X}
- X
- X/*
- X * Write a string to STDERR
- X */
- X
- Xvoid S_puts (s)
- Xchar *s;
- X{
- X write (STDERR_FILENO, s, strlen (s));
- X}
- X
- X/*
- X * Check for restricted shell
- X */
- X
- Xbool check_rsh (s)
- Xchar *s;
- X{
- X if (r_flag)
- X {
- X print_error ("%s: restricted\n", s);
- X return TRUE;
- X }
- X
- X return FALSE;
- X}
- X
- X/*
- X * Check to see if a file is a shell script. If it is, return the file
- X * handler for the file
- X */
- X
- Xint O_for_execute (path)
- Xchar *path;
- X{
- X int i, end;
- X char local_path[FFNAME_MAX];
- X
- X/* Work on a copy of the path */
- X
- X strcpy (local_path, path);
- X
- X/* Try the file name and then with a .sh appended */
- X
- X for (end = 0; end < 2; end++)
- X {
- X if ((i = Check_Script (local_path)) >= 0)
- X return i;
- X
- X if (!end)
- X strcat (local_path, ".sh");
- X }
- X
- X return -1;
- X}
- X
- X/*
- X * Check for shell script
- X */
- X
- Xint Check_Script (path)
- Xchar *path;
- X{
- X char buf[5];
- X int i;
- X
- X if (((i = S_open (FALSE, path, O_RMASK)) >= 0) &&
- X ((read (i, buf, 6) == 5) && (strncmp (buf, "#!sh\n", 5) == 0)))
- X return i;
- X
- X if (i != -1)
- X S_close (i, TRUE);
- X
- X return -1;
- X}
- X
- X/*
- X * Convert slashes to backslashes for MSDOS
- X */
- X
- Xvoid Convert_Slashes (sp)
- Xchar *sp;
- X{
- X while (*sp)
- X {
- X if (*sp == '/')
- X *sp = '\\';
- X
- X ++sp;
- X }
- X}
- SHAR_EOF
- chmod 0644 shell/sh8.c || echo "restore of shell/sh8.c fails"
- set `wc -c shell/sh8.c`;Sum=$1
- if test "$Sum" != "9874"
- then echo original size 9874, current size $Sum;fi
- echo "x - extracting shell/sh9.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > shell/sh9.c &&
- X/* MS-DOS SHELL - History Processing
- X *
- X * MS-DOS SHELL - Copyright (c) 1990 Data Logic Limited
- X *
- X * This code 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: sh9.c 1.1 90/01/26 17:25:19 MS_user Exp $
- X *
- X * $Log: sh9.c $
- X * Revision 1.1 90/01/26 17:25:19 MS_user
- X * Initial revision
- X *
- X *
- X */
- X
- X#include <sys/types.h>
- X#include <stdio.h>
- X#include <conio.h>
- X#include <string.h>
- X#include <memory.h>
- X#include <ctype.h>
- X#include <signal.h>
- X#include <stdlib.h>
- X#include <stddef.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include <limits.h>
- X#include <dos.h>
- X#include <unistd.h>
- X#include "sh.h"
- X
- Xstatic bool alpha_numeric (int);
- Xstatic bool function (int);
- Xstatic bool Process_History (int);
- Xstatic bool Scan_History (void);
- Xstatic void Redisplay_Line (void);
- Xstatic void Process_Stdin (void);
- Xstatic void Page_History (int);
- Xstatic bool UpDate_CLine (char *);
- Xstatic bool Re_start (char *);
- Xstatic void memrcpy (char *, char *, int);
- Xstatic int read_cursor_position (void);
- Xstatic void set_cursor_position (int);
- Xstatic void gen_cursor_position (void);
- X
- Xstatic bool insert_mode = FALSE;
- Xstatic char *c_buffer_pos; /* Position in command line */
- Xstatic char *end_buffer; /* End of command line */
- Xstatic int s_cursor; /* Start cursor position */
- Xstatic int c_history = -1; /* Current entry */
- Xstatic int l_history = 0; /* End of history array */
- Xstatic int M_length = -1; /* Match length */
- Xstatic char l_buffer[LINE_MAX + 1];
- Xstatic char *No_prehistory = "history: No previous commands\033[2K\n";
- Xstatic char *No_MatchHistory = "history: No history match found\033[2K\n";
- Xstatic char *No_posthistory = "history: No more commands\033[2K\n";
- Xstatic char *History_2long = "history: History line too long\033[2K\n";
- Xstatic char *H_TooLongI = "History file line too long - ignored (%d)\n";
- X
- X/* Arrary of history Items */
- X
- Xstatic struct cmd_history {
- X int number;
- X char *command;
- X} cmd_history[HISTORY_MAX];
- X
- X/* Processing standard input */
- X
- Xint Get_stdin (ap)
- Xregister IO_Args *ap;
- X{
- X int coff = (int)ap->afpos;
- X char rv;
- X
- X/* Is there anything in the input buffer. If not, add the previous line to
- X * the history buffer and get the next line
- X */
- X
- X if (!coff)
- X Process_Stdin (); /* No - get input */
- X
- X/* Get the next character */
- X
- X if ((rv = l_buffer[coff]) == NL)
- X {
- X l_buffer[coff] = 0;
- X ap->afpos = 0L;
- X }
- X
- X/* Check for end of file */
- X
- X else if (rv == 0x1a)
- X {
- X l_buffer[coff] = 0;
- X ap->afpos = 0L;
- X rv = 0;
- X }
- X
- X else
- X ap->afpos++;
- X
- X return rv;
- X}
- X
- X/* Input processing function */
- X
- Xstatic void Process_Stdin ()
- X{
- X int i;
- X char *control = "^x";
- X
- X/* Set to last history item */
- X
- X c_history = l_history - 1;
- X
- X/* Process the input */
- X
- X while (TRUE)
- X {
- X c_buffer_pos = l_buffer; /* Initialise */
- X end_buffer = l_buffer;
- X insert_mode = FALSE;
- X M_length = -1;
- X s_cursor = read_cursor_position ();
- X
- X while (((i = getch ()) != 0x1a) && (i != NL) && (i != '\r'))
- X {
- X
- X/* Re-position the line? */
- X
- X if (((i) ? alpha_numeric (i) : function (getch ())))
- X Redisplay_Line ();
- X
- X/* Reposition the cursor */
- X
- X gen_cursor_position ();
- X }
- X
- X/* Terminate the line */
- X
- X *end_buffer = 0;
- X v1_putc (NL);
- X
- X/* Line input - check for history */
- X
- X if ((*l_buffer == '!') && Process_History (0))
- X {
- X v1a_puts (l_buffer);
- X break;
- X }
- X
- X else if (*l_buffer != '!')
- X break;
- X
- X/* Output prompt and try again */
- X
- X Re_start ((char *)NULL);
- X }
- X
- X *end_buffer = (char)((i == '\r') ? NL : i);
- X}
- X
- X/* Handler Alpha_numeric characters */
- X
- Xstatic bool alpha_numeric (c)
- Xint c;
- X{
- X bool redisplay = FALSE;
- X
- X/* Backspace processing */
- X
- X if (c == 0x08)
- X {
- X if (c_buffer_pos == l_buffer)
- X {
- X v1_putc (0x07); /* Ring bell */
- X return FALSE;
- X }
- X
- X/* Decrement current position */
- X
- X if ((c_buffer_pos--) == end_buffer)
- X --end_buffer;
- X
- X else
- X *c_buffer_pos = ' ';
- X
- X return TRUE;
- X }
- X
- X/* Normal character processing */
- X
- X if ((c_buffer_pos - l_buffer) == LINE_MAX)
- X {
- X v1_putc (0x07); /* Ring bell */
- X return FALSE;
- X }
- X
- X else if (!insert_mode)
- X {
- X if (c_buffer_pos == end_buffer)
- X ++end_buffer;
- X
- X else if (iscntrl (*c_buffer_pos) || iscntrl (c))
- X redisplay = TRUE;
- X
- X *(c_buffer_pos++) = (char)c;
- X
- X if (redisplay || (c == '\t'))
- X return TRUE;
- X
- X if (iscntrl (c))
- X {
- X v1_putc ('^');
- X c += '@';
- X }
- X
- X v1_putc ((char)c);
- X return FALSE;
- X }
- X
- X else if ((end_buffer - l_buffer) == LINE_MAX)
- X {
- X v1_putc (0x07); /* Ring bell - line full */
- X return FALSE;
- X }
- X
- X else
- X {
- X if (c_buffer_pos != end_buffer)
- X memrcpy (end_buffer + 1, end_buffer, end_buffer - c_buffer_pos + 1);
- X
- X ++end_buffer;
- X *(c_buffer_pos++) = (char)c;
- X return TRUE;
- X }
- X}
- X
- X/* Process function keys */
- X
- Xstatic bool function (fn)
- Xint fn;
- X{
- X switch (fn)
- X {
- X case 'I': /* Scan back command line */
- X case 'Q': /* Scan up command line */
- X if (M_length == -1)
- X break;
- X
- X Page_History ((fn == 'I') ? -1 : 1);
- X return TRUE;
- X
- X case 'H': /* Previous command line */
- X Process_History (-1);
- X return TRUE;
- X
- X case 'P': /* Next command line */
- X Process_History (1);
- X return TRUE;
- X
- X case 'K': /* Cursor left */
- X if (c_buffer_pos != l_buffer)
- X --c_buffer_pos;
- X
- X else
- X v1_putc (0x07);
- X
- X return FALSE;
- X
- X case 'M': /* Cursor right */
- X if (c_buffer_pos != end_buffer)
- X ++c_buffer_pos;
- X
- X else
- X v1_putc (0x07);
- X
- X return FALSE;
- X
- X case 's': /* Cursor left a word */
- X if (c_buffer_pos != l_buffer)
- X {
- X --c_buffer_pos; /* Reposition on previous char */
- X
- X while (isspace (*c_buffer_pos) && (c_buffer_pos != l_buffer))
- X --c_buffer_pos;
- X
- X while (!isspace (*c_buffer_pos) && (c_buffer_pos != l_buffer))
- X --c_buffer_pos;
- X
- X if (c_buffer_pos != l_buffer)
- X ++c_buffer_pos;
- X }
- X
- X else
- X v1_putc (0x07);
- X
- X return FALSE;
- X
- X case 't': /* Cursor right a word */
- X if (c_buffer_pos != end_buffer)
- X {
- X
- X/* Skip to the end of the current word */
- X
- X while (!isspace (*c_buffer_pos) && (c_buffer_pos != end_buffer))
- X ++c_buffer_pos;
- X
- X/* Skip over the white space */
- X
- X while (isspace (*c_buffer_pos) && (c_buffer_pos != end_buffer))
- X ++c_buffer_pos;
- X }
- X
- X else
- X v1_putc (0x07);
- X
- X return FALSE;
- X
- X case 'G': /* Cursor home */
- X c_buffer_pos = l_buffer;
- X return FALSE;
- X
- X case 'u': /* Flush to end */
- X memset (c_buffer_pos, ' ', end_buffer - c_buffer_pos);
- X end_buffer = c_buffer_pos;
- X return TRUE;
- X
- X case 'O': /* Cursor end of command */
- X if (*l_buffer == '!')
- X {
- X *end_buffer = 0;
- X Process_History (2);
- X return TRUE;
- X }
- X
- X c_buffer_pos = end_buffer;
- X return FALSE;
- X
- X case 'R': /* Switch insert mode */
- X insert_mode = (insert_mode) ? FALSE : TRUE;
- X return FALSE;
- X
- X case 'S': /* Delete character */
- X if (c_buffer_pos != end_buffer)
- X memcpy (c_buffer_pos, c_buffer_pos + 1,
- X end_buffer - c_buffer_pos);
- X
- X if (end_buffer == l_buffer)
- X {
- X v1_putc (0x07);
- X return TRUE;
- X }
- X
- X if (--end_buffer < c_buffer_pos)
- X --c_buffer_pos;
- X
- X return TRUE;
- X }
- X
- X v1_putc (0x07);
- X return FALSE;
- X}
- X
- X/* Read Cursor position */
- X
- Xstatic int read_cursor_position ()
- X{
- X union REGS r;
- X
- X r.h.ah = 0x03; /* Read cursor position */
- X r.h.bh = 0; /* Page zero */
- X int86 (0x10, &r, &r);
- X return (r.h.dh * 80) + r.h.dl;
- X}
- X
- X/* Re-position the cursor */
- X
- Xstatic void set_cursor_position (new)
- Xint new;
- X{
- X union REGS r;
- X
- X r.h.ah = 0x02; /* Set new position */
- X r.h.bh = 0; /* Page zero */
- X r.h.dh = (unsigned char)(new / 80);
- X r.h.dl = (unsigned char)(new % 80);
- X
- X/* Are we at the bottom of the page? */
- X
- X if (r.h.dh == 25)
- X {
- X r.h.dh = 24;
- X s_cursor -= 80;
- X }
- X
- X int86 (0x10, &r, &r);
- X}
- X
- X/* Generate the new cursor position */
- X
- Xstatic void gen_cursor_position ()
- X{
- X char *cp = l_buffer - 1;
- X int off = s_cursor;
- X
- X/* Search to current position */
- X
- X while (++cp != c_buffer_pos)
- X {
- X if (*cp == '\t')
- X while ((++off) % 8);
- X
- X else if (iscntrl (*cp))
- X off += 2;
- X
- X else
- X ++off;
- X }
- X
- X/* Position the cursor */
- X
- X set_cursor_position (off);
- X}
- X
- X/* Redisplay the current line */
- X
- Xstatic void Redisplay_Line ()
- X{
- X char *control = "^x";
- X char *cp = l_buffer;
- X int off = s_cursor;
- X
- X/* Reposition to start of line */
- X
- X set_cursor_position (s_cursor);
- X
- X/* Output the line */
- X
- X while (cp != end_buffer)
- X {
- X if (*cp == '\t')
- X {
- X do
- X {
- X v1_putc (SP);
- X } while ((++off) % 8);
- X }
- X
- X else if (iscntrl (*cp))
- X {
- X control[1] = *cp + '@';
- X v1_puts (control);
- X off += 2;
- X }
- X
- X else
- X {
- X ++off;
- X v1_putc (*cp);
- X }
- X
- X ++cp;
- X }
- X
- X v1_puts ("\033[2K"); /* clear to end of line */
- X}
- X
- X/* Process history command
- X *
- X * -1: Previous command
- X * 1: Next command
- X * 0: Current command
- X * 2: Current command with no options processing
- X */
- X
- Xstatic bool Process_History (direction)
- Xint direction;
- X{
- X char *optionals = null;
- X
- X c_buffer_pos = l_buffer;
- X end_buffer = l_buffer;
- X c_history += (direction == 2) ? 0 : direction;
- X
- X switch (direction)
- X {
- X case -1: /* Move up one line */
- X if (c_history < 0)
- X {
- X ++c_history;
- X return Re_start (No_prehistory);
- X }
- X
- X break;
- X
- X case 1: /* Move to next history line */
- X if (c_history >= l_history)
- X {
- X --c_history;
- X return Re_start (No_posthistory);
- X }
- X
- X break;
- X
- X case 0: /* Check out l_buffer */
- X optionals = l_buffer; /* Are there any additions to */
- X /* the history line */
- X
- X/* Find the end of the first part */
- X
- X while (!isspace (*optionals) && *optionals)
- X ++optionals;
- X
- X/* Terminate the history command */
- X
- X if (*optionals)
- X *(optionals++) = 0;
- X
- X/* Find the end of the space separator part which gives the start of the
- X * optionals
- X */
- X
- X while (isspace (*optionals))
- X ++optionals;
- X
- X
- X/* Copy selected item into line buffer */
- X
- X case 2:
- X M_length = strlen (l_buffer) - 1;
- X if (!Scan_History ())
- X return FALSE;
- X
- X break;
- X }
- X
- X return UpDate_CLine (optionals);
- X}
- X
- X/* Ok c_history points to the new line. Move optionals after history
- X * and the copy in history and add a space
- X */
- X
- Xstatic bool UpDate_CLine (optionals)
- Xchar *optionals;
- X{
- X int opt_len;
- X
- X end_buffer = &l_buffer[strlen (cmd_history[c_history].command)];
- X
- X if ((end_buffer - l_buffer + (opt_len = strlen (optionals)) + 1) >= LINE_MAX)
- X return Re_start (History_2long);
- X
- X if (end_buffer > optionals)
- X memrcpy (end_buffer + 1 + opt_len, optionals + opt_len, opt_len + 1);
- X
- X else
- X strcpy (end_buffer + 1, optionals);
- X
- X strcpy (l_buffer, cmd_history[c_history].command);
- X
- X if (opt_len)
- X *end_buffer = ' ';
- X
- X end_buffer = &l_buffer[strlen (l_buffer)];
- X return TRUE;
- X}
- X
- X/* Scan the line buffer for a history match */
- X
- Xstatic bool Scan_History ()
- X{
- X char *cp = &l_buffer[1];
- X int c_len = strlen (cp);
- X char *ep;
- X int i = (int)strtol (cp, &ep, 10);
- X
- X/* Get the previous command ? (single !) */
- X
- X if (c_len == 0)
- X {
- X if (c_history < 0)
- X {
- X M_length = -1;
- X return Re_start (No_prehistory);
- X }
- X
- X return TRUE;
- X }
- X
- X/* Request for special history number item. Check History file empty */
- X
- X if (l_history == 0)
- X {
- X M_length = -1;
- X return Re_start (No_MatchHistory);
- X }
- X
- X/* Check for number */
- X
- X if (!*ep)
- X {
- X M_length = -1;
- X
- X for (c_history = l_history - 1;
- X (cmd_history[c_history].number != i) && (c_history >= 0);
- X --c_history);
- X }
- X
- X/* No - scan for a match */
- X
- X else
- X {
- X for (c_history = l_history - 1;
- X (strncmp (cp, cmd_history[c_history].command, c_len) != 0)
- X && (c_history >= 0);
- X --c_history);
- X }
- X
- X/* Anything found ? */
- X
- X if (c_history == -1)
- X {
- X c_history = l_history - 1;
- X return Re_start (No_MatchHistory);
- X }
- X
- X return TRUE;
- X}
- X
- X/* Scan back or forward from current history */
- X
- Xstatic void Page_History (direction)
- Xint direction;
- X{
- X c_buffer_pos = l_buffer;
- X end_buffer = l_buffer;
- X
- X if (l_history == 0)
- X {
- X M_length = -1;
- X Re_start (No_MatchHistory);
- X return;
- X }
- X
- X/* scan for a match */
- X
- X while (((c_history += direction) >= 0) && (c_history != l_history) &&
- X (strncmp (l_buffer, cmd_history[c_history].command, M_length) != 0));
- X
- X/* Anything found ? */
- X
- X if ((c_history < 0) || (c_history == l_history))
- X {
- X c_history = l_history - 1;
- X Re_start (No_MatchHistory);
- X }
- X
- X else
- X UpDate_CLine (null);
- X}
- X
- X/* Load history file */
- X
- Xvoid Load_History ()
- X{
- X FILE *fp;
- X char *cp;
- X int i = 0;
- X Var_List *lset;
- X
- X/* Initialise history array */
- X
- X memset (cmd_history, 0, sizeof (struct cmd_history) * HISTORY_MAX);
- X c_history = -1; /* Current entry */
- X l_history = 0; /* End of history array */
- X
- X if ((lset = lookup (history_file, TRUE))->value == null)
- X setval (lset, strcat (strcpy (l_buffer, lookup (home, FALSE)->value),
- X "history.sh"));
- X
- X if (!History_Enabled || ((fp = fopen (lset->value, "rt")) == (FILE *)NULL))
- X return;
- X
- X/* Read in file */
- X
- X while (fgets (l_buffer, LINE_MAX, fp) != (char *)NULL)
- X {
- X ++i;
- X
- X if ((cp = strchr (l_buffer, NL)) == (char *)NULL)
- X print_warn (H_TooLongI, i);
- X
- X else
- X {
- X *cp = 0;
- X Add_History (TRUE);
- X }
- X }
- X
- X fclose (fp);
- X}
- X
- X/* Add entry to history file */
- X
- Xvoid Add_History (past)
- Xbool past; /* Past history? */
- X{
- X int i;
- X
- X if ((!History_Enabled) || (strlen (l_buffer) == 0))
- X return;
- X
- X/* If adding past history, decrement all numbers previous */
- X
- X if ((past) && l_history)
- X {
- X for (i = 0; i < l_history; i++)
- X --(cmd_history[i].number);
- X }
- X
- X/* If the array is full, remove the last item */
- X
- X if (l_history == HISTORY_MAX)
- X {
- X if (cmd_history[0].command != null)
- X DELETE (cmd_history[0].command);
- X
- X --l_history;
- X memcpy (&cmd_history[0], &cmd_history[1],
- X sizeof (struct cmd_history) * (HISTORY_MAX - 1));
- X }
- X
- X/* If there are any items in the array */
- X
- X c_history = l_history;
- X Current_Event = (l_history) ? cmd_history[l_history - 1].number + 1 : 0;
- X cmd_history[l_history].number = Current_Event;
- X
- X/* Save the string */
- X
- X cmd_history[l_history++].command = strsave (l_buffer, 0);
- X}
- X
- X/* Print history */
- X
- Xvoid Display_History ()
- X{
- X int i;
- X struct cmd_history *cp = cmd_history;
- X
- X if (!l_history)
- X return;
- X
- X for (i = 0; i < l_history; ++cp, ++i)
- X {
- X v1printf ("%5d: ", cp->number);
- X v1a_puts (cp->command);
- X }
- X}
- X
- X/* Dump history to file */
- X
- Xvoid Dump_History ()
- X{
- X int i;
- X struct cmd_history *cp = cmd_history;
- X FILE *fp;
- X
- X if (!History_Enabled ||
- X ((fp = fopen (lookup (history_file, FALSE)->value, "wt")) ==
- X (FILE *)NULL))
- X return;
- X
- X for (i = 0; i < l_history; ++cp, ++i)
- X {
- X fputs (cp->command, fp);
- X fputc (NL, fp);
- X }
- X
- X fclose (fp);
- X}
- X
- X/* Clear out history */
- X
- Xvoid Clear_History ()
- X{
- X int i;
- X struct cmd_history *cp = cmd_history;
- X
- X for (i = 0; i < l_history; ++cp, ++i)
- X {
- X if (cp->command != null)
- X DELETE (cp->command);
- X }
- X
- X memset (cmd_history, 0, sizeof (struct cmd_history) * HISTORY_MAX);
- X
- X c_history = -1; /* Current entry */
- X l_history = 0; /* End of history array */
- X Current_Event = 0;
- X}
- X
- X/* Output warning message and prompt */
- X
- Xstatic bool Re_start (cp)
- Xchar *cp;
- X{
- X if (cp != (char *)NULL)
- X print_warn (cp);
- X
- X put_prompt (last_prompt);
- X
- X/* Re-initialise */
- X
- X c_buffer_pos = l_buffer;
- X end_buffer = l_buffer;
- X s_cursor = read_cursor_position ();
- X
- X return FALSE;
- X}
- X
- X/* Copy backwards */
- X
- Xstatic void memrcpy (sp1, sp, cnt)
- Xchar *sp1;
- Xchar *sp;
- Xint cnt;
- X{
- X while (cnt--)
- X *(sp1--) = *(sp--);
- X}
- SHAR_EOF
- chmod 0644 shell/sh9.c || echo "restore of shell/sh9.c fails"
- set `wc -c shell/sh9.c`;Sum=$1
- if test "$Sum" != "15932"
- then echo original size 15932, current size $Sum;fi
- echo "x - extracting shell/sh10.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > shell/sh10.c &&
- X/* MS-DOS SHELL - Function Processing
- X *
- X * MS-DOS SHELL - Copyright (c) 1990 Data Logic Limited
- X *
- X * This code 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: sh10.c 1.1 90/01/25 13:40:54 MS_user Exp $
- X *
- X * $Log: sh10.c $
- X * Revision 1.1 90/01/25 13:40:54 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#include "sh.h"
- X
- X/* Function declarations */
- X
- Xstatic void Print_Command (C_Op *);
- Xstatic void Print_IO (IO_Actions *);
- Xstatic void Print_Case (C_Op *);
- Xstatic void Print_IString (char *, int);
- Xstatic void Set_Free_ExTree (C_Op *, void (*)(char *));
- Xstatic void Set_Free_Command (C_Op *, void (*)(char *));
- Xstatic void Set_Free_Case (C_Op *, void (*)(char *));
- Xstatic void Set_ExTree (char *);
- Xstatic void Free_ExTree (char *);
- X
- Xstatic int Print_indent; /* Current indent level */
- X
- X/*
- X * print the execute tree - used for displaying functions
- X */
- X
- Xvoid Print_ExTree (t)
- Xregister C_Op *t;
- X{
- X char **wp;
- X
- X if (t == (C_Op *)NULL)
- X return;
- X
- X/* Check for start of print */
- X
- X if (t->type == TFUNC)
- X {
- X Print_indent = 0;
- X v1_puts (*t->words);
- X v1a_puts (" ()");
- X Print_ExTree (t->left);
- X return;
- X }
- X
- X/* Otherwise, process the tree and print it */
- X
- X switch (t->type)
- X {
- X case TPAREN: /* () */
- X case TCOM: /* A command process */
- X Print_Command (t);
- X return;
- X
- X case TPIPE: /* Pipe processing */
- X Print_ExTree (t->left);
- X Print_IString ("|\n", 0);
- X Print_ExTree (t->right);
- X return;
- X
- X case TLIST: /* Entries in a for statement */
- X Print_ExTree (t->left);
- X Print_ExTree (t->right);
- X return;
- X
- X case TOR: /* || and && */
- X case TAND:
- X Print_ExTree (t->left);
- X
- X if (t->right != (C_Op *)NULL)
- X {
- X Print_IString ((t->type == TAND) ? "&&\n" : "||\n", 0);
- X Print_ExTree (t->right);
- X }
- X
- X return;
- X
- X case TFOR: /* First part of a for statement*/
- X Print_IString ("for ", 0);
- X v1_puts (t->str);
- X
- X if ((wp = t->words) != (char **)NULL)
- X {
- X v1_puts (" in");
- X
- X while (*wp != (char *)NULL)
- X {
- X v1_putc (SP);
- X v1_puts (*wp++);
- X }
- X }
- X
- X v1_putc (NL);
- X Print_IString ("do\n", 1);
- X Print_ExTree (t->left);
- X Print_IString ("done\n", -1);
- X return;
- X
- X case TWHILE: /* WHILE and UNTIL functions */
- X case TUNTIL:
- X Print_IString ((t->type == TWHILE) ? "while " : "until ", 1);
- X Print_ExTree (t->left);
- X Print_IString ("do\n", 0);
- X Print_ExTree (t->right);
- X Print_IString ("done\n", -1);
- X return;
- X
- X case TIF: /* IF and ELSE IF functions */
- X case TELIF:
- X if (t->type == TIF)
- X Print_IString ("if\n", 1);
- X
- X else
- X Print_IString ("elif\n", 1);
- X
- X Print_ExTree (t->left);
- X
- X Print_indent -= 1;
- X Print_IString ("then\n", 1);
- X Print_ExTree (t->right->left);
- X
- X if (t->right->right != (C_Op *)NULL)
- X {
- X Print_indent -= 1;
- X
- X if (t->right->right->type != TELIF)
- X Print_IString ("else\n", 1);
- X
- X Print_ExTree (t->right->right);
- X }
- X
- X if (t->type == TIF)
- X Print_IString ("fi\n", -1);
- X
- X return;
- X
- X case TCASE: /* CASE function */
- X Print_IString ("case ", 1);
- X v1_puts (t->str);
- X v1a_puts (" do");
- X Print_Case (t->left);
- X Print_IString (" esac\n", -1);
- X return;
- X
- X case TBRACE: /* {} statement */
- X Print_IString ("{\n", 1);
- X if (t->left != (C_Op *)NULL)
- X Print_ExTree (t->left);
- X
- X Print_IString ("}\n", -1);
- X return;
- X }
- X}
- X
- X/*
- X * Print a command line
- X */
- X
- Xstatic void Print_Command (t)
- Xregister C_Op *t;
- X{
- X char *cp;
- X IO_Actions **iopp;
- X char **wp = t->words;
- X char **owp = wp;
- 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 ((cp == (char *)NULL) && (t->ioact == (IO_Actions **)NULL))
- X {
- X Print_IString (null, 0);
- X
- X while (*owp != (char *)NULL)
- X v1a_puts (*(owp++));
- X
- X return;
- X }
- X }
- X
- X/* Parenthesis ? */
- X
- X if (t->type == TPAREN)
- X {
- X Print_IString ("(\n", 1);
- X Print_ExTree (t->left);
- X Print_IString (")", -1);
- X }
- X
- X else
- X {
- X Print_IString (null, 0);
- X
- X while (*owp != (char *)NULL)
- X {
- X v1_puts (*owp++);
- X
- X if (*owp != (char *)NULL)
- X v1_putc (SP);
- X }
- X }
- X
- X/* Set up anyother IO required */
- X
- X if ((iopp = t->ioact) != (IO_Actions **)NULL)
- X {
- X while (*iopp != (IO_Actions *)NULL)
- X Print_IO (*iopp++);
- X }
- X
- X v1_putc (NL);
- X}
- X
- X/*
- X * Print the IO re-direction
- X */
- X
- Xstatic void Print_IO (iop)
- Xregister IO_Actions *iop;
- X{
- X int unit = iop->io_unit;
- X static char *cunit = " x";
- X
- X if (unit == IODEFAULT) /* take default */
- X unit = (iop->io_flag & (IOREAD | IOHERE)) ? STDIN_FILENO
- X : STDOUT_FILENO;
- X
- X/* Output unit number */
- X
- X cunit[1] = (char)(unit + '0');
- X v1_puts (cunit);
- X
- X switch (iop->io_flag)
- X {
- X case IOHERE:
- X case IOHERE | IOXHERE:
- X v1_putc ('<');
- X
- X case IOREAD:
- X v1_putc ('<');
- X break;
- X
- X case IOWRITE | IOCAT:
- X v1_putc ('>');
- X
- X case IOWRITE:
- X v1_putc ('>');
- X break;
- X
- X case IODUP:
- X v1_puts (">&");
- X v1_putc (*iop->io_name);
- X return;
- X }
- X
- X v1_puts (iop->io_name);
- X}
- X
- X/*
- X * Print out the contents of a case statement
- X */
- X
- Xstatic void Print_Case (t)
- XC_Op *t;
- X{
- X register C_Op *t1;
- X register char **wp;
- X
- X if (t == (C_Op *)NULL)
- X return;
- X
- X/* type - TLIST - go down the left tree first and then processes this level */
- X
- X if (t->type == TLIST)
- X {
- X Print_Case (t->left);
- X t1 = t->right;
- X }
- X
- X else
- X t1 = t;
- X
- X/* Output the conditions */
- X
- X Print_IString (null, 0);
- X
- X for (wp = t1->words; *wp != (char *)NULL;)
- X {
- X v1_puts (*(wp++));
- X
- X if (*wp != (char *)NULL)
- X v1_puts (" | ");
- X }
- X
- X v1a_puts (" )");
- X Print_indent += 1;
- X
- X/* Output the commands */
- X
- X Print_ExTree (t1->left);
- X Print_IString (";;\n", -1);
- X}
- X
- X/*
- X * Print an indented string
- X */
- X
- Xstatic void Print_IString (cp, indent)
- Xchar *cp;
- Xint indent;
- X{
- X int i;
- X
- X if (indent < 0)
- X Print_indent += indent;
- X
- X for (i = 0; i < (Print_indent / 2); i++)
- X v1_putc ('\t');
- X
- X if (Print_indent % 2)
- X v1_puts (" ");
- X
- X v1_puts (cp);
- X
- X if (indent > 0)
- X Print_indent += indent;
- X}
- X
- X/*
- X * Look up a function in the save tree
- X */
- X
- XFun_Ops *Fun_Search (name)
- Xchar *name;
- X{
- X Fun_Ops *fp;
- X
- X for (fp = fun_list; fp != (Fun_Ops *)NULL; fp = fp->next)
- X {
- X if (strcmp (*(fp->tree->words), name) == 0)
- X return fp;
- X }
- X
- X return (Fun_Ops *)NULL;
- X}
- X
- X/*
- X * Save or delete a function tree
- X */
- X
- Xvoid Save_Function (t, delete_only)
- XC_Op *t;
- Xbool delete_only; /* True - delete */
- X{
- X char *name = *t->words;
- X register Fun_Ops *fp = Fun_Search (name);
- X Fun_Ops *p_fp = (Fun_Ops *)NULL;
- X
- X/* Find the entry */
- X
- X for (fp = fun_list; (fp != (Fun_Ops *)NULL) &&
- X (strcmp (*(fp->tree->words), name) != 0);
- X p_fp = fp, fp = fp->next);
- X
- X/* If it already exists, free the tree and delete the entry */
- X
- X if (fp != (Fun_Ops *)NULL)
- X {
- X Set_Free_ExTree (fp->tree, Free_ExTree);
- X
- X if (p_fp == (Fun_Ops *)NULL)
- X fun_list = fp->next;
- X
- X else
- X p_fp->next = fp->next;
- X
- X DELETE (fp);
- X }
- X
- X/* If delete only - exit */
- X
- X if (delete_only)
- X return;
- X
- X/* Create new entry */
- X
- X if ((fp = (Fun_Ops *)space (sizeof (Fun_Ops))) == (Fun_Ops *)NULL)
- X return;
- X
- X setarea ((char *)fp, 0);
- X Set_Free_ExTree (t, Set_ExTree);
- X
- X fp->tree = t;
- X fp->next = fun_list;
- X fun_list = fp;
- X}
- X
- X/*
- X * Set ExTree areas to zero function
- X */
- X
- Xstatic void Set_ExTree (s)
- Xchar *s;
- X{
- X setarea (s, 0);
- X}
- X
- X/*
- X * Free the ExTree function
- X */
- X
- Xstatic void Free_ExTree (s)
- Xchar *s;
- X{
- X DELETE (s);
- X}
- X
- X/*
- X * Set/Free function tree area by recursively processing of tree
- X */
- X
- Xstatic void Set_Free_ExTree (t, func)
- XC_Op *t;
- Xvoid (*func)(char *);
- X{
- X char **wp;
- X
- X if (t == (C_Op *)NULL)
- X return;
- X
- X/* Check for start of print */
- X
- X if (t->type == TFUNC)
- X {
- X (*func)(*t->words);
- X (*func)((char *)t->words);
- X Set_Free_ExTree (t->left, func);
- X }
- X
- X/* Otherwise, process the tree and print it */
- X
- X switch (t->type)
- X {
- X case TPAREN: /* () */
- X case TCOM: /* A command process */
- X Set_Free_Command (t, func);
- X break;
- X
- X case TPIPE: /* Pipe processing */
- X case TLIST: /* Entries in a for statement */
- X case TOR: /* || and && */
- X case TAND:
- X case TWHILE: /* WHILE and UNTIL functions */
- X case TUNTIL:
- X Set_Free_ExTree (t->left, func);
- X Set_Free_ExTree (t->right, func);
- X break;
- X
- X case TFOR: /* First part of a for statement*/
- X (*func)(t->str);
- X
- X if ((wp = t->words) != (char **)NULL)
- X {
- X while (*wp != (char *)NULL)
- X (*func) (*wp++);
- X
- X (*func)((char *)t->words);
- X }
- X
- X Set_Free_ExTree (t->left, func);
- X break;
- X
- X case TIF: /* IF and ELSE IF functions */
- X case TELIF:
- X Set_Free_ExTree (t->right->left, func);
- X Set_Free_ExTree (t->right->right, func);
- X (*func)((char *)t->right);
- X
- X case TBRACE: /* {} statement */
- X Set_Free_ExTree (t->left, func);
- X break;
- X
- X case TCASE: /* CASE function */
- X (*func)(t->str);
- X Set_Free_Case (t->left, func);
- X break;
- X }
- X
- X (*func)((char *)t);
- X}
- X
- X/*
- X * Set/Free a command line
- X */
- X
- Xstatic void Set_Free_Command (t, func)
- XC_Op *t;
- Xvoid (*func)(char *);
- X{
- X IO_Actions **iopp;
- X char **wp = t->words;
- X
- X/* Parenthesis ? */
- X
- X if (t->type == TPAREN)
- X Set_Free_ExTree (t->left, func);
- X
- X else
- X {
- X while (*wp != (char *)NULL)
- X (*func)(*wp++);
- X
- X (*func) ((char *)t->words);
- X }
- X
- X/* Process up any IO required */
- X
- X if ((iopp = t->ioact) != (IO_Actions **)NULL)
- X {
- X while (*iopp != (IO_Actions *)NULL)
- X {
- X (*func)((char *)(*iopp)->io_name);
- X (*func)((char *)*iopp);
- X iopp++;
- X }
- X
- X (*func)((char *)t->ioact);
- X }
- X}
- X
- X/*
- X * Set/Free the contents of a case statement
- X */
- X
- Xstatic void Set_Free_Case (t, func)
- XC_Op *t;
- Xvoid (*func)(char *);
- X{
- X register C_Op *t1;
- X register char **wp;
- X
- X if (t == (C_Op *)NULL)
- X return;
- X
- X/* type - TLIST - go down the left tree first and then processes this level */
- X
- X if (t->type == TLIST)
- X {
- X Set_Free_Case (t->left, func);
- X t1 = t->right;
- X }
- X
- X else
- X t1 = t;
- X
- X/* Set/Free the conditions */
- X
- X for (wp = t1->words; *wp != (char *)NULL;)
- X (*func)(*(wp++));
- X
- X (*func)((char *)t1->words);
- X
- X Set_Free_ExTree (t1->left, func);
- X}
- SHAR_EOF
- chmod 0644 shell/sh10.c || echo "restore of shell/sh10.c fails"
- set `wc -c shell/sh10.c`;Sum=$1
- if test "$Sum" != "10869"
- then echo original size 10869, current size $Sum;fi
- echo "x - extracting shell/sh0.asm (Text)"
- sed 's/^X//' << 'SHAR_EOF' > shell/sh0.asm &&
- X TITLE sh0.asm
- X NAME sh0
- X .8087
- X
- X; MS-DOS SHELL - Swapper
- X;
- X; MS-DOS SHELL - Copyright (c) 1989 Data Logic Limited.
- X;
- X; MS-DOS SHELL - Copyright (c) 1990 Data Logic Limited
- X;
- X; This code 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: sh0.asm 1.1 90/01/25 13:43:36 MS_user Exp $
- X;
- X; $Log: sh0.asm $
- X; Revision 1.1 90/01/25 13:43:36 MS_user
- X; Initial revision
- X;
- X;
- X
- X;
- X; Segment declarations
- X;
- X
- XSH0_TEXT segment word public 'CODE'
- XSH0_TEXT ends
- X
- X_DATA segment word public 'DATA'
- X_DATA ends
- X
- XCONST segment word public 'CONST'
- XCONST ends
- X
- X_BSS segment word public 'BSS'
- X_BSS ends
- X
- XDGROUP group CONST, _BSS, _DATA
- X
- X;
- X; Declare external functions and data
- X;
- X extrn _raise:far
- X extrn __maperror:far
- X extrn _errno:word
- X extrn __psp:word
- X
- X;
- X; Start of the spawn function
- X;
- X
- XSH0_TEXT segment
- X assume cs: SH0_TEXT, ds: NOTHING, ss: DGROUP
- X
- X;
- X; For this function, all the code and data space are in the code space
- X;
- X public _cmd_line
- X public _path_line
- X public _SW_intr
- X public _SW_Blocks
- X public _SW_fp
- X public _SW_I0_V_BX
- X public _SW_I0_V_ES
- X public _SW_I23_V_ES
- X public _SW_I23_V_BX
- X public _SW_EMstart
- X public _SW_Mode
- X public _SW_EMSFrame
- X
- X_cmd_line db 129 dup (?) ; Command line
- X_path_line db 80 dup (?) ; Path line
- X_SW_Blocks dw 0 ; Number of blocks to read/write
- X_SW_fp dw 0 ; File ID
- X_SW_I23_V_ES dw 0 ; Interrupt 23 address
- X_SW_I23_V_BX dw 0
- X_SW_I0_V_BX dw 0 ; Our Interrupt zero value
- X_SW_I0_V_ES dw 0
- X_SW_EMstart dd 0100000H ; Default Extended Mem start
- X_SW_Mode dw 0 ; Type of swapping to do
- X ; 1 - disk
- X ; 2 - Extended memory
- X ; 3 - Expanded memory
- X_SW_EMSFrame dw 0 ; EMS Frame segment
- X_SW_intr dw 0 ; Interrupt 23 detected.
- X
- X
- X;
- X; Some addition variables
- X;
- X
- XSW_LMstart dd 0 ; Low Mem start for Extended Mem swap
- XN_mcb dw 0 ; Start write address
- XResult dw 0 ; Return value
- XInShell db 0 ; In shell flag for Interrupt 23
- X
- X;
- X; Stack save pointers
- X;
- X
- XS_ss dw 0 ; Save Stack pointers
- XS_sp dw 0
- XS_di dw 0 ; Save DI, SI
- XS_si dw 0
- XS_ds dw 0 ; Save the original DS
- X
- X;
- X; Two blank FCB
- X;
- X
- XFCB1 dw 16 dup (?)
- XFCB2 dw 16 dup (?)
- X
- X;
- X; Extended Memory Global Descriptor tables
- X;
- X
- XGD_table equ $
- XGDT_Dummy dw 4 dup (0) ; Dummy
- XGDT_self dw 4 dup (0) ; For self
- XGDT_src equ $ ; Source
- X dw 04000H ; Length - 16K bytes
- XGDT_src_low dw 0 ; Low Order address
- XGDT_src_high db 0 ; High Order address
- X db 093h ; Access Rights
- X dw 0 ; Reserved
- XGDT_dest equ $ ; Destination
- X dw 04000H ; Length - 16K bytes
- XGDT_dest_low dw 0 ; Low Order address
- XGDT_dest_high db 0 ; High Order address
- X db 093h ; Access Rights
- X dw 0 ; Reserved
- XGDT_bios dw 4 dup (0) ; Bios
- XGDT_stack dw 4 dup (0) ; Stack
- X
- X;
- X; Execute interrupt structure
- X;
- X
- Xexec_parms equ $
- Xexec_env dw 0
- X dw offset _cmd_line ; Command line address
- Xexec_cseg dw ?
- X dw offset FCB1 ; FCB1 address
- Xexec_f1seg dw ?
- X dw offset FCB2 ; FCB1 address
- Xexec_f2seg dw ?
- X
- XSwap_PANIC db 'PANIC: Swap file re-load error - REBOOT', 0aH, 0dH
- X db '$'
- X
- XSwap_DZERO db 'PANIC: Divide by zero', 0aH, 0dH
- X db '$'
- X
- X;
- X; OK - exec requires a local stack, cause some programs overwrite it
- X;
- X even
- X db 398 dup (0)
- XLocal_Stack:
- X dw 0
- X
- X;
- X; Code starts
- X;
- X public _SA_spawn
- X
- X_SA_spawn proc far
- X
- X push bp
- X mov bp, sp
- X
- X;
- X; Entry Offsets
- X;
- X; Environment = 6
- X;
- X
- X mov word ptr cs:S_di, di ; Save registers
- X mov word ptr cs:S_si, si
- X mov word ptr cs:S_ds, ds
- X
- X;
- X; Set up to ingnore Control C interrupts
- X;
- X
- X push ds
- X mov ax, 02523H ; Set Control C Interrupt
- X mov dx, offset SA_IRET
- X push cs
- X pop ds
- X mov byte ptr cs:InShell, 0 ; Set In shell flag for Interrupt 23
- X int 021H
- X
- X mov ax, 02500H ; Set Divide Zero Interrupt
- X mov dx, offset SA_DZERO
- X push cs
- X pop ds
- X int 021H
- X
- X pop ds
- X
- X;
- X; Save the length of the current MCB block;
- X;
- X
- X mov ax, word ptr ds:__psp
- X dec ax
- X mov word ptr cs:N_mcb, ax ; Save MCB address for swap out
- X
- X; Calculate low mem start for extended memory
- X
- X mov bx, ax ; Save copy
- X mov cl, 4 ; mult low order by 16
- X shl ax, cl
- X mov word ptr cs:SW_LMstart, ax ; Save low order
- X mov cl, 12 ; div by 16 ** 3
- X shr bx, cl
- X mov byte ptr cs:SW_LMstart + 2, bl ; Save low order
- X
- X;
- X; Set up Environment segment in execute structure
- X;
- X
- X mov bx, cs
- X mov ax, offset Env_OWrite
- X mov cl, 4
- X shr ax, cl
- X add ax, bx
- X mov word ptr cs:exec_env, ax ; Save Env seg.
- X
- X;
- X; Set up rest of execute structure
- X;
- X
- X mov word ptr cs:exec_cseg, cs ; Command line address
- X mov word ptr cs:exec_f1seg, cs ; FCB 1 address
- X mov word ptr cs:exec_f2seg, cs ; FCB 2 address
- X
- X;
- X; Generate the FCBs
- X;
- X
- X mov ax, cs ; Set up segments
- X mov ds, ax
- X mov es, ax
- X
- X mov ax, 02901H ; Set up FCB interrupt
- X mov si, offset _cmd_line + 1
- X mov di, offset FCB1 ; FCB 1;
- X
- X int 021H ; Execute the interrupt
- X
- X mov ax, cs ; Set up segment
- X mov es, ax
- X
- X mov ax, 02901H ; Reset AX cause errors are ignored
- X mov di, offset FCB2 ; FCB 2;
- X
- X int 021H ; Execute the interrupt
- X
- X;
- X; Copy out to the swap file
- X;
- X
- X mov si, word ptr cs:_SW_Blocks ; Load Number of blocks to read
- X mov bx, word ptr cs:_SW_fp ; Load file handler
- X
- X; load up extended memory GDT for destination
- X
- X mov ax, word ptr cs:_SW_EMstart
- X mov dl, byte ptr cs:_SW_EMstart + 2
- X call $GDT_dest_load
- X
- X;
- X; set up DS register with start of start copy
- X;
- X
- X mov ax, word ptr cs:N_mcb ; Load the start address
- X mov ds, ax
- X
- X mov ax, word ptr cs:SW_LMstart ; Load Full start address
- X mov dl, byte ptr cs:SW_LMstart + 2
- SHAR_EOF
- echo "End of part 4"
- echo "File shell/sh0.asm is continued in part 5"
- echo "5" > s2_seq_.tmp
- exit 0
-
- --
- Regards,
-
- Ian Stewartson
- Data Logic Ltd.
-
-
-