xref: /onnv-gate/usr/src/cmd/fs.d/smbclnt/mount/mount.c (revision 12019:cfe7a7d0d7f0)
16007Sthurlow /*
26007Sthurlow  * Copyright (c) 2000-2001, Boris Popov
36007Sthurlow  * All rights reserved.
46007Sthurlow  *
56007Sthurlow  * Redistribution and use in source and binary forms, with or without
66007Sthurlow  * modification, are permitted provided that the following conditions
76007Sthurlow  * are met:
86007Sthurlow  * 1. Redistributions of source code must retain the above copyright
96007Sthurlow  *    notice, this list of conditions and the following disclaimer.
106007Sthurlow  * 2. Redistributions in binary form must reproduce the above copyright
116007Sthurlow  *    notice, this list of conditions and the following disclaimer in the
126007Sthurlow  *    documentation and/or other materials provided with the distribution.
136007Sthurlow  * 3. All advertising materials mentioning features or use of this software
146007Sthurlow  *    must display the following acknowledgement:
156007Sthurlow  *    This product includes software developed by Boris Popov.
166007Sthurlow  * 4. Neither the name of the author nor the names of any co-contributors
176007Sthurlow  *    may be used to endorse or promote products derived from this software
186007Sthurlow  *    without specific prior written permission.
196007Sthurlow  *
206007Sthurlow  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
216007Sthurlow  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
226007Sthurlow  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
236007Sthurlow  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
246007Sthurlow  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
256007Sthurlow  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
266007Sthurlow  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
276007Sthurlow  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
286007Sthurlow  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
296007Sthurlow  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
306007Sthurlow  * SUCH DAMAGE.
316007Sthurlow  *
326007Sthurlow  * $Id: mount_smbfs.c,v 1.28.44.2 2005/06/02 00:55:41 lindak Exp $
336007Sthurlow  */
346007Sthurlow 
356007Sthurlow /*
3611564SGordon.Ross@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
376007Sthurlow  * Use is subject to license terms.
386007Sthurlow  */
396007Sthurlow 
406007Sthurlow #include <stdio.h>
416007Sthurlow #include <string.h>
426007Sthurlow #include <strings.h>
436007Sthurlow #include <pwd.h>
446007Sthurlow #include <grp.h>
456007Sthurlow #include <unistd.h>
466007Sthurlow #include <ctype.h>
476007Sthurlow #include <stdlib.h>
486007Sthurlow #include <errno.h>
496007Sthurlow #include <err.h>
506007Sthurlow #include <libintl.h>
516007Sthurlow #include <locale.h>
526007Sthurlow #include <libscf.h>
53*12019SGordon.Ross@Sun.COM #include <priv_utils.h>
546007Sthurlow 
5510023SGordon.Ross@Sun.COM #include <sys/types.h>
5610023SGordon.Ross@Sun.COM #include <sys/stat.h>
5710023SGordon.Ross@Sun.COM #include <sys/errno.h>
5810023SGordon.Ross@Sun.COM #include <sys/mount.h>
596007Sthurlow #include <sys/mntent.h>
606007Sthurlow #include <sys/mnttab.h>
616007Sthurlow 
6211332SGordon.Ross@Sun.COM #include <sys/fs/smbfs_mount.h>
6311332SGordon.Ross@Sun.COM 
6410023SGordon.Ross@Sun.COM /* This needs to know ctx->ct_dev_fd, etc. */
656007Sthurlow #include <netsmb/smb_lib.h>
666007Sthurlow 
6710023SGordon.Ross@Sun.COM extern char *optarg;
6810023SGordon.Ross@Sun.COM extern int optind;
6911564SGordon.Ross@Sun.COM int enable_noacl_option = 0;
7010023SGordon.Ross@Sun.COM 
716007Sthurlow static char mount_point[MAXPATHLEN + 1];
726007Sthurlow static void usage(void);
7311332SGordon.Ross@Sun.COM static int setsubopt(smb_ctx_t *, struct smbfs_args *, char *);
7411332SGordon.Ross@Sun.COM 
7511332SGordon.Ross@Sun.COM const char * const optlist[] = {
766007Sthurlow 
7711332SGordon.Ross@Sun.COM 	/* Generic VFS options. */
7811332SGordon.Ross@Sun.COM #define	OPT_RO		0
7911332SGordon.Ross@Sun.COM 	MNTOPT_RO,
8011332SGordon.Ross@Sun.COM #define	OPT_RW		1
8111332SGordon.Ross@Sun.COM 	MNTOPT_RW,
8211332SGordon.Ross@Sun.COM #define	OPT_SUID 	2
8311332SGordon.Ross@Sun.COM 	MNTOPT_SUID,
8411332SGordon.Ross@Sun.COM #define	OPT_NOSUID 	3
8511332SGordon.Ross@Sun.COM 	MNTOPT_NOSUID,
8611332SGordon.Ross@Sun.COM #define	OPT_DEVICES	4
8711332SGordon.Ross@Sun.COM 	MNTOPT_DEVICES,
8811332SGordon.Ross@Sun.COM #define	OPT_NODEVICES	5
8911332SGordon.Ross@Sun.COM 	MNTOPT_NODEVICES,
9011332SGordon.Ross@Sun.COM #define	OPT_SETUID	6
9111332SGordon.Ross@Sun.COM 	MNTOPT_SETUID,
9211332SGordon.Ross@Sun.COM #define	OPT_NOSETUID	7
9311332SGordon.Ross@Sun.COM 	MNTOPT_NOSETUID,
9411332SGordon.Ross@Sun.COM #define	OPT_EXEC	8
9511332SGordon.Ross@Sun.COM 	MNTOPT_EXEC,
9611332SGordon.Ross@Sun.COM #define	OPT_NOEXEC	9
9711332SGordon.Ross@Sun.COM 	MNTOPT_NOEXEC,
9811332SGordon.Ross@Sun.COM #define	OPT_XATTR	10
9911332SGordon.Ross@Sun.COM 	MNTOPT_XATTR,
10011332SGordon.Ross@Sun.COM #define	OPT_NOXATTR	11
10111332SGordon.Ross@Sun.COM 	MNTOPT_NOXATTR,
1026007Sthurlow 
10311332SGordon.Ross@Sun.COM 	/* Sort of generic (from NFS) */
10411332SGordon.Ross@Sun.COM #define	OPT_NOAC	12
10511332SGordon.Ross@Sun.COM 	MNTOPT_NOAC,
10611332SGordon.Ross@Sun.COM #define	OPT_ACTIMEO	13
10711332SGordon.Ross@Sun.COM 	MNTOPT_ACTIMEO,
10811332SGordon.Ross@Sun.COM #define	OPT_ACREGMIN	14
10911332SGordon.Ross@Sun.COM 	MNTOPT_ACREGMIN,
11011332SGordon.Ross@Sun.COM #define	OPT_ACREGMAX	15
11111332SGordon.Ross@Sun.COM 	MNTOPT_ACREGMAX,
11211332SGordon.Ross@Sun.COM #define	OPT_ACDIRMIN	16
11311332SGordon.Ross@Sun.COM 	MNTOPT_ACDIRMIN,
11411332SGordon.Ross@Sun.COM #define	OPT_ACDIRMAX	17
11511332SGordon.Ross@Sun.COM 	MNTOPT_ACDIRMAX,
1166007Sthurlow 
11711332SGordon.Ross@Sun.COM 	/* smbfs-specifis options */
11811332SGordon.Ross@Sun.COM #define	OPT_DOMAIN	18
11911332SGordon.Ross@Sun.COM 	"domain",
12011332SGordon.Ross@Sun.COM #define	OPT_USER	19
12111332SGordon.Ross@Sun.COM 	"user",
12211332SGordon.Ross@Sun.COM #define	OPT_UID		20
12311332SGordon.Ross@Sun.COM 	"uid",
12411332SGordon.Ross@Sun.COM #define	OPT_GID		21
12511332SGordon.Ross@Sun.COM 	"gid",
12611332SGordon.Ross@Sun.COM #define	OPT_DIRPERMS	22
12711332SGordon.Ross@Sun.COM 	"dirperms",
12811332SGordon.Ross@Sun.COM #define	OPT_FILEPERMS	23
12911332SGordon.Ross@Sun.COM 	"fileperms",
13011332SGordon.Ross@Sun.COM #define	OPT_NOPROMPT	24
13111332SGordon.Ross@Sun.COM 	"noprompt",
13211564SGordon.Ross@Sun.COM #define	OPT_ACL		25
13311564SGordon.Ross@Sun.COM 	MNTOPT_ACL,
13411564SGordon.Ross@Sun.COM #define	OPT_NOACL	26
13511564SGordon.Ross@Sun.COM 	MNTOPT_NOACL,
13611332SGordon.Ross@Sun.COM 
13711332SGordon.Ross@Sun.COM 	NULL
1386007Sthurlow };
1396007Sthurlow 
1406007Sthurlow static int Oflg = 0;    /* Overlay mounts */
1416007Sthurlow static int qflg = 0;    /* quiet - don't print warnings on bad options */
1426007Sthurlow static int noprompt = 0;	/* don't prompt for password */
1436007Sthurlow 
14411332SGordon.Ross@Sun.COM /* Note: smbfs uses _both_ kinds of options. */
14511332SGordon.Ross@Sun.COM static int mntflags = MS_DATA | MS_OPTIONSTR;
14611332SGordon.Ross@Sun.COM 
14711332SGordon.Ross@Sun.COM #define	EX_OK	0	/* normal */
14811332SGordon.Ross@Sun.COM #define	EX_OPT	1	/* bad options, usage, etc */
14911332SGordon.Ross@Sun.COM #define	EX_MNT	2	/* mount point problems, etc */
15011332SGordon.Ross@Sun.COM #define	RET_ERR	3	/* later errors */
15111332SGordon.Ross@Sun.COM 
1526007Sthurlow #define	SERVICE "svc:/network/smb/client:default"
1536007Sthurlow 
15410023SGordon.Ross@Sun.COM struct smbfs_args mdata;
15510023SGordon.Ross@Sun.COM struct mnttab mnt;
15611332SGordon.Ross@Sun.COM 
15711332SGordon.Ross@Sun.COM /*
15811332SGordon.Ross@Sun.COM  * Initialize this with "rw" just to have something there,
15911332SGordon.Ross@Sun.COM  * so we don't have to decide whether to add a comma when
16011332SGordon.Ross@Sun.COM  * we strcat another option.  Note the "rw" may be changed
16111332SGordon.Ross@Sun.COM  * to an "ro" by option processing.
16211332SGordon.Ross@Sun.COM  */
16311332SGordon.Ross@Sun.COM char optbuf[MAX_MNTOPT_STR] = "rw";
16410023SGordon.Ross@Sun.COM 
1656007Sthurlow int
main(int argc,char * argv[])1666007Sthurlow main(int argc, char *argv[])
1676007Sthurlow {
16810023SGordon.Ross@Sun.COM 	struct smb_ctx *ctx = NULL;
1696007Sthurlow 	struct stat st;
17011332SGordon.Ross@Sun.COM 	int opt, error, err2;
1716007Sthurlow 	static char *fstype = MNTTYPE_SMBFS;
1726007Sthurlow 	char *env, *state;
1736007Sthurlow 
1746007Sthurlow 	(void) setlocale(LC_ALL, "");
1756007Sthurlow #if !defined(TEXT_DOMAIN)
1766007Sthurlow #define	TEXT_DOMAIN	"SYS_TEST"
1776007Sthurlow #endif
1786007Sthurlow 	(void) textdomain(TEXT_DOMAIN);
179*12019SGordon.Ross@Sun.COM 
180*12019SGordon.Ross@Sun.COM 	/*
181*12019SGordon.Ross@Sun.COM 	 * Normal users are allowed to run "mount -F smbfs ..."
182*12019SGordon.Ross@Sun.COM 	 * to mount on a directory they own.  To allow that, this
183*12019SGordon.Ross@Sun.COM 	 * program is installed setuid root, and it adds SYS_MOUNT
184*12019SGordon.Ross@Sun.COM 	 * privilege here (if needed), and then restores the user's
185*12019SGordon.Ross@Sun.COM 	 * normal privileges.  When root runs this, it's a no-op.
186*12019SGordon.Ross@Sun.COM 	 */
187*12019SGordon.Ross@Sun.COM 	if (__init_suid_priv(0, PRIV_SYS_MOUNT, (char *)NULL) < 0) {
188*12019SGordon.Ross@Sun.COM 		(void) fprintf(stderr,
189*12019SGordon.Ross@Sun.COM 		    gettext("Insufficient privileges, "
190*12019SGordon.Ross@Sun.COM 		    "%s must be set-uid root\n"), argv[0]);
191*12019SGordon.Ross@Sun.COM 		exit(RET_ERR);
192*12019SGordon.Ross@Sun.COM 	}
193*12019SGordon.Ross@Sun.COM 
1946007Sthurlow 	if (argc == 2) {
1956007Sthurlow 		if (strcmp(argv[1], "-h") == 0) {
1966007Sthurlow 			usage();
1976007Sthurlow 		} else if (strcmp(argv[1], "-v") == 0) {
1986007Sthurlow 			errx(EX_OK, gettext("version %d.%d.%d"),
1996007Sthurlow 			    SMBFS_VERSION / 100000,
2006007Sthurlow 			    (SMBFS_VERSION % 10000) / 1000,
2016007Sthurlow 			    (SMBFS_VERSION % 1000) / 100);
2026007Sthurlow 		}
2036007Sthurlow 	}
2046007Sthurlow 	if (argc < 3)
2056007Sthurlow 		usage();
2066007Sthurlow 
2076007Sthurlow 	state = smf_get_state(SERVICE);
2086007Sthurlow 	if (state == NULL || strcmp(state, SCF_STATE_STRING_ONLINE) != 0) {
2096007Sthurlow 		fprintf(stderr,
2106007Sthurlow 		    gettext("mount_smbfs: service \"%s\" not enabled.\n"),
2116007Sthurlow 		    SERVICE);
21210023SGordon.Ross@Sun.COM 		exit(RET_ERR);
2136007Sthurlow 	}
21410023SGordon.Ross@Sun.COM 	free(state);
2156007Sthurlow 
2166007Sthurlow 	/* Debugging support. */
2176007Sthurlow 	if ((env = getenv("SMBFS_DEBUG")) != NULL) {
2186007Sthurlow 		smb_debug = atoi(env);
2196007Sthurlow 		if (smb_debug < 1)
2206007Sthurlow 			smb_debug = 1;
2216007Sthurlow 	}
2226007Sthurlow 
2236007Sthurlow 	error = smb_lib_init();
2246007Sthurlow 	if (error)
22510023SGordon.Ross@Sun.COM 		exit(RET_ERR);
2266007Sthurlow 
2276007Sthurlow 	mnt.mnt_mntopts = optbuf;
22810023SGordon.Ross@Sun.COM 
2296007Sthurlow 	bzero(&mdata, sizeof (mdata));
23010023SGordon.Ross@Sun.COM 	mdata.version = SMBFS_VERSION;		/* smbfs mount version */
2316007Sthurlow 	mdata.uid = (uid_t)-1;
2326007Sthurlow 	mdata.gid = (gid_t)-1;
2336007Sthurlow 
23410023SGordon.Ross@Sun.COM 	error = smb_ctx_alloc(&ctx);
2356007Sthurlow 	if (error)
23610023SGordon.Ross@Sun.COM 		exit(RET_ERR);
23710023SGordon.Ross@Sun.COM 
23810023SGordon.Ross@Sun.COM 	/*
23910023SGordon.Ross@Sun.COM 	 * Parse the UNC path so we have the server (etc.)
24010023SGordon.Ross@Sun.COM 	 * that we need during rcfile+sharectl parsing.
24110023SGordon.Ross@Sun.COM 	 */
24210023SGordon.Ross@Sun.COM 	if (argc < 3)
24310023SGordon.Ross@Sun.COM 		usage();
24410023SGordon.Ross@Sun.COM 	error = smb_ctx_parseunc(ctx, argv[argc - 2],
24510023SGordon.Ross@Sun.COM 	    SMBL_SHARE, SMBL_SHARE, USE_DISKDEV, NULL);
24610023SGordon.Ross@Sun.COM 	if (error)
24711332SGordon.Ross@Sun.COM 		exit(EX_OPT);
24810023SGordon.Ross@Sun.COM 
2496007Sthurlow 	error = smb_ctx_readrc(ctx);
2506007Sthurlow 	if (error)
25111332SGordon.Ross@Sun.COM 		exit(EX_OPT);
2526007Sthurlow 
2536007Sthurlow 	while ((opt = getopt(argc, argv, "ro:Oq")) != -1) {
2546007Sthurlow 		switch (opt) {
2556007Sthurlow 		case 'O':
2566007Sthurlow 			Oflg++;
2576007Sthurlow 			break;
2586007Sthurlow 
2596007Sthurlow 		case 'q':
2606007Sthurlow 			qflg++;
2616007Sthurlow 			break;
2626007Sthurlow 
2636007Sthurlow 		case 'r':
26411332SGordon.Ross@Sun.COM 			mntflags |= MS_RDONLY;
2656007Sthurlow 			break;
2666007Sthurlow 
2676007Sthurlow 		case 'o': {
26811332SGordon.Ross@Sun.COM 			char *nextopt, *comma, *sopt;
26911332SGordon.Ross@Sun.COM 			int ret;
2706007Sthurlow 
2716007Sthurlow 			for (sopt = optarg; sopt != NULL; sopt = nextopt) {
2726007Sthurlow 				comma = strchr(sopt, ',');
2736007Sthurlow 				if (comma) {
2746007Sthurlow 					nextopt = comma + 1;
2756007Sthurlow 					*comma = '\0';
2766007Sthurlow 				} else
2776007Sthurlow 					nextopt = NULL;
27811332SGordon.Ross@Sun.COM 				ret = setsubopt(ctx, &mdata, sopt);
2796007Sthurlow 				if (ret != 0)
28011332SGordon.Ross@Sun.COM 					exit(EX_OPT);
28111332SGordon.Ross@Sun.COM 				/* undo changes to optarg */
2826007Sthurlow 				if (comma)
2836007Sthurlow 					*comma = ',';
2846007Sthurlow 			}
2856007Sthurlow 			break;
2866007Sthurlow 		}
2876007Sthurlow 
2886007Sthurlow 		case '?':
2896007Sthurlow 		default:
2906007Sthurlow 			usage();
2916007Sthurlow 		}
2926007Sthurlow 	}
2936007Sthurlow 
2946007Sthurlow 	if (Oflg)
2956007Sthurlow 		mntflags |= MS_OVERLAY;
2966007Sthurlow 
29711332SGordon.Ross@Sun.COM 	if (mntflags & MS_RDONLY) {
2986007Sthurlow 		char *p;
2996007Sthurlow 		/* convert "rw"->"ro" */
30011332SGordon.Ross@Sun.COM 		if (p = strstr(optbuf, "rw")) {
3016007Sthurlow 			if (*(p+2) == ',' || *(p+2) == '\0')
3026007Sthurlow 				*(p+1) = 'o';
3036007Sthurlow 		}
3046007Sthurlow 	}
3056007Sthurlow 
30610023SGordon.Ross@Sun.COM 	if (optind + 2 != argc)
30710023SGordon.Ross@Sun.COM 		usage();
30810023SGordon.Ross@Sun.COM 
3096007Sthurlow 	mnt.mnt_special = argv[optind];
3106007Sthurlow 	mnt.mnt_mountp = argv[optind+1];
3116007Sthurlow 
31210023SGordon.Ross@Sun.COM 	realpath(argv[optind+1], mount_point);
3136007Sthurlow 	if (stat(mount_point, &st) == -1)
31411332SGordon.Ross@Sun.COM 		err(EX_MNT, gettext("could not find mount point %s"),
3156007Sthurlow 		    mount_point);
3166007Sthurlow 	if (!S_ISDIR(st.st_mode)) {
3176007Sthurlow 		errno = ENOTDIR;
31811332SGordon.Ross@Sun.COM 		err(EX_MNT, gettext("can't mount on %s"), mount_point);
3196007Sthurlow 	}
3206007Sthurlow 
3216007Sthurlow 	/*
3229035SGordon.Ross@Sun.COM 	 * Fill in mdata defaults.
3236007Sthurlow 	 */
3246007Sthurlow 	if (mdata.uid == (uid_t)-1)
3256007Sthurlow 		mdata.uid = getuid();
3266007Sthurlow 	if (mdata.gid == (gid_t)-1)
3276007Sthurlow 		mdata.gid = getgid();
3286007Sthurlow 	if (mdata.file_mode == 0)
3299035SGordon.Ross@Sun.COM 		mdata.file_mode = S_IRWXU;
3306007Sthurlow 	if (mdata.dir_mode == 0) {
3316007Sthurlow 		mdata.dir_mode = mdata.file_mode;
3326007Sthurlow 		if (mdata.dir_mode & S_IRUSR)
3336007Sthurlow 			mdata.dir_mode |= S_IXUSR;
3346007Sthurlow 		if (mdata.dir_mode & S_IRGRP)
3356007Sthurlow 			mdata.dir_mode |= S_IXGRP;
3366007Sthurlow 		if (mdata.dir_mode & S_IROTH)
3376007Sthurlow 			mdata.dir_mode |= S_IXOTH;
3386007Sthurlow 	}
3396007Sthurlow 
34010023SGordon.Ross@Sun.COM 	ctx->ct_ssn.ssn_owner = SMBM_ANY_OWNER;
3416007Sthurlow 	if (noprompt)
3426007Sthurlow 		ctx->ct_flags |= SMBCF_NOPWD;
3436007Sthurlow 
3446007Sthurlow 	/*
34510023SGordon.Ross@Sun.COM 	 * Resolve the server address,
34610023SGordon.Ross@Sun.COM 	 * setup derived defaults.
3476007Sthurlow 	 */
3486007Sthurlow 	error = smb_ctx_resolve(ctx);
3496007Sthurlow 	if (error)
35010023SGordon.Ross@Sun.COM 		exit(RET_ERR);
3516007Sthurlow 
35210023SGordon.Ross@Sun.COM 	/*
35310023SGordon.Ross@Sun.COM 	 * Have server, share, etc. from above:
35410023SGordon.Ross@Sun.COM 	 * smb_ctx_scan_argv, option settings.
35510023SGordon.Ross@Sun.COM 	 * Get the session and tree.
35610023SGordon.Ross@Sun.COM 	 */
3576007Sthurlow again:
35810023SGordon.Ross@Sun.COM 	error = smb_ctx_get_ssn(ctx);
35910023SGordon.Ross@Sun.COM 	if (error == EAUTH && noprompt == 0) {
36010023SGordon.Ross@Sun.COM 		err2 = smb_get_authentication(ctx);
36110023SGordon.Ross@Sun.COM 		if (err2 == 0)
36210023SGordon.Ross@Sun.COM 			goto again;
3636007Sthurlow 	}
36410023SGordon.Ross@Sun.COM 	if (error) {
36510023SGordon.Ross@Sun.COM 		smb_error(gettext("//%s: login failed"),
36610023SGordon.Ross@Sun.COM 		    error, ctx->ct_fullserver);
36710023SGordon.Ross@Sun.COM 		exit(RET_ERR);
3686007Sthurlow 	}
36910023SGordon.Ross@Sun.COM 
37010023SGordon.Ross@Sun.COM 	error = smb_ctx_get_tree(ctx);
37110023SGordon.Ross@Sun.COM 	if (error) {
37210023SGordon.Ross@Sun.COM 		smb_error(gettext("//%s/%s: tree connect failed"),
37310023SGordon.Ross@Sun.COM 		    error, ctx->ct_fullserver, ctx->ct_origshare);
37410023SGordon.Ross@Sun.COM 		exit(RET_ERR);
37510023SGordon.Ross@Sun.COM 	}
3766007Sthurlow 
37710023SGordon.Ross@Sun.COM 	/*
37810023SGordon.Ross@Sun.COM 	 * Have tree connection, now mount it.
37910023SGordon.Ross@Sun.COM 	 */
38010023SGordon.Ross@Sun.COM 	mdata.devfd = ctx->ct_dev_fd;
3816007Sthurlow 
382*12019SGordon.Ross@Sun.COM 	/* Need sys_mount privilege for the mount call. */
383*12019SGordon.Ross@Sun.COM 	(void) __priv_bracket(PRIV_ON);
384*12019SGordon.Ross@Sun.COM 	err2 = mount(mnt.mnt_special, mnt.mnt_mountp,
3856007Sthurlow 	    mntflags, fstype, &mdata, sizeof (mdata),
386*12019SGordon.Ross@Sun.COM 	    mnt.mnt_mntopts, MAX_MNTOPT_STR);
387*12019SGordon.Ross@Sun.COM 	(void) __priv_bracket(PRIV_OFF);
388*12019SGordon.Ross@Sun.COM 
389*12019SGordon.Ross@Sun.COM 	if (err2 < 0) {
3906007Sthurlow 		if (errno != ENOENT) {
39111332SGordon.Ross@Sun.COM 			err(EX_MNT, gettext("mount_smbfs: %s"),
39210023SGordon.Ross@Sun.COM 			    mnt.mnt_mountp);
3936007Sthurlow 		} else {
3946007Sthurlow 			struct stat sb;
39510023SGordon.Ross@Sun.COM 			if (stat(mnt.mnt_mountp, &sb) < 0 &&
3966007Sthurlow 			    errno == ENOENT)
39711332SGordon.Ross@Sun.COM 				err(EX_MNT, gettext("mount_smbfs: %s"),
39810023SGordon.Ross@Sun.COM 				    mnt.mnt_mountp);
3996007Sthurlow 			else
40011332SGordon.Ross@Sun.COM 				err(EX_MNT, gettext("mount_smbfs: %s"),
40110023SGordon.Ross@Sun.COM 				    mnt.mnt_special);
4026007Sthurlow 		}
4036007Sthurlow 	}
4046007Sthurlow 
40510023SGordon.Ross@Sun.COM 	smb_ctx_free(ctx);
4066007Sthurlow 	return (0);
4076007Sthurlow }
4086007Sthurlow 
40911332SGordon.Ross@Sun.COM #define	bad(val) (val == NULL || !isdigit(*val))
41011332SGordon.Ross@Sun.COM 
4116007Sthurlow int
setsubopt(smb_ctx_t * ctx,struct smbfs_args * mdatap,char * subopt)41211332SGordon.Ross@Sun.COM setsubopt(smb_ctx_t *ctx, struct smbfs_args *mdatap, char *subopt)
4136007Sthurlow {
41411332SGordon.Ross@Sun.COM 	char *equals, *optarg;
4156007Sthurlow 	struct passwd *pwd;
4166007Sthurlow 	struct group *grp;
41711332SGordon.Ross@Sun.COM 	long val;
41811332SGordon.Ross@Sun.COM 	int rc = EX_OK;
41911332SGordon.Ross@Sun.COM 	int index;
42011332SGordon.Ross@Sun.COM 	char *p;
42111332SGordon.Ross@Sun.COM 
42211332SGordon.Ross@Sun.COM 	equals = strchr(subopt, '=');
42311332SGordon.Ross@Sun.COM 	if (equals) {
42411332SGordon.Ross@Sun.COM 		*equals = '\0';
42511332SGordon.Ross@Sun.COM 		optarg = equals + 1;
42611332SGordon.Ross@Sun.COM 	} else
42711332SGordon.Ross@Sun.COM 		optarg = NULL;
42811332SGordon.Ross@Sun.COM 
42911332SGordon.Ross@Sun.COM 	for (index = 0; optlist[index] != NULL; index++) {
43011332SGordon.Ross@Sun.COM 		if (strcmp(subopt, optlist[index]) == 0)
43111332SGordon.Ross@Sun.COM 			break;
43211332SGordon.Ross@Sun.COM 	}
43311332SGordon.Ross@Sun.COM 
43411332SGordon.Ross@Sun.COM 	/*
43511332SGordon.Ross@Sun.COM 	 * Note: if the option was unknown, index will
43611332SGordon.Ross@Sun.COM 	 * point to the NULL at the end of optlist[],
43711332SGordon.Ross@Sun.COM 	 * and we'll take the switch default.
43811332SGordon.Ross@Sun.COM 	 */
4396007Sthurlow 
4406007Sthurlow 	switch (index) {
44111332SGordon.Ross@Sun.COM 
44211564SGordon.Ross@Sun.COM 	case OPT_ACL:
44311564SGordon.Ross@Sun.COM 	case OPT_NOACL:
44411564SGordon.Ross@Sun.COM 		/* Some of our tests use this. */
44511564SGordon.Ross@Sun.COM 		if (enable_noacl_option == 0)
44611564SGordon.Ross@Sun.COM 			goto badopt;
44711564SGordon.Ross@Sun.COM 		/* fallthrough */
4486007Sthurlow 	case OPT_SUID:
4496007Sthurlow 	case OPT_NOSUID:
4506007Sthurlow 	case OPT_DEVICES:
4516007Sthurlow 	case OPT_NODEVICES:
4526007Sthurlow 	case OPT_SETUID:
4536007Sthurlow 	case OPT_NOSETUID:
4546007Sthurlow 	case OPT_EXEC:
4556007Sthurlow 	case OPT_NOEXEC:
45611332SGordon.Ross@Sun.COM 	case OPT_XATTR:
45711332SGordon.Ross@Sun.COM 	case OPT_NOXATTR:
45811332SGordon.Ross@Sun.COM 		/*
45911332SGordon.Ross@Sun.COM 		 * These options are handled via the
46011332SGordon.Ross@Sun.COM 		 * generic option string mechanism.
46111332SGordon.Ross@Sun.COM 		 * None of these take an optarg.
46211332SGordon.Ross@Sun.COM 		 */
46311332SGordon.Ross@Sun.COM 		if (optarg != NULL)
46411332SGordon.Ross@Sun.COM 			goto badval;
46511332SGordon.Ross@Sun.COM 		(void) strlcat(optbuf, ",", sizeof (optbuf));
46611332SGordon.Ross@Sun.COM 		if (strlcat(optbuf, subopt, sizeof (optbuf)) >=
46711332SGordon.Ross@Sun.COM 		    sizeof (optbuf)) {
46811332SGordon.Ross@Sun.COM 			if (!qflg)
46911332SGordon.Ross@Sun.COM 				warnx(gettext("option string too long"));
47011332SGordon.Ross@Sun.COM 			rc = EX_OPT;
47111332SGordon.Ross@Sun.COM 		}
47211332SGordon.Ross@Sun.COM 		break;
47311332SGordon.Ross@Sun.COM 
47411332SGordon.Ross@Sun.COM 	/*
47511332SGordon.Ross@Sun.COM 	 * OPT_RO, OPT_RW, are actually generic too,
47611332SGordon.Ross@Sun.COM 	 * but we use the mntflags for these, and
47711332SGordon.Ross@Sun.COM 	 * then update the options string later.
47811332SGordon.Ross@Sun.COM 	 */
47911332SGordon.Ross@Sun.COM 	case OPT_RO:
48011332SGordon.Ross@Sun.COM 		mntflags |= MS_RDONLY;
48111332SGordon.Ross@Sun.COM 		break;
48211332SGordon.Ross@Sun.COM 	case OPT_RW:
48311332SGordon.Ross@Sun.COM 		mntflags &= ~MS_RDONLY;
48411332SGordon.Ross@Sun.COM 		break;
48511332SGordon.Ross@Sun.COM 
48611332SGordon.Ross@Sun.COM 	/*
48711332SGordon.Ross@Sun.COM 	 * NFS-derived options for attribute cache
48811332SGordon.Ross@Sun.COM 	 * handling (disable, set min/max timeouts)
48911332SGordon.Ross@Sun.COM 	 */
49011332SGordon.Ross@Sun.COM 	case OPT_NOAC:
49111332SGordon.Ross@Sun.COM 		mdatap->flags |= SMBFS_MF_NOAC;
49211332SGordon.Ross@Sun.COM 		break;
49310023SGordon.Ross@Sun.COM 
49411332SGordon.Ross@Sun.COM 	case OPT_ACTIMEO:
49511332SGordon.Ross@Sun.COM 		errno = 0;
49611332SGordon.Ross@Sun.COM 		val = strtol(optarg, &p, 10);
49711332SGordon.Ross@Sun.COM 		if (errno || *p != 0)
49811332SGordon.Ross@Sun.COM 			goto badval;
49911332SGordon.Ross@Sun.COM 		mdatap->acdirmin = mdatap->acregmin = val;
50011332SGordon.Ross@Sun.COM 		mdatap->acdirmax = mdatap->acregmax = val;
50111332SGordon.Ross@Sun.COM 		mdatap->flags |= SMBFS_MF_ACDIRMAX;
50211332SGordon.Ross@Sun.COM 		mdatap->flags |= SMBFS_MF_ACREGMAX;
50311332SGordon.Ross@Sun.COM 		mdatap->flags |= SMBFS_MF_ACDIRMIN;
50411332SGordon.Ross@Sun.COM 		mdatap->flags |= SMBFS_MF_ACREGMIN;
50511332SGordon.Ross@Sun.COM 		break;
50611332SGordon.Ross@Sun.COM 
50711332SGordon.Ross@Sun.COM 	case OPT_ACREGMIN:
50811332SGordon.Ross@Sun.COM 		errno = 0;
50911332SGordon.Ross@Sun.COM 		val = strtol(optarg, &p, 10);
51011332SGordon.Ross@Sun.COM 		if (errno || *p != 0)
51111332SGordon.Ross@Sun.COM 			goto badval;
51211332SGordon.Ross@Sun.COM 		mdatap->acregmin = val;
51311332SGordon.Ross@Sun.COM 		mdatap->flags |= SMBFS_MF_ACREGMIN;
51411332SGordon.Ross@Sun.COM 		break;
51511332SGordon.Ross@Sun.COM 
51611332SGordon.Ross@Sun.COM 	case OPT_ACREGMAX:
51711332SGordon.Ross@Sun.COM 		errno = 0;
51811332SGordon.Ross@Sun.COM 		val = strtol(optarg, &p, 10);
51911332SGordon.Ross@Sun.COM 		if (errno || *p != 0)
52011332SGordon.Ross@Sun.COM 			goto badval;
52111332SGordon.Ross@Sun.COM 		mdatap->acregmax = val;
52211332SGordon.Ross@Sun.COM 		mdatap->flags |= SMBFS_MF_ACREGMAX;
52311332SGordon.Ross@Sun.COM 		break;
52411332SGordon.Ross@Sun.COM 
52511332SGordon.Ross@Sun.COM 	case OPT_ACDIRMIN:
52611332SGordon.Ross@Sun.COM 		errno = 0;
52711332SGordon.Ross@Sun.COM 		val = strtol(optarg, &p, 10);
52811332SGordon.Ross@Sun.COM 		if (errno || *p != 0)
52911332SGordon.Ross@Sun.COM 			goto badval;
53011332SGordon.Ross@Sun.COM 		mdatap->acdirmin = val;
53111332SGordon.Ross@Sun.COM 		mdatap->flags |= SMBFS_MF_ACDIRMIN;
53211332SGordon.Ross@Sun.COM 		break;
53311332SGordon.Ross@Sun.COM 
53411332SGordon.Ross@Sun.COM 	case OPT_ACDIRMAX:
53511332SGordon.Ross@Sun.COM 		errno = 0;
53611332SGordon.Ross@Sun.COM 		val = strtol(optarg, &p, 10);
53711332SGordon.Ross@Sun.COM 		if (errno || *p != 0)
53811332SGordon.Ross@Sun.COM 			goto badval;
53911332SGordon.Ross@Sun.COM 		mdatap->acdirmax = val;
54011332SGordon.Ross@Sun.COM 		mdatap->flags |= SMBFS_MF_ACDIRMAX;
54111332SGordon.Ross@Sun.COM 		break;
54211332SGordon.Ross@Sun.COM 
54311332SGordon.Ross@Sun.COM 	/*
54411332SGordon.Ross@Sun.COM 	 * SMBFS-specific options.  Some of these
54511332SGordon.Ross@Sun.COM 	 * don't go through the mount system call,
54611332SGordon.Ross@Sun.COM 	 * but just set libsmbfs options.
54711332SGordon.Ross@Sun.COM 	 */
54810023SGordon.Ross@Sun.COM 	case OPT_DOMAIN:
54911332SGordon.Ross@Sun.COM 		if (smb_ctx_setdomain(ctx, optarg, B_TRUE) != 0)
55011332SGordon.Ross@Sun.COM 			rc = EX_OPT;
55110023SGordon.Ross@Sun.COM 		break;
55210023SGordon.Ross@Sun.COM 
55310023SGordon.Ross@Sun.COM 	case OPT_USER:
55411332SGordon.Ross@Sun.COM 		if (smb_ctx_setuser(ctx, optarg, B_TRUE) != 0)
55511332SGordon.Ross@Sun.COM 			rc = EX_OPT;
55610023SGordon.Ross@Sun.COM 		break;
55710023SGordon.Ross@Sun.COM 
5586007Sthurlow 	case OPT_UID:
5596007Sthurlow 		pwd = isdigit(optarg[0]) ?
5606007Sthurlow 		    getpwuid(atoi(optarg)) : getpwnam(optarg);
5616007Sthurlow 		if (pwd == NULL) {
5626007Sthurlow 			if (!qflg)
5636007Sthurlow 				warnx(gettext("unknown user '%s'"), optarg);
56411332SGordon.Ross@Sun.COM 			rc = EX_OPT;
5656007Sthurlow 		} else {
5666007Sthurlow 			mdatap->uid = pwd->pw_uid;
5676007Sthurlow 		}
5686007Sthurlow 		break;
56911332SGordon.Ross@Sun.COM 
5706007Sthurlow 	case OPT_GID:
5716007Sthurlow 		grp = isdigit(optarg[0]) ?
5726007Sthurlow 		    getgrgid(atoi(optarg)) : getgrnam(optarg);
5736007Sthurlow 		if (grp == NULL) {
5746007Sthurlow 			if (!qflg)
5756007Sthurlow 				warnx(gettext("unknown group '%s'"), optarg);
57611332SGordon.Ross@Sun.COM 			rc = EX_OPT;
5776007Sthurlow 		} else {
5786007Sthurlow 			mdatap->gid = grp->gr_gid;
5796007Sthurlow 		}
5806007Sthurlow 		break;
58111332SGordon.Ross@Sun.COM 
5826007Sthurlow 	case OPT_DIRPERMS:
5836007Sthurlow 		errno = 0;
58411332SGordon.Ross@Sun.COM 		val = strtol(optarg, &p, 8);
58511332SGordon.Ross@Sun.COM 		if (errno || *p != 0)
58611332SGordon.Ross@Sun.COM 			goto badval;
58711332SGordon.Ross@Sun.COM 		mdatap->dir_mode = val;
5886007Sthurlow 		break;
58911332SGordon.Ross@Sun.COM 
5906007Sthurlow 	case OPT_FILEPERMS:
5916007Sthurlow 		errno = 0;
59211332SGordon.Ross@Sun.COM 		val = strtol(optarg, &p, 8);
59311332SGordon.Ross@Sun.COM 		if (errno || *p != 0)
59411332SGordon.Ross@Sun.COM 			goto badval;
59511332SGordon.Ross@Sun.COM 		mdatap->file_mode = val;
5966007Sthurlow 		break;
59711332SGordon.Ross@Sun.COM 
5986007Sthurlow 	case OPT_NOPROMPT:
5996007Sthurlow 		noprompt++;
60011332SGordon.Ross@Sun.COM 		break;
60111332SGordon.Ross@Sun.COM 
60211332SGordon.Ross@Sun.COM 	default:
60311564SGordon.Ross@Sun.COM 	badopt:
60411332SGordon.Ross@Sun.COM 		if (!qflg)
60511332SGordon.Ross@Sun.COM 			warnx(gettext("unknown option %s"), subopt);
60611332SGordon.Ross@Sun.COM 		rc = EX_OPT;
60711332SGordon.Ross@Sun.COM 		break;
60811332SGordon.Ross@Sun.COM 
60911332SGordon.Ross@Sun.COM 	badval:
61011332SGordon.Ross@Sun.COM 		if (!qflg)
61111332SGordon.Ross@Sun.COM 			warnx(gettext("invalid value for %s"), subopt);
61211332SGordon.Ross@Sun.COM 		rc = EX_OPT;
61311332SGordon.Ross@Sun.COM 		break;
6146007Sthurlow 	}
61511332SGordon.Ross@Sun.COM 
61611332SGordon.Ross@Sun.COM 	/* Undo changes made to subopt */
61711332SGordon.Ross@Sun.COM 	if (equals)
61811332SGordon.Ross@Sun.COM 		*equals = '=';
61911332SGordon.Ross@Sun.COM 
62011332SGordon.Ross@Sun.COM 	return (rc);
6216007Sthurlow }
6226007Sthurlow 
6236007Sthurlow static void
usage(void)6246007Sthurlow usage(void)
6256007Sthurlow {
6266007Sthurlow 	fprintf(stderr, "%s\n",
6276007Sthurlow 	gettext("usage: mount -F smbfs [-Orq] [-o option[,option]]"
6286007Sthurlow 	"	//[workgroup;][user[:password]@]server[/share] path"));
6296007Sthurlow 
63011332SGordon.Ross@Sun.COM 	exit(EX_OPT);
6316007Sthurlow }
632