xargs.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 484 行

C
484
字号
/* *			Copyright (c) 1988 by *		Digital Equipment Corporation, Maynard, MA *			All rights reserved. *								 *	This software is furnished under a license and may be used and *	copied  only  in accordance with the terms of such license and *	with the  inclusion  of  the  above  copyright  notice.   This *	software  or  any  other copies thereof may not be provided or *	otherwise made available to any other person.  No title to and *	ownership of the software is hereby transferred.		 *								 *	This software is  derived  from  software  received  from  the *	University    of   California,   Berkeley,   and   from   Bell *	Laboratories.  Use, duplication, or disclosure is  subject  to *	restrictions  under  license  agreements  with  University  of *	California and with AT&T.					 *								 *	The information in this software is subject to change  without *	notice  and should not be construed as a commitment by Digital *	Equipment Corporation.					 *								 *	Digital assumes no responsibility for the use  or  reliability *	of its software on equipment which is not supplied by Digital.*/#ifndef lintstatic	char *sccsid = "@(#)xargs.c	4.1	(ULTRIX)	7/17/90";#endif lint/* *	28-July-1988, T. Topcubasi *	Original code adopted from System V Rel. 2 *	I changed the call to wait which is different on BSD *	within the function lcall(). * *	10-nov-88 rjl *		fixed null pointer bug in argument parsing loop * *	20-nov-88 reeves for dlong *		Added exit arguments * */#include <stdio.h>#include <strings.h>#include <sys/wait.h>#define FALSE 0#define TRUE 1#define MAXSBUF 255#define MAXIBUF 512#define MAXINSERTS 5#define BUFSIZE 570#define MAXARGS 255#define EXITSHIFT 8 * (sizeof (int) - 1)char Errstr[BUFSIZE];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 = BUFSIZE-100;int N_ARGS = 0;int N_args = 0;int N_lines = 0;int DASHX = FALSE;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 = 0;main(argc,argv)int argc;char **argv; {extern char *addarg(), *getarg(), *checklen(), *insert();char *cmdname, *initbuf, **initlist, *flagval;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] && (*argv)[0] == '-'  ) {	flagval = *argv+1;	switch ( *flagval++ ) {	case 'x': DASHX = LEGAL = TRUE;		  break;	case 'l': PER_LINE = LEGAL = TRUE;		  N_ARGS = 0;		  INSERT = FALSE;		  if( *flagval && (PER_LINE=atoi(flagval)) <= 0 ) {			sprintf(Errstr, "#lines must be positive int: %s\n", *argv);			ermsg(Errstr);			}		  break;	case 'i': INSERT = PER_LINE = LEGAL = TRUE;		  N_ARGS = 0;		  if ( *flagval ) {			INSPAT = flagval;			}		  break;	case 't': TRACE = TRUE;		  break;	case 'e': LEOF = flagval;		  break;	case 's': BUFLIM = atoi(flagval);		  if( BUFLIM>470  ||  BUFLIM<=0 ) {			sprintf(Errstr, "0 < max-cmd-line-size <= 470: %s\n", *argv);			ermsg(Errstr);			}		  break;	case 'n': if( (N_ARGS = atoi(flagval)) <= 0 ) {			sprintf(Errstr, "#args must be positive int: %s\n", *argv);			ermsg(Errstr);			}		  else {			LEGAL = DASHX || N_ARGS==1;			INSERT = PER_LINE = FALSE;			}		  break;	case 'p': if( (PROMPT = open("/dev/tty",0)) == -1) {			ermsg("can't read from tty for -p\n");			}		  else			TRACE = TRUE;		  break;	default:  sprintf(Errstr, "unknown option: %s\n", *argv);		  ermsg(Errstr);		  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 ( xindex(*argv, INSPAT) != 0 ) {			if ( ++n_inserts > MAXINSERTS ) {				sprintf(Errstr, "too many args with %s\n", INSPAT);				ermsg(Errstr);				ERR = TRUE;				}			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 ( !ERR && 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_lines==0 || N_ARGS && N_args==0) ) exit (0);		OK = TRUE;		j = TRACE ? echoargs() : TRUE;		if( j ) {			if ( lcall(cmdname, arglist) != -1 ) continue;			sprintf(Errstr, "%s not executed or returned -1\n", cmdname);			ermsg(Errstr);			}		}	}if ( OK ) exit (0); else exit (1);}char *checklen(arg)char *arg;{register int oklen;oklen = TRUE;if ( (linesize += strlen(arg)+1) > BUFLIM ) {	lastarg = arg;	oklen = OK = FALSE;	if ( LEGAL ) {		ERR = TRUE;		ermsg("arg list too long\n");		}	else if( N_args > 1 )			N_args = 1;	else {		ermsg("a single arg was greater than the max arglist size\n");		ERR = TRUE;		}	}return ( oklen  ? arg : 0 );}char *addarg(arg)char *arg;{	strcpy(next, arg);	arg = next;	next += strlen(arg)+1;	return ( checklen(arg) );}char *getarg(){register char c, c1, *arg;char *retarg;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 '\0':	case '\n':		*next++ = '\0';		if( !strcmp(arg,LEOF) || c=='\0' ) {			MORE = FALSE;			if( c != '\n' )				while( c=getchr() )					if( c=='\n' ) break;			return 0;			}		else {			++N_args;			if( retarg = checklen(arg) ) {				if( (PER_LINE && c=='\n' && ++N_lines>=PER_LINE)				||   (N_ARGS && N_args>=N_ARGS) ) {					N_lines = N_args = 0;					lastarg = "";					OK = FALSE;					}				}			return retarg;			}	case '\\':		*next++ = getchr();		break;	case '"':	case '\'':		while( (c1=getchr()) != c) {			if( c1 == '\0' || c1 == '\n' ) {				*next++ = '\0';				sprintf(Errstr, "missing quote?: %s\n", arg);				ermsg(Errstr);				ERR = TRUE;				return (0);				}			*next++ = c1;			}		break;	default:		*next++ = c;		break;	}}ermsg(messages)char *messages;{write(2,"xargs: ",7);write(2,messages,strlen(messages));OK = FALSE;}echoargs(){register char **anarg;char yesorno[1], junk[1];register int j;anarg = arglist-1;while ( *++anarg ) {	write(2, *anarg, strlen(*anarg) );	write(2," ",1);	}if( PROMPT == -1 ) {	write(2,"\n",1);	return TRUE;	}write(2,"?...",4);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' );}char *insert(pattern, subst)char *pattern, *subst;{static 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( xindex(pat,INSPAT) == 0 ) {		if ( pbuf+len >= bufend ) break;		else {			strcpy(pbuf, subst);			pat += ipatlen;			pbuf += len;			}		}	else {		*pbuf++ = *pat;		if (pbuf >= bufend ) break;		}	}if ( ! *pat ) {	*pbuf = '\0';	return (buffer);	}else {	sprintf(Errstr, "max arg size with insertion via %s's exceeded\n", INSPAT);	ermsg(Errstr);	ERR = TRUE;	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");		ERR = TRUE;		}	strcpy(p_ibuf, newarg);	*(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;{	union wait retcode;	register int iwait, child;	switch( child=fork() ) {	default:		while( (iwait=wait(&retcode))!=child  &&  iwait!= -1 );		if( iwait == -1  ||  retcode.w_stopval )			return -1;		return( retcode.w_retcode );	case 0:		execvp(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.*/xindex(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);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?