C-Shell for the PC
michael regoli
mr at isrnix.UUCP
Thu Nov 21 09:00:43 AEST 1985
]:[
what follows is the source code for the recently-posted "shell.exe" to
net.micro.pc. there have been many requests for kent's sources...*so*
many, i had to post them.
this package is public-domain and was downloaded from a local rbbs.
for the UUENCODED(1C) version, please see the corrected version in
net.micro.pc. the documentation is there also.
the sources that follow have been successfully compiled using the AZTEC-C
compiler.
-- CHOP CHOP --
#########################################################
# #
# 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 _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,®s,®s);
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,®s,®s);
Z /* get attribute to see if it changed */
Z regs.ax = 0x4300;
Z regs.dx = (int)current;
Z regs.ds = _dsval;
Z sysint(0x21,®s,®s);
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 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 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