C-Shell for the PC (PART_1: 60224 bytes)

michael regoli mr at isrnix.UUCP
Mon Dec 16 04:32:38 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 PACKING_LIST:
sed 's/^Z//' >PACKING_LIST <<\STUNKYFLUFF
Z
Z Volume in drive A is UNIX CSH PC
Z Directory of  A:\
Z
ZCMDS              794  10-03-85   1:56p
ZMAKEFILE         1879  10-03-85   2:22p
ZCSHELL   ARC    86912  11-12-85  11:13a
ZCTLBRK   ASM     1540  10-03-85   1:29p
ZFEXEC    ASM     1134   9-05-85   2:23p
ZSSBRK    ASM     1903   9-30-85   2:35p
ZCAT      C       1295   9-06-85  10:18a
ZCD       C        231   9-06-85   9:33a
ZCHMOD    C       2315   9-06-85   9:33a
ZCMDLIST  C       1058   9-12-85  11:02a
ZCMDS     C       2097   9-12-85  11:02a
ZCP       C       2184  10-03-85   2:46p
ZCRLF     C         59   9-06-85   9:33a
ZCROOT    C       3917   8-16-85   2:31p
ZDOPROG   C        180   9-06-85   9:33a
ZDRIVE    C        214   9-06-85   9:33a
ZDUMP2    C       6969   9-12-85  11:25a
ZECHO     C        193   9-06-85   9:33a
ZENV      C       2922   9-06-85   9:33a
ZFEXECV   C       1119   9-06-85   9:33a
ZFEXECVP  C       1017   9-06-85   9:33a
ZFGREP    C       2141   9-06-85  10:13a
ZGETCMD   C       1453   9-06-85   9:33a
ZINVALID  C        248   9-06-85   9:33a
ZLS       C       8042  10-03-85  12:27p
ZMAIN     C      11239  10-03-85   4:27p
ZMD       C        121   9-06-85   9:33a
ZMORE     C       4920   9-19-85  10:27a
ZMV       C       3802  10-03-85   2:43p
ZMVCP     C       2600  10-03-85   2:49p
ZPUSHD    C       1039   9-06-85   9:33a
ZPWD      C        268   9-06-85   9:33a
ZRM       C        537   9-06-85   9:33a
ZRMDIR    C        240   9-06-85   9:33a
ZSAVESTR  C        243   9-06-85   9:33a
ZSTDSAVE  C        438   9-06-85   9:33a
ZSTKSIZ   C        161  10-02-85   2:31p
ZTOUCH    C        104   9-06-85   9:33a
ZY        C       2093   9-06-85  10:17a
Z_CROOT   C       5537   9-19-85  10:16a
ZCSHELL   DOC    16714  10-03-85   2:11p
ZSHELL    EXE    28464  10-03-85   4:27p
ZSHELL    LNK      276  10-03-85   2:22p
ZMAIN     S       9750  10-03-85   9:24a
Z       44 File(s)    115712 bytes free
STUNKYFLUFF
set `sum PACKING_LIST`
if test 56252 != $1
then
echo PACKING_LIST: Checksum error. Is: $1, should be: 56252.
fi
#
#
echo Extracting _croot.c:
sed 's/^Z//' >_croot.c <<\STUNKYFLUFF
Z/* Copyright (C) 1981,1982, 1983 by Manx Software Systems */
Z#include <stdio.h>
Z#include <errno.h>
Z#include <fcntl.h>
Z#ifndef NULL
Z#define NULL ((void *)0)
Z#endif
Z
Zchar *get_first(), *get_next(), *sbrk();
Zchar *wilderr = "No wild cards in command names!!\r\n";
Z
Z/* noexpand can be set by routines before calling _Croot */
Zint noexpand = 0;
Z
Z#define ARGMAX 256
Zstatic char *Argv[ARGMAX];
Zstatic int Argc;
Zstatic char curr_path[128];
Z
Z_Croot(cp,cmd)
Zregister char *cp;
Zint (*cmd)();
Z{
Z	int returnval = 0;
Z	char *startbuf,*endbuf;
Z	register char *cp2;
Z	char *wild_match;
Z	char *index(),*rindex(), *save_str();
Z	char *path,*copy; int j;
Z	char *quote;
Z	int k,omode; char *fname;
Z	int in = -1, out = -1;
Z	/* lets try not to free things not allocated by malloc */
Z	startbuf = cp; endbuf = &cp[strlen(cp)];
Z	if (!noexpand)
Z	{
Z		/* ls is a special case !!! */
Z		if(0 == strncmp(cp,"ls",2) || 0 == strncmp(cp,"dir",3))
Z			noexpand++;
Z	}
Z
Z	/* loop through arguments */
Z	for (Argc = 0;;) 
Z	{
Z		/* skip blanks */
Z		while (*cp == ' ' || *cp == '\t')
Z			++cp;
Z
Z		/* if you're at the end of command line, you're done */
Z		if (*cp == 0)
Z			break;
Z		/* handle redirection . . . */
Z		if (*cp == '>')
Z		{
Z			k = 1;
Z			if (cp[1] == '>')
Z			{
Z				++cp;
Z				omode = O_CREAT | O_WRONLY | O_APPEND; 
Z			}
Z			else
Z				omode = O_CREAT | O_WRONLY | O_TRUNC;
Z			goto redirect;
Z		} else if (*cp == '<')
Z		{
Z			k = 0;
Z	redirect:
Z			while (*++cp == ' ' || *cp == '\t')
Z				;
Z			fname = cp;
Z			while(*++cp)
Z				if (*cp == ' ' || *cp == '\t')
Z				{
Z					*cp++ = 0;
Z					break;
Z				}
Z			close(k);
Z			if (k)
Z				out = k = open(fname,omode);
Z			else
Z				in = k = open(fname,O_RDONLY);
Z			if (k == -1)
Z			{
Z				perror("redirection");
Z				return -1;
Z			}
Z			/* go back for next argument */
Z			continue;
Z		}
Z		/* find beginning of next argument */
Z		cp2 = cp;	/* save original pointer to the string */
Z		while (*++cp2)
Z		{
Z			/* if you hit a space char - stick a null in to terminate last
Z			   argument
Z			 */
Z			if (*cp2 == ' ' || *cp2 == '\t') 
Z			{
Z				*cp2++ = 0;
Z				break;
Z			}
Z		}
Z
Z		/* if no wild card characters, do it the old fashioned way */
Z		if (index(cp,'*') == NULL && index(cp,'?') == NULL)
Z		{
Znotranslate:
Z			if (*cp == '\'')
Z			/* pass through untranslated, with quotes stripped */
Z			{
Z				cp++;	/* point past quote */
Z				if ( NULL == (quote = rindex(cp,'\'')))
Z				{
Z					write(2,"sh - no close quotes on command line\r\n",38);
Z					goto free_args;
Z				}
Z				*quote = '\0';
Z			}
Z			/* update the next argv pointer */
Z			Argv[Argc] = cp;
Z			/* bump the argument count */
Z			if (++Argc == ARGMAX)
Z				abort();
Z		}
Z		else
Z		{
Z			if (*cp == '"' || *cp == '\'')
Z				goto notranslate;
Z			if (noexpand)
Z				goto notranslate;
Z			/* wild cards not permitted on first run thru */
Z			if (Argc == 0)
Z			{
Z				write(2,wilderr,strlen(wilderr));
Z				return -1;
Z			}
Z			/* if there is a path included, save it off */
Z			if ((path = rindex(cp,'\\')) || (path = rindex(cp,'/')))
Z			{
Z				copy = cp;
Z				/* copy to curr_path, mapping / to \ */
Z				for (j = 0; j < sizeof(curr_path) && copy != path+1; copy++,j++)
Z					curr_path[j] = (*copy == '/' ? '\\' : *copy);
Z				/* terminate string */
Z				curr_path[j] = '\0';
Z			}
Z			else if (cp[1] == ':')
Z			{
Z				copy = cp;
Z				for (j = 0; j < 2; j++)
Z					curr_path[j] = *copy++;
Z				curr_path[j] = '\0';
Z			} else
Z			/* null path */
Z				curr_path[0] = 0;
Z			if (wild_match = get_first(cp))
Z			{
Z				/* update the next argv pointer */
Z				Argv[Argc]= save_str(wild_match);
Z				/* bump the argument count */
Z				if (++Argc == ARGMAX)
Z					abort();
Z				/* get the rest of the matching file names */
Z				while (wild_match = get_next())
Z				{
Z					
Z					/* update the next argv pointer */
Z					Argv[Argc] = save_str(wild_match);
Z					/* bump the argument count */
Z					if (++Argc == ARGMAX)
Z						abort();
Z				}
Z			}
Z		}
Z		cp = cp2;	/* point to beginning of next argument */
Z	}
Z	Argv[Argc] = NULL;	
Z	returnval=(*cmd)(Argc,Argv);
Z	if (in != -1)
Z		close(in);
Z	if (out != -1)
Z		close(out);
Z	/* free anything not dynamically allocated */
Zfree_args:
Z	if (!noexpand)
Z	{
Z		for(j = 1;j < Argc; j++)
Z			if (
Z			!(Argv[j] >= startbuf && Argv[j] <= endbuf)	/* not in cmd line */
Z			&& Argv[j]									/* Not NULL			*/
Z		   		)
Z			free(Argv[j]);
Z	}
Z	noexpand = 0;
Z	return returnval;
Z}
Z
Zchar *
Zsave_str(s)
Z	register char *s;
Z{
Z	register char *r,*malloc();
Z	int pathlen;
Z	/* squirrel away matched file name */
Z	if (NULL == (r = malloc(strlen(s)+(pathlen = strlen(curr_path))+1)))
Z		abort();
Z	strcat(curr_path,s);
Z	strcpy(r,curr_path);
Z	curr_path[pathlen] = '\0';
Z	return r;
Z}
Z
Zabort()
Z{
Z	write(2, "Too many args.", 14);
Z	_exit(200);
Z}
Z
Z
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} fcb;
Zfcb wildcard;
Z
Zchar *get_first(fname)
Z	char *fname;
Z{
Z	register int result;
Z	/* set the disk transfer address */
Z	bdos(0x1A,&wildcard);
Z	result = bdos(0x4E,fname,0);
Z	/* make the find first call */
Z	if(2 == result || 18 == result)
Z		return NULL;
Z	return &(wildcard.file_name[0]);
Z}
Z
Zchar *get_next()
Z{
Z	register int result;
Z	/* set the disk transfer address */
Z	bdos(0x1A,&wildcard);
Z	result = bdos(0x4f,0,0);
Z	/* make the find next call */
Z	if (18 == result)
Z		return NULL;
Z	return &(wildcard.file_name[0]);
Z}
STUNKYFLUFF
set `sum _croot.c`
if test 54651 != $1
then
echo _croot.c: Checksum error. Is: $1, should be: 54651.
fi
#
#
echo Extracting cat.c:
sed 's/^Z//' >cat.c <<\STUNKYFLUFF
Z#include <stdio.h>
Z#include <signal.h>
Z#include <setjmp.h>
Z
Zvoid (*signal())();
Z
ZFILE *fd1,*fd2;
Z
Zvoid (*oldsig)();
Zchar *fgets();
Zjmp_buf catenv;
Zcatintr()
Z{
Z	signal(SIGINT,SIG_IGN);			/* ignore signals */
Z	fclose(fd1);
Z	fclose(fd2);
Z	signal(SIGINT,oldsig);			/* restore shell interrupt */
Z	longjmp(catenv,-1);
Z}
Z
Zcat(argc,argv)
Z	char *argv[];
Z{
Z	char *intmsg = "Interrupt received\n";
Z
Z	FILE *fdopen(), *fopen();
Z	if (-1==setjmp(catenv))
Z	{
Z		write(2,intmsg,strlen(intmsg));
Z		return -1;
Z	}
Z	oldsig = signal(SIGINT,catintr);	/* trap interrupts from keyboard */
Z	/* get standard output opened for business */
Z	if (NULL == (fd2 = fdopen(1,"w")))
Z	{
Z		perror("cat : Can't open stdout");
Z	}
Z
Z	/* handle pipes */
Z	if (argc == 1)
Z	{
Z		if (NULL == (fd1 = fdopen(0,"r")))
Z		{
Z			perror("cat : Can't open stdin");
Z		}
Z		_cat();
Z		fclose(fd1);fclose(fd2);
Z	}
Z	/* handle specified files */
Z	else
Z	{
Z		while(--argc)
Z		{
Z			if (NULL == (fd1 = fopen(*(++argv),"r")))
Z			{
Z				fprintf(stderr,"can't open %s\n",*argv);
Z				continue;
Z			}
Z			_cat();
Z			fclose(fd1);
Z		}
Z	}
Z	fclose(fd2);
Z	signal(SIGINT,oldsig);				/* restore old int catcher		*/
Z}
Z
Z_cat()
Z{
Z	char buffer[512];
Z	while (NULL != fgets(buffer,512,fd1))
Z		fputs(buffer,fd2);
Z}
STUNKYFLUFF
set `sum cat.c`
if test 12297 != $1
then
echo cat.c: Checksum error. Is: $1, should be: 12297.
fi
#
#
echo Extracting cd.c:
sed 's/^Z//' >cd.c <<\STUNKYFLUFF
Z#include <stdio.h>
Zcd(argc,argv)
Zchar *argv[];
Z{
Z	static char *usage = "usage : cd newdir";
Z	if (argc == 1)
Z		write(2,usage,strlen(usage));
Z	if (-1 == chdir(*(++argv)))
Z	{
Z		perror("cd");
Z		return -1;
Z	}
Z	return 0;
Z}
STUNKYFLUFF
set `sum cd.c`
if test 24433 != $1
then
echo cd.c: Checksum error. Is: $1, should be: 24433.
fi
#
#
echo Extracting chmod.c:
sed 's/^Z//' >chmod.c <<\STUNKYFLUFF
Z#include <stdio.h>
Z#include <stat.h>
Z#ifdef MAIN
Zmain
Z#else
Zch_mod
Z#endif
Z(argc,argv)
Z	char *argv[];
Z{
Z	int or_mask,and_mask,file_stat;
Z	struct { int ax,bx,cx,dx,si,di,ds,es; } regs;
Z	extern int _dsval;
Z	char *current;
Z	regs.ds = _dsval;
Z	if (argc==1)
Z	{
Z		fprintf(stderr,"Usage : chmod +|-[ahw] file [file ...]\n");
Z	}
Z	/* set attributes to default */
Z	or_mask = 0; and_mask = 0xFFFF;
Z	while(--argc)
Z	{
Z		current = *(++argv);
Z		switch (*current)
Z		{
Z		case '-':
Z			while (*++current)
Z			{
Z				switch(*current)
Z				{
Z				case 'w':
Z				case 'W':
Z					or_mask |= ST_RDONLY;
Z					break;
Z				case 'h':
Z				case 'H':
Z					and_mask &= (ST_HIDDEN ^ 0xFFFF);
Z					break;
Z				case 'r':
Z				case 'R':
Z					or_mask |= ST_HIDDEN;
Z					break;
Z				case 'a':
Z				case 'A':
Z					and_mask &= (ST_ARCHIV ^ 0xFFFF);
Z					break;
Z				case 's':
Z				case 'S':
Z					and_mask &= (ST_SYSTEM ^ 0xFFFF);
Z					break;
Z				default:
Z					write(2,"invalid attribute\r\n",19);
Z				return -1;
Z				}
Z			}
Z			break;
Z		case '+':
Z			while(*++current)
Z			{
Z				switch(*current)
Z				{
Z				case 'w':
Z				case 'W':
Z					and_mask &= (ST_RDONLY ^ 0xFFFF);
Z					break;
Z				case 'h':
Z				case 'H':
Z					or_mask |= ST_HIDDEN;
Z					break;
Z				case 's':
Z				case 'S':
Z					or_mask |= ST_SYSTEM;
Z					break;
Z				case 'r':
Z				case 'R':
Z					and_mask &= (ST_HIDDEN ^ 0xFFFF);
Z					break;
Z				case 'a':
Z				case 'A':
Z					or_mask |= ST_ARCHIV;
Z					break;
Z				default:
Z					write(2,"invalid attribute\r\n",19);
Z					return -1;
Z
Z				}
Z			}
Z			break;
Z		default:
Z			/* get current attribute */
Z			regs.ax = 0x4300;
Z			regs.dx = (int)current;
Z			regs.ds = _dsval;
Z			sysint(0x21,&regs,&regs);
Z			file_stat = regs.cx;
Z			fprintf(stderr,"current attribute for %s = %x\n",
Z				current,file_stat);
Z			/* set new attribute */
Z			file_stat |= or_mask;
Z			file_stat &= and_mask;
Z			regs.ax = 0x4301;
Z			regs.dx = (int)current;
Z			regs.cx = file_stat;
Z			regs.ds = _dsval;
Z			sysint(0x21,&regs,&regs);
Z			/* get attribute to see if it changed */
Z			regs.ax = 0x4300;
Z			regs.dx = (int)current;
Z			regs.ds = _dsval;
Z			sysint(0x21,&regs,&regs);
Z			file_stat = regs.cx;
Z			fprintf(stderr,"new attribute for %s = %x\n",
Z				current,file_stat);
Z			break;
Z		}
Z	}
Z}
Z
STUNKYFLUFF
set `sum chmod.c`
if test 37605 != $1
then
echo chmod.c: Checksum error. Is: $1, should be: 37605.
fi
#
#
echo Extracting cmdlist.c:
sed 's/^Z//' >cmdlist.c <<\STUNKYFLUFF
Z
Zextern int cmds(),ls(), cp(), rm(), do_prog(),pushd(),popd(),drive(), ver(),
Z		more(),fgrep(),scr_clear(),set(),ch_mod(),cat(),echo(), 
Z		y(),t(),dump(),
Z		last(),invalid(),mv(),md(),touch(),cd(),pwd(),rd(),hist(),my_exit();
Ztypedef struct
Z{
Z	char *cmdname;
Z	int (*func)();
Z} builtin;
Zbuiltin commands[] =
Z{
Z	"a:",drive,
Z	"b:",drive,
Z	"c:",drive,
Z	"cat",cat,
Z	"cd",cd,
Z	"chdir",cd,
Z	"chmod",ch_mod,
Z	"cls",scr_clear,
Z	"commands",cmds,
Z	"copy",cp,
Z	"cp",cp,
Z	"copy",cp,
Z	"d:",drive,
Z	"del",rm,
Z	"dir",ls,
Z	"dump",dump,
Z	"e:",drive,
Z	"echo",echo,
Z	"era",rm,
Z	"erase",rm,
Z	"error",last,
Z	"exit",my_exit,
Z	"f:",drive,
Z	"fgrep",fgrep,
Z	"g:",drive,
Z	"h:",drive,
Z	"hd",dump,
Z	"hist",hist,
Z	"history",hist,
Z	"i:",drive,
Z	"j:",drive,
Z	"ls",ls,
Z	"md",md,
Z	"mkdir",md,
Z	"more",more,
Z	"mv",mv,
Z	"no history",invalid,
Z	"popd",popd,
Z	"pushd",pushd,
Z	"pwd",pwd,
Z	"rd",rd,
Z	"rm",rm,
Z	"rmdir",rd,
Z	"set",set,
Z	"tee",t,
Z	"touch",touch,
Z	"version",ver,
Z	"y",y
Z};
Zint numcmds =  (sizeof(commands)/sizeof(builtin));
STUNKYFLUFF
set `sum cmdlist.c`
if test 20023 != $1
then
echo cmdlist.c: Checksum error. Is: $1, should be: 20023.
fi
#
#
echo Extracting cmds:
sed 's/^Z//' >cmds <<\STUNKYFLUFF
Za:              b:              c:              cat             
Zcd              chdir           chmod           cls             
Zcommands        copy            cp              copy            
Zd:              del             dir             dump            
Ze:              echo            era             erase           
Zerror           exit            f:              fgrep           
Zg:              h:              hd              hist            
Zhistory         i:              j:              ls              
Zmd              mkdir           more            mv              
Zno history      popd            pushd           pwd             
Zrd              rm              rmdir           set             
Ztee             touch           version         y               
Z
STUNKYFLUFF
set `sum cmds`
if test 18223 != $1
then
echo cmds: Checksum error. Is: $1, should be: 18223.
fi
#
#
echo Extracting cmds.c:
sed 's/^Z//' >cmds.c <<\STUNKYFLUFF
Z#include <stdio.h>
Z#include <fcntl.h>
Ztypedef struct
Z{
Z	char *cmdname;
Z	int (*func)();
Z} builtin;
Z
Zchar *str_lower();
Z
Zextern int result;
Z
Zextern int cmds(),ls(), cp(), rm(), do_prog(),pushd(),popd(),drive(), ver(),
Z		more(),fgrep(),scr_clear(),set(),ch_mod(),cat(),echo(), 
Z		y(),t(),dump(),
Z		last(),invalid(),mv(),md(),touch(),cd(),pwd(),rd(),hist(),my_exit();
Z
Zmy_exit(argc,argv)
Z	char *argv[];
Z{
Z	exit(result);
Z}
Z
Zver()
Z{
Z	extern char *version;
Z	write(2,version,strlen(version));
Z	write(2,"\r\n",2);
Z}
Z
Zextern builtin commands[];
Zextern int numcmds;
Zchar *histerr = "no history";
Zint j,hiscount;
Zchar *history[] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
Z					 NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
Z
Zint histsize = (sizeof(history)/sizeof(char *));
Z
Zcmds()
Z{
Z	char *current;
Z	register int i,j,col;
Z	col = 1;
Z	for (i = 0; i < numcmds; i++)
Z	{
Z		current = commands[i].cmdname;
Z		write(1,current,j = strlen(current));
Z		for (;j < 16;j++)
Z			write(1," ",1);
Z		if (col == 4)
Z		{
Z			col = 1;
Z			crlf();
Z		}
Z		else
Z			++col;
Z	}
Z	crlf();
Z}
Z
Zfindcmd(cmdbuf)
Z	char *cmdbuf;
Z{
Z	register int low,high,mid;
Z	char localbuf[256];
Z	int cond;
Z	strcpy(localbuf,cmdbuf);
Z	cmdbuf = str_lower(localbuf);
Z	low = 0;
Z	high = numcmds - 1;
Z	while (low <= high)
Z	{
Z		mid = (low+high) / 2;
Z		if	( ( cond =  strncmp( cmdbuf,
Z								 commands[mid].cmdname,
Z								 strlen(commands[mid].cmdname) ) ) < 0 )
Z				high = mid - 1;
Z		else if (cond > 0)
Z				low = mid + 1;
Z		else
Z		{
Z			/* kludge to allow for program invocations like d:command */
Z			if (cmdbuf[1] == ':')
Z				if (cmdbuf[2] == '\0')
Z					return mid;
Z				else
Z					return -1;
Z			return mid;
Z		}
Z	}
Z	return -1;
Z}
Z
Zhist()
Z{
Z	register int i;
Z	char localbuf[256];
Z	if (j < histsize)
Z		i = 0;
Z	else
Z		i = j - histsize + 1;
Z	for (;i <= j; i++)
Z	{
Z		sprintf(localbuf,"%d : %s\r\n",i,history[i % histsize]);
Z		write(1,localbuf,strlen(localbuf));
Z	}
Z}
Z
Zlast()
Z{
Z	printf("return code of last command %d\n",result);
Z	return result;
Z}
STUNKYFLUFF
set `sum cmds.c`
if test 01085 != $1
then
echo cmds.c: Checksum error. Is: $1, should be: 01085.
fi
#
#
echo Extracting cp.c:
sed 's/^Z//' >cp.c <<\STUNKYFLUFF
Z#include <stdio.h>
Zchar *me;
Z/* cp.c - implements a version of UNIX cp */
Zchar target_name[128];
Z#ifndef MAIN
Zcp
Z#else
Zmain
Z#endif
Z(argc,argv)
Zint argc;
Zregister char *argv[];
Z{
Z	static char *usage = "cp : usage cp file1 [file2 . . fileN] target\r\n";
Z    char target[128],*fname_part();
Z    register int i;
Z	me = argv[0];
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 (target[1] == ':' && !target[2])
Z	    strcat(target,fname_part(argv[1]));
Z	/* if the target doesn't exist and it's not a directory then rename */
Z	if (access(target,0) && !dirp(target))
Z	{
Z	    fprintf(stderr,"copying %s to %s\n",argv[1],target);
Z	    filecopy(target,argv[1]);
Z	}
Z	else
Z	{
Z	    /* if the target is a directory copy to same name that directory */
Z	    if (dirp(target))
Z	    {
Z		int len;
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		fprintf(stderr,"copying %s to %s\n",argv[1],target_name);
Z		filecopy(target_name,argv[1]);
Z	    }
Z	    else
Z	    {
Z		fprintf(stderr,"copying %s to %s\n",argv[1],target);
Z		filecopy(target,argv[1]);
Z	    }
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,"cp : %s isn't a directory\n",target);
Z	    return(-1);
Z	}
Z    for (i = 1; i < argc-1; i++)
Z    {
Z	int len;
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,"cp : %s isn't a file\n",argv[i]);
Z	    continue;
Z	}
Z	fprintf(stderr,"copying %s to %s\n",argv[i],target_name);
Z	filecopy(target_name,argv[i]);
Z    }
Z	return 0;
Z}
STUNKYFLUFF
set `sum cp.c`
if test 27151 != $1
then
echo cp.c: Checksum error. Is: $1, should be: 27151.
fi
#
#
echo Extracting crlf.c:
sed 's/^Z//' >crlf.c <<\STUNKYFLUFF
Zcrlf()
Z{
Z	static char *cr = "\r\n";
Z	write(1,cr,2);
Z}
STUNKYFLUFF
set `sum crlf.c`
if test 19813 != $1
then
echo crlf.c: Checksum error. Is: $1, should be: 19813.
fi
#
#
echo Extracting croot.c:
sed 's/^Z//' >croot.c <<\STUNKYFLUFF
Z/* Copyright (C) 1981,1982, 1983 by Manx Software Systems */
Z#include <errno.h>
Z#include <fcntl.h>
Z#ifndef NULL
Z#define NULL ((void *)0)
Z#endif
Z
Zchar *get_first(), *get_next(), *sbrk();
Z
Z#define ARGMAX 256
Zstatic char *Argv[ARGMAX];
Zstatic int argvsize;
Zstatic int Argc;
Zstatic char curr_path[128];
Z
Znoper()
Z{
Z	return 0;
Z}
Z
Zint (*cls_)() = noper;
Zextern char _ioflg[];
Z
ZCroot(cp, first)
Zregister char *cp;
Z{
Z	register char *cp2;
Z	char *save;
Z	char *wild_match;
Z	char *index(),*rindex(), *save_str();
Z	char *path,*copy; int j;
Z
Z	_ioflg[0] = isatty(0);	/* set flag for i/o routines */
Z	_ioflg[1] = isatty(1);	/* set flag for i/o routines */
Z	_ioflg[2] = isatty(2);	/* set flag for i/o routines */
Z
Z
Z	/* Null out first argument */
Z	Argv[0] = "";
Z	Argc = first;
Z
Z	/* loop through arguments */
Z	for (;;) 
Z	{
Z		/* skip blanks */
Z		while (*cp == ' ' || *cp == '\t')
Z			++cp;
Z
Z		/* if you're at the end of command line, you're done */
Z		if (*cp == 0)
Z			break;
Z
Z		/* find beginning of next argument */
Z		cp2 = cp;	/* save original pointer to the string */
Z		*cp2 = (*cp2 == '/' ? '\\' : *cp2);
Z		while (*++cp2)
Z		{
Z			/* if you hit a space char - stick a null in to terminate last
Z			   argument
Z			 */
Z			if (*cp2 == ' ' || *cp2 == '\t') 
Z			{
Z				*cp2++ = 0;
Z				break;
Z			}
Z			*cp2 = (*cp2 == '/' ? '\\' : *cp2);
Z		}
Z
Z		/* if no wild card characters, do it the old fashioned way */
Z		if (index(cp,'*') == NULL && index(cp,'?') == NULL)
Z		{
Z			/* update the next argv pointer */
Z			Argv[Argc] = cp;
Z			/* bump the argument count */
Z			if (++Argc == ARGMAX)
Z				abort();
Z		}
Z		else
Z		{
Z			/* if there is a path included, save it off */
Z			if ((path = rindex(cp,'\\')) || (path = rindex(cp,'/')))
Z			{
Z				copy = cp;
Z				/* copy to curr_path, mapping / to \ */
Z				for (j = 0; j < sizeof(curr_path) && copy != path+1; copy++,j++)
Z					curr_path[j] = (*copy == '/' ? '\\' : *copy);
Z				/* terminate string */
Z				curr_path[j] = '\0';
Z			}
Z			else if (cp[1] == ':')
Z			{
Z				copy = cp;
Z				for (j = 0; j < 2; j++)
Z					curr_path[j] = *copy++;
Z				curr_path[j] = '\0';
Z			} else
Z			/* null path */
Z				curr_path[0] = 0;
Z			if (wild_match = get_first(cp))
Z			{
Z				/* update the next argv pointer */
Z				Argv[Argc]= save_str(wild_match);
Z				/* bump the argument count */
Z				if (++Argc == ARGMAX)
Z					abort();
Z				/* get the rest of the matching file names */
Z				while (wild_match = get_next())
Z				{
Z					
Z					/* update the next argv pointer */
Z					Argv[Argc] = save_str(wild_match);
Z					/* bump the argument count */
Z					if (++Argc == ARGMAX)
Z						abort();
Z				}
Z			}
Z		}
Z		cp = cp2;	/* point to beginning of next argument */
Z	}
Z	Argv[Argc] = NULL;	
Z	main(Argc,Argv);
Z	exit(0);
Z}
Z
Zchar *save_str(s)
Z	register char *s;
Z{
Z	register char *r;
Z	int pathlen;
Z	/* squirrel away matched file name */
Z	if (NULL == (r = sbrk(strlen(s)+(pathlen = strlen(curr_path))+1)))
Z		abort();
Z	strcat(curr_path,s);
Z	strcpy(r,curr_path);
Z	curr_path[pathlen] = '\0';
Z	return r;
Z}
Z
Zabort()
Z{
Z	write(2, "Too many args.", 14);
Z	_exit(200);
Z}
Z
Zexit(code)
Z{
Z	(*cls_)();
Z	_exit(code);
Z}
Z
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} fcb;
Zfcb wildcard;
Z
Zchar *get_first(fname)
Z	char *fname;
Z{
Z	register int result;
Z	/* set the disk transfer address */
Z	bdos(0x1A,&wildcard);
Z	result = bdos(0x4E,fname,0);
Z	/* make the find first call */
Z	if(2 == result || 18 == result)
Z		return NULL;
Z	return &(wildcard.file_name[0]);
Z}
Z
Zchar *get_next(fname)
Z	char *fname;
Z{
Z	register int result;
Z	/* set the disk transfer address */
Z	bdos(0x1A,&wildcard);
Z	result = bdos(0x4f,0,0);
Z	/* make the find next call */
Z	if (18 == result)
Z		return NULL;
Z	return &(wildcard.file_name[0]);
Z}
STUNKYFLUFF
set `sum croot.c`
if test 02895 != $1
then
echo croot.c: Checksum error. Is: $1, should be: 02895.
fi
#
#
echo Extracting cshell.doc:
sed 's/^Z//' >cshell.doc <<\STUNKYFLUFF
Z        shell.exe 
Z
Z        command processor for ms.dos 
Z
Z        This is  yet  another  command.com  replacement.    It implements
Z        unix-like shell commands (ls, mv, fgrep, rm, chdir,  chmod)  etc.
Z        Other features include: 
Z
Z        1. Command line expansion of ambiguous file names.  
Z
Z        Programs  invoked  from  shell   never see '*.*' as an argument -
Z        they see  the  list  of  all  matching  files  in    the  current
Z        directory.  
Z
Z        2. History substitution - ala C-shell.  
Z
Z        History substitution is a powerful means to save retyping of long 
Z        command lines.It allows you to do things like re-execute the last 
Z        command,  re-execute  the  last  command but redirect output to a
Z        file, or execute a  new  command  with  arguments  from  previous
Z        command  lines.    The  last  20  commands  are saved, and can be
Z        reviewed by typing the 'history' command.  
Z
Z        Previous commands can be referred to by their number, or relative 
Z        to the  current  command's  number.    Parameters  from  previous
Z        commands can be seperated out and used individually.  
Z
Z        History  substitutions  specifications  come  in  two parts - the
Z        command number  specifier and the argument  specifier,  seperated
Z        by a  colon.    The  argument    specifier  is optional; if it is
Z        omitted, the entire command line is specified.  
Z
Z            <command specifier> ::= !! | !n | !-n 
Z            !!  = last command
Z            !n  = nth command
Z            !-n = command n commands before current command number
Z
Z            <argument specifier> ::= :[^$*] | :n | :n* | <empty>
Z            n   = number of argument (0 being the command name)
Z            ^   = first argument (i.e. argv[1])
Z            $   = last argument
Z            *   = ^-$, or nothing if only one word on command line
Z            n*  = arguments n through $
Z
Z            <history subst specification> ::= <command specifier><argument specifier>
Z
Z        This is not as complicatated as  it  may  appear.    Here  is  an
Z        example session.  
Z
Z            0% ls *.c
Z            *.c
Z            foo.c bar.c
Z            1% more foo.c
Z            /* edit the last argument of the last command */
Z            2% edit !!:$			
Z            /* go off and edit */
Z            /* reference last argument of last command */
Z            3% fgrep foo !!:$ bar.c 
Z            FOO.C : foo
Z            BAR.C : foo
Z            /* edit the second thru the last args of command 3 */
Z
Z
Z
Z
Z
Z
Z
Z
Z            4% edit !3:2*			
Z            (go off and edit)
Z            /* repeat last command */
Z            %5 !!
Z            (go off and edit)
Z            /* remove the 1st argument of the command 2 before the current one */
Z            %6 rm !-6:^
Z
Z        History  substitution here is a compatible subset of the C-shells
Z        history substitution  facility.    Cshell  allows  even   weirder
Z        combinations.  
Z
Z        3.  Multiple  commands  on  one  command line - Command lines are
Z        split at  semicolons.  
Z
Z        example 
Z
Z            %0 ls -l *.c ; make shell.exe ; exit
Z
Z        4. Character escapes and argument quoting - i.e.  '\;' suppresses 
Z        the command  parser  from  seeing  the  semicolon  as  a  command
Z        seperator.  
Z
Z        Quotes are handles thusly: 
Z
Z            1.  String  surrounded  by  single quotes are stripped of the
Z            single quotes, and passed without wild-card expansion to  the
Z            invoked program.  
Z
Z            2.  Strings  surrounded  by double quotes are passed complete
Z            with quotes to the calling program.   This  was  done  for  a
Z            version  of grep that I have that accepts regular expressions
Z            with embedded blanks within double quotes.  
Z
Z        5. Many builtin commands.  
Z
Z            Output of the 'commands' command
Z
Z            a:              b:              c:              cat             
Z            cd              chdir           chmod           cls             
Z            commands        copy            cp              copy            
Z            d:              del             dir             dump            
Z            e:              echo            era             erase           
Z            error           exit            f:              fgrep           
Z            g:              h:              hd              hist            
Z            history         i:              j:              ls              
Z            md              mkdir           more            mv              
Z            no history      popd            pushd           pwd             
Z            rd              rm              rmdir           set             
Z            tee             touch           version         y               
Z            
Z
Z        There are many that are simply aliases, e.g.    'copy'  and  'cp'
Z        invoke the same program.  
Z
Z        6. commands description syntax 
Z
Z            terms used in syntax explanations :
Z
Z
Z
Z
Z
Z
Z
Z
Z            
Z            fname ::= PC-DOS ambiguous or unambiguous file or directory name.
Z            
Z            uname ::= unambiguous PC-DOS file or directory name
Z            
Z            string ::= any string of printable characters of arbitrary(<512) length.
Z            
Z            filelist ::= filename [filename .. filename]
Z            
Z            noargs ::= no arguments at all
Z            
Z            {arg} ::= term is optional
Z            
Z            envstring ::=	<string>=<string> 
Z
Z        7. command syntax 
Z
Z        drive
Z            a: | b: | c: | d: | e: | f: | g: | h: | i: | j: <noargs> 
Z
Z            changes default  drive.    If  you  don't  have such a drive,
Z            nothing happens.  
Z
Z        cat
Z            cat {<filelist>} 
Z
Z            copies specified files to  standard  output.    If  none  are
Z            given, copies standard input to standard output 
Z
Z        cp
Z            cp | copy <filelist> <uname> 
Z
Z            copies specified  files  to  destination  file or device.  If
Z            more than one file is in the file list,  <uname>  must  be  a
Z            directory.  
Z
Z        cd
Z            cd | chdir <dirname> 
Z
Z            makes <dirname> the current default directory.  
Z
Z        chmod
Z            chmod {-|+[rwh]*} <filelist> 
Z
Z            change file permissions for specified files 
Z
Z            +r, -r turn on or off read permission - i.e. hide the file.
Z            +w, -w turn on or off write permission.
Z            +h, -h turn on or off hidden attribute - converse of r
Z            +a, -a turn on or off archive attribute
Z
Z            Note  that '-r' or '+rwh' are both valid syntax for switches.
Z            Also new permission switches  are  permissable  between  file
Z            names  with  the  following  warning: I don't reset the masks
Z            between file names - if you have a second batch of  attribute
Z            changes on  the  command  line,  the  effect is additive.  If
Z            you're not  careful,  you  could  make  a  mess  of  a  files
Z            attributes.  
Z
Z
Z
Z
Z
Z
Z
Z
Z            If  you don't specify any attribute switches, file attributes
Z            will be set  to  0,  which  means  read,write,not  hidden,not
Z            system, not  modified since last backup.  
Z
Z        cls
Z            cls | clear <noargs> 
Z
Z            clears the screen and homes the cursor.  
Z
Z        commands
Z            commands <noargs> 
Z
Z            prints a table of available built-in commands.  
Z
Z        del
Z            del 
Z
Z            synonym for rm.  
Z
Z        dir
Z            dir 
Z
Z            synonym for ls.  
Z
Z        dump
Z
Z            dump filespec [block [page]] | [segment:[offset]] [count] 
Z
Z            Where a block is 64K bytes and a page is 256 bytes
Z            Segment:offset are standard 8086 notation in hexadecimal
Z            Count is the number of bytes to dump in decimal
Z
Z            This came from some anonymous public domain source, ported by me
Z
Z        echo
Z            echo <anything> 
Z
Z            echos argument list to screen.  
Z
Z        era
Z            era 
Z
Z            synonym for rm.  
Z
Z        error
Z            error <noargs> 
Z
Z            prints returned value of last command to the screen.  
Z
Z        exit
Z            exit <noargs> 
Z
Z            terminates execution of the shell.  
Z
Z        fgrep
Z            fgrep <pattern> <filelist> 
Z
Z            looks for unambiguous pattern <pattern> in <filelist>.  echos 
Z
Z
Z
Z
Z
Z
Z
Z
Z            lines matching to the screen.  
Z
Z        hist
Z            hist | history <noargs> 
Z
Z            prints history list to standard output.  
Z
Z        ls
Z            ls | dir {-[alqcr]} <filelist> 
Z
Z            Lists files that match <filelist> 
Z
Z            -a all  files,  including  system  files are listed.  '.' and
Z            '..' are suppressed, but you know they're there if  you  need
Z            them, don't you?  
Z            -l prints out file times, permissions, etc 
Z            -q suppresses header line from display - useful when you want 
Z            to pipe stuff into another program.  
Z            -c print as one column.  
Z            -r recurse through all encountered subdirectories.  
Z
Z        md
Z            md | mkdir <uname> 
Z
Z            make a directory.  Prints an error if it can't be done 
Z
Z        more
Z            more {-[0-9]*} {<filelist>} 
Z
Z            List file to screen with pauses 
Z
Z            -n  specify  tab  width  when  expanding  tabs, where n is an
Z            integer.  more acts like 'cat'  when  redirected  -  you  can
Z            concatenate files  in this manner.  If no files are specifed,
Z            standard input is 'mored.' 
Z
Z        mv
Z            mv <filelist> <uname> 
Z
Z            moves specified file or files to target specifed by  <uname>.
Z            If  there  is  more  than one file in list, <uname> must be a
Z            directory 
Z
Z        popd
Z            popd <noargs> 
Z
Z            returns to directory at top of directory stack.  
Z
Z        pushd
Z            pushd <uname> 
Z
Z            save  current  working  directory  on  directory  stack,  and
Z            changes current working directory to <uname>.  
Z
Z        pwd
Z            pwd 
Z
Z            prints current working directory to standard output.  
Z
Z
Z
Z
Z
Z
Z
Z
Z        rd
Z            rd | rmdir <uname> 
Z
Z            remove specified directory if possible.  
Z
Z        rm
Z            rm {-q} <filelist> 
Z
Z            blows  away all files in <filelist>. If -q is specified, will
Z            ask if they should be removed.  
Z
Z        set
Z            set {<envstring> {<envstring> .. <envstring>}} 
Z
Z            sets a string in the environment.   If  you  specify  'name='
Z            with   no   string   after,   it  will  remove  it  from  the
Z            environment.  If you don't specify a string, set  prints  out
Z            current environment.  
Z
Z        tee
Z            tee <uname> 
Z
Z            Copies  standard  input to standard output, depositing a copy
Z            in <uname> 
Z
Z        touch
Z            touch <filelist> 
Z
Z            Makes the modification time of specified  files  the  current
Z            date and time.  
Z
Z        y
Z            y <filelist> 
Z
Z            copies standard input to standard output, and then copies the 
Z            specified files  to standard output.  Sort of the opposite of
Z            tee, in other words.  
Z
Z        7. Helpful hints 
Z
Z            Use forward slashes in all path names - they get converted to 
Z            back slashes before  dos  hears  about  them.    If  you  are
Z            invoking a program that expects forward slashes (dos external 
Z            commands frinstance) precede it with a back slash.  
Z
Z            put  single  quotes around arguments with semicolons in them,
Z            so they don't turn into command delimiters.  
Z
Z            The set command affects only the local  shell's  environment.
Z            You can 'exit' to command.com and the original environment is 
Z            intact.   The  local  environment  is  4K  large  -  which is
Z            useful.  
Z
Z            Exit and re-invoke if you have trouble loading large programs 
Z            from it - shell dynamically allocates and  frees  memory  all
Z            the  time,  but the AZTEC run-time doesn't tell DOS to shrink
Z            memory 
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z        8. Implementation notes 
Z
Z            DOS doesn't acknowledge  a  'change  default  drive'  command
Z            until you issue  a  'get  current directory' call.  Why?  The
Z            only way I figured this out is by disassembling command.com.  
Z
Z            This was developed with AZTEC C by MANX.  In  it  are  a  few
Z            hacked  up  pieces  of  AZTECS library source, which I hereby
Z            acknowledge.  If MANX has  a  problem  with  me  distributing
Z            them,  they  can  call  me direct - I figure I'm doing them a
Z            favor by disseminating this program  as  an  example  of  the
Z            power and quality of their compiler and development tools.  
Z
Z            If  you  have  the AZTEC compiler and MANX's version of make,
Z            you can recreate the shell  from  source,  by  using  arc  to
Z            unpack everything into a directory, editing the macros BINDIR 
Z            and CLIB  and then making  shell.com.  I wouldn't try it with
Z            any other compiler, because I make a lot of  calls  to  AZTEC
Z            specific routines.    You can write your own commands and add
Z            them  by  editing  cmds.c,  and  putting  the  name  of  your
Z            subroutine and its associated command string into the builtin 
Z            array.   
Z
Z            You  can  safely  modify  any  of my builtins, as long as you
Z            don't assume that all of your static variables are  going  to
Z            stay initialized to startup values.  
Z
Z            Any  of the other code (main.c, fexecvp.c fexecv.c) modify at
Z            your own peril.  I break them every time I do it, and I wrote 
Z            them!!!  
Z
Z            PC|MS-DOS has a limit of 20 file  handles.    If  you  add  a
Z            command  that opens files, make sure you catch the ctrl-break
Z            signal and close them.  Look at CAT.C or Y.C for examples.  
Z
Z        9. BUGS 
Z            External DOS commands have trouble parsing the  command  line
Z            when invoked from   shell.  The command line gets garbled.  I
Z            spent a lot of time trying to figure this problem out  to  no
Z            avail.  They apparently get their command line arguments some 
Z            way that  is a mystery to me.  The only solution is either to
Z            either run command.com, or 'exit'  to  the  original  command
Z            prompt.  
Z
Z            This  problem  has  kept  me  from running this as a straight
Z            command.com   replacement.    It  just  goes  to  show   that
Z            Microsoft and IBM have one hell of a time following their own 
Z            rules.  
Z
Z            Programs  compiled  by  AZTEC  C  that don't set up their own
Z            signal  handlers  seem  to  be  'unbreakable'  -  you   can't
Z            ctrl-break  out  of  them, as though SIGINT is set to SIG_IGN
Z            before entry.  You might not want to invoke such a program if 
Z            it lasts hours and you want to be able to break  out  of  it.
Z            FIXED in current version.  Thanks to AZTEC Tech Support.  
Z
Z        10. HISTORY 
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z            V 1.0 - Initial release
Z
Z            Functional, but   somewhat   buggy.     Lacked  full  history
Z            substitution.  
Z
Z            V 1.1
Z
Z            Added history substitution.  Fixed some bugs.  This has  been
Z            floating around for a while.  
Z
Z            V 1.2
Z
Z            Fixed bugs.    Added 'free space' display to ls -l. Minimized
Z            weird behavior of cp and  mv.    Did  you  know  that  PC-DOS
Z            doesn't  think  the  root directory is a directory if you ask
Z        it?  Caused much pain.  
Z
Z        QUESTIONS COMMENTS GOTO 
Z        KENT WILLIAMS
Z        NORAND INC.
Z        550 2nd ST. S.E.
Z        Cedar Rapids Iowa 52401
Z        (319) 338-6053 (HOME VOICE)
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
STUNKYFLUFF
set `sum cshell.doc`
if test 25555 != $1
then
echo cshell.doc: Checksum error. Is: $1, should be: 25555.
fi
#
#
echo Extracting ctlbrk.asm:
sed 's/^Z//' >ctlbrk.asm <<\STUNKYFLUFF
Z; Copyright (C) 1985 by Manx Software Systems, Inc.
Z; :ts=8
Z	include lmacros.h
Z
Zdataseg	segment	word public 'data'
Z	extrn	_PSP_:word
Z	_brkvec	dw ?
Z		dw ?
Z	localstk	dw	20	dup(?)
Z	stktop	label	word
Z	savess	dw ?
Z	savesp	dw ?
Zdataseg	ends
Z
Zourds	dw	0
Z
Z	assume	ds:dataseg
Z;
Z	procdef	ctl_brk_setup
Z	mov	ourds,ds
Z	push	ds
Z	mov	ax,3523H	;get cntl-break (cntl-c) handler
Z	int	21H
Z	mov	_brkvec,bx
Z	mov	_brkvec+2,es
Z	mov	dx,offset brk_handler
Z	mov	ax,cs
Z	mov	ds,ax
Z	mov	ax,2523H	;set new cntl-break handler
Z	int	21H
Z	pop	ds
Z	pret
Z	pend	ctl_brk_setup
Z
Z	procdef	ctl_brk_restore
Z	push	ds
Z	mov	dx,_brkvec
Z	mov	bx,word ptr _brkvec+2
Z	mov	ds,bx
Z	mov	ax,2523H	;restore old cntl-break handler
Z	int	21H
Z	pop	ds
Z	pret
Z	pend	ctl_brk_restore
Z
Zbrk_handler proc far
Z	;save ds and address our data segment
Z	push	ds
Z	mov	ds,ourds
Z	;move to the local stack after saving dos stack
Z	push	ax
Z	mov	savess,ss
Z	mov	savesp,sp
Z	mov	ax,ds
Z	mov	ss,ax
Z	mov	sp,offset stktop
Z	;save registers
Z	push	bp
Z	push	bx
Z	push	cx
Z	push	dx
Z	push	si
Z	push	di
Z	push	es
Z	mov	ah,051H	;find the current psp
Z	int	21H
Z	cmp	bx,_PSP_	;is it our program segment?
Z	je	noabort
Z	;set carry flag
Z	mov	ax,0FFFFH	;set up to shift bit into carry
Z	rcr	ax,1
Z	jmp	short done
Znoabort:
Z	;clear carry flag
Z	or	ax,ax		;should clear carry
Zdone:
Z	pop	es
Z	pop	di
Z	pop	si
Z	pop	dx
Z	pop	cx
Z	pop	bx
Z	pop	bp
Z	mov	ax,savess
Z	mov	ss,ax
Z	mov	sp,savesp
Z	pop	ax
Z	pop	ds
Z	jc	abortend
Z	iret
Zabortend:
Z	ret
Zbrk_handler endp
Z	finish
Z	end
STUNKYFLUFF
set `sum ctlbrk.asm`
if test 52105 != $1
then
echo ctlbrk.asm: Checksum error. Is: $1, should be: 52105.
fi
#
#
echo Extracting doprog.c:
sed 's/^Z//' >doprog.c <<\STUNKYFLUFF
Zdo_prog(argc,argv)
Zchar *argv[];
Z{
Z	int result;
Z	if (666 == (result = fexecvp(argv[0],argv)))
Z	{
Z		invalid(argc,argv);
Z		perror("");
Z		return -1;
Z	}
Z	return result; 
Z}
STUNKYFLUFF
set `sum doprog.c`
if test 44858 != $1
then
echo doprog.c: Checksum error. Is: $1, should be: 44858.
fi
#
#
echo Extracting drive.c:
sed 's/^Z//' >drive.c <<\STUNKYFLUFF
Z#define NULL (void *)0
Zdrive(argc,argv)
Z	char *argv[];
Z{
Z	char *dir,*getcwd();
Z
Z	bdos(0xe,**argv - 'a');	/* select drive 0 */
Z	if (NULL == (dir = getcwd(NULL,64)))
Z		return -1;
Z	free(dir);
Z	return 0;
Z}
STUNKYFLUFF
set `sum drive.c`
if test 37068 != $1
then
echo drive.c: Checksum error. Is: $1, should be: 37068.
fi
#
#
echo Extracting dump2.c:
sed 's/^Z//' >dump2.c <<\STUNKYFLUFF
Z
Z/*  dump.c  (10/83)  Debug style dump of a file from any starting position.
Z*/
Z#include <stdio.h>
Z#include <ctype.h>
Z#include <signal.h>
Z#include <setjmp.h>
Z#define FAIL        1
Z#define SUCCESS     0
Z#define TRUE      	(1)
Z#define FALSE       0
Z#define FOREVER     for (;;)
Z#define PAUSE       if (getch()=='\0') getch();
Z#define STDIN       0
Z#define STDOUT      1
Z#define STDERR      2
Zchar *dumpusage[] =
Z{
Z  "Usage: dump filespec [block [page]] | [segment:[offset]] [count]\r\n",
Z  "Where a block is 64K bytes and a page is 256 bytes.\r\n",
Z  "Segment:offset are standard 8086 notation in hexadecimal.\r\n",
Z  "Count is the number of bytes to dump in decimal.\r\n",
Z  NULL
Z};
Zchar *index();		/* suppress warning about conversion to int */
Z#define BUFSIZE 512
Ztypedef unsigned    ushort;
Z
Zstatic int _fmode = 0x8000;            /* Lattice 'c' - forces binary I/O */
Zextern short errno;             /* DOS 2.0 error number */
Zlong lseek();
Z
Zstatic char   buffer[BUFSIZE];         /* input buffer */
Zstatic ushort block = 0;               /* block number ( 64k bytes/block ) */
Zstatic ushort page = 0;                /* page number ( 256 bytes/page ) */
Zstatic ushort segment = 0;
Zstatic ushort offset = 0;
Zstatic long   filpos = 0;              /* beginning file position */
Zstatic long   count = 0x7FFFFFFFL;     /* number of bytes to dump */
Z
Zvoid ohw(),ohb(),onib(),abort();
Z
Zstatic jmp_buf env;
Zvoid (*signal())();
Zstatic void (*oldsig)();
Zstatic onintr()
Z{
Z	signal(SIGINT,SIG_IGN);	/* disable interrupts from kbd */
Z	longjmp(env,-1);
Z}
Z
Z#ifdef MAIN
Zmain
Z#else
Zdump
Z#endif
Z(argc,argv)                 /* DUMP ENTRY */
Zint  argc;
Zchar *argv[];
Z{
Z   char c;
Z   ushort i, numin, tot, file, cfrom;
Z   char *flag = 0;
Z   char *index();
Z   oldsig=signal(SIGINT,onintr);
Z   if (-1 == setjmp(env))
Z   {
Z   		close(file);
Z		write(2,"Interrupted\r\n",13);
Z		signal(SIGINT,oldsig);
Z		return -1;
Z   }
Z   if (argc < 2)
Z   {
Z   		char **u = (char **) dumpusage;
Z		while(*u)
Z		{
Z			write (2,*u,strlen(*u));
Z			++u;
Z		}
Z		return -1;
Z   }
Z   if ((file = open( argv[1], 0 )) == -1)
Z      abort( "cannot open", argv[1], errno );
Z
Z   if (argc > 2) {
Z      if ((flag = index( argv[2], ':' )) != NULL) {
Z         i = stch_i( argv[2], &segment );
Z         stch_i( argv[2]+i+1, &offset );
Z      }
Z      if (sscanf( argv[2], "%d", &block ) != 1)
Z         abort( "invalid block", argv[2], 0 );
Z   }
Z   if (argc > 3)
Z      if (sscanf( argv[3], "%d", &page ) != 1)
Z         abort( "invalid page", argv[3], 0 );
Z
Z   if ( flag ) {
Z      filpos = (long)segment*16L + (long)offset;
Z      tot = offset;
Z   }
Z   else {
Z      filpos = (block * 65536L) + (page * 256);
Z      tot = page * 256;
Z      segment = block * 4096;
Z   }
Z
Z   if (lseek( file, filpos, 0 ) == -1L)
Z      abort( "positioning to", argv[2], errno );
Z
Z   if (argc > 4)
Z      if (sscanf( argv[4], "%ld", &count ) != 1)
Z         abort( "invalid count", argv[4], 0 );
Z
Z
Z   do {                                    /* read & dump BUFSIZE bytes */
Z      numin = read( file, buffer, BUFSIZE );
Z      if (numin == -1)
Z         abort( "cannot read", argv[1], errno );
Z      cfrom=0;
Z      while (cfrom < numin) {
Z
Z         ohw(segment);                     /* print offset in hex */
Z         putchar(':');
Z         ohw(cfrom+tot);
Z         putchar(' ');
Z
Z         for (i=0; i < 16; i++) {          /* print 16 bytes in hex */
Z            putchar(' ');
Z            ohb(buffer[cfrom++]);
Z         }
Z
Z         putchar(' '); putchar(' '); putchar(' ');
Z
Z         cfrom -= 16;
Z         for (i=0; i < 16; i++) {          /* print 16 bytes in ASCII */
Z            c = buffer[cfrom] & 0x7f;
Z            if ( isprint(c) )              /* if printable character */
Z               putchar(c);
Z            else
Z               putchar('.');               /* else print period */
Z            cfrom++;
Z         }
Z
Z         putchar('\r'); putchar('\n');     /* print CR/LF */
Z
Z         if ((count -= 16) <= 0)             /* is count exhausted? */
Z            exit(0);
Z      }                                    /* end of while */
Z      tot += numin;
Z      if ( tot == 0 )
Z         segment += 4096;
Z   }                                       /* end of do */
Z   while (numin == BUFSIZE);
Z	signal(SIGINT,oldsig);					/* restore signal */
Z	return 0;
Z}                                          /* end of main */
Z
Zstatic void ohw(wrd)                        /*      print a word in hex     */
Zushort wrd;
Z{
Z   ohb( wrd>>8 );
Z   ohb( wrd );
Z}
Z
Zstatic void ohb(byt)                        /*      print a byte in hex     */
Zchar byt;
Z{
Z   onib( byt>>4 );
Z   onib( byt );
Z}
Z
Zstatic void onib(nib)            /*      print a nibble as a hex character   */
Zchar nib;
Z{
Z   nib &= 15;
Z   putchar((nib >= 10) ? nib-10+'A': nib+'0');
Z}
Z
Zstatic void abort( msg1 ,msg2 ,errno)     /*  print error msg1, msg2, and nbr */
Zchar *msg1,*msg2;                  /*   Does not close files.  */
Zshort errno;
Z{
Z   char stemp[10];
Z
Z   write( STDERR, "ERR: ", 5 );
Z   if (msg1)
Z      write( STDERR, msg1, strlen(msg1) );
Z   if (msg2)
Z      write( STDERR, " ", 1 );
Z      write( STDERR, msg2, strlen(msg2) );
Z   if (errno)   {
Z      sprintf( stemp," #%d", errno );
Z      write( STDERR, stemp, strlen(stemp) );
Z   }
Z   write( STDERR, "\r\n", 2 );
Z   longjmp(env,-1);
Z}
Z/** END DUMP **/
Z
Z#define BDOS_IN   7     /* input function for "getch" */
Z#define BDOS_OUT  6     /* output function for "putch" */
Z#define BDOS_CKS  11    /* check keyboard status for "kbhit" */
Z#define BDOS_BKI  10    /* buffered keyboardd input for "cgets" */
Z#define BDOS_PRT  9     /* print string for "cputs" */
Z
Zstatic char pushback;   /* character save for "ungetch" */
Z
Zstatic getch()
Z{
Zint c;
Z
Zif (pushback != '\0')
Z   {                    /* character was pushed back */
Z   c = pushback;
Z   pushback = '\0';
Z   return(c);
Z   }
Zreturn(bdos(BDOS_IN, 0xFF) & 127);
Z}
Zstatic putch(c)
Zchar c;
Z{
Zbdos(BDOS_OUT, c&127);
Zreturn(c);
Z}
Zstatic ungetch(c)
Zchar c;
Z{
Z
Zif (pushback != '\0') return(-1);
Zpushback = c;
Zreturn(c);
Z}
Zstatic char *cgets(s)
Zchar *s;
Z{
Zchar *p;
Z
Zif (*s == 0) *s = 250;          /* do not allow zero byte count */
Zbdos(BDOS_BKI, s);
Zp = s+2;
Zp[s[1]] = '\0';                 /* set terminating byte */
Zreturn(p);
Z}
Zstatic cputs(s)
Zchar *s;
Z{
Zchar *p;
Z
Zfor (p = s; *p != '\0'; p++) ;          /* find string terminator */
Z*p = '$';
Zbdos(BDOS_PRT, s);
Z*p = '\0';
Zreturn;
Z}
Z
Z
Zstatic int stch_i(p,r)
Z	char *p;
Z	int	*r;
Z{
Z	int count;
Z	int acc;
Z	int hdtoi();
Z	count = 0;
Z	*r = 0;
Z	while (-1 != (acc = hdtoi(*p++)))
Z	{
Z		++count;
Z		*r = (*r << 4) | acc;
Z	}
Z	return count;
Z}
Z
Zstatic hdtoi(c)
Z	char c;
Z{
Z	c = toupper(c);
Z	if (!isxdigit(c)) 
Z		return -1;
Z	if (isdigit(c))
Z		return (c - '0');
Z	return (c - 'A' + 10);
Z}
STUNKYFLUFF
set `sum dump2.c`
if test 53530 != $1
then
echo dump2.c: Checksum error. Is: $1, should be: 53530.
fi
#
#
echo Extracting echo.c:
sed 's/^Z//' >echo.c <<\STUNKYFLUFF
Z
Zecho(argc,argv)
Z	char *argv[];
Z{
Z	register int i;
Z	for (i = 1; i < argc;i++)
Z	{
Z		write(2,argv[i],strlen(argv[i]));
Z		if (i < argc-1)
Z			write(2," ",1);
Z	}
Z	crlf();
Z	return 0;
Z}
STUNKYFLUFF
set `sum echo.c`
if test 29675 != $1
then
echo echo.c: Checksum error. Is: $1, should be: 29675.
fi
#
#
echo Extracting env.c:
sed 's/^Z//' >env.c <<\STUNKYFLUFF
Z#include <stdio.h>
Z
Z#define ENVSIZE 4000
Zextern int _PSP;
Zvoid *calloc();
Zchar *environment=NULL, *str_upper();
Zint env_paragraph;
Zchar *next_env;
Z#define envlimit(a) &a[ENVSIZE-1]
Z
Z#ifdef MAIN
Zmain
Z#else
Zset
Z#endif
Z(argc,argv)
Z	char *argv[];
Z{
Z	if (!environment)
Z		init_env();
Z	if (argc == 1)
Z	{
Z		show_env();
Z		return 0;
Z	}
Z	while(--argc)
Z	{
Z		add_env(str_upper(*(++argv)));
Z	}
Z	return 0;
Z}
Z
Zchar *
Zstr_upper(c)
Z	register char *c;
Z{
Z	register char *save = c;
Z	while(*c)
Z	{
Z		*c = toupper(*c);
Z		c++;
Z	}
Z	return save;
Z}
Z
Zchar *
Zstr_lower(c)
Z	register char *c;
Z{
Z	register char *save = c;
Z	while(*c)
Z	{
Z		*c = tolower(*c);
Z		c++;
Z	}
Z	return save;
Z}
Zinit_env()
Z{
Z	extern unsigned _dsval;	/* current data segment register value */
Z	long fudgefactor;
Z	register int c;
Z	unsigned envseg;
Z	unsigned offset = 0;
Z	envseg = peekw(0x2c,_PSP);
Z	environment = calloc(1,ENVSIZE+16);
Z	fudgefactor = (long)_dsval << 4;	/* convert to absolute paragraph */
Z	fudgefactor += (unsigned)environment + 16;
Z	fudgefactor &= 0xFFFF0L;
Z	env_paragraph = (int)((fudgefactor >>4) & 0xFFFF);
Z	environment = (char *) (fudgefactor - (long)(_dsval << 4));
Z	next_env = environment;
Z	while (c = peekb(offset,envseg))
Z	{
Z		while (c = peekb(offset++,envseg))
Z		{
Z			*next_env++ = c;
Z		}
Z		*next_env++ = '\0';
Z	}
Z}
Z
Zshow_env()
Z{
Z	register char *env;
Z	char c;
Z	for (env = environment;*env;)
Z	{
Z		while (c = *env++)
Z			write(1,&c,1);
Z		crlf();
Z	}
Z}
Z
Zstatic char *enverr = "No more environment space\r\n";
Zstatic char *enverr2 = "Improper environment string format!!\r\n";
Z
Zadd_env(string)
Z	char *string;
Z
Z{
Z	char *env_copy, *new, *index();
Z	char *old = environment;
Z	char *name_end,*new_name_end;
Z	int added = 0;
Z	int namelen;
Z
Z	if (NULL == (env_copy = new = calloc(1,ENVSIZE)))
Z	{
Z		write(2,enverr,strlen(enverr));
Z		return -1;
Z	}
Z
Z	while (*old)
Z	{
Z		if ( NULL == (name_end = index(old,'=')) || 
Z			NULL == (new_name_end = index(string,'=')) 
Z		)
Z		{
Z			write(2,enverr2,strlen(enverr2));
Z			free(env_copy);
Z			return -1;
Z		}
Z		namelen = (int)(name_end - old);
Z		if (!strncmp(old,string,namelen))
Z		{
Z			if (new_name_end[1])
Z			{
Z				/* if we don't have a string of the form name= */
Z				/* copy new string instead of old string */
Z				strcpy(new,string);
Z			}
Z			else
Z			/* if we have a set name= with no string then we want
Z			   to remove the string from the environment
Z			 */
Z				;
Z			added++;
Z		}
Z		else
Z		{
Z			strcpy(new,old);
Z		}
Z		new = &new[strlen(new)+1];
Z		old = &old[strlen(old)+1];
Z		if (new >= envlimit(new))
Z		{
Z			write(2,enverr,strlen(enverr));
Z			free(env_copy);
Z			return -1;
Z		}
Z	}
Z	if (!added)
Z	{
Z		strcpy(new,string);
Z	}
Z	new = &new[strlen(new)+1];
Z	/* copy the copy back to the environment */
Z	movmem(env_copy,environment,(int)(new-env_copy)+2);
Z	free(env_copy);
Z	return 0;
Z}
STUNKYFLUFF
set `sum env.c`
if test 56918 != $1
then
echo env.c: Checksum error. Is: $1, should be: 56918.
fi
#
#
echo Extracting fexec.asm:
sed 's/^Z//' >fexec.asm <<\STUNKYFLUFF
Z; Copyright (C) 1984 by Manx Software Systems
Z; :ts=8
Z	include lmacros.h
Zdataseg segment para public 'data'
Zparam	equ	this word
Zenv	dw	?
Zcline	dw	?,?
Zfcb1	dw	?,?
Zfcb2	dw	?,?
Z	extrn	errno_:word
Zdataseg	ends
Z	assume	ds:dataseg
Zsave_ss	dw	0
Zsave_sp	dw	0
Z	procdef	fexec,<<filname,ptr>,<enva,word>,<clinea,ptr>,<fcb1a,ptr>,<fcb2a,ptr>>
Z;			char *fexec(name,env,cline,fcb1,fcb2)
Z;
Z	push	si
Z	push	di
Z	pushf
Z	push	[030H]
Z	push	[02EH]
Z	push	ds
Z	push	es
Z	mov	cs:save_ss,ss
Z	mov	cs:save_sp,sp
Z;
Z;	set up parameter block for exec call
Z;
Z	mov	ax,enva
Z	mov	env,ax
Zifndef LONGPTR
Z	mov	ax,ds
Z	mov	es,ax
Zendif
Z	ldptr	ax,clinea,es
Z	mov	cline,ax
Z	mov	cline+2,es
Z	ldptr	ax,fcb1a,es
Z	mov	fcb1,ax
Z	mov	fcb1+2,es
Z	ldptr	ax,fcb2a,es
Z	mov	fcb2,ax
Z	mov	fcb2+2,es
Z;
Z	mov	ax,ds
Z	mov	es,ax
Z	mov	bx,offset param
Z	ldptr	dx,filname,ds		;name of file to exec
Z	mov	ax,04b00H
Z	int	21h
Z	mov	ss,cs:save_ss
Z	mov	sp,cs:save_sp
Z	pop	es
Z	pop	ds
Z	jnc	noerror
Z	mov	errno_,ax
Z	mov	ax,666
Z	jmp	short done
Znoerror:
Z	sub	ax,ax
Zdone:
Z	pop	[02EH]
Z	pop	[030H]
Z	popf
Z	pop	di
Z	pop	si
Z	pret
Z	pend	fexec
Z	finish
Z	end
STUNKYFLUFF
set `sum fexec.asm`
if test 35466 != $1
then
echo fexec.asm: Checksum error. Is: $1, should be: 35466.
fi
#
#
echo Extracting fexecv.c:
sed 's/^Z//' >fexecv.c <<\STUNKYFLUFF
Z#ifdef DEBUG
Z#ifndef FILE
Z#include <stdio.h>
Z#endif
Z#include <ctype.h>
Z#include <debug.h>
Z#endif
Z
Z
Z/* Copyright (C) 1983, 1984 by Manx Software Systems */
Z/* modified by kent williams to employ environment managed in env.c */
Zextern int env_paragraph;
Z
Zfexecv(path, argv)
Zchar *path, **argv;
Z{
Z	register char *cp, *xp;
Z	int i;
Z	char buffer[258];
Z	char fcb1[16], fcb2[16];
Z
Z	cp = buffer+1;
Z	i = 1;
Z	if (*argv) {
Z		++argv;			/* skip arg0, used for unix (tm) compatibility */
Z		while (xp = *argv++) {
Z			if (i == 1)
Z				fcbinit(xp, fcb1);
Z			else if (i == 2)
Z				fcbinit(xp, fcb2);
Z			while (*xp) {
Z				if (cp >= buffer+256)
Z					goto done;
Z				*cp++ = *xp++;
Z			}
Z			*cp++ = ' ';
Z			++i;
Z		}
Z	}
Zdone:
Z	buffer[0] = cp - (buffer+2);
Z	/* terminate string */
Z	buffer[buffer[0]+1] = 0;
Z#ifdef DEBUG
Z		fprintf(stderr,"\nbuffer[0] = %d\n",buffer[0]);
Z		for (i = 1; buffer[i] ; i++)
Z		{
Z			if (isprint(buffer[i]))
Z				putchar(buffer[i]);
Z			else
Z				fprintf("buffer[%d] = %d\n",i,buffer[i]);
Z		}
Z		crlf();
Z#endif
Z	return fexec(path, env_paragraph, buffer, fcb1, fcb2);
Z}
Z
STUNKYFLUFF
set `sum fexecv.c`
if test 22589 != $1
then
echo fexecv.c: Checksum error. Is: $1, should be: 22589.
fi
#
#
echo Extracting fexecvp.c:
sed 's/^Z//' >fexecvp.c <<\STUNKYFLUFF
Zfexecvp(name, argv)
Zchar *name, **argv;
Z{
Z	register char *cp, *xp;
Z	int result;
Z	char *getenv(), path[64];
Z
Z	if (666 != (result = tryexec("", name, argv)))
Z		return result;
Z	if ((cp = getenv("PATH")) != 0) {
Z		while (*cp) {
Z			xp = path;
Z			while (*cp) {
Z				if (*cp == ';') {
Z					++cp;
Z					break;
Z				}
Z				*xp++ = *cp++;
Z			}
Z			*xp = 0;
Z			if (path[0] != 0)
Z				if (666 != (result = tryexec(path, name, argv)))
Z					return result;
Z		}
Z	}
Z	return 666;
Z}
Z
Zstatic
Ztryexec(dir, name, argv)
Zchar *dir, *name, **argv;
Z{
Z	char newname[64];
Z	register char *cp;
Z	char *rindex(),*index();
Z
Z	strcpy(newname, dir);
Z	if (((cp = index(newname, '/')) || (cp = index(newname, '\\')))
Z				&& *(cp+1) != '\0')
Z		strcat(newname, "/");
Z	strcat(newname, name);
Z	if (index(name, '.') == 0) {
Z		strcat(newname, ".com");
Z		if (666 != fexecv(newname, argv))
Z			return wait();
Z		strcpy(rindex(newname,'.'), ".exe");
Z	}
Z	if (666 != fexecv(newname, argv))
Z			return wait();
Z	return 666;
Z}
STUNKYFLUFF
set `sum fexecvp.c`
if test 44134 != $1
then
echo fexecvp.c: Checksum error. Is: $1, should be: 44134.
fi
#
#
echo Extracting fgrep.c:
sed 's/^Z//' >fgrep.c <<\STUNKYFLUFF
Z#include <stdio.h>
Z#include <fcntl.h>
Z
Z#include <signal.h>
Z#include <setjmp.h>
Z
Zvoid (*signal())();
Zvoid (*fgrepsig)();
Zjmp_buf fgrep_env;
Z
Zvoid fgrep_intr()
Z{
Z	/* restore old signal */
Z	signal(SIGINT,fgrepsig);
Z	/* jump to exit */
Z	longjmp(fgrep_env,-1);
Z}
Z
ZFILE *fopen(),*fdopen();
Z
Zchar *fgets();
Z
Zfgrep( argc, argv )
Zint	argc;
Zchar * argv[];
Z	{
Z	FILE *  fd;
Z	int	rc;
Z	char * pattern;
Z	/* handle interrupts */
Z	if (-1 == setjmp(fgrep_env))
Z	{
Z		static char *intmsg = "Interrupted\r\n";
Z		write(2,intmsg,strlen(intmsg));
Z		fclose(fd);
Z		return -1;
Z	}
Z	/* set signal catcher */
Z	fgrepsig= signal(SIGINT,fgrep_intr);
Z	while( --argc )
Z		{
Z		if( (*++argv)[0] == '-' )
Z			switch( (*argv)[1] )
Z				{
Z				default:
Z					fprintf( stderr, "invalid argument %s\n", *argv );
Z					return(1);
Z				}
Z		else
Z			break;
Z		}
Z
Z	if( argc == 0 )
Z		{
Z		fprintf( stderr, "usage: fgrep pattern [file ...]\n" );
Z		return(1);
Z		}
Z
Z	pattern = *argv++;
Z	argc--;
Z
Z	rc = 0;
Z	if( argc == 0 )
Z		{
Z		fd = fdopen(0,"r");
Z		rc = _fgrep( NULL, pattern, fd);
Z		fclose(fd);
Z		return( 0 );
Z		}
Z	else
Z	while( argc-- )
Z		{
Z
Z		if( (fd = fopen( *argv, "r" )) == NULL )
Z			fprintf( stderr, "couldn't open %s\n", *argv );
Z		else
Z			{
Z			rc |= _fgrep( *argv, pattern, fd );
Z			fclose( fd );
Z			}
Z		argv++;
Z
Z		}
Z
Z	return( !rc );
Z	signal(SIGINT,fgrepsig);
Z	}
Z
Z
Z_fgrep( file, pattern, fd )
Zchar	* file;
Zchar	* pattern;
ZFILE *	fd;
Z	{
Z	char	line[BUFSIZ];
Z	int		rc;
Z	int		linenumber = 1;
Z	rc = 0;
Z	while( fgets( line, sizeof(line), fd ) != NULL )
Z	{
Z		if( rc = match( pattern, line ) )
Z			printf( "%s %d: %s", (file) ? file : "stdin", linenumber, line );
Z		linenumber++;
Z	}
Z	return( rc );
Z
Z	}
Z
Zmatch( pattern, line )
Zregister char	* pattern;
Zchar	* line;
Z	{
Z	/*  not a great algorithm  */
Z	register char * ptr;
Z	char	* end;
Z	int	plen = strlen(pattern);
Z	int llen = strlen(line);
Z
Z	if( plen > llen )
Z		return( 0 );
Z
Z	end = line+(llen-plen);
Z
Z	for( ptr=line; ptr < end; ptr++ )
Z		{
Z		if( strncmp( pattern, ptr, plen ) == 0 )
Z			return( 1 );
Z		}
Z
Z	return( 0 );
Z	}
STUNKYFLUFF
set `sum fgrep.c`
if test 15656 != $1
then
echo fgrep.c: Checksum error. Is: $1, should be: 15656.
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