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