1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1993 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 #include <stdio.h> 34 #include <errno.h> 35 #include <limits.h> 36 #include <fcntl.h> 37 #include <string.h> 38 #include <sys/types.h> 39 #include <sys/stat.h> 40 #include <sys/wait.h> 41 #include <sys/vfstab.h> 42 #include <sys/mntent.h> 43 #include <locale.h> 44 #include <libintl.h> 45 46 #define ARGV_MAX 16 47 #define FSTYPE_MAX 8 48 #define VFS_PATH "/usr/lib/fs" 49 #define VFS_PATH2 "/etc/fs" 50 51 #define CHECK(xx, yy)\ 52 if (xx == (yy)-1) {\ 53 fprintf(stderr, gettext("%s: too many arguments\n"), myname); \ 54 usage(); \ 55 } 56 #define OPTION(flag)\ 57 options++; \ 58 nargv[nargc++] = flag; \ 59 CHECK(nargc, ARGV_MAX); \ 60 break 61 #define OPTARG(flag)\ 62 nargv[nargc++] = flag; \ 63 CHECK(nargc, ARGV_MAX); \ 64 if (optarg) {\ 65 nargv[nargc++] = optarg; \ 66 CHECK(nargc, ARGV_MAX); \ 67 }\ 68 break 69 70 71 int nrun, ndisks; 72 int maxrun = 8; /* should be based on the machine resources */ 73 74 extern char *optarg; 75 extern int optind; 76 extern char *default_fstype(); 77 78 int nargc = 2; 79 int options = 0; 80 int mnt_passno = 0; 81 int exitstat = 0; 82 char *nargv[ARGV_MAX]; 83 char *myname, *fstype; 84 char *malloc(); 85 char vfstab[] = VFSTAB; 86 char pflg = 0, Vflg = 0; 87 88 /* 89 * Keep an idea of the last device arg type as a hint to the 90 * type of the next arg. In the case of mountall, it's very likely 91 * to be the same type and the next entry in the file. This should 92 * help speed vfstab lookups. 93 */ 94 enum dev_arg_t { UNKNOWN, SPECIAL, FSCKDEV, MOUNTPT }; 95 enum dev_arg_t arg_hint = UNKNOWN; 96 97 static struct devlist { 98 char *name; 99 char *fsname; 100 pid_t pid; 101 struct devlist *nxt; 102 } *newdev(), *getdev(); 103 104 /* 105 * private copy vfstab functions 106 */ 107 static struct vfstab vfsave = {NULL, NULL, NULL, NULL, NULL, NULL, NULL}; 108 109 static int 110 vfdup(struct vfstab *vp) 111 { 112 if (vfsave.vfs_special != NULL) { 113 free(vfsave.vfs_special); 114 vfsave.vfs_special = NULL; 115 } 116 if ((vp->vfs_special != NULL) && 117 ((vfsave.vfs_special = strdup(vp->vfs_special)) == NULL)) { 118 perror(myname); 119 return (4); /* XXX */ 120 } 121 122 if (vfsave.vfs_fsckdev != NULL) { 123 free(vfsave.vfs_fsckdev); 124 vfsave.vfs_fsckdev = NULL; 125 } 126 if ((vp->vfs_fsckdev != NULL) && 127 ((vfsave.vfs_fsckdev = strdup(vp->vfs_fsckdev)) == NULL)) { 128 perror(myname); 129 return (4); /* XXX */ 130 } 131 132 if (vfsave.vfs_mountp != NULL) { 133 free(vfsave.vfs_mountp); 134 vfsave.vfs_mountp = NULL; 135 } 136 if ((vp->vfs_mountp != NULL) && 137 ((vfsave.vfs_mountp = strdup(vp->vfs_mountp)) == NULL)) { 138 perror(myname); 139 return (4); /* XXX */ 140 } 141 142 if (vfsave.vfs_fstype != NULL) { 143 free(vfsave.vfs_fstype); 144 vfsave.vfs_fstype = NULL; 145 } 146 if ((vp->vfs_fstype != NULL) && 147 ((vfsave.vfs_fstype = strdup(vp->vfs_fstype)) == NULL)) { 148 perror(myname); 149 return (4); /* XXX */ 150 } 151 152 if (vfsave.vfs_fsckpass != NULL) { 153 free(vfsave.vfs_fsckpass); 154 vfsave.vfs_fsckpass = NULL; 155 } 156 if ((vp->vfs_fsckpass != NULL) && 157 ((vfsave.vfs_fsckpass = strdup(vp->vfs_fsckpass)) == NULL)) { 158 perror(myname); 159 return (4); /* XXX */ 160 } 161 162 if (vfsave.vfs_automnt != NULL) { 163 free(vfsave.vfs_automnt); 164 vfsave.vfs_automnt = NULL; 165 } 166 if ((vp->vfs_automnt != NULL) && 167 ((vfsave.vfs_automnt = strdup(vp->vfs_automnt)) == NULL)) { 168 perror(myname); 169 return (4); /* XXX */ 170 } 171 172 if (vfsave.vfs_mntopts != NULL) { 173 free(vfsave.vfs_mntopts); 174 vfsave.vfs_mntopts = NULL; 175 } 176 if ((vp->vfs_mntopts != NULL) && 177 ((vfsave.vfs_mntopts = strdup(vp->vfs_mntopts)) == NULL)) { 178 perror(myname); 179 return (4); /* XXX */ 180 } 181 182 *vp = vfsave; 183 return (0); 184 } 185 186 static int 187 mygetvfsent(FILE *fp, struct vfstab *vp) 188 { 189 int error; 190 191 if ((error = getvfsent(fp, vp)) != 0) 192 return (error); 193 return (vfdup(vp)); 194 } 195 196 static int 197 mygetvfsany(FILE *fp, struct vfstab *vp, struct vfstab *vrefp) 198 { 199 int error; 200 201 if ((error = getvfsany(fp, vp, vrefp)) != 0) 202 return (error); 203 return (vfdup(vp)); 204 } 205 206 main(argc, argv) 207 int argc; 208 char *argv[]; 209 { 210 int cc, ret, other_than_ufs = 0; 211 int questflg = 0, Fflg = 0, Vflg = 0, sanity = 0; 212 char *subopt; 213 FILE *fd = NULL; 214 struct vfstab vget, vref; 215 int preencnt = 0; 216 struct devlist *dp, *devs = NULL; 217 int status; 218 219 (void) setlocale(LC_ALL, ""); 220 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 221 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 222 #endif 223 (void) textdomain(TEXT_DOMAIN); 224 225 myname = strrchr(argv[0], '/'); 226 if (myname) 227 myname++; 228 else 229 myname = argv[0]; 230 231 while ((cc = getopt(argc, argv, "?F:mnNo:VyY")) != -1) { 232 switch (cc) { 233 case '?': 234 questflg++; 235 if (questflg > 1) 236 usage(); 237 nargv[nargc++] = "-?"; 238 CHECK(nargc, ARGV_MAX); 239 break; 240 case 'F': 241 Fflg++; 242 /* check for more that one -F */ 243 if (Fflg > 1) { 244 fprintf(stderr, 245 gettext("%s: more than one fstype specified\n"), 246 myname); 247 usage(); 248 } 249 fstype = optarg; 250 if (strlen(fstype) > (size_t) FSTYPE_MAX) { 251 fprintf(stderr, 252 gettext("%s: Fstype %s exceeds %d characters\n"), 253 myname, fstype, FSTYPE_MAX); 254 exit(1); 255 } 256 break; 257 case 'm': 258 sanity++; 259 OPTION("-m"); 260 case 'n': 261 OPTION("-n"); 262 case 'N': 263 OPTION("-N"); 264 case 'o': 265 subopt = optarg; 266 while (*subopt != '\0') { 267 if (*subopt == 'p') { 268 pflg++; 269 break; 270 } 271 subopt++; 272 } 273 OPTARG("-o"); 274 case 'V': 275 Vflg++; 276 if (Vflg > 1) 277 usage(); 278 break; 279 case 'y': 280 OPTION("-y"); 281 case 'Y': 282 OPTION("-Y"); 283 } 284 optarg = NULL; 285 } 286 287 /* copy '--' to specific */ 288 if (strcmp(argv[optind-1], "--") == 0) { 289 nargv[nargc++] = argv[optind-1]; 290 CHECK(nargc, ARGV_MAX); 291 } 292 293 if (questflg) { 294 if (Fflg) { 295 nargc = 2; 296 nargv[nargc++] = "-?"; 297 nargv[nargc] = NULL; 298 do_exec(fstype, nargv); 299 } 300 usage(); 301 } 302 303 if ((sanity) && (options > 1)) { 304 usage(); 305 } 306 307 if (optind == argc) { /* no device name is specified */ 308 if (fstype == NULL) { 309 if ((argc > 2) && (sanity)) { 310 usage(); 311 } 312 } 313 /* 314 * Try to check UFS filesystems first, then check other 315 * filesystems if they exist. 316 * Note: Parallel checking is only available in UFS for now. 317 */ 318 if (fstype == NULL || strcmp(fstype, MNTTYPE_UFS) == 0) { 319 if ((fd = fopen(vfstab, "r")) == NULL) { 320 fprintf(stderr, 321 gettext("%s: cannot open vfstab\n"), 322 myname); 323 exit(1); 324 } 325 while ((ret = mygetvfsent(fd, &vget)) == 0) { 326 if (strcmp(vget.vfs_fstype, MNTTYPE_UFS) && 327 numbers(vget.vfs_fsckpass)) { 328 other_than_ufs ++; 329 continue; 330 } 331 if (numbers(vget.vfs_fsckpass)) 332 mnt_passno = atoi(vget.vfs_fsckpass); 333 else 334 continue; 335 if (mnt_passno < 1) 336 continue; 337 if (pflg == 0 || mnt_passno == 1) { 338 status = execute(vget.vfs_fsckdev, 339 MNTTYPE_UFS, Vflg, fd); 340 /* return the highest exit code */ 341 if (status > exitstat) 342 exitstat = status; 343 } else if (preen_addev(vget.vfs_fsckdev) == 0) { 344 preencnt++; 345 dp = newdev(&vget); 346 dp->nxt = devs; 347 devs = dp; 348 } else { 349 /* 350 * preening setup failed, so 351 * execute serially here... 352 */ 353 fprintf(stderr, 354 gettext("%s: preen_addev error\n"), 355 myname); 356 status = execute(vget.vfs_fsckdev, 357 MNTTYPE_UFS, Vflg, fd); 358 /* return the highest exit code */ 359 if (status > exitstat) 360 exitstat = status; 361 } 362 } 363 fclose(fd); 364 if (ret > 0) 365 vfserror(ret); 366 if (pflg && exitstat == 0) { 367 fsck_dopreen(&devs, preencnt); 368 } 369 } 370 else 371 other_than_ufs = 1; 372 373 if (other_than_ufs) { 374 if ((fd = fopen(vfstab, "r")) == NULL) { 375 fprintf(stderr, 376 gettext("%s: cannot open vfstab\n"), 377 myname); 378 exit(1); 379 } 380 while ((ret = mygetvfsent(fd, &vget)) == 0) 381 if (strcmp(vget.vfs_fstype, MNTTYPE_UFS) && 382 numbers(vget.vfs_fsckpass) && 383 vget.vfs_fsckdev != NULL && 384 (fstype == NULL || 385 strcmp(fstype, vget.vfs_fstype) == 0)) { 386 status = execute(vget.vfs_fsckdev, 387 vget.vfs_fstype, Vflg, fd); 388 /* return the highest exit code */ 389 if (status > exitstat) 390 exitstat = status; 391 } 392 fclose(fd); 393 if (ret > 0) 394 vfserror(ret); 395 } 396 397 } else { /* device name is specified */ 398 if (fstype == NULL && (fd = fopen(vfstab, "r")) == NULL) { 399 fprintf(stderr, gettext("%s: cannot open vfstab\n"), 400 myname); 401 exit(1); 402 } 403 while (optind < argc) { 404 /* 405 * If "-F FStype" is specified, use that fs type. 406 * Otherwise, determine the fs type from /etc/vfstab 407 * if the entry exists. Otherwise, determine the 408 * local or remote fs type from /etc/default/df 409 * or /etc/dfs/fstypes respectively. 410 */ 411 if (fstype == NULL) { 412 if ((argc > 3) && (sanity)) { 413 usage(); 414 } 415 /* must check for both special && raw devices */ 416 vfsnull(&vref); 417 418 /* 419 * Find the vfstab entry for this device. 420 * arg_hint tells us what to try to match, 421 * based on the type of the last arg. If 422 * arg_hint equals UNKNOWN, then we're not 423 * sure of the type and need to fallthrough 424 * all 3 possibilities for vfstab lookup. 425 * Try it as a mountpt first, since that's 426 * what mountall gives us. 427 */ 428 try_again: 429 switch (arg_hint) { 430 case UNKNOWN: 431 /* FALLTHROUGH */ 432 433 case MOUNTPT: 434 vref.vfs_mountp = argv[optind]; 435 if ((ret = mygetvfsany(fd, &vget, 436 &vref)) == -1 || 437 vget.vfs_fstype == NULL) { 438 439 vref.vfs_mountp = NULL; 440 rewind(fd); 441 442 if (arg_hint == MOUNTPT) { 443 arg_hint = UNKNOWN; 444 goto try_again; 445 } 446 /* FALLTHROUGH */ 447 } else { 448 /* Found it */ 449 if (vget.vfs_fsckdev != NULL) { 450 argv[optind] = 451 vget.vfs_fsckdev; 452 } 453 arg_hint = MOUNTPT; 454 break; 455 } 456 457 case FSCKDEV: 458 vref.vfs_fsckdev = argv[optind]; 459 if ((ret = mygetvfsany(fd, &vget, 460 &vref)) == -1 || 461 vget.vfs_fstype == NULL) { 462 463 vref.vfs_fsckdev = NULL; 464 rewind(fd); 465 466 if (arg_hint == FSCKDEV) { 467 arg_hint = UNKNOWN; 468 goto try_again; 469 } 470 /* FALLTHROUGH */ 471 } else { 472 /* Found it */ 473 arg_hint = FSCKDEV; 474 break; 475 } 476 477 case SPECIAL: 478 vref.vfs_special = argv[optind]; 479 if ((ret = mygetvfsany(fd, &vget, 480 &vref)) == -1 || 481 vget.vfs_fstype == NULL) { 482 483 vref.vfs_special = NULL; 484 rewind(fd); 485 486 if (arg_hint == SPECIAL) { 487 arg_hint = UNKNOWN; 488 goto try_again; 489 } 490 /* FALLTHROUGH */ 491 } else { 492 /* Found it */ 493 arg_hint = SPECIAL; 494 break; 495 } 496 } 497 498 if (ret == 0 && vget.vfs_fstype) { 499 if ((pflg) && (strcmp(vget.vfs_fstype, 500 MNTTYPE_UFS) == 0) && (preen_addev( 501 vget.vfs_fsckdev) == 0)) { 502 preencnt++; 503 dp = newdev(&vget); 504 dp->nxt = devs; 505 devs = dp; 506 } else { 507 status = execute(argv[optind], 508 vget.vfs_fstype, Vflg, fd); 509 if (status > exitstat) 510 exitstat = status; 511 } 512 } else if (ret == -1 || 513 vget.vfs_fstype == NULL) { 514 fstype = 515 default_fstype(argv[optind]); 516 status = execute(argv[optind], fstype, 517 Vflg, fd); 518 /* return the highest exit code */ 519 if (status > exitstat) 520 exitstat = status; 521 } else 522 vfserror(ret); 523 } else { 524 status = execute(argv[optind], fstype, 525 Vflg, NULL); 526 /* return the highest exit code */ 527 if (status > exitstat) 528 exitstat = status; 529 } 530 optind++; 531 } 532 if (fd != NULL) 533 fclose(fd); 534 if ((pflg) && (exitstat == 0)) { 535 fsck_dopreen(&devs, preencnt); 536 } 537 } 538 exit(exitstat); 539 } 540 541 static 542 fsck_dopreen(devp, ndevs) 543 struct devlist **devp; 544 int ndevs; 545 { 546 char name[1024]; 547 int rc; 548 register int i; 549 struct devlist *bl, *bdp; 550 struct devlist *badlist; 551 552 bl = badlist = NULL; 553 while (ndevs > 0) { 554 if (nrun > maxrun) 555 waiter(&bl, &badlist); 556 rc = preen_getdev(name); 557 switch (rc) { 558 case 0: 559 break; 560 case 1: 561 bdp = getdev(name, devp); 562 if (bdp == NULL) { 563 fprintf(stderr, 564 gettext("%s: unknown dev: `%s'\n"), 565 myname, name); 566 exit(1); 567 } 568 bdp->nxt = bl; 569 bl = bdp; 570 startdisk(bdp); 571 ndevs--; 572 break; 573 case 2: 574 waiter(&bl, &badlist); 575 break; 576 default: 577 fprintf(stderr, 578 gettext("%s: bad return `%d' from preen_getdev\n"), 579 myname, rc); 580 break; 581 } 582 } 583 while (bl != NULL) { 584 waiter(&bl, &badlist); 585 } 586 587 if (badlist != NULL) 588 print_badlist(badlist); 589 } 590 591 static 592 startdisk(dp) 593 struct devlist *dp; 594 { 595 pid_t pid; 596 597 nrun++; 598 if ((pid = fork()) == -1) { 599 perror("fork"); 600 exit(1); 601 } else if (pid == 0) { 602 exitstat = execute(dp->name, MNTTYPE_UFS, Vflg, NULL); 603 exit(exitstat); 604 } else { 605 dp->pid = pid; 606 } 607 } 608 609 static 610 waiter(blp, badlist) 611 struct devlist **blp; 612 struct devlist **badlist; 613 { 614 pid_t curpid; 615 int status; 616 register struct devlist *bdp, *pbdp; 617 618 curpid = wait(&status); 619 if (curpid == -1) { 620 perror("wait"); 621 exit(1); 622 } 623 624 for (pbdp = NULL, bdp = *blp; bdp != NULL; pbdp = bdp, bdp = bdp->nxt) { 625 if (bdp->pid == curpid) { 626 break; 627 } 628 } 629 if (bdp == NULL) 630 return; 631 nrun--; 632 633 if (pbdp) 634 pbdp->nxt = bdp->nxt; 635 else 636 *blp = bdp->nxt; 637 preen_releasedev(bdp->name); 638 639 if (WTERMSIG(status)) { 640 printf(gettext("%s (%s): EXITED WITH SIGNAL %d\n"), 641 bdp->name, bdp->fsname, WTERMSIG(status)); 642 status = status&0377 | 8<<8; 643 } 644 if (WHIBYTE(status) != 0) { 645 if (WHIBYTE(status) > exitstat) 646 exitstat = WHIBYTE(status); 647 while (*badlist != NULL) 648 badlist = &(*badlist)->nxt; 649 *badlist = bdp; 650 bdp->nxt = NULL; 651 } 652 } 653 654 static 655 print_badlist(lp) 656 struct devlist *lp; 657 { 658 int x, len; 659 660 printf( 661 gettext("\nTHE FOLLOWING FILE SYSTEM(S) HAD AN UNEXPECTED INCONSISTENCY:")); 662 for (x = 3; lp != NULL; lp = lp->nxt) { 663 len = strlen(lp->name) + strlen(lp->fsname) + 5; 664 x += len; 665 if (x >= 80) { 666 printf("\n "); 667 x = len + 3; 668 } else { 669 printf(" "); 670 } 671 printf("%s (%s)%s", lp->name, lp->fsname, 672 lp->nxt ? "," : "\n"); 673 } 674 } 675 676 /* 677 * allocate and initialize a `devlist' structure 678 */ 679 static 680 struct devlist * 681 newdev(vfsp) 682 struct vfstab *vfsp; 683 { 684 struct devlist *dp; 685 extern char *strdup(); 686 687 dp = (struct devlist *)malloc(sizeof (struct devlist)); 688 if (dp == NULL) { 689 fprintf(stderr, gettext("%s: out of memory\n"), myname); 690 exit(1); 691 } 692 dp->name = strdup(vfsp->vfs_fsckdev); 693 dp->fsname = strdup(vfsp->vfs_mountp); 694 if (dp->name == NULL || dp->fsname == NULL) { 695 fprintf(stderr, gettext("%s: out of memory\n"), myname); 696 exit(1); 697 } 698 return (dp); 699 } 700 701 /* 702 * locate the devlist structure in the given list that matches `name'. 703 * If found, the structure is removed from the list, and a pointer to 704 * it is returned. If not, NULL is returned. 705 */ 706 static 707 struct devlist * 708 getdev(name, list) 709 char *name; 710 struct devlist **list; 711 { 712 register struct devlist *p, *lp; 713 714 for (lp = NULL, p = *list; p != NULL; lp = p, p = p->nxt) { 715 if (strcmp(p->name, name) == 0) 716 break; 717 } 718 719 if (p != NULL) { 720 if (lp != NULL) 721 lp->nxt = p->nxt; 722 else 723 *list = p->nxt; 724 } 725 return (p); 726 } 727 728 /* see if all numbers */ 729 numbers(yp) 730 char *yp; 731 { 732 if (yp == NULL) 733 return (0); 734 while ('0' <= *yp && *yp <= '9') 735 yp++; 736 if (*yp) 737 return (0); 738 return (1); 739 } 740 741 execute(fsckdev, fstype, Vflg, fd) 742 char *fsckdev, *fstype; 743 int Vflg; 744 FILE *fd; 745 { 746 int st; 747 pid_t fk; 748 char full_path[PATH_MAX]; 749 char *vfs_path = VFS_PATH; 750 int status = 0; 751 752 nargv[nargc] = fsckdev; 753 754 if (Vflg) { 755 prnt_cmd(stdout, fstype); 756 return (0); 757 } 758 759 if (fd) 760 fcntl(fileno(fd), F_SETFD, 1); /* close on exec */ 761 762 if ((fk = fork()) == (pid_t)-1) { 763 fprintf(stderr, 764 gettext("%s: cannot fork. Try again later\n"), 765 myname); 766 perror(myname); 767 exit(1); 768 } 769 770 if (fk == 0) { 771 /* Try to exec the fstype dependent portion of the fsck. */ 772 do_exec(fstype, nargv); 773 } else { 774 /* parent waits for child */ 775 if (wait(&st) == (pid_t)-1) { 776 fprintf(stderr, gettext("%s: bad wait\n"), myname); 777 perror(myname); 778 exit(1); 779 } 780 781 if ((st & 0xff) == 0x7f) { 782 fprintf(stderr, 783 gettext("%s: warning: the following command" 784 " (process %d) was stopped by signal %d\n"), 785 myname, fk, (st >> 8) & 0xff); 786 prnt_cmd(stderr, fstype); 787 status = ((st >> 8) & 0xff) | 0x80; 788 } else if (st & 0xff) { 789 if (st & 0x80) 790 fprintf(stderr, 791 gettext("%s: warning: the following command" 792 " (process %d) was terminated by signal %d" 793 " and dumped core\n"), 794 myname, fk, st & 0x7f); 795 else 796 fprintf(stderr, 797 gettext("%s: warning: the following command" 798 " (process %d) was terminated by signal %d\n"), 799 myname, fk, st & 0x7f); 800 801 prnt_cmd(stderr, fstype); 802 status = ((st & 0xff) | 0x80); 803 } else if (st & 0xff00) 804 status = (st >> 8) & 0xff; 805 } 806 807 return (status); 808 } 809 810 do_exec(fstype, nargv) 811 char *fstype, *nargv[]; 812 { 813 char full_path[PATH_MAX]; 814 char *vfs_path = VFS_PATH; 815 816 if (strlen(fstype) > (size_t) FSTYPE_MAX) { 817 fprintf(stderr, 818 gettext("%s: Fstype %s exceeds %d characters\n"), 819 myname, fstype, FSTYPE_MAX); 820 exit(1); 821 } 822 /* build the full pathname of the fstype dependent command. */ 823 sprintf(full_path, "%s/%s/%s", vfs_path, fstype, myname); 824 825 /* set the new argv[0] to the filename */ 826 nargv[1] = myname; 827 /* Try to exec the fstype dependent portion of the fsck. */ 828 execv(full_path, &nargv[1]); 829 if (errno == EACCES) { 830 fprintf(stderr, 831 gettext("%s: cannot execute %s - permission denied\n"), 832 myname, full_path); 833 } 834 if (errno == ENOEXEC) { 835 nargv[0] = "sh"; 836 nargv[1] = full_path; 837 execv("/sbin/sh", &nargv[0]); 838 } 839 /* second path to try */ 840 vfs_path = VFS_PATH2; 841 /* build the full pathname of the fstype dependent command. */ 842 sprintf(full_path, "%s/%s/%s", vfs_path, fstype, myname); 843 844 /* set the new argv[0] to the filename */ 845 nargv[1] = myname; 846 /* Try to exec the second fstype dependent portion of the fsck. */ 847 execv(full_path, &nargv[1]); 848 if (errno == EACCES) { 849 fprintf(stderr, 850 gettext("%s: cannot execute %s - permission denied\n"), 851 myname, full_path); 852 exit(1); 853 } 854 if (errno == ENOEXEC) { 855 nargv[0] = "sh"; 856 nargv[1] = full_path; 857 execv("/sbin/sh", &nargv[0]); 858 } 859 fprintf(stderr, 860 gettext("%s: operation not applicable to FSType %s\n"), 861 myname, fstype); 862 exit(1); 863 } 864 865 prnt_cmd(fd, fstype) 866 FILE *fd; 867 char *fstype; 868 { 869 char **argp; 870 871 fprintf(fd, "%s -F %s", myname, fstype); 872 for (argp = &nargv[2]; *argp; argp++) 873 fprintf(fd, " %s", *argp); 874 fprintf(fd, "\n"); 875 } 876 877 vfserror(flag) 878 int flag; 879 { 880 switch (flag) { 881 case VFS_TOOLONG: 882 fprintf(stderr, 883 gettext("%s: line in vfstab exceeds %d characters\n"), 884 myname, VFS_LINE_MAX-2); 885 break; 886 case VFS_TOOFEW: 887 fprintf(stderr, 888 gettext("%s: line in vfstab has too few entries\n"), 889 myname); 890 break; 891 case VFS_TOOMANY: 892 fprintf(stderr, 893 gettext("%s: line in vfstab has too many entries\n"), 894 myname); 895 break; 896 } 897 exit(1); 898 } 899 900 int opterr = 1, optind = 1, optopt = 0; 901 char *optarg = 0; 902 903 int 904 getopt(int argc, char * const *argv, const char *opts) 905 { 906 static int sp = 1; 907 register int c; 908 register char *cp; 909 910 if (sp == 1) 911 if (optind >= argc || 912 argv[optind][0] != '-' || argv[optind][1] == '\0') 913 return (-1); 914 else if (strcmp(argv[optind], "--") == 0) { 915 optind++; 916 return (-1); 917 } 918 optopt = c = argv[optind][sp]; 919 if (c == ':' || (cp = strchr(opts, c)) == 0) { 920 if (opterr) 921 fprintf(stderr, 922 gettext("%s: illegal option -- %c\n"), 923 *argv, c); 924 if (argv[optind][++sp] == '\0') { 925 optind++; 926 sp = 1; 927 } 928 return ('?'); 929 } 930 if (*++cp == ':') { 931 if (argv[optind][sp+1] != '\0') 932 optarg = &argv[optind++][sp+1]; 933 else if (++optind >= argc) { 934 if (opterr) 935 fprintf(stderr, 936 gettext("%s: option requires an argument -- %c\n"), *argv, c); 937 sp = 1; 938 return ('?'); 939 } else 940 optarg = argv[optind++]; 941 sp = 1; 942 } else if (*cp == ';') { 943 if (argv[optind][++sp] != '\0') 944 if (isoptarg(c, &argv[optind][sp])) { 945 optarg = &argv[optind++][sp]; 946 sp = 1; 947 } else 948 optarg = NULL; 949 else { 950 sp = 1; 951 if (++optind >= argc || !isoptarg(c, &argv[optind][0])) 952 optarg = NULL; 953 else 954 optarg = argv[optind++]; 955 } 956 } else { 957 if (argv[optind][++sp] == '\0') { 958 sp = 1; 959 optind++; 960 } 961 optarg = NULL; 962 } 963 return (c); 964 } 965 966 isoptarg(cc, arg) 967 int cc; 968 char *arg; 969 { 970 if (cc == 's' || cc == 'S') { 971 while (*arg >= '0' && *arg <= '9') 972 arg++; 973 if (*arg++ != ':') 974 return (0); 975 while (*arg >= '0' && *arg <= '9') 976 arg++; 977 if (*arg) 978 return (0); 979 return (1); 980 } 981 return (0); 982 } 983 984 usage() 985 { 986 fprintf(stderr, 987 gettext("Usage:\n%s [-F FSType] [-V] [-m] [special ...]\n" 988 "%s [-F FSType] [-V] [-y|Y|n|N]" 989 " [-o specific_options] [special ...]\n"), 990 myname, myname); 991 992 exit(1); 993 } 994