home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
100-199
/
ff174.lzh
/
Sh
/
sh.c
< prev
Wrap
C/C++ Source or Header
|
1989-02-04
|
8KB
|
407 lines
/* sh - JimG's version of sh to unshar files */
char *help = "\
Usage: sh [-v(012)] [-s(01)] [-o(01)] [filename]\n\
-v = verbosity\n\
0 = print nothing\n\
1 = print anything not understood\n\
2 = echo commands as they are executed\n\
-s = safety\n\
1 = exit when something is not understood\n";
char *help2 = "\
-o = overwrite\n\
1 = don't overwrite existing files\n\
filename\n\
read shar file from here (or stdin if missing)\n";
#define NDEBUG
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define ST_CMDLINE 1
#define ST_CAT 2
#define ST_SED 3
#define TST_OUT 1
#define TST_QUOTE 2
#define TST_ALPHA 3
#define TST_DIR 4
#define BUFSIZE 161
char buf1[BUFSIZE], buf2[BUFSIZE];
char *buff1end = buf1 + BUFSIZE;
unsigned short int verbosity = 1;
unsigned short int safety = 0;
unsigned short int overwrite = 1;
FILE *fopen(char*,char*);
void sh(FILE*);
int tokenize(char**,int,char*);
void bumpstr(char*);
void ind_error(char**,int);
void fileparse(char**,int,char*,FILE**);
int fillbuffer(char*,int,FILE*);
int match(char*,char*);
void ptokens(char**,int,FILE*);
int
fillbuffer(buf,len,fp) /* This will read up to len-1 characters */
char *buf;
int len;
FILE *fp;
{
register int i, c;
for (i=1; i<len; i++) {
c = getc(fp);
if (c == EOF) break;
*(buf++) = c;
if (c == '\n') break;
}
*buf = 0;
return (c);
}
main(argc,argv)
int argc;
char *argv[];
{
register FILE *fp;
register char *s;
while ((--argc > 0) && ((*++argv)[0] == '-'))
for (s = argv[0]+1; *s != '\0'; s++)
switch (*s) {
case 'v':
switch (s[1]) {
case '0':
case '1':
case '2':
verbosity = (*++s) - '0';
break;
default:
verbosity = 1;
break;
}
break;
case 's':
switch(s[1]) {
case '0':
case '1':
safety = (*++s) - '0';
break;
default:
safety = 1;
break;
}
break;
case 'o':
switch(s[1]) {
case '0':
case '1':
overwrite = (*++s) - '0';
break;
default:
overwrite = 1;
break;
}
break;
default:
fputs("sh: illegal option ",stderr);
putc(*s,stderr);
putc('\n',stderr);
exit(10);
break;
}
switch (argc) {
case 0: sh(stdin);
break;
case 1: fp = fopen(argv[0],"r");
if (fp == NULL) {
fputs("Error - can't open file: ",stderr);
fputs(argv[0],stderr);
putc('\n',stderr);
exit(10);
}
sh(fp);
fclose(fp);
break;
default:
fputs(help,stderr);
fputs(help2,stderr);
exit(5);
}
return (0);
}
int
match(pat,str)
register char *pat, *str;
{
while (*pat != '\0')
if (*pat++ != *str++) return (0);
return(1);
}
void
sh(fp)
FILE *fp;
{
int state = ST_CMDLINE;
int oldc, c, tcnt;
FILE *outfp;
char *tokens[20];
char schar;
oldc = '\n';
while ((c = fillbuffer(buf1, BUFSIZE, fp)) != EOF ) {
switch (state) {
case ST_CMDLINE:
if (oldc != '\n') break;
if (*buf1 == '#') break;
tcnt = tokenize(tokens, 20, buf1);
if (tcnt == 0) break;
if (strcmp(tokens[0],"echo") == 0) {
ptokens(tokens+1,tcnt-1,stdout);
} else if (strcmp(tokens[0],"cat") == 0) {
fileparse(tokens,tcnt,buf2,&outfp);
if (*buf2) {
state = ST_CAT;
if (verbosity == 2) {
fputs("I am executing: ",stdout);
ptokens(tokens,tcnt,stdout);
}
} else if (outfp != stdout) fclose(outfp);
} else if (strcmp(tokens[0],"sed") == 0) {
fileparse(tokens,tcnt,buf2,&outfp);
if (*buf2) {
if (verbosity == 2) {
fputs("I am executing: ",stdout);
ptokens(tokens,tcnt,stdout);
}
if ((tokens[1][0] == 's') &&
(tokens[1][1] == tokens[1][4]) &&
(tokens[1][2] == '^') &&
(tokens[1][5] == tokens[1][1])) {
schar = tokens[1][3];
state = ST_SED;
} else {
fputs("Warning -- unknown sed option\n",stderr);
fputs(tokens[1],stderr);
fputs("\nI am treating it as a 'cat'\n",stderr);
fflush(stderr);
state = ST_CAT;
}
} else if (outfp != stdout) fclose(outfp);
} else if (strcmp(tokens[0], "exit") == 0) {
return;
} else {
if (verbosity > 0) {
/* fputs("I don't understand and am ignoring:\n",stdout);*/
fputs("Don't understand: ",stdout);
ptokens(tokens,tcnt,stdout);
}
if (safety == 1) exit(5);
}
break;
case ST_CAT:
if ((oldc == '\n') && (match(buf2,buf1))) {
state = ST_CMDLINE;
if (outfp != stdout) fclose(outfp);
} else fputs(buf1,outfp);
break;
case ST_SED:
if ((oldc == '\n') && (match(buf2,buf1))) {
state = ST_CMDLINE;
if (outfp != stdout) fclose(outfp);
} else if ((oldc == '\n') && (*buf1 == schar))
fputs(buf1+1,outfp);
else fputs(buf1,outfp);
break;
default:
fputs("\nInternal Error -- unknown state!\n",stderr);
exit(20);
}
oldc = c;
}
}
void
ptokens(tokens, size, fp)
char *tokens[];
int size;
FILE *fp;
{
register int i;
for (i = 0; i < (size - 1); i++) {
fputs(tokens[i],fp);
putc(' ',fp);
}
if (size > 0) fputs(tokens[size - 1],fp);
putc('\n',fp);
fflush(fp);
}
int
tokenize(tokens, tsize, buf)
char *tokens[];
int tsize;
char *buf;
{
register char c;
char quote;
int tcnt;
char *tbuf;
int state;
tcnt = 0;
state = TST_OUT;
for (; ((c = *buf) != NULL); buf++) {
switch (state) {
case TST_OUT:
switch (c) {
case ' ':
case '\t':
case '\n':
break;
case '\'':
case '"':
case '`':
quote = c;
state = TST_QUOTE;
if (tcnt >= tsize) return(tsize);
tokens[tcnt++] = tbuf = (buf + 1);
tbuf++;
break;
case '<':
case '>':
state = TST_DIR;
if (tcnt >= tsize) return(tsize);
tokens[tcnt++] = tbuf = buf;
tbuf++;
break;
case '\\':
buf++;
default:
state = TST_ALPHA;
if (tcnt >= tsize) return(tsize);
tokens[tcnt++] = tbuf = buf;
tbuf++;
break;
} /* end of switch (c) */
break;
case TST_QUOTE:
if (c == quote) {
*buf = 0;
state = TST_OUT;
} else {
/* *tbuf++ = c; */ /* Currently no-op */
}
break;
case TST_DIR:
if ((c != '>') && (c != '<')) {
if ((c != ' ') &&
(c != '\t') &&
(c != '\n')) bumpstr(buf);
*buf = 0;
state = TST_OUT;
} else {
/* *tbuf++ = c; */ /* Currently no-op */
}
break;
case TST_ALPHA:
if ((c == ' ') ||
(c == '\t') ||
(c == '\n')) {
*tbuf = 0;
state = TST_OUT;
} else if (c != '\\') {
*tbuf++ = c;
/* *tbuf++ = c; */ /* Currently no-op */
}
break;
} /* end switch (state) */
}
return (tcnt);
}
void
bumpstr(buff) /* buff has to be a pointer in buf1 !!!!! */
register char *buff;
{
register char c1, c2;
assert(((buff >= buf1) && (buff < buff1end)));
c1 = *buff++;
while (buff != buff1end) {
c2 = *buff;
*buff++ = c1;
if ((buff == buff1end) || (c1 == 0)) break;
c1 = *buff;
*buff++ = c2;
if (c2 == 0) break;
}
}
void
ind_error(tokens, tcnt)
char *tokens[];
int tcnt;
{
fputs("Error in indirection -- ignored\n",stderr);
ptokens(tokens,tcnt,stderr);
}
void
fileparse(tokens, tcnt, buf, outfp)
char *tokens[];
int tcnt;
char *buf;
FILE **outfp;
{
int i;
*buf = 0;
*outfp = NULL;
for (i=0; i < tcnt; i++) {
if (strcmp(">",tokens[i])==0) {
if (*outfp) ind_error(tokens,tcnt);
else if (++i == tcnt) ind_error(tokens,tcnt);
else {
if (overwrite == 1) {
*outfp = fopen(tokens[i],"r");
if (*outfp != NULL) {
fputs("Warning: will not overwrite: ",stderr);
fputs(tokens[i],stderr);
putc('\n',stderr);
fflush(stderr);
fclose(*outfp);
tokens[i]="nil:";
}
}
*outfp = fopen(tokens[i],"w");
if (*outfp == NULL) ind_error(tokens,tcnt);
}
} else if (strcmp(">>",tokens[i])==0) {
if (*outfp) ind_error(tokens,tcnt);
else if (++i == tcnt) ind_error(tokens,tcnt);
else {
*outfp = fopen(tokens[i],"a");
if (*outfp == NULL) ind_error(tokens,tcnt);
}
} else if (strcmp("<<",tokens[i])==0) {
if (*buf) ind_error(tokens,tcnt);
else if (++i == tcnt) ind_error(tokens,tcnt);
else strcpy(buf,tokens[i]);
}
} /* end for */
if (*outfp == NULL) *outfp = stdout;
}