Пример #1
0
static void
run(char **argv)
{
	char **avec;
	pid_t pid;

	/*
	 * If the user wants to be notified of each command before it is
	 * executed, notify them.  If they want the notification to be
	 * followed by a prompt, then prompt them.
	 */
	if (tflag || pflag) {
		(void)fprintf(stderr, "%s", *argv);
		for (avec = argv + 1; *avec != NULL; ++avec)
			(void)fprintf(stderr, " %s", *avec);
		/*
		 * If the user has asked to be prompted, do so.
		 */
		if (pflag)
			/*
			 * If they asked not to exec, return without execution
			 * but if they asked to, go to the execution.  If we
			 * could not open their tty, break the switch and drop
			 * back to -t behaviour.
			 */
			switch (prompt()) {
			case 0:
				return;
			case 1:
				goto exec;
			case 2:
				break;
			}
		(void)fprintf(stderr, "\n");
		(void)fflush(stderr);
	}
exec:
	childerr = 0;
	switch(pid = vfork()) {
	case -1:
		err(1, "vfork");
	case 0:
		close(0);
		if (oflag) {
			if (open("/dev/tty", O_RDONLY) == -1)
				err(1, "open /dev/tty");
		} else {
			if (open("/dev/null", O_RDONLY) == -1)
				err(1, "open /dev/null");
		}
		execvp(argv[0], argv);
		childerr = errno;
		_exit(1);
	}
	curprocs++;
	waitchildren(*argv, 0);
}
Пример #2
0
static void
xexit(const char *name, const int exit_code) {
	waitchildren(name, 1);
	exit(exit_code);
}
Пример #3
0
static void
run(char **argv)
{
	pid_t pid;
	int fd;
	char **avec;

	/*
	 * If the user wants to be notified of each command before it is
	 * executed, notify them.  If they want the notification to be
	 * followed by a prompt, then prompt them.
	 */
	if (tflag || pflag) {
		(void)fprintf(stderr, "%s", *argv);
		for (avec = argv + 1; *avec != NULL; ++avec)
			(void)fprintf(stderr, " %s", *avec);
		/*
		 * If the user has asked to be prompted, do so.
		 */
		if (pflag)
			/*
			 * If they asked not to exec, return without execution
			 * but if they asked to, go to the execution.  If we
			 * could not open their tty, break the switch and drop
			 * back to -t behaviour.
			 */
			switch (prompt()) {
			case 0:
				return;
			case 1:
				goto exec;
			case 2:
				break;
			}
		(void)fprintf(stderr, "\n");
		(void)fflush(stderr);
	}
exec:
	childerr = 0;
	switch (pid = vfork()) {
	case -1:
		warn("vfork");
		xexit(*argv, 1);
	case 0:
		if (oflag) {
			if ((fd = open(_PATH_TTY, O_RDONLY)) == -1)
				err(1, "can't open /dev/tty");
		} else {
			fd = open(_PATH_DEVNULL, O_RDONLY);
		}
		if (fd > STDIN_FILENO) {
			if (dup2(fd, STDIN_FILENO) != 0)
				err(1, "can't dup2 to stdin");
			close(fd);
		}
		execvp(argv[0], argv);
		childerr = errno;
		_exit(1);
	}
	pids_add(pid);
	waitchildren(*argv, 0);
}
Пример #4
0
static void
parse_input(int argc, char *argv[])
{
	int ch, foundeof;
	char **avj;
	int last_was_backslashed = 0;

	foundeof = 0;

	switch(ch = getchar()) {
	case EOF:
		/* No arguments since last exec. */
		if (p == bbp) {
			waitchildren(*argv, 1);
			exit(rval);
		}
		goto arg1;
	case ' ':
		last_was_blank = 1;
	case '\t':
		/* Quotes escape tabs and spaces. */
		if (insingle || indouble || zflag)
			goto addch;
		goto arg2;
	case '\0':
		if (zflag) {
			/*
			 * Increment 'count', so that nulls will be treated
			 * as end-of-line, as well as end-of-argument.  This
			 * is needed so -0 works properly with -I and -L.
			 */
			count++;
			goto arg2;
		}
		goto addch;
	case '\n':
		if (zflag)
			goto addch;
		if (COMPAT_MODE("bin/xargs", "Unix2003")) {
			if (last_was_newline) {
				/* don't count empty line */
				break;
			}
			if (!last_was_blank ) {
				/* only count if NOT continuation line */
				count++;
			} 
		} else {
			count++;
		}
		last_was_newline = 1;

		/* Quotes do not escape newlines. */
arg1:		if (insingle || indouble)
			errx(1, "unterminated quote");
arg2:
		foundeof = *eofstr != '\0' &&
		    strcmp(argp, eofstr) == 0;

#ifdef __APPLE__
		/* 6591323: -I specifies that it processes the entire line,
		 * so only recognize eofstr at the end of a line. */
		if (Iflag && !last_was_newline)
			foundeof = 0;

		/* 6591323: Essentially the same as the EOF handling above. */
		if (foundeof && (p - strlen(eofstr) == bbp)) {
			waitchildren(*argv, 1);
			exit(rval);
		}
#endif

		/* Do not make empty args unless they are quoted */
		if ((argp != p || wasquoted) && !foundeof) {
			*p++ = '\0';
			*xp++ = argp;
			if (Iflag) {
				size_t curlen;

				if (inpline == NULL)
					curlen = 0;
				else {
					/*
					 * If this string is not zero
					 * length, append a space for
					 * separation before the next
					 * argument.
					 */
					if ((curlen = strlen(inpline)))
						strcat(inpline, " ");
				}
				curlen++;
				/*
				 * Allocate enough to hold what we will
				 * be holding in a second, and to append
				 * a space next time through, if we have
				 * to.
				 */
				inpline = realloc(inpline, curlen + 2 +
				    strlen(argp));
				if (inpline == NULL)
					errx(1, "realloc failed");
				if (curlen == 1)
					strcpy(inpline, argp);
				else
					strcat(inpline, argp);
			}
		}

		/*
		 * If max'd out on args or buffer, or reached EOF,
		 * run the command.  If xflag and max'd out on buffer
		 * but not on args, object.  Having reached the limit
		 * of input lines, as specified by -L is the same as
		 * maxing out on arguments.
		 */
		if (xp == endxp || p + (count * pad9314053) > ebp || ch == EOF ||
		    (Lflag <= count && xflag) || foundeof) {
			if (xflag && xp != endxp && p + (count * pad9314053) > ebp)
				errx(1, "insufficient space for arguments");
			if (jfound) {
				for (avj = argv; *avj; avj++)
					*xp++ = *avj;
			}
			prerun(argc, av);
			if (ch == EOF || foundeof) {
				waitchildren(*argv, 1);
				exit(rval);
			}
			p = bbp;
			xp = bxp;
			count = 0;
		}
		argp = p;
		wasquoted = 0;
		break;
	case '\'':
		if (indouble || zflag)
			goto addch;
		insingle = !insingle;
		wasquoted = 1;
		break;
	case '"':
		if (insingle || zflag)
			goto addch;
		indouble = !indouble;
		wasquoted = 1;
		break;
	case '\\':
		last_was_backslashed = 1;
		if (zflag)
			goto addch;
		/* Backslash escapes anything, is escaped by quotes. */
		if (!insingle && !indouble && (ch = getchar()) == EOF)
			errx(1, "backslash at EOF");
		/* FALLTHROUGH */
	default:
addch:		if (p < ebp) {
			*p++ = ch;
			break;
		}

		/* If only one argument, not enough buffer space. */
		if (bxp == xp)
			errx(1, "insufficient space for argument");
		/* Didn't hit argument limit, so if xflag object. */
		if (xflag)
			errx(1, "insufficient space for arguments");

		if (jfound) {
			for (avj = argv; *avj; avj++)
				*xp++ = *avj;
		}
		prerun(argc, av);
		xp = bxp;
		cnt = ebp - argp;
		memcpy(bbp, argp, (size_t)cnt);
		p = (argp = bbp) + cnt;
		*p++ = ch;
		break;
	}
	if (ch != ' ')
		last_was_blank = 0;
	if (ch != '\n' || last_was_backslashed)
		last_was_newline = 0;
}
Пример #5
0
static void
parse_input(int argc, char *argv[])
{
	int hasblank = 0;
	static int hadblank = 0;
	int ch, foundeof = 0;
	char **avj;

	ch = getchar();
	if (isblank(ch)) {
		/* Quotes escape tabs and spaces. */
		if (insingle || indouble)
			goto addch;
		hasblank = 1;
		if (zflag)
			goto addch;
		goto arg2;
	}

	switch (ch) {
	case EOF:
		/* No arguments since last exec. */
		if (p == bbp) {
			if (runeof)
				prerun(0, av);
			waitchildren(*argv, 1);
			exit(rval);
		}
		goto arg1;
	case '\0':
		if (zflag)
			goto arg2;
		goto addch;
	case '\n':
		hasblank = 1;
		if (hadblank == 0)
			count++;
		if (zflag)
			goto addch;

		/* Quotes do not escape newlines. */
arg1:		if (insingle || indouble)
			errx(1, "unterminated quote");
arg2:
		foundeof = *eofstr != '\0' &&
		    strcmp(argp, eofstr) == 0;

		/* Do not make empty args unless they are quoted */
		if ((argp != p || wasquoted) && !foundeof) {
			*p++ = '\0';
			*xp++ = argp;
			if (Iflag) {
				size_t curlen;

				if (inpline == NULL)
					curlen = 0;
				else {
					/*
					 * If this string is not zero
					 * length, append a space for
					 * separation before the next
					 * argument.
					 */
					if ((curlen = strlen(inpline)))
						strlcat(inpline, " ", inpsize);
				}
				curlen++;
				/*
				 * Allocate enough to hold what we will
				 * be holding in a second, and to append
				 * a space next time through, if we have
				 * to.
				 */
				inpsize = curlen + 2 + strlen(argp);
				inpline = realloc(inpline, inpsize);
				if (inpline == NULL)
					errx(1, "realloc failed");
				if (curlen == 1)
					strlcpy(inpline, argp, inpsize);
				else
					strlcat(inpline, argp, inpsize);
			}
		}

		/*
		 * If max'd out on args or buffer, or reached EOF,
		 * run the command.  If xflag and max'd out on buffer
		 * but not on args, object.  Having reached the limit
		 * of input lines, as specified by -L is the same as
		 * maxing out on arguments.
		 */
		if (xp == endxp || p > ebp || ch == EOF ||
		    (Lflag <= count && xflag) || foundeof) {
			if (xflag && xp != endxp && p > ebp)
				errx(1, "insufficient space for arguments");
			if (jfound) {
				for (avj = argv; *avj; avj++)
					*xp++ = *avj;
			}
			prerun(argc, av);
			if (ch == EOF || foundeof) {
				waitchildren(*argv, 1);
				exit(rval);
			}
			p = bbp;
			xp = bxp;
			count = 0;
		}
		argp = p;
		wasquoted = 0;
		break;
	case '\'':
		if (indouble || zflag)
			goto addch;
		insingle = !insingle;
		wasquoted = 1;
		break;
	case '"':
		if (insingle || zflag)
			goto addch;
		indouble = !indouble;
		wasquoted = 1;
		break;
	case '\\':
		if (zflag)
			goto addch;
		/* Backslash escapes anything, is escaped by quotes. */
		if (!insingle && !indouble && (ch = getchar()) == EOF)
			errx(1, "backslash at EOF");
		/* FALLTHROUGH */
	default:
addch:		if (p < ebp) {
			*p++ = ch;
			break;
		}

		/* If only one argument, not enough buffer space. */
		if (bxp == xp)
			errx(1, "insufficient space for argument");
		/* Didn't hit argument limit, so if xflag object. */
		if (xflag)
			errx(1, "insufficient space for arguments");

		if (jfound) {
			for (avj = argv; *avj; avj++)
				*xp++ = *avj;
		}
		prerun(argc, av);
		xp = bxp;
		cnt = ebp - argp;
		memcpy(bbp, argp, (size_t)cnt);
		p = (argp = bbp) + cnt;
		*p++ = ch;
		break;
	}
	hadblank = hasblank;
}