home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-02-21 | 78.9 KB | 3,980 lines |
-
- #!/bin/sh
- # this is part 2 of a multipart archive
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file lib/ms_dio.c continued
- #
- CurArch=2
- 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 lib/ms_dio.c"
- sed 's/^X//' << 'SHAR_EOF' >> lib/ms_dio.c
- X
- X if (FP->drive & HD_FLAG)
- X {
- X struct partition *pp, tp;
- X
- X/* System call failed - no device */
- X
- X if ((iregs.x.cflag) || (ndrive >= iregs.h.dl))
- X {
- X free (FP);
- X errno = ENOENT;
- X return -1;
- X }
- X
- X/* OK - save the parameters */
- X
- X FP->m_cyl = (iregs.h.ch | ((iregs.h.cl & 0x0c0) << 2)) + 2;
- X FP->m_head = iregs.h.dh + 1;
- X FP->m_sector = iregs.h.cl & 0x03f;
- X FP->m_scount = FP->m_cyl * FP->m_head * FP->m_sector;
- X
- X/* If this is not partition 0 - read the partition table */
- X
- X if (FP->partition)
- X {
- X if (dio_do (BIOS_READ, FP, buf, 0L, 1) == -1)
- X {
- X free (FP);
- X return -1;
- X }
- X
- X if (*(int *)&buf[510] != 0xaa55)
- X {
- X errno = ENOENT;
- X return -1;
- X }
- X
- X/* Sort the partition table */
- X
- X pp = (struct partition *)&buf[0x1be];
- X
- X for (i = 0; i < 4; i++)
- X {
- X for (j = 0; j < 3; j++)
- X {
- X if (((!pp[j].offset) && pp[j + 1].offset) ||
- X ((pp[j].offset > pp[j + 1].offset) &&
- X pp[j + 1].offset))
- X {
- X tp = pp[j];
- X pp[j] = pp[j + 1];
- X pp[j + 1] = tp;
- X }
- X }
- X }
- X
- X if (pp[FP->partition - 1].offset == 0L)
- X {
- X errno = ENOENT;
- X return -1;
- X }
- X
- X FP->m_start = pp[FP->partition - 1].offset;
- X FP->m_scount = pp[FP->partition - 1].size;
- X }
- X }
- X
- X/* Floppy disk - get parameters. We try our best here, but DOS 3.3 allows
- X * you to format any number of sectors per track and tracks per disk
- X */
- X
- X else
- X {
- X
- X/* System call failed - think this means we're on an XT. So set up the
- X * XT parameters
- X */
- X
- X if ((iregs.x.cflag) && (ndrive < 2))
- X {
- X iregs.h.bl = 0x01;
- X FP->m_cyl = 40;
- X FP->m_head = 2;
- X FP->m_sector = 9;
- X }
- X
- X/* No Drive */
- X
- X else if ((iregs.x.cflag) || (ndrive >= iregs.h.dl))
- X {
- X free (FP);
- X errno = ENOENT;
- X return -1;
- X }
- X
- X/* OK - save the parameters */
- X
- X else
- X {
- X FP->m_cyl = iregs.h.ch;
- X FP->m_head = iregs.h.dh + 1;
- X FP->m_sector = iregs.h.cl;
- X }
- X
- X FP->m_scount = FP->m_cyl * FP->m_head * FP->m_sector;
- X
- X/* High capacity drive ? */
- X
- X if ((iregs.h.bl == 0x02) || (iregs.h.bl == 0x03))
- X {
- X
- X/* Try reading sector 0 */
- X
- X FP->m_sector = (iregs.h.bl == 0x02) ? 9 : 15;
- X
- X/* If it failed - switch to the other type */
- X
- X if (dio_do (BIOS_READ, FP, buf, 0L, 1) == -1)
- X {
- X FP->m_sector = (iregs.h.bl == 0x02) ? 15 : 9;
- X
- X iregs.h.ah = 0x17;
- X iregs.h.dl = (unsigned char)FP->drive;
- X iregs.h.al = (unsigned char)(5 - iregs.h.bl);
- X int86 (0x13, &iregs, &iregs);
- X }
- X }
- X
- X/* 8 or 9 Sectors, 1 or 2 heads */
- X
- X if (((iregs.h.bl > 0x00) || (iregs.h.bl < 0x04)) &&
- X (FP->m_sector == 9))
- X {
- X FP->m_scount = FP->m_cyl * FP->m_head * FP->m_sector;
- X
- X/* Check to see if sector 8 exists */
- X
- X if (dio_do (BIOS_READ, FP, buf, 8L, 1) == -1)
- X FP->m_sector = 8;
- X
- X/* Check to see if sector 380 exists */
- X
- X if (dio_do (BIOS_READ, FP, buf, 380L, 1) == -1)
- X FP->m_head = 1;
- X }
- X
- X/* 720K drive - read sector 15 to see if 1.4M */
- X
- X else if (iregs.h.bl == 0x04)
- X {
- X FP->m_scount = FP->m_cyl * FP->m_head * FP->m_sector;
- X
- X if (dio_do (BIOS_READ, FP, buf, 17L, 1) == -1)
- X FP->m_sector = 9;
- X }
- X
- X FP->m_scount = FP->m_cyl * FP->m_head * FP->m_sector;
- X }
- X
- X/* Set up the file descriptor entry and return the number */
- X
- X MS_io_fs[fp] = FP;
- X return fp + MS_MODIFIER;
- X }
- X
- X else
- X return open (name, mode, permissions);
- X}
- X
- X/* fstat function */
- X
- Xint dio_fstat (fp, St)
- Xint fp;
- Xstruct stat *St;
- X{
- X struct fs *FP;
- X
- X if (fp < MS_MODIFIER)
- X return fstat (fp, St);
- X
- X if ((FP = dio_fpcheck (fp)) == (struct fs *)NULL)
- X return -1;
- X
- X/* Dummy values */
- X
- X memset (St, 0, sizeof (struct stat));
- X St->st_mode = 0x61b6;
- X St->st_nlink = 1;
- X
- X if (FP->drive == DRIVE_RAM)
- X {
- X St->st_size = MEGABYTE;
- X St->st_rdev = 0x0300;
- X }
- X
- X else
- X {
- X St->st_rdev = ((FP->drive & (~HD_FLAG)) * 10 + FP->partition) |
- X ((FP->drive & HD_FLAG) ? 0x0200 : 0x0100);
- X St->st_dev = FP->drive;
- X }
- X
- X St->st_atime = time ((time_t *)NULL);
- X St->st_ctime = St->st_ctime;
- X St->st_mtime = St->st_atime;
- X return 0;
- X}
- X
- X/*
- X * Close function
- X */
- X
- Xint dio_close (fp)
- Xint fp;
- X{
- X struct fs *FP;
- X
- X if (fp < MS_MODIFIER)
- X return close (fp);
- X
- X if ((FP = dio_fpcheck (fp)) == (struct fs *)NULL)
- X return -1;
- X
- X free (FP);
- X MS_io_fs[fp - MS_MODIFIER] = (struct fs *)NULL;
- X return 0;
- X}
- X
- X/*
- X * Seek function
- X */
- X
- Xlong dio_lseek (fp, off, type)
- Xint fp;
- Xoff_t off;
- Xint type;
- X{
- X off_t check;
- X struct fs *FP;
- X
- X if (fp < MS_MODIFIER)
- X return lseek (fp, off, type);
- X
- X if ((FP = dio_fpcheck (fp)) == (struct fs *)NULL)
- X return -1L;
- X
- X switch (type)
- X {
- X case SEEK_SET:
- X check = off;
- X break;
- X
- X case SEEK_CUR:
- X check = off + FP->location;
- X break;
- X
- X case SEEK_END:
- X default:
- X errno = EINVAL;
- X return -1L;
- X }
- X
- X if (check < 0L)
- X {
- X errno = EINVAL;
- X return -1L;
- X }
- X
- X return (FP->location = check);
- X}
- X
- X/* Check for a valid file pointer */
- X
- Xstatic struct fs *dio_fpcheck (fp)
- Xint fp;
- X{
- X struct fs *FP;
- X
- X if (((FP = MS_io_fs[fp - MS_MODIFIER]) == (struct fs *)NULL) ||
- X (fp - MS_MODIFIER >= _NFILE) || (fp - MS_MODIFIER < 0))
- X {
- X errno = EBADF;
- X return (struct fs *)NULL;
- X }
- X
- X return FP;
- X}
- X
- X/* Check for a valid file name */
- X
- Xstatic int dio_fncheck (name)
- Xchar *name;
- X{
- X
- X/* Check for hard disk */
- X
- X if (isdigit(name[7]) && isdigit(name[8]) && (strlen (name) == 9) &&
- X (!strnicmp (name, "/dev/hd", 6)))
- X {
- X int i = atoi (&name[7]);
- X
- X return ((i % 10) > 4) ? -1 : i | HD_FLAG;
- X }
- X
- X/* Check for floppy disk */
- X
- X else if (isdigit(name[7]) && (strlen (name) == 8) &&
- X (!strnicmp (name, "/dev/fd", 6)))
- X return name[7] - '0';
- X
- X else if (!stricmp (name, "/dev/kmem"))
- X return DRIVE_RAM;
- X
- X return -1;
- X}
- X
- X/* Get file status */
- X
- Xint dio_stat (name, St)
- Xchar *name;
- Xstruct stat *St;
- X{
- X int drive;
- X
- X if ((drive = dio_fncheck (name)) == -1)
- X return stat (name, St);
- X
- X memset (St, 0, sizeof (struct stat));
- X St->st_mode = 0x61b6;
- X St->st_nlink = 1;
- X St->st_atime = time ((time_t *)NULL);
- X St->st_ctime = St->st_ctime;
- X St->st_mtime = St->st_atime;
- X
- X if (drive == DRIVE_RAM)
- X {
- X St->st_size = MEGABYTE;
- X St->st_rdev = 0x0300;
- X }
- X
- X else
- X {
- X St->st_rdev = (drive & (~HD_FLAG)) | ((drive & HD_FLAG) ? 0x0200
- X : 0x0100);
- X St->st_dev = drive;
- X }
- X
- X return 0;
- X}
- X
- X/* Check file access */
- X
- Xint dio_access (name, mode)
- Xchar *name;
- Xint mode;
- X{
- X if (dio_fncheck (name) == -1)
- X return access (name, mode);
- X
- X else if (mode & 1)
- X {
- X errno = EACCES;
- X return -1;
- X }
- X
- X return 0;
- X}
- X
- X/* Change file permissions */
- X
- Xint dio_chmod (name, mode)
- Xchar *name;
- Xint mode;
- X{
- X return (dio_fncheck (name) == -1) ? chmod (name, mode) : 0;
- X}
- X
- X/* Create file */
- X
- Xint dio_creat (name, mode)
- Xchar *name;
- Xint mode;
- X{
- X return (dio_fncheck (name) == -1) ? creat (name, mode)
- X : dio_open (name, O_WRONLY, mode);
- X}
- X
- X/* Duplicate handler */
- X
- Xint dio_dup (fp)
- Xint fp;
- X{
- X struct fs *FP; /* New pointer */
- X struct fs *FP1; /* Old pointer */
- X
- X if (fp < MS_MODIFIER)
- X return dup (fp);
- X
- X if ((FP1 = dio_fpcheck (fp)) == (struct fs *)NULL)
- X return -1;
- X
- X for (fp = 0; (fp < _NFILE) && (MS_io_fs[fp] != (struct fs *)NULL); fp++)
- X ;
- X
- X if ((fp == _NFILE) ||
- X ((FP = (struct fs *)malloc (sizeof (struct fs))) == (struct fs *)NULL))
- X {
- X errno = EMFILE;
- X return -1;
- X }
- X
- X MS_io_fs[fp] = FP;
- X *FP = *FP1;
- X return fp;
- X}
- X
- X/* Check if tty */
- X
- Xint dio_isatty (fp)
- Xint fp;
- X{
- X if (fp < MS_MODIFIER)
- X return isatty (fp);
- X
- X return 0;
- X}
- X
- X/* Tell location */
- X
- Xlong dio_tell (fp)
- Xint fp;
- X{
- X struct fs *FP;
- X
- X if (fp < MS_MODIFIER)
- X return tell (fp);
- X
- X return ((FP = dio_fpcheck (fp)) == (struct fs *)NULL) ? -1L : FP->location;
- X}
- SHAR_EOF
- echo "File lib/ms_dio.c is complete"
- chmod 0644 lib/ms_dio.c || echo "restore of lib/ms_dio.c fails"
- set `wc -c lib/ms_dio.c`;Sum=$1
- if test "$Sum" != "17329"
- then echo original size 17329, current size $Sum;fi
- echo "x - extracting lib/director.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > lib/director.c &&
- X/*
- X * @(#)msd_dir.c 1.4 87/11/06 Public Domain.
- X *
- X * A public domain implementation of BSD directory routines for
- X * MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
- X * August 1897
- X */
- X
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <malloc.h>
- X#include <string.h>
- X#include <limits.h>
- X#include <errno.h>
- X#include <dirent.h>
- X#include <dos.h>
- X
- X#define ATTRIBUTES (_A_SUBDIR | _A_HIDDEN | _A_SYSTEM | \
- X _A_NORMAL | _A_RDONLY | _A_ARCH | _A_VOLID)
- X
- Xstatic void free_dircontents (struct _dircontents *);
- X
- XDIR *opendir(name)
- Xchar *name;
- X{
- X struct stat statb;
- X DIR *dirp;
- X char c;
- X struct _dircontents *dp;
- X char nbuf[PATH_MAX + NAME_MAX + 2];
- X struct find_t dtabuf;
- X
- X if (stat (name, &statb) < 0)
- X return (DIR *) NULL;
- X
- X if (!S_ISDIR(statb.st_mode))
- X {
- X errno = ENOTDIR;
- X return (DIR *)NULL;
- X }
- X
- X if ((dirp = (DIR *) malloc (sizeof (DIR))) == (DIR *) NULL)
- X return (DIR *) NULL;
- X
- X if (*name && (c = name[strlen (name) - 1]) != '\\' && c != '/')
- X (void) strcat (strcpy (nbuf, name), "\\*.*");
- X
- X else
- X (void) strcat (strcpy (nbuf, name), "*.*");
- X
- X dirp->dd_loc = 0;
- X dirp->dd_cp = (struct _dircontents *) NULL;
- X dirp->dd_contents = (struct _dircontents *) NULL;
- X
- X if (_dos_findfirst (nbuf, ATTRIBUTES, &dtabuf) != 0)
- X return dirp;
- X
- X do
- X {
- X if (((dp = (struct _dircontents *) malloc(sizeof(struct _dircontents))) == (struct _dircontents *) NULL) ||
- X ((dp->_d_entry = strdup (dtabuf.name)) == (char *) NULL))
- X {
- X if (dp != (char *)NULL)
- X free ((char *) dp);
- X
- X free_dircontents (dirp->dd_contents);
- X return (DIR *) NULL;
- X }
- X
- X if (dirp->dd_contents)
- X dirp->dd_cp = dirp->dd_cp->_d_next = dp;
- X
- X else
- X dirp->dd_contents = dirp->dd_cp = dp;
- X
- X dp->_d_next = (struct _dircontents *) NULL;
- X
- X } while (_dos_findnext (&dtabuf) == 0);
- X
- X dirp->dd_cp = dirp->dd_contents;
- X
- X return dirp;
- X}
- X
- Xint closedir(dirp)
- XDIR *dirp;
- X{
- X free_dircontents (dirp->dd_contents);
- X free ((char *) dirp);
- X return 0;
- X}
- X
- Xstruct dirent *readdir(dirp)
- XDIR *dirp;
- X{
- X static struct dirent dp;
- X
- X if (dirp->dd_cp == (struct _dircontents *) NULL)
- X return (struct dirent *) NULL;
- X
- X dp.d_reclen = strlen (strcpy (dp.d_name, dirp->dd_cp->_d_entry));
- X dp.d_off = dirp->dd_loc * 32;
- X dp.d_ino = (ino_t)++dirp->dd_loc;
- X dirp->dd_cp = dirp->dd_cp->_d_next;
- X strlwr (dp.d_name);
- X
- X return &dp;
- X}
- X
- Xvoid rewinddir (dirp)
- XDIR *dirp;
- X{
- X seekdir (dirp, (off_t)0);
- X}
- X
- Xvoid seekdir (dirp, off)
- XDIR *dirp;
- Xoff_t off;
- X{
- X long i = off;
- X struct _dircontents *dp;
- X
- X if (off < 0L)
- X return;
- X
- X for (dp = dirp->dd_contents ; --i >= 0 && dp ; dp = dp->_d_next)
- X ;
- X
- X dirp->dd_loc = off - (i + 1);
- X dirp->dd_cp = dp;
- X}
- X
- Xoff_t telldir(dirp)
- XDIR *dirp;
- X{
- X return dirp->dd_loc;
- X}
- X
- Xstatic void free_dircontents(dp)
- Xstruct _dircontents *dp;
- X{
- X struct _dircontents *odp;
- X
- X while (dp)
- X {
- X if (dp->_d_entry)
- X free(dp->_d_entry);
- X
- X dp = (odp = dp)->_d_next;
- X free((char *) odp);
- X }
- X}
- SHAR_EOF
- chmod 0644 lib/director.c || echo "restore of lib/director.c fails"
- set `wc -c lib/director.c`;Sum=$1
- if test "$Sum" != "3067"
- then echo original size 3067, current size $Sum;fi
- echo "x - extracting lib/popen.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > lib/popen.c &&
- X/*
- X * popen/pclose: simple MS-DOS piping scheme to imitate UNIX pipes
- X */
- X
- X#include <sys/types.h>
- X#include <stdio.h>
- X#include <string.h>
- X#include <errno.h>
- X#include <process.h>
- X#include <limits.h>
- X#include <stdlib.h>
- X#include <unistd.h>
- X
- Xtypedef struct pipes {
- X FILE *p_fp; /* File id */
- X char *p_process; /* Program name */
- X char *p_file; /* Pipe file name */
- X int p_status; /* Status for close to return */
- X /* Read pipes only */
- X bool p_write; /* Read or write */
- X} PIPE;
- X
- Xstatic PIPE P_list[_NFILE]; /* The pipe structures */
- Xstatic int Pipes_Inited = 0; /* Initialised ? */
- Xstatic int Unique_Pipe = 0;
- X
- Xstatic PIPE *_p_save_entry (char *, bool);
- Xstatic int _p_run (char *);
- Xstatic int _p_reset_entry (PIPE *, int);
- Xstatic PIPE *_p_get_entry (FILE *);
- X
- X/* Set up a pipe structure */
- X
- Xstatic PIPE *_p_save_entry (prog, mode)
- Xchar *prog;
- Xbool mode;
- X{
- X FILE *fp; /* File handler */
- X PIPE *pp; /* Pipe handler structure */
- X char tmpfile[NAME_MAX + PATH_MAX + 2];
- X char *tmpdir; /* Points to directory prefix of pipe */
- X
- X/* Find out where we should put temporary files */
- X
- X if ((tmpdir = getenv ("TMPDIR")) == (char *) NULL)
- X tmpdir = getenv ("TMP");
- X
- X/* Use temporary directory if available */
- X
- X if (tmpdir == (char *)NULL)
- X tmpdir = ".";
- X
- X/* Get a unique pipe file name */
- X
- X sprintf (tmpfile, "%s/pipe%05d.tmp", tmpdir, Unique_Pipe++);
- X unlink (tmpfile);
- X
- X/* Create the pipe */
- X
- X if ((fp = fopen (tmpfile, "w")) == (FILE *) NULL)
- X return (PIPE *)NULL;
- X
- X/* Create the PIPE entry */
- X
- X if ((pp = _p_get_entry ((FILE *)NULL)) == (PIPE *)NULL)
- X {
- X fclose (fp);
- X unlink (tmpfile);
- X errno = EMFILE;
- X return (PIPE *)NULL;
- X }
- X
- X/* Set up the entry */
- X
- X pp->p_fp = fp;
- X pp->p_write = mode;
- X pp->p_process = strdup (prog);
- X pp->p_file = strdup (tmpfile);
- X
- X/* Check for errors */
- X
- X if ((pp->p_process == (char *)NULL) || (pp->p_file == (char *)NULL))
- X {
- X _p_reset_entry (pp, 1);
- X errno = ENOMEM;
- X return (FILE *)NULL;
- X }
- X
- X return pp;
- X}
- X
- X/* Execute command via SHELL or COMSPEC */
- X
- Xstatic int _p_run (command)
- Xchar *command;
- X{
- X char *shell; /* Command processor */
- X char *shellpath; /* Full command processor path */
- X char *bp; /* Generic string pointer */
- X char *dash = "/c";
- X
- X/* Determine the command processor */
- X
- X if (((shell = getenv ("SHELL")) == (char *) NULL) &&
- X ((shell = getenv ("COMSPEC")) == (char *) NULL))
- X shell = "command.com";
- X
- X shellpath = strlwr (shell);
- X
- X/* Strip off any leading backslash directories */
- X
- X if ((shell = strrchr (shellpath, '\\')) != (char *)NULL)
- X ++shell;
- X
- X else
- X shell = shellpath;
- X
- X/* Strip off any leading slash directories */
- X
- X if ((bp = strrchr (shell, '/')) != (char *)NULL)
- X shell = ++bp;
- X
- X if (strcmp (shell, "command.com"))
- X *dash = '-';
- X
- X/* Run the program */
- X
- X return spawnl (P_WAIT, shellpath, shell, dash, command, (char *) NULL);
- X}
- X
- X/* resetpipe: Private routine to cancel a pipe */
- X
- Xstatic int _p_reset_entry (pp, mode)
- XPIPE *pp;
- Xint mode;
- X{
- X int result = (!mode) ? 0 : -1;
- X int serrno = errno;
- X
- X/* Close the pipe */
- X
- X fclose (pp->p_fp);
- X
- X/* Free up memory */
- X
- X if (pp->p_file != (char *)NULL)
- X {
- X result = unlink (pp->p_file);
- X
- X if (!mode)
- X serrno = errno;
- X
- X else
- X result = -1;
- X
- X free (pp->p_file);
- X }
- X
- X if (pp->p_process != (char *)NULL)
- X free (pp->p_process);
- X
- X memset (pp, 0, sizeof (PIPE));
- X
- X/* Return error code */
- X
- X errno = serrno;
- X return result;
- X}
- X
- X/* Find a free entry */
- X
- Xstatic PIPE *_p_get_entry (fp)
- XFILE *fp;
- X{
- X int i;
- X
- X for (i = 0; i < _NFILE; i++)
- X {
- X if (P_list[i].p_fp == fp)
- X return &P_list[i];
- X }
- X
- X return (PIPE *)NULL;
- X}
- X
- X
- X/* popen: open a pipe */
- X
- XFILE *popen (command, type)
- Xchar *command; /* The command to be run */
- Xchar *type; /* "w" or "r" */
- X{
- X int old_stdout;
- X PIPE *pp;
- X
- X/* Initialise the pipe structure */
- X
- X if (!Pipes_Inited)
- X {
- X memset (&P_list[0], 0, sizeof (P_list));
- X Pipes_Inited = 1;
- X }
- X
- X/* For write style pipe, pclose handles program execution */
- X
- X if (strcmp (type, "w") == 0)
- X return ((pp = _p_save_entry (command, TRUE)) == (PIPE *)NULL)
- X ? (FILE *)NULL : pp->p_fp;
- X
- X/* read pipe must create tmp file, set up stdout to point to the temp
- X * file, and run the program. note that if the pipe file cannot be
- X * opened, it'll return a condition indicating pipe failure, which is
- X * fine.
- X */
- X
- X else if (strcmp (type, "r") == 0)
- X {
- X if ((pp = _p_save_entry (command, FALSE)) == (PIPE *)NULL)
- X return (FILE *)NULL;
- X
- X/* Save the stdout file descriptor, dup the pipe onto standard out,
- X * execute the command, close the pipe and re-open it
- X */
- X
- X if ((old_stdout = dup (fileno(stdout)) < 0) ||
- X (dup2 (fileno (pp->p_fp), fileno(stdout)) < 0) ||
- X ((pp->p_status = _p_run (command)) < 0) ||
- X (fclose (pp->p_fp) < 0) ||
- X (dup2 (old_stdout, fileno (stdout)) < 0) ||
- X ((pp->p_fp = fopen (pp->p_file, "r")) == (FILE *)NULL))
- X {
- X _p_reset_entry (pp, 1);
- X return (FILE *)NULL;
- X }
- X
- X else
- X return pp->p_fp;
- X }
- X
- X/* screwy call or unsupported type */
- X
- X errno = EINVAL;
- X return (FILE *)NULL;
- X}
- X
- X/* close a pipe */
- X
- Xint pclose (fp)
- XFILE *fp;
- X{
- X PIPE *pp; /* Current pipe structure */
- X int old_stdin; /* Where our stdin points now */
- X
- X if ((pp = _p_get_entry (fp)) == (PIPE *)NULL)
- X {
- X errno = EBADF;
- X return -1;
- X }
- X
- X if (fclose (pp->p_fp) < 0)
- X return _p_reset_entry (pp, 1);
- X
- X/* Open the pipe in read mode, Save stdin file descriptor, copy pipe file
- X * descriptor to stdin, execute the command, and then restore stdin
- X */
- X
- X if (pp->p_write &&
- X ( ((pp->p_fp = fopen (pp->p_file, "r")) == (FILE *)NULL) ||
- X ((old_stdin = dup (fileno (stdin))) < 0) ||
- X (dup2 (fileno (pp->p_fp), fileno (stdin)) < 0) ||
- X ((pp->p_status = _p_run (pp->p_process)) < 0) ||
- X (fclose (pp->p_fp) < 0) ||
- X (dup2 (old_stdin, fileno (stdin)) < 0)
- X ))
- X return _p_reset_entry (pp, 1);
- X
- X/* Close the temp file and remove it */
- X
- X return _p_reset_entry (pp, 0);
- X}
- SHAR_EOF
- chmod 0644 lib/popen.c || echo "restore of lib/popen.c fails"
- set `wc -c lib/popen.c`;Sum=$1
- if test "$Sum" != "6060"
- then echo original size 6060, current size $Sum;fi
- echo "x - extracting lib/syserr.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > lib/syserr.c &&
- X/* perror(s) print the current error message. */
- X
- Xchar *sys_errlist[] = {
- X "Error 0 ",
- X "Operation not permitted",
- X "No such file or directory",
- X "No such process",
- X "Interrupted system call",
- X "I/O error",
- X "No such device or address",
- X "Arg list too long",
- X "Exec format error",
- X "Bad file number",
- X "No children",
- X "No more processes",
- X "Not enough core",
- X "Permission denied",
- X "Bad address",
- X "Block device required",
- X "Mount device busy",
- X "File exists",
- X "Cross-device link",
- X "No such device",
- X "Not a directory",
- X "Is a directory",
- X "Invalid argument",
- X "File table overflow",
- X "Too many open files",
- X "Not a typewriter",
- X "Text file busy",
- X "File too large",
- X "No space left on device",
- X#define ESPIPE 29
- X "Illegal seek",
- X "Read-only file system",
- X "Too many links",
- X
- X "Broken pipe",
- X "Math argument",
- X "Result too large",
- X "EUCLEAN",
- X "No message of desired type",
- X "Resource deadlock would occur"
- X "Unknown error"
- X};
- X
- Xint sys_nerr = sizeof(sys_errlist)/sizeof(char *) - 1;
- SHAR_EOF
- chmod 0644 lib/syserr.c || echo "restore of lib/syserr.c fails"
- set `wc -c lib/syserr.c`;Sum=$1
- if test "$Sum" != "1106"
- then echo original size 1106, current size $Sum;fi
- echo "x - extracting lib/stdargv.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > lib/stdargv.c &&
- X/*
- X * MODULE NAME: expand.c Revision: 1.0
- X *
- X * AUTHOR: Ian Stewartson
- X *
- X * LOCATION: Data Logic,
- X * Greenford,
- X * Middlesex,
- X * England.
- X *
- X#include <logo.h>
- X * MODULE DEFINITION: This function expandes the command line parameters
- X * in a UNIX like manner. Wild character *?[] are
- X * allowed in file names. @filename causes command lines
- X * to be read from filename. Strings between " or ' are
- X * not expanded. All entries in the array are malloced.
- X *
- X * This function replaces the standard MS-DOS command
- X * line processing function (_setargv in stdargv.obj).
- X *
- X * CALLING SEQUENCE: The following calling sequences are used:
- X *
- X * void _setargv ();
- X *
- X * ERROR MESSAGES: Out of memory
- X *
- X * INCLUDE FILES:
- X */
- X
- X#include <sys/types.h> /* MS-DOS type definitions */
- X#include <sys/stat.h> /* File status definitions */
- X#include <stdio.h> /* Standard I/O delarations */
- X#include <stdlib.h> /* Standard library functions */
- X#include <errno.h> /* Error number declarations */
- X#include <dos.h> /* DOS functions declarations */
- X#include <bios.h> /* BIOS functions declarations */
- X#include <ctype.h> /* Character type declarations */
- X#include <string.h> /* String library functions */
- X#include <limits.h> /* String library functions */
- X#include <fcntl.h> /* File Control Declarations */
- X#include <io.h> /* Input/Output Declarations */
- X#include <dirent.h> /* Direction I/O functions */
- X
- X/*
- X * DATA DEFINITIONS:
- X */
- X
- X#define MAX_LINE 160 /* Max line length */
- X#define S_ENTRY sizeof (char *)
- X
- X/*
- X * DATA DECLARATIONS:
- X */
- X#ifdef MSDOS
- X
- Xextern void _setargv (void);
- Xstatic void exp_line (char *); /* Expand file */
- Xstatic int ex_pfield (char *, char *); /* Expand field */
- Xstatic void ex_pfile (char *);
- Xstatic char *ex_gspace (int, char *); /* Get space */
- Xstatic void ex_add_arg (char *); /* Add argument */
- Xstatic char *ex_skip_sp (char *); /* Skip spaces */
- Xstatic char *ex_tounix (char *); /* Convert name to Unix format */
- Xstatic int ex_find (char*, int); /* Split file name */
- Xstatic void ex_fatal (int, char *, char *); /* Fatal error processing*/
- Xstatic char *ex_environment (char *); /* Process environment */
- Xstatic char *_ex_multi_drive (char *); /* Check for multidrive */
- Xstatic char *ex_nomem = "%s: %s\n";
- X
- Xextern char far *_pgmptr; /* Program name */
- Xextern char **__argv; /* Current argument address */
- Xextern int __argc; /* Current argument count */
- X
- X/*
- X * MODULE ABSTRACT: _setargv
- X *
- X * UNIX like command line expansion
- X */
- X
- Xvoid _setargv ()
- X{
- X /* Set up pointer to command line */
- X char far *argvp = (char far *)((((long)_psp) << 16) + 0x081L);
- X unsigned int envs = *(int far *)((((long)_psp) << 16) + 0x02cL);
- X char far *s; /* Temporary string pointer */
- X#ifndef M_I86LM
- X char buf[MAX_LINE]; /* Temporary space */
- X char *cp;
- X#endif
- X
- X/* Command line can be null or 0x0d terminated - convert to null */
- X
- X s = argvp;
- X
- X while (*s && (*s != 0x0d))
- X ++s;
- X
- X if (*s == 0x0d)
- X *s = 0;
- X
- X/* Set up global parameters and expand */
- X
- X __argc = 0;
- X
- X/* Get the program name */
- X
- X if (_osmajor <= 2)
- X s = "unknown";
- X
- X/* In the case of DOS 3+, we look in the environment space */
- X
- X else
- X {
- X s = (char far *)(((long)envs) << 16);
- X
- X while (*s)
- X {
- X while (*(s++) != 0);
- X }
- X
- X s += 3;
- X }
- X
- X _pgmptr = s;
- X
- X#ifndef M_I86LM
- X cp = buf;
- X while (*(cp++) = *(s++));
- X
- X ex_add_arg (ex_tounix (buf)); /* Add the program name */
- X
- X s = argvp;
- X cp = buf;
- X while (*(cp++) = *(s++));
- X
- X exp_line (buf);
- X#else
- X ex_add_arg (ex_tounix (s)); /* Add the program name */
- X exp_line (argvp);
- X#endif
- X
- X ex_add_arg ((char *)NULL);
- X --__argc;
- X}
- X
- X/*
- X * Expand a line
- X */
- X
- Xstatic void exp_line (argvp)
- Xchar *argvp; /* Line to expand */
- X{
- X char *spos; /* End of string pointer */
- X char *cpos; /* Start of string pointer */
- X char *fn; /* Extracted file name string */
- X
- X/* Search for next separator */
- X
- X spos = argvp;
- X
- X while (*(cpos = ex_skip_sp (spos)))
- X {
- X
- X/* Extract string argument */
- X
- X if ((*cpos == '"') || (*cpos == '\''))
- X {
- X spos = cpos + 1;
- X
- X do
- X {
- X if ((spos = strchr (spos, *cpos)) != NULL)
- X {
- X spos++;
- X if (spos[-2] != '\\')
- X break;
- X }
- X
- X else
- X spos = &spos[strlen (cpos)];
- X
- X }
- X while (*spos);
- X
- X fn = ex_gspace (spos - cpos - 2, cpos + 1);
- X }
- X
- X/* Extract normal argument */
- X
- X else
- X {
- X spos = cpos;
- X while (!isspace(*spos) && *spos)
- X spos++;
- X
- X fn = ex_gspace (spos - cpos, cpos);
- X }
- X
- X/* Process argument */
- X
- X if (*cpos != '"')
- X fn = ex_environment (fn);
- X
- X switch (*cpos)
- X {
- X case '@': /* Expand file */
- X ex_pfile (fn);
- X break;
- X
- X case '"': /* Expand string */
- X case '\'':
- X ex_add_arg (fn);
- X break;
- X
- X default: /* Expand field */
- X if (!ex_find (fn, 0))
- X ex_add_arg (fn);
- X }
- X
- X free (fn);
- X }
- X}
- X
- X/* Expand a field if it has metacharacters in it */
- X
- Xstatic int ex_pfield (prefix, postfix)
- Xchar *prefix; /* Prefix field */
- Xchar *postfix; /* Postfix field */
- X{
- X int count; /* File path length */
- X int f_count = 0; /* Number of files generated */
- X int slash_flag = 0; /* slash required */
- X char fn[PATH_MAX + NAME_MAX + 2];/* Search file name */
- X char *name; /* Match string */
- X char *p, *p1;
- X DIR *dp;
- X struct dirent *c_de;
- 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 char t_drive[2];
- X
- X/* Convert file name to lower case */
- X
- X strlwr (prefix);
- X
- X/* Search all drives ? */
- X
- X if ((multi = _ex_multi_drive (prefix)) != (char *)NULL)
- X {
- X _dos_getdrive (&c_drive); /* Get number of drives */
- X _dos_setdrive (c_drive, &m_drive);
- X t_drive[1] = 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 *multi = 0;
- X *t_drive = (char)(s_drive + 'a' - 1);
- X
- X if ((y_drive == s_drive) && pnmatch (t_drive, prefix, 0))
- X {
- X *multi = ':';
- X *fn = *t_drive;
- X strcpy (fn + 1, multi);
- X f_count += ex_pfield (fn, postfix);
- X }
- X
- X *multi = ':';
- X }
- X
- X return f_count;
- X }
- X
- X/* Get the path length */
- X
- X p = strrchr (prefix, '/');
- X p1 = strchr (prefix, ':');
- X
- X if ((p1 == (char *)NULL) || (p1 < p))
- X {
- X if (p == (char *)NULL)
- X {
- X count = 0;
- X name = prefix;
- X }
- X
- X else
- X {
- X count = p - prefix;
- X name = p + 1;
- X }
- X }
- X
- X else if ((p == (char *)NULL) || (p < p1))
- X {
- X count = p1 - prefix;
- X name = p1 + 1;
- X }
- X
- X/* Set up file name for search */
- X
- X if (((count == 2) && (strncmp (prefix + 1, ":/", 2) == 0)) ||
- X ((count == 0) && (*prefix == '/')))
- X {
- X strncpy (fn, prefix, ++count);
- X fn[count] = 0;
- X strcat (fn, ".");
- X }
- X
- X else
- X {
- X if ((count == 1) && (*(prefix + 1) == ':'))
- X count++;
- X
- X strncpy (fn, prefix, count);
- X fn[count] = 0;
- X
- X if (((count == 2) && (*(prefix + 1) == ':')) || (count == 0))
- X strcat (fn, ".");
- X
- X else
- X slash_flag = 1;
- X }
- X
- X/* Search for file names */
- X
- X if ((dp = opendir (fn)) == (DIR *)NULL)
- X return 0;
- X
- X/* Are there any matches */
- X
- X while ((c_de = readdir (dp)) != (struct dirent *)NULL)
- X {
- X if ((*c_de->d_name == '.') && (*name != '.'))
- X continue;
- X
- X/* Check for match */
- X
- X if (pnmatch (c_de->d_name, name, 0))
- X {
- X fn[count] = 0;
- X
- X if (slash_flag)
- X strcat (fn, "/");
- X
- X strcat (fn, c_de->d_name);
- X
- X/* If the postfix is not null, this must be a directory */
- X
- X if (postfix != (char *)NULL)
- X {
- X struct stat statb;
- X
- X if (stat (fn, &statb) < 0 ||
- X (statb.st_mode & S_IFMT) != S_IFDIR)
- X continue;
- X
- X strcat (fn, "/");
- X strcat (fn, postfix);
- X }
- X
- X f_count += ex_find (fn, 1);
- X }
- X }
- X
- X closedir (dp);
- X return f_count;
- X}
- X
- X/* Expand file name */
- X
- Xstatic void ex_pfile (file)
- Xchar *file; /* Expand file name */
- X{
- X FILE *fp; /* File descriptor */
- X char *p; /* Pointer */
- X int c_maxlen = MAX_LINE;
- X char *line; /* Line buffer */
- X
- X/* Grab some memory for the line */
- X
- X if ((line = malloc (c_maxlen)) == (char *)NULL)
- X ex_fatal (ENOMEM, ex_nomem, (char *)NULL);
- X
- X/* If file open fails, expand as a field */
- X
- X if ((fp = fopen (file + 1, "rt")) == NULL)
- X {
- X if (!ex_find (file, 0))
- X ex_add_arg (file);
- X
- X return;
- X }
- X
- X/* For each line in the file, remove EOF characters and add argument */
- X
- X while (fgets (line, c_maxlen, fp) != (char *)NULL)
- X {
- X while ((p = strchr (line, '\n')) == (char *)NULL)
- X {
- X if ((p = strchr (line, 0x1a)) != (char *)NULL)
- X break;
- X
- X if ((line = realloc (line, c_maxlen + MAX_LINE)) == (char *)NULL)
- X ex_fatal (ENOMEM, ex_nomem, (char *)NULL);
- X
- X if (fgets (&line[c_maxlen - 1], MAX_LINE, fp) == (char *)NULL)
- X break;
- X
- X c_maxlen += MAX_LINE - 1;
- X }
- X
- X if (p != (char *)NULL)
- X *p = 0;
- X
- X ex_add_arg (line);
- X }
- X
- X if (ferror(fp))
- X ex_fatal (errno, "%s: %s (%s)\n", file + 1);
- X
- X free (line);
- X fclose (fp);
- X}
- X
- X/* Get space for name */
- X
- Xstatic char *ex_gspace (l, in_s)
- Xint l; /* String length */
- Xchar *in_s; /* String address */
- X{
- X char *out_s; /* Malloced space address */
- X
- X if ((out_s = malloc (l + 1)) == (char *)NULL)
- X ex_fatal (ENOMEM, ex_nomem, (char *)NULL);
- X
- X/* Copy string for specified length */
- X
- X strncpy (out_s, in_s, l);
- X out_s[l] = 0;
- X
- X return (out_s);
- X}
- X
- X/* Append an argument to the string */
- X
- Xstatic void ex_add_arg (fn)
- Xchar *fn; /* Argument to add */
- X{
- X if (__argc == 0)
- X __argv = (char **)malloc (50 * S_ENTRY);
- X
- X else if ((__argc % 50) == 0)
- X __argv = (char **)realloc (__argv, (__argc + 50) * S_ENTRY);
- X
- X if (__argv == (char **)NULL)
- X ex_fatal (ENOMEM, ex_nomem, (char *)NULL);
- X
- X __argv[__argc++] = (fn == (char *)NULL) ? fn : ex_gspace (strlen (fn), fn);
- X}
- X
- X/* Skip over spaces */
- X
- Xstatic char *ex_skip_sp (a)
- Xchar *a; /* String start address */
- X{
- X while (isspace(*a))
- X a++;
- X
- X return (a);
- X}
- X
- X/* Convert name to Unix format */
- X
- Xstatic char *ex_tounix (a)
- Xchar *a;
- X{
- X char *sp = a;
- X
- X while ((a = strchr (a, '\\')) != (char *)NULL)
- X *(a++) = '/';
- X
- X return strlwr (sp);
- X}
- X
- X/* Find the location of meta-characters. If no meta, add the argument and
- X * return NULL. If meta characters, return position of end of directory
- X * name. If not multiple directories, return -1
- X */
- X
- Xstatic int ex_find (file, must_exist)
- Xchar *file;
- Xint must_exist; /* FIle must exist flag */
- X{
- X char *p;
- X int i;
- X static char ex_meta[] = "?*[]\\"; /* Metacharacters */
- X
- X if ((p = strpbrk (file, ex_meta)) == (char *)NULL)
- X {
- X if (must_exist && (access (file, 0) < 0))
- X return 0;
- X
- X ex_add_arg (file);
- X return 1;
- X }
- X
- X else if ((p = strchr (p, '/')) != (char *)NULL)
- X *(p++) = 0;
- X
- X i = ex_pfield (file, p);
- X
- X if (p != (char *)NULL)
- X *(--p) = '/';
- X
- X return i;
- X}
- X
- X/* Fatal errors */
- X
- Xstatic void ex_fatal (ecode, format, para)
- Xint ecode;
- Xchar *format;
- Xchar *para;
- X{
- X fprintf (stderr, format, "stdargv", strerror (ecode), para);
- X exit (1);
- X}
- X
- X/* Process Environment - note that field is a malloc'ed field */
- X
- Xstatic char *ex_environment (field)
- Xchar *field;
- X{
- X char *sp, *cp, *np, *ep;
- X char save;
- X int b_flag;
- X
- X sp = field;
- X
- X/* Replace any $ strings */
- X
- X while ((sp = strchr (sp, '$')) != (char *)NULL)
- X {
- X if (*(cp = ++sp) == '{')
- X {
- X b_flag = 1;
- X ++cp;
- X
- X while (*cp && (*cp != '}'))
- X cp++;
- X }
- X
- X else
- X {
- X b_flag;
- X
- X while (isalnum(*cp))
- X cp++;
- X }
- X
- X/* Grab the environment variable */
- X
- X if (cp == sp)
- X continue;
- X
- X save = *cp;
- X *cp = 0;
- X ep = getenv (sp + b_flag);
- X *cp = save;
- X
- X if (ep != (char *)NULL)
- X {
- X np = ex_gspace (strlen(field) - (cp - sp) + strlen (ep) - 1, field);
- X strcpy (&np[sp - field - 1], ep);
- X ex_tounix (&np[sp - field - 1]);
- X free (field);
- X strcpy ((sp = &np[strlen(np)]), cp + b_flag);
- X field = np;
- X }
- X }
- X
- X return field;
- X}
- X
- X/* Check for multi_drive prefix */
- X
- Xstatic char *_ex_multi_drive (prefix)
- Xchar *prefix;
- X{
- X if (strlen (prefix) < 2)
- X return (char *)NULL;
- X
- X if (((*prefix == '*') || (*prefix == '?')) && (prefix[1] == ':'))
- X return prefix + 1;
- X
- X if (*prefix != '[')
- X return (char *)NULL;
- X
- X while (*prefix && (*prefix != ']'))
- X {
- X if ((*prefix == '\\') && (*(prefix + 1)))
- X ++prefix;
- X
- X ++prefix;
- X }
- X
- X return (*prefix && (*(prefix + 1) == ':')) ? prefix + 1 : (char *)NULL;
- X}
- X#endif
- SHAR_EOF
- chmod 0644 lib/stdargv.c || echo "restore of lib/stdargv.c fails"
- set `wc -c lib/stdargv.c`;Sum=$1
- if test "$Sum" != "12922"
- then echo original size 12922, current size $Sum;fi
- echo "x - extracting lib/pnmatch.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > lib/pnmatch.c &&
- X#include <stdlib.h>
- X
- X/* File name pattern matching function */
- X
- Xint pnmatch (string, pattern, flag)
- Xchar *string; /* String to match */
- Xchar *pattern; /* Pattern to match against */
- Xint flag; /* Match using '$' & '^' */
- X{
- X register int cur_s; /* Current string character */
- X register int cur_p; /* Current pattern character */
- X
- X/* Match $ and ^ ? */
- X
- X if (flag == 1)
- X {
- X while (*string)
- X {
- X if (pnmatch (string++, pattern, ++flag))
- X return 1;
- X }
- X
- X return 0;
- X }
- X
- X/* Match string */
- X
- X while (cur_p = *(pattern++))
- X {
- X cur_s = *(string++); /* Load current string character */
- X
- X switch (cur_p) /* Switch on pattern character */
- X {
- X case '^': /* Match start of string */
- X {
- X if (flag == 2)
- X string--;
- X
- X else if ((flag) || (cur_p != cur_s))
- X return 0;
- X
- X break;
- X }
- X
- X case '$': /* Match end of string */
- X {
- X if (!flag)
- X {
- X if (cur_p != cur_s)
- X return 0;
- X
- X break;
- X }
- X
- X else
- X return ((cur_s) ? 0 : 1);
- X }
- X
- X case '[': /* Match class of characters */
- X {
- X while(1)
- X {
- X if (!(cur_p = *(pattern++)))
- X return 0;
- X
- X if (cur_p == ']')
- X return 0;
- X
- X if (cur_s != cur_p)
- X {
- X if (*pattern == '-')
- X {
- X if(cur_p > cur_s)
- X continue;
- X
- X if (cur_s > *(++pattern))
- X continue;
- X }
- X else
- X continue;
- X }
- X
- X break;
- X }
- X
- X while (*pattern)
- X {
- X if (*(pattern++) == ']')
- X break;
- X }
- X }
- X
- X case '?': /* Match any character */
- X {
- X if (!cur_s)
- X return 0;
- X
- X break;
- X }
- X
- X case '*': /* Match any number of any character*/
- X {
- X string--;
- X
- X do
- X {
- X if (pnmatch (string, pattern, 0))
- X return 1;
- X }
- X while (*(string++));
- X
- X return 0;
- X }
- X
- X case '\\': /* Next character is non-meta */
- X {
- X if (!(cur_p = *(pattern++)))
- X return 0;
- X }
- X
- X default: /* Match against current pattern */
- X {
- X if (cur_p != cur_s)
- X return 0;
- X
- X break;
- X }
- X }
- X }
- X
- X return ((flag || (!(*string))) ? 1 : 0);
- X}
- SHAR_EOF
- chmod 0644 lib/pnmatch.c || echo "restore of lib/pnmatch.c fails"
- set `wc -c lib/pnmatch.c`;Sum=$1
- if test "$Sum" != "2985"
- then echo original size 2985, current size $Sum;fi
- echo "x - extracting lib/getopt.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > lib/getopt.c &&
- X/*
- X * MODULE NAME: getopt.c Revision 1.0
- X *
- X * AUTHOR: I. Stewartson
- X * Data Logic Ltd.,
- X * Queens House,
- X * Greenhill Way,
- X * Harrow,
- X * Middlesex HA1 1YR.
- X * Telephone: London (01) 863 0383
- X *
- X#include <logo.h>
- X * MODULE DESCRIPTION: This function is based on the UNIX library function.
- X * getopt return the next option letter in argv that
- X * matches a letter in opstring. optstring is a string
- X * of recognised option letters; if a letter is followed
- X * by a colon, the option is expected to have an argument
- X * that may or may not be separated from it by white
- X * space. optarg is set to point to the start of the
- X * option argument on return from getopt.
- X *
- X * getopt places in optind the argv index of the next
- X * argument to be processed. Because optind is external,
- X * it is normally initialised to zero automatically before
- X * the first call to getopt.
- X *
- X * When all options have been processed (i.e. up to the
- X * first non-option argument), getopt returns EOF. The
- X * special option -- may be used to delimit the end of
- X * the options; EOF will be returned, and -- will be
- X * skipped.
- X *
- X * getopt prints an error message on stderr and returns a
- X * question mark (?) when it encounters an option letter
- X * not included in optstring. This error message may be
- X * disabled by setting opterr to a non-zero value.
- X *
- X * CALLING SEQUENCE: The following calling sequences are used:
- X *
- X * int getopt(argc, argv, optstring)
- X * int argc;
- X * char **argv;
- X * char *optstring;
- X *
- X * ERROR MESSAGES:
- X * %s: illegal option -- %c
- X * %s: option requires an argument -- %c
- X *
- X * INCLUDE FILES:
- X */
- X
- X#include <stdio.h> /* Standard Input/Output */
- X#include <string.h> /* String function declarations */
- X#include <stdlib.h> /* Standard library declarations*/
- X
- X/*
- X * DATA DECLARATIONS:
- X */
- X
- Xint opterr = 0;
- Xint optind = 1;
- Xint optopt;
- Xint optvar = 0;
- Xchar *optarg;
- X
- Xstatic char *errmes1 = "%s: illegal option -- %c\n";
- Xstatic char *errmes2 = "%s: option requires an argument -- %c\n";
- X
- X/*
- X * MODULE ABSTRACT:
- X *
- X * EXECUTABLE CODE:
- X */
- X
- Xint getopt(argc, argv, optstring)
- Xint argc; /* Argument count */
- Xchar **argv; /* Argument string vector */
- Xchar *optstring; /* Valid options */
- X{
- X static int string_off = 1; /* Current position */
- X int cur_option; /* Current option */
- X char *cp; /* Character pointer */
- X
- X if (string_off == 1)
- X {
- X if ((optind >= argc) || (argv[optind][0] != '-') || (!argv[optind][1]))
- X return (EOF);
- X
- X else if (!strcmp(argv[optind], "--"))
- X {
- X optind++;
- X return (EOF);
- X }
- X }
- X
- X/* Get the current character from the current argument vector */
- X
- X optopt = cur_option = argv[optind][string_off];
- X
- X/* Validate it */
- X
- X if ((cur_option == ':') || ((cur_option == '*') && optvar) ||
- X ((cp = strchr(optstring, cur_option)) == (char *)NULL))
- X {
- X if (opterr)
- X fprintf(stderr, errmes1, cur_option, argv[0]);
- X
- X if (!argv[optind][++string_off])
- X {
- X optind++;
- X string_off = 1;
- X }
- X
- X return ('?');
- X }
- X
- X/* Parameters following ? */
- X
- X if (*(++cp) == ':')
- X {
- X if (argv[optind][string_off + 1])
- X optarg = &argv[optind++][string_off + 1];
- X
- X else if (++optind >= argc)
- X {
- X if (opterr)
- X fprintf(stderr, errmes2, cur_option, argv[0]);
- X
- X string_off = 1;
- X return ('?');
- X }
- X
- X else
- X optarg = argv[optind++];
- X
- X string_off = 1;
- X }
- X
- X else if ((*cp == '*') && optvar)
- X {
- X if (argv[optind][string_off + 1] != 0)
- X optarg = &argv[optind++][string_off + 1];
- X else
- X {
- X optarg = "";
- X optind++;
- X string_off = 1;
- X }
- X }
- X
- X else
- X {
- X if (!argv[optind][++string_off])
- X {
- X string_off = 1;
- X optind++;
- X }
- X
- X optarg = (char *)NULL;
- X }
- X
- X return (cur_option);
- X}
- SHAR_EOF
- chmod 0644 lib/getopt.c || echo "restore of lib/getopt.c fails"
- set `wc -c lib/getopt.c`;Sum=$1
- if test "$Sum" != "3853"
- then echo original size 3853, current size $Sum;fi
- echo "x - extracting scripts/l (Text)"
- sed 's/^X//' << 'SHAR_EOF' > scripts/l &&
- X#!sh
- Xls -C $*
- SHAR_EOF
- chmod 0644 scripts/l || echo "restore of scripts/l fails"
- set `wc -c scripts/l`;Sum=$1
- if test "$Sum" != "14"
- then echo original size 14, current size $Sum;fi
- echo "x - extracting scripts/extend.lst (Text)"
- sed 's/^X//' << 'SHAR_EOF' > scripts/extend.lst &&
- XLIB.EXE
- XLINK.EXE
- Xsh.exe
- SHAR_EOF
- chmod 0644 scripts/extend.lst || echo "restore of scripts/extend.lst fails"
- set `wc -c scripts/extend.lst`;Sum=$1
- if test "$Sum" != "24"
- then echo original size 24, current size $Sum;fi
- echo "x - extracting scripts/profile.sh (Text)"
- sed 's/^X//' << 'SHAR_EOF' > scripts/profile.sh &&
- X#!sh
- XPATH=".;..;c:/oracle5/bin;c:/bin;c:/dos;c:/scm;c:/windows"
- XCDPATH=".;..;/;c:/;c:/windows;c:/scm;c:/ian"
- XINCLUDE=c:/include
- XLIB=c:/lib
- XTMP=c:/tmp
- XTZ=GMT0BST
- XEDITOR=vi
- XPS1="[s[1;20H[1;33;44m[%p] %d %t[0m[u%n %e> "
- XHOME=c:/
- XTERM=ibmpc-mono
- XCL="-AL -Zid -W3"
- XINIT=c:/bin/me_ini
- XEXTENDED_LINE=c:/bin/extend.lst
- XEXINIT="set aw ai sm dm sw=4 wm=5"
- X
- Xmsdos LIB TMP
- SHAR_EOF
- chmod 0644 scripts/profile.sh || echo "restore of scripts/profile.sh fails"
- set `wc -c scripts/profile.sh`;Sum=$1
- if test "$Sum" != "366"
- then echo original size 366, current size $Sum;fi
- echo "x - extracting shell/Makefile (Text)"
- sed 's/^X//' << 'SHAR_EOF' > shell/Makefile &&
- X#
- X# MS-DOS SHELL - Makefile
- X#
- X# MS-DOS SHELL - Copyright (c) 1989 Data Logic Limited.
- X#
- X# Redistribution and use in source and binary forms are permitted
- X# provided that the above copyright notice is duplicated in the
- X# source form.
- X#
- X#
- X# $Header$
- X#
- X# $Log$
- X#
- X
- XOBJS=sh0.obj sh1.obj sh2.obj sh3.obj sh4.obj sh5.obj sh6.obj \
- X sh7.obj sh8.obj sh9.obj sh10.obj
- XASFLAGS= /Ml /Zi /Zd
- X
- Xsh.exe: $(OBJS)
- X link sh0+sh1+sh2+sh3+sh4+sh5+sh6+sh7+sh8+sh9+sh10/noi, sh.exe;
- SHAR_EOF
- chmod 0644 shell/Makefile || echo "restore of shell/Makefile fails"
- set `wc -c shell/Makefile`;Sum=$1
- if test "$Sum" != "470"
- then echo original size 470, current size $Sum;fi
- echo "x - extracting shell/sh1.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > shell/sh1.c &&
- X/* MS-DOS SHELL - Main program, memory and variable management
- 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: sh1.c 1.1 90/01/25 13:40:39 MS_user Exp $
- X *
- X * $Log: sh1.c $
- X * Revision 1.1 90/01/25 13:40:39 MS_user
- X * Initial revision
- X *
- X */
- X
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <signal.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include <stdarg.h>
- X#include <string.h>
- X#include <unistd.h>
- X#include <ctype.h>
- X#include <fcntl.h>
- X#include <limits.h>
- X#include <dos.h>
- X#include <time.h>
- X#include "sh.h"
- X
- X/*
- X * Structure of Malloced space to allow release of space nolonger required
- X * without having to know about it.
- X */
- X
- Xtypedef struct region {
- X struct region *next;
- X int area;
- X} s_region;
- X
- Xstatic struct region *areastart = (s_region *)NULL;
- X
- X/*
- X * default shell, search rules
- X */
- X
- Xstatic char *shellname = "c:/bin/sh";
- Xstatic char *search = ";c:/bin;c:/usr/bin";
- Xstatic char *ymail = "You have mail\n";
- Xstatic char *Path = "PATH";
- X#ifdef SIGQUIT
- Xstatic void (*qflag)() = SIG_IGN;
- X#endif
- X
- X/* Functions */
- X
- Xstatic char *cclass (char *, int, bool);
- Xstatic char *copy_to_equals (char *, char *);
- Xstatic void nameval (Var_List *, char *, char *, bool);
- Xstatic void patch_up (void);
- Xstatic void onecommand (void);
- Xstatic void Check_Mail (void);
- Xstatic void Pre_Process_Argv (char **);
- Xstatic void Load_G_VL (void);
- X
- X/*
- X * The main program starts here
- X */
- X
- Xvoid main (argc, argv)
- Xint argc;
- Xregister char **argv;
- X{
- X register int f;
- X register char *s, *s1;
- X int cflag = 0;
- X int sc;
- X char *name, **ap;
- X int (*iof)(IO_State *) = filechar;
- X Var_List *lset;
- X bool l_rflag = FALSE;
- X
- X/* Patch up various parts of the system */
- X
- X patch_up ();
- X
- X/* Load the environment into our structures */
- X
- X if ((ap = environ) != (char **)NULL)
- X {
- X while (*ap)
- X assign (*ap++, !COPYV);
- X
- X for (ap = environ; *ap;)
- X s_vstatus (lookup (*ap++, TRUE), EXPORT);
- X }
- X
- X/* Zap all files */
- X
- X closeall ();
- X areanum = 1;
- X
- X/* Get the current directory */
- X
- X Getcwd ();
- X
- X/* Set up some stardard variables if their not set */
- X
- X if ((lset = lookup (shell, TRUE))->value == null)
- X setval (lset, shellname);
- X
- X s_vstatus (lset, EXPORT);
- X
- X/* Check for restricted shell */
- X
- X if ((s = strrchr (lset->value, '/')) == (char *)NULL)
- X s = lset->value;
- X
- X else
- X s++;
- X
- X if (*s == 'r')
- X l_rflag = TRUE;
- X
- X/* Set up home directory */
- X
- X if ((lset = lookup (home, TRUE))->value == null)
- X setval (lset, "c:/");
- X
- X s_vstatus (lset, EXPORT);
- X
- X/* Set up history file location */
- X
- X setval (lookup ("$", TRUE), putn (getpid ()));
- X
- X Load_G_VL ();
- X path->status |= (EXPORT | PONLY);
- X ifs->status |= (EXPORT | PONLY);
- X ps1->status |= (EXPORT | PONLY);
- X ps2->status |= (EXPORT | PONLY);
- X
- X if (path->value == null)
- X setval (path, search);
- X
- X if (ifs->value == null)
- X setval (ifs, " \t\n");
- X
- X if (ps1->value == null)
- X setval (ps1, "$ ");
- X
- X if (ps2->value == null)
- X setval (ps2, "> ");
- X
- X/* Check the restricted shell */
- X
- X if ((s = strrchr ((name = *argv), '/')) == (char *)NULL)
- X s = name;
- X
- X if ((s1 = strchr (s, '.')) != (char *)NULL)
- X *s1 = 0;
- X
- X if (strcmp (s, "rsh") == 0)
- X l_rflag = TRUE;
- X
- X if (s1 != (char *)NULL)
- X *s1 = '.';
- X
- X/* Preprocess options to convert two character options of the form /x to
- X * -x. Some programs!!
- X */
- X
- X Pre_Process_Argv (argv);
- X
- X/* Process the options */
- X
- X while ((sc = getopt (argc, argv, "abc:defghijklmnopqrtsuvwxyz0")) != EOF)
- X {
- X switch (sc)
- X {
- X case '0': /* Level 0 flag for DOS */
- X level0 = TRUE;
- X break;
- X
- X case 'r': /* Restricted */
- X l_rflag = TRUE;
- X break;
- X
- X case 'c': /* Command on line */
- X ps1->status &= ~EXPORT;
- X ps2->status &= ~EXPORT;
- X setval (ps1, null);
- X setval (ps2, null);
- X cflag = 1;
- X
- X PUSHIO (aword, optarg, iof = nlchar);
- X break;
- X
- X case 'q': /* No quit ints */
- X#ifdef SIGQUIT
- X qflag = SIG_DFL;
- X#endif
- X break;
- X
- X case 's': /* standard input */
- X break;
- X
- X case 't': /* One command */
- X ps1->status &= ~EXPORT;
- X setval (ps1, null);
- X iof = linechar;
- X break;
- X
- X case 'i': /* Set interactive */
- X talking++;
- X
- X default:
- X if (islower (sc))
- X FL_SET (sc);
- X }
- X }
- X
- X argv += optind;
- X argc -= optind;
- X
- X/* Execute one off command - disable prompts */
- X
- X if ((iof == filechar) && (argc > 0))
- X {
- X setval (ps1, null);
- X setval (ps2, null);
- X ps1->status &= ~EXPORT;
- X ps2->status &= ~EXPORT;
- X
- X f = 0;
- X
- X/* Open the file if necessary */
- X
- X if (strcmp ((name = *argv), "-") != 0)
- X {
- X if ((f = O_for_execute (name)) < 0)
- X {
- X print_error ("%s: cannot open\n", name);
- X exit (1);
- X }
- X }
- X
- X next (remap (f)); /* Load into I/O stack */
- X }
- X
- X/* Set up the $- variable */
- X
- X setdash ();
- X
- X/* Load terminal I/O structure if necessary and load the history file */
- X
- X if (e.iop < iostack)
- X {
- X PUSHIO (afile, 0, iof);
- X
- X if (isatty (0) && isatty (1) && !cflag)
- X {
- X fprintf (stderr, Copy_Right1, _osmajor, _osminor);
- X fputs (Copy_Right2, stderr);
- X
- X talking++;
- X History_Enabled = TRUE;
- X Load_History ();
- X }
- X }
- X
- X#ifdef SIGQUIT
- X signal (SIGQUIT, qflag);
- X#endif
- X
- X/* Read profile ? */
- X
- X if (((name != (char *)NULL) && (*name == '-')) || level0)
- X {
- X talking++;
- X
- X if ((f = O_for_execute ("/etc/profile")) >= 0)
- X next (remap(f));
- X
- X if ((f = O_for_execute ("profile")) >= 0)
- X next (remap(f));
- X }
- X
- X/* Set up signals */
- X
- X if (talking)
- X signal (SIGTERM, sig);
- X
- X if (signal (SIGINT, SIG_IGN) != SIG_IGN)
- X signal (SIGINT, onintr);
- X
- X/* Load any parameters */
- X
- X dolv = argv;
- X dolc = argc;
- X dolv[0] = name;
- X
- X if (dolc > 1)
- X {
- X for (ap = ++argv; --argc > 0;)
- X {
- X if (assign (*ap = *argv++, !COPYV))
- X dolc--; /* keyword */
- X
- X else
- X ap++;
- X }
- X }
- X
- X setval (lookup ("#", TRUE), putn ((--dolc < 0) ? (dolc = 0) : dolc));
- X
- X/* Execute the command loop */
- X
- X while (1)
- X {
- X if (talking && e.iop <= iostack)
- X {
- X Check_Mail ();
- X put_prompt (ps1->value);
- X r_flag = l_rflag;
- X }
- X
- X onecommand ();
- X }
- X}
- X
- X/*
- X * Set up the value of $-
- X */
- X
- Xvoid setdash ()
- X{
- X register char *cp, c;
- X char m['z' - 'a' + 1];
- X
- X for (cp = m, c = 'a'; c <= 'z'; ++c)
- X {
- X if (FL_TEST (c))
- X *(cp++) = c;
- X }
- X
- X *cp = 0;
- X setval (lookup ("-", TRUE), m);
- X}
- X
- X/* Execute a command */
- X
- Xstatic void onecommand ()
- X{
- X register int i;
- X jmp_buf m1;
- X C_Op *outtree;
- X
- X
- X/* Exit any previous environments */
- X
- X while (e.oenv)
- X quitenv ();
- X
- X/* initialise space */
- X
- X areanum = 1;
- X freehere (areanum);
- X freearea (areanum);
- X wdlist = (Word_B *)NULL;
- X iolist = (Word_B *)NULL;
- X e.errpt = (int *)NULL;
- X e.cline = space (LINE_MAX);
- X e.eline = e.cline + LINE_MAX - 5;
- X e.linep = e.cline;
- X yynerrs = 0;
- X multiline = 0;
- X inparse = 1;
- X SW_intr = 0;
- X execflg = 0;
- X
- X/* Get the line and process it */
- X
- X if (setjmp (failpt = m1) || ((outtree = yyparse ()) == (C_Op *)NULL) ||
- X SW_intr)
- X {
- X
- X/* Failed - clean up */
- X
- X while (e.oenv)
- X quitenv ();
- X
- X scraphere ();
- X
- X if (!talking && SW_intr)
- X leave ();
- X
- X/* Exit */
- X
- X inparse = 0;
- X SW_intr = 0;
- X return;
- X }
- X
- X/* Ok - reset some variables and then execute the command tree */
- X
- X inparse = 0;
- X Break_List = (Break_C *)NULL;
- X Return_List = (Break_C *)NULL;
- X SShell_List = (Break_C *)NULL;
- X SW_intr = 0;
- X execflg = 0;
- X
- X/* Set execute function recursive level and the SubShell count to zero */
- X
- X Execute_stack_depth = 0;
- X
- X/* Set up Redirection IO (Saved) array and SubShell Environment information */
- X
- X NSave_IO_E = 0; /* Number of entries */
- X MSave_IO_E = 0; /* Max Number of entries */
- X NSubShells = 0; /* Number of entries */
- X MSubShells = 0; /* Max Number of entries */
- X
- X/* Save the environment information */
- X
- X if (talking && e.iop <= iostack)
- X Add_History (FALSE);
- X
- X if (!FL_TEST ('n'))
- X execute (outtree, NOPIPE, NOPIPE, 0);
- X
- X/* Make sure the I/O and environment are back at level 0 and then clear them */
- X
- X Execute_stack_depth = 0;
- X
- X if (NSubShells != 0)
- X Delete_G_VL ();
- X
- X if (NSave_IO_E)
- X restore_std (0);
- X
- X if (MSubShells)
- X DELETE (SubShells);
- X
- X if (MSave_IO_E)
- X DELETE (SSave_IO);
- X
- X/* Check for interrupts */
- X
- X if (!talking && SW_intr)
- X {
- X execflg = 0;
- X leave ();
- X }
- X
- X/* Run any traps that are required */
- X
- X if ((i = trapset) != 0)
- X {
- X trapset = 0;
- X runtrap (i);
- X }
- X}
- X
- X/*
- X * Terminate current environment with an error
- X */
- X
- Xvoid fail ()
- X{
- X longjmp (failpt, 1);
- X
- X /* NOTREACHED */
- X}
- X
- X/*
- X * Exit the shell
- X */
- X
- Xvoid leave ()
- X{
- X if (execflg)
- X fail ();
- X
- X/* Clean up */
- X
- X scraphere ();
- X freehere (1);
- X
- X/* Trap zero on exit */
- X
- X runtrap (0);
- X
- X/* Dump history on exit */
- X
- X if (talking && isatty(0))
- X Dump_History ();
- X
- X closeall ();
- X exit (exstat);
- X
- X/* NOTREACHED */
- X}
- X
- X/*
- X * Output warning message
- X */
- X
- Xvoid print_warn (fmt)
- Xchar *fmt;
- X{
- X va_list ap;
- X char x[100];
- X
- X va_start (ap, fmt);
- X vsprintf (x, fmt, ap);
- X S_puts (x);
- X exstat = -1;
- X
- X/* If leave on error - exit */
- X
- X if (FL_TEST ('e'))
- X leave ();
- X
- X va_end (ap);
- X}
- X
- X/*
- X * Output error message
- X */
- X
- Xvoid print_error (fmt)
- Xchar *fmt;
- X{
- X va_list ap;
- X char x[100];
- X
- X/* Error message processing */
- X
- X va_start (ap, fmt);
- X vsprintf (x, fmt, ap);
- X S_puts (x);
- X exstat = -1;
- X
- X if (FL_TEST ('e'))
- X leave ();
- X
- X va_end (ap);
- X
- X/* Error processing */
- X
- X if (FL_TEST ('n'))
- X return;
- X
- X/* If not interactive - exit */
- X
- X if (!talking)
- X leave ();
- X
- X if (e.errpt)
- X longjmp (e.errpt, 1);
- X
- X/* closeall (); Removed - caused problems. There may be problems
- X * remaining with files left open?
- X */
- X
- X e.iop = e.iobase = iostack;
- X}
- X
- X/*
- X * Create or delete a new environment. If f is set, delete the environment
- X */
- X
- Xbool newenv (f)
- Xint f;
- X{
- X register Environ *ep;
- X
- X/* Delete environment? */
- X
- X if (f)
- X {
- X quitenv ();
- X return TRUE;
- X }
- X
- X/* Create a new environment */
- X
- X if ((ep = (Environ *) space (sizeof (Environ))) == (Environ *)NULL)
- X {
- X while (e.oenv)
- X quitenv ();
- X
- X fail ();
- X }
- X
- X *ep = e;
- X e.oenv = ep;
- X e.errpt = errpt;
- X return FALSE;
- X}
- X
- X/*
- X * Exit the current environment successfully
- X */
- X
- Xvoid quitenv ()
- X{
- X register Environ *ep;
- X register int fd;
- X
- X/* Restore old environment, delete the space and close any files opened in
- X * this environment
- X */
- X
- X if ((ep = e.oenv) != (Environ *)NULL)
- X {
- X fd = e.iofd;
- X e = *ep;
- X
- X DELETE (ep);
- X
- X while (--fd >= e.iofd)
- X S_close (fd, TRUE);
- X }
- X}
- X
- X/*
- X * Is character c in s?
- X */
- X
- Xbool any (c, s)
- Xregister char c;
- Xregister char *s;
- X{
- X while (*s)
- X {
- X if (*(s++) == c)
- X return TRUE;
- X }
- X
- X return FALSE;
- X}
- X
- X/*
- X * Convert binary to ascii
- X */
- X
- Xchar *putn (n)
- Xregister int n;
- X{
- X static char nt[10];
- X
- X sprintf (nt, "%u", n);
- X return nt;
- X}
- X
- X/*
- X * Add a file to the input stack
- X */
- X
- Xvoid next (f)
- Xint f;
- X{
- X PUSHIO (afile, f, filechar);
- X}
- X
- X/*
- X * SIGINT interrupt processing
- X */
- X
- Xvoid onintr (signo)
- Xint signo;
- X{
- X
- X/* Restore signal processing and set SIGINT detected flag */
- X
- X signal (SIGINT, onintr);
- X SW_intr = 1;
- X
- X/* Are we talking to the user? Yes - check in parser */
- X
- X if (talking)
- X {
- X if (inparse)
- X {
- X S_putc (NL);
- X fail ();
- X }
- X }
- X
- X/* No - exit */
- X
- X else
- X {
- X execflg = 0;
- X leave ();
- X }
- X}
- X
- X/*
- X * Grap some space and check for an error
- X */
- X
- Xchar *space (n)
- Xint n;
- X{
- X register char *cp;
- X
- X if ((cp = getcell (n)) == (char *)NULL)
- X print_error ("sh: out of string space\n");
- X
- X return cp;
- X}
- X
- X/*
- X * Save a string in a given area
- X */
- X
- Xchar *strsave (s, a)
- Xregister char *s;
- X{
- X register char *cp;
- X
- X if ((cp = space (strlen (s) + 1)) != (char *)NULL)
- X {
- X setarea ((char *)cp, a);
- X return strcpy (cp, s);
- X }
- X
- X return null;
- X}
- X
- X/*
- X * trap handling - Save signal number and restore signal processing
- X */
- X
- Xvoid sig (i)
- Xregister int i;
- X{
- X trapset = i;
- X signal (i, sig);
- X}
- X
- X/*
- X * Execute a trap command
- X */
- X
- Xvoid runtrap (i)
- Xint i;
- X{
- X char *trapstr;
- X char tval[10];
- X
- X sprintf (tval, "~%d", i);
- X
- X if (((trapstr = lookup (tval, FALSE)->value)) == null)
- X return;
- X
- X/* If signal zero, save a copy of the trap value and then delete the trap */
- X
- X if (i == 0)
- X {
- X trapstr = strsave (trapstr, areanum);
- X unset (tval, TRUE);
- X }
- X
- X RUN (aword, trapstr, nlchar);
- X}
- X
- X/*
- X * Find the given name in the dictionary and return its value. If the name was
- X * not previously there, enter it now and return a null value.
- X */
- X
- XVar_List *lookup (n, cflag)
- Xregister char *n;
- Xbool cflag;
- X{
- X register Var_List *vp;
- X register char *cp;
- X register int c;
- X static Var_List dummy;
- X
- X/* Set up the dummy variable */
- X
- X dummy.name = n;
- X dummy.status = RONLY;
- X dummy.value = null;
- X
- X/* If digit string - use the dummy to return the value */
- X
- X if (isdigit (*n))
- X {
- X for (c = 0; isdigit (*n) && (c < 1000); n++)
- X c = c * 10 + *n - '0';
- X
- X dummy.value = (c <= dolc) ? dolv[c] : null;
- X return &dummy;
- X }
- X
- X/* Look up in list */
- X
- X for (vp = vlist; vp != (Var_List *)NULL; vp = vp->next)
- X {
- X if (eqname (vp->name, n))
- X return vp;
- X }
- X
- X/* If we don't want to create it, return a dummy */
- X
- X if (!cflag)
- X return &dummy;
- X
- X/* Create a new variable */
- X
- X cp = findeq (n);
- X
- X if (((vp = (Var_List *)space (sizeof (Var_List))) == (Var_List *)NULL)
- X || (vp->name = space ((int)(cp - n) + 2)) == (char *)NULL)
- X {
- X dummy.name = null;
- X return &dummy;
- X }
- X
- X/* Set area for space to zero - no auto-delete */
- X
- X setarea ((char *)vp, 0);
- X setarea ((char *)vp->name, 0);
- X
- X/* Just the name upto the equals sign, no more */
- X
- X copy_to_equals (vp->name, n);
- X
- X/* Link into list */
- X
- X vp->value = null;
- X vp->next = vlist;
- X vp->status = GETCELL;
- X vlist = vp;
- X return vp;
- X}
- X
- X/*
- X * give variable at `vp' the value `val'.
- X */
- X
- Xvoid setval(vp, val)
- XVar_List *vp;
- Xchar *val;
- X{
- X nameval (vp, val, (char *)NULL, FALSE);
- X}
- X
- X/*
- X * Copy and check that it terminates in an equals sign
- X */
- X
- Xstatic char *copy_to_equals (d, s)
- Xchar *d, *s;
- X{
- X int n = (int) (findeq (s) - s);
- X
- X strncpy (d, s, n);
- X *(d += n) = '=';
- X *(++d) = 0;
- X return d;
- X}
- X
- X/*
- X * Set up new value for name
- X *
- X * If name is not NULL, it must be a prefix of the space `val', and end with
- X * `='. This is all so that exporting values is reasonably painless.
- X */
- X
- Xstatic void nameval (vp, val, name, disable)
- Xregister Var_List *vp;
- Xchar *val;
- Xchar *name;
- Xbool disable;
- X{
- X register char *xp;
- X int fl = 0;
- X
- X/* Check if variable is read only */
- X
- X if (vp->status & RONLY)
- X {
- X char c = *(xp = findeq (vp->name));
- X
- X *xp = 0;
- X S_puts (xp);
- X *xp = c;
- X print_error (" is read-only\n");
- X return;
- X }
- X
- X/* Check for $PATH reset in restricted shell */
- X
- X if (!disable && (strcmp (vp->name, Path) == 0) && check_rsh (Path))
- X return;
- X
- X/* Get space for string ? */
- X
- X if (name == (char *)NULL)
- X {
- X if ((xp = space (strlen (vp->name) + strlen (val) + 2)) == (char *)NULL)
- X return;
- X
- X/* make string: name=value */
- X
- X setarea ((char *)xp, 0);
- X name = xp;
- X
- X xp = copy_to_equals (xp, vp->name);
- X strcpy (xp, val);
- X val = xp;
- X fl = GETCELL;
- X }
- X
- X if (vp->status & GETCELL)
- X DELETE (vp->name); /* form new string `name=value' */
- X
- X vp->name = name;
- X vp->value = val;
- X vp->status |= fl;
- X
- X if (FL_TEST ('a'))
- X s_vstatus (vp, EXPORT);
- X}
- X
- X/*
- X * Set the status of an environment variable
- X */
- X
- Xvoid s_vstatus (vp, flag)
- XVar_List *vp;
- Xint flag; /* Addition status flags */
- X{
- X if (isalpha (*vp->name)) /* not an internal symbol ($# etc) */
- X vp->status |= flag;
- X}
- X
- X/*
- X * Check for assignment X=Y
- X */
- X
- Xbool isassign (s)
- Xregister char *s;
- X{
- X if (!isalpha (*s))
- X return FALSE;
- X
- X for (; *s != '='; s++)
- X {
- X if (!*s || !isalnum (*s))
- X return FALSE;
- X }
- X
- X return TRUE;
- X}
- X
- X/*
- X * Execute an assignment. If a valid assignment, load it into the variable
- X * list.
- X */
- X
- Xbool assign (s, cf)
- Xregister char *s;
- Xint cf;
- X{
- X register char *cp;
- X Var_List *vp;
- X
- X if (!isalpha (*s))
- X return FALSE;
- X
- X for (cp = s; *cp != '='; cp++)
- X {
- X if (!*cp || !isalnum (*cp))
- X return FALSE;
- X }
- X
- X nameval ((vp = lookup (s, TRUE)), ++cp, (cf == COPYV ? (char *)NULL : s),
- X FALSE);
- X
- X if (cf != COPYV)
- X vp->status &= ~GETCELL;
- X
- X return TRUE;
- X}
- X
- X/*
- X * Compare two environment strings
- X */
- X
- Xbool eqname(n1, n2)
- Xregister char *n1, *n2;
- X{
- X for (; *n1 != '=' && *n1 != 0; n1++)
- X {
- X if (*n2++ != *n1)
- X return FALSE;
- X }
- X
- X return (!*n2 || (*n2 == '=')) ? TRUE : FALSE;
- X}
- X
- X/*
- X * Find the equals sign in a string
- X */
- X
- Xchar *findeq (cp)
- Xregister char *cp;
- X{
- X while (*cp && (*cp != '='))
- X cp++;
- X
- X return cp;
- X}
- X
- X/*
- X * Duplicate the Variable List for a Subshell
- X *
- X * Create a new Var_list environment for a Sub Shell
- X */
- X
- Xint Create_NG_VL ()
- X{
- X int i;
- X S_SubShell *sp;
- X Var_List *vp, *vp1;
- X
- X for (sp = SubShells, i = 0; (i < NSubShells) &&
- X (SubShells[i].depth < Execute_stack_depth);
- X i++);
- X
- X/* If depth is greater or equal to the Execute_stack_depth - we should panic
- X * as this should not happen. However, for the moment, I'll ignore it
- X */
- X
- X if (NSubShells == MSubShells)
- X {
- X sp = (S_SubShell *)space ((MSubShells + SSAVE_IO_SIZE) * sizeof (S_SubShell));
- X
- X/* Check for error */
- X
- X if (sp == (S_SubShell *)NULL)
- X {
- X errno = ENOMEM;
- X return -1;
- X }
- X
- X/* Save original data */
- X
- X if (MSubShells != 0)
- X {
- X memcpy (sp, SubShells, sizeof (S_SubShell) * MSubShells);
- X DELETE (SubShells);
- X }
- X
- X setarea ((char *)sp, 0);
- X SubShells = sp;
- X MSubShells += SSAVE_IO_SIZE;
- X }
- X
- X/* Save the depth and the old vlist value */
- X
- X sp = &SubShells[NSubShells++];
- X sp->depth = Execute_stack_depth;
- X sp->header = vlist;
- X vlist = (Var_List *)NULL;
- X
- X/* Duplicate the old Variable list */
- X
- X for (vp = sp->header; vp != (Var_List *)NULL; vp = vp->next)
- X {
- X nameval ((vp1 = lookup (vp->name, TRUE)), findeq (vp->name) + 1,
- X (char *)NULL, TRUE);
- X
- X vp1->status |= (vp->status & (C_MSDOS | PONLY | EXPORT | RONLY));
- X }
- X
- X/* Reset global values */
- X
- X Load_G_VL ();
- X return 0;
- X}
- X
- X/*
- X * Delete a SubShell environment and restore the original
- X */
- X
- Xvoid Delete_G_VL ()
- X{
- X int j;
- X S_SubShell *sp;
- X Var_List *vp;
- X
- X for (j = NSubShells; j > 0; j--)
- X {
- X sp = &SubShells[j - 1];
- X
- X if (sp->depth < Execute_stack_depth)
- X break;
- X
- X/* Reduce number of entries */
- X
- X --NSubShells;
- X
- X/* Release the space */
- X
- X for (vp = vlist; vp != (Var_List *)NULL; vp = vp->next)
- X {
- X if (vp->status & GETCELL)
- X DELETE (vp->name);
- X
- X DELETE (vp);
- X }
- X
- X/* Restore vlist information */
- X
- X vlist = sp->header;
- X Load_G_VL ();
- X }
- X}
- X
- X/*
- X * Load GLobal Var List values
- X */
- X
- Xstatic void Load_G_VL ()
- X{
- X path = lookup (Path, TRUE);
- X ifs = lookup ("IFS", TRUE);
- X ps1 = lookup ("PS1", TRUE);
- X ps2 = lookup ("PS2", TRUE);
- X C_dir = lookup ("~", TRUE);
- X Restore_Dir ();
- X}
- X
- X/*
- X * Match a pattern as in sh(1).
- X */
- X
- Xbool gmatch (s, p, IgnoreCase)
- Xregister char *s, *p;
- Xbool IgnoreCase;
- X{
- X register int sc, pc;
- X
- X if ((s == (char *)NULL) || (p == (char *)NULL))
- X return FALSE;
- X
- X while ((pc = *(p++) & CMASK) != '\0')
- X {
- X sc = *(s++) & QMASK;
- X
- X switch (pc)
- X {
- X case '[': /* Class expression */
- X if ((p = cclass (p, sc, IgnoreCase)) == (char *)NULL)
- X return FALSE;
- X
- X break;
- X
- X case '?': /* Match any character */
- X if (sc == 0)
- X return FALSE;
- X
- X break;
- X
- X case '*': /* Match as many as possible */
- X s--;
- X do
- X {
- X if (!*p || gmatch (s, p, IgnoreCase))
- X return TRUE;
- X
- X } while (*(s++));
- X
- X return FALSE;
- X
- X default:
- X if (IgnoreCase)
- X {
- X sc = tolower (sc);
- X pc = tolower ((pc & ~QUOTE));
- X }
- X
- X if (sc != (pc & ~QUOTE))
- X return FALSE;
- X }
- X }
- X
- X return (*s == 0) ? TRUE : FALSE;
- X}
- X
- X/*
- X * Process a class expression - []
- X */
- X
- Xstatic char *cclass (p, sub, IgnoreCase)
- Xregister char *p;
- Xregister int sub;
- Xbool IgnoreCase;
- X{
- X register int c, d, not, found;
- X
- X/* Exclusive or inclusive class */
- X
- X if ((not = *p == NOT) != 0)
- X p++;
- X
- X found = not;
- X
- X do
- X {
- X if (!*p)
- X return (char *)NULL;
- X
- X/* Get the next character in class, converting to lower case if necessary */
- X
- X c = IgnoreCase ? tolower ((*p & CMASK)) : (*p & CMASK);
- X
- X/* If this is a range, get the end of range character */
- X
- X if ((*(p + 1) == '-') && (*(p + 2) != ']'))
- X {
- X d = IgnoreCase ? tolower ((*(p + 2) & CMASK)) : (*(p + 2) & CMASK);
- X p++;
- X }
- X
- X else
- X d = c;
- X
- X/* Is the current character in the class? */
- X
- X if ((c <= sub) && (sub <= d))
- X found = !not;
- X
- X } while (*(++p) != ']');
- X
- X return found ? p + 1 : (char *)NULL;
- X}
- X
- X/*
- X * Get a string in a malloced area
- X */
- X
- Xchar *getcell(nbytes)
- Xunsigned int nbytes;
- X{
- X s_region *np;
- X
- X if (nbytes == 0)
- X abort (); /* silly and defeats the algorithm */
- X
- X/* Grab some space */
- X
- X if ((np = (s_region *)calloc (nbytes + sizeof (s_region), 1)) == (s_region *)NULL)
- X return (char *)NULL;
- X
- X/* Link into chain */
- X
- X np->next = areastart;
- X np->area = areanum;
- X areastart = np;
- X
- X return ((char *)np) + sizeof (s_region);
- X}
- X
- X/*
- X * Free a string in a malloced area
- X */
- X
- Xvoid freecell (s)
- Xchar *s;
- X{
- X register s_region *cp = areastart;
- X s_region *lp = (s_region *)NULL;
- X s_region *sp = (s_region *)(s - sizeof (s_region));
- X
- X/* Find the string in the chain */
- X
- X if (s != (char *)NULL)
- X {
- X while (cp != (s_region *)NULL)
- X {
- X if (cp != sp)
- X {
- X lp = cp;
- X cp = cp->next;
- X continue;
- X }
- X
- X/* First in chain ? */
- X
- X else if (lp == (s_region *)NULL)
- X areastart = cp->next;
- X
- X/* Delete the current entry and relink */
- X
- X else
- X lp->next = cp->next;
- X
- X free (cp);
- X break;
- X }
- X }
- X}
- X
- X/*
- X * Autodelete space nolonger required. Ie. Free all the strings in a malloced
- X * area
- X */
- X
- Xvoid freearea (a)
- Xregister int a;
- X{
- X register s_region *cp = areastart;
- X s_region *lp = (s_region *)NULL;
- X
- X while (cp != (s_region *)NULL)
- X {
- X
- X/* Is the area number less than that specified - yes, continue */
- X if (cp->area < a)
- X {
- X lp = cp;
- X cp = cp->next;
- X }
- X
- X/* OK - delete the area. Is it the first in chain ? Yes, delete, relink
- X * and update start location
- X */
- X
- X else if (lp == (s_region *)NULL)
- X {
- X lp = cp;
- X cp = cp->next;
- X areastart = cp;
- X
- X free (lp);
- X lp = (char *)NULL;
- X }
- X
- X/* Not first, delete the current entry and relink */
- X
- X else
- X {
- X lp->next = cp->next;
- X free (cp);
- X cp = lp->next;
- X }
- X }
- X}
- X
- X/*
- X * Set the area number for a malloced string. This allows autodeletion of
- X * space that is nolonger required.
- X */
- X
- Xvoid setarea (cp,a)
- Xchar *cp;
- Xint a;
- X{
- X s_region *sp = (s_region *)(cp - sizeof (s_region));
- X
- X if (cp != (char *)NULL)
- X sp->area = a;
- X}
- X
- X/*
- X * Get the area number for a malloced string
- X */
- X
- Xint getarea (cp)
- Xchar *cp;
- X{
- X s_region *sp = (s_region *)(cp - sizeof (s_region));
- X
- X return sp->area;
- X}
- X
- X/* Output one of the Prompt. We save the prompt for the history part of
- X * the program
- X */
- X
- Xvoid put_prompt (s)
- Xchar *s;
- X{
- X struct dosdate_t d_date;
- X struct dostime_t d_time;
- X int i;
- X char buf[PATH_MAX + 4];
- X
- X last_prompt = s; /* Save the Last prompt output */
- X
- X _dos_gettime (&d_time); /* Get the date and time in case */
- X _dos_getdate (&d_date);
- X
- X while (*s)
- X {
- X
- X/* If a format character, process it */
- X
- X if (*s == '%')
- X {
- X s++;
- X *s = tolower(*s);
- X
- X if (*s == '%')
- X S_putc ('%');
- X
- X else
- X {
- X *buf = 0;
- X
- X switch (*s)
- X {
- X case 'e': /* Current event number */
- X if (History_Enabled)
- X sprintf (buf, "%d", Current_Event + 1);
- X
- X break;
- X
- X case 't': /* time */
- X sprintf (buf,"%.2d:%.2d", d_time.hour, d_time.minute);
- X break;
- X
- X case 'd': /* date */
- X sprintf (buf, "%.3s %.2d-%.2d-%.2d",
- X &"SunMonTueWedThuFriSat"[d_date.dayofweek * 3],
- X d_date.day, d_date.month, d_date.year % 100);
- X break;
- X
- X case 'p': /* directory */
- X case 'n': /* default drive */
- X strcpy (buf, C_dir->value);
- X
- X if (*s == 'n')
- X buf[1] = 0;
- X
- X break;
- X
- X case 'v': /* version */
- X sprintf (buf, "MS-DOS %.2d:%.2d", _osmajor, _osminor);
- X break;
- X }
- X
- X/* Output the string */
- X
- X S_puts (buf);
- X }
- X }
- X
- X/* Escaped character ? */
- X
- X else if (*s == '\\')
- X {
- X if ((i = Process_Escape (&s)) == -1)
- X i = 0;
- X
- X S_putc (i);
- X }
- X
- X else
- X S_putc (*s);
- X
- X/* Go to the next character */
- X
- X s++;
- X }
- X}
- X
- X/*
- X * Get the current path in UNIX format and save it in the environment
- X * variable $~
- X */
- X
- Xvoid Getcwd ()
- X{
- X char ldir[PATH_MAX + 6];
- X char *cp = getcwd (ldir, PATH_MAX + 4);
- X
- X strlwr (cp);
- X
- X/* Convert to Unix format */
- X
- X while (*cp)
- X {
- X if (*cp == '\\')
- X *cp = '/';
- X
- X ++cp;
- X }
- X
- X/* Save in environment */
- X
- X setval ((C_dir = lookup ("~", TRUE)), ldir);
- X}
- X
- X/*
- X * Patch up various parts of the system for the shell. At the moment, we
- X * modify the ctype table so that _ is an upper case character.
- X */
- X
- Xstatic void patch_up ()
- X{
- X/* Patch the ctype table as a cheat */
- X
- X (_ctype+1)['_'] |= _UPPER;
- X}
- X
- X/*
- X * Mail Check processing. Every $MAILCHECK seconds, we check either $MAIL
- X * or $MAILPATH to see if any file has changed its modification time since
- X * we last looked. In $MAILCHECK, the files are separated by colons (:).
- X * If the filename contains a %, the string following the % is the message
- X * to display if the file has changed.
- X */
- X
- Xstatic void Check_Mail ()
- X{
- X int delay = atoi (lookup ("MAILCHECK", FALSE)->value);
- X Var_List *mail = lookup ("MAIL", FALSE);
- X Var_List *mailp = lookup ("MAILPATH", FALSE);
- X static time_t last = 0L;
- X time_t current = time ((time_t *)NULL);
- X struct stat st;
- X char *cp, *sp, *ap;
- X
- X/* Have we waited long enough */
- X
- X if ((current - last) < delay)
- X return;
- X
- X/* Yes - Check $MAILPATH. If it is defined, process it. Otherwise, use
- X * $MAIL
- X */
- X
- X if (mailp->value != null)
- X {
- X
- X/* Check MAILPATH */
- X
- X sp = mailp->value;
- X
- X/* Look for the next separator */
- X
- X while ((cp = strchr (sp, ':')) != (char *)NULL)
- X {
- X *cp = 0;
- X
- X/* % in string ? */
- X
- X if ((ap = strchr (ap, '%')) != (char *)NULL)
- X *ap = 0;
- X
- X/* Check the file name */
- X
- X if ((stat (sp, &st) != -1) && (st.st_mtime > last))
- X {
- X if (ap != (char *)NULL)
- X {
- X S_puts (ap + 1);
- X S_putc (NL);
- X }
- X
- X else
- X S_puts (ymail);
- X }
- X
- X/* Restore the % */
- X
- X if (ap != (char *)NULL)
- X *ap = '%';
- X
- X/* Restore the colon and find the next one */
- X
- X *cp = ':';
- X sp = cp + 1;
- X }
- X }
- X
- X/* Just check MAIL */
- X
- X else if ((mail->value != null) && (stat (mail->value, &st) != -1) &&
- X (st.st_mtime > last))
- X S_puts (ymail);
- X
- X/* Save the last check time */
- X
- X last = current;
- X}
- X
- X/*
- X * Preprocess Argv to get handle of options in the format /x
- X *
- X * Some programs invoke the shell using / instead of - to mark the options.
- X * We need to convert to -. Also /c is a special case. The rest of the
- X * command line is the command to execute. So, we get the command line
- X * from the original buffer instead of argv array.
- X */
- X
- Xstatic void Pre_Process_Argv (argv)
- Xchar **argv;
- X{
- X char *ocl = (char far *)((((long)_psp) << 16) + 0x081L);
- X
- X
- X/* Check for these options */
- X
- X while ((*++argv != (char *)NULL) && (strlen (*argv) == 2) &&
- X (**argv == '/'))
- X {
- X *strlwr (*argv) = '-';
- X
- X/* Get the original information from the command line */
- X
- X if ((*argv)[1] == 'c')
- X {
- X while ((*ocl != '/') && (*(ocl + 1) != 'c') && (*ocl) &&
- X (*ocl != '\r'))
- X ++ocl;
- X
- X if (*ocl != '/')
- X continue;
- X
- X/* Find the start of the string */
- X
- X ocl += 2;
- X
- X while (isspace (*ocl) && (*ocl != '\r'))
- X ++ocl;
- X
- X if (*ocl == '\r')
- X continue;
- X
- X/* Found the start. Set up next parameter and ignore the rest */
- X
- X if (*(argv + 1) == (char *)NULL)
- X continue;
- X
- X *(argv + 1) = ocl;
- X *(argv + 2) = (char *)NULL;
- X
- X if ((ocl = strchr (ocl, '\r')) != (char *)NULL)
- X *ocl = 0;
- X
- X return;
- X }
- X }
- X}
- SHAR_EOF
- chmod 0644 shell/sh1.c || echo "restore of shell/sh1.c fails"
- set `wc -c shell/sh1.c`;Sum=$1
- if test "$Sum" != "28366"
- then echo original size 28366, current size $Sum;fi
- echo "x - extracting shell/sh2.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > shell/sh2.c &&
- X/* MS-DOS SHELL - Parser
- 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: sh2.c 1.1 90/01/25 13:41:12 MS_user Exp $
- X *
- X * $Log: sh2.c $
- X * Revision 1.1 90/01/25 13:41:12 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 <string.h>
- X#include <ctype.h>
- X#include <unistd.h>
- X#include "sh.h"
- X
- X/*
- X * shell: syntax (C version)
- X */
- X
- Xtypedef union {
- X char *cp;
- X char **wp;
- X int i;
- X C_Op *o;
- X} YYSTYPE;
- X
- X#define WORD 256
- X#define LOGAND 257
- X#define LOGOR 258
- X#define BREAK 259
- X#define IF 260
- X#define THEN 261
- X#define ELSE 262
- X#define ELIF 263
- X#define FI 264
- X#define CASE 265
- X#define ESAC 266
- X#define FOR 267
- X#define WHILE 268
- X#define UNTIL 269
- X#define DO 270
- X#define DONE 271
- X#define IN 272
- X#define YYERRCODE 300
- X
- X/* flags to yylex */
- X
- X#define CONTIN 01 /* skip new lines to complete command */
- X
- Xstatic bool startl;
- Xstatic int peeksym;
- Xstatic bool Allow_funcs;
- Xstatic int iounit = IODEFAULT;
- Xstatic C_Op *tp;
- Xstatic YYSTYPE yylval;
- Xstatic char *syntax_err = "sh: syntax error\n";
- X
- Xstatic C_Op *pipeline (int);
- Xstatic C_Op *andor (void);
- Xstatic C_Op *c_list (bool);
- Xstatic bool synio (int);
- Xstatic void musthave (int, int);
- Xstatic C_Op *simple (void);
- Xstatic C_Op *nested (int, int);
- Xstatic C_Op *command (int);
- Xstatic C_Op *dogroup (int);
- Xstatic C_Op *thenpart (void);
- Xstatic C_Op *elsepart (void);
- Xstatic C_Op *caselist (void);
- Xstatic C_Op *casepart (void);
- Xstatic char **pattern (void);
- Xstatic char **wordlist (void);
- Xstatic C_Op *list (C_Op *, C_Op *);
- Xstatic C_Op *block (int, C_Op *, C_Op *, char **);
- Xstatic int rlookup (char *);
- Xstatic C_Op *namelist (C_Op *);
- Xstatic char **copyw (void);
- Xstatic void word (char *);
- Xstatic IO_Actions **copyio (void);
- Xstatic IO_Actions *io (int, int, char *);
- Xstatic void yyerror (char *);
- Xstatic int yylex (int);
- Xstatic int collect (int, int);
- Xstatic int dual (int);
- Xstatic void diag (int);
- Xstatic char *tree (unsigned int);
- X
- XC_Op *yyparse ()
- X{
- X C_Op *outtree;
- X
- X startl = TRUE;
- X peeksym = 0;
- X yynerrs = 0;
- X outtree = c_list (TRUE);
- X musthave (NL, 0);
- X
- X return (yynerrs != 0) ? (C_Op *)NULL : outtree;
- X}
- X
- Xstatic C_Op *pipeline (cf)
- Xint cf;
- X{
- X register C_Op *t, *p;
- X register int c;
- X
- X if ((t = command (cf)) != (C_Op *)NULL)
- X {
- X Allow_funcs = FALSE;
- X while ((c = yylex (0)) == '|')
- X {
- X if ((p = command (CONTIN)) == (C_Op *)NULL)
- X yyerror (syntax_err);
- X
- X/* shell statement */
- X
- X if ((t->type != TPAREN) && (t->type != TCOM))
- X t = block (TPAREN, t, NOBLOCK, NOWORDS);
- X
- X t = block (TPIPE, t, p, NOWORDS);
- X }
- X
- X peeksym = c;
- X }
- X
- X return t;
- X}
- X
- Xstatic C_Op *andor ()
- X{
- X register C_Op *t, *p;
- X register int c;
- X
- X if ((t = pipeline (0)) != (C_Op *)NULL)
- X {
- X Allow_funcs = FALSE;
- X while (((c = yylex (0)) == LOGAND) || (c == LOGOR))
- X {
- X if ((p = pipeline (CONTIN)) == (C_Op *)NULL)
- X yyerror (syntax_err);
- X
- X t = block ((c == LOGAND) ? TAND : TOR, t, p, NOWORDS);
- X }
- X
- X peeksym = c;
- X }
- X
- X return t;
- X}
- X
- Xstatic C_Op *c_list (allow)
- Xbool allow;
- X{
- X register C_Op *t, *p;
- X register int c;
- X
- X/* Functions are only allowed at the start of a line */
- X
- X Allow_funcs = allow;
- X
- X if ((t = andor ()) != (C_Op *)NULL)
- X {
- X Allow_funcs = FALSE;
- X
- X if ((peeksym = yylex (0)) == '&')
- X t = block (TASYNC, t, NOBLOCK, NOWORDS);
- X
- X while ((c = yylex(0)) == ';' || c == '&' || multiline && c == NL)
- X {
- X if ((p = andor ()) == (C_Op *)NULL)
- X return t;
- X
- X if ((peeksym = yylex (0)) == '&')
- X p = block (TASYNC, p, NOBLOCK, NOWORDS);
- X
- X t = list (t, p);
- X }
- X peeksym = c;
- X }
- X
- X return t;
- X}
- X
- X
- Xstatic bool synio (cf)
- Xint cf;
- X{
- X register IO_Actions *iop;
- X register int i;
- X register int c;
- X
- X if (((c = yylex (cf)) != '<') && (c != '>'))
- X {
- X peeksym = c;
- X return FALSE;
- X }
- X
- X i = yylval.i;
- X musthave (WORD, 0);
- X iop = io (iounit, i, yylval.cp);
- X iounit = IODEFAULT;
- X
- X if (i & IOHERE)
- X markhere (yylval.cp, iop);
- X
- X return TRUE;
- X}
- X
- Xstatic void musthave (c, cf)
- Xint c, cf;
- X{
- X if ((peeksym = yylex (cf)) != c)
- X yyerror (syntax_err);
- X
- X peeksym = 0;
- X}
- X
- Xstatic C_Op *simple ()
- X{
- X register C_Op *t = (C_Op *)NULL;
- X
- X while (1)
- X {
- X switch (peeksym = yylex (0))
- X {
- X case '<':
- X case '>':
- X synio (0);
- X break;
- X
- X case WORD:
- X if (t == (C_Op *)NULL)
- X (t = (C_Op *)tree (sizeof (C_Op)))->type = TCOM;
- X
- X peeksym = 0;
- X word (yylval.cp);
- X break;
- X
- X/* Check for function - name () { word; } */
- X
- X case '(':
- X if ((t != (C_Op *)NULL) && (Allow_funcs == TRUE) &&
- X (wdlist != (Word_B *)NULL) && (wdlist->w_nword == 1))
- X {
- X Word_B *save;
- X
- X peeksym = 0;
- X musthave (')', 0);
- X musthave ('{', 0);
- X save = wdlist;
- X wdlist = (Word_B *)NULL;
- X t->type = TFUNC;
- X t->left = nested (TBRACE, '}');
- X wdlist = save;
- X Allow_funcs = FALSE;
- X musthave (NL, 0);
- X peeksym = NL;
- X }
- X
- X default:
- X return t;
- X }
- X }
- X}
- X
- Xstatic C_Op *nested (type, mark)
- Xint type, mark;
- X{
- X register C_Op *t;
- X
- X multiline++;
- X t = c_list (FALSE);
- X musthave (mark, 0);
- X multiline--;
- X return block (type, t, NOBLOCK, NOWORDS);
- X}
- X
- Xstatic C_Op *command (cf)
- Xint cf;
- X{
- X register C_Op *t;
- X Word_B *iosave = iolist;
- X register int c;
- X
- X iolist = (Word_B *)NULL;
- X
- X if (multiline)
- X cf |= CONTIN;
- X
- X while (synio (cf))
- X cf = 0;
- X
- X switch (c = yylex (cf))
- X {
- X default:
- X peeksym = c;
- X
- X if ((t = simple ()) == (C_Op *)NULL)
- SHAR_EOF
- echo "End of part 2"
- echo "File shell/sh2.c is continued in part 3"
- echo "3" > s2_seq_.tmp
- exit 0
-
- --
- Regards,
-
- Ian Stewartson
- Data Logic Ltd.
-
-
-