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