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