AUSAM/source/S/xargs.c

Compare this file to the similar file:
Show the results in this format:

#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);
}