Yet Another Shell (part 2 of 11)

Dave Clemans dclemans.falcon at mntgfx.mentor.com
Thu Mar 16 08:14:08 AEST 1989


With all the talk about shells that has been going on recently...

Here's an early pre-release of a "Korn"-like shell for anyone
who might want to experiment.  It is definitely NOT complete,
but it starting to be usable.  It does use some GNU code (for
expression evaluation), so it presumably comes under their
"copyleft".

It basically runs on BSD/USG Unix systems, and on the Atari ST.
I'm currently working on a port to the Amiga.

dgc

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 11)."
# Contents:  io.c reader/vi.c reader/words.c shell.h trap.c
# Wrapped by dclemans at dclemans on Wed Mar 15 14:03:52 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'io.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'io.c'\"
else
echo shar: Extracting \"'io.c'\" \(10624 characters\)
sed "s/^X//" >'io.c' <<'END_OF_FILE'
X/*
X * Command Input Shell
X * Dave Clemans
X * 12/88-1/89
X *
X * "spiritually" based on Bourne, Korn shells
X *
X * I/O Functions
X *
X * $Id: io.c,v 1.5 89/02/22 10:16:32 dclemans Exp $
X *
X * $Log:	io.c,v $
X * Revision 1.5  89/02/22  10:16:32  dclemans
X * Fix bugs with process waiting, pid reporting, parsing of &
X * 
X * Revision 1.4  89/02/20  20:11:49  dclemans
X * Add RCS identifiers
X * 
X */
X#include <stdio.h>
X#include "shell.h"
X
Xchar    buffer[BUFSIZ];
Xchar    *bufstart = buffer;
Xchar    *bufend = buffer;
Xstruct  infile *buffile = (struct infile *)NULL;
Xstruct  strsave *strings = (struct strsave *)NULL;
X
Xint io_prompt(prompt_level)
Xint prompt_level;
X{
X    register char *p,*in,*out;
X    char buffer[256];
X
X    if (prompt_level > PROMPT_MAX)
X    {   /* a known prompt? */
X        sprintf(buffer,"? ");
X    }
X    else if (prompt_level < 0)
X    {   /* explicit non-prompting? */
X        return 0;
X    }
X    else
X    {   /* user specified prompt */
X        if (base_env.prompts[prompt_level] == (char *)NULL)
X            return 0;
X        base_env.prompts_issued[prompt_level]++;
X        out = buffer;
X        p = strcopy(base_env.prompts[prompt_level]);
X        if (p == (char *)NULL)
X        {   /* enough memory? */
X            /* message already printed */
X            return 0;
X        }
X        stripquotes(p);
X        for (in = p; *in; in++)
X        {   /* build the prompt */
X            if (*in == '!')
X            {   /* put in cmd number */
X                sprintf(out,"%d",base_env.prompts_issued[prompt_level]);
X                while (*out) out++;
X            }
X            else    *out++ = *in;
X        }
X        *out = '\0';
X        free(p);
X    }
X    io_writestring(0,buffer);
X    io_writestring(0,(char *)NULL);
X    return (int)(out - buffer);
X}   /* end of io_prompt */
X
Xint io_savestring(s)
Xchar *s;
X{
X    register struct strsave *sp;
X
X    if (s == (char *)NULL || strlen(s) == 0)
X        return 0;
X    sp = new_strsave(s);
X    if (sp == (struct strsave *)NULL)
X    {   /* enough memory? */
X        errmsg(SHERR_NOMEM,LOC("io_savestring"));
X        return -1;
X    }
X    sp->next = strings;
X    strings = sp;
X    return 0;
X}   /* end of io_savestring */
X
Xint io_getchar(prompt_level)
Xint prompt_level;
X{
X    register int new_char;
X    register struct strsave *sp;
X    int markeof,rc;
X#ifdef  GEMDOS
X    int i;
X#endif  /* GEMDOS */
X    register struct infile *ip;
X
X    if (strings != (struct strsave *)NULL)
X    {   /* scanning a "pushed back" string? */
X        new_char = *strings->ptr++;
X        if (*strings->ptr == '\0')
X        {   /* finished with the string? */
X            free(strings->string);
X            sp = strings;
X            strings = strings->next;
X            free(sp);
X        }
X        return new_char;
X    }
X    if (buffile != (struct infile *)NULL)
X    {   /* if reading inserted input */
X        if (buffile->start >= buffile->end)
X        {   /* if need more input */
X#ifdef  GEMDOS
X            rc = Fread(buffile->fp,(long)(sizeof buffile->buffer-1),buffile->buffer);
X            if (rc > 0)
X            {   /* got a good buffer? */
X                buffile->buffer[rc] = '\0';
X                for (i = 0; i < rc; i++)
X                {   /* kill any double eol's */
X                    if (buffile->buffer[i] == '\r' &&
X                        (i+1) < rc &&
X                        buffile->buffer[i+1] == '\n')
X                        buffile->buffer[i] = base_env.separators[0];
X                }
X            }
X#else
X            rc = read(buffile->fp,buffile->buffer,sizeof buffile->buffer - 1);
X            if (rc > 0)
X                buffile->buffer[rc] = '\0';
X#endif  /* GEMDOS */
X            if (rc <= 0)
X            {   /* at end of temp file? */
X#ifdef  GEMDOS
X                Fclose(buffile->fp);
X#else
X                close(buffile->fp);
X                main_fdput(buffile->fp);
X#endif  /* GEMDOS */
X                if (buffile->delete)
X                    delete_later(buffile->name);
X                free(buffile->name);
X                ip = buffile;
X                buffile = buffile->next;
X                markeof = ip->markeof;
X                free(ip);
X                if (markeof)
X                    return SYM_MARKER;
X                else return io_getchar(prompt_level);
X            }
X            buffile->buffer[sizeof buffile->buffer - 1] = '\0';
X            if (flag_echoinput)
X            {   /* what did we just read? */
X                io_writestring(0,buffile->buffer);
X            }
X            for (buffile->end = buffile->buffer; *buffile->end != '\0'; buffile->end++)
X                /* do nothing */;
X            buffile->start = buffile->buffer;
X        }
X        new_char = *buffile->start++;
X        if (buffile->nonl)
X        {   /* no nls from this file? */
X            if (new_char == '\r' || new_char == '\n')
X                new_char = ' ';
X        }
X        return new_char;
X    }
X    if (bufstart >= bufend)
X    {   /* need more characters? */
X        if (buffile != (struct infile *)NULL)
X        {   /* reading from temp file? */
X        }
X        else
X        {   /* read from normal input */
X            if (flag_interactive)
X                io_prompt(prompt_level);
X#ifdef  LINED
X            if (flag_interactive)
X            {   /* get a line */
X                buffer[0] == '\0';
X                rc = Reader(base_env.fd_input,buffer,sizeof buffer - 1);
X                if (rc == 1 && (buffer[0] == '\r' || buffer[0] == '\n') && prompt_level <= PROMPT_MAX)
X                    base_env.prompts_issued[prompt_level]--;
X            }
X            else
X                rc = read(base_env.fd_input,buffer,sizeof buffer-1);
X#else
X            rc = read(base_env.fd_input,buffer,sizeof buffer-1);
X            if (rc == 1 && (buffer[0] == '\r' || buffer[0] == '\n') && prompt_level <= PROMPT_MAX)
X                base_env.prompts_issued[prompt_level]--;
X#ifdef  GEMDOS
X            if (flag_interactive && rc >= 0 && rc < (sizeof buffer -1))
X            {   /* add in eol if necessary */
X                if (rc == 0 && prompt_level >= 0 && prompt_level <= PROMPT_MAX)
X                    base_env.prompts_issued[prompt_level]--;
X                if (rc > 0 && buffer[rc-1] != '\n')
X                    buffer[rc++] = '\n';
X                else if (rc > 0 && buffer[rc-1] == '\032')
X                    rc = 0;
X                else if (rc == 0)
X                    buffer[rc++] = '\n';
X                io_writestring(0,"\n");
X            }
X#endif  /* GEMDOS */
X#endif  /* LINED */
X            if (rc <= 0)
X                return SYM_EOF;
X            buffer[rc] = '\0';
X        }
X        buffer[sizeof buffer - 1] = '\0';
X        if (flag_echoinput)
X        {   /* what did we just read? */
X            io_writestring(0,buffer);
X        }
X        for (bufend = buffer; *bufend != '\0'; bufend++)
X            /* do nothing */;
X        bufstart = buffer;
X    }
X    new_char = *bufstart++;
X    return new_char;
X}   /* end of io_getchar */
X
Xvoid io_pushback(c)
Xchar c;
X{
X    char buf[2];
X
X    buf[0] = c;
X    buf[1] = '\0';
X    io_savestring(buf);
X}   /* end of io_pushback */
X
Xint io_pushtoken(name,strip)
Xregister char *name;
Xint strip;
X{
X    register char *cp;
X    register int result;
X
X    cp = new_string(strlen(name)+2);
X    if (cp == (char *)NULL)
X    {   /* enough memory? */
X        errmsg(SHERR_NOMEM,LOC("io_pushtoken"));
X        return -1;
X    }
X    strcpy(cp,name);
X    if (strip)
X        stripquotes(cp);
X    strcat(cp," ");
X    result = io_savestring(cp);
X    free(cp);
X    return result;
X}   /* end of io_pushtoken */
X
Xint io_pushfile(file,delete,nonl,markeof)
Xchar *file;
Xint delete;
Xint nonl;
Xint markeof;
X{
X    register struct infile *ip;
X#ifndef GEMDOS
X    int tfd;
X#endif  /* GEMDOS */
X
X    ip = new_infile();
X    if (ip == (struct infile *)NULL)
X    {   /* enough memory? */
X        errmsg(SHERR_NOMEM,LOC("io_pushfile"));
X        return -1;
X    }
X    ip->delete = delete;
X    ip->nonl = nonl;
X    ip->markeof = markeof;
X    ip->name = strcopy(file);
X    if (ip->name == (char *)NULL)
X    {   /* enough memory? */
X        /* message already printed */
X        free(ip);
X        return -1;
X    }
X    stripquotes(ip->name);
X#ifdef  GEMDOS
X    ip->fp = Fopen(ip->name,0);
X    if (ip->fp < 0)
X    {   /* did the file open? */
X        errmsg(0,LOC("io_pushfile"),"can't open %s",file);
X        free(ip);
X        return -1;
X    }
X#else
X    ip->fp = open(ip->name,0);
X    if (ip->fp < 0)
X    {   /* did the file open? */
X        errmsg(0,LOC("io_pushfile"),"can't open %s",file);
X        free(ip);
X        return -1;
X    }
X    else
X    {   /* put the fd into a safe place */
X        tfd = main_fdget();
X        if (dup2(ip->fp,tfd) < 0)
X        {   /* everything setup? */
X            errmsg(0,LOC("io_pushfile"),"can't associate %s with right fd",file);
X            main_fdput(tfd);
X            free(ip);
X            return -1;
X        }
X        close(ip->fp);
X        ip->fp = tfd;
X    }
X#endif  /* GEMDOS */
X    ip->start = ip->end = ip->buffer;
X    ip->next = buffile;
X    buffile = ip;
X    return 0;
X}   /* end of io_pushfile */
X
Xvoid io_writestring(file,s)
Xint file;
Xchar *s;
X{
X    static char *buffer = (char *)NULL;
X    static int bufsiz = 0;
X    register int fd;
X    register char *in,*out;
X    
X    if (buffer == (char *)NULL)
X    {   /* do we have any buffer space? */
X        bufsiz = 128;
X        buffer = new_string(bufsiz);
X        if (buffer == (char *)NULL)
X        {   /* enough memory? */
X            errmsg(SHERR_NOMEM,LOC("io_writestring"));
X            return;
X        }
X    }
X
X    switch (file)
X    {   /* what file descriptor should we use? */
X        case 0:
X            fd = base_env.io->output;
X            break;
X        case 1:
X            fd = base_env.io->errout;
X            break;
X        case 2:
X            fd = 1;
X            break;
X        case 3:
X            fd = 2;
X            break;
X        default:
X            errmsg(0,LOC("io_writestring"),"illegal file specified");
X            return;
X    }
X
X    for (out = buffer; *out; out++)
X        /* do nothing */;
X    if (s == (char *)NULL)
X    {   /* just flush existing buffer */
X        write(fd,buffer,(unsigned)(out - buffer));
X        out = buffer;
X        *out = '\0';
X        return;
X    }
X    for (in = s; *in; in++)
X    {   /* add in the string */
X#ifdef  GEMDOS
X        if (*in == '\n')
X            *out++ = '\r';
X#endif  /* GEMDOS */
X        *out++ = *in;
X        *out = '\0';
X        if (out >= &buffer[bufsiz-1] || *in == '\n')
X        {   /* dump current contents of buffer */
X            write(fd,buffer,(unsigned)(out - buffer));
X            out = buffer;
X            *out = '\0';
X        }
X    }
X}   /* end of io_writestring */
X
END_OF_FILE
if test 10624 -ne `wc -c <'io.c'`; then
    echo shar: \"'io.c'\" unpacked with wrong size!
fi
# end of 'io.c'
fi
if test -f 'reader/vi.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'reader/vi.c'\"
else
echo shar: Extracting \"'reader/vi.c'\" \(9300 characters\)
sed "s/^X//" >'reader/vi.c' <<'END_OF_FILE'
X/*
X * vi		- an "vi" style single line editor for reader
X *
X * Dave Clemans, 4/84 (initial version); 1/89 (more generality)
X *
X * Commands supported:
X *    Input mode:
X *	alphabetic chars are inserted
X *	normal backspace, kill supported
X *	kill word	^W
X *	eof		^D
X *    Editing mode:
X *	forward		l
X *	forward word	e
X *	fwd word nws	E
X *	back word	b
X *	back word nws	B
X *	next word	w
X *	next word nws	W
X *	backward	h
X *	start line	0
X *	start line nws	^
X *	end line	$
X *	prev line	k
X *	next line	j
X *	search prev	/
X *	append		a
X *	append eol	A
X *	kill eol&append	C
X *	kill end line	D
X *	insert		i
X *	insert, 1st nws	I
X *	repeat prev	.
X *	delete char	x
X *	retype		^L
X *	erase		^H
X *	replace char	r
X *	repeat search	n
X *	find char	f
X *	repeat find	;
X *	change chars	c
X *	delete chars	d
X *	pop kill, ins	P
X *	pop kill, app	p
X *	undo change	u
X *	undo all	U
X *	goto		G
X *	arguments	digits
X *
X * If we return 0, we did not handle the input character; it should be
X * handled by the standard editor.
X * If we return <0, signal end-of-file.
X * Otherwise the character has been
X * handled and the next character can be read.
X *
X * $Id: vi.c,v 1.2 89/02/20 20:20:30 dclemans Exp $
X *
X * $Log:	vi.c,v $
X * Revision 1.2  89/02/20  20:20:30  dclemans
X * Add RCS identifiers
X * 
X */
X#include <ctype.h>
X#ifndef GEMDOS
X#include <sgtty.h>
X#endif  GEMDOS
X
X#include "history.h"
X
X/*
X * If true, in "vi" editing mode; else just normal tty style editing
X */
Xstatic int editingMode;
X
X/*
X * Saved copies of things for undo's, etc.
X */
Xstatic char editingChar;
Xstatic char searchChar;
Xstatic struct historyLine saveChange;
Xstatic struct historyLine saveAll;
Xstatic int argument = 1;
X
X/*
X * Check for "vi" style commands
X */
Xint _doVi(c)
Xregister char c;
X{
X	register char cc;
X	register int counter;
X	register int cursor;
X
X	if (!editingMode)
X	{	/* if not doing real editing; i.e. just text insertion */
X		if (c == '\033')
X		{	/* switch to editing mode */
X			strncpy(saveAll.contents,History.currentLine->contents,History.currentLine->size);
X			saveAll.size = History.currentLine->size;
X			saveAll.cursor = History.currentLine->cursor;
X			saveAll.ttycursor = History.currentLine->ttycursor;
X			strncpy(saveChange.contents,History.currentLine->contents,History.currentLine->size);
X			saveChange.size = History.currentLine->size;
X			saveChange.cursor = History.currentLine->cursor;
X			saveChange.ttycursor = History.currentLine->ttycursor;
X			editingMode = 1;
X			return(1);
X		}
X		if (c == '\004')
X		{	/* end of file */
X			editingMode = 0;
X			return(-1);
X		}
X		return(0);
X	}
X
X	/*
X	 * Check for vi style editing commands
X	 */
X	if (c == '.')
X		cc = editingChar;
X	else	cc = c;
X	switch (cc)
X	{	/* if going to make a change, save current state */
X	    case 'x':
X	    case 'a':
X	    case 'A':
X	    case 'i':
X	    case 'I':
X	    case 'c':
X	    case 'C':
X	    case 'd':
X	    case 'D':
X	    case '\010':
X	    case 'p':
X	    case 'P':
X	    case 'G':
X		strncpy(saveChange.contents,History.currentLine->contents,History.currentLine->size);
X		saveChange.size = History.currentLine->size;
X		saveChange.cursor = History.currentLine->cursor;
X		saveChange.ttycursor = History.currentLine->ttycursor;
X		break;
X	    default:	/* no need to do anything here */
X		break;
X	}
X	switch (c)
X	{	/* see which command ... */
X	    case 'l':	/* forward one character */
X		_doStandardSpace(c);
X		break;
X	    case 'h':	/* backward one character */
X		_doStandardBackspace(c);
X		break;
X	    case 'e':	/* forward one word */
X		_spaceNextStdWord();
X		break;
X	    case 'b':	/* backward one word */
X		_spacePrevStdWord();
X		break;
X	    case 'w':	/* to next word */
X		_skipNextStdWord();
X		break;
X	    case 'W':	/* to next word; non-white space */
X		_skipNextWord(" \t");
X		break;
X	    case '0':	/* beginning of line */
X		_doStandardStartLine(c);
X		break;
X	    case '$':	/* end of line */
X		_doStandardEndLine(c);
X		break;
X	    case 'k':	/* previous line */
X		_doStandardPrevLine(c);
X		break;
X	    case 'j':	/* next line */
X		_doStandardNextLine(c);
X		break;
X	    case '/':	/* search lines */
X		_doStandardSrchPrevLine(c,0);
X		break;
X	    case 'n':	/* repeat last search */
X		_doStandardSrchPrevLine(c,1);
X		break;
X	    case 'a':	/* append chars */
X		_doStandardSpace(c);
X		editingMode = 0;
X		break;
X	    case 'A':	/* append to end of line */
X		_doStandardEndLine(c);
X		editingMode = 0;
X		break;
X	    case 'C':	/* delete to end of line; start appending */
X		_doStandardDelEndLine(c);
X		editingMode = 0;
X		break;
X	    case 'D':	/* delete to end of line */
X		_doStandardDelEndLine(c);
X		break;
X	    case 'i':	/* start inserting */
X		editingMode = 0;
X		break;
X	    case 'x':	/* delete current character */
X		_doStandardDelete(c);
X		break;
X	    case '\014':	/* retype line */
X		_doStandardRetype(c);
X		break;
X	    case '^':	/* first non-white space in line */
X		_doStandardStartLine(c);
X		_skipNextWord(" \t");
X		break;
X	    case 'I':	/* goto to first non-white space char in line, start inserting */
X		_doStandardStartLine(c);
X		while ((History.currentLine->cursor < History.currentLine->size) &&
X		    !isspace(History.currentLine->contents[History.currentLine->cursor]))
X			_doStandardSpace(c);
X		editingMode = 0;
X		break;
X	    case '\010':/* do character erase */
X		_doStandardErase(c);
X		break;
X	    case '.':	/* repeat previous editing command */
X		_savechar(editingChar);
X		break;
X	    case 'r':	/* replace char */
X		if (_savedState.stream < 0)
X		{	/* nothing to read from? */
X			_writechar('\007');
X			return(1);
X		}
X		cc = _readchar(_savedState.stream);
X		_doStandardDelete(c);
X		_doStandardCharacter(cc);
X		break;
X	    case '\030':/* expand command or filename */
X		_doStandardExpand(c);
X		break;
X	    case 'E':	/* next word defined by white space */
X		_spaceNextWord(" \t");
X		break;
X	    case 'B':	/* prev word defined by white space */
X		_spacePrevWord(" \t");
X		break;
X	    case 'f':	/* find char */
X		if (_savedState.stream < 0)
X		{	/* nothing to read from? */
X			_writechar('\007');
X			return(1);
X		}
X		searchChar = _readchar(_savedState.stream);
X		/* FALL THROUGH!!! */
X	    case ';':	/* repeat last find char */
X		for (counter = History.currentLine->cursor+1; counter < History.currentLine->size; counter++)
X			if (History.currentLine->contents[counter] == searchChar)
X				break;
X		if ((counter >= History.currentLine->size) ||
X		    (History.currentLine->contents[counter] != searchChar))
X		{	/* not found, at end of line, etc. */
X			_writechar('\007');
X			return(1);
X		}
X		while (History.currentLine->cursor < counter)
X			_doStandardSpace('\000');
X		break;
X	    case 'c':	/* change chars */
X	    case 'd':	/* delete chars */
X		if (_savedState.stream < 0)
X		{	/* nothing to read from? */
X			_writechar('\007');
X			return(1);
X		}
X		cc = _readchar(_savedState.stream);
X		counter = History.currentLine->cursor;
X		_doVi(cc);
X		editingChar = c;
X		if (counter <= History.currentLine->cursor)
X		{	/* set start and stop points for range delete */
X			cursor = counter;
X			counter = History.currentLine->cursor;
X		}
X		else
X		{	/* moved other direction */
X			cursor = History.currentLine->cursor;
X		}
X		_deleteTo(cursor,counter);
X		if (c == 'c')
X			editingMode = 0;
X		break;
X	    case 'P':	/* pop from kill ring, inserting before cursor */
X		_savechar('i');
X		_popOffKillRing();
X		_savechar('\033');
X		break;
X	    case 'p':	/* pop from kill ring, appending to cursor */
X		_savechar('a');
X		_popOffKillRing();
X		_savechar('\033');
X		break;
X	    case 'U':	/* undo all changes */
X		_doStandardKill('\000');
X		strncpy(History.currentLine->contents,saveAll.contents,saveAll.size);
X		History.currentLine->size = saveAll.size;
X		History.currentLine->cursor = saveAll.cursor;
X		History.currentLine->ttycursor = saveAll.ttycursor;
X		_doStandardRetype('\000');
X		break;
X	    case 'u':	/* undo last changes */
X		_doStandardKill('\000');
X		strncpy(History.currentLine->contents,saveChange.contents,saveChange.size);
X		History.currentLine->size = saveChange.size;
X		History.currentLine->cursor = saveChange.cursor;
X		History.currentLine->ttycursor = saveChange.ttycursor;
X		_doStandardRetype('\000');
X		break;
X	    case 'G':	/* goto a command */
X		/* so far, support only for default case; goto oldest command */
X		_doStandardKill('\000');
X		strncpy(History.currentLine->contents,History.listBottom->contents,History.listBottom->size);
X		History.currentLine->size = History.listBottom->size;
X		History.currentLine->cursor = History.listBottom->cursor;
X		History.currentLine->ttycursor = History.listBottom->ttycursor;
X		_doStandardRetype('\000');
X		_doStandardEndLine('\000');
X		break;
X	    case '\004':/* eof; use default handling */
X	    case '\r':	/* eol; use default handling */
X	    case '\n':
X		editingMode = 0;
X		return(0);
X	    case '1':	/* for setting numerical argument */
X	    case '2':
X	    case '3':
X	    case '4':
X	    case '5':
X	    case '6':
X	    case '7':
X	    case '8':
X	    case '9':
X		argument = 0;
X		if (_savedState.stream < 0)
X		{	/* nothing to read from? */
X			_writechar('\007');
X			return(1);
X		}
X		argument = 0;
X		for (; isdigit(c); c = _readchar(_savedState.stream))
X		{	/* build value */
X			argument *= 10;
X			argument += (int)((int)c - (int)'0');
X		}
X		if (c == EOF)
X			return(-1);
X		_savechar(c);
X		return(1);
X	    default:	/* we don't know about it */
X		_writechar('\007');
X		break;
X	}
X	editingChar = c;
X	argument = 1;
X	return(1);
X};	/* end of _doVi */
END_OF_FILE
if test 9300 -ne `wc -c <'reader/vi.c'`; then
    echo shar: \"'reader/vi.c'\" unpacked with wrong size!
fi
# end of 'reader/vi.c'
fi
if test -f 'reader/words.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'reader/words.c'\"
else
echo shar: Extracting \"'reader/words.c'\" \(8564 characters\)
sed "s/^X//" >'reader/words.c' <<'END_OF_FILE'
X/*
X * words		- routines to find words in lines for reader
X *
X * Dave Clemans, 4/84 (initial version); 1/89 (more generality)
X *
X * Entry points:
X *	_findNextWord	- find next "word" given by specified delimiters
X *	_findPrevWord	- find prev "word" given by specified delimiters
X *	_deleteNextWord	- delete next "word"
X *	_deletePrevWord	- delete prev "word"
X *	_spaceNextWord	- space to next "word"
X *	_spacePrevWord	- space to previous "word"
X *	_skipNextWord	- skip to next "word"
X *	_findNextStdWord	- find next word given by [A-Z][a-z][0-9]_
X *	_findPrevStdWord	- find prev word given by [A-Z][a-z][0-9]_
X *	_deleteNextStdWord	- delete next standard word
X *	_deletePrevStdWord	- delete prev standard word
X *	_spaceNextStdWord	- space to next word
X *	_spacePrevStdWord	- space to previous word
X *	_skipNextStdWord	- skip to next word
X *	_capitalizeStdWord	- capitalize this word
X *
X * $Id: words.c,v 1.2 89/02/20 20:20:33 dclemans Exp $
X *
X * $Log:	words.c,v $
X * Revision 1.2  89/02/20  20:20:33  dclemans
X * Add RCS identifiers
X * 
X */
X#include <ctype.h>
X#ifndef GEMDOS
X#include <sgtty.h>
X#endif  GEMDOS
X
X#include "history.h"
X
X/*
X * Interesting function definitions
X */
Xextern char *index();
X
X/*
X * Find the next word in the global History.currentLine given by the
X * passed delimiters; return index of end of that word
X */
Xint _findNextWord(delimiters)
Xchar *delimiters;
X{
X	register char *rc;
X	register int ip;
X
X	ip = History.currentLine->cursor+1;
X	while (index(delimiters,History.currentLine->contents[ip]))
X	{	/* between words */
X		ip++;
X		if (ip >= History.currentLine->size)
X			break;
X	}
X	for (; ip < History.currentLine->size; ++ip)
X	{	/* go through rest of line */
X		rc = index(delimiters,History.currentLine->contents[ip]);
X		if (rc)	/* a delimiter is found! */
X			return(ip-1);
X	}
X	return(ip);	/* ip == end of line at this point */
X};	/* end of _findNextWord */
X
X/*
X * Find the previous word in the global History.currentLine given by the
X * passed delimiters; return index of end of that word
X */
Xint _findPrevWord(delimiters)
Xchar *delimiters;
X{
X	register char *rc;
X	register int ip;
X
X	ip = History.currentLine->cursor-1;
X	while (index(delimiters,History.currentLine->contents[ip]))
X	{	/* between words */
X		ip--;
X		if (ip < 0)
X			break;
X	}
X	for (; ip >= 0; --ip)
X	{	/* go through rest of line */
X		rc = index(delimiters,History.currentLine->contents[ip]);
X		if (rc)	/* a delimiter is found! */
X			return(ip+1);
X	}
X	return(0);	/* beginning of line */
X};	/* end of _findPrevWord */
X
X/*
X * Delete the next word in the line given by "delimiters"
X */
X_deleteNextWord(delimiters)
Xchar *delimiters;
X{
X	register int word;
X	register int counter;
X
X	word = _findNextWord(delimiters);
X	_pushOnKillRing(History.currentLine->cursor,word);
X	for (counter = 0; counter < (word-History.currentLine->cursor+1); counter++)
X		_doStandardDelete('\000');
X};	/* end of _deleteNextWord */
X
X/* Delete the previous word in the line given by "delimiters"
X */
X_deletePrevWord(delimiters)
Xchar *delimiters;
X{
X	register int word;
X	register int counter;
X
X	word = _findPrevWord(delimiters);
X	_doStandardSpace('\000');
X	for (counter = 0; counter < (History.currentLine->cursor-word+1); counter++)
X		_doStandardErase('\000');
X};	/* end of _deletePrevWord */
X
X/*
X * Space forward to next word in line
X */
X_spaceNextWord(delimiters)
Xchar *delimiters;
X{
X	register int word;
X
X	word = _findNextWord(delimiters);
X	while (History.currentLine->cursor < word)
X		_doStandardSpace('\000');
X};	/* end of _spaceNextWord */
X
X/*
X * Space backward to next word in line
X */
X_spacePrevWord(delimiters)
Xchar *delimiters;
X{
X	register int word;
X
X	word = _findPrevWord(delimiters);
X	while (History.currentLine->cursor > word)
X		_doStandardBackspace('\000');
X};	/* end of _spacePrevWord */
X
X/*
X * Skip to beginning of word after one that we are in.
X */
X_skipNextWord(delimiters)
Xchar *delimiters;
X{
X	register int ip;
X
X	ip = History.currentLine->cursor;
X	if (!index(delimiters,History.currentLine->contents[ip]))
X	{	/* in a word; goto end */
X		for (;ip < History.currentLine->size;)
X		{	/* goto end of current word */
X			if (index(delimiters,History.currentLine->contents[ip]))
X				break;
X			ip++;
X		}
X	}
X	if (index(delimiters,History.currentLine->contents[ip]))
X	{	/* between words */
X		for (;ip < History.currentLine->size;)
X		{	/* goto next word */
X			if (!index(delimiters,History.currentLine->contents[ip]))
X				break;
X			ip++;
X		}
X	}
X	while (History.currentLine->cursor < ip)
X		_doStandardSpace('\000');
X};	/* end of _skipNextWord */
X
X/*
X * Find the next word in the line where a word is composed of alphanumeric's
X * and _.
X */
Xint _findNextStdWord()
X{
X	register int ip;
X	register char cc;
X
X	ip = History.currentLine->cursor+1;
X	cc = History.currentLine->contents[ip];
X	if (!isalpha(cc) && !isdigit(cc) && (cc != '_'))
X	{	/* between words */
X		for (;ip < History.currentLine->size;)
X		{	/* between words; look for next one */
X			cc = History.currentLine->contents[ip];
X			if (isalpha(cc) || isdigit(cc) || (cc == '_'))
X				break;
X			ip++;
X		}
X	}
X	for (; ip < History.currentLine->size; ip++)
X	{	/* search for words */
X		cc = History.currentLine->contents[ip];
X		if (!isalpha(cc) && !isdigit(cc) && (cc != '_'))
X			return(ip-1);
X	}
X	return(ip);	/* will always be end of line */
X};	/* end of _findNextStdWord */
X
X/*
X * Find the previous word in the line where a word is composed of alphanumeric's
X * and _.
X */
Xint _findPrevStdWord()
X{
X	register int ip;
X	register char cc;
X
X	ip = History.currentLine->cursor-1;
X	cc = History.currentLine->contents[ip];
X	if (!isalpha(cc) && !isdigit(cc) && (cc != '_'))
X	{	/* between words */
X		for (;ip >= 0;)
X		{	/* between words; look for next one */
X			cc = History.currentLine->contents[ip];
X			if (isalpha(cc) || isdigit(cc) || (cc == '_'))
X				break;
X			ip--;
X		}
X	}
X	for (; ip > 0; --ip)
X	{	/* search for words */
X		cc = History.currentLine->contents[ip];
X		if (!isalpha(cc) && !isdigit(cc) && (cc != '_'))
X			return(ip+1);
X	}
X	return(0);	/* beginning of line */
X};	/* end of _findPrevStdWord */
X
X/*
X * Delete the next word in the line
X */
X_deleteNextStdWord()
X{
X	register int word;
X	register int counter;
X
X	word = _findNextStdWord();
X	_pushOnKillRing(History.currentLine->cursor,word);
X	for (counter = 0; counter < (word-History.currentLine->cursor+1); counter++)
X		_doStandardDelete('\000');
X};	/* end of _deleteNextStdWord */
X
X/*
X * Delete the previous word in the line
X */
X_deletePrevStdWord()
X{
X	register int word;
X	register int counter;
X
X	word = _findPrevStdWord();
X	_doStandardSpace('\000');
X	for (counter = 0; counter < (History.currentLine->cursor-word+1); counter++)
X		_doStandardErase('\000');
X};	/* end of _deletePrevStdWord */
X
X/*
X * Space forward to next word in line
X */
X_spaceNextStdWord()
X{
X	register int word;
X
X	word = _findNextStdWord();
X	while (History.currentLine->cursor < word)
X		_doStandardSpace('\000');
X};	/* end of _spaceNextStdWord */
X
X/*
X * Space backward to next word in line
X */
X_spacePrevStdWord()
X{
X	register int word;
X
X	word = _findPrevStdWord();
X	while (History.currentLine->cursor > word)
X		_doStandardBackspace('\000');
X};	/* end of _spacePrevStdWord */
X
X/*
X * Skip to beginning of word after one that we are in.
X */
X_skipNextStdWord()
X{
X	register char cc;
X	register int ip;
X
X	ip = History.currentLine->cursor;
X	cc = History.currentLine->contents[ip];
X	if (isalpha(cc) || isdigit(cc) || (cc == '_'))
X	{	/* in a word; goto end */
X		for (;ip < History.currentLine->size;)
X		{	/* goto end of current word */
X			if (!isalpha(cc) && !isdigit(cc) && (cc != '_'))
X				break;
X			ip++;
X			cc = History.currentLine->contents[ip];
X		}
X	}
X	if (!isalpha(cc) && !isdigit(cc) && (cc != '_'))
X	{	/* between words */
X		for (;ip < History.currentLine->size;)
X		{	/* goto next word */
X			if (isalpha(cc) || isdigit(cc) || (cc == '_'))
X				break;
X			ip++;
X			cc = History.currentLine->contents[ip];
X		}
X	}
X	while (History.currentLine->cursor < ip)
X		_doStandardSpace('\000');
X};	/* end of _skipNextStdWord */
X
X/*
X * Capitalize the word that we are now in
X */
X_capitalizeStdWord()
X{
X	register char cc;
X	register int ip,size;
X
X	ip = History.currentLine->cursor;
X	cc = History.currentLine->contents[ip];
X	if (!isalpha(cc) && !isdigit(cc) && (cc != '_'))
X	{	/* not in word??? */
X		_writechar('\007');
X		return;
X	}
X	_spaceNextStdWord();
X	_spacePrevStdWord();
X	ip = _findNextStdWord();
X	_pushOnKillRing(History.currentLine->cursor,ip);
X	size = ip-History.currentLine->cursor+1;
X	for (ip = 0; ip < size; ip++)
X	{	/* go through word, capitalizing it */
X		_doStandardCapitalize('\000');
X		_doStandardSpace('\000');
X	}
X};	/* end of _capitalizeStdWord */
END_OF_FILE
if test 8564 -ne `wc -c <'reader/words.c'`; then
    echo shar: \"'reader/words.c'\" unpacked with wrong size!
fi
# end of 'reader/words.c'
fi
if test -f 'shell.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'shell.h'\"
else
echo shar: Extracting \"'shell.h'\" \(8325 characters\)
sed "s/^X//" >'shell.h' <<'END_OF_FILE'
X/*
X * Command Input Shell
X * Dave Clemans
X * 12/88-1/89
X *
X * "spiritually" based on Bourne, Korn shells
X *
X * $Id: shell.h,v 1.10 89/03/05 15:38:52 dclemans Exp $
X *
X * $Log:	shell.h,v $
X * Revision 1.10  89/03/05  15:38:52  dclemans
X * more fixes
X * 
X * Revision 1.9  89/02/22  21:32:02  dclemans
X * Implement simple background job monitoring facility
X * 
X * Revision 1.8  89/02/22  13:19:00  dclemans
X * Implement $!
X * 
X * Revision 1.7  89/02/22  08:17:15  dclemans
X * implement left-justified, right-justified, etc. parameter attributes
X * 
X * Revision 1.6  89/02/21  19:40:11  dclemans
X * Implement RANDOM and SECONDS variables
X * 
X * Revision 1.5  89/02/20  20:07:16  dclemans
X * Add RCS identifiers
X * 
X */
X#ifdef  USG
X#include <string.h>
X#else
X#include <strings.h>
X#endif  /* USG */
X#include <ctype.h>
X#ifdef  GEMDOS
X#include <osbind.h>
X#ifdef  MWC
X#define DEFSTACK    6144L
X#endif  /* MWC */
X#endif  /* GEMDOS */
X
X#define LOC(r)  __FILE__,r,__LINE__
X
X#include <errno.h>
X
X#ifndef GEMDOS
X#ifndef USG
X#define strchr  index
X#define strrchr rindex
X#define memcpy(t,f,n) bcopy(f,t,n)
X#endif  /* USG */
X#else
X#define	bcopy(f,t,n) memcpy(t,f,n)
X#endif  /* GEMDOS */
X
X#ifdef  GEMDOS
X#define NO_FILE(rc) (rc == AEFILNF || rc == AEPTHNF || rc == AENHNDL || rc == AENSMEM || rc == AEDRIVE || rc == AENMFIL)
X#define NOT_EXEC(rc)    (rc == AEPLFMT)
X#else
X/* fix these */
X#define NO_FILE(rc) (rc == ENOENT)
X#define NOT_EXEC(rc)    (rc == ENOEXEC)
X#endif  /* GEMDOS */
X
X#define SYM_MARKER          -3
X#define SYM_EOF             -2
X#define SYM_EOL             -1
X#define SYM_WORD            0
X#define SYM_SEMI            1
X#define SYM_BACK            2
X#define SYM_LT              3
X#define SYM_LLT             4
X#define SYM_RT              5
X#define SYM_RRT             6
X#define SYM_LBT             7
X#define SYM_RBT             8
X#define SYM_LBRACE          9
X#define SYM_RBRACE          10
X#define SYM_PIPE            11
X#define SYM_ORIF            12
X#define SYM_ANDIF           13
X#define SYM_KEYWORD         14
X#define SYM_NUMBER          15
X#define SYM_LPAREN          16
X#define SYM_RPAREN          17
X#define SYM_PIPER           18      /* pseudo-marker used in pipe tagging */
X#define SYM_BQUOTE          19
X#define SYM_DLPAREN         20
X#define SYM_DRPAREN         21
X#define SYM_LLTL            22
X#define SYM_DLBRACK         23
X#define SYM_DRBRACK         24
X#define SYM_DSEMI           25
X
X#define DEFAULT_HISTORY 16
X#define PROMPT_MAX      3
X#ifdef  GEMDOS
X#define ESCAPE_CHAR     '@'
X#define DIR_SEPARATOR   '\\'
X#define MAXUFD          5
X#else
X#define ESCAPE_CHAR     '\\'
X#define DIR_SEPARATOR   '/'
X#define MAXUFD          ((_NFILE > 20) ? 20 : _NFILE)
X#endif  /* GEMDOS */
X
X#define SHERR_NOMEM     -1
X#define SHERR_PERROR    -2
X
X#define TYPE_EXPORTED   0x01
X#define TYPE_READONLY   0x02
X#define TYPE_INTEGER    0x04
X#define TYPE_UPPERCASE	0x10
X#define TYPE_LOWERCASE	0x20
X#define TYPE_TAGGED     0x40
X#define TYPE_FUNCTION   0x80
X#define TYPE_LEFTJUST   0x100
X#define TYPE_RIGHTJUST  0x200
X#define TYPE_ZEROS      0x400
X#define TYPE_HOSTMAP    0x800
X#define TYPE_DELETED    0x8000
X
X#define TYPE_TRACKED    0x4000
X
X/*
X * Shell lexing structures
X */
Xstruct token
X{
X    int     type;
X    struct  token *next;
X    char    name[1];        /* over-indexed, must be at end */
X};
Xstruct  iotoken
X{
X    int     fd;
X    int     type;
X    char    *tempfile;
X    struct  iotoken *next;
X    char    file[1];        /* over-indexed; must be at end */
X};
Xstruct phrase
X{
X    struct  token *type;
X    struct  token *body;
X    struct  token *body_end;
X    struct  token *var;
X    struct  token *var_end;
X    struct  iotoken *io;
X    struct  iotoken *io_end;
X    struct  phrase *group;
X    struct  phrase *group_end;
X    struct  phrase *next;
X};
Xstruct  infile
X{
X    char    *name;
X    int     fp;
X    int     delete;
X    int     nonl;
X    int     markeof;
X    char    *start;
X    char    *end;
X    char    buffer[256];
X    struct  infile *next;
X};
Xstruct strsave
X{
X    char    *string;
X    char    *ptr;
X    struct  strsave *next;
X};
X#ifndef GEMDOS
Xstruct procs
X{
X    int pid;
X    struct procs *next;
X};
Xstruct bg_job
X{
X    struct phrase *job;
X    struct procs *cmds;
X    struct bg_job *next;
X};
X#endif  /* GEMDOS */
X
X/*
X * Shell environment structures
X */
Xstruct  commands
X{
X    char    *name;
X    int     (*cmd)();
X};
Xstruct variable
X{
X    char    *name;
X    char    *value;
X    int     cmd;
X    int     type;
X    int     misc;
X    struct  variable *left,*right;
X};
Xstruct  aliases
X{
X    char    *name;
X    struct  token *tp;
X    int     type;
X    struct  aliases *left,*right;
X};
Xstruct  function
X{
X    char    *name;
X    struct  phrase *code;
X    struct  function *left,*right;
X};
Xstruct  iostack
X{
X    int input;
X    int output;
X    int errout;
X    struct  iostack *next;
X};
Xstruct  dirstack
X{
X    char    *current;
X    struct  dirstack *next;
X};
Xstruct  varstack
X{
X    struct  variable *table;
X    struct  varstack *next;
X};
Xstruct  herestack
X{
X    struct  iotoken *doc;
X    struct  herestack *next;
X};
Xstruct  hist_phrase
X{   int     number;
X    struct  phrase *cmd;
X};
Xstruct  envinfo
X{
X    long    start_at;
X    int     prompts_issued[PROMPT_MAX+1];
X    char    *prompts[PROMPT_MAX+1];
X    char    *homedir;
X    char    *envfile;
X    char    *shellname;
X    int     columns,lines;
X    char    *separators;
X    char    *cd_path;
X    char    *exec_path;
X    int     break_level;
X    int     continue_level;
X    int     temp_count;
X    int     history_size;
X    struct  hist_phrase *history_list;
X#ifdef  GEMDOS
X    int     fd_con,fd_aux,fd_prn;
X    char    *tmpdir;
X    char    *exec_suff;
X#endif  /* GEMDOS */
X    struct  varstack *var;
X    struct  aliases *alias_table;
X    struct  function *func_table;
X    struct  dirstack *dir;
X#ifndef GEMDOS
X    struct  bg_job *jobs;
X#endif  /* GEMDOS */
X    int     fd_input;
X    int     background_pid;
X    struct  iostack *io;
X    struct  herestack *pending_heredocs;
X};
X
Xextern  char    shell_version[];
Xextern  struct  envinfo base_env;
X
Xextern  char    *var_arg0;
Xextern  int     var_argc;
Xextern  char    **var_argv;
Xextern  char    *var_init[];
Xextern  void    var_dump();
Xextern  void    var_settype();
Xextern  void    var_resetargs();
Xextern  void    var_shiftargs();
Xextern  void    var_define0();
Xextern  char    *var_makeenv();
Xextern  char    *var_normal();
Xextern  char    *var_reference();
X
Xextern  void    alias_dump();
Xextern  int     alias_print();
Xextern  void    alias_define();
Xextern  int     alias_tracked();
Xextern  struct  aliases *alias_get();
X
Xextern  void    io_writestring();
Xextern  struct  infile *buffile;
Xextern  struct  strsave *strings;
X
Xextern  int     lchdir();
Xextern  char    *strcopy();
Xextern  void    stripquotes();
Xextern  int     errmsg();
Xextern  char    *new_string();
Xextern  char    **new_argv();
Xextern  struct  phrase *copy_phrase();
Xextern  struct  phrase *copy_group();
Xextern  struct  phrase *new_phrase();
Xextern  struct  token *new_token();
Xextern  struct  iotoken *new_iotoken();
Xextern  struct  variable *new_variable();
Xextern  struct  aliases *new_alias();
Xextern  struct  function *new_function();
Xextern  struct  infile *new_infile();
Xextern  struct  strsave *new_strsave();
X
Xextern  struct  phrase *lex_sentence();
Xextern	struct	phrase *lex_phrase();
Xextern  struct  token *lex_token();
Xextern  struct  token *lex_reparse_tokens();
X
Xextern  struct  function *func_get();
Xextern  char    *exec_pathsearch();
Xextern  int     exec_phrase();
Xextern	void	phrase_dump();
Xextern  void    sentence_dump();
Xextern	void	phrase_free();
Xextern  void    sentence_free();
Xextern  void    tokens_free();
X
Xextern  int     flag_echoinput;
Xextern  int     flag_echoexec;
Xextern  int     flag_keywords;
Xextern  int     flag_cmdhash;
Xextern  int     flag_varerr;
Xextern  int     flag_noglob;
Xextern  int     flag_allexport;
Xextern  int     flag_noexec;
Xextern  int     flag_interactive;
Xextern  int     flag_monitor;
X
Xextern  int     cmd_lastrc;
Xextern  int     cmd_forceexit;
Xextern  int     cmd_returnexit;
Xextern  int     cmd_count;
Xextern  struct  commands cmd_builtin[];
X
Xextern  struct  token *wild_search();
X
X#ifndef GEMDOS
Xextern  int     main_fdget();
Xextern  int     main_fdput();
X#endif  /* GEMDOS */
Xextern  int     main_iopush();
Xextern  int     main_iopop();
Xextern  int     main_dirpush();
Xextern  int     main_dirpop();
END_OF_FILE
if test 8325 -ne `wc -c <'shell.h'`; then
    echo shar: \"'shell.h'\" unpacked with wrong size!
fi
# end of 'shell.h'
fi
if test -f 'trap.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'trap.c'\"
else
echo shar: Extracting \"'trap.c'\" \(14049 characters\)
sed "s/^X//" >'trap.c' <<'END_OF_FILE'
X/*
X * Command Input Shell
X * Dave Clemans
X * 12/88-1/89
X *
X * "spiritually" based on Bourne, Korn shells
X *
X * Signal handling; the "kill" built-in; the "jobs" built-in
X *
X * $Id: trap.c,v 1.9 89/03/05 15:38:55 dclemans Exp $
X *
X * $Log:	trap.c,v $
X * Revision 1.9  89/03/05  15:38:55  dclemans
X * more fixes
X * 
X * Revision 1.8  89/02/23  08:08:42  dclemans
X * make kill work with background jobs list
X * 
X * Revision 1.7  89/02/22  21:32:04  dclemans
X * Implement simple background job monitoring facility
X * 
X * Revision 1.6  89/02/21  20:37:29  dclemans
X * Fix bug with signal_map on systems with varying
X * numbers of signals
X * 
X * Revision 1.5  89/02/21  20:30:00  dclemans
X * Fix bug with shell variable references in history lists.
X * 
X * Revision 1.4  89/02/21  08:36:51  dclemans
X * Implement pseudo-signals ERR, EXIT, DEBUG
X * 
X * Revision 1.3  89/02/20  22:54:24  dclemans
X * correct signal names
X * 
X * Revision 1.2  89/02/20  22:49:11  dclemans
X * bug fix
X * implement kill -l
X * 
X * Revision 1.1  89/02/20  22:27:23  dclemans
X * Initial revision
X * 
X */
X#include <stdio.h>
X#include "shell.h"
X
X#ifndef GEMDOS
X#include <signal.h>
X#else
X#define NSIG    0
X#endif  /* GEMDOS */
X
Xstatic char *signal_map[] =
X{
X    "EXIT",
X#ifndef GEMDOS
X    "HUP",
X    "INT",
X    "QUIT",
X    "ILL",
X    "TRAP",
X    "IOT",
X    "EMT",
X    "FPE",
X    "KILL",
X    "BUS",
X    "SEGV",
X    "SYS",
X    "PIPE",
X    "ALRM",
X    "TERM",
X    "USR1",
X#if NSIG > 16
X    "USR2",
X    "CLD",
X    "",
X    "STOP",
X    "TSTP",
X    "",
X    "CHLD",
X    "TTIN",
X    "TTOU",
X    "TINT",
X    "XCPU",
X    "XFSZ",
X    "VTALRM",
X    "PROF",
X    "URG",
X    "WINCH",
X#endif
X#endif  /* GEMDOS */
X    "ERR",
X    "DEBUG",
X    (char *)NULL
X};
X
Xstruct  signal_record
X{
X    struct  phrase *action;
X    int     status;
X};
X#define IGNORED 0x0001
X#define ACTION  0x0002
Xstatic struct signal_record signals[NSIG+3];
X
Xstatic int signal_number(sig)
Xregister char *sig;
X{
X    register int i;
X    register char *cp;
X    char buffer[16];
X
X    for (i = 0; signal_map[i] != (char *)NULL; i++)
X    {   /* look for a match */
X        if (strlen(signal_map[i]) == 0)
X            continue;
X        if (strcmp(sig,signal_map[i]) == 0)
X            return i;
X        strcpy(buffer,signal_map[i]);
X        for (cp = buffer; *cp; cp++)
X            if (isupper(*cp))
X                *cp = _tolower(*cp);
X        if (strcmp(sig,buffer) == 0)
X            return i;
X    }
X    return -1;
X}   /* end of signal_name */
X
Xint signal_handler(sig)
Xint sig;
X{
X    register struct signal_record *this_sig;
X    char buffer[256];
X
X    if (sig >= 1 || sig <= NSIG)
X    {   /* need to reset the signal? */
X#ifndef GEMDOS
X#ifndef USG
X        /* don't need anything here; BSD semantics don't need resetting */
X#else
X        signal(sig,signal_handler);
X#endif  /* USG */
X#endif  /* GEMDOS */
X    }
X    if (sig < 0 || sig >= NSIG+3)
X        return -1;
X    this_sig = &signals[sig];
X    if (this_sig->status & IGNORED)
X        return 0;
X    if (this_sig->status & ACTION)
X    {   /* execute the specified phrase */
X        if (this_sig->action != (struct phrase *)NULL)
X            exec_phrase(this_sig->action,0);
X        return 0;
X    }
X    if (sig == 0 || sig > NSIG)
X        return 0;
X    errmsg(0,LOC("signal_handler"),"received signal #%d; exiting.",sig);
X    cmd_forceexit = 1;
X    return 0;
X}   /* end of signal_handler */
X
Xvoid force_signal(name)
Xchar *name;
X{
X    register int sig;
X
X    sig = signal_number(name);
X    if (sig < 0)
X    {   /* if unknown signal */
X        errmsg(0,LOC("force_signal"),"unable to decode pseudo-signal name %s",name);
X        return;
X    }
X    signal_handler(sig);
X}   /* end of force_signal */
X
Xint signal_init()
X{
X#ifdef  never
X    /* don't know what to do here yet... don't want to hit every signal */
X    register int i;
X#ifndef GEMDOS
X#ifndef USG
X    struct sigvec handler;
X#endif  /* USG */
X#endif  /* GEMDOS */
X
X#ifndef GEMDOS
X#ifndef USG
X    handler.sv_handler = signal_handler;
X    handler.sv_onstack = 0;
X    for (i = 1; i <= NSIG; i++)
X    {   /* set up the appropriate handlers */
X        handler.sv_mask = sigmask(i);
X        sigvec(i,&handler,(struct sigvec *)NULL);
X    }
X#else
X    for (i = 1; i <= NSIG; i++)
X        signal(i,signal_handler);
X#endif  /* USG */
X#endif  /* GEMDOS */
X#endif  /* never */
X}   /* end of signal_init */
X
Xint cmd_trap(pp)
Xstruct phrase *pp;
X{
X    register struct token *tp;
X    register int sig;
X    struct phrase *torun,*toend,*np;
X    char *cp;
X    char tempfile[64];
X    struct token *action;
X    int status,fd;
X#ifndef GEMDOS
X#ifndef USG
X    struct sigvec handler;
X#endif  /* USG */
X#endif  /* GEMDOS */
X
X    if (pp->body->next == (struct token *)NULL)
X    {   /* any parms? */
X        errmsg(0,LOC("cmd_trap"),"missing action or condition args");
X        return -1;
X    }
X    action = pp->body->next;
X    tp = action->next;
X    if (tp == (struct token *)NULL)
X    {   /* any conditions? */
X        errmsg(0,LOC("cmd_trap"),"missing condition args");
X        return -1;
X    }
X    if (strlen(action->name) == 0)
X    {   /* ignore signal action? */
X        action = (struct token *)NULL;
X        status = IGNORED;
X    }
X    else if (strcmp(action->name,"-") == 0)
X    {   /* reset signal action? */
X        action = (struct token *)NULL;
X        status = 0;
X    }
X    else status = ACTION;
X    if (action->type == SYM_NUMBER || signal_number(action->name) >= 0)
X    {   /* was a action REALLY specified? */
X        tp = action;
X        status = 0;
X        action = (struct token *)NULL;
X    }
X    torun = (struct phrase *)NULL;
X    if (action != (struct token *)NULL)
X    {   /* need to reparse tokens into an executable phrase */
X        cp = strcopy(action->name);
X        if (cp == (char *)NULL)
X        {   /* enough memory? */
X            /* message already printed */
X            return -1;
X        }
X        stripquotes(cp);
X#ifdef  GEMDOS
X        sprintf(tempfile,"%stemp%d.tmp",base_env.tmpdir,base_env.temp_count++);
X#else
X        sprintf(tempfile,"/tmp/sh%d.temp",base_env.temp_count++);
X#endif  /* GEMDOS */
X        fd = creat(tempfile,0666);
X        if (fd < 0)
X        {   /* did we get a temporary file? */
X            errmsg(0,LOC("cmd_trap"),"unable to open tempfile");
X            return 1;
X        }
X        write(fd,cp,strlen(cp));
X        write(fd,"\n",1);
X        close(fd);
X        free(cp);
X
X        if (io_pushfile(tempfile,1,0,1) < 0)
X        {   /* if saving the file failed */
X            errmsg(0,LOC("cmd_trap"),"unable to put tempfile into input stream");
X            delete_later(tempfile);
X            return 1;
X        }
X        torun = toend = (struct phrase *)NULL;
X        while ((np = lex_phrase(1,0)) != (struct phrase *)NULL)
X        {   /* get back contents of file */
X            if (np->type != (struct token *)NULL && np->type->type == SYM_MARKER)
X            {   /* reached end of file */
X                phrase_free(np);
X                break;
X            }
X            if (torun == (struct phrase *)NULL)
X                torun = toend = np;
X            else
X            {   /* tack onto end */
X                toend->next = np;
X                toend = np;
X            }
X        }
X    }
X
X    while (tp != (struct token *)NULL)
X    {   /* while there is a condition we need to set */
X        if (tp->type == SYM_NUMBER)
X            sig = atoi(tp->name);
X        else sig = signal_number(tp->name);
X        if (sig < 0 || sig >= NSIG+3)
X        {   /* good signal number? */
X            errmsg(0,LOC("cmd_trap"),"bad signal number %s=%d",tp->name,sig);
X            tp = tp->next;
X            continue;
X        }
X        if (signals[sig].action != (struct phrase *)NULL)
X        {   /* free old action? */
X            phrase_free(signals[sig].action);
X            signals[sig].action = (struct phrase *)NULL;
X        }
X        switch (status)
X        {   /* what to do... */
X            case ACTION:
X#ifndef GEMDOS
X                if (sig >= 1 && sig <= NSIG)
X                {   /* if a valid system signal */
X#ifndef USG
X                    handler.sv_handler = signal_handler;
X                    handler.sv_mask = sigmask(sig);
X                    handler.sv_onstack = 0;
X                    sigvec(sig,&handler,(struct sigvec *)NULL);
X#else
X                    signal(sig,signal_handler);
X#endif  /* USG */
X                }
X#endif  /* GEMDOS */
X                signals[sig].status = ACTION;
X                if (torun != (struct phrase *)NULL)
X                    signals[sig].action = copy_phrase(torun,0,0,1);
X                break;
X            case IGNORED:
X#ifndef GEMDOS
X                if (sig >= 1 && sig <= NSIG)
X                {   /* if a valid system signal */
X#ifndef USG
X                    handler.sv_handler = SIG_IGN;
X                    handler.sv_mask = sigmask(sig);
X                    handler.sv_onstack = 0;
X                    sigvec(sig,&handler,(struct sigvec *)NULL);
X#else
X                    signal(sig,SIG_IGN);
X#endif  /* USG */
X                }
X#endif  /* GEMDOS */
X                signals[sig].status = IGNORED;
X                break;
X            default:
X#ifndef GEMDOS
X                if (sig >= 1 && sig <= NSIG)
X                {   /* if a valid system signal */
X#ifndef USG
X                    handler.sv_handler = SIG_DFL;
X                    handler.sv_mask = sigmask(sig);
X                    handler.sv_onstack = 0;
X                    sigvec(sig,&handler,(struct sigvec *)NULL);
X#else
X                    signal(sig,SIG_DFL);
X#endif  /* USG */
X                }
X#endif  /* GEMDOS */
X                signals[sig].status = 0;
X                break;
X        }
X        tp = tp->next;
X    }
X    if (torun != (struct phrase *)NULL)
X        phrase_free(torun);
X
X    return 0;
X}   /* end of cmd_trap */
X
X#ifndef GEMDOS
Xint cmd_kill(pp)
Xstruct phrase *pp;
X{
X    register struct token *tp;
X    register int sig;
X    register char *p;
X    struct bg_job *job;
X    struct procs *cmd;
X    char *savep;
X    int i,ncol,maxlength;
X    char buffer[BUFSIZ];
X
X    tp = pp->body->next;
X    if (tp == (struct token *)NULL)
X    {   /* anything to do? */
X        errmsg(0,LOC("cmd_kill"),"no args specified");
X        return -1;
X    }
X    if (strcmp(tp->name,"-l") == 0 || strcmp(tp->name,"-L") == 0)
X    {   /* list out known signal names */
X        maxlength = 0;
X        for (sig = 1; sig <= NSIG; sig++)
X            if (strlen(signal_map[sig]) > maxlength)
X                maxlength = strlen(signal_map[sig]);
X        maxlength += 7;     /* for column sep, etc. */
X        ncol = base_env.columns / maxlength;
X        if ((NSIG < (base_env.lines*2/3)) || (ncol < 1))
X        {   /* just a single list? */
X            for (sig = 1; sig <= NSIG; sig++)
X            {   /* print the menu */
X                sprintf(buffer,"%d) %s\n",sig,signal_map[sig]);
X                io_writestring(0,buffer);
X            }
X        }
X        else
X        {   /* a multi-column list? */
X            for (sig = 1; sig <= NSIG; )
X            {   /* build lines... */
X                p = buffer;
X                *p = '\0';
X                for (i = 0; i < ncol && (sig+i) <= NSIG; i++)
X                {   /* for each column */
X                    sprintf(p,"%d) %s",sig+i,signal_map[sig+i]);
X                    savep = p;
X                    while (*p)
X                        p++;
X                    while ((int)(p - savep) < maxlength)
X                        *p++ = ' ';
X                    *p = '\0';
X                }
X                sig += ncol;
X                strcpy(p,"\n");
X                io_writestring(0,buffer);
X            }
X        }
X        return 0;
X    }
X    if (tp->name[0] != '-')
X        sig = SIGTERM;
X    else
X    {   /* decode the value */
X        sig = atoi(&tp->name[1]);
X        if (sig < 1 || sig > NSIG)
X            sig = signal_number(&tp->name[1]);
X        if (sig < 1 || sig > NSIG)
X        {   /* a good value? */
X            errmsg(0,LOC("cmd_kill"),"bad signal number %d; range is 1 <-> %d",sig,NSIG);
X            return 1;
X        }
X        tp = tp->next;
X    }
X    for (; tp != (struct token *)NULL; tp = tp->next)
X    {   /* send sig to the specified pids */
X        if (tp->name[0] == '%')
X        {   /* check in pending jobs list? */
X            i = 1;
X            for (job = base_env.jobs; job != (struct bg_job *)NULL; job = job->next)
X            {   /* found what we are looking for? */
X                if (i == atoi(&tp->name[1]))
X                    break;
X                i++;
X            }
X            if (job == (struct bg_job *)NULL)
X            {   /* if we didn't find the job */
X                errmsg(0,LOC("cmd_kill"),"job %s doesn't exist",tp->name);
X                continue;
X            }
X            for (cmd = job->cmds; cmd != (struct procs *)NULL; cmd = cmd->next)
X            {   /* kill each process involved in job */
X                if (kill(cmd->pid,sig) < 0)
X                    errmsg(0,LOC("cmd_kill"),"unable to send signal %d to process %d",sig,cmd->pid);
X            }
X            continue;
X        }
X        if (kill(atoi(tp->name),sig) < 0)
X            errmsg(0,LOC("cmd_kill"),"unable to send signal %d to process %s",sig,tp->name);
X    }
X
X    return 0;
X}   /* end of cmd_kill */
X
Xvoid cmd_jobs_dump(curr,num,stat)
Xstruct phrase *curr;
Xint num;
Xchar *stat;
X{
X    char buffer[33];
X    register struct phrase *pp;
X
X    if (curr == (struct phrase *)NULL)
X        return;
X    sprintf(buffer,"[%d] + %s",num,stat);
X    while (strlen(buffer) < 32)
X        strcat(buffer," ");
X    io_writestring(0,buffer);
X    for (pp = curr; pp != (struct phrase *)NULL; pp = pp->next)
X    {   /* dump out the lines */
X        phrase_dump(pp,1,32);
X        if (pp->next != (struct phrase *)NULL)
X            io_writestring(0,"\n                                ");
X    }
X}   /* end of cmd_jobs_dump */
X
Xint cmd_jobs()
X{
X    register int cmd;
X    register struct bg_job *job;
X
X    exec_waitfor();
X    cmd = 1;
X    for (job = base_env.jobs; job != (struct bg_job *)NULL; job = job->next)
X    {   /* step through pending jobs */
X        cmd_jobs_dump(job->job,cmd,"Running");
X        cmd++;
X    }
X}   /* end of cmd_jobs */
X#endif  /* GEMDOS */
END_OF_FILE
if test 14049 -ne `wc -c <'trap.c'`; then
    echo shar: \"'trap.c'\" unpacked with wrong size!
fi
# end of 'trap.c'
fi
echo shar: End of archive 2 \(of 11\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 11 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0



More information about the Alt.sources mailing list