AUSAM/source/S/xargs.c
#define FALSE 0
#define TRUE 1
#define MAXSBUF 255
#define MAXIBUF 512
#define MAXINSERTS 5
#define BUFSIZE 570
#define MAXARGS 255
char *arglist[MAXARGS+1];
char argbuf[BUFSIZE+1];
char *next argbuf;
char *lastarg "";
char **ARGV arglist;
char *LEOF "_";
char *INSPAT "{}";
struct inserts
{
char **p_ARGV; /* where to put newarg ptr in arg list */
char *p_skel; /* ptr to arg template */
} saveargv[MAXINSERTS];
char ins_buf[MAXIBUF];
char *p_ibuf;
int PROMPT -1;
int BUFLIM 470;
int N_ARGS 0;
int N_args 0;
int MORE TRUE;
int PER_LINE FALSE;
int ERR FALSE;
int OK TRUE;
int LEGAL FALSE;
int TRACE FALSE;
int INSERT FALSE;
int linesize 0;
int ibufsize;
#define copy(srce, dest) strcat(dest, srce)
#define equal(s1, s2) !strcmp(s1, s2)
main(argc, argv)
int argc;
char **argv;
{
char *cmdname, *initbuf, **initlist;
int initsize;
register int j, n_inserts;
register struct inserts *psave;
/* initialization */
argc--;
argv++;
n_inserts = 0;
psave = saveargv;
/* look for flag arguments */
while((*argv)[0] == '-')
{
switch((*argv)[1])
{
case 'x':
LEGAL = TRUE;
break;
case 'l':
PER_LINE = LEGAL = TRUE;
N_ARGS = 0;
INSERT = FALSE;
break;
case 'i':
INSERT = PER_LINE = LEGAL = TRUE;
N_ARGS = 0;
if((*argv)[2])
{
INSPAT = &(*argv)[2];
}
break;
case 't':
TRACE = TRUE;
break;
case 'e':
LEOF = &(*argv)[2];
break;
case 's':
BUFLIM = atoi(&(*argv)[2]);
if(BUFLIM > 470 || BUFLIM <= 0)
{
ermsg("0 < max-line-size <= 470: ", *argv, "\n", 0);
OK = FALSE;
}
break;
case 'n':
if((N_ARGS = atoi(&(*argv)[2])) <= 0)
{
ermsg("#args must be positive int: ", *argv, "\n", 0);
OK = FALSE;
}
else
{
if(PER_LINE)
LEGAL = FALSE;
INSERT = PER_LINE = FALSE;
}
break;
case 'p':
if((PROMPT = open("/dev/tty", 0)) == -1)
{
ermsg("can't read from tty for -p\n", 0);
OK = FALSE;
}
else
TRACE = TRUE;
break;
default:
ermsg("unknown option: ", *argv, "\n", 0);
OK = FALSE;
break;
}
argv++;
if(--argc < 1)
break;
}
if(!OK)
ERR = TRUE;
/* pick up command name */
if(argc == 0)
{
cmdname = "/bin/echo";
*ARGV++ = addarg(cmdname);
}
else
cmdname = *argv;
/* pick up args on command line */
while(OK && argc--)
{
if(INSERT && !ERR)
{
if(index(*argv, INSPAT) != -1)
{
if(++n_inserts > MAXINSERTS)
{
ermsg("too many args with ", INSPAT, "\n", 0);
ERR = TRUE;
OK = FALSE;
}
psave->p_ARGV = ARGV;
(psave++)->p_skel = *argv;
}
}
*ARGV++ = addarg(*argv++);
}
/* pick up args from standard input */
initbuf = next;
initlist = ARGV;
initsize = linesize;
while(OK && MORE)
{
next = initbuf;
ARGV = initlist;
linesize = initsize;
if(*lastarg)
*ARGV++ = addarg(lastarg);
while((*ARGV++ = getarg()) && OK);
/* insert arg if requested */
if(INSERT)
{
p_ibuf = ins_buf;
ARGV--;
j = ibufsize = 0;
for(psave = saveargv; ++j <= n_inserts; ++psave)
{
addibuf(psave);
if(ERR)
break;
}
}
*ARGV = 0;
/* exec command */
if(!ERR)
{
if(!MORE && (PER_LINE|(N_ARGS && (N_args == 0))))
exit(0);
OK = TRUE;
j = TRACE?echoargs():TRUE;
if(j)
{
if(lcall(cmdname, arglist) != -1)
continue;
ermsg(cmdname, " not executed or returned -1\n", 0);
OK = FALSE;
}
}
}
if(OK)
exit(0);
else
exit(1);
}
checklen(arg)
char *arg;
{
register int oklen;
oklen = TRUE;
if((linesize =+ strlen(arg)+1) > BUFLIM)
{
lastarg = arg;
if(N_ARGS)
N_args = 1;
oklen = OK = FALSE;
if(LEGAL)
{
ERR = TRUE;
ermsg("arg list too long\n", 0);
}
}
return(oklen?arg:0);
}
addarg(arg)
char *arg;
{
copy( arg, next);
arg = next;
next =+ strlen(arg)+1;
return(checklen(arg));
}
getarg()
{
register char c, c1, *arg;
while((c = getchr()) == ' ' || c == '\n' || c == '\t');
if(c == '\0')
{
MORE = FALSE;
return 0;
}
arg = next;
for(; ; c = getchr())
switch(c)
{
case '\t':
case ' ':
if(INSERT)
{
*next++ = c;
break;
}
case '\n':
case '\0':
*next++ = '\0';
if( equal(arg,LEOF))
{
MORE = FALSE;
if(c == ' ' || c == '\t')
while(c = getchr())
if(c == '\n')
break;
return 0;
}
else
{
if((PER_LINE && (c == '\n')) || (N_ARGS && (++N_args >= N_ARGS)))
{
N_args = 0;
lastarg = "";
OK = FALSE;
}
return(checklen(arg));
}
case '\\':
*next++ = getchr();
break;
case '"':
case '\'':
while((c1 = getchr()) != c)
{
if(c1 == '\0' || c1 == '\n')
{
*next++ = '\0';
ermsg("missing quote?: ", arg, "\n", 0);
OK = FALSE;
ERR = TRUE;
return(0);
}
*next++ = c1;
}
break;
default:
*next++ = c;
break;
}
}
ermsg(messages)
char *messages;
{
register char **pmsg;
pmsg = (&messages)-1;
while(*++pmsg)
prints(2, *pmsg);
}
echoargs()
{
register char **anarg;
char yesorno[1], junk[1];
register int j;
anarg = arglist-1;
while(*++anarg)
{
prints(2, *anarg);
prints(2, " ");
}
if(PROMPT == -1)
{
prints(2, "\n");
return TRUE;
}
prints(2, "?...");
if(read(PROMPT, yesorno, 1) == 0)
exit(0);
if(yesorno[0] == '\n')
return FALSE;
while(((j = read(PROMPT, junk, 1)) == 1) && (junk[0] != '\n'));
if(j == 0)
exit(0);
return(yesorno[0] == 'y');
}
insert(pattern, subst)
char *pattern, *subst;
{
char buffer[MAXSBUF+1];
int len, ipatlen;
register char *pat;
register char *bufend;
register char *pbuf;
len = strlen(subst);
ipatlen = strlen(INSPAT)-1;
pat = pattern-1;
pbuf = buffer;
bufend = &buffer[MAXSBUF];
while(*++pat)
{
if(index(pat, INSPAT) == 0)
{
if(pbuf+len >= bufend)
break;
else
{
copy( subst, pbuf);
pat =+ ipatlen;
pbuf =+ len;
}
}
else
{
*pbuf++ = *pat;
if(pbuf >= bufend)
break;
}
}
if(!*pat)
{
*pbuf = '\0';
return(&buffer);
}
else
{
ermsg("max arg size with insertion via ", INSPAT, "'s exceeded\n", 0);
ERR = TRUE;
OK = FALSE;
return 0;
}
}
addibuf(p)
struct inserts *p;
{
register char *newarg, *skel, *sub;
int l;
skel = p->p_skel;
sub = *ARGV;
linesize =- strlen(skel)+1;
newarg = insert(skel, sub);
if(checklen(newarg))
{
if((ibufsize =+ (l = strlen(newarg)+1)) > MAXIBUF)
{
ermsg("insert-buffer overflow\n", 0);
ERR = TRUE;
OK = FALSE;
}
copy(newarg, p_ibuf);
*(p->p_ARGV) = p_ibuf;
p_ibuf =+ l;
}
}
getchr()
{
char c;
if(read(0, &c, 1) == 1)
return(c);
return(0);
}
int lcall(sub, subargs)
char *sub, **subargs;
{
int retcode;
switch(fork())
{
default:
if(wait(&retcode) == -1 || retcode<<8 != 0)
return -1;
return(retcode>>8);
case 0:
execc(sub, subargs);
exit(-1);
case -1:
return(-1);
}
}
/*
If `s2' is a substring of `s1' return the offset of the first
occurrence of `s2' in `s1',
else return -1.
*/
index(as1, as2)
char *as1, *as2;
{
register char *s1, *s2, c;
int offset;
s1 = as1;
s2 = as2;
c = *s2;
while(*s1)
if(*s1++ == c)
{
offset = s1-as1-1;
s2++;
while((c = *s2++) == *s1++ && c);
if(c == 0)
return(offset);
s1 = offset+as1+1;
s2 = as2;
c = *s2;
}
return(-1);
}
/*
Concatenate strings.
cat(destination,source1,source2,...,sourcen,0);
returns destination.
*/
cat(dest, source)
char *dest, *source;
{
register char *d, *s, **sp;
d = dest;
for(sp = &source; s = *sp; sp++)
{
while(*d++ = *s++);
d--;
}
return(dest);
}