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