xref: /onnv-gate/usr/src/cmd/fs.d/fsck.c (revision 392:68e38aa09ba8)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
23*392Sswilcox  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
280Sstevel@tonic-gate /*	  All Rights Reserved  	*/
290Sstevel@tonic-gate 
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include	<stdio.h>
340Sstevel@tonic-gate #include	<errno.h>
350Sstevel@tonic-gate #include	<limits.h>
360Sstevel@tonic-gate #include	<fcntl.h>
370Sstevel@tonic-gate #include	<string.h>
380Sstevel@tonic-gate #include	<sys/types.h>
390Sstevel@tonic-gate #include	<sys/stat.h>
400Sstevel@tonic-gate #include	<sys/wait.h>
410Sstevel@tonic-gate #include	<sys/vfstab.h>
420Sstevel@tonic-gate #include	<sys/mntent.h>
430Sstevel@tonic-gate #include	<locale.h>
440Sstevel@tonic-gate #include	<libintl.h>
450Sstevel@tonic-gate 
460Sstevel@tonic-gate #define	ARGV_MAX	16
470Sstevel@tonic-gate #define	FSTYPE_MAX	8
480Sstevel@tonic-gate #define	VFS_PATH	"/usr/lib/fs"
490Sstevel@tonic-gate #define	VFS_PATH2	"/etc/fs"
500Sstevel@tonic-gate 
510Sstevel@tonic-gate #define	CHECK(xx, yy)\
520Sstevel@tonic-gate 	if (xx == (yy)-1) {\
530Sstevel@tonic-gate 		fprintf(stderr, gettext("%s: too many arguments\n"), myname); \
540Sstevel@tonic-gate 		usage(); \
550Sstevel@tonic-gate 	}
560Sstevel@tonic-gate #define	OPTION(flag)\
570Sstevel@tonic-gate 		options++; \
580Sstevel@tonic-gate 		nargv[nargc++] = flag; \
590Sstevel@tonic-gate 		CHECK(nargc, ARGV_MAX); \
600Sstevel@tonic-gate 		break
610Sstevel@tonic-gate #define	OPTARG(flag)\
620Sstevel@tonic-gate 		nargv[nargc++] = flag; \
630Sstevel@tonic-gate 		CHECK(nargc, ARGV_MAX); \
640Sstevel@tonic-gate 		if (optarg) {\
650Sstevel@tonic-gate 			nargv[nargc++] = optarg; \
660Sstevel@tonic-gate 			CHECK(nargc, ARGV_MAX); \
670Sstevel@tonic-gate 		}\
680Sstevel@tonic-gate 		break
690Sstevel@tonic-gate 
700Sstevel@tonic-gate 
710Sstevel@tonic-gate int	nrun, ndisks;
720Sstevel@tonic-gate int	maxrun = 8;	/* should be based on the machine resources */
730Sstevel@tonic-gate 
740Sstevel@tonic-gate extern char	*optarg;
750Sstevel@tonic-gate extern int	optind;
760Sstevel@tonic-gate extern char	*default_fstype();
770Sstevel@tonic-gate 
780Sstevel@tonic-gate int	nargc = 2;
790Sstevel@tonic-gate int	options = 0;
800Sstevel@tonic-gate int	mnt_passno = 0;
810Sstevel@tonic-gate int	exitstat = 0;
82*392Sswilcox int	verbose = 0;
830Sstevel@tonic-gate char	*nargv[ARGV_MAX];
840Sstevel@tonic-gate char	*myname, *fstype;
850Sstevel@tonic-gate char	*malloc();
860Sstevel@tonic-gate char	vfstab[] = VFSTAB;
870Sstevel@tonic-gate char	pflg = 0, Vflg = 0;
880Sstevel@tonic-gate 
890Sstevel@tonic-gate /*
900Sstevel@tonic-gate  * Keep an idea of the last device arg type as a hint to the
910Sstevel@tonic-gate  * type of the next arg. In the case of mountall, it's very likely
920Sstevel@tonic-gate  * to be the same type and the next entry in the file. This should
930Sstevel@tonic-gate  * help speed vfstab lookups.
940Sstevel@tonic-gate  */
950Sstevel@tonic-gate enum dev_arg_t { UNKNOWN, SPECIAL, FSCKDEV, MOUNTPT };
960Sstevel@tonic-gate enum dev_arg_t arg_hint = UNKNOWN;
970Sstevel@tonic-gate 
980Sstevel@tonic-gate static struct devlist {
990Sstevel@tonic-gate 	char *name;
1000Sstevel@tonic-gate 	char *fsname;
1010Sstevel@tonic-gate 	pid_t pid;
1020Sstevel@tonic-gate 	struct devlist *nxt;
1030Sstevel@tonic-gate } *newdev(), *getdev();
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate /*
1060Sstevel@tonic-gate  * private copy vfstab functions
1070Sstevel@tonic-gate  */
1080Sstevel@tonic-gate static struct vfstab	vfsave = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate static int
1110Sstevel@tonic-gate vfdup(struct vfstab *vp)
1120Sstevel@tonic-gate {
1130Sstevel@tonic-gate 	if (vfsave.vfs_special != NULL) {
1140Sstevel@tonic-gate 		free(vfsave.vfs_special);
1150Sstevel@tonic-gate 		vfsave.vfs_special = NULL;
1160Sstevel@tonic-gate 	}
1170Sstevel@tonic-gate 	if ((vp->vfs_special != NULL) &&
1180Sstevel@tonic-gate 	    ((vfsave.vfs_special = strdup(vp->vfs_special)) == NULL)) {
1190Sstevel@tonic-gate 		perror(myname);
1200Sstevel@tonic-gate 		return (4);	/* XXX */
1210Sstevel@tonic-gate 	}
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 	if (vfsave.vfs_fsckdev != NULL) {
1240Sstevel@tonic-gate 		free(vfsave.vfs_fsckdev);
1250Sstevel@tonic-gate 		vfsave.vfs_fsckdev = NULL;
1260Sstevel@tonic-gate 	}
1270Sstevel@tonic-gate 	if ((vp->vfs_fsckdev != NULL) &&
1280Sstevel@tonic-gate 	    ((vfsave.vfs_fsckdev = strdup(vp->vfs_fsckdev)) == NULL)) {
1290Sstevel@tonic-gate 		perror(myname);
1300Sstevel@tonic-gate 		return (4);	/* XXX */
1310Sstevel@tonic-gate 	}
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate 	if (vfsave.vfs_mountp != NULL) {
1340Sstevel@tonic-gate 		free(vfsave.vfs_mountp);
1350Sstevel@tonic-gate 		vfsave.vfs_mountp = NULL;
1360Sstevel@tonic-gate 	}
1370Sstevel@tonic-gate 	if ((vp->vfs_mountp != NULL) &&
1380Sstevel@tonic-gate 	    ((vfsave.vfs_mountp = strdup(vp->vfs_mountp)) == NULL)) {
1390Sstevel@tonic-gate 		perror(myname);
1400Sstevel@tonic-gate 		return (4);	/* XXX */
1410Sstevel@tonic-gate 	}
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 	if (vfsave.vfs_fstype != NULL) {
1440Sstevel@tonic-gate 		free(vfsave.vfs_fstype);
1450Sstevel@tonic-gate 		vfsave.vfs_fstype = NULL;
1460Sstevel@tonic-gate 	}
1470Sstevel@tonic-gate 	if ((vp->vfs_fstype != NULL) &&
1480Sstevel@tonic-gate 	    ((vfsave.vfs_fstype = strdup(vp->vfs_fstype)) == NULL)) {
1490Sstevel@tonic-gate 		perror(myname);
1500Sstevel@tonic-gate 		return (4);	/* XXX */
1510Sstevel@tonic-gate 	}
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	if (vfsave.vfs_fsckpass != NULL) {
1540Sstevel@tonic-gate 		free(vfsave.vfs_fsckpass);
1550Sstevel@tonic-gate 		vfsave.vfs_fsckpass = NULL;
1560Sstevel@tonic-gate 	}
1570Sstevel@tonic-gate 	if ((vp->vfs_fsckpass != NULL) &&
1580Sstevel@tonic-gate 	    ((vfsave.vfs_fsckpass = strdup(vp->vfs_fsckpass)) == NULL)) {
1590Sstevel@tonic-gate 		perror(myname);
1600Sstevel@tonic-gate 		return (4);	/* XXX */
1610Sstevel@tonic-gate 	}
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate 	if (vfsave.vfs_automnt != NULL) {
1640Sstevel@tonic-gate 		free(vfsave.vfs_automnt);
1650Sstevel@tonic-gate 		vfsave.vfs_automnt = NULL;
1660Sstevel@tonic-gate 	}
1670Sstevel@tonic-gate 	if ((vp->vfs_automnt != NULL) &&
1680Sstevel@tonic-gate 	    ((vfsave.vfs_automnt = strdup(vp->vfs_automnt)) == NULL)) {
1690Sstevel@tonic-gate 		perror(myname);
1700Sstevel@tonic-gate 		return (4);	/* XXX */
1710Sstevel@tonic-gate 	}
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 	if (vfsave.vfs_mntopts != NULL) {
1740Sstevel@tonic-gate 		free(vfsave.vfs_mntopts);
1750Sstevel@tonic-gate 		vfsave.vfs_mntopts = NULL;
1760Sstevel@tonic-gate 	}
1770Sstevel@tonic-gate 	if ((vp->vfs_mntopts != NULL) &&
1780Sstevel@tonic-gate 	    ((vfsave.vfs_mntopts = strdup(vp->vfs_mntopts)) == NULL)) {
1790Sstevel@tonic-gate 		perror(myname);
1800Sstevel@tonic-gate 		return (4);	/* XXX */
1810Sstevel@tonic-gate 	}
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate 	*vp = vfsave;
1840Sstevel@tonic-gate 	return (0);
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate static int
1880Sstevel@tonic-gate mygetvfsent(FILE *fp, struct vfstab *vp)
1890Sstevel@tonic-gate {
1900Sstevel@tonic-gate 	int	error;
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 	if ((error = getvfsent(fp, vp)) != 0)
1930Sstevel@tonic-gate 		return (error);
1940Sstevel@tonic-gate 	return (vfdup(vp));
1950Sstevel@tonic-gate }
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate static int
1980Sstevel@tonic-gate mygetvfsany(FILE *fp, struct vfstab *vp, struct vfstab *vrefp)
1990Sstevel@tonic-gate {
2000Sstevel@tonic-gate 	int	error;
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	if ((error = getvfsany(fp, vp, vrefp)) != 0)
2030Sstevel@tonic-gate 		return (error);
2040Sstevel@tonic-gate 	return (vfdup(vp));
2050Sstevel@tonic-gate }
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate main(argc, argv)
2080Sstevel@tonic-gate 	int	argc;
2090Sstevel@tonic-gate 	char	*argv[];
2100Sstevel@tonic-gate {
2110Sstevel@tonic-gate 	int	cc, ret, other_than_ufs = 0;
2120Sstevel@tonic-gate 	int	questflg = 0, Fflg = 0, Vflg = 0, sanity = 0;
2130Sstevel@tonic-gate 	char	*subopt;
2140Sstevel@tonic-gate 	FILE	*fd = NULL;
2150Sstevel@tonic-gate 	struct vfstab	vget, vref;
2160Sstevel@tonic-gate 	int preencnt = 0;
2170Sstevel@tonic-gate 	struct devlist *dp, *devs = NULL;
2180Sstevel@tonic-gate 	int status;
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
2210Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
2220Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
2230Sstevel@tonic-gate #endif
2240Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate 	myname = strrchr(argv[0], '/');
2270Sstevel@tonic-gate 	if (myname)
2280Sstevel@tonic-gate 		myname++;
2290Sstevel@tonic-gate 	else
2300Sstevel@tonic-gate 		myname = argv[0];
2310Sstevel@tonic-gate 
232*392Sswilcox 	while ((cc = getopt(argc, argv, "?F:mnNo:vVyY")) != -1) {
2330Sstevel@tonic-gate 		switch (cc) {
2340Sstevel@tonic-gate 		case '?':
2350Sstevel@tonic-gate 			questflg++;
2360Sstevel@tonic-gate 			if (questflg > 1)
2370Sstevel@tonic-gate 				usage();
2380Sstevel@tonic-gate 			nargv[nargc++] = "-?";
2390Sstevel@tonic-gate 			CHECK(nargc, ARGV_MAX);
2400Sstevel@tonic-gate 			break;
2410Sstevel@tonic-gate 		case 'F':
2420Sstevel@tonic-gate 			Fflg++;
2430Sstevel@tonic-gate 			/* check for more that one -F */
2440Sstevel@tonic-gate 			if (Fflg > 1) {
2450Sstevel@tonic-gate 				fprintf(stderr,
2460Sstevel@tonic-gate 				gettext("%s: more than one fstype specified\n"),
2470Sstevel@tonic-gate 					myname);
2480Sstevel@tonic-gate 				usage();
2490Sstevel@tonic-gate 			}
2500Sstevel@tonic-gate 			fstype = optarg;
251*392Sswilcox 			if (strlen(fstype) > (size_t)FSTYPE_MAX) {
2520Sstevel@tonic-gate 				fprintf(stderr,
2530Sstevel@tonic-gate 			gettext("%s: Fstype %s exceeds %d characters\n"),
2540Sstevel@tonic-gate 					myname, fstype, FSTYPE_MAX);
2550Sstevel@tonic-gate 						exit(1);
2560Sstevel@tonic-gate 			}
2570Sstevel@tonic-gate 			break;
2580Sstevel@tonic-gate 		case 'm':
2590Sstevel@tonic-gate 			sanity++;
2600Sstevel@tonic-gate 			OPTION("-m");
2610Sstevel@tonic-gate 		case 'n':
2620Sstevel@tonic-gate 			OPTION("-n");
2630Sstevel@tonic-gate 		case 'N':
2640Sstevel@tonic-gate 			OPTION("-N");
2650Sstevel@tonic-gate 		case 'o':
2660Sstevel@tonic-gate 			subopt = optarg;
2670Sstevel@tonic-gate 			while (*subopt != '\0') {
2680Sstevel@tonic-gate 				if (*subopt == 'p') {
2690Sstevel@tonic-gate 					pflg++;
2700Sstevel@tonic-gate 					break;
2710Sstevel@tonic-gate 				}
2720Sstevel@tonic-gate 				subopt++;
2730Sstevel@tonic-gate 			}
2740Sstevel@tonic-gate 			OPTARG("-o");
275*392Sswilcox 		case 'v':
276*392Sswilcox 			OPTION("-v");
2770Sstevel@tonic-gate 		case 'V':
2780Sstevel@tonic-gate 			Vflg++;
2790Sstevel@tonic-gate 			if (Vflg > 1)
2800Sstevel@tonic-gate 				usage();
2810Sstevel@tonic-gate 			break;
2820Sstevel@tonic-gate 		case 'y':
2830Sstevel@tonic-gate 			OPTION("-y");
2840Sstevel@tonic-gate 		case 'Y':
2850Sstevel@tonic-gate 			OPTION("-Y");
2860Sstevel@tonic-gate 		}
2870Sstevel@tonic-gate 		optarg = NULL;
2880Sstevel@tonic-gate 	}
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 	/* copy '--' to specific */
2910Sstevel@tonic-gate 	if (strcmp(argv[optind-1], "--") == 0) {
2920Sstevel@tonic-gate 		nargv[nargc++] = argv[optind-1];
2930Sstevel@tonic-gate 		CHECK(nargc, ARGV_MAX);
2940Sstevel@tonic-gate 	}
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate 	if (questflg) {
2970Sstevel@tonic-gate 		if (Fflg) {
2980Sstevel@tonic-gate 			nargc = 2;
2990Sstevel@tonic-gate 			nargv[nargc++] = "-?";
3000Sstevel@tonic-gate 			nargv[nargc] = NULL;
3010Sstevel@tonic-gate 			do_exec(fstype, nargv);
3020Sstevel@tonic-gate 		}
3030Sstevel@tonic-gate 		usage();
3040Sstevel@tonic-gate 	}
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 	if ((sanity) && (options > 1)) {
3070Sstevel@tonic-gate 		usage();
3080Sstevel@tonic-gate 	}
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate 	if (optind == argc) {	/* no device name is specified */
3110Sstevel@tonic-gate 		if (fstype == NULL) {
3120Sstevel@tonic-gate 			if ((argc > 2) && (sanity)) {
3130Sstevel@tonic-gate 				usage();
3140Sstevel@tonic-gate 			}
3150Sstevel@tonic-gate 		}
3160Sstevel@tonic-gate 		/*
3170Sstevel@tonic-gate 		 * Try to check UFS filesystems first, then check other
3180Sstevel@tonic-gate 		 * filesystems if they exist.
3190Sstevel@tonic-gate 		 * Note: Parallel checking is only available in UFS for now.
3200Sstevel@tonic-gate 		 */
3210Sstevel@tonic-gate 		if (fstype == NULL || strcmp(fstype, MNTTYPE_UFS) == 0) {
3220Sstevel@tonic-gate 			if ((fd = fopen(vfstab, "r")) == NULL) {
3230Sstevel@tonic-gate 				fprintf(stderr,
3240Sstevel@tonic-gate 					gettext("%s: cannot open vfstab\n"),
3250Sstevel@tonic-gate 					myname);
3260Sstevel@tonic-gate 				exit(1);
3270Sstevel@tonic-gate 			}
3280Sstevel@tonic-gate 			while ((ret = mygetvfsent(fd, &vget)) == 0) {
3290Sstevel@tonic-gate 				if (strcmp(vget.vfs_fstype, MNTTYPE_UFS) &&
3300Sstevel@tonic-gate 				    numbers(vget.vfs_fsckpass)) {
3310Sstevel@tonic-gate 					other_than_ufs ++;
3320Sstevel@tonic-gate 					continue;
3330Sstevel@tonic-gate 				}
3340Sstevel@tonic-gate 				if (numbers(vget.vfs_fsckpass))
3350Sstevel@tonic-gate 					mnt_passno = atoi(vget.vfs_fsckpass);
3360Sstevel@tonic-gate 				else
3370Sstevel@tonic-gate 					continue;
3380Sstevel@tonic-gate 				if (mnt_passno < 1)
3390Sstevel@tonic-gate 					continue;
3400Sstevel@tonic-gate 				if (pflg == 0 || mnt_passno == 1) {
3410Sstevel@tonic-gate 					status = execute(vget.vfs_fsckdev,
3420Sstevel@tonic-gate 					    MNTTYPE_UFS, Vflg, fd);
3430Sstevel@tonic-gate 					/* return the highest exit code */
3440Sstevel@tonic-gate 					if (status > exitstat)
3450Sstevel@tonic-gate 						exitstat = status;
3460Sstevel@tonic-gate 				} else if (preen_addev(vget.vfs_fsckdev) == 0) {
3470Sstevel@tonic-gate 					preencnt++;
3480Sstevel@tonic-gate 					dp = newdev(&vget);
3490Sstevel@tonic-gate 					dp->nxt = devs;
3500Sstevel@tonic-gate 					devs = dp;
3510Sstevel@tonic-gate 				} else {
3520Sstevel@tonic-gate 					/*
3530Sstevel@tonic-gate 					 * preening setup failed, so
3540Sstevel@tonic-gate 					 * execute serially here...
3550Sstevel@tonic-gate 					 */
3560Sstevel@tonic-gate 					fprintf(stderr,
3570Sstevel@tonic-gate 					gettext("%s: preen_addev error\n"),
3580Sstevel@tonic-gate 						myname);
3590Sstevel@tonic-gate 					status = execute(vget.vfs_fsckdev,
3600Sstevel@tonic-gate 					    MNTTYPE_UFS, Vflg, fd);
3610Sstevel@tonic-gate 					/* return the highest exit code */
3620Sstevel@tonic-gate 					if (status > exitstat)
3630Sstevel@tonic-gate 						exitstat = status;
3640Sstevel@tonic-gate 				}
3650Sstevel@tonic-gate 			}
3660Sstevel@tonic-gate 			fclose(fd);
3670Sstevel@tonic-gate 			if (ret > 0)
3680Sstevel@tonic-gate 				vfserror(ret);
3690Sstevel@tonic-gate 			if (pflg && exitstat == 0) {
3700Sstevel@tonic-gate 				fsck_dopreen(&devs, preencnt);
3710Sstevel@tonic-gate 			}
3720Sstevel@tonic-gate 		}
3730Sstevel@tonic-gate 		else
3740Sstevel@tonic-gate 			other_than_ufs = 1;
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 		if (other_than_ufs) {
3770Sstevel@tonic-gate 			if ((fd = fopen(vfstab, "r")) == NULL) {
3780Sstevel@tonic-gate 				fprintf(stderr,
3790Sstevel@tonic-gate 					gettext("%s: cannot open vfstab\n"),
3800Sstevel@tonic-gate 					myname);
3810Sstevel@tonic-gate 				exit(1);
3820Sstevel@tonic-gate 			}
3830Sstevel@tonic-gate 			while ((ret = mygetvfsent(fd, &vget)) == 0)
3840Sstevel@tonic-gate 				if (strcmp(vget.vfs_fstype, MNTTYPE_UFS) &&
3850Sstevel@tonic-gate 				    numbers(vget.vfs_fsckpass) &&
3860Sstevel@tonic-gate 				    vget.vfs_fsckdev != NULL &&
3870Sstevel@tonic-gate 				    (fstype == NULL ||
3880Sstevel@tonic-gate 				    strcmp(fstype, vget.vfs_fstype) == 0)) {
3890Sstevel@tonic-gate 					status = execute(vget.vfs_fsckdev,
3900Sstevel@tonic-gate 					    vget.vfs_fstype, Vflg, fd);
3910Sstevel@tonic-gate 					/* return the highest exit code */
3920Sstevel@tonic-gate 					if (status > exitstat)
3930Sstevel@tonic-gate 						exitstat = status;
3940Sstevel@tonic-gate 				}
3950Sstevel@tonic-gate 			fclose(fd);
3960Sstevel@tonic-gate 			if (ret > 0)
3970Sstevel@tonic-gate 				vfserror(ret);
3980Sstevel@tonic-gate 		}
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	} else {	/* device name is specified */
4010Sstevel@tonic-gate 		if (fstype == NULL && (fd = fopen(vfstab, "r")) == NULL) {
4020Sstevel@tonic-gate 			fprintf(stderr, gettext("%s: cannot open vfstab\n"),
4030Sstevel@tonic-gate 				myname);
4040Sstevel@tonic-gate 			exit(1);
4050Sstevel@tonic-gate 		}
4060Sstevel@tonic-gate 		while (optind < argc) {
4070Sstevel@tonic-gate 			/*
4080Sstevel@tonic-gate 			 * If "-F FStype" is specified, use that fs type.
4090Sstevel@tonic-gate 			 * Otherwise, determine the fs type from /etc/vfstab
4100Sstevel@tonic-gate 			 * if the entry exists.  Otherwise, determine the
4110Sstevel@tonic-gate 			 * local or remote fs type from /etc/default/df
4120Sstevel@tonic-gate 			 * or /etc/dfs/fstypes respectively.
4130Sstevel@tonic-gate 			 */
4140Sstevel@tonic-gate 			if (fstype == NULL) {
4150Sstevel@tonic-gate 				if ((argc > 3) && (sanity)) {
4160Sstevel@tonic-gate 					usage();
4170Sstevel@tonic-gate 				}
4180Sstevel@tonic-gate 				/* must check for both special && raw devices */
4190Sstevel@tonic-gate 				vfsnull(&vref);
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 				/*
4220Sstevel@tonic-gate 				 * Find the vfstab entry for this device.
4230Sstevel@tonic-gate 				 * arg_hint tells us what to try to match,
4240Sstevel@tonic-gate 				 * based on the type of the last arg. If
4250Sstevel@tonic-gate 				 * arg_hint equals UNKNOWN, then we're not
4260Sstevel@tonic-gate 				 * sure of the type and need to fallthrough
4270Sstevel@tonic-gate 				 * all 3 possibilities for vfstab lookup.
4280Sstevel@tonic-gate 				 * Try it as a mountpt first, since that's
4290Sstevel@tonic-gate 				 * what mountall gives us.
4300Sstevel@tonic-gate 				 */
4310Sstevel@tonic-gate try_again:
4320Sstevel@tonic-gate 				switch (arg_hint) {
4330Sstevel@tonic-gate 				case UNKNOWN:
4340Sstevel@tonic-gate 					/* FALLTHROUGH */
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate 				case MOUNTPT:
4370Sstevel@tonic-gate 					vref.vfs_mountp = argv[optind];
4380Sstevel@tonic-gate 					if ((ret = mygetvfsany(fd, &vget,
4390Sstevel@tonic-gate 						&vref)) == -1 ||
4400Sstevel@tonic-gate 						vget.vfs_fstype == NULL) {
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 						vref.vfs_mountp = NULL;
4430Sstevel@tonic-gate 						rewind(fd);
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate 						if (arg_hint == MOUNTPT) {
4460Sstevel@tonic-gate 							arg_hint = UNKNOWN;
4470Sstevel@tonic-gate 							goto try_again;
4480Sstevel@tonic-gate 						}
4490Sstevel@tonic-gate 						/* FALLTHROUGH */
4500Sstevel@tonic-gate 					} else {
4510Sstevel@tonic-gate 						/* Found it */
4520Sstevel@tonic-gate 						if (vget.vfs_fsckdev != NULL) {
4530Sstevel@tonic-gate 							argv[optind] =
4540Sstevel@tonic-gate 							vget.vfs_fsckdev;
4550Sstevel@tonic-gate 						}
4560Sstevel@tonic-gate 						arg_hint = MOUNTPT;
4570Sstevel@tonic-gate 						break;
4580Sstevel@tonic-gate 					}
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 				case FSCKDEV:
4610Sstevel@tonic-gate 					vref.vfs_fsckdev = argv[optind];
4620Sstevel@tonic-gate 					if ((ret = mygetvfsany(fd, &vget,
4630Sstevel@tonic-gate 						&vref)) == -1 ||
4640Sstevel@tonic-gate 						vget.vfs_fstype == NULL) {
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate 						vref.vfs_fsckdev = NULL;
4670Sstevel@tonic-gate 						rewind(fd);
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate 						if (arg_hint == FSCKDEV) {
4700Sstevel@tonic-gate 							arg_hint = UNKNOWN;
4710Sstevel@tonic-gate 							goto try_again;
4720Sstevel@tonic-gate 						}
4730Sstevel@tonic-gate 						/* FALLTHROUGH */
4740Sstevel@tonic-gate 					} else {
4750Sstevel@tonic-gate 						/* Found it */
4760Sstevel@tonic-gate 						arg_hint = FSCKDEV;
4770Sstevel@tonic-gate 						break;
4780Sstevel@tonic-gate 					}
4790Sstevel@tonic-gate 
4800Sstevel@tonic-gate 				case SPECIAL:
4810Sstevel@tonic-gate 					vref.vfs_special = argv[optind];
4820Sstevel@tonic-gate 					if ((ret = mygetvfsany(fd, &vget,
4830Sstevel@tonic-gate 						&vref)) == -1 ||
4840Sstevel@tonic-gate 						vget.vfs_fstype == NULL) {
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 						vref.vfs_special = NULL;
4870Sstevel@tonic-gate 						rewind(fd);
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate 						if (arg_hint == SPECIAL) {
4900Sstevel@tonic-gate 							arg_hint = UNKNOWN;
4910Sstevel@tonic-gate 							goto try_again;
4920Sstevel@tonic-gate 						}
4930Sstevel@tonic-gate 						/* FALLTHROUGH */
4940Sstevel@tonic-gate 					} else {
4950Sstevel@tonic-gate 						/* Found it */
4960Sstevel@tonic-gate 						arg_hint = SPECIAL;
4970Sstevel@tonic-gate 						break;
4980Sstevel@tonic-gate 					}
4990Sstevel@tonic-gate 				}
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 				if (ret == 0 && vget.vfs_fstype) {
5020Sstevel@tonic-gate 					if ((pflg) && (strcmp(vget.vfs_fstype,
5030Sstevel@tonic-gate 					    MNTTYPE_UFS) == 0) && (preen_addev(
5040Sstevel@tonic-gate 					    vget.vfs_fsckdev) == 0)) {
5050Sstevel@tonic-gate 						preencnt++;
5060Sstevel@tonic-gate 						dp = newdev(&vget);
5070Sstevel@tonic-gate 						dp->nxt = devs;
5080Sstevel@tonic-gate 						devs = dp;
5090Sstevel@tonic-gate 					} else {
5100Sstevel@tonic-gate 						status = execute(argv[optind],
5110Sstevel@tonic-gate 						    vget.vfs_fstype, Vflg, fd);
5120Sstevel@tonic-gate 						if (status > exitstat)
5130Sstevel@tonic-gate 							exitstat = status;
5140Sstevel@tonic-gate 					}
5150Sstevel@tonic-gate 				} else if (ret == -1 ||
5160Sstevel@tonic-gate 				    vget.vfs_fstype == NULL) {
5170Sstevel@tonic-gate 					fstype =
5180Sstevel@tonic-gate 					    default_fstype(argv[optind]);
5190Sstevel@tonic-gate 					status = execute(argv[optind], fstype,
5200Sstevel@tonic-gate 					    Vflg, fd);
5210Sstevel@tonic-gate 					/* return the highest exit code */
5220Sstevel@tonic-gate 					if (status > exitstat)
5230Sstevel@tonic-gate 						exitstat = status;
5240Sstevel@tonic-gate 				} else
5250Sstevel@tonic-gate 					vfserror(ret);
5260Sstevel@tonic-gate 			} else {
5270Sstevel@tonic-gate 				status = execute(argv[optind], fstype,
5280Sstevel@tonic-gate 				    Vflg, NULL);
5290Sstevel@tonic-gate 				/* return the highest exit code */
5300Sstevel@tonic-gate 				if (status > exitstat)
5310Sstevel@tonic-gate 					exitstat = status;
5320Sstevel@tonic-gate 			}
5330Sstevel@tonic-gate 			optind++;
5340Sstevel@tonic-gate 		}
5350Sstevel@tonic-gate 		if (fd != NULL)
5360Sstevel@tonic-gate 			fclose(fd);
5370Sstevel@tonic-gate 		if ((pflg) && (exitstat == 0)) {
5380Sstevel@tonic-gate 			fsck_dopreen(&devs, preencnt);
5390Sstevel@tonic-gate 		}
5400Sstevel@tonic-gate 	}
5410Sstevel@tonic-gate 	exit(exitstat);
5420Sstevel@tonic-gate }
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate static
5450Sstevel@tonic-gate fsck_dopreen(devp, ndevs)
5460Sstevel@tonic-gate 	struct devlist **devp;
5470Sstevel@tonic-gate 	int ndevs;
5480Sstevel@tonic-gate {
5490Sstevel@tonic-gate 	char name[1024];
5500Sstevel@tonic-gate 	int rc;
5510Sstevel@tonic-gate 	register int i;
5520Sstevel@tonic-gate 	struct devlist *bl, *bdp;
5530Sstevel@tonic-gate 	struct devlist *badlist;
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate 	bl = badlist = NULL;
5560Sstevel@tonic-gate 	while (ndevs > 0) {
5570Sstevel@tonic-gate 		if (nrun > maxrun)
5580Sstevel@tonic-gate 			waiter(&bl, &badlist);
5590Sstevel@tonic-gate 		rc = preen_getdev(name);
5600Sstevel@tonic-gate 		switch (rc) {
5610Sstevel@tonic-gate 		case 0:
5620Sstevel@tonic-gate 			break;
5630Sstevel@tonic-gate 		case 1:
5640Sstevel@tonic-gate 			bdp = getdev(name, devp);
5650Sstevel@tonic-gate 			if (bdp == NULL) {
5660Sstevel@tonic-gate 				fprintf(stderr,
5670Sstevel@tonic-gate 					gettext("%s: unknown dev: `%s'\n"),
5680Sstevel@tonic-gate 					myname, name);
5690Sstevel@tonic-gate 				exit(1);
5700Sstevel@tonic-gate 			}
5710Sstevel@tonic-gate 			bdp->nxt = bl;
5720Sstevel@tonic-gate 			bl = bdp;
5730Sstevel@tonic-gate 			startdisk(bdp);
5740Sstevel@tonic-gate 			ndevs--;
5750Sstevel@tonic-gate 			break;
5760Sstevel@tonic-gate 		case 2:
5770Sstevel@tonic-gate 			waiter(&bl, &badlist);
5780Sstevel@tonic-gate 			break;
5790Sstevel@tonic-gate 		default:
5800Sstevel@tonic-gate 			fprintf(stderr,
5810Sstevel@tonic-gate 			gettext("%s: bad return `%d' from preen_getdev\n"),
5820Sstevel@tonic-gate 				myname, rc);
5830Sstevel@tonic-gate 			break;
5840Sstevel@tonic-gate 		}
5850Sstevel@tonic-gate 	}
5860Sstevel@tonic-gate 	while (bl != NULL) {
5870Sstevel@tonic-gate 		waiter(&bl, &badlist);
5880Sstevel@tonic-gate 	}
5890Sstevel@tonic-gate 
5900Sstevel@tonic-gate 	if (badlist != NULL)
5910Sstevel@tonic-gate 		print_badlist(badlist);
5920Sstevel@tonic-gate }
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate static
5950Sstevel@tonic-gate startdisk(dp)
5960Sstevel@tonic-gate 	struct devlist *dp;
5970Sstevel@tonic-gate {
5980Sstevel@tonic-gate 	pid_t pid;
5990Sstevel@tonic-gate 
6000Sstevel@tonic-gate 	nrun++;
6010Sstevel@tonic-gate 	if ((pid = fork()) == -1) {
6020Sstevel@tonic-gate 		perror("fork");
6030Sstevel@tonic-gate 		exit(1);
6040Sstevel@tonic-gate 	} else if (pid == 0) {
6050Sstevel@tonic-gate 		exitstat = execute(dp->name, MNTTYPE_UFS, Vflg, NULL);
6060Sstevel@tonic-gate 		exit(exitstat);
6070Sstevel@tonic-gate 	} else {
6080Sstevel@tonic-gate 		dp->pid = pid;
6090Sstevel@tonic-gate 	}
6100Sstevel@tonic-gate }
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate static
6130Sstevel@tonic-gate waiter(blp, badlist)
6140Sstevel@tonic-gate 	struct devlist **blp;
6150Sstevel@tonic-gate 	struct devlist **badlist;
6160Sstevel@tonic-gate {
6170Sstevel@tonic-gate 	pid_t curpid;
6180Sstevel@tonic-gate 	int status;
6190Sstevel@tonic-gate 	register struct devlist *bdp, *pbdp;
6200Sstevel@tonic-gate 
6210Sstevel@tonic-gate 	curpid = wait(&status);
6220Sstevel@tonic-gate 	if (curpid == -1) {
6230Sstevel@tonic-gate 		perror("wait");
6240Sstevel@tonic-gate 		exit(1);
6250Sstevel@tonic-gate 	}
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate 	for (pbdp = NULL, bdp = *blp; bdp != NULL; pbdp = bdp, bdp = bdp->nxt) {
6280Sstevel@tonic-gate 		if (bdp->pid == curpid) {
6290Sstevel@tonic-gate 			break;
6300Sstevel@tonic-gate 		}
6310Sstevel@tonic-gate 	}
6320Sstevel@tonic-gate 	if (bdp == NULL)
6330Sstevel@tonic-gate 		return;
6340Sstevel@tonic-gate 	nrun--;
6350Sstevel@tonic-gate 
6360Sstevel@tonic-gate 	if (pbdp)
6370Sstevel@tonic-gate 		pbdp->nxt = bdp->nxt;
6380Sstevel@tonic-gate 	else
6390Sstevel@tonic-gate 		*blp = bdp->nxt;
6400Sstevel@tonic-gate 	preen_releasedev(bdp->name);
6410Sstevel@tonic-gate 
6420Sstevel@tonic-gate 	if (WTERMSIG(status)) {
6430Sstevel@tonic-gate 		printf(gettext("%s (%s): EXITED WITH SIGNAL %d\n"),
6440Sstevel@tonic-gate 			bdp->name, bdp->fsname, WTERMSIG(status));
6450Sstevel@tonic-gate 		status = status&0377 | 8<<8;
6460Sstevel@tonic-gate 	}
6470Sstevel@tonic-gate 	if (WHIBYTE(status) != 0) {
6480Sstevel@tonic-gate 		if (WHIBYTE(status) > exitstat)
6490Sstevel@tonic-gate 			exitstat = WHIBYTE(status);
6500Sstevel@tonic-gate 		while (*badlist != NULL)
6510Sstevel@tonic-gate 			badlist = &(*badlist)->nxt;
6520Sstevel@tonic-gate 		*badlist = bdp;
6530Sstevel@tonic-gate 		bdp->nxt = NULL;
6540Sstevel@tonic-gate 	}
6550Sstevel@tonic-gate }
6560Sstevel@tonic-gate 
6570Sstevel@tonic-gate static
6580Sstevel@tonic-gate print_badlist(lp)
6590Sstevel@tonic-gate 	struct devlist *lp;
6600Sstevel@tonic-gate {
6610Sstevel@tonic-gate 	int x, len;
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate 	printf(
6640Sstevel@tonic-gate gettext("\nTHE FOLLOWING FILE SYSTEM(S) HAD AN UNEXPECTED INCONSISTENCY:"));
6650Sstevel@tonic-gate 	for (x = 3; lp != NULL; lp = lp->nxt) {
6660Sstevel@tonic-gate 		len = strlen(lp->name) + strlen(lp->fsname) + 5;
6670Sstevel@tonic-gate 		x += len;
6680Sstevel@tonic-gate 		if (x >= 80) {
6690Sstevel@tonic-gate 			printf("\n   ");
6700Sstevel@tonic-gate 			x = len + 3;
6710Sstevel@tonic-gate 		} else {
6720Sstevel@tonic-gate 			printf(" ");
6730Sstevel@tonic-gate 		}
6740Sstevel@tonic-gate 		printf("%s (%s)%s", lp->name, lp->fsname,
6750Sstevel@tonic-gate 		    lp->nxt ? "," : "\n");
6760Sstevel@tonic-gate 	}
6770Sstevel@tonic-gate }
6780Sstevel@tonic-gate 
6790Sstevel@tonic-gate /*
6800Sstevel@tonic-gate  * allocate and initialize a `devlist' structure
6810Sstevel@tonic-gate  */
6820Sstevel@tonic-gate static
6830Sstevel@tonic-gate struct devlist *
6840Sstevel@tonic-gate newdev(vfsp)
6850Sstevel@tonic-gate 	struct vfstab *vfsp;
6860Sstevel@tonic-gate {
6870Sstevel@tonic-gate 	struct devlist *dp;
6880Sstevel@tonic-gate 	extern char *strdup();
6890Sstevel@tonic-gate 
6900Sstevel@tonic-gate 	dp = (struct devlist *)malloc(sizeof (struct devlist));
6910Sstevel@tonic-gate 	if (dp == NULL) {
6920Sstevel@tonic-gate 		fprintf(stderr, gettext("%s: out of memory\n"), myname);
6930Sstevel@tonic-gate 		exit(1);
6940Sstevel@tonic-gate 	}
6950Sstevel@tonic-gate 	dp->name = strdup(vfsp->vfs_fsckdev);
6960Sstevel@tonic-gate 	dp->fsname = strdup(vfsp->vfs_mountp);
6970Sstevel@tonic-gate 	if (dp->name == NULL || dp->fsname == NULL) {
6980Sstevel@tonic-gate 		fprintf(stderr, gettext("%s: out of memory\n"), myname);
6990Sstevel@tonic-gate 		exit(1);
7000Sstevel@tonic-gate 	}
7010Sstevel@tonic-gate 	return (dp);
7020Sstevel@tonic-gate }
7030Sstevel@tonic-gate 
7040Sstevel@tonic-gate /*
7050Sstevel@tonic-gate  * locate the devlist structure in the given list that matches `name'.
7060Sstevel@tonic-gate  * If found, the structure is removed from the list, and a pointer to
7070Sstevel@tonic-gate  * it is returned.  If not, NULL is returned.
7080Sstevel@tonic-gate  */
7090Sstevel@tonic-gate static
7100Sstevel@tonic-gate struct devlist *
7110Sstevel@tonic-gate getdev(name, list)
7120Sstevel@tonic-gate 	char *name;
7130Sstevel@tonic-gate 	struct devlist **list;
7140Sstevel@tonic-gate {
7150Sstevel@tonic-gate 	register struct devlist *p, *lp;
7160Sstevel@tonic-gate 
7170Sstevel@tonic-gate 	for (lp = NULL, p = *list; p != NULL; lp = p, p = p->nxt) {
7180Sstevel@tonic-gate 		if (strcmp(p->name, name) == 0)
7190Sstevel@tonic-gate 			break;
7200Sstevel@tonic-gate 	}
7210Sstevel@tonic-gate 
7220Sstevel@tonic-gate 	if (p != NULL) {
7230Sstevel@tonic-gate 		if (lp != NULL)
7240Sstevel@tonic-gate 			lp->nxt = p->nxt;
7250Sstevel@tonic-gate 		else
7260Sstevel@tonic-gate 			*list = p->nxt;
7270Sstevel@tonic-gate 	}
7280Sstevel@tonic-gate 	return (p);
7290Sstevel@tonic-gate }
7300Sstevel@tonic-gate 
7310Sstevel@tonic-gate /* see if all numbers */
7320Sstevel@tonic-gate numbers(yp)
7330Sstevel@tonic-gate 	char	*yp;
7340Sstevel@tonic-gate {
7350Sstevel@tonic-gate 	if (yp == NULL)
7360Sstevel@tonic-gate 		return (0);
7370Sstevel@tonic-gate 	while ('0' <= *yp && *yp <= '9')
7380Sstevel@tonic-gate 		yp++;
7390Sstevel@tonic-gate 	if (*yp)
7400Sstevel@tonic-gate 		return (0);
7410Sstevel@tonic-gate 	return (1);
7420Sstevel@tonic-gate }
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate execute(fsckdev, fstype, Vflg, fd)
7450Sstevel@tonic-gate 	char	*fsckdev, *fstype;
7460Sstevel@tonic-gate 	int	Vflg;
7470Sstevel@tonic-gate 	FILE	*fd;
7480Sstevel@tonic-gate {
7490Sstevel@tonic-gate 	int	st;
7500Sstevel@tonic-gate 	pid_t	fk;
7510Sstevel@tonic-gate 	char	full_path[PATH_MAX];
7520Sstevel@tonic-gate 	char	*vfs_path = VFS_PATH;
7530Sstevel@tonic-gate 	int	status = 0;
7540Sstevel@tonic-gate 
7550Sstevel@tonic-gate 	nargv[nargc] = fsckdev;
7560Sstevel@tonic-gate 
7570Sstevel@tonic-gate 	if (Vflg) {
7580Sstevel@tonic-gate 		prnt_cmd(stdout, fstype);
7590Sstevel@tonic-gate 		return (0);
7600Sstevel@tonic-gate 	}
7610Sstevel@tonic-gate 
7620Sstevel@tonic-gate 	if (fd)
7630Sstevel@tonic-gate 		fcntl(fileno(fd), F_SETFD, 1);	/* close on exec */
7640Sstevel@tonic-gate 
7650Sstevel@tonic-gate 	if ((fk = fork()) == (pid_t)-1) {
7660Sstevel@tonic-gate 		fprintf(stderr,
7670Sstevel@tonic-gate 			gettext("%s: cannot fork.  Try again later\n"),
7680Sstevel@tonic-gate 			myname);
7690Sstevel@tonic-gate 		perror(myname);
7700Sstevel@tonic-gate 		exit(1);
7710Sstevel@tonic-gate 	}
7720Sstevel@tonic-gate 
7730Sstevel@tonic-gate 	if (fk == 0) {
7740Sstevel@tonic-gate 		/* Try to exec the fstype dependent portion of the fsck. */
7750Sstevel@tonic-gate 		do_exec(fstype, nargv);
7760Sstevel@tonic-gate 	} else {
7770Sstevel@tonic-gate 		/* parent waits for child */
7780Sstevel@tonic-gate 		if (wait(&st) == (pid_t)-1) {
7790Sstevel@tonic-gate 			fprintf(stderr, gettext("%s: bad wait\n"), myname);
7800Sstevel@tonic-gate 			perror(myname);
7810Sstevel@tonic-gate 			exit(1);
7820Sstevel@tonic-gate 		}
7830Sstevel@tonic-gate 
7840Sstevel@tonic-gate 		if ((st & 0xff) == 0x7f) {
7850Sstevel@tonic-gate 			fprintf(stderr,
7860Sstevel@tonic-gate 				gettext("%s: warning: the following command"
7870Sstevel@tonic-gate 				" (process %d) was stopped by signal %d\n"),
7880Sstevel@tonic-gate 				myname, fk, (st >> 8) & 0xff);
7890Sstevel@tonic-gate 			prnt_cmd(stderr, fstype);
7900Sstevel@tonic-gate 			status = ((st >> 8) & 0xff) | 0x80;
7910Sstevel@tonic-gate 		} else if (st & 0xff) {
7920Sstevel@tonic-gate 			if (st & 0x80)
7930Sstevel@tonic-gate 				fprintf(stderr,
7940Sstevel@tonic-gate 				gettext("%s: warning: the following command"
7950Sstevel@tonic-gate 				" (process %d) was terminated by signal %d"
7960Sstevel@tonic-gate 				" and dumped core\n"),
7970Sstevel@tonic-gate 				myname, fk, st & 0x7f);
7980Sstevel@tonic-gate 			else
7990Sstevel@tonic-gate 				fprintf(stderr,
8000Sstevel@tonic-gate 				gettext("%s: warning: the following command"
8010Sstevel@tonic-gate 				" (process %d) was terminated by signal %d\n"),
8020Sstevel@tonic-gate 				myname, fk, st & 0x7f);
8030Sstevel@tonic-gate 
8040Sstevel@tonic-gate 			prnt_cmd(stderr, fstype);
8050Sstevel@tonic-gate 			status = ((st & 0xff) | 0x80);
8060Sstevel@tonic-gate 		} else if (st & 0xff00)
8070Sstevel@tonic-gate 			status = (st >> 8) & 0xff;
8080Sstevel@tonic-gate 	}
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate 	return (status);
8110Sstevel@tonic-gate }
8120Sstevel@tonic-gate 
8130Sstevel@tonic-gate do_exec(fstype, nargv)
8140Sstevel@tonic-gate 	char	*fstype, *nargv[];
8150Sstevel@tonic-gate {
8160Sstevel@tonic-gate 	char	full_path[PATH_MAX];
8170Sstevel@tonic-gate 	char	*vfs_path = VFS_PATH;
8180Sstevel@tonic-gate 
819*392Sswilcox 	if (strlen(fstype) > (size_t)FSTYPE_MAX) {
8200Sstevel@tonic-gate 		fprintf(stderr,
8210Sstevel@tonic-gate 			gettext("%s: Fstype %s exceeds %d characters\n"),
8220Sstevel@tonic-gate 			myname, fstype, FSTYPE_MAX);
8230Sstevel@tonic-gate 		exit(1);
8240Sstevel@tonic-gate 	}
8250Sstevel@tonic-gate 	/* build the full pathname of the fstype dependent command. */
8260Sstevel@tonic-gate 	sprintf(full_path, "%s/%s/%s", vfs_path, fstype, myname);
8270Sstevel@tonic-gate 
8280Sstevel@tonic-gate 	/* set the new argv[0] to the filename */
8290Sstevel@tonic-gate 	nargv[1] = myname;
8300Sstevel@tonic-gate 	/* Try to exec the fstype dependent portion of the fsck. */
8310Sstevel@tonic-gate 	execv(full_path, &nargv[1]);
8320Sstevel@tonic-gate 	if (errno == EACCES) {
8330Sstevel@tonic-gate 		fprintf(stderr,
8340Sstevel@tonic-gate 			gettext("%s: cannot execute %s - permission denied\n"),
8350Sstevel@tonic-gate 			myname, full_path);
8360Sstevel@tonic-gate 	}
8370Sstevel@tonic-gate 	if (errno == ENOEXEC) {
8380Sstevel@tonic-gate 		nargv[0] = "sh";
8390Sstevel@tonic-gate 		nargv[1] = full_path;
8400Sstevel@tonic-gate 		execv("/sbin/sh", &nargv[0]);
8410Sstevel@tonic-gate 	}
8420Sstevel@tonic-gate 	/* second path to try */
8430Sstevel@tonic-gate 	vfs_path = VFS_PATH2;
8440Sstevel@tonic-gate 	/* build the full pathname of the fstype dependent command. */
8450Sstevel@tonic-gate 	sprintf(full_path, "%s/%s/%s", vfs_path, fstype, myname);
8460Sstevel@tonic-gate 
8470Sstevel@tonic-gate 	/* set the new argv[0] to the filename */
8480Sstevel@tonic-gate 	nargv[1] = myname;
8490Sstevel@tonic-gate 	/* Try to exec the second fstype dependent portion of the fsck. */
8500Sstevel@tonic-gate 	execv(full_path, &nargv[1]);
8510Sstevel@tonic-gate 	if (errno == EACCES) {
8520Sstevel@tonic-gate 		fprintf(stderr,
8530Sstevel@tonic-gate 			gettext("%s: cannot execute %s - permission denied\n"),
8540Sstevel@tonic-gate 			myname, full_path);
8550Sstevel@tonic-gate 		exit(1);
8560Sstevel@tonic-gate 	}
8570Sstevel@tonic-gate 	if (errno == ENOEXEC) {
8580Sstevel@tonic-gate 		nargv[0] = "sh";
8590Sstevel@tonic-gate 		nargv[1] = full_path;
8600Sstevel@tonic-gate 		execv("/sbin/sh", &nargv[0]);
8610Sstevel@tonic-gate 	}
8620Sstevel@tonic-gate 	fprintf(stderr,
8630Sstevel@tonic-gate 		gettext("%s: operation not applicable to FSType %s\n"),
8640Sstevel@tonic-gate 		myname, fstype);
8650Sstevel@tonic-gate 	exit(1);
8660Sstevel@tonic-gate }
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate prnt_cmd(fd, fstype)
8690Sstevel@tonic-gate 	FILE	*fd;
8700Sstevel@tonic-gate 	char	*fstype;
8710Sstevel@tonic-gate {
8720Sstevel@tonic-gate 	char	**argp;
8730Sstevel@tonic-gate 
8740Sstevel@tonic-gate 	fprintf(fd, "%s -F %s", myname, fstype);
8750Sstevel@tonic-gate 	for (argp = &nargv[2]; *argp; argp++)
8760Sstevel@tonic-gate 		fprintf(fd, " %s", *argp);
8770Sstevel@tonic-gate 	fprintf(fd, "\n");
8780Sstevel@tonic-gate }
8790Sstevel@tonic-gate 
8800Sstevel@tonic-gate vfserror(flag)
8810Sstevel@tonic-gate 	int	flag;
8820Sstevel@tonic-gate {
8830Sstevel@tonic-gate 	switch (flag) {
8840Sstevel@tonic-gate 	case VFS_TOOLONG:
8850Sstevel@tonic-gate 		fprintf(stderr,
8860Sstevel@tonic-gate 			gettext("%s: line in vfstab exceeds %d characters\n"),
8870Sstevel@tonic-gate 			myname, VFS_LINE_MAX-2);
8880Sstevel@tonic-gate 		break;
8890Sstevel@tonic-gate 	case VFS_TOOFEW:
8900Sstevel@tonic-gate 		fprintf(stderr,
8910Sstevel@tonic-gate 			gettext("%s: line in vfstab has too few entries\n"),
8920Sstevel@tonic-gate 			myname);
8930Sstevel@tonic-gate 		break;
8940Sstevel@tonic-gate 	case VFS_TOOMANY:
8950Sstevel@tonic-gate 		fprintf(stderr,
8960Sstevel@tonic-gate 			gettext("%s: line in vfstab has too many entries\n"),
8970Sstevel@tonic-gate 			myname);
8980Sstevel@tonic-gate 		break;
8990Sstevel@tonic-gate 	}
9000Sstevel@tonic-gate 	exit(1);
9010Sstevel@tonic-gate }
9020Sstevel@tonic-gate 
9030Sstevel@tonic-gate int opterr = 1, optind = 1, optopt = 0;
9040Sstevel@tonic-gate char *optarg = 0;
9050Sstevel@tonic-gate 
9060Sstevel@tonic-gate int
9070Sstevel@tonic-gate getopt(int argc, char * const *argv, const char *opts)
9080Sstevel@tonic-gate {
9090Sstevel@tonic-gate 	static int sp = 1;
9100Sstevel@tonic-gate 	register int c;
9110Sstevel@tonic-gate 	register char *cp;
9120Sstevel@tonic-gate 
9130Sstevel@tonic-gate 	if (sp == 1)
9140Sstevel@tonic-gate 		if (optind >= argc ||
9150Sstevel@tonic-gate 		    argv[optind][0] != '-' || argv[optind][1] == '\0')
9160Sstevel@tonic-gate 			return (-1);
9170Sstevel@tonic-gate 		else if (strcmp(argv[optind], "--") == 0) {
9180Sstevel@tonic-gate 			optind++;
9190Sstevel@tonic-gate 			return (-1);
9200Sstevel@tonic-gate 		}
9210Sstevel@tonic-gate 	optopt = c = argv[optind][sp];
9220Sstevel@tonic-gate 	if (c == ':' || (cp = strchr(opts, c)) == 0) {
9230Sstevel@tonic-gate 		if (opterr)
9240Sstevel@tonic-gate 			fprintf(stderr,
9250Sstevel@tonic-gate 				gettext("%s: illegal option -- %c\n"),
9260Sstevel@tonic-gate 				*argv, c);
9270Sstevel@tonic-gate 		if (argv[optind][++sp] == '\0') {
9280Sstevel@tonic-gate 			optind++;
9290Sstevel@tonic-gate 			sp = 1;
9300Sstevel@tonic-gate 		}
9310Sstevel@tonic-gate 		return ('?');
9320Sstevel@tonic-gate 	}
9330Sstevel@tonic-gate 	if (*++cp == ':') {
9340Sstevel@tonic-gate 		if (argv[optind][sp+1] != '\0')
9350Sstevel@tonic-gate 			optarg = &argv[optind++][sp+1];
9360Sstevel@tonic-gate 		else if (++optind >= argc) {
9370Sstevel@tonic-gate 			if (opterr)
9380Sstevel@tonic-gate 				fprintf(stderr,
9390Sstevel@tonic-gate 		gettext("%s: option requires an argument -- %c\n"), *argv, c);
9400Sstevel@tonic-gate 			sp = 1;
9410Sstevel@tonic-gate 			return ('?');
9420Sstevel@tonic-gate 		} else
9430Sstevel@tonic-gate 			optarg = argv[optind++];
9440Sstevel@tonic-gate 		sp = 1;
9450Sstevel@tonic-gate 	} else if (*cp == ';') {
9460Sstevel@tonic-gate 		if (argv[optind][++sp] != '\0')
9470Sstevel@tonic-gate 			if (isoptarg(c, &argv[optind][sp])) {
9480Sstevel@tonic-gate 				optarg = &argv[optind++][sp];
9490Sstevel@tonic-gate 				sp = 1;
9500Sstevel@tonic-gate 			} else
9510Sstevel@tonic-gate 				optarg = NULL;
9520Sstevel@tonic-gate 		else {
9530Sstevel@tonic-gate 			sp = 1;
9540Sstevel@tonic-gate 			if (++optind >= argc || !isoptarg(c, &argv[optind][0]))
9550Sstevel@tonic-gate 				optarg = NULL;
9560Sstevel@tonic-gate 			else
9570Sstevel@tonic-gate 				optarg = argv[optind++];
9580Sstevel@tonic-gate 		}
9590Sstevel@tonic-gate 	} else {
9600Sstevel@tonic-gate 		if (argv[optind][++sp] == '\0') {
9610Sstevel@tonic-gate 			sp = 1;
9620Sstevel@tonic-gate 			optind++;
9630Sstevel@tonic-gate 		}
9640Sstevel@tonic-gate 		optarg = NULL;
9650Sstevel@tonic-gate 	}
9660Sstevel@tonic-gate 	return (c);
9670Sstevel@tonic-gate }
9680Sstevel@tonic-gate 
9690Sstevel@tonic-gate isoptarg(cc, arg)
9700Sstevel@tonic-gate 	int	cc;
9710Sstevel@tonic-gate 	char	*arg;
9720Sstevel@tonic-gate {
9730Sstevel@tonic-gate 	if (cc == 's' || cc == 'S') {
9740Sstevel@tonic-gate 		while (*arg >= '0' && *arg <= '9')
9750Sstevel@tonic-gate 			arg++;
9760Sstevel@tonic-gate 		if (*arg++ != ':')
9770Sstevel@tonic-gate 			return (0);
9780Sstevel@tonic-gate 		while (*arg >= '0' && *arg <= '9')
9790Sstevel@tonic-gate 			arg++;
9800Sstevel@tonic-gate 		if (*arg)
9810Sstevel@tonic-gate 			return (0);
9820Sstevel@tonic-gate 		return (1);
9830Sstevel@tonic-gate 	}
9840Sstevel@tonic-gate 	return (0);
9850Sstevel@tonic-gate }
9860Sstevel@tonic-gate 
9870Sstevel@tonic-gate usage()
9880Sstevel@tonic-gate {
9890Sstevel@tonic-gate 	fprintf(stderr,
9900Sstevel@tonic-gate 		gettext("Usage:\n%s [-F FSType] [-V] [-m] [special ...]\n"
9910Sstevel@tonic-gate 			"%s [-F FSType] [-V] [-y|Y|n|N]"
9920Sstevel@tonic-gate 			" [-o specific_options] [special ...]\n"),
9930Sstevel@tonic-gate 			myname, myname);
9940Sstevel@tonic-gate 
9950Sstevel@tonic-gate 	exit(1);
9960Sstevel@tonic-gate }
997