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); }
static void xexit(const char *name, const int exit_code) { waitchildren(name, 1); exit(exit_code); }
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); }
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; }
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; }