1 /*- 2 * Copyright (c) 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * John B. Roll Jr. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $xMach: xargs.c,v 1.6 2002/02/23 05:27:47 tim Exp $ 33 */ 34 35 #if 0 36 #ifndef lint 37 static const char copyright[] = 38 "@(#) Copyright (c) 1990, 1993\n\ 39 The Regents of the University of California. All rights reserved.\n"; 40 #endif /* not lint */ 41 42 #ifndef lint 43 static char sccsid[] = "@(#)xargs.c 8.1 (Berkeley) 6/6/93"; 44 #endif /* not lint */ 45 #endif 46 #include <sys/cdefs.h> 47 __FBSDID("$FreeBSD$"); 48 49 #include <sys/types.h> 50 #include <sys/wait.h> 51 #include <sys/time.h> 52 #include <sys/limits.h> 53 #include <sys/resource.h> 54 #include <err.h> 55 #include <errno.h> 56 #include <fcntl.h> 57 #include <langinfo.h> 58 #include <locale.h> 59 #include <paths.h> 60 #include <regex.h> 61 #include <stdio.h> 62 #include <stdlib.h> 63 #include <string.h> 64 #include <unistd.h> 65 66 #include "pathnames.h" 67 68 static void parse_input(int, char *[]); 69 static void prerun(int, char *[]); 70 static int prompt(void); 71 static void run(char **); 72 static void usage(void); 73 void strnsubst(char **, const char *, const char *, size_t); 74 static pid_t xwait(int block, int *status); 75 static void xexit(const char *, const int); 76 static void waitchildren(const char *, int); 77 static void pids_init(void); 78 static int pids_empty(void); 79 static int pids_full(void); 80 static void pids_add(pid_t pid); 81 static int pids_remove(pid_t pid); 82 static int findslot(pid_t pid); 83 static int findfreeslot(void); 84 static void clearslot(int slot); 85 86 static char echo[] = _PATH_ECHO; 87 static char **av, **bxp, **ep, **endxp, **xp; 88 static char *argp, *bbp, *ebp, *inpline, *p, *replstr; 89 static const char *eofstr; 90 static int count, insingle, indouble, oflag, pflag, tflag, Rflag, rval, zflag; 91 static int cnt, Iflag, jfound, Lflag, Sflag, wasquoted, xflag; 92 static int curprocs, maxprocs; 93 static pid_t *childpids; 94 95 static volatile int childerr; 96 97 extern char **environ; 98 99 int 100 main(int argc, char *argv[]) 101 { 102 long arg_max; 103 int ch, Jflag, nargs, nflag, nline; 104 size_t linelen; 105 struct rlimit rl; 106 char *endptr; 107 const char *errstr; 108 109 inpline = replstr = NULL; 110 ep = environ; 111 eofstr = ""; 112 Jflag = nflag = 0; 113 114 (void)setlocale(LC_ALL, ""); 115 116 /* 117 * POSIX.2 limits the exec line length to ARG_MAX - 2K. Running that 118 * caused some E2BIG errors, so it was changed to ARG_MAX - 4K. Given 119 * that the smallest argument is 2 bytes in length, this means that 120 * the number of arguments is limited to: 121 * 122 * (ARG_MAX - 4K - LENGTH(utility + arguments)) / 2. 123 * 124 * We arbitrarily limit the number of arguments to 5000. This is 125 * allowed by POSIX.2 as long as the resulting minimum exec line is 126 * at least LINE_MAX. Realloc'ing as necessary is possible, but 127 * probably not worthwhile. 128 */ 129 nargs = 5000; 130 if ((arg_max = sysconf(_SC_ARG_MAX)) == -1) 131 errx(1, "sysconf(_SC_ARG_MAX) failed"); 132 nline = arg_max - 4 * 1024; 133 while (*ep != NULL) { 134 /* 1 byte for each '\0' */ 135 nline -= strlen(*ep++) + 1 + sizeof(*ep); 136 } 137 maxprocs = 1; 138 while ((ch = getopt(argc, argv, "0E:I:J:L:n:oP:pR:S:s:rtx")) != -1) 139 switch (ch) { 140 case 'E': 141 eofstr = optarg; 142 break; 143 case 'I': 144 Jflag = 0; 145 Iflag = 1; 146 Lflag = 1; 147 replstr = optarg; 148 break; 149 case 'J': 150 Iflag = 0; 151 Jflag = 1; 152 replstr = optarg; 153 break; 154 case 'L': 155 Lflag = strtonum(optarg, 0, INT_MAX, &errstr); 156 if (errstr) 157 errx(1, "-L %s: %s", optarg, errstr); 158 break; 159 case 'n': 160 nflag = 1; 161 nargs = strtonum(optarg, 1, INT_MAX, &errstr); 162 if (errstr) 163 errx(1, "-n %s: %s", optarg, errstr); 164 break; 165 case 'o': 166 oflag = 1; 167 break; 168 case 'P': 169 maxprocs = strtonum(optarg, 0, INT_MAX, &errstr); 170 if (errstr) 171 errx(1, "-P %s: %s", optarg, errstr); 172 if (getrlimit(RLIMIT_NPROC, &rl) != 0) 173 errx(1, "getrlimit failed"); 174 if (maxprocs == 0 || maxprocs > rl.rlim_cur) 175 maxprocs = rl.rlim_cur; 176 break; 177 case 'p': 178 pflag = 1; 179 break; 180 case 'R': 181 Rflag = strtol(optarg, &endptr, 10); 182 if (*endptr != '\0') 183 errx(1, "replacements must be a number"); 184 break; 185 case 'r': 186 /* GNU compatibility */ 187 break; 188 case 'S': 189 Sflag = strtoul(optarg, &endptr, 10); 190 if (*endptr != '\0') 191 errx(1, "replsize must be a number"); 192 break; 193 case 's': 194 nline = strtonum(optarg, 0, INT_MAX, &errstr); 195 if (errstr) 196 errx(1, "-s %s: %s", optarg, errstr); 197 break; 198 case 't': 199 tflag = 1; 200 break; 201 case 'x': 202 xflag = 1; 203 break; 204 case '0': 205 zflag = 1; 206 break; 207 case '?': 208 default: 209 usage(); 210 } 211 argc -= optind; 212 argv += optind; 213 214 if (!Iflag && Rflag) 215 usage(); 216 if (!Iflag && Sflag) 217 usage(); 218 if (Iflag && !Rflag) 219 Rflag = 5; 220 if (Iflag && !Sflag) 221 Sflag = 255; 222 if (xflag && !nflag) 223 usage(); 224 if (Iflag || Lflag) 225 xflag = 1; 226 if (replstr != NULL && *replstr == '\0') 227 errx(1, "replstr may not be empty"); 228 229 pids_init(); 230 231 /* 232 * Allocate pointers for the utility name, the utility arguments, 233 * the maximum arguments to be read from stdin and the trailing 234 * NULL. 235 */ 236 linelen = 1 + argc + nargs + 1; 237 if ((av = bxp = malloc(linelen * sizeof(char *))) == NULL) 238 errx(1, "malloc failed"); 239 240 /* 241 * Use the user's name for the utility as argv[0], just like the 242 * shell. Echo is the default. Set up pointers for the user's 243 * arguments. 244 */ 245 if (*argv == NULL) 246 cnt = strlen(*bxp++ = echo); 247 else { 248 do { 249 if (Jflag && strcmp(*argv, replstr) == 0) { 250 char **avj; 251 jfound = 1; 252 argv++; 253 for (avj = argv; *avj; avj++) 254 cnt += strlen(*avj) + 1; 255 break; 256 } 257 cnt += strlen(*bxp++ = *argv) + 1; 258 } while (*++argv != NULL); 259 } 260 261 /* 262 * Set up begin/end/traversing pointers into the array. The -n 263 * count doesn't include the trailing NULL pointer, so the malloc 264 * added in an extra slot. 265 */ 266 endxp = (xp = bxp) + nargs; 267 268 /* 269 * Allocate buffer space for the arguments read from stdin and the 270 * trailing NULL. Buffer space is defined as the default or specified 271 * space, minus the length of the utility name and arguments. Set up 272 * begin/end/traversing pointers into the array. The -s count does 273 * include the trailing NULL, so the malloc didn't add in an extra 274 * slot. 275 */ 276 nline -= cnt; 277 if (nline <= 0) 278 errx(1, "insufficient space for command"); 279 280 if ((bbp = malloc((size_t)(nline + 1))) == NULL) 281 errx(1, "malloc failed"); 282 ebp = (argp = p = bbp) + nline - 1; 283 for (;;) 284 parse_input(argc, argv); 285 } 286 287 static void 288 parse_input(int argc, char *argv[]) 289 { 290 int ch, foundeof; 291 char **avj; 292 293 foundeof = 0; 294 295 switch (ch = getchar()) { 296 case EOF: 297 /* No arguments since last exec. */ 298 if (p == bbp) 299 xexit(*av, rval); 300 goto arg1; 301 case ' ': 302 case '\t': 303 /* Quotes escape tabs and spaces. */ 304 if (insingle || indouble || zflag) 305 goto addch; 306 goto arg2; 307 case '\0': 308 if (zflag) { 309 /* 310 * Increment 'count', so that nulls will be treated 311 * as end-of-line, as well as end-of-argument. This 312 * is needed so -0 works properly with -I and -L. 313 */ 314 count++; 315 goto arg2; 316 } 317 goto addch; 318 case '\n': 319 if (zflag) 320 goto addch; 321 count++; /* Indicate end-of-line (used by -L) */ 322 323 /* Quotes do not escape newlines. */ 324 arg1: if (insingle || indouble) { 325 warnx("unterminated quote"); 326 xexit(*av, 1); 327 } 328 arg2: 329 foundeof = *eofstr != '\0' && 330 strncmp(argp, eofstr, p - argp) == 0; 331 332 /* Do not make empty args unless they are quoted */ 333 if ((argp != p || wasquoted) && !foundeof) { 334 *p++ = '\0'; 335 *xp++ = argp; 336 if (Iflag) { 337 size_t curlen; 338 339 if (inpline == NULL) 340 curlen = 0; 341 else { 342 /* 343 * If this string is not zero 344 * length, append a space for 345 * separation before the next 346 * argument. 347 */ 348 if ((curlen = strlen(inpline))) 349 strcat(inpline, " "); 350 } 351 curlen++; 352 /* 353 * Allocate enough to hold what we will 354 * be holding in a second, and to append 355 * a space next time through, if we have 356 * to. 357 */ 358 inpline = realloc(inpline, curlen + 2 + 359 strlen(argp)); 360 if (inpline == NULL) { 361 warnx("realloc failed"); 362 xexit(*av, 1); 363 } 364 if (curlen == 1) 365 strcpy(inpline, argp); 366 else 367 strcat(inpline, argp); 368 } 369 } 370 371 /* 372 * If max'd out on args or buffer, or reached EOF, 373 * run the command. If xflag and max'd out on buffer 374 * but not on args, object. Having reached the limit 375 * of input lines, as specified by -L is the same as 376 * maxing out on arguments. 377 */ 378 if (xp == endxp || p > ebp || ch == EOF || 379 (Lflag <= count && xflag) || foundeof) { 380 if (xflag && xp != endxp && p > ebp) { 381 warnx("insufficient space for arguments"); 382 xexit(*av, 1); 383 } 384 if (jfound) { 385 for (avj = argv; *avj; avj++) 386 *xp++ = *avj; 387 } 388 prerun(argc, av); 389 if (ch == EOF || foundeof) 390 xexit(*av, rval); 391 p = bbp; 392 xp = bxp; 393 count = 0; 394 } 395 argp = p; 396 wasquoted = 0; 397 break; 398 case '\'': 399 if (indouble || zflag) 400 goto addch; 401 insingle = !insingle; 402 wasquoted = 1; 403 break; 404 case '"': 405 if (insingle || zflag) 406 goto addch; 407 indouble = !indouble; 408 wasquoted = 1; 409 break; 410 case '\\': 411 if (zflag) 412 goto addch; 413 /* Backslash escapes anything, is escaped by quotes. */ 414 if (!insingle && !indouble && (ch = getchar()) == EOF) { 415 warnx("backslash at EOF"); 416 xexit(*av, 1); 417 } 418 /* FALLTHROUGH */ 419 default: 420 addch: if (p < ebp) { 421 *p++ = ch; 422 break; 423 } 424 425 /* If only one argument, not enough buffer space. */ 426 if (bxp == xp) { 427 warnx("insufficient space for argument"); 428 xexit(*av, 1); 429 } 430 /* Didn't hit argument limit, so if xflag object. */ 431 if (xflag) { 432 warnx("insufficient space for arguments"); 433 xexit(*av, 1); 434 } 435 436 if (jfound) { 437 for (avj = argv; *avj; avj++) 438 *xp++ = *avj; 439 } 440 prerun(argc, av); 441 xp = bxp; 442 cnt = ebp - argp; 443 memcpy(bbp, argp, (size_t)cnt); 444 p = (argp = bbp) + cnt; 445 *p++ = ch; 446 break; 447 } 448 } 449 450 /* 451 * Do things necessary before run()'ing, such as -I substitution, 452 * and then call run(). 453 */ 454 static void 455 prerun(int argc, char *argv[]) 456 { 457 char **tmp, **tmp2, **avj; 458 int repls; 459 460 repls = Rflag; 461 462 if (argc == 0 || repls == 0) { 463 *xp = NULL; 464 run(argv); 465 return; 466 } 467 468 avj = argv; 469 470 /* 471 * Allocate memory to hold the argument list, and 472 * a NULL at the tail. 473 */ 474 tmp = malloc((argc + 1) * sizeof(char *)); 475 if (tmp == NULL) { 476 warnx("malloc failed"); 477 xexit(*argv, 1); 478 } 479 tmp2 = tmp; 480 481 /* 482 * Save the first argument and iterate over it, we 483 * cannot do strnsubst() to it. 484 */ 485 if ((*tmp++ = strdup(*avj++)) == NULL) { 486 warnx("strdup failed"); 487 xexit(*argv, 1); 488 } 489 490 /* 491 * For each argument to utility, if we have not used up 492 * the number of replacements we are allowed to do, and 493 * if the argument contains at least one occurrence of 494 * replstr, call strnsubst(), else just save the string. 495 * Iterations over elements of avj and tmp are done 496 * where appropriate. 497 */ 498 while (--argc) { 499 *tmp = *avj++; 500 if (repls && strstr(*tmp, replstr) != NULL) { 501 strnsubst(tmp++, replstr, inpline, (size_t)Sflag); 502 if (repls > 0) 503 repls--; 504 } else { 505 if ((*tmp = strdup(*tmp)) == NULL) { 506 warnx("strdup failed"); 507 xexit(*argv, 1); 508 } 509 tmp++; 510 } 511 } 512 513 /* 514 * Run it. 515 */ 516 *tmp = NULL; 517 run(tmp2); 518 519 /* 520 * Walk from the tail to the head, free along the way. 521 */ 522 for (; tmp2 != tmp; tmp--) 523 free(*tmp); 524 /* 525 * Now free the list itself. 526 */ 527 free(tmp2); 528 529 /* 530 * Free the input line buffer, if we have one. 531 */ 532 if (inpline != NULL) { 533 free(inpline); 534 inpline = NULL; 535 } 536 } 537 538 static void 539 run(char **argv) 540 { 541 pid_t pid; 542 int fd; 543 char **avec; 544 545 /* 546 * If the user wants to be notified of each command before it is 547 * executed, notify them. If they want the notification to be 548 * followed by a prompt, then prompt them. 549 */ 550 if (tflag || pflag) { 551 (void)fprintf(stderr, "%s", *argv); 552 for (avec = argv + 1; *avec != NULL; ++avec) 553 (void)fprintf(stderr, " %s", *avec); 554 /* 555 * If the user has asked to be prompted, do so. 556 */ 557 if (pflag) 558 /* 559 * If they asked not to exec, return without execution 560 * but if they asked to, go to the execution. If we 561 * could not open their tty, break the switch and drop 562 * back to -t behaviour. 563 */ 564 switch (prompt()) { 565 case 0: 566 return; 567 case 1: 568 goto exec; 569 case 2: 570 break; 571 } 572 (void)fprintf(stderr, "\n"); 573 (void)fflush(stderr); 574 } 575 exec: 576 childerr = 0; 577 switch (pid = vfork()) { 578 case -1: 579 warn("vfork"); 580 xexit(*argv, 1); 581 case 0: 582 if (oflag) { 583 if ((fd = open(_PATH_TTY, O_RDONLY)) == -1) 584 err(1, "can't open /dev/tty"); 585 } else { 586 fd = open(_PATH_DEVNULL, O_RDONLY); 587 } 588 if (fd > STDIN_FILENO) { 589 if (dup2(fd, STDIN_FILENO) != 0) 590 err(1, "can't dup2 to stdin"); 591 close(fd); 592 } 593 execvp(argv[0], argv); 594 childerr = errno; 595 _exit(1); 596 } 597 pids_add(pid); 598 waitchildren(*argv, 0); 599 } 600 601 /* 602 * Wait for a tracked child to exit and return its pid and exit status. 603 * 604 * Ignores (discards) all untracked child processes. 605 * Returns -1 and sets errno to ECHILD if no tracked children exist. 606 * If block is set, waits indefinitely for a child process to exit. 607 * If block is not set and no children have exited, returns 0 immediately. 608 */ 609 static pid_t 610 xwait(int block, int *status) { 611 pid_t pid; 612 613 if (pids_empty()) { 614 errno = ECHILD; 615 return (-1); 616 } 617 618 while ((pid = waitpid(-1, status, block ? 0 : WNOHANG)) > 0) 619 if (pids_remove(pid)) 620 break; 621 622 return (pid); 623 } 624 625 static void 626 xexit(const char *name, const int exit_code) { 627 waitchildren(name, 1); 628 exit(exit_code); 629 } 630 631 static void 632 waitchildren(const char *name, int waitall) 633 { 634 pid_t pid; 635 int status; 636 int cause_exit = 0; 637 638 while ((pid = xwait(waitall || pids_full(), &status)) > 0) { 639 /* 640 * If we couldn't invoke the utility or if utility exited 641 * because of a signal or with a value of 255, warn (per 642 * POSIX), and then wait until all other children have 643 * exited before exiting 1-125. POSIX requires us to stop 644 * reading if child exits because of a signal or with 255, 645 * but it does not require us to exit immediately; waiting 646 * is preferable to orphaning. 647 */ 648 if (childerr != 0 && cause_exit == 0) { 649 errno = childerr; 650 waitall = 1; 651 cause_exit = ENOENT ? 127 : 126; 652 warn("%s", name); 653 } else if (WIFSIGNALED(status)) { 654 waitall = cause_exit = 1; 655 warnx("%s: terminated with signal %d; aborting", 656 name, WTERMSIG(status)); 657 } else if (WEXITSTATUS(status) == 255) { 658 waitall = cause_exit = 1; 659 warnx("%s: exited with status 255; aborting", name); 660 } else if (WEXITSTATUS(status)) 661 rval = 1; 662 } 663 664 if (cause_exit) 665 exit(cause_exit); 666 if (pid == -1 && errno != ECHILD) 667 err(1, "waitpid"); 668 } 669 670 #define NOPID (0) 671 672 static void 673 pids_init(void) 674 { 675 int i; 676 677 if ((childpids = malloc(maxprocs * sizeof(*childpids))) == NULL) 678 errx(1, "malloc failed"); 679 680 for (i = 0; i < maxprocs; i++) 681 clearslot(i); 682 } 683 684 static int 685 pids_empty(void) 686 { 687 688 return (curprocs == 0); 689 } 690 691 static int 692 pids_full(void) 693 { 694 695 return (curprocs >= maxprocs); 696 } 697 698 static void 699 pids_add(pid_t pid) 700 { 701 int slot; 702 703 slot = findfreeslot(); 704 childpids[slot] = pid; 705 curprocs++; 706 } 707 708 static int 709 pids_remove(pid_t pid) 710 { 711 int slot; 712 713 if ((slot = findslot(pid)) < 0) 714 return (0); 715 716 clearslot(slot); 717 curprocs--; 718 return (1); 719 } 720 721 static int 722 findfreeslot(void) 723 { 724 int slot; 725 726 if ((slot = findslot(NOPID)) < 0) 727 errx(1, "internal error: no free pid slot"); 728 return (slot); 729 } 730 731 static int 732 findslot(pid_t pid) 733 { 734 int slot; 735 736 for (slot = 0; slot < maxprocs; slot++) 737 if (childpids[slot] == pid) 738 return (slot); 739 return (-1); 740 } 741 742 static void 743 clearslot(int slot) 744 { 745 746 childpids[slot] = NOPID; 747 } 748 749 /* 750 * Prompt the user about running a command. 751 */ 752 static int 753 prompt(void) 754 { 755 regex_t cre; 756 size_t rsize; 757 int match; 758 char *response; 759 FILE *ttyfp; 760 761 if ((ttyfp = fopen(_PATH_TTY, "r")) == NULL) 762 return (2); /* Indicate that the TTY failed to open. */ 763 (void)fprintf(stderr, "?..."); 764 (void)fflush(stderr); 765 if ((response = fgetln(ttyfp, &rsize)) == NULL || 766 regcomp(&cre, nl_langinfo(YESEXPR), REG_BASIC) != 0) { 767 (void)fclose(ttyfp); 768 return (0); 769 } 770 response[rsize - 1] = '\0'; 771 match = regexec(&cre, response, 0, NULL, 0); 772 (void)fclose(ttyfp); 773 regfree(&cre); 774 return (match == 0); 775 } 776 777 static void 778 usage(void) 779 { 780 781 fprintf(stderr, 782 "usage: xargs [-0opt] [-E eofstr] [-I replstr [-R replacements] [-S replsize]]\n" 783 " [-J replstr] [-L number] [-n number [-x]] [-P maxprocs]\n" 784 " [-s size] [utility [argument ...]]\n"); 785 exit(1); 786 } 787