C-Shell for the PC (PART_2 of 2: 55766 bytes)

michael regoli mr at isrnix.UUCP
Mon Dec 16 04:33:54 AEST 1985


#########################################################
#                                                       #
# This is a shell archive file.  To extract files:      #
#                                                       #
#    1)	Make a directory for the files.                 #
#    2) Write a file, such as "file.shar", containing   #
#       this archive file into the directory.           #
#    3) Type "sh file.shar".  Do not use csh.           #
#                                                       #
#########################################################
#
#
echo Extracting getcmd.c:
sed 's/^Z//' >getcmd.c <<\STUNKYFLUFF
Z#include <stdio.h>
Z#include <fcntl.h>
Z
Zchar *gets();
Zchar rest[256];
Zchar *rptr = NULL;
Zchar pipeactive = 0;
Zcurrname = 0;
Zchar *pipename[2] = {
Z	"shtmp1",
Z	"shtmp2"};
Zchar *
Zgetnextcmd(buf)
Z	char *buf;
Z{
Z	char *fgets(),*index(),*pipe,*semi;
Z	if (!rptr)
Z	{
Z		register char *c;
Z		if (0 == read(0,rest,sizeof(rest)))
Z			return NULL;
Z		c = rptr = rest;
Z		while (*c)
Z		{
Z			if (*c == '\r' || *c == '\n')
Z			{
Z				*c = '\0';
Z				break;
Z			}
Z			++c;
Z		}
Z
Z	}
Z	pipe = index(rptr,'|');
Z	semi = index(rptr,';');
Z	if (pipe == NULL && semi == NULL)
Z	{
Z		strcpy(buf,rptr);
Z		if (pipeactive)
Z		{
Z			pipeactive = 0;
Z			strcat(buf," < ");
Z			strcat(buf,pipename[currname]);
Z		}
Z		rptr=NULL;
Z	}
Z	/* one or the other, or both are not NULL, so comparison is in order */
Z	else if (pipe && (!semi || (pipe < semi)))
Z	{
Z		*pipe = '\0';	/* terminate string */
Z		strcpy(buf,rptr); /* copy to buf */
Z		rptr = pipe+1;	/* set up rest */
Z		if (pipeactive++)
Z		{
Z			pipeactive = 1;
Z			strcat(buf," < ");
Z			strcat(buf,pipename[currname]);
Z		}
Z		strcat(buf," > ");
Z		currname ^= 1;	/* flip flop pipe names */
Z		strcat(buf,pipename[currname]);
Z	}
Z	else if (semi && (!pipe || (semi < pipe)))
Z	/* we have a semicolon to deal with */
Z	{
Z		*semi = '\0';
Z		strcpy(buf,rptr);
Z		rptr = semi+1;
Z		if (pipeactive)
Z		{
Z			pipeactive = 0;
Z			strcat(buf," < ");
Z			strcat(buf,pipename[currname]);
Z		}
Z	}
Z	return buf;
Z}
STUNKYFLUFF
set `sum getcmd.c`
if test 06449 != $1
then
echo getcmd.c: Checksum error. Is: $1, should be: 06449.
fi
#
#
echo Extracting invalid.c:
sed 's/^Z//' >invalid.c <<\STUNKYFLUFF
Z
Zinvalid(argc,argv)
Z	char *argv[];
Z{
Z	register int i;
Z	static char *invmsg = "sh : bad command : ";
Z	write(2,invmsg,strlen(invmsg));
Z	for (i = 0; i < argc;i++)
Z	{
Z		write(2,argv[i],strlen(argv[i]));
Z		write(2," ",1);
Z	}
Z	return -1;
Z}
STUNKYFLUFF
set `sum invalid.c`
if test 00995 != $1
then
echo invalid.c: Checksum error. Is: $1, should be: 00995.
fi
#
#
echo Extracting ls.c:
sed 's/^Z//' >ls.c <<\STUNKYFLUFF
Z#include <stdio.h>
Z
Ztypedef struct
Z{
Z	char attribute;
Z	unsigned file_time;
Z	unsigned file_date;
Z	long file_size;
Z	char file_name[13];
Z} file_desc;
Z
Ztypedef struct
Z{
Z	char dos_reserved[21];
Z	file_desc file;
Z} fcb;
Z
Z#define maxfiles 128 
Z
Zchar printbuf[256];
Zfile_desc *getfirst(),*getnext();
Zchar *index(), *rindex();
Zint mode = 0x10;
Zint verbose=0,column=4,recurse=0;
Zint quiet = 0;
Zint drivenum = 0;
Zlong time();
Zshort year;
Z
Zdo_return(result)
Z{
Z	verbose = quiet = recurse = 0;
Z	column = 4;
Z	return result;
Z}
Z#ifndef MAIN
Zls
Z#else
Zmain
Z#endif
Z(argc,argv)
Zchar *argv[];
Z{
Z	int noargs;
Z	char *current;
Z	char namebuf[128];
Z	/* 
Z	 * initialize statics
Z	 */
Z	mode = 0x10;
Z	verbose=0;column=4;recurse=0;
Z	quiet = 0;
Z	drivenum = 0;
Z	/*
Z	 * get current time
Z	 */
Z	year = (int)((time(NULL) >> 25) & 0x7F) + 80;
Z	/*
Z	 * set up a default search name
Z	 */
Z	if (noargs = (argc == 1))
Z		argc++;
Z	while(--argc)
Z	{
Z		if (noargs)
Z			current = "*.*";
Z		else
Z			current = *(++argv);	/* get current file name */
Z		if (*current == '-')
Z		{
Z			++current;	/* point past - */
Z			while (*current)
Z			{
Z				switch (*current++)
Z				{
Z				case 'l':
Z				case 'L':
Z					verbose = 1;
Z					if (column != 1)
Z						column = 2;
Z					if (quiet)
Z					{
Z						fprintf(stderr,"ls : verbose and quiet conflict\n");
Z						do_return(-1);
Z					}
Z					break;
Z				case 'q':
Z				case 'Q':
Z					quiet = 1;
Z					if (verbose)
Z					{
Z						fprintf(stderr,"ls : quiet and verbose conflict\n");
Z						do_return(-1);
Z					}
Z					break;
Z				case 'c':
Z				case 'C':
Z					column = 1;
Z					break;
Z				case 'a':
Z				case 'A':
Z					mode = 0x2 + 0x4 + 0x10;
Z					break;
Z				case 'r':
Z				case 'R':
Z					recurse = 1;
Z					mode = 0x2 + 0x4 + 0x10;
Z					break;
Z				default:
Z					break;
Z				}
Z			}
Z			/* if we're down to one argument after looking at all the
Z			   switches, we need to set noargs to true */
Z			if (noargs = (argc == 1))
Z				argc++;
Z			continue;
Z		}
Z		/* if a drive is specified, figure out what drive it is */
Z		if (current[1] == ':')
Z		{
Z			drivenum = toupper(current[0]) - 'A' + 1;
Z		}
Z		else
Z			drivenum = 0;
Z		/* if no wild cards, look for directory and drive names */
Z		if ( NULL == index(current,'?') && NULL == index(current,'*'))
Z		{
Z			if (getfirst(current)->attribute & 0x10)
Z			{
Z				strcpy(namebuf,current);
Z				strcat(namebuf,"\\*.*");
Z				current = namebuf;
Z			} 
Z			/* look for drive names */
Z			else if (current[strlen(current)-1] == ':' && 
Z						!current[strlen(current)])
Z			{
Z				strcpy(namebuf,current);
Z				strcat(namebuf,"\\*.*");
Z				current = namebuf;
Z			}
Z		}
Z		do_dir(current);
Z	}
Z	do_return( 0);
Z}
Z
Zdo_dir(current)
Z	char *current;
Z{
Z	typedef file_desc fblock[maxfiles];	/* as many as we'll likely need */
Z	file_desc *files;
Z	file_desc *curr_file,*getnext();
Z	void *malloc();
Z	unsigned int ftime,date;
Z	int i,j,col;
Z	int files_cmp();
Z	long total = 0;
Z	char atts[4]; /* drw */
Z	/* allocate file block */
Z	if (NULL == (files = malloc(sizeof(fblock))))
Z	{
Z		fprintf(stderr,"Not enough memory to do directory\n");
Z		return -1;
Z	}
Z	/* look for match */
Z	i = 0;
Z	if (!(curr_file = getfirst(current)))
Z	{
Z		printf(stderr,"ls : no files matching %s\n",current);
Z		free(files);
Z		return;	
Z	}
Z	files[i++] = *curr_file;
Z	/* get all matching */
Z	while ((curr_file = getnext()) && i < maxfiles)
Z		files[i++] = *curr_file;	
Z	if (i > 1)
Z		qsort(files,i,sizeof(file_desc),files_cmp);
Z	if (!quiet)
Z	{
Z		write(1,"\r\n",2);
Z		write(1,current,strlen(current));
Z		write(1,"\r\n",2);
Z	}
Z	col = 1;
Z	for (j = 0; j < i; j++)
Z	{
Z		register char *c = files[j].file_name;
Z		if (*c == '.')
Z			continue;	/* filter out . and .. */
Z		while (*c)
Z		{
Z			*c = tolower(*c);
Z			c++;
Z		}
Z		if (verbose)
Z		{
Z			register char att = files[j].attribute;
Z			register int fyear;
Z			fyear = ((files[j].file_date >> 9) & 0x7F)+80; 
Z			atts[3] = 0;	/* terminate string */
Z			atts[0] = att & 0x10 ? 'd' : '-';
Z			atts[1] = att & 2 ? '-' : 'r';
Z			atts[2] = att & 1 ? '-' : 'w';
Z			if (atts[0] == 'd')
Z			{
Z				register int k;
Z				sprintf(printbuf,"%s %s\\",atts,files[j].file_name);
Z				write(1,printbuf,strlen(printbuf));
Z				k = 12 - strlen(files[j].file_name)+7;
Z				while(k--)
Z					write(1," ",1);
Z
Z			}
Z			else
Z			{
Z				total += files[j].file_size;
Z				sprintf(printbuf,"%s %-12s %-6ld ",atts,files[j].file_name,
Z						files[j].file_size);
Z				write(1,printbuf,strlen(printbuf));
Z			}
Z			ftime = files[j].file_time;
Z			date = files[j].file_date;
Z			if (year == fyear)
Z			{
Z				sprintf(printbuf,"%02d/%02d %02d:%02d ",
Z					((date >> 5) & 0x0F),	/* month */
Z					date & 0x1F,		/* day	*/
Z					(ftime >> 11) & 0x1F,		/* hours */
Z					(ftime >> 5) & 0x3F);		/* minutes */
Z				write(1,printbuf,strlen(printbuf));
Z			}
Z			else
Z			{
Z				sprintf(printbuf,"%02d/%02d       ",
Z					((date >> 5) & 0x0F),	/* month */
Z					fyear,					/* file year */
Z					(ftime >> 11) & 0x1F,		/* hours */
Z					(ftime >> 5) & 0x3F);		/* minutes */
Z				write(1,printbuf,strlen(printbuf));
Z			}
Z		}
Z		else
Z		{
Z			if (files[j].attribute & 0x10)
Z			{
Z				register int k;
Z				sprintf(printbuf,"%s\\",files[j].file_name);
Z				write(1,printbuf,strlen(printbuf));
Z				k = 16 - strlen(files[j].file_name);
Z				while(--k)
Z					write(1," ",1);
Z
Z			}
Z			else
Z			{
Z				sprintf(printbuf,"%-13s   ",files[j].file_name);
Z				write(1,printbuf,strlen(printbuf));
Z			}
Z		}
Z		if (col == column)
Z		{
Z			col = 1;
Z			write(1,"\r\n",2);
Z		}
Z		else
Z			col++;
Z	}
Z	write(1,"\r\n",2);
Z	if (verbose)
Z	{
Z		sprintf(printbuf,"%ld bytes in %d files ",total,i);
Z		write(1,printbuf,strlen(printbuf));
Z		pr_freespace();
Z	}
Z	if (recurse)
Z		for (j = 0; j < i; j++)
Z		{
Z			/* we've got a subdirectory */
Z			if (files[j].attribute & 0x10 && files[j].file_name[0] != '.')
Z			{
Z				char *path;
Z				char dirname[48];
Z				if (!strcmp(current,"*.*"))
Z					dirname[0] = '\0';
Z				else
Z					strcpy(dirname,current);
Z				if (path = rindex(dirname,'\\'))
Z					*(++path) = '\0';
Z				strcat(dirname,files[j].file_name);	/* get name */
Z				strcat(dirname,"\\*.*");
Z				do_dir(dirname);
Z			}
Z		}
Z	free(files);
Z}
Z
Zfiles_cmp(a,b)
Z	file_desc *a,*b;
Z{
Z	return strcmp(a->file_name,b->file_name);
Z}
Z
Zfcb tmp;
Z
Zfile_desc *getfirst(fname)
Z	char *fname;
Z{
Z	register int result;
Z	/* set the disk transfer address */
Z	bdos(0x1A,&tmp);
Z	result = bdos(0x4E,fname,mode);
Z	/* make the find first call */
Z	if(2 == result || 18 == result)
Z		return NULL;
Z	return &(tmp.file);
Z}
Z
Zfile_desc *getnext()
Z{
Z	register int result;
Z	/* set the disk transfer address */
Z	bdos(0x1A,&tmp);
Z	result = bdos(0x4f,0,0);
Z	/* make the find next call */
Z	if (18 == result)
Z		return NULL;
Z	return &(tmp.file);
Z}
Z
Z/*	determine available space on default drive
Z*/
Z
Zpr_freespace()
Z{
Z	/* register arguments for INT */
Z    struct   {int ax,bx,cx,dx,si,di,ds,es;}sysr;
Z    unsigned int    retstat;		    /* flags returned from INT */
Z
Z#define 	    cls_avail  sysr.bx	    /* number of available clusters */
Z#define 	    cls_total  sysr.dx	    /* total number of clusters on volume */
Z#define 	    byt_sectr  sysr.cx	    /* bytes per sector */
Z#define 	    sec_clstr  sysr.ax	    /* sectors per cluster */
Z
Z    unsigned long   byt_clstr,		    /* bytes per cluster */
Z		    vol_total,		    /* total size of volume, bytes */
Z		    fre_total;		    /* size of free space, bytes */
Z
Z    sysr.ax = 0x3600;		    /* get disk free space function code */
Z    sysr.dx = drivenum;			    /* (DL) = drive id, 0=current, 1=A, */
Z    retstat = sysint(0x21,&sysr,&sysr);		    /* invoke DOS */
Z    if( sec_clstr!=0xffff ) 
Z	{
Z		byt_clstr = byt_sectr * sec_clstr;
Z		vol_total = cls_total * byt_clstr;
Z		fre_total = cls_avail * byt_clstr;
Z		fprintf(stdout,
Z		"%lu out of %lu bytes available on %c:\n", 
Z		fre_total,vol_total, 
Z		drivenum ? drivenum + 'A' - 1 : bdos(0x19,0,0)+'A');
Z	}
Z}
STUNKYFLUFF
set `sum ls.c`
if test 06358 != $1
then
echo ls.c: Checksum error. Is: $1, should be: 06358.
fi
#
#
echo Extracting main.c:
sed 's/^Z//' >main.c <<\STUNKYFLUFF
Z#line 1 "main.s"
Z#include <stdio.h>
Z#include <ctype.h>
Z#include <signal.h>
Z#include <fcntl.h>
Z#include <setjmp.h>
Ztypedef struct		/* used to find builtin commands */
Z{
Z	char *cmdname;
Z	int (*func)();
Z} builtin;
Z
Zextern builtin commands[];
Zextern char histerr[];
Zextern int j,hiscount;
Zextern char *history[];
Zextern int histsize;
Zextern int numcmds;
Zstatic int quiet = 0;
Z
Zchar *version = "SHELL VERSION 1.2 Kent Williams";
Z
Zjmp_buf env;
Z
Zchar *pipename[] =
Z{
Z	"\\shtmp1",
Z	"\\shtmp2"
Z};
Z
Zchar cmdbuf[512];
Zint  currname = 0;
Zint result = 0;
Z
Zmain(argc,argv)
Z	char *argv[];
Z{
Z	signal(SIGINT,SIG_IGN);	/* ignore breaks */
Z
Z	quiet = !isatty(0);		/* quiet = batch shell */
Z
Z	/* initialize local environment */
Z	init_env();
Z	cli();
Z	exit(0);
Z}
Z
Z#ifndef SNODEBUG
Z#define SNODEBUG
Z#endif
Z#line 46 "main.s"
Z
Z/*
Z * statemachine cli
Z */
Zcli () 
Z
Z#line 48 "main.s"
Z{
Z#line 49 "main.s"
Z/* global variables */
Z	int i;
Z	int repeat, state, inpipe = 0;
Z	static char localbuf[256];
Z	static char histbuf[256];
Z	static char tail[256];
Z	int histindex,argindex,takeline;
Z	char *local = localbuf;
Z	char *current,*curr_save;
Z	char *ntharg(), *argptr;
Z	char *savestr();
Z
Z
Z/*
Z * end of declarations for cli
Z */
Z/* $ */ goto getline;
Z#line 62 "main.s"
Z
Zgetline:
Z{
Z#line 62 "main.s"
Z		/* kill tmp files */
Z		unlink(pipename[0]); unlink(pipename[1]);
Z
Z		hiscount = j % histsize; /* hiscount is current position in history */
Z		if(!quiet)
Z			fprintf(stderr,"%d%% ",j);
Z
Z/*
Z * The following code simply reads a line from standard input.
Z * It is so complicated because when you save the standard stream
Z * files and execute another program/command, standard input is
Z * left in an uncertain state - the FILE stdin seems to be at EOF,
Z * even when standard input is associated with the console, and
Z * cr/lf combinations show up as line terminators, whereas usually
Z * only linefeeds get placed in the input stream.
Z * WHY? beats me.  Something could be wrong with
Z *  1. AZTEC C runtime
Z *  2. PCDOS
Z *  3. Me
Z *  4. All three, or permutations of 1-3 reducto ad absurdum.
Z * All I know is this works
Z */
Z		/* clear command buffer so string read is null terminated */
Z		setmem(cmdbuf,sizeof(cmdbuf),0);
Z		for (current = cmdbuf;;current++)
Z		{
Z			int readresult;
Z			if ((readresult = read(0,current,1)) == 0 ||
Z				readresult == -1)
Z			{
Z/* $ */ goto terminal;
Z			}
Z			if (*current == '\r')
Z			{
Z				if ((readresult = read(0,current,1)) == 0 ||
Z					readresult == -1)
Z				{
Z/* $ */ goto terminal;
Z				}
Z				*current = '\0';
Z				break;
Z			}
Z			else if (*current == '\n')
Z			{
Z				*current = '\0';	/* terminate string */
Z				break;
Z			}
Z		}
Z		current = cmdbuf;	/* point current at start of buffer */
Z/*
Z * end of input weirdness
Z */
Z		/* if we're recycling history strings, free previous one */
Z		if (history[hiscount])
Z			free(history[hiscount]);
Z
Z		/* save current in history array */
Z		history[hiscount] = savestr(current);
Z		/* parse command for compound statements and pipes */
Z		local = localbuf;	/* set pointer to state of buffer */
Z		setmem(localbuf,sizeof(localbuf),0);	/* clear buffer */
Z/* $ */ goto eatwhitespace;
Z
Z#ifndef SNODEBUG
Zgoto badstate;
Z#endif
Z/* 
Z * $endstate getline
Z */
Z};
Z#line 125 "main.s"
Z
Z
Zcharstate:
Z{
Z#line 127 "main.s"
Z	switch(*current)
Z	{
Z	case '\0':
Z		*local = '\0';
Z		current++;
Z/* $ */ goto emit;
Z	case '"' :
Z		*local++ = *current++;
Z/* $ */ goto doublequotes;
Z	case '/' :
Z		*local++ = '\\';
Z		current++;
Z/* $ */ goto charstate;;
Z	case '\'':
Z		*local++ = *current++;
Z/* $ */ goto singlequotes;
Z	case '\\':
Z		*local++ = *++current;
Z		current++;
Z/* $ */ goto charstate;
Z	case ';':
Z		*local = '\0';
Z		current++;
Z/* $ */ goto compound;
Z	case '|':
Z		*local = '\0';
Z		current++;
Z/* $ */ goto pipe;
Z	case '!':
Z		current++;
Z/* $ */ goto histstate;
Z	default:
Z		*local++ = *current++;
Z/* $ */ goto charstate;
Z	}
Z
Z#ifndef SNODEBUG
Zgoto badstate;
Z#endif
Z/* 
Z * $endstate charstate
Z */
Z};
Z#line 163 "main.s"
Z
Z
Zemit:
Z{
Z#line 165 "main.s"
Z	if (inpipe)
Z	{
Z		inpipe = 0;
Z		strcat(localbuf," < ");
Z		strcat(localbuf,pipename[currname]);
Z	}
Z	command(localbuf);
Z/* $ */ goto done;
Z
Z#ifndef SNODEBUG
Zgoto badstate;
Z#endif
Z/* 
Z * $endstate emit
Z */
Z};
Z#line 174 "main.s"
Z
Z
Zcompound:
Z{
Z#line 176 "main.s"
Z	if (inpipe)
Z	{
Z		inpipe = 0;
Z		strcat(localbuf," < ");
Z		strcat(localbuf,pipename[currname]);
Z	}
Z	command(localbuf);
Z	local = localbuf;
Z	setmem(localbuf,sizeof(localbuf),0);	/* clear buffer */
Z/* $ */ goto eatwhitespace;
Z
Z#ifndef SNODEBUG
Zgoto badstate;
Z#endif
Z/* 
Z * $endstate compound
Z */
Z};
Z#line 187 "main.s"
Z
Z
Zsinglequotes:
Z{
Z#line 189 "main.s"
Z	switch (*current)
Z	{
Z	case '\0':
Z		write(2,"No closing quotes!!\r\n",21);
Z/* $ */ goto parserr;
Z	case '\'':
Z		*local++ = *current++;
Z/* $ */ goto charstate;
Z	default:
Z		*local++ = *current++;
Z/* $ */ goto singlequotes;
Z	}
Z
Z#ifndef SNODEBUG
Zgoto badstate;
Z#endif
Z/* 
Z * $endstate singlequotes
Z */
Z};
Z#line 202 "main.s"
Z
Z
Zdoublequotes:
Z{
Z#line 204 "main.s"
Z	switch(*current)
Z	{
Z	case '\0':
Z		write(2,"No closing quotes!!\r\n",21);
Z/* $ */ goto done;
Z	case '"':
Z		*local++ = *current++;
Z/* $ */ goto charstate;
Z	default:
Z		*local++ = *current++;
Z/* $ */ goto doublequotes;
Z	}
Z
Z#ifndef SNODEBUG
Zgoto badstate;
Z#endif
Z/* 
Z * $endstate doublequotes
Z */
Z};
Z#line 217 "main.s"
Z
Z
Zhiststate:
Z{
Z#line 219 "main.s"
Z	/* handle history substitutions */
Z	setmem(histbuf,sizeof(histbuf),0);	/* clear buffer */
Z
Z	/* save current pointer into command buffer */
Z	curr_save = current;
Z
Z	/* copy command head */
Z	strncpy(histbuf,cmdbuf,(int)(current-cmdbuf)-1);
Z
Z	/* takeline means take all arguments past current one */
Z	takeline = 0;
Z
Z	/* parse history expression */
Z	switch (*current)
Z	{
Z	case '!':	/* last command line */
Z		if (j)	/* special case first time through */
Z		{
Z			histindex = hiscount ? hiscount - 1 : histsize - 1;
Z		}
Z		else
Z		{
Z			/* force error condition */
Z			write(2,histerr,strlen(histerr));
Z/* $ */ goto parserr;
Z		}
Z		current++;	/* point to next */
Z		break;
Z	case '-':		/* negative (relative #) */
Z	/* a particular numbered command */
Z	case '0':
Z	case '1':
Z	case '2':
Z	case '3':
Z	case '4':
Z	case '5':
Z	case '6':
Z	case '7':
Z	case '8':
Z	case '9':
Z		/* repeat numbered command */
Z		repeat = atoi(current);
Z		if (repeat < 0)	/* handle relative addressing */
Z			repeat += j;
Z
Z		/* if command is within range */
Z		if ((j - repeat) <= histsize && repeat < j)
Z		{
Z			histindex = repeat % histsize;
Z		}
Z		else
Z		{
Z/* $ */ goto parserr;
Z		}
Z
Z		/* skip past numeric expression */
Z		while(isdigit(*current)||*current=='-')
Z			++current;
Z		break;
Z	default:
Z		write(2,"Bad history expression\r\n",24);
Z/* $ */ goto parserr;
Z	}
Z	/* look for particular argument substitutions */
Z	switch (*current)
Z	{
Z	/* we want the whole enchilada */
Z	case '\0':
Z	case '\t':
Z	case '\r':
Z	case '\n':
Z	case ' ':
Z		strcat(histbuf,history[histindex]);
Z		break;
Z	case ':':
Z		++current;	/* point past colon */
Z		switch (*current)
Z		{
Z		case '^':
Z			argindex = 1;
Z			++current;
Z			break;
Z		case '0':
Z		case '1':
Z		case '2':
Z		case '3':
Z		case '4':
Z		case '5':
Z		case '6':
Z		case '7':
Z		case '8':
Z		case '9':
Z			/* index of argument */ 
Z			argindex = atoi(current);
Z			while(isdigit(*current))
Z				++current;
Z			if (*current == '*')
Z			{
Z				takeline = 1;
Z				current++;
Z			}
Z			break;
Z		case '$':
Z			argindex = lastarg(history[histindex]);
Z			current++;
Z			break;
Z		case '*':
Z			takeline = 1;	/* take arg 1 through arg n */
Z			argindex = 1;
Z			current++;
Z			break;
Z		default:
Z/* $ */ goto parserr;
Z		}
Z		/* pick up pointer to argument in history we need */
Z		if (takeline == 0)
Z		{
Z			if (NULL == 
Z				(argptr = ntharg(history[histindex],argindex)))
Z			{
Z/* $ */ goto parserr;
Z			}
Z			strcat(histbuf,argptr);
Z		}
Z		else
Z		{
Z			while (NULL !=
Z				(argptr = ntharg(history[histindex],argindex++)))
Z			{
Z				strcat(histbuf,argptr);
Z				strcat(histbuf," ");
Z			}
Z		}
Z	}
Z	/* history substitutions */
Z	/* copy command buffer tail to tail buffer */
Z	strcpy(tail,current);
Z	/* copy histbuf back to cmdbuf */
Z	strcpy(cmdbuf,histbuf);
Z	/* point current at history substitution to continue parsing */
Z	current = --curr_save; /* -1 to backup over first ! */
Z	/* copy tail in */
Z	strcat(cmdbuf,tail);
Z	free(history[hiscount]);
Z	history[hiscount] = savestr(cmdbuf);
Z/* $ */ goto charstate;
Z
Z#ifndef SNODEBUG
Zgoto badstate;
Z#endif
Z/* 
Z * $endstate histstate
Z */
Z};
Z#line 366 "main.s"
Z
Z
Zpipe:
Z{
Z#line 368 "main.s"
Z	if (inpipe++)
Z	{
Z		inpipe = 1;
Z		strcat(localbuf," < ");
Z		strcat(localbuf,pipename[currname]);
Z	}
Z	strcat(localbuf," > ");
Z	currname ^= 1;
Z	strcat(localbuf,pipename[currname]);
Z	command(localbuf);
Z	local = localbuf;
Z	setmem(localbuf,sizeof(localbuf),0);
Z/* $ */ goto eatwhitespace;
Z
Z#ifndef SNODEBUG
Zgoto badstate;
Z#endif
Z/* 
Z * $endstate pipe
Z */
Z};
Z#line 382 "main.s"
Z
Z
Zeatwhitespace:
Z{
Z#line 384 "main.s"
Z/* strip out leading white space */
Zwhile(isspace(*current))
Z		current++;
Z	if (!*current)
Z/* $ */ goto parserr;
Z	else
Z/* $ */ goto charstate;
Z
Z#ifndef SNODEBUG
Zgoto badstate;
Z#endif
Z/* 
Z * $endstate eatwhitespace
Z */
Z};
Z#line 392 "main.s"
Z
Z
Zparserr:
Z{
Z#line 394 "main.s"
Z/* $ */ goto getline;
Z
Z#ifndef SNODEBUG
Zgoto badstate;
Z#endif
Z/* 
Z * $endstate parserr
Z */
Z};
Z#line 396 "main.s"
Z
Z
Zdone:
Z{
Z#line 398 "main.s"
Z	j++;	/* next command # */
Z/* $ */ goto getline;
Z
Z#ifndef SNODEBUG
Zgoto badstate;
Z#endif
Z/* 
Z * $endstate done
Z */
Z};
Z#line 401 "main.s"
Z
Z
Z/*
Z * BAD STATE LABEL
Z */
Zbadstate:
Z
Z	fprintf(stderr,"Fallen off end of a state!!!\n");
Z
Z	return -1;
Z
Z/*
Z * TERMINAL STATE LABEL
Z */
Zterminal:
Z
Z	return 0;
Z
Z/*
Z * end of state machine cli
Z */
Z}
Z
Zonintr()
Z{
Z	longjmp(env,-1);
Z}
Z
Zcommand(current)
Z	register char *current;
Z{
Z	extern do_prog();
Z	register int i;
Z	std_save();
Z	if (-1 == (i = findcmd(current)))
Z	{
Z		ctl_brk_setup();
Z		result = _Croot(current,do_prog);
Z		ctl_brk_restore();
Z	}
Z	else
Z	{
Z		if (-1 != setjmp(env))
Z		{
Z			signal(SIGINT,onintr);
Z			result = _Croot(current,commands[i].func);
Z		}
Z		signal(SIGINT,SIG_IGN);
Z	}
Z	std_restore();
Z}
Z
Zchar *
Zntharg(line,index)
Zregister char *line;
Z{
Z	register int i;
Z	static char buf[64];
Z	char *bptr;
Z	for (i = 0; *line;i++)
Z	{
Z		/* find start of arg[i] */
Z		while(*line && isspace(*line))
Z		{
Z			++line;
Z		}
Z		/* if this is start of requested arg, return pointer to it */
Z		if (i == index)
Z		{
Z			bptr = buf;
Z			while(*line && !isspace(*line))
Z				*bptr++ = *line++;
Z			*bptr = '\0';
Z			return buf;
Z		}
Z		/* find end of arg[i] */
Z		while(*line && !isspace(*line))
Z			++line;
Z	}
Z	return NULL;
Z}
Z
Zlastarg(line)
Zregister char *line;
Z{
Z	register int i;
Z
Z	for (i = 0; *line;i++)
Z	{
Z		/* find start of arg[i] */
Z		while(*line && isspace(*line))
Z			++line;
Z		/* find end of arg[i] */
Z		while(*line && !isspace(*line))
Z			++line;
Z	}
Z	return i-1;
Z}
STUNKYFLUFF
set `sum main.c`
if test 41066 != $1
then
echo main.c: Checksum error. Is: $1, should be: 41066.
fi
#
#
echo Extracting main.s:
sed 's/^Z//' >main.s <<\STUNKYFLUFF
Z#include <stdio.h>
Z#include <ctype.h>
Z#include <signal.h>
Z#include <fcntl.h>
Z#include <setjmp.h>
Ztypedef struct		/* used to find builtin commands */
Z{
Z	char *cmdname;
Z	int (*func)();
Z} builtin;
Z
Zextern builtin commands[];
Zextern char histerr[];
Zextern int j,hiscount;
Zextern char *history[];
Zextern int histsize;
Zextern int numcmds;
Zstatic int quiet = 0;
Z
Zchar *version = "SHELL VERSION 1.1 Kent Williams";
Z
Zjmp_buf env;
Z
Zchar *pipename[] =
Z{
Z	"\\shtmp1",
Z	"\\shtmp2"
Z};
Z
Zchar cmdbuf[512];
Zint  currname = 0;
Zint result = 0;
Z
Zmain(argc,argv)
Z	char *argv[];
Z{
Z	signal(SIGINT,SIG_IGN);	/* ignore breaks */
Z
Z	quiet = !isatty(0);		/* quiet = batch shell */
Z
Z	/* initialize local environment */
Z	init_env();
Z	cli();
Z	exit(0);
Z}
Z$nodebug		/* turn off state machine debugging */
Z$machine cli getline () 
Z$endargs
Z/* global variables */
Z	int i;
Z	int repeat, state, inpipe = 0;
Z	static char localbuf[256];
Z	static char histbuf[256];
Z	static char tail[256];
Z	int histindex,argindex,takeline;
Z	char *local = localbuf;
Z	char *current,*curr_save;
Z	char *ntharg(), *argptr;
Z	char *savestr();
Z
Z$state getline
Z		/* kill tmp files */
Z		unlink(pipename[0]); unlink(pipename[1]);
Z
Z		hiscount = j % histsize; /* hiscount is current position in history */
Z		if(!quiet)
Z			fprintf(stderr,"%d%% ",j);
Z
Z/*
Z * The following code simply reads a line from standard input.
Z * It is so complicated because when you save the standard stream
Z * files and execute another program/command, standard input is
Z * left in an uncertain state - the FILE stdin seems to be at EOF,
Z * even when standard input is associated with the console, and
Z * cr/lf combinations show up as line terminators, whereas usually
Z * only linefeeds get placed in the input stream.
Z * WHY? beats me.  Something could be wrong with
Z *  1. AZTEC C runtime
Z *  2. PCDOS
Z *  3. Me
Z *  4. All three, or permutations of 1-3 reducto ad absurdum.
Z * All I know is this works
Z */
Z		/* clear command buffer so string read is null terminated */
Z		setmem(cmdbuf,sizeof(cmdbuf),0);
Z		for (current = cmdbuf;;current++)
Z		{
Z			int readresult;
Z			if ((readresult = read(0,current,1)) == 0 ||
Z				readresult == -1)
Z			{
Z				$nextstate terminal
Z			}
Z			if (*current == '\r')
Z			{
Z				if ((readresult = read(0,current,1)) == 0 ||
Z					readresult == -1)
Z				{
Z					$nextstate terminal
Z				}
Z				*current = '\0';
Z				break;
Z			}
Z			else if (*current == '\n')
Z			{
Z				*current = '\0';	/* terminate string */
Z				break;
Z			}
Z		}
Z		current = cmdbuf;	/* point current at start of buffer */
Z/*
Z * end of input weirdness
Z */
Z		/* if we're recycling history strings, free previous one */
Z		if (history[hiscount])
Z			free(history[hiscount]);
Z
Z		/* save current in history array */
Z		history[hiscount] = savestr(current);
Z		/* parse command for compound statements and pipes */
Z		local = localbuf;	/* set pointer to state of buffer */
Z		setmem(localbuf,sizeof(localbuf),0);	/* clear buffer */
Z		$nextstate eatwhitespace 
Z$endstate getline
Z
Z$state charstate
Z	switch(*current)
Z	{
Z	case '\0':
Z		*local = '\0';
Z		current++;
Z		$nextstate emit
Z	case '"' :
Z		*local++ = *current++;
Z		$nextstate doublequotes
Z	case '/' :
Z		*local++ = '\\';
Z		current++;
Z		$nextstate charstate;
Z	case '\'':
Z		*local++ = *current++;
Z		$nextstate singlequotes
Z	case '\\':
Z		*local++ = *++current;
Z		current++;
Z		$nextstate charstate
Z	case ';':
Z		*local = '\0';
Z		current++;
Z		$nextstate compound
Z	case '|':
Z		*local = '\0';
Z		current++;
Z		$nextstate pipe
Z	case '!':
Z		current++;
Z		$nextstate histstate
Z	default:
Z		*local++ = *current++;
Z		$nextstate charstate
Z	}
Z$endstate charstate
Z
Z$state emit
Z	if (inpipe)
Z	{
Z		inpipe = 0;
Z		strcat(localbuf," < ");
Z		strcat(localbuf,pipename[currname]);
Z	}
Z	command(localbuf);
Z	$nextstate done
Z$endstate emit
Z
Z$state compound
Z	if (inpipe)
Z	{
Z		inpipe = 0;
Z		strcat(localbuf," < ");
Z		strcat(localbuf,pipename[currname]);
Z	}
Z	command(localbuf);
Z	local = localbuf;
Z	setmem(localbuf,sizeof(localbuf),0);	/* clear buffer */
Z	$nextstate eatwhitespace
Z$endstate compound
Z
Z$state singlequotes
Z	switch (*current)
Z	{
Z	case '\0':
Z		write(2,"No closing quotes!!\r\n",21);
Z		$nextstate parserr
Z	case '\'':
Z		*local++ = *current++;
Z		$nextstate charstate
Z	default:
Z		*local++ = *current++;
Z		$nextstate singlequotes
Z	}
Z$endstate singlequotes
Z
Z$state doublequotes
Z	switch(*current)
Z	{
Z	case '\0':
Z		write(2,"No closing quotes!!\r\n",21);
Z		$nextstate done
Z	case '"':
Z		*local++ = *current++;
Z		$nextstate charstate
Z	default:
Z		*local++ = *current++;
Z		$nextstate doublequotes
Z	}
Z$endstate doublequotes
Z
Z$state histstate
Z	/* handle history substitutions */
Z	setmem(histbuf,sizeof(histbuf),0);	/* clear buffer */
Z
Z	/* save current pointer into command buffer */
Z	curr_save = current;
Z
Z	/* copy command head */
Z	strncpy(histbuf,cmdbuf,(int)(current-cmdbuf)-1);
Z
Z	/* takeline means take all arguments past current one */
Z	takeline = 0;
Z
Z	/* parse history expression */
Z	switch (*current)
Z	{
Z	case '!':	/* last command line */
Z		if (j)	/* special case first time through */
Z		{
Z			histindex = hiscount ? hiscount - 1 : histsize - 1;
Z		}
Z		else
Z		{
Z			/* force error condition */
Z			write(2,histerr,strlen(histerr));
Z			$nextstate parserr
Z		}
Z		current++;	/* point to next */
Z		break;
Z	case '-':		/* negative (relative #) */
Z	/* a particular numbered command */
Z	case '0':
Z	case '1':
Z	case '2':
Z	case '3':
Z	case '4':
Z	case '5':
Z	case '6':
Z	case '7':
Z	case '8':
Z	case '9':
Z		/* repeat numbered command */
Z		repeat = atoi(current);
Z		if (repeat < 0)	/* handle relative addressing */
Z			repeat += j;
Z
Z		/* if command is within range */
Z		if ((j - repeat) <= histsize && repeat < j)
Z		{
Z			histindex = repeat % histsize;
Z		}
Z		else
Z		{
Z			$nextstate parserr
Z		}
Z
Z		/* skip past numeric expression */
Z		while(isdigit(*current)||*current=='-')
Z			++current;
Z		break;
Z	default:
Z		write(2,"Bad history expression\r\n",24);
Z		$nextstate parserr
Z	}
Z	/* look for particular argument substitutions */
Z	switch (*current)
Z	{
Z	/* we want the whole enchilada */
Z	case '\0':
Z	case '\t':
Z	case '\r':
Z	case '\n':
Z	case ' ':
Z		strcat(histbuf,history[histindex]);
Z		break;
Z	case ':':
Z		++current;	/* point past colon */
Z		switch (*current)
Z		{
Z		case '^':
Z			argindex = 1;
Z			++current;
Z			break;
Z		case '0':
Z		case '1':
Z		case '2':
Z		case '3':
Z		case '4':
Z		case '5':
Z		case '6':
Z		case '7':
Z		case '8':
Z		case '9':
Z			/* index of argument */ 
Z			argindex = atoi(current);
Z			while(isdigit(*current))
Z				++current;
Z			if (*current == '*')
Z			{
Z				takeline = 1;
Z				current++;
Z			}
Z			break;
Z		case '$':
Z			argindex = lastarg(history[histindex]);
Z			current++;
Z			break;
Z		case '*':
Z			takeline = 1;	/* take arg 1 through arg n */
Z			argindex = 1;
Z			current++;
Z			break;
Z		default:
Z			$nextstate parserr
Z		}
Z		/* pick up pointer to argument in history we need */
Z		if (takeline == 0)
Z		{
Z			if (NULL == 
Z				(argptr = ntharg(history[histindex],argindex)))
Z			{
Z				$nextstate parserr
Z			}
Z			strcat(histbuf,argptr);
Z		}
Z		else
Z		{
Z			while (NULL !=
Z				(argptr = ntharg(history[histindex],argindex++)))
Z			{
Z				strcat(histbuf,argptr);
Z				strcat(histbuf," ");
Z			}
Z		}
Z	}
Z	/* history substitutions */
Z	/* copy command buffer tail to tail buffer */
Z	strcpy(tail,current);
Z	/* copy histbuf back to cmdbuf */
Z	strcpy(cmdbuf,histbuf);
Z	/* point current at history substitution to continue parsing */
Z	current = --curr_save; /* -1 to backup over first ! */
Z	/* copy tail in */
Z	strcat(cmdbuf,tail);
Z	free(history[hiscount]);
Z	history[hiscount] = savestr(cmdbuf);
Z	$nextstate charstate
Z$endstate histstate
Z
Z$state pipe
Z	if (inpipe++)
Z	{
Z		inpipe = 1;
Z		strcat(localbuf," < ");
Z		strcat(localbuf,pipename[currname]);
Z	}
Z	strcat(localbuf," > ");
Z	currname ^= 1;
Z	strcat(localbuf,pipename[currname]);
Z	command(localbuf);
Z	local = localbuf;
Z	setmem(localbuf,sizeof(localbuf),0);
Z	$nextstate eatwhitespace
Z$endstate pipe
Z
Z$state eatwhitespace
Z/* strip out leading white space */
Zwhile(isspace(*current))
Z		current++;
Z	if (!*current)
Z		$nextstate parserr
Z	else
Z		$nextstate charstate
Z$endstate eatwhitespace
Z
Z$state parserr
Z	$nextstate getline
Z$endstate parserr
Z
Z$state done
Z	j++;	/* next command # */
Z	$nextstate getline
Z$endstate done
Z
Z$endmachine cli
Z
Zonintr()
Z{
Z	longjmp(env,-1);
Z}
Z
Zcommand(current)
Z	register char *current;
Z{
Z	extern do_prog();
Z	register int i;
Z	std_save();
Z	if (-1 == (i = findcmd(current)))
Z	{
Z		ctl_brk_setup();
Z		result = _Croot(current,do_prog);
Z		ctl_brk_restore();
Z	}
Z	else
Z	{
Z		if (-1 != setjmp(env))
Z		{
Z			signal(SIGINT,onintr);
Z			result = _Croot(current,commands[i].func);
Z		}
Z		signal(SIGINT,SIG_IGN);
Z	}
Z	std_restore();
Z}
Z
Zchar *
Zntharg(line,index)
Zregister char *line;
Z{
Z	register int i;
Z	static char buf[64];
Z	char *bptr;
Z	for (i = 0; *line;i++)
Z	{
Z		/* find start of arg[i] */
Z		while(*line && isspace(*line))
Z		{
Z			++line;
Z		}
Z		/* if this is start of requested arg, return pointer to it */
Z		if (i == index)
Z		{
Z			bptr = buf;
Z			while(*line && !isspace(*line))
Z				*bptr++ = *line++;
Z			*bptr = '\0';
Z			return buf;
Z		}
Z		/* find end of arg[i] */
Z		while(*line && !isspace(*line))
Z			++line;
Z	}
Z	return NULL;
Z}
Z
Zlastarg(line)
Zregister char *line;
Z{
Z	register int i;
Z
Z	for (i = 0; *line;i++)
Z	{
Z		/* find start of arg[i] */
Z		while(*line && isspace(*line))
Z			++line;
Z		/* find end of arg[i] */
Z		while(*line && !isspace(*line))
Z			++line;
Z	}
Z	return i-1;
Z}
STUNKYFLUFF
set `sum main.s`
if test 47403 != $1
then
echo main.s: Checksum error. Is: $1, should be: 47403.
fi
#
#
echo Extracting makefile:
sed 's/^Z//' >makefile <<\STUNKYFLUFF
Z# home for all commands
ZBINDIR=\\bin\\
Z# small model library path
ZCLIB=-l/clibs/c
Z
Z# source files for shell
Zshsrc=main.c cd.c cp.c doprog.c fexecvp.c more.c cmds.c chmod.c y.c fexec.asm \
Zinvalid.c ls.c pushd.c fgrep.c md.c mv.c pwd.c rm.c crlf.c drive.c dump2.c \
Zrmdir.c savestr.c stdsave.c touch.c _croot.c env.c fexecv.c cat.c echo.c \
Zcmdlist.c ctlbrk.asm mvcp.c
Z
Z# object files for shell
Zshobj=main.o cd.o cp.o doprog.o fexecvp.o more.o cmds.o chmod.o y.o fexec.o \
Zinvalid.o ls.o pushd.o fgrep.o md.o mv.o pwd.o rm.o crlf.o drive.o dump2.o \
Zrmdir.o savestr.o stdsave.o touch.o _croot.o env.o fexecv.o cat.o echo.o \
Zcmdlist.o ctlbrk.o mvcp.o
Z
Zmain.c : main.s
Z	statecom main
Z
Z#
Z# make shell - check currency of all percursors, link and then move to
Z# bin directory
Z#
Zshell.exe : $(shobj) 
Z	ln -t -o $@ -f shell.lnk
Z	\\atron\\aztoat <shell.sym >shell.map
Z	chmod +w $(BINDIR)$@
Z	mv $@ $(BINDIR)$@
Z	chmod -w $(BINDIR)$@
Z
Z#
Z# make entries to produce stand-alone versions of shell builtins
Z#
Zchmod.com : 
Z	cc -dMAIN $*
Z	ln -o $@ $*.o -l/clibs/c
Z	rm $*.o
Z	chmod +w $(BINDIR)chmod.com
Z	mv chmod.com $(BINDIR)chmod.com
Z	chmod -w $(BINDIR)chmod.com
Z
Zmore.com : 
Z	cc -dMAIN $*
Z	ln -o $@ $*.o -l/clibs/s -l/clibs/c
Z	rm $*.o
Z	chmod +w $(BINDIR)$@
Z	mv $@ $(BINDIR)$@
Z	chmod -w $(BINDIR)$@
Z
Zmv.com : croot.o savestr.o mvcp.o
Z	cc -dMAIN $*
Z	ln -o $@ $*.o savestr.o croot.o mvcp.o  -l/clibs/c
Z	rm $*.o
Z	chmod +w $(BINDIR)$@
Z	mv $@ $(BINDIR)$@
Z	chmod -w $(BINDIR)$@
Z
Zcp.com : croot.o savestr.o mvcp.o
Z	cc -dMAIN $*
Z	ln -o $@ $*.o savestr.o croot.o  mvcp.o -l/clibs/c
Z	rm $*.o
Z	chmod +w $(BINDIR)$@
Z	mv $@ $(BINDIR)$@
Z	chmod -w $(BINDIR)$@
Z
Zls.com : 
Z	cc -dMAIN $*
Z	ln -o $@ $*.o -l/clibs/c
Z	rm $*.o
Z	chmod +w $(BINDIR)$@
Z	mv $@ $(BINDIR)$@
Z	chmod -w $(BINDIR)$@
Zeditall :
Z	z $(shsrc)
Zclean :
Z	rm *.o *.bak *.sym
STUNKYFLUFF
set `sum makefile`
if test 36319 != $1
then
echo makefile: Checksum error. Is: $1, should be: 36319.
fi
#
#
echo Extracting md.c:
sed 's/^Z//' >md.c <<\STUNKYFLUFF
Zmd(argc,argv)
Z	char *argv[];
Z{
Z	if (-1 == mkdir(*(++argv)))
Z	{
Z		perror("mkdir");
Z		return -1;
Z	}
Z	return 0;
Z}
STUNKYFLUFF
set `sum md.c`
if test 21756 != $1
then
echo md.c: Checksum error. Is: $1, should be: 21756.
fi
#
#
echo Extracting more.c:
sed 's/^Z//' >more.c <<\STUNKYFLUFF
Z#include <stdio.h>
Z#include <sgtty.h>
Z#include <debug.h>
Z#include <ctype.h>
Z#include <setjmp.h>
Z#include <signal.h>
Zvoid (*signal())();
Zvoid (*moresig)();
ZFILE *fdopen();
Z
Zlong int size, position;
Zchar filename[30];
Zchar isaconsole = '\0';
Zchar isapipe = '\0';
Zint tabsize = 8;
Z#define STDIN 0
Z#define STDOUT 1
Z#define STDERR 2
Z#define ESC '\033'
Z#define IBMPC			/* display code dependent on PC hardware/bios */
Z#ifdef IBMPC
Zextern void scr_putc();
Z#endif
Zvoid std_out(c)
Z{
Z	write(1,&c,1);
Z}
Zvoid (*output)();
Z#ifdef MAIN
Zcrlf()
Z{
Z	write(2,"\r\n",2);
Z}
Z#endif
Zjmp_buf moreenv;
Zmoreintr()
Z{
Z	signal(SIGINT,SIG_IGN);	/* ignore signals until we finish putting stuff
Z	                           back in order */
Z	longjmp(moreenv,-1);
Z}
Z#ifdef MAIN
Zmain
Z#else
Zmore
Z#endif
Z(argc,argv)
Z	int argc;
Z	char *argv[];
Z{
Z	FILE *fp, *fopen();
Z	long ftell();
Z	long int i;
Z	long int fsize();
Z
Z	if (-1 == setjmp(moreenv))
Z	{
Z		write(2,"Interrupted\r\n",13);
Z		fclose(fp);
Z		signal(SIGINT,moresig);
Z		return -1;
Z	}
Z
Z	moresig = signal(SIGINT,moreintr);
Z	isaconsole = isatty(STDOUT);
Z	isapipe = !isatty(STDIN);
Z#ifdef IBMPC
Z	if (isaconsole)
Z	{
Z		output = scr_putc;
Z		scr_echo(0);
Z	}
Z	else
Z#endif
Z		output = std_out;
Z	if ( (*(++argv))[0] == '-' && isdigit((*argv)[1]) )
Z	{
Z		tabsize = atoi( (*argv+1) );
Z		--argc;
Z	} else
Z	{
Z		--argv;
Z	}
Z	if (argc == 1)
Z	{
Z		if (NULL == (fp = fdopen(0,"r")))
Z		{
Z			return -1;
Z		}
Z		display(fp);
Z		crlf();
Z		return 0;
Z	}
Z	while(--argc) 
Z	{
Z		if (NULL == (fp = fopen(*(++argv),"r")) )
Z		{
Z			fprintf(stderr,"more - can't open %s\n",*argv);
Z			continue;
Z		}
Z		strncpy(filename,*argv,30);
Z		if (filename[29])
Z			filename[29] = '\0';
Z		if (!isapipe)
Z			size = fsize(fp);
Z		position = 0;
Z		if (-2 == display(fp))
Z			argc = 0;		/* force completion of command */
Z		fclose(fp);
Z	}
Zbugout:
Z#ifdef IBMPC
Z	if (isaconsole)
Z		scr_echo(0);
Z#endif
Z	crlf();
Z	tabsize = 8;
Z	isaconsole = isapipe = '\0';
Z	signal(SIGINT,moresig);
Z	return 0;
Z}
Z
Zlong fsize(fp) 
Z	FILE *fp;
Z{
Z	long ftell();
Z	long position, last;
Z	position = ftell(fp);
Z	if (-1 == fseek(fp,0L,2))
Z	{
Z		fprintf(stderr,"more - error on fseek\n");
Z	}
Z	last = (ftell(fp));
Z	fseek(fp,position,0);
Z	return last;
Z}
Z#define LBUFSIZE 160
Zchar linebuffer[LBUFSIZE];
Zint lines;
Z
Zdisplay(fp)
Z	FILE *fp;
Z{
Z	FILE *fgets();
Z	long ftell();
Z	char c;
Z	lines = 1;
Z	while ( NULL != fgets(linebuffer,LBUFSIZE,fp))
Z	{
Z		if (isaconsole)
Z		{
Z			if (lines == 1)		/* top of display */
Z			{
Z#ifdef IBMPC
Z				scr_clear();
Z#else
Z/* ansi terminal screen clear */
Z				printf("%c[2J",ESC);	/* clear display */
Z#endif
Z			}
Z		}
Z		lines += localputs(linebuffer);
Z		if (isaconsole)
Z		{
Z			if (lines >=  24)		/* bottome of display */
Z			{
Z				char tst;
Z				position = ftell(fp);
Z#ifdef IBMPC
Z				scr_curs(24,0);
Z#else
Z/* ansi terminal positioning */
Z				printf("%c[25;1H%c[7m",ESC,ESC);
Z#endif
Z				if (!isapipe)
Z#ifdef IBMPC
Z					scr_printf(
Z#else
Z					fprintf(stderr,
Z#endif
Z				"%s - %ld bytes - %d%% displayed - <ESC> = skip to next file",
Z					filename,size,percent(position,size) );
Z				else
Z#ifdef IBMPC
Z					scr_printf(
Z#else
Z					fprintf(stderr,
Z#endif
Z									"-more-");
Z				switch (bdos(7,0,0))	/* get a character no echo */
Z				{
Z				case ESC :
Z					return 0;
Z				case 3 :
Z					return -2;
Z				default:
Z					break;
Z				}
Z
Z				lines = 1;
Z			}
Z		}
Z	}
Z	if (isaconsole)
Z	{
Z		if (lines != 1)		/* bottome of display */
Z		{
Z#ifdef IBMPC
Z			scr_curs(24,0);
Z#else
Z/* ansi terminal positioning */
Z				printf("%c[25;1H%c[7m",ESC,ESC);
Z#endif
Z			if (!isapipe)
Z			{
Z				position = ftell(fp);
Z#ifdef IBMPC
Z				scr_printf(
Z#else
Z				fprintf(stderr,
Z#endif
Z						"%s - %ld characters - %d%% displayed",
Z					filename,size,percent(position,size) );
Z			}
Z			else
Z#ifdef IBMPC
Z				scr_printf(
Z#else
Z				fprintf(stderr,
Z#endif
Z								"-done-");
Z			bdos(7,0,0); /* console input no echo */
Z			lines = 1;
Z		}
Z	}
Z}
Z
Zpercent(x,y)
Z	long int x,y;
Z{	/* returns integer percentage of x into y */
Z#ifdef FLOAT
Z	float xf,yf;
Z	xf = x; yf = y;
Z	x = ((xf/yf)*100);
Z#endif
Z	x *= 100;
Z	if (y)
Z		x /= y;
Z	else
Z		x = 100;
Z	return (x);
Z}
Z
Zlocalputs(lb)
Z	register char *lb;
Z{
Z	int lines, pos, tabstop;
Z	lines = 1;
Z	pos = 0;
Z	while (*lb)
Z	{
Z		switch (*lb)
Z		{
Z		case '\t':
Z			tabstop = pos + (tabsize - (pos % tabsize));	
Z			for (;pos <= tabstop; pos++)
Z				(*output)(' ');
Z			break;
Z		case '\n':
Z			(*output)('\r');
Z		default:
Z			(*output)(*lb);
Z			pos++;
Z		}
Z		if (pos == 79)
Z		{
Z			pos = 1;
Z			(*output)('\r');
Z			(*output)('\n');
Z			++lines;
Z		} else if (pos > 79)
Z		{
Z			pos -= 80;
Z			++lines;
Z		}
Z		++lb;
Z	}
Z	return lines;
Z}
Z
Z#ifdef IBMPC
Zscr_printf(fmt,args)
Zchar *fmt; unsigned args;
Z{
Z	format(scr_putc,fmt,&args);
Z}
Z#endif
STUNKYFLUFF
set `sum more.c`
if test 34929 != $1
then
echo more.c: Checksum error. Is: $1, should be: 34929.
fi
#
#
echo Extracting mv.c:
sed 's/^Z//' >mv.c <<\STUNKYFLUFF
Z/* :ts=2 */
Z#include <stdio.h>
Zchar *savestr();
Z#ifndef MAIN
Zextern char *fname_part(),*savestr();
Zextern char *me;
Z#else
Zchar *me;
Z#endif
Z/* mv.c - implements a version of UNIX mv */
Z#ifdef MAIN
Zmain
Z#else
Zmv
Z#endif
Z(argc,argv)
Z	int argc;
Z	register char *argv[];
Z{
Z	static char *usage = "mv : usage mv file1 [file2 . . fileN] target\r\n";
Z	static char target_name[128];
Z	char target[128],*fname_part();
Z	register int i;
Z	int len;
Z#ifndef MAIN
Z	me = argv[0];	/* referenced in routines common with cp.c */
Z#endif
Z	if (argc < 3)
Z	{
Z		write(2,usage,strlen(usage));
Z		return(-1);
Z	}
Z	strcpy(target, argv[argc-1]);
Z	/* kill trailing backslashes */
Z	if (target[i = strlen(target) - 1] == '\\')
Z		target[i] = '\0';
Z	if (argc == 3)
Z	{
Z		/* if the target doesn't exist and it's not a directory then rename */
Z		if (!filep(target))
Z		{
Z			if (!dirp(target))
Z			{
Z				fprintf(stderr,"rename : moving %s to %s\n"
Z				,argv[1],argv[2]);
Z				rename(argv[1],argv[2]);
Z			}
Z			else
Z			{
Z			/* if the target is a directory copy to same name that directory */
Z				strcpy(target_name,target);
Z				if (target_name[(len = strlen(target_name))-1] != '\\')
Z				{
Z					target_name[len = strlen(target_name)] = '\\';
Z					target_name[len+1] = '\0';
Z				}
Z				strcat(target_name,fname_part(argv[1]));
Z#ifdef DEBUG
Z				fprintf(stderr,"interdirectory copy same name : moving %s to %s\n"
Z#else
Z				fprintf(stderr,"moving %s to %s\n"
Z#endif
Z				,argv[1],target_name);
Z				if (-1 != maybecopy(target_name,argv[1]))
Z					unlink(argv[1]);
Z			}
Z		}
Z		else
Z		{
Z		/* target exists , and isn't a directory */
Z			char *tpath,*spath;
Z			char tpathsaved = 0,spathsaved = 0;
Z			char *path_part();
Z			/* find path parts of source and target */
Z			if (tpath = path_part(target))
Z			{
Z				tpath = savestr(tpath);
Z				tpathsaved++;
Z			}
Z			else
Z				tpath = ".";	/* current directory */
Z			if (spath = path_part(argv[1]))
Z			{
Z				spath = savestr(spath);
Z				spathsaved++;
Z			}
Z			else
Z				spath = ".";	/* current directory */
Z			if (0 == strcmp(tpath,spath))
Z			{
Z			/* if source and target are in the same directory */
Z#ifdef DEBUG
Z				fprintf(stderr,"intradirectory delete then rename : moving %s to %s\n"
Z#else
Z				fprintf(stderr,"moving %s to %s\n"
Z#endif
Z				,argv[1],target);
Z				unlink(target);
Z				rename(argv[1],target);
Z			}
Z			else
Z			{
Z#ifdef DEBUG
Z				fprintf(stderr,"interdirectory file to file: moving %s to %s\n"
Z#else
Z				fprintf(stderr,"moving %s to %s\n"
Z#endif
Z				,argv[1],target);
Z				if (-1 != maybecopy(target,argv[1]))
Z					unlink(argv[1]);
Z			}
Z			if (tpathsaved)
Z				free(tpath);
Z			if (spathsaved)
Z				free(spath);
Z		}
Z		return(0);
Z	}
Z	/* handle special case of a drive designation */
Z	if (target[(i = strlen(target))-1] != ':')
Z		if (!dirp(target))
Z		{
Z			fprintf(stderr,"mv : %s isn't a directory\n",target);
Z			return(-1);
Z		}
Z	for (i = 1; i < argc-1; i++)
Z	{
Z		strcpy(target_name,target);
Z		if (target_name[(len = strlen(target_name))-1] != '\\')
Z		{
Z			target_name[len = strlen(target_name)] = '\\';
Z			target_name[len+1] = '\0';
Z		}
Z		strcat(target_name,fname_part(argv[i]));
Z		if (!filep(argv[i]))
Z		{
Z			fprintf(stderr,"mv : %s isn't a file\n",argv[i]);
Z			continue;
Z		}
Z		fprintf(stderr,"moving %s to %s\n",argv[i],target_name);
Z		if (-1 != maybecopy(target_name,argv[i]))
Z			unlink(argv[i]);
Z	}
Z	return 0;
Z}
Z
Zmaybecopy(target,source)
Z	char *target,*source;
Z{
Z	char *drive_part();
Z	static char targetdrive[3], sourcedrive[3];
Z	strcpy(targetdrive,drive_part(target));
Z	strcpy(sourcedrive,drive_part(source));
Z	if (0 == strcmp(targetdrive,sourcedrive))
Z	{
Z		unlink(target);
Z		rename(source,target);
Z		return 0;
Z	}
Z	return (filecopy(target,source));
Z}
STUNKYFLUFF
set `sum mv.c`
if test 37323 != $1
then
echo mv.c: Checksum error. Is: $1, should be: 37323.
fi
#
#
echo Extracting mvcp.c:
sed 's/^Z//' >mvcp.c <<\STUNKYFLUFF
Z#include <stdio.h>
Z/*
Z * mvcp.c - routines common to mv and cp
Z */
Z#include <fcntl.h>
Zchar buffer[BUFSIZ*16];
Zextern char *me;
Zfilecopy(target,source)
Zchar *target,*source;
Z{
Z    int t,s,r;
Z    if (-1 == (s = open(source,O_RDONLY)))
Z    {
Z		fprintf(stderr,"%s : can't open %s\n",me,source);
Z		return(-1);
Z    }
Z    if (-1 == (t = open(target,O_TRUNC)))
Z    {
Z		fprintf(stderr,"%s : can't open %s\n",me,target);
Z		return(-1);
Z    }
Z    while(0 != (r = read(s,buffer,BUFSIZ*16)) && r != -1)
Z    {
Z		if(-1 == write(t,buffer,r))
Z		{
Z		    fprintf(stderr,"%s : error writing %s\n",me,target);
Z		    return(-1);
Z		}
Z    }
Z    close(t); 
Z    close(s);
Z	return (0);
Z}
Z
Z#include <errno.h>
Ztypedef struct
Z{
Z    char dos_reserved[21];
Z    char attribute;
Z    unsigned file_time;
Z    unsigned file_date;
Z    long file_size;
Z    char file_name[13];
Z} 
Zfcb;
Zfcb dir;
Z
Zdirp(s)
Zchar *s;
Z{
Z	register int junk1,junk2;
Z	/* handle all of the stupid special cases */
Z	if ((s[1] == ':' && s[2] == '\0')	/* root directory on a drive */
Z		|| (s[1] == '\0')				/* root directory default drive */
Z	)
Z	{
Z		return 1;
Z	}
Z	if (0 == strcmp(s,".."))			/* parent of this directory */
Z	{
Z		int returnval;
Z		char *current,*parent;
Z		current = getcwd(NULL,64);
Z		if (-1 == chdir(s)) /* go to parent */
Z			returnval = 0;
Z		else
Z			returnval = 1;
Z		parent = getcwd(NULL,64);
Z		chdir(current);
Z		free(current); free(parent);
Z		return returnval;
Z	}
Z    /* set the disk transfer address */
Z    bdos(0x1A,&dir);
Z    /* do a search first for the directory path */
Z    return (bdos(0x4E,s,0x10) == 0 && bdos(0x4E,s,0) != 0);
Z}
Z
Zfilep(s)
Zchar *s;
Z{
Z    /* set the disk transfer address */
Z    bdos(0x1A,&dir);
Z    /* do a search first for the directory path */
Z    return bdos(0x4E,s,0) == 0;
Z}
Zchar *fname_part(s)
Zregister char *s;
Z{
Z    register char *r; 
Z    char *rindex();
Z    if (r = rindex(s,'\\'))
Z	{
Z		return r+1;
Z	}
Z    if (r = rindex(s,':'))
Z	{
Z		return r+1;
Z	}
Z    return s;
Z}
Zchar *path_part(s)
Zregister char *s;
Z{
Z	static char buffer[64];
Z    register char *r; 
Z    char *rindex();
Z	strcpy(buffer,s);	/* copy string */
Z	if (r = rindex(buffer,'\\'))
Z	{
Z		*++r = '\0';
Z		return buffer;
Z	}
Z	if (r = rindex(buffer,':'))
Z	{
Z		*++r = '\0';
Z		return buffer;
Z	}
Z	return NULL;
Z}
Zchar *drive_part(s)
Zregister char *s;
Z{
Z	static char buffer[64];
Z    register char *r; 
Z    char *rindex();
Z	strcpy(buffer,s);	/* copy string */
Z	if (buffer[1] == ':')
Z	{
Z		buffer[2] = '\0';
Z		return buffer;
Z	}
Z	return NULL;
Z}
STUNKYFLUFF
set `sum mvcp.c`
if test 16416 != $1
then
echo mvcp.c: Checksum error. Is: $1, should be: 16416.
fi
#
#
echo Extracting pushd.c:
sed 's/^Z//' >pushd.c <<\STUNKYFLUFF
Z#define NULL (void *)0
Z
Zstatic char *dirstack[10];
Zstatic int dsp = -1;
Z
Zpushd(argc,argv)
Zchar *argv[];
Z{
Z	char *getcwd(), *savestr();
Z	static char *usage = "usage : pushd newdir";
Z	static char *pusherr = "pushd : dir stack overflow";
Z	char dirbuf[64];
Z	if (argc == 1)
Z	{
Z		write(2,usage,strlen(usage));
Z		crlf();
Z		return -1;
Z	}
Z	if (NULL ==  getcwd(&dirbuf[1],64))
Z	{
Z		perror("pushd");
Z		return -1;
Z	}
Z	if (++dsp == 10)
Z	{
Z		write(2,pusherr,strlen(pusherr));
Z		crlf();
Z		return -1;
Z	}
Z	dirbuf[0] = '\\';
Z	if (-1 == chdir(*(++argv)))
Z	{
Z		--dsp;
Z		perror("pushd");
Z		return -1;
Z	}
Z	dirstack[dsp] = savestr(dirbuf);
Z	return 0;
Z}
Z
Zpopd()
Z{
Z	register int returnval = 0;
Z	static char *poperr = "popd : dir stack underflow";
Z	if (dsp == -1)
Z	{
Z		write(2,poperr,strlen(poperr));
Z		crlf();
Z		return -1;
Z	}
Z	if (-1 == chdir(dirstack[dsp]))
Z	{
Z		perror("popd");
Z		write(2,dirstack[dsp],strlen(dirstack[dsp]));
Z		crlf();
Z		returnval = -1;
Z	}
Z	free(dirstack[dsp--]);
Z	return returnval;
Z}
STUNKYFLUFF
set `sum pushd.c`
if test 22547 != $1
then
echo pushd.c: Checksum error. Is: $1, should be: 22547.
fi
#
#
echo Extracting pwd.c:
sed 's/^Z//' >pwd.c <<\STUNKYFLUFF
Z#define NULL (void *)0
Zpwd(argc,argv)
Zchar *argv[];
Z{
Z	char *getcwd();
Z	register char *dir;
Z	if (!(dir = getcwd(NULL,256)))
Z	{
Z		perror("pwd");
Z		return -1;
Z	}
Z	write(1,"\\",1);
Z	write(1,dir,strlen(dir));
Z	crlf();
Z	if (dir)
Z		free(dir);
Z	return 0;
Z}
STUNKYFLUFF
set `sum pwd.c`
if test 11133 != $1
then
echo pwd.c: Checksum error. Is: $1, should be: 11133.
fi
#
#
echo Extracting rm.c:
sed 's/^Z//' >rm.c <<\STUNKYFLUFF
Z#include <stdio.h>
Zrm(argc,argv)
Z	int argc;
Z	char *argv[];
Z{
Z	extern int _echo;
Z	int oldecho = _echo;
Z	char ask = 0;
Z
Z	if (argv[1][0] == '-' && toupper(argv[1][1]) == 'Q')
Z	{
Z		ask++;
Z		_echo = 1;
Z		++argv; --argc;
Z	}
Z	while(--argc) 
Z	{
Z		++argv;
Z		if (ask)
Z		{
Z			fprintf(stderr,"delete %s? (y or n) : ",*argv);
Z			if (toupper(scr_getc()) != 'Y')
Z			{
Z				write(2,"\r\n",2);
Z				continue;
Z			}
Z			write(2,"\r\n",2);
Z		}
Z		if (-1 == unlink(*(argv)))
Z		{
Z			perror("rm");
Z		}
Z	}
Z	_echo = oldecho;
Z}
Z
Z
STUNKYFLUFF
set `sum rm.c`
if test 00071 != $1
then
echo rm.c: Checksum error. Is: $1, should be: 00071.
fi
#
#
echo Extracting rmdir.c:
sed 's/^Z//' >rmdir.c <<\STUNKYFLUFF
Z#include <stdio.h>
Zrd(argc,argv)
Zchar *argv[];
Z{
Z	static char *usage = "usage : rmdir directory";
Z	if (argc == 1)
Z		write(2,usage,strlen(usage));
Z	if (-1 == rmdir(*(++argv)))
Z	{
Z		perror("rmdir");
Z		return -1;
Z	}
Z	return 0;
Z}
STUNKYFLUFF
set `sum rmdir.c`
if test 22459 != $1
then
echo rmdir.c: Checksum error. Is: $1, should be: 22459.
fi
#
#
echo Extracting savestr.c:
sed 's/^Z//' >savestr.c <<\STUNKYFLUFF
Z#define NULL (void *)0
Zchar *
Zsavestr(s)
Z	register char *s;
Z{
Z	register char *r,*malloc();
Z	/* squirrel away matched file name */
Z	if (NULL == (r = malloc(strlen(s)+1)))
Z		abort();
Z	strcpy(r,s);
Z	r[strlen(s)] = '\0';
Z	return r;
Z}
STUNKYFLUFF
set `sum savestr.c`
if test 32164 != $1
then
echo savestr.c: Checksum error. Is: $1, should be: 32164.
fi
#
#
echo Extracting shell.lnk:
sed 's/^Z//' >shell.lnk <<\STUNKYFLUFF
Zmain.o cd.o cp.o doprog.o fexecvp.o more.o
Zinvalid.o ls.o pushd.o fgrep.o env.o cmds.o chmod.o
Zmd.o mv.o pwd.o rm.o crlf.o drive.o fexecv.o
Zrmdir.o savestr.o stdsave.o touch.o dump2.o mvcp.o
Z_croot.o cat.o echo.o y.o fexec.o cmdlist.o ctlbrk.o
Z/clibs/c.lib /clibs/s.lib
STUNKYFLUFF
set `sum shell.lnk`
if test 41375 != $1
then
echo shell.lnk: Checksum error. Is: $1, should be: 41375.
fi
#
#
echo Extracting ssbrk.asm:
sed 's/^Z//' >ssbrk.asm <<\STUNKYFLUFF
Z; :ts=8
Z;Copyright (C) 1983 by Manx Software Systems
Z	include lmacros.h
Zdataseg	segment	word public 'data'
Z	extrn	$MEMRY:word
Z	extrn	_mbot_:word, _sbot_:word
Z	extrn	_mtop_:word
Z	extrn	errno_:word
Z	extrn	_STKLOW_:word
Z	extrn	_PSP_:word
Zdataseg	ends
Z	assume	ds:dataseg
Z;
Z; sbrk(size): return address of current top & bump by size bytes
Z;
Z	procdef	sbrk,<<siz,word>>
Z	push	di
Z	mov	ax,siz
Z	mov	di,$MEMRY
Z	add	ax,di
Z	push	ax
Z	call	brk_
Z	pop	cx
Z	test	ax,ax
Z	jnz	brk_error
Z	mov	ax,di		;return original value of the break
Zbrk_error:
Z	pop	di
Z	test	ax,ax		;set flags for C
Z	pret
Z	pend	sbrk
Z;
Z; brk(addr):	set current top address to addr
Z;		returns 0 if ok, -1 if error
Z;
Z	procdef brk,<<addr,word>>
Z	mov	ax,addr
Z	inc	ax
Z	and	al,-2
Z	cmp	ax,_mbot_
Z	jb	brk_ov
Z	mov	bx,_STKLOW_
Z	cmp	bx,0
Z	jnz	abovestk
Z	cmp	ax,_sbot_
Z	jae	brk_ov
Z	mov	bx,sp
Z	cmp	ax,bx
Z	jae	brk_ov
Zbrk_ok2:
Z	mov	$MEMRY,ax	;new value is good so save it away
Z	sub	ax,ax
Z	pret
Z;heap is above stack
Zabovestk:
Z	cmp	ax,_mtop_
Z	ja	getstore
Z	cmp	ax,$MEMRY
Z	ja	brk_ok2
Z;			going to do a SETBLOCK call
Zgetstore:
Z	push	ax
Z	mov	bx,ax
Z	mov 	cx,4
Z	shr	bx,cl
Z	and	bx,0fffh
Z	add	bx,65		;bump to nearest 1k increment
Z	and	bx,0ffc0h	;and round
Z	push	bx
Z	push	es
Z	mov	cx,ds
Z	add	bx,cx		;get actual paragraph address
Z	mov	es,_PSP_
Z	sub	bx,_PSP_
Z	mov	ah,04ah
Z	int	21h		;SETBLOCK
Z	pop	es
Z	pop	bx
Z	pop	ax
Z	jc	brk_ov		; couldn't do it, so punt
Z	mov	$MEMRY,ax
Z	test	bx,0e000h
Z	jnz	brk_ov
Z	mov	cx,4
Z	shl	bx,cl
Z	mov	_mtop_,bx
Z	sub	ax,ax
Z	pret
Z; invalid request
Zbrk_ov:
Z	mov	errno_,-4
Z	mov	ax,-1
Z	test	ax,ax
Z	pret
Z	pend	brk
Z;
Z; rsvstk(size):		set safety margin for stack
Z;			this will make sure that at least size
Z;			bytes of stack below the current level remain.
Z;
Z	procdef	rsvstk,<<stksize,word>>
Z	mov	ax,sp
Z	sub	ax,stksize
Z	mov	_sbot_,ax
Z	pret
Z	pend	rsvstk
Z	finish
Z	end
STUNKYFLUFF
set `sum ssbrk.asm`
if test 58681 != $1
then
echo ssbrk.asm: Checksum error. Is: $1, should be: 58681.
fi
#
#
echo Extracting stdsave.c:
sed 's/^Z//' >stdsave.c <<\STUNKYFLUFF
Z#include <stdio.h>
Z#include <fcntl.h>
Z
Zint console;
Zint in,out;	/* old standard input and standard output */
Zstd_save()
Z{
Z	if (-1 == (console = open("con",O_RDWR)))
Z	{
Z		perror("sh : can't open console");
Z		return -1;
Z	}
Z	in = dup(0);
Z	out = dup(1);
Z	fdup(console,0);
Z	fdup(console,1);
Z	fdup(console,2);
Z	return 0;
Z}
Zvoid 
Zstd_restore()
Z{
Z	fdup(in,0);
Z	fdup(out,1);
Z	close(console);
Z	close(in);
Z	close(out);
Z}
STUNKYFLUFF
set `sum stdsave.c`
if test 61619 != $1
then
echo stdsave.c: Checksum error. Is: $1, should be: 61619.
fi
#
#
echo Extracting stksiz.c:
sed 's/^Z//' >stksiz.c <<\STUNKYFLUFF
Zint _STKSIZ = 8192/16;  /* (in paragraphs) */
Zint _HEAPSIZ = 32768/16; /* (in paragraphs) */
Zint _STKLOW = 1;		/* default is stack above heap (small only) */
STUNKYFLUFF
set `sum stksiz.c`
if test 11181 != $1
then
echo stksiz.c: Checksum error. Is: $1, should be: 11181.
fi
#
#
echo Extracting touch.c:
sed 's/^Z//' >touch.c <<\STUNKYFLUFF
Z#include <stdio.h>
Z
Ztouch(argc,argv)
Z	char *argv[];
Z{
Z	while(--argc)
Z		utime(*(++argv),NULL);
Z}
STUNKYFLUFF
set `sum touch.c`
if test 31978 != $1
then
echo touch.c: Checksum error. Is: $1, should be: 31978.
fi
#
#
echo Extracting y.c:
sed 's/^Z//' >y.c <<\STUNKYFLUFF
Z#include <stdio.h>
Z#include <signal.h>
Z#include <setjmp.h>
Z
Z/* y and t
Z * y reads the standard input to standard output, then invokes cat
Z * to put one or more files to standard output
Z * tee copies standard input to output and puts a copy
Z * into a file specified on the command line
Z */
Z
Zvoid (*signal())();
Zvoid (*teesig)();
Zjmp_buf y_env;
Zstatic FILE *in,*out;
Z
ZFILE *fopen(),*fdopen();
Z
Zvoid y_intr()
Z{
Z	signal(SIGINT,SIG_IGN);
Z	longjmp(y_env,-1);
Z}
Z
Zy(argc,argv)
Z	int argc;
Z	char *argv[];
Z{
Z	register int c;
Z
Z	/* handle interrupts */
Z	if (-1 == setjmp(y_env))
Z	{
Z		static char *intmsg = "Interrupted\r\n";
Z		write(2,intmsg,strlen(intmsg));
Z		fclose(in);
Z		fclose(out);
Z		signal(SIGINT,teesig);
Z		return -1;
Z	}
Z
Z	/* set signal catcher */
Z	teesig = signal(SIGINT,y_intr);
Z
Z	if (NULL == (in = fdopen(0,"r")))
Z	{
Z		fprintf(stderr,"can't open stdin\n");
Z	};
Z	if (NULL == (out = fdopen(1,"w")))
Z	{
Z		fprintf(stderr,"can't open stdout\n");
Z	};
Z
Z	while(EOF != (c = agetc(in)))
Z		aputc(c,out);
Z	if (argc > 1)
Z		cat(argc,argv);
Z	fclose(in);
Z	fclose(out);
Z	signal(SIGINT,teesig);
Z	return 0;
Z}
Z
Zjmp_buf t_env;
Z
Zvoid t_intr()
Z{
Z	signal(SIGINT,SIG_IGN);
Z	longjmp(t_env,-1);
Z}
Z
Zt(argc,argv)
Z	int argc;
Z	char *argv[];
Z{
Z	register int c;
Z	register FILE *tfile;
Z	FILE *fopen();
Z
Z	/* handle interrupts */
Z	if (-1 == setjmp(t_env))
Z	{
Z		static char *intmsg = "Interrupted\r\n";
Z		write(2,intmsg,strlen(intmsg));
Z		fclose (tfile);
Z		fclose(in);
Z		fclose(out);
Z		signal(SIGINT,teesig);
Z		return -1;
Z	}
Z
Z	/* set signal catcher */
Z	teesig = signal(SIGINT,t_intr);
Z
Z	if (NULL == (tfile = fopen(*(++argv),"w")))
Z	{
Z		fprintf(stderr,"can't open %s\n",*argv);
Z	};
Z	if (NULL == (in = fdopen(0,"r")))
Z	{
Z		fprintf(stderr,"can't open stdin\n");
Z	};
Z	if (NULL == (out = fdopen(1,"w")))
Z	{
Z		fprintf(stderr,"can't open stdout\n");
Z	};
Z
Z	while(EOF != (c = agetc(in)))
Z	{
Z		aputc(c,out);
Z		if (tfile)
Z			aputc(c,tfile);
Z	}
Z	fclose(in);
Z	fclose(out);
Z	fclose(tfile);
Z	signal(SIGINT,teesig);
Z	return 0;
Z}
STUNKYFLUFF
set `sum y.c`
if test 44898 != $1
then
echo y.c: Checksum error. Is: $1, should be: 44898.
fi
echo ALL DONE BUNKY!
exit 0
-- 
                                                                          --
                .^.                        michael regoli 
                /|\        ...ihnp4!inuxc!iuvax!isrnix!mr 
               '|!|`                     <mr at isrnix.UUCP> 



More information about the Comp.sources.unix mailing list