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