[comp.sources.amiga] v02i023: shell - cshell-like command processor V2.11, Part02/02

page@swan.ulowell.edu (Bob Page) (10/25/88)

Submitted-by: dillon@cory.berkeley.edu (Matt Dillon)
Posting-number: Volume 2, Issue 23
Archive-name: unix/shell211.2

# This is a shell archive.  Remove anything before this line
# then unpack it by saving it in a file and typing "sh file"
# (Files unpacked will be owned by you and have default permissions).
# This archive contains the following files:
#	Makefile
#	TODO
#	c.asm
#	comm1.c
#	comm2.c
#
if `test ! -s Makefile`
then
echo "writing Makefile"
cat > Makefile << '\Rogue\Monster\'

#  SHELL makefile for AZTEC C

EXE  = srcc:shell
SYMS = ram:symbols.m
SYM  = comp:include/symbols.m

AUX  = $(EXE) TODO examples.txt shell.h

SRC1 = execom.c
SRC2 = comm2.c
SRC3 = set.c
SRC4 = sub.c
SRC5 = main.c
SRC6 = globals.c
SRC7 = comm1.c
SRC8 = run.c
SRC9 = fexec1.c
SRCA = fexec2.asm
SRCB = c.asm
SRCC = sort.c
SRCD = hat.c

OBJ1 = vd0:execom.o
OBJ2 = vd0:comm2.o
OBJ3 = vd0:set.o
OBJ4 = vd0:sub.o
OBJ5 = vd0:main.o
OBJ6 = vd0:globals.o
OBJ7 = vd0:comm1.o
OBJ8 = vd0:run.o
OBJ9 = vd0:fexec1.o
OBJA = vd0:fexec2.o
OBJB = vd0:c.o
OBJC = vd0:sort.o
OBJD = vd0:hat.o

SRCS = $(SRC1) $(SRC2) $(SRC3) $(SRC4) $(SRC5) $(SRC6) $(SRC7) $(SRC8) $(SRC9) $(SRCA) $(SRCB) $(SRCC) $(SRCD)

OBJS = $(OBJ1) $(OBJ2) $(OBJ3) $(OBJ4) $(OBJ5) $(OBJ6) $(OBJ7) $(OBJ8) $(OBJ9) $(OBJA) $(OBJB) $(OBJC) $(OBJD)

CFLAGS	= +L +I$(SYMS)


$(EXE): $(SYMS) $(OBJS)
    ln +Q $(OBJS) -lsup32 -ldres -lc32 -o $(EXE)

arc:
    -delete ram:shell.arc
    arc a ram:shell $(SRCS)
    arc a ram:shell $(AUX)


$(SYMS):    $(SYM)
    copy $(SYM) $(SYMS)

$(OBJ1): $(SRC1)
    cc $(CFLAGS) $*.c -o $(OBJ1)
$(OBJ2): $(SRC2)
    cc $(CFLAGS) $*.c -o $(OBJ2)
$(OBJ3): $(SRC3)
    cc $(CFLAGS) $*.c -o $(OBJ3)
$(OBJ4): $(SRC4)
    cc $(CFLAGS) $*.c -o $(OBJ4)
$(OBJ5): $(SRC5)
    cc $(CFLAGS) $*.c -o $(OBJ5)
$(OBJ6): $(SRC6)
    cc $(CFLAGS) $*.c -o $(OBJ6)
$(OBJ7): $(SRC7)
    cc $(CFLAGS) $*.c -o $(OBJ7)
$(OBJ8): $(SRC8)
    cc $(CFLAGS) $*.c -o $(OBJ8)
$(OBJ9): $(SRC9)
    cc $(CFLAGS) $*.c -o $(OBJ9)
$(OBJA): $(SRCA)
    as $*.asm -o	 $(OBJA)
$(OBJB): $(SRCB)
    as $*.asm -o	 $(OBJB)
$(OBJC): $(SRCC)
    cc $(CFLAGS) $*.c -o $(OBJC)
$(OBJD): $(SRCD)
    cc $(CFLAGS) $*.c -o $(OBJD)


\Rogue\Monster\
else
  echo "will not over write Makefile"
fi
if [ `wc -c Makefile | awk '{printf $1}'` -ne 1665 ]
then
echo `wc -c Makefile | awk '{print "Got " $1 ", Expected " 1665}'`
fi
if `test ! -s TODO`
then
echo "writing TODO"
cat > TODO << '\Rogue\Monster\'

    -SetFileDate() routine in comm2.c

    -set xx " x"  initial space ignored in quoted section.
    -change -f to -e


    -version

    -history rel.

    -flag copy noisy.



recompile version

LATTICE free_memory().

PIPE/PARALLEL implimentation:

    a | b	-pipe
    a || b	-execute in parallel parallel

break each command into:

    command, parameters
    input redirection or pipe in
    output redirection or pipe out

    call command executor


MUST always specify redirection file names.

command executor:
    If not pipe segment (last seg is not considered a pipe)
	execute via shell
    else
	execute a RUN via shell
    send pipe terminate command for input and output pipe's in case RUN
    failed.


external(avlist, infilename, outfilename)
char **avlist;
char *infilename;   NULL means take last pipe segment
char *outfilename;  NULL means send to next pipe segment
{
    figure out aux. names (for pipes).
    if (outfilename == NULL) {
	exec a c:RUN >file <file
	if (infilename == NULL)     /* Ensure pipe has been cleared */
	    pipeclear inpipe
	if (outfilename == NULL)
	    pipeclear outpipe
    } else {
	open pert. files
	exec a .........
	close pert. files
    }
}


\Rogue\Monster\
else
  echo "will not over write TODO"
fi
if [ `wc -c TODO | awk '{printf $1}'` -ne 1200 ]
then
echo `wc -c TODO | awk '{print "Got " $1 ", Expected " 1200}'`
fi
if `test ! -s c.asm`
then
echo "writing c.asm"
cat > c.asm << '\Rogue\Monster\'
;:ts=8
; Copyright (C) 1986,1987 by Manx Software Systems, Inc.
;
;       Initial startup routine for Aztec C.
;       NOTE: code down to "start" must be placed at beginning of
;               all programs linked with Aztec Linker using small
;               code or small data.

        mc68881
        entry   .begin
        public  .begin

        FAR code
        FAR data

.begin
        move.l  a0,-(sp)
        lea     _SysRegs,a0
        movem.l d0-d7/a0-a6,(a0)
        move.l  (sp)+,a0
        bsr     _geta4                  ;get A4
        lea     __H1_end,a1
        lea     __H2_org,a2
        cmp.l   a1,a2                   ;check if BSS and DATA together
        bne     start                   ;no, don't have to clear
        move.w  #((__H2_end-__H2_org)/4)-1,d1
        bmi     start                   ;skip if no bss
        move.l  #0,d2
loop
        move.l  d2,(a1)+                ;clear out memory
        dbra    d1,loop

start
        move.l  sp,__savsp              ;save stack pointer
        move.l  4,a6                    ;get Exec's library base pointer
        move.l  a6,_SysBase             ;put where we can get it
        movem.l d0/a0,-(sp)             ;save CLI command parameters

        btst.b  #4,$129(a6)             ;check for 68881 flag in AttnFlags
        beq     x1                      ;skip if not
        lea     x2,a5
        jsr     -30(a6)                 ;do it in supervisor mode
        bra     x1
x2
        clr.l   -(sp)
        frestore (sp)+                  ;reset the ffp stuff
        rte                             ;and return
x1

        lea     dos_name,a1             ;get name of dos library
        jsr     -408(a6)                ;open the library any version
        move.l  d0,_DOSBase             ;set it up
        bne     x3                      ;skip if okay

        move.l  #$38007,d7              ;AG_OpenLib | AO_DOSLib
        jsr     -108(a6)                ;Alert
        bra     x4
x3
        jsr     __main                  ;call the startup stuff
x4
        add.w   #8,sp                   ;pop args
        rts                             ;and return

dos_name:
        dc.b    'dos.library',0

        public  _geta4

_geta4:
        far     data
        lea     __H1_org+32766,a4
        rts

        public  __main,__H0_org

        dseg

        public  _SysRegs
        public  _SysBase,__savsp,_DOSBase
        public  __H1_org,__H1_end,__H2_org,__H2_end



\Rogue\Monster\
else
  echo "will not over write c.asm"
fi
if [ `wc -c c.asm | awk '{printf $1}'` -ne 2456 ]
then
echo `wc -c c.asm | awk '{print "Got " $1 ", Expected " 2456}'`
fi
if `test ! -s comm1.c`
then
echo "writing comm1.c"
cat > comm1.c << '\Rogue\Monster\'

/*
 * COMM1.C
 *
 * (c)1986 Matthew Dillon     9 October 1986
 *
 *    SLEEP
 *    NUMBER	  -handles values as commands, actually a NULL command.
 *    CAT
 *    COMMENT
 *    DIR	  -also handles DEVINFO
 *    QUIT	  -also handles EXIT
 *    ECHO
 *    SOURCE
 *    CD
 *    MKDIR
 *    MV
 *    RM
 *    HISTORY
 *    MEM
 *    FOREACH
 *    FOREVER
 *
 *    NOTE: SET/UNSET/ALIAS/UNALIAS handled in SET.C
 *
 */

#include "shell.h"
#include <stdio.h>

extern LOCK *CreateDir(), *CurrentDir(), *ParentDir();
extern LOCK *Lock(), *DupLock();

extern long disp_entry();

struct FileLock *Clock;

do_sleep()
{
    register int i;

    if (ac == 2) {
	i = atoi(av[1]);
	while (i > 0) {
	    Delay (50*2);
	    i -= 2;
	    if (CHECKBREAK())
		break;
	 }
    }
    return (0);
}


do_number()
{
    return (0);
}

do_cat()
{
    FILE *fi;
    short i;
    char buf[256];

    if (ac == 1) {
	while (fgets(buf, 256, stdin)) {
	    Write(Cout, buf, strlen(buf));
	    if (CHECKBREAK())
		break;
	}
	clearerr(stdin);
    }
    for (i = 1; i < ac; ++i) {
	if (fi = fopen (av[i], "r")) {
	    while (fgets (buf, 256, fi)) {
		Write(Cout, buf, strlen(buf));
		if (CHECKBREAK())
		    break;
	    }
	    fclose(fi);
	} else {
	    fhprintf (Cerr, "could not open %s\n", av[i]);
	}
    }
    return (0);
}

/*
 * comment file string
 */

do_comment(str)
char *str;
{
    register char *ptr = next_word(next_word(str));

    if (SetComment(av[1], ptr) == 0) {
	perror(av[1]);
	return(1);
    }
    return(0);
}

do_dir(garbage, com)
char *garbage;
{
    register struct DPTR	  *dp;
    register struct InfoData	  *info;
    char *name;
    char br = 0;
    register short i;
    int   stat;
    short longmode = 1;
    short dcomment = 1;
    short avstart = 1;
    register long total = 0;

    if (av[1][0] == '-') {
	++avstart;
	for (i = 1; av[1][i]; ++i) {
	    switch(av[1][i]) {
	    case 's':
		longmode = 0;
		break;
	    case 'l':
		longmode = 1;
		break;
	    case 'C':
		dcomment = 0;
		break;
	    }
	}
    }
    if (ac == avstart)
	av[ac++] = "";
    for (i = avstart; !br && i < ac; ++i) {
	if ((dp = dopen (av[i], &stat)) == NULL)
	    continue;
	if (com < 0) {
	    info = (struct InfoData *)AllocMem(sizeof(struct InfoData), MEMF_PUBLIC);
	    if (Info (dp->lock, info)) {
		int bpb = info->id_BytesPerBlock;
		fhprintf (Cout, "Unit:%2ld  Errs:%3ld  Bytes: %-7ld Free: %-7ld %%full: %ld\n",
		       info->id_UnitNumber,
		       info->id_NumSoftErrors,
		       bpb * info->id_NumBlocks,
		       bpb * (info->id_NumBlocks - info->id_NumBlocksUsed),
		       info->id_NumBlocksUsed * 100 / info->id_NumBlocks
		);
	    } else {
		perror (av[i]);
	    }
	    FreeMem (info, sizeof(*info));
	} else {
	    if (stat) {
		while (dnext (dp, &name, &stat)) {
		    total += disp_entry (dp->fib, longmode, dcomment);
		    if (CHECKBREAK()) {
			br = 1;
			break;
		    }
		}
	    } else {
		total += disp_entry(dp->fib, longmode, dcomment);
	    }
	}
	dclose (dp);
    }
    fhprintf (Cout, "TOTAL: %ld\n", total);
    return (0);
}

static long
disp_entry(fib, lengthy, comment)
register struct FileInfoBlock *fib;
{
    char str[6];
    char dstr[32];
    register char *dirstr;

    str[5] = '\0';
    str[0] = (fib->fib_Protection & FIBF_READ) ? '-' : 'r';
    str[1] = (fib->fib_Protection & FIBF_WRITE) ? '-' : 'w';
    str[2] = (fib->fib_Protection & FIBF_EXECUTE) ? '-' : 'x';
    str[3] = (fib->fib_Protection & FIBF_DELETE) ? '-' : 'd';
    str[4] = (fib->fib_Protection & FIBF_ARCHIVE) ? '-' : 'a';
    dirstr = (fib->fib_DirEntryType < 0) ? "   " : "DIR";

    fhprintf (Cout, "%s %6ld %s  %-20s", str, (long)fib->fib_Size,
	dirstr, fib->fib_FileName
    );
    if (lengthy)
	fhprintf (Cout, " %s", datetos(&fib->fib_Date, dstr, "D M Y h:m"));
    if (comment)
	fhprintf (Cout, " %s", fib->fib_Comment);
    fhprintf(Cout, "\n");
    return ((long)fib->fib_Size);
}


do_quit()
{
    if (Src_stack) {
	Quit = 1;
	return(do_return());
    }
    main_exit (0);
}


do_echo(str)
char *str;
{
    register char *ptr;
    char nl = 1;

    for (ptr = str; *ptr && *ptr != ' '; ++ptr);
    if (*ptr == ' ')
	++ptr;
    if (av[1] && strcmp (av[1], "-n") == 0) {
	nl = 0;
	ptr += 2;
	if (*ptr == ' ')
	    ++ptr;
     }
     Write(Cout, ptr, strlen(ptr));
     if (nl)
	 Oputs("");
     return (0);
}


do_source(str)
char *str;
{
    register FILE *fi;
    register char *buf;

    buf = malloc(256);
    if (buf == NULL) {
	Eputs ("no memory");
	goto error;
    }
    if (Src_stack == MAXSRC) {
	Eputs ("Too many source levels");
error:
	if ((long)av[0] == -1)
	    UnLock(av[1]);
	return(-1);
    }
    if ((long)av[0] == -1) {
	long oldir = (long)CurrentDir(av[1]);
	fi = fopen("", "r");
	UnLock(CurrentDir(oldir));
    } else {
	fi = fopen (av[1], "r");
    }
    if (fi == NULL) {
	fhprintf(Cerr, "Cannot open %s\n", next_word(str));
	return(-1);
    }
    set_var(LEVEL_SET, V_PASSED, next_word(next_word(str)));
    ++H_stack;
    Src_pos[Src_stack] = 0;
    Src_base[Src_stack] = (long)fi;
    ++Src_stack;
    while (fgets(buf, 256, fi)) {
	register int len = strlen(buf);
	buf[len-1] = 0; 		    /* remove \n		*/
	Src_pos[Src_stack - 1] += len;	    /* + (1 + actual length)    */
	if (Verbose)
	    Eputs(buf);
	exec_command (buf);
	if (CHECKBREAK())
	    break;
    }
    --H_stack;
    --Src_stack;
    unset_level(LEVEL_LABEL + Src_stack);
    unset_var(LEVEL_SET, V_PASSED);
    fclose (fi);
    return (0);
}

/*
 * CD
 *
 * CD(str, -1)      -do pwd and display current cd. if str = NULL don't disp.
 * CD(str, 0)       -do CD operation.
 *
 *    standard operation: breakup path by '/'s and process independantly
 *    x:    -reset cwd base
 *    ..    -remove last cwd element
 *    N     -add N or /N to cwd
 */

do_cd(str, com)
register char *str;
{
    static char cwd[256];
    register char sc, *ptr;
    char *name;

    if (com < 0) {
	register struct FileLock *lock, *newlock;
	register FIB *fib;
	short i, len;

	fib = (FIB *)AllocMem(sizeof(FIB), 0);
	Clock = (struct FileLock *)((PROC *)FindTask(0))->pr_CurrentDir;
	if (!Clock)
	    CurrentDir(Clock = Lock(":", ACCESS_READ));
	lock = DupLock(Clock);
	cwd[i = 255] = '\0';
	while (lock) {
	    newlock = ParentDir(lock);
	    Examine(lock, fib);
	    name = fib->fib_FileName;
	    if (*name == '\0')            /* HACK TO FIX RAM: DISK BUG */
		name = "ram";
	    len = strlen(name);
	    if (newlock) {
		if (i == 255) {
		    i -= len;
		    bmov(name, cwd + i, len);
		} else {
		    i -= len + 1;
		    bmov(name, cwd + i, len);
		    cwd[i+len] = '/';
		}
	    } else {
		i -= len + 1;
		bmov(name, cwd + i, len);
		cwd[i+len] = ':';
	    }
	    UnLock(lock);
	    lock = newlock;
	}
	FreeMem(fib, sizeof(FIB));
	bmov(cwd + i, cwd, 256 - i);
	if (str)
	    Oputs(cwd);
	goto cdset;
    }
    str = next_word(str);
    if (*str == '\0')
	Oputs(cwd);
    str[strlen(str)+1] = '\0';          /* add second \0 on end */
    while (*str) {
	for (ptr = str; *ptr && *ptr != '/' && *ptr != ':'; ++ptr);
	switch (*ptr) {
	case ':':
	    sc = ptr[1];
	    ptr[1] = '\0';
	    if (attempt_cd(str))
		strcpy(cwd, str);
	    ptr[1] = sc;
	    break;
	case '\0':
	case '/':
	    *ptr = '\0';
	    if (strcmp(str, "..") == 0 || str == ptr)
		str = "/";
	    if (*str && attempt_cd(str)) {
		if (*str == '/') {
		    rmlast(cwd);
		} else {
		    if (cwd[0] == 0 || cwd[strlen(cwd)-1] != ':')
			strcat(cwd, "/");
		    strcat(cwd, str);
		}
	    }
	    break;
	}
	str = ptr + 1;
    }
cdset:
    set_var(LEVEL_SET, V_CWD, cwd);
    return (0);
}

attempt_cd(str)
char *str;
{
    register struct FileLock *oldlock, *filelock;

    if (filelock = Lock(str, ACCESS_READ)) {
	if (isdir(str)) {
	    UnLock(CurrentDir(filelock));
	    Clock = filelock;
	    return(1);
	}
	UnLock(filelock);
	ierror(str, 212);
    } else {
	ierror(str, 205);
    }
    return (0);
}


/*
 * remove last component. Start at end and work backwards until reach
 * a '/'
 */

rmlast(str)
char *str;
{
    register char *ptr = str + strlen(str) - 1;

    while (ptr != str && *ptr != '/' && *ptr != ':')
	--ptr;
    if (*ptr != ':')
	ptr[0] = '\0';
    else
	ptr[1] = '\0';
}


do_mkdir()
{
    register short i;
    register struct FileLock *lock;

    for (i = 1; i < ac; ++i) {
	if (lock = CreateDir (av[i])) {
	    UnLock (lock);
	    continue;
	}
	perror (av[i]);
    }
    return (0);
}

/*
 *  MV file1 file2
 *  MV file1 file2....fileN dir
 */

do_mv()
{
    char dest[256];
    register short i, len;
    register char *str;

    --ac;
    if (isdir(av[ac])) {
	len = strlen(av[ac]);
	for (i = 1; i < ac; ++i) {
	    str = av[i] + strlen(av[i]) - 1;
	    while (str >= av[i] && *str != '/' && *str != ':')
		--str;
	    ++str;
	    if (*str == 0) {
		ierror(av[i], 508);
		return (-1);
	    }
	    strcpy(dest, av[ac]);
	    if (dest[0] && dest[len-1] != ':' && dest[len-1] != '/')
		strcat(dest, "/");
	    strcat(dest, str);
	    if (Rename(av[i], dest) == 0)
		break;
	}
	if (i == ac)
	    return (1);
    } else {
	i = 1;
	if (ac != 2) {
	    ierror("mv:", 507);
	    return (-1);
	}
	if (Rename (av[1], av[2]))
	    return (0);
    }
    perror (av[i]);
    return (-1);
}


do_rm()
{
    register short i, recur;

    recur = (strncmp(av[1], "-r", 2)) ? 0 : 1;

    for (i = 1 + recur; i < ac; ++i) {
	if (isdir(av[i]) && recur)
	    rmdir(av[i]);
	if (!DeleteFile(av[i]))
	    perror(av[i]);
    }
    return (0);
}

rmdir(name)
char *name;
{
    register LOCK *lock, *cwd;
    register FIB *fib;
    register char *buf;

    buf = (char *)AllocMem(256, 0);
    fib = (FIB *)AllocMem(sizeof(FIB), 0);

    if (lock = Lock(name, ACCESS_READ)) {
	cwd = CurrentDir(lock);
	if (Examine(lock, fib)) {
	    buf[0] = 0;
	    while (ExNext(lock, fib)) {
		if (isdir(fib->fib_FileName))
		    rmdir(fib->fib_FileName);
		if (buf[0]) {
		    if (!DeleteFile(buf))
			perror(buf);
		}
		strcpy(buf, fib->fib_FileName);
	    }
	    if (buf[0]) {
		if (!DeleteFile(buf))
		    perror(buf);
	    }
	}
	UnLock(CurrentDir(cwd));
    } else {
	perror(name);
    }
    FreeMem(fib, sizeof(FIB));
    FreeMem(buf, 256);
}


do_history()
{
    register struct HIST *hist;
    register short i = H_tail_base;
    register short len = (av[1]) ? strlen(av[1]) : 0;

    for (hist = H_tail; hist; hist = hist->prev) {
	if (len == 0 || strncmp(av[1], hist->line, len) == 0) {
	    fhprintf (Cout, "%3ld ", i);
	    Oputs (hist->line);
	}
	++i;
	if (CHECKBREAK())
	    break;
    }
    return (0);
}


do_mem()
{
    register long cfree, ffree;
    extern long AvailMem();

    Forbid();
    cfree = AvailMem (MEMF_CHIP);
    ffree = AvailMem (MEMF_FAST);
    Permit();

    if (ffree)
	fhprintf (Cout, "FAST memory:%10ld\n", ffree);
    fhprintf (Cout, "CHIP memory:%10ld\n", cfree);
    fhprintf (Cout, "Total -----:%5ld K\n", (ffree + cfree) >> 10);
    return (0);
}

/*
 * foreach var_name  ( str str str str... str ) commands
 * spacing is important (unfortunetly)
 *
 * ac=0    1 2 3 4 5 6 7
 * foreach i ( a b c ) echo $i
 * foreach i ( *.c )   "echo -n "file ->";echo $i"
 */

do_foreach()
{
    register short i, cstart, cend, old;
    register char *cstr, *vname, *ptr, *scr, *args;

    cstart = i = (*av[2] == '(') ? 3 : 2;
    while (i < ac) {
	if (*av[i] == ')')
	    break;
	++i;
    }
    if (i == ac) {
	Eputs ("')' expected");
	return (-1);
    }
    ++H_stack;
    cend = i;
    vname = strcpy(malloc(strlen(av[1])+1), av[1]);
    cstr = compile_av (av, cend + 1, ac);
    ptr = args = compile_av (av, cstart, cend);
    while (*ptr) {
	while (*ptr == ' ' || *ptr == 9)
	    ++ptr;
	scr = ptr;
	if (*scr == '\0')
	    break;
	while (*ptr && *ptr != ' ' && *ptr != 9)
	    ++ptr;
	old = *ptr;
	*ptr = '\0';
	set_var (LEVEL_SET, vname, scr);
	if (CHECKBREAK())
	    break;
	exec_command (cstr);
	*ptr = old;
    }
    --H_stack;
    free (args);
    free (cstr);
    unset_var (LEVEL_SET, vname);
    free (vname);
    return (0);
}


do_forever(str)
register char *str;
{
    long rcode = 0;
    register char *ptr = next_word(str);

    ++H_stack;
    for (;;) {
	if (CHECKBREAK()) {
	    rcode = 20;
	    break;
	}
	if (exec_command (ptr) < 0) {
	    str = get_var(LEVEL_SET, V_LASTERR);
	    rcode = (str) ? atoi(str) : 20;
	    break;
	}
    }
    --H_stack;
    return (rcode);
}


\Rogue\Monster\
else
  echo "will not over write comm1.c"
fi
if [ `wc -c comm1.c | awk '{printf $1}'` -ne 12245 ]
then
echo `wc -c comm1.c | awk '{print "Got " $1 ", Expected " 12245}'`
fi
if `test ! -s comm2.c`
then
echo "writing comm2.c"
cat > comm2.c << '\Rogue\Monster\'

/*
 * COMM2.C
 *
 *
 * (c)1986 Matthew Dillon     Feb 1987
 *
 *    ABORTLINE
 *    RETURN
 *    STRHEAD
 *    STRTAIL
 *    IF
 *    LABEL
 *    GOTO
 *    INC
 *    INPUT
 *    VER
 *    CP
 *    SHELLSTAT
 *    SETENV
 *    UNSETENV
 *    IPC
 *    CLDRES
 *
 */

#include "shell.h"
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <local/ipc.h>

typedef struct CommandLineInterface CLI;

extern LOCK *CurrentDir(), *Lock(), *CreateDir();
extern IPCMSG *SendIPC();

do_cldres()
{
    if (DResBase)
	CloseLibrary(DResBase);
    DResBase = NULL;
}

/*
 *  do_ipc appname[.project] command
 */

do_ipc(command)
char *command;
{
    IPCMSG *msg;
    char *str = next_word(next_word(command));
    char *ptr;
    char appname[64];
    char *cmd;
    long result;

    if (!DResBase)
	DResBase = (long)OpenLibrary("dres.library", 0);
    if (!DResBase) {
	puts("Unable to open dres.library");
	return(-1);
    }
    for (ptr = av[1]; *ptr && *ptr != '.'; ++ptr);
    if (*ptr == '.') {
	if (cmd = malloc(strlen(ptr+1)+strlen(str)+2)) {
	    strcpy(cmd, ptr+1);
	    strcpy(cmd + strlen(cmd) + 1, str);
	}
    } else {
	if (cmd = malloc(strlen(str)+2)) {
	    cmd[0] = 0;
	    strcpy(cmd+1, str);
	}
    }
    if (!cmd)
	return(-1);
    strcpy(appname, av[1]);
    appname[ptr - av[1]] = 0;
    strcat(appname, ".CMD");

    msg = SendIPC(appname, cmd, strlen(cmd)+strlen(str)+2, 0);
    free(cmd);
    if (!msg)
	return(-1);
    WaitMsg(msg);
    if (msg->RFlags & IF_ERROR) {
	if (msg->RFlags & IF_NOAPP)
	    printf("Application not found");
	else
	    printf("Operation Failed");
	if (msg->RBuf)
	    printf(": %s\n", msg->RBuf);
	puts("");
	if (!msg->Error)
	    msg->Error = 20;
    } else {
	if (msg->RBuf)
	    Oputs(msg->RBuf);
    }
    result = msg->Error;
    FreeIPC(msg);
    return(result);
}

do_abortline()
{
    Exec_abortline = 1;
    return (0);
}

do_return()
{
    Exec_abortline = 1;
    if (Src_stack) {
	fseek (Src_base[Src_stack - 1], 0, 2);
	return ((ac < 2) ? 0 : atoi(av[1]));
    } else {
	main_exit ((ac < 2) ? 0 : atoi(av[1]));
    }
}

/*
 * STRHEAD
 *
 * place a string into a variable removing everything after and including
 * the 'break' character or until a space is found in the string.
 *
 * strhead varname breakchar string
 *
 */

do_strhead()
{
    register char *str = av[3];
    register char bc = *av[2];

    while (*str && *str != bc)
	++str;
    *str = '\0';
    set_var (LEVEL_SET, av[1], av[3]);
    return (0);
}

do_strtail()
{
    register char *str = av[3];
    register char bc = *av[2];

    while (*str && *str != bc)
	++str;
    if (*str)
	++str;
    set_var (LEVEL_SET, av[1], str);
    return (0);
}

/*
 * if A < B   <, >, =, <=, >=, !=, where A and B are either:
 * nothing
 * a string
 * a value (begins w/ number)
 *
 *  if -[!]f file
 *
 */

do_if(garbage, com)
char *garbage;
{
    register char *v1, *v2, *v3, result, num;
    register int n1, n2;

    switch (com) {
    case 0:
	if (If_stack && If_base[If_stack - 1]) {
	    if (If_stack == MAXIF) {
		ierror(NULL, 510);
	    } else {
		If_base[If_stack++] = 1;
	    }
	    break;
	}
	result = num = 0;
	v1 = av[1];
	switch(ac) {
	case 2: 	     /* if $var; */
	    if (v1[0] == 0 || (v1[1] == 0 && v1[0] == ' '))
		goto do_result;
	    result = 1;      /* fall through	*/
	case 1: 	     /* if		*/
	    goto do_result;
	case 3: 	     /* if -flag name	*/
	    if (*v1 == '-')
		++v1;
	    if (*v1 == '!') {
		++v1;
		result = 1 - result;
	    }
	    switch(*v1) {
	    case 'f':
		{
		    LOCK *lock;
		    mountrequest(0);
		    if (lock = Lock(av[2], SHARED_LOCK)) {
			result = 1 - result;
			UnLock(lock);
		    }
		    mountrequest(1);
		}
		break;
	    default:
		goto splug;
	    }
	    goto do_result;
	case 4:
	    goto cond;
	}
splug:
	ierror(NULL, 500);
	goto do_result;
cond:
	v1 = av[1]; v2 = av[2]; v3 = av[3];
	while (*v1 == ' ')
	    ++v1;
	while (*v2 == ' ')
	    ++v2;
	while (*v3 == ' ')
	    ++v3;
	if (*v1 >= '0' && *v1 <= '9') {
	    num = 1;
	    n1 = atoi(v1);
	    n2 = atoi(v3);
	}
	while (*v2) {
	    switch (*v2++) {
	    case '>':
		result |= (num) ? (n1 >  n2) : (strcmp(v1, v3) > 0);
		break;
	    case '<':
		result |= (num) ? (n1 <  n2) : (strcmp(v1, v3) < 0);
		break;
	    case '=':
		result |= (num) ? (n1 == n2) : (strcmp(v1, v3) ==0);
		break;
	    default:
		ierror (NULL, 503);
		break;
	    }
	}
do_result:
	if (If_stack == MAXIF)
	    ierror(NULL,510);
	else
	    If_base[If_stack++] = !result;
	break;
    case 1:
	if (If_stack > 1 && If_base[If_stack - 2])
	    break;
	if (If_stack)
	    If_base[If_stack - 1] ^= 1;
	break;
    case 2:
	if (If_stack)
	    --If_stack;
	break;
    }
    SDisable = (If_stack) ? If_base[If_stack - 1] : 0;
    return (0);
}

do_label()
{
    char aseek[32];

    if (Src_stack == 0) {
	ierror (NULL, 502);
	return (-1);
    }
    sprintf (aseek, "%ld %ld", Src_pos[Src_stack-1], If_stack);
    set_var (LEVEL_LABEL + Src_stack - 1, av[1], aseek);
    return (0);
}

do_goto()
{
    register long new;
    register long pos;
    register char *lab;

    if (Src_stack == 0) {
	ierror (NULL, 502);
    } else {
	lab = get_var (LEVEL_LABEL + Src_stack - 1, av[1]);
	if (lab == NULL) {
	    ierror (NULL, 501);
	} else {
	    pos = atoi(lab);
	    fseek (Src_base[Src_stack - 1], pos, 0);
	    Src_pos[Src_stack - 1] = pos;
	    new = atoi(next_word(lab));
	    if (new > MAXIF)
		new = MAXIF;
	    for (; If_stack < new; ++If_stack)
		If_base[If_stack] = 0;
	    If_stack = new;
	}
    }
    Exec_abortline = 1;
    return (0);      /* Don't execute rest of this line */
}


do_inc(garbage, com)
char *garbage;
{
    register char *var;
    char num[32];

    if (ac == 3)
	com = atoi(av[2]);
    var = get_var (LEVEL_SET, av[1]);
    if (var) {
	sprintf (num, "%ld", atoi(var)+com);
	set_var (LEVEL_SET, av[1], num);
    }
    return (0);
}

do_input()
{
    char in[256];

    if (Ogets(in))
	set_var (LEVEL_SET, av[1], in);
    return (0);
}

do_ver()
{
    Oputs (VERSION);
    return (0);
}


/*
 * CP file		    (to current directory)
 * CP [-r] dir		    (to current directory)
 * CP file file
 * CP file file file... destdir
 * CP [-r] dir dir dir... destdir
 */

do_cp()
{
    register short recur, i, ierr;
    register char *destname;
    register char destisdir;
    register FIB *fib;
    char copysilent = (get_var(LEVEL_SET, V_COPYSILENT) != NULL);

    if (get_var(LEVEL_SET, V_COPYDATE) != NULL)
	copysilent |= 2;

    ierr = 0;
    fib = (FIB *)AllocMem(sizeof(FIB), 0);
    recur = (strncmp(av[1], "-r", 2)) ? 0 : 1;
    destname = av[ac - 1];

    if (ac < recur + 3) {
	++ac;
	destname = "";
    }
    /*
     *	ierr = 500;
     *	goto done;
     */

    destisdir = isdir(destname);
    if (ac > recur + 3 && !destisdir) {
	ierr = 507;
	goto done;
    }

    /*
     * copy set:			reduce to:
     *	  file to file			   file to file
     *	  dir  to file (NOT ALLOWED)
     *	  file to dir			   dir to dir
     *	  dir  to dir			   dir to dir
     *
     */


    for (i = recur + 1; i < ac - 1; ++i) {
	short srcisdir = isdir(av[i]);
	if (srcisdir) {
	    struct FileLock *srcdir, *destdir;
	    if (!destisdir) {        /* disallow dir to file */
		ierr = 507;
		goto done;
	    }
	    if (!(destdir = Lock(destname, ACCESS_READ))) {
		ierr = 205;
		goto done;
	    }
	    if (!(srcdir = Lock(av[i], ACCESS_READ))) {
		ierr = 205;
		UnLock(destdir);
		goto done;
	    }
	    ierr = copydir(srcdir, destdir, recur, copysilent, 1);
	    UnLock(srcdir);
	    UnLock(destdir);
	    if (ierr)
		break;
	} else {		      /* FILE to DIR,	FILE to FILE   */
	    struct FileLock *destdir, *srcdir, *tmp;
	    char *destfilename;

	    srcdir = (struct FileLock *)((PROC *)FindTask(NULL))->pr_CurrentDir;
	    if (destisdir) {
		if ((tmp = Lock(av[i], ACCESS_READ)) == NULL || !Examine(tmp,fib)){
		    if (tmp)
			UnLock(tmp);
		    ierr = 205;
		    goto done;
		}
		UnLock(tmp);
		destdir = Lock(destname, ACCESS_READ);
		destfilename = fib->fib_FileName;
	    } else {
		destdir = srcdir;
		destfilename = destname;
		copysilent |= 1;
	    }
	    ierr = copyfile(av[i], srcdir, destfilename, destdir, copysilent, 0);
	    if (destisdir)
		UnLock(destdir);
	    if (ierr)
		break;
	}
    }
done:
    FreeMem(fib, sizeof(*fib));
    if (ierr) {
	ierror("cp", ierr);
	return(20);
    }
    return(0);
}


copydir(srcdir, destdir, recur, silent, tab)
register struct FileLock *srcdir, *destdir;
{
    LOCK *cwd;
    register FIB *srcfib;
    register LOCK *destlock, *srclock;
    DATESTAMP DS;
    int ierr;

    ierr = 0;
    srcfib = (FIB *)AllocMem(sizeof(FIB), 0);
    if (Examine(srcdir, srcfib)) {
	DS = srcfib->fib_Date;
	if (!(silent & 1))
	    printf("%*s%s (DIR)\n", tab, "", srcfib->fib_FileName);
	while (ExNext(srcdir, srcfib)) {
	    if (srcfib->fib_DirEntryType < 0) {
		ierr = copyfile(srcfib->fib_FileName,srcdir,srcfib->fib_FileName,destdir,silent,tab+4);
		if (ierr)
		    break;
	    } else {
		if (recur) {
		    cwd = CurrentDir(srcdir);
		    if (srclock = Lock(srcfib->fib_FileName, ACCESS_READ)) {
			CurrentDir(destdir);
			if (!(destlock = Lock(srcfib->fib_FileName, ACCESS_READ))) {
			    if (destlock = CreateDir(srcfib->fib_FileName)) {
				UnLock(destlock);
				if (silent & 2) {
				    setfiledate(srcfib->fib_FileName, &DS);
				    if (srcfib->fib_Comment[0])
					SetComment(srcfib->fib_FileName, srcfib->fib_Comment);
				}
				destlock = Lock(srcfib->fib_FileName, ACCESS_READ);
			    }
			}
			if (destlock) {
			    ierr = copydir(srclock, destlock, recur, silent, tab+4);
			    UnLock(destlock);
			} else {
			    ierr = IoErr();
			}
			UnLock(srclock);
		    } else {
			ierr = IoErr();
		    }
		    CurrentDir(cwd);
		    if (ierr)
			break;
		}
	    }
	}
    } else {
	ierr = IoErr();
    }
    FreeMem(srcfib, sizeof(FIB));
    return(ierr);
}


copyfile(srcname, srcdir, destname, destdir, silent, tab)
char *srcname, *destname;
struct FileLock *srcdir, *destdir;
{
    LOCK *cwd;
    DATESTAMP DS;
    int i, ierr;
    char *buf;
    char *com = NULL;
    long  buflen;
    long  fhs, fhd;

    if (!(silent&1))
	printf("%*s%s\n", tab, "", srcname);
    for (buflen = 65536; buflen; buflen >>= 1) {
	if (buf = AllocMem(buflen, MEMF_PUBLIC))
	    break;
    }
    if (buf == NULL)
	return(103);    /* ERROR_NO_FREE_STORE      */
    ierr = 0;
    cwd = (LOCK *)CurrentDir(srcdir);

    if (silent & 2) {
	register FIB *fib = (FIB *)AllocMem(sizeof(FIB), MEMF_PUBLIC);
	register LOCK *lock = Lock(srcname, ACCESS_READ);
	if (lock && fib && Examine(lock, fib)) {
	    if (fib->fib_Comment[0]) {
		com = malloc(strlen(fib->fib_Comment)+1);
		strcpy(com, fib->fib_Comment);
	    }
	    DS = fib->fib_Date;
	} else {
	    silent &= ~2;
	}
	if (lock)
	    UnLock(lock);
	if (fib)
	    FreeMem(fib, sizeof(FIB));
    }
    fhs = Open(srcname, 1005);
    if (fhs == NULL) {
	ierr = 205;
	goto fail;
    }
    CurrentDir(destdir);
    fhd = Open(destname, 1006);
    if (fhd == NULL) {
	ierr = IoErr();
	Close(fhs);
	goto fail;
    }
    while ((i = Read(fhs, buf, buflen)) > 0) {
	if (CHECKBREAK()) {
	    ierr = 509;
	    break;
	}
	if (Write(fhd, buf, i) != i) {
	    ierr = IoErr();
	    break;
	}
	if (CHECKBREAK()) {
	    ierr = 509;
	    break;
	}
    }
    if (i < 0)
	ierr = IoErr();
    Close(fhd);
    Close(fhs);
    if (!ierr && (silent & 2)) {
	setfiledate(destname, &DS);
	if (com)
	    SetComment(destname, com);
    }
fail:
    if (com)
	free(com);
    FreeMem(buf, buflen);
    CurrentDir(cwd);
    return(ierr);
}

do_shellstat()
{
    {
	register short i = 0;
	register unsigned long mask = ((TASK *)FindTask(NULL))->tc_SigAlloc;
	printf("Signals: %08lx  ", mask);
	while (mask) {
	    if (mask & 1)
		++i;
	    mask >>= 1;
	}
	printf("(%ld)\n", i);
    }
    /*
    {
	register PROC *proc = (PROC *)FindTask(NULL);
	register CLI  *cli = (CLI *)((long)proc->pr_CLI << 2);
	if (proc) {
	    long stack;
	    printf("pr_TaskNum: %ld\n", proc->pr_TaskNum);
	    printf("pr_CIS: %08lx\n", proc->pr_CIS);
	    printf("pr_COS: %08lx\n", proc->pr_COS);
	    printf("cli_standardinput : %08lx\n", cli->cli_StandardInput);
	    printf("cli_standardoutput: %08lx\n", cli->cli_StandardOutput);
	    printf("cli_currentinput  : %08lx\n", cli->cli_CurrentInput);
	    printf("cli_currentoutput : %08lx\n", cli->cli_CurrentOutput);
	    printf("cli_Module        : %08lx\n", cli->cli_Module);
	    printf("STACK:  %ld bytes, %08lx %08lx %08lx (%ld Free)\n",
		cli->cli_DefaultStack*4,
		proc->pr_ReturnAddr - cli->cli_DefaultStack*4, &stack, proc->pr_ReturnAddr,
		(long)&stack - (long)proc->pr_ReturnAddr + cli->cli_DefaultStack*4
	    );
	}
    }
    */
    return(0);
}

do_printenv()
{
    register long lock;
    register FIB *fib = (FIB *)malloc(sizeof(FIB));
    register short i;
    char buf[256];
    long fh;

    if (lock = (long)Lock("ENV:", SHARED_LOCK)) {
	if (Examine(lock, fib)) {
	    while (ExNext(lock, fib)) {
		sprintf(buf, "%-10s ", fib->fib_FileName);
		Write(Cout, buf, strlen(buf));
		sprintf(buf, "ENV:%s", fib->fib_FileName);
		if (fh = Open(buf, 1005)) {
		    while ((i = Read(fh, buf, sizeof(buf))) > 0) {
			Write(Cout, buf, i);
		    }
		    Close(fh);
		    Oputs("");
		} else {
		    Oputs("<unable to open>");
		}
	    }
	}
	UnLock(lock);
    }
    free(fib);
    return(0);
}



do_setenv(command)
char *command;
{
    long fh;
    char buf[256];
    short ierr = 0;

    if (ac <= 2)
	return(0);
    strcpy(buf, "ENV:");
    strcat(buf, av[1]);
    if (fh = Open(buf, 1006)) {
	register char *str = next_word(next_word(command));
	Write(fh, str, strlen(str));
	Close(fh);
    } else {
	ierr = IoErr();
    }
    return(ierr);
}

do_unsetenv()
{
    char buf[256];
    short i;

    for (i = 1; i < ac; ++i) {
	strcpy(buf, "ENV:");
	strcat(buf, av[i]);
	DeleteFile(buf);
    }
    return(0);
}

\Rogue\Monster\
else
  echo "will not over write comm2.c"
fi
if [ `wc -c comm2.c | awk '{printf $1}'` -ne 13801 ]
then
echo `wc -c comm2.c | awk '{print "Got " $1 ", Expected " 13801}'`
fi
echo "Finished archive 2 of 2"
# if you want to concatenate archives, remove anything after this line
exit
-- 
Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
Have five nice days.