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