mount.c revision 23678
11558Srgrimes/*
21558Srgrimes * Copyright (c) 1980, 1989, 1993, 1994
31558Srgrimes *	The Regents of the University of California.  All rights reserved.
41558Srgrimes *
51558Srgrimes * Redistribution and use in source and binary forms, with or without
61558Srgrimes * modification, are permitted provided that the following conditions
71558Srgrimes * are met:
81558Srgrimes * 1. Redistributions of source code must retain the above copyright
91558Srgrimes *    notice, this list of conditions and the following disclaimer.
101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111558Srgrimes *    notice, this list of conditions and the following disclaimer in the
121558Srgrimes *    documentation and/or other materials provided with the distribution.
131558Srgrimes * 3. All advertising materials mentioning features or use of this software
141558Srgrimes *    must display the following acknowledgement:
151558Srgrimes *	This product includes software developed by the University of
161558Srgrimes *	California, Berkeley and its contributors.
171558Srgrimes * 4. Neither the name of the University nor the names of its contributors
181558Srgrimes *    may be used to endorse or promote products derived from this software
191558Srgrimes *    without specific prior written permission.
201558Srgrimes *
211558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241558Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311558Srgrimes * SUCH DAMAGE.
321558Srgrimes */
331558Srgrimes
341558Srgrimes#ifndef lint
351558Srgrimesstatic char copyright[] =
361558Srgrimes"@(#) Copyright (c) 1980, 1989, 1993, 1994\n\
371558Srgrimes	The Regents of the University of California.  All rights reserved.\n";
381558Srgrimes#endif /* not lint */
391558Srgrimes
401558Srgrimes#ifndef lint
4123678Speterstatic char sccsid[] = "@(#)mount.c	8.25 (Berkeley) 5/8/95";
421558Srgrimes#endif /* not lint */
431558Srgrimes
441558Srgrimes#include <sys/param.h>
451558Srgrimes#include <sys/mount.h>
461558Srgrimes#include <sys/wait.h>
476441Sdg#include <sys/types.h>
486441Sdg#include <sys/stat.h>
491558Srgrimes
501558Srgrimes#include <err.h>
511558Srgrimes#include <errno.h>
521558Srgrimes#include <fstab.h>
5323678Speter#include <pwd.h>
541558Srgrimes#include <signal.h>
551558Srgrimes#include <stdio.h>
561558Srgrimes#include <stdlib.h>
571558Srgrimes#include <string.h>
581558Srgrimes#include <unistd.h>
591558Srgrimes
601558Srgrimes#include "pathnames.h"
611558Srgrimes
6223678Speterint debug, verbose;
6317243Sjkhint fstab_style = 0;
641558Srgrimes
6523678Speterint	checkvfsname __P((const char *, const char **));
661558Srgrimeschar   *catopt __P((char *, const char *));
671558Srgrimesstruct statfs
681558Srgrimes       *getmntpt __P((const char *));
6923678Speterint	hasopt __P((const char *, const char *));
701558Srgrimesconst char
711558Srgrimes      **makevfslist __P((char *));
721558Srgrimesvoid	mangle __P((char *, int *, const char **));
731558Srgrimesint	mountfs __P((const char *, const char *, const char *,
741558Srgrimes			int, const char *, const char *));
7523678Spetervoid	prmount __P((struct statfs *));
761558Srgrimesvoid	usage __P((void));
7717243Sjkhvoid	putfsent __P((const struct statfs *));
781558Srgrimes
791558Srgrimes/* From mount_ufs.c. */
801558Srgrimesint	mount_ufs __P((int, char * const *));
811558Srgrimes
821558Srgrimes/* Map from mount otions to printable formats. */
831558Srgrimesstatic struct opt {
841558Srgrimes	int o_opt;
851558Srgrimes	const char *o_name;
861558Srgrimes} optnames[] = {
871558Srgrimes	{ MNT_ASYNC,		"asynchronous" },
881558Srgrimes	{ MNT_EXPORTED,		"NFS exported" },
891558Srgrimes	{ MNT_LOCAL,		"local" },
9018007Sdg	{ MNT_NOATIME,		"noatime" },
911558Srgrimes	{ MNT_NODEV,		"nodev" },
921558Srgrimes	{ MNT_NOEXEC,		"noexec" },
931558Srgrimes	{ MNT_NOSUID,		"nosuid" },
941558Srgrimes	{ MNT_QUOTA,		"with quotas" },
951558Srgrimes	{ MNT_RDONLY,		"read-only" },
961558Srgrimes	{ MNT_SYNCHRONOUS,	"synchronous" },
971558Srgrimes	{ MNT_UNION,		"union" },
9823678Speter	{ MNT_NOATIME,		"noatime" },
991558Srgrimes	{ NULL }
1001558Srgrimes};
1011558Srgrimes
1021558Srgrimesint
1031558Srgrimesmain(argc, argv)
1041558Srgrimes	int argc;
1051558Srgrimes	char * const argv[];
1061558Srgrimes{
10723678Speter	const char *mntfromname, **vfslist, *vfstype;
1081558Srgrimes	struct fstab *fs;
1091558Srgrimes	struct statfs *mntbuf;
1101558Srgrimes	FILE *mountdfp;
1111558Srgrimes	pid_t pid;
1121558Srgrimes	int all, ch, i, init_flags, mntsize, rval;
1131558Srgrimes	char *options;
1141558Srgrimes
1151558Srgrimes	all = init_flags = 0;
1161558Srgrimes	options = NULL;
1171558Srgrimes	vfslist = NULL;
1181558Srgrimes	vfstype = "ufs";
11917243Sjkh	while ((ch = getopt(argc, argv, "padfo:rwt:uv")) != EOF)
1201558Srgrimes		switch (ch) {
12117243Sjkh		case 'p':
12217243Sjkh			fstab_style = 1;
12317243Sjkh			verbose = 1;
12417243Sjkh			break;
1251558Srgrimes		case 'a':
1261558Srgrimes			all = 1;
1271558Srgrimes			break;
1281558Srgrimes		case 'd':
1291558Srgrimes			debug = 1;
1301558Srgrimes			break;
1311558Srgrimes		case 'f':
1321558Srgrimes			init_flags |= MNT_FORCE;
1331558Srgrimes			break;
1341558Srgrimes		case 'o':
1351558Srgrimes			if (*optarg)
1361558Srgrimes				options = catopt(options, optarg);
1371558Srgrimes			break;
1381558Srgrimes		case 'r':
1391558Srgrimes			init_flags |= MNT_RDONLY;
1401558Srgrimes			break;
1411558Srgrimes		case 't':
1421558Srgrimes			if (vfslist != NULL)
1431558Srgrimes				errx(1, "only one -t option may be specified.");
1441558Srgrimes			vfslist = makevfslist(optarg);
1451558Srgrimes			vfstype = optarg;
1461558Srgrimes			break;
1471558Srgrimes		case 'u':
1481558Srgrimes			init_flags |= MNT_UPDATE;
1491558Srgrimes			break;
1501558Srgrimes		case 'v':
1511558Srgrimes			verbose = 1;
1521558Srgrimes			break;
1531558Srgrimes		case 'w':
1541558Srgrimes			init_flags &= ~MNT_RDONLY;
1551558Srgrimes			break;
1561558Srgrimes		case '?':
1571558Srgrimes		default:
1581558Srgrimes			usage();
1591558Srgrimes			/* NOTREACHED */
1601558Srgrimes		}
1611558Srgrimes	argc -= optind;
1621558Srgrimes	argv += optind;
1631558Srgrimes
1641558Srgrimes#define	BADTYPE(type)							\
1651558Srgrimes	(strcmp(type, FSTAB_RO) &&					\
1661558Srgrimes	    strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ))
1671558Srgrimes
1681558Srgrimes	rval = 0;
1691558Srgrimes	switch (argc) {
1701558Srgrimes	case 0:
1711558Srgrimes		if (all)
1721558Srgrimes			while ((fs = getfsent()) != NULL) {
1731558Srgrimes				if (BADTYPE(fs->fs_type))
1741558Srgrimes					continue;
17523678Speter				if (checkvfsname(fs->fs_vfstype, vfslist))
1761558Srgrimes					continue;
17723678Speter				if (hasopt(fs->fs_mntops, "noauto"))
17810288Sdg					continue;
1791558Srgrimes				if (mountfs(fs->fs_vfstype, fs->fs_spec,
18010288Sdg		    			fs->fs_file, init_flags, options,
18110288Sdg			    		fs->fs_mntops))
18210199Sjkh						rval = 1;
1831558Srgrimes			}
18417243Sjkh		else if (fstab_style) {
18517243Sjkh			if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0)
18617243Sjkh				err(1, "getmntinfo");
18717243Sjkh			for (i = 0; i < mntsize; i++) {
18823678Speter				if (checkvfsname(mntbuf[i].f_fstypename, vfslist))
18917243Sjkh					continue;
19017243Sjkh				putfsent (&mntbuf[i]);
19117243Sjkh			}
19217243Sjkh		}
1931558Srgrimes		else {
1941558Srgrimes			if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0)
1951558Srgrimes				err(1, "getmntinfo");
1961558Srgrimes			for (i = 0; i < mntsize; i++) {
19723678Speter				if (checkvfsname(mntbuf[i].f_fstypename, vfslist))
1981558Srgrimes					continue;
19923678Speter				prmount(&mntbuf[i]);
2001558Srgrimes			}
2011558Srgrimes		}
2021558Srgrimes		exit(rval);
2031558Srgrimes	case 1:
2041558Srgrimes		if (vfslist != NULL)
2051558Srgrimes			usage();
2061558Srgrimes
2071558Srgrimes		if (init_flags & MNT_UPDATE) {
2081558Srgrimes			if ((mntbuf = getmntpt(*argv)) == NULL)
2091558Srgrimes				errx(1,
2101558Srgrimes				    "unknown special file or file system %s.",
2111558Srgrimes				    *argv);
21223678Speter			if ((fs = getfsfile(mntbuf->f_mntonname)) != NULL)
21323678Speter				mntfromname = fs->fs_spec;
21423678Speter			else
21523678Speter				mntfromname = mntbuf->f_mntfromname;
21623678Speter			rval = mountfs(mntbuf->f_fstypename, mntfromname,
21723678Speter			    mntbuf->f_mntonname, init_flags, options, 0);
21823678Speter			break;
2191558Srgrimes		}
22023678Speter		if ((fs = getfsfile(*argv)) == NULL &&
22123678Speter		    (fs = getfsspec(*argv)) == NULL)
22223678Speter			errx(1, "%s: unknown special file or file system.",
22323678Speter			    *argv);
22423678Speter		if (BADTYPE(fs->fs_type))
22523678Speter			errx(1, "%s has unknown file system type.",
22623678Speter			    *argv);
22723678Speter		rval = mountfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file,
22823678Speter		    init_flags, options, fs->fs_mntops);
2291558Srgrimes		break;
2301558Srgrimes	case 2:
2311558Srgrimes		/*
2321558Srgrimes		 * If -t flag has not been specified, and spec contains either
2331558Srgrimes		 * a ':' or a '@' then assume that an NFS filesystem is being
2341558Srgrimes		 * specified ala Sun.
2351558Srgrimes		 */
2361558Srgrimes		if (vfslist == NULL && strpbrk(argv[0], ":@") != NULL)
2371558Srgrimes			vfstype = "nfs";
2381558Srgrimes		rval = mountfs(vfstype,
2391558Srgrimes		    argv[0], argv[1], init_flags, options, NULL);
2401558Srgrimes		break;
2411558Srgrimes	default:
2421558Srgrimes		usage();
2431558Srgrimes		/* NOTREACHED */
2441558Srgrimes	}
2451558Srgrimes
2461558Srgrimes	/*
2471558Srgrimes	 * If the mount was successfully, and done by root, tell mountd the
2481558Srgrimes	 * good news.  Pid checks are probably unnecessary, but don't hurt.
2491558Srgrimes	 */
2501558Srgrimes	if (rval == 0 && getuid() == 0 &&
2511558Srgrimes	    (mountdfp = fopen(_PATH_MOUNTDPID, "r")) != NULL) {
2521558Srgrimes		if (fscanf(mountdfp, "%ld", &pid) == 1 &&
2531558Srgrimes		     pid > 0 && kill(pid, SIGHUP) == -1 && errno != ESRCH)
2541558Srgrimes			err(1, "signal mountd");
2551558Srgrimes		(void)fclose(mountdfp);
2561558Srgrimes	}
2571558Srgrimes
2581558Srgrimes	exit(rval);
2591558Srgrimes}
2601558Srgrimes
2611558Srgrimesint
26223678Speterhasopt(mntopts, option)
26323678Speter	const char *mntopts, *option;
26423678Speter{
26523678Speter	int negative, found;
26623678Speter	char *opt, *optbuf;
26723678Speter
26823678Speter	if (option[0] == 'n' && option[1] == 'o') {
26923678Speter		negative = 1;
27023678Speter		option += 2;
27123678Speter	} else
27223678Speter		negative = 0;
27323678Speter	optbuf = strdup(mntopts);
27423678Speter	found = 0;
27523678Speter	for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) {
27623678Speter		if (opt[0] == 'n' && opt[1] == 'o') {
27723678Speter			if (!strcasecmp(opt + 2, option))
27823678Speter				found = negative;
27923678Speter		} else if (!strcasecmp(opt, option))
28023678Speter			found = !negative;
28123678Speter	}
28223678Speter	free(optbuf);
28323678Speter	return (found);
28423678Speter}
28523678Speter
28623678Speterint
2871558Srgrimesmountfs(vfstype, spec, name, flags, options, mntopts)
2881558Srgrimes	const char *vfstype, *spec, *name, *options, *mntopts;
2891558Srgrimes	int flags;
2901558Srgrimes{
2916441Sdg	struct stat sb;
2926441Sdg
2931558Srgrimes	/* List of directories containing mount_xxx subcommands. */
2941558Srgrimes	static const char *edirs[] = {
2951558Srgrimes		_PATH_SBIN,
2961558Srgrimes		_PATH_USRSBIN,
2971558Srgrimes		NULL
2981558Srgrimes	};
2991558Srgrimes	const char *argv[100], **edir;
3001558Srgrimes	struct statfs sf;
3011558Srgrimes	pid_t pid;
3021558Srgrimes	int argc, i, status;
3031558Srgrimes	char *optbuf, execname[MAXPATHLEN + 1], mntpath[MAXPATHLEN];
3041558Srgrimes
3056491Sbde	if (realpath(name, mntpath) != NULL && stat(mntpath, &sb) == 0) {
3066444Sdg		if (!S_ISDIR(sb.st_mode)) {
3076441Sdg			warnx("%s: Not a directory", mntpath);
3086441Sdg			return (1);
3096441Sdg		}
3106441Sdg	} else {
3111558Srgrimes		warn("%s", mntpath);
3121558Srgrimes		return (1);
3131558Srgrimes	}
3146441Sdg
3151818Sdg	if (mntopts == NULL)
3161818Sdg		mntopts = "";
3171558Srgrimes
3181558Srgrimes	name = mntpath;
3191558Srgrimes
32023678Speter	if (mntopts == NULL)
32123678Speter		mntopts = "";
3221558Srgrimes	if (options == NULL) {
32323678Speter		if (*mntopts == '\0') {
3241558Srgrimes			options = "rw";
32523678Speter		} else {
3261558Srgrimes			options = mntopts;
32723678Speter			mntopts = "";
32823678Speter		}
3291558Srgrimes	}
3301558Srgrimes	optbuf = catopt(strdup(mntopts), options);
3311558Srgrimes
3321558Srgrimes	if (strcmp(name, "/") == 0)
3331558Srgrimes		flags |= MNT_UPDATE;
3341558Srgrimes	if (flags & MNT_FORCE)
3351558Srgrimes		optbuf = catopt(optbuf, "force");
3361558Srgrimes	if (flags & MNT_RDONLY)
3371558Srgrimes		optbuf = catopt(optbuf, "ro");
3381558Srgrimes	/*
3391558Srgrimes	 * XXX
3401558Srgrimes	 * The mount_mfs (newfs) command uses -o to select the
3411558Srgrimes	 * optimisation mode.  We don't pass the default "-o rw"
3421558Srgrimes	 * for that reason.
3431558Srgrimes	 */
3441558Srgrimes	if (flags & MNT_UPDATE)
3451558Srgrimes		optbuf = catopt(optbuf, "update");
3461558Srgrimes
3471558Srgrimes	argc = 0;
3481558Srgrimes	argv[argc++] = vfstype;
3491558Srgrimes	mangle(optbuf, &argc, argv);
3501558Srgrimes	argv[argc++] = spec;
3511558Srgrimes	argv[argc++] = name;
3521558Srgrimes	argv[argc] = NULL;
3531558Srgrimes
3541558Srgrimes	if (debug) {
3551558Srgrimes		(void)printf("exec: mount_%s", vfstype);
3561558Srgrimes		for (i = 1; i < argc; i++)
3571558Srgrimes			(void)printf(" %s", argv[i]);
3581558Srgrimes		(void)printf("\n");
3591558Srgrimes		return (0);
3601558Srgrimes	}
3611558Srgrimes
3621558Srgrimes	switch (pid = vfork()) {
3631558Srgrimes	case -1:				/* Error. */
3641558Srgrimes		warn("vfork");
3651558Srgrimes		free(optbuf);
3661558Srgrimes		return (1);
3671558Srgrimes	case 0:					/* Child. */
3681558Srgrimes		if (strcmp(vfstype, "ufs") == 0)
3691558Srgrimes			exit(mount_ufs(argc, (char * const *) argv));
3701558Srgrimes
3711558Srgrimes		/* Go find an executable. */
37214626Sasami		for (edir = edirs; *edir; edir++) {
3731558Srgrimes			(void)snprintf(execname,
3741558Srgrimes			    sizeof(execname), "%s/mount_%s", *edir, vfstype);
3751558Srgrimes			execv(execname, (char * const *)argv);
37614626Sasami		}
37714626Sasami		if (errno == ENOENT) {
37814626Sasami			int len = 0;
37914626Sasami			char *cp;
38014626Sasami			for (edir = edirs; *edir; edir++)
38114626Sasami				len += strlen(*edir) + 2;	/* ", " */
38214626Sasami			if ((cp = malloc(len)) == NULL) {
38314626Sasami				warn(NULL);
38414626Sasami				exit(1);
38514626Sasami			}
38614626Sasami			cp[0] = '\0';
38714626Sasami			for (edir = edirs; *edir; edir++) {
38814626Sasami				strcat(cp, *edir);
38914626Sasami				if (edir[1] != NULL)
39014626Sasami					strcat(cp, ", ");
39114626Sasami			}
39214626Sasami			warn("exec mount_%s not found in %s", vfstype, cp);
39314626Sasami		}
3941558Srgrimes		exit(1);
3951558Srgrimes		/* NOTREACHED */
3961558Srgrimes	default:				/* Parent. */
3971558Srgrimes		free(optbuf);
3981558Srgrimes
3991558Srgrimes		if (waitpid(pid, &status, 0) < 0) {
4001558Srgrimes			warn("waitpid");
4011558Srgrimes			return (1);
4021558Srgrimes		}
4031558Srgrimes
4041558Srgrimes		if (WIFEXITED(status)) {
4051558Srgrimes			if (WEXITSTATUS(status) != 0)
4061558Srgrimes				return (WEXITSTATUS(status));
4071558Srgrimes		} else if (WIFSIGNALED(status)) {
4081558Srgrimes			warnx("%s: %s", name, sys_siglist[WTERMSIG(status)]);
4091558Srgrimes			return (1);
4101558Srgrimes		}
4111558Srgrimes
4121558Srgrimes		if (verbose) {
4131558Srgrimes			if (statfs(name, &sf) < 0) {
41423678Speter				warn("statfs %s", name);
4151558Srgrimes				return (1);
4161558Srgrimes			}
41717243Sjkh			if (fstab_style)
41823678Speter				putfsent (&sf);
41917243Sjkh			else
42023678Speter				prmount(&sf);
4211558Srgrimes		}
4221558Srgrimes		break;
4231558Srgrimes	}
4241558Srgrimes
4251558Srgrimes	return (0);
4261558Srgrimes}
4271558Srgrimes
4281558Srgrimesvoid
42923678Speterprmount(sfp)
43023678Speter	struct statfs *sfp;
43123678Speter{
4321558Srgrimes	int flags;
4331558Srgrimes	struct opt *o;
43423678Speter	struct passwd *pw;
4351558Srgrimes	int f;
4361558Srgrimes
43723678Speter	(void)printf("%s on %s", sfp->f_mntfromname, sfp->f_mntonname);
4381558Srgrimes
43923678Speter	flags = sfp->f_flags & MNT_VISFLAGMASK;
4401558Srgrimes	for (f = 0, o = optnames; flags && o->o_opt; o++)
4411558Srgrimes		if (flags & o->o_opt) {
4421558Srgrimes			(void)printf("%s%s", !f++ ? " (" : ", ", o->o_name);
4431558Srgrimes			flags &= ~o->o_opt;
4441558Srgrimes		}
44523678Speter	if (sfp->f_owner) {
44623678Speter		(void)printf("%smounted by ", !f++ ? " (" : ", ");
44723678Speter		if ((pw = getpwuid(sfp->f_owner)) != NULL)
44823678Speter			(void)printf("%s", pw->pw_name);
44923678Speter		else
45023678Speter			(void)printf("%d", sfp->f_owner);
45123678Speter	}
4521558Srgrimes	(void)printf(f ? ")\n" : "\n");
4531558Srgrimes}
4541558Srgrimes
4551558Srgrimesstruct statfs *
4561558Srgrimesgetmntpt(name)
4571558Srgrimes	const char *name;
4581558Srgrimes{
4591558Srgrimes	struct statfs *mntbuf;
4601558Srgrimes	int i, mntsize;
4611558Srgrimes
4621558Srgrimes	mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
4631558Srgrimes	for (i = 0; i < mntsize; i++)
4641558Srgrimes		if (strcmp(mntbuf[i].f_mntfromname, name) == 0 ||
4651558Srgrimes		    strcmp(mntbuf[i].f_mntonname, name) == 0)
4661558Srgrimes			return (&mntbuf[i]);
4671558Srgrimes	return (NULL);
4681558Srgrimes}
4691558Srgrimes
4701558Srgrimeschar *
4711558Srgrimescatopt(s0, s1)
4721558Srgrimes	char *s0;
4731558Srgrimes	const char *s1;
4741558Srgrimes{
4751558Srgrimes	size_t i;
4761558Srgrimes	char *cp;
4771558Srgrimes
4781558Srgrimes	if (s0 && *s0) {
4791558Srgrimes		i = strlen(s0) + strlen(s1) + 1 + 1;
4801558Srgrimes		if ((cp = malloc(i)) == NULL)
4811558Srgrimes			err(1, NULL);
4821558Srgrimes		(void)snprintf(cp, i, "%s,%s", s0, s1);
4831558Srgrimes	} else
4841558Srgrimes		cp = strdup(s1);
4851558Srgrimes
4861558Srgrimes	if (s0)
4871558Srgrimes		free(s0);
4881558Srgrimes	return (cp);
4891558Srgrimes}
4901558Srgrimes
4911558Srgrimesvoid
4921558Srgrimesmangle(options, argcp, argv)
4931558Srgrimes	char *options;
4941558Srgrimes	int *argcp;
4951558Srgrimes	const char **argv;
4961558Srgrimes{
4971558Srgrimes	char *p, *s;
4981558Srgrimes	int argc;
4991558Srgrimes
5001558Srgrimes	argc = *argcp;
5011558Srgrimes	for (s = options; (p = strsep(&s, ",")) != NULL;)
5021558Srgrimes		if (*p != '\0')
5031558Srgrimes			if (*p == '-') {
5041558Srgrimes				argv[argc++] = p;
5051558Srgrimes				p = strchr(p, '=');
5061558Srgrimes				if (p) {
5071558Srgrimes					*p = '\0';
5081558Srgrimes					argv[argc++] = p+1;
5091558Srgrimes				}
5101558Srgrimes			} else if (strcmp(p, "rw") != 0) {
5111558Srgrimes				argv[argc++] = "-o";
5121558Srgrimes				argv[argc++] = p;
5131558Srgrimes			}
5141558Srgrimes
5151558Srgrimes	*argcp = argc;
5161558Srgrimes}
5171558Srgrimes
5181558Srgrimesvoid
5191558Srgrimesusage()
5201558Srgrimes{
5211558Srgrimes
5221558Srgrimes	(void)fprintf(stderr,
5231558Srgrimes		"usage: mount %s %s\n       mount %s\n       mount %s\n",
52417243Sjkh		"[-dfpruvw] [-o options] [-t ufs | external_type]",
5251558Srgrimes			"special node",
52617243Sjkh		"[-adfpruvw] [-t ufs | external_type]",
52717243Sjkh		"[-dfpruvw] special | node");
5281558Srgrimes	exit(1);
5291558Srgrimes}
53017243Sjkh
53117243Sjkhvoid
53217243Sjkhputfsent (ent)
53317243Sjkh    const struct statfs	    *ent;
53417243Sjkh{
53517243Sjkh    struct fstab    *fst;
53617243Sjkh
53717243Sjkh    printf ("%s\t%s\t%s %s",
53817243Sjkh	    ent->f_mntfromname, ent->f_mntonname,
53923678Speter	    ent->f_fstypename,
54017243Sjkh	    (ent->f_flags & MNT_RDONLY) ? "ro" : "rw");
54117243Sjkh
54217243Sjkh    if (ent->f_flags & MNT_SYNCHRONOUS)
54317243Sjkh	printf (",sync");
54417243Sjkh
54517243Sjkh    if (ent->f_flags & MNT_NOEXEC)
54617243Sjkh	printf (",noexec");
54717243Sjkh
54817243Sjkh    if (ent->f_flags & MNT_NOSUID)
54917243Sjkh	printf (",nosuid");
55017243Sjkh
55117243Sjkh    if (ent->f_flags & MNT_NODEV)
55217243Sjkh	printf (",nodev");
55317243Sjkh
55417243Sjkh    if (ent->f_flags & MNT_UNION)
55517243Sjkh	printf (",union");
55617243Sjkh
55717243Sjkh    if (ent->f_flags & MNT_ASYNC)
55817243Sjkh	printf (",async");
55917243Sjkh
56023678Speter    if (ent->f_flags & MNT_NOATIME)
56123678Speter	printf (",noatime");
56223678Speter
56317243Sjkh    if (fst = getfsspec (ent->f_mntfromname))
56417243Sjkh	printf ("\t%u %u\n", fst->fs_freq, fst->fs_passno);
56517243Sjkh    else if (fst = getfsfile (ent->f_mntonname))
56617243Sjkh	printf ("\t%u %u\n", fst->fs_freq, fst->fs_passno);
56717243Sjkh    else if (ent->f_type == MOUNT_UFS)
56817243Sjkh	printf ("\t1 1\n");
56917243Sjkh    else
57017243Sjkh	printf ("\t0 0\n");
57117243Sjkh}
572