xref: /titanic_44/usr/src/cmd/fs.d/autofs/automount.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  *	automount.c
24*7c478bd9Sstevel@tonic-gate  *
25*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
26*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
27*7c478bd9Sstevel@tonic-gate  */
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #include <ctype.h>
32*7c478bd9Sstevel@tonic-gate #include <stdio.h>
33*7c478bd9Sstevel@tonic-gate #include <unistd.h>
34*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
35*7c478bd9Sstevel@tonic-gate #include <locale.h>
36*7c478bd9Sstevel@tonic-gate #include <stdarg.h>
37*7c478bd9Sstevel@tonic-gate #include <errno.h>
38*7c478bd9Sstevel@tonic-gate #include <string.h>
39*7c478bd9Sstevel@tonic-gate #include <dirent.h>
40*7c478bd9Sstevel@tonic-gate #include <signal.h>
41*7c478bd9Sstevel@tonic-gate #include <syslog.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
47*7c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/mntent.h>
49*7c478bd9Sstevel@tonic-gate #include <sys/mount.h>
50*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
51*7c478bd9Sstevel@tonic-gate #include <sys/tiuser.h>
52*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
53*7c478bd9Sstevel@tonic-gate #include <rpcsvc/nfs_prot.h>
54*7c478bd9Sstevel@tonic-gate #include <nsswitch.h>
55*7c478bd9Sstevel@tonic-gate #include <deflt.h>
56*7c478bd9Sstevel@tonic-gate #include <rpcsvc/daemon_utils.h>
57*7c478bd9Sstevel@tonic-gate #include "automount.h"
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate static int mkdir_r(char *);
60*7c478bd9Sstevel@tonic-gate struct autodir *dir_head;
61*7c478bd9Sstevel@tonic-gate struct autodir *dir_tail;
62*7c478bd9Sstevel@tonic-gate static struct extmnttab *find_mount();
63*7c478bd9Sstevel@tonic-gate int verbose = 0;
64*7c478bd9Sstevel@tonic-gate int trace = 0;
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate static void usage();
67*7c478bd9Sstevel@tonic-gate static int compare_opts(char *, char *);
68*7c478bd9Sstevel@tonic-gate static void do_unmounts();
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate static int mount_timeout = AUTOFS_MOUNT_TIMEOUT;
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate static char	*service_list[] = { AUTOMOUNTD, NULL };
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate /*
75*7c478bd9Sstevel@tonic-gate  * XXX
76*7c478bd9Sstevel@tonic-gate  * The following are needed because they're used in auto_subr.c and
77*7c478bd9Sstevel@tonic-gate  * we link with it. Should avoid this.
78*7c478bd9Sstevel@tonic-gate  */
79*7c478bd9Sstevel@tonic-gate mutex_t cleanup_lock;
80*7c478bd9Sstevel@tonic-gate cond_t cleanup_start_cv;
81*7c478bd9Sstevel@tonic-gate cond_t cleanup_done_cv;
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate main(argc, argv)
84*7c478bd9Sstevel@tonic-gate 	int argc;
85*7c478bd9Sstevel@tonic-gate 	char *argv[];
86*7c478bd9Sstevel@tonic-gate {
87*7c478bd9Sstevel@tonic-gate 	int c;
88*7c478bd9Sstevel@tonic-gate 	struct autofs_args ai;
89*7c478bd9Sstevel@tonic-gate 	struct utsname utsname;
90*7c478bd9Sstevel@tonic-gate 	char autofs_addr[MAXADDRLEN];
91*7c478bd9Sstevel@tonic-gate 	struct autodir *dir, *d;
92*7c478bd9Sstevel@tonic-gate 	struct stat stbuf;
93*7c478bd9Sstevel@tonic-gate 	char *master_map = "auto_master";
94*7c478bd9Sstevel@tonic-gate 	int null;
95*7c478bd9Sstevel@tonic-gate 	struct extmnttab mnt, *mntp;
96*7c478bd9Sstevel@tonic-gate 	struct mnttab *omntp;
97*7c478bd9Sstevel@tonic-gate 	char mntopts[MAX_MNTOPT_STR];
98*7c478bd9Sstevel@tonic-gate 	int mntflgs;
99*7c478bd9Sstevel@tonic-gate 	int count = 0;
100*7c478bd9Sstevel@tonic-gate 	char *stack[STACKSIZ];
101*7c478bd9Sstevel@tonic-gate 	char **stkptr;
102*7c478bd9Sstevel@tonic-gate 	char *defval;
103*7c478bd9Sstevel@tonic-gate 	struct sigaction sigintact;
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate 	/*
106*7c478bd9Sstevel@tonic-gate 	 * protect this command from session termination when run in background
107*7c478bd9Sstevel@tonic-gate 	 * we test background by whether SIGINT is ignored
108*7c478bd9Sstevel@tonic-gate 	 */
109*7c478bd9Sstevel@tonic-gate 	(void) sigaction(SIGINT, NULL, &sigintact);
110*7c478bd9Sstevel@tonic-gate 	if (sigintact.sa_sigaction == SIG_IGN) {
111*7c478bd9Sstevel@tonic-gate 		(void) signal(SIGHUP, SIG_IGN);
112*7c478bd9Sstevel@tonic-gate 		(void) setsid();
113*7c478bd9Sstevel@tonic-gate 	}
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate 	/*
116*7c478bd9Sstevel@tonic-gate 	 * Read in the values from config file first before we check
117*7c478bd9Sstevel@tonic-gate 	 * commandline options so the options override the file.
118*7c478bd9Sstevel@tonic-gate 	 */
119*7c478bd9Sstevel@tonic-gate 	if ((defopen(AUTOFSADMIN)) == 0) {
120*7c478bd9Sstevel@tonic-gate 		if ((defval = defread("AUTOMOUNT_TIMEOUT=")) != NULL) {
121*7c478bd9Sstevel@tonic-gate 			errno = 0;
122*7c478bd9Sstevel@tonic-gate 			mount_timeout = strtol(defval, (char **)NULL, 10);
123*7c478bd9Sstevel@tonic-gate 			if (errno != 0)
124*7c478bd9Sstevel@tonic-gate 				mount_timeout = AUTOFS_MOUNT_TIMEOUT;
125*7c478bd9Sstevel@tonic-gate 		}
126*7c478bd9Sstevel@tonic-gate 		if ((defval = defread("AUTOMOUNT_VERBOSE=")) != NULL) {
127*7c478bd9Sstevel@tonic-gate 			if (strncasecmp("true", defval, 4) == 0)
128*7c478bd9Sstevel@tonic-gate 				verbose = TRUE;
129*7c478bd9Sstevel@tonic-gate 			else
130*7c478bd9Sstevel@tonic-gate 				verbose = FALSE;
131*7c478bd9Sstevel@tonic-gate 		}
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 		/* close defaults file */
134*7c478bd9Sstevel@tonic-gate 		defopen(NULL);
135*7c478bd9Sstevel@tonic-gate 	}
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "mM:D:f:t:v?")) != EOF) {
138*7c478bd9Sstevel@tonic-gate 		switch (c) {
139*7c478bd9Sstevel@tonic-gate 		case 'm':
140*7c478bd9Sstevel@tonic-gate 			pr_msg("Warning: -m option not supported");
141*7c478bd9Sstevel@tonic-gate 			break;
142*7c478bd9Sstevel@tonic-gate 		case 'M':
143*7c478bd9Sstevel@tonic-gate 			pr_msg("Warning: -M option not supported");
144*7c478bd9Sstevel@tonic-gate 			break;
145*7c478bd9Sstevel@tonic-gate 		case 'D':
146*7c478bd9Sstevel@tonic-gate 			pr_msg("Warning: -D option not supported");
147*7c478bd9Sstevel@tonic-gate 			break;
148*7c478bd9Sstevel@tonic-gate 		case 'f':
149*7c478bd9Sstevel@tonic-gate 			pr_msg("Error: -f option no longer supported");
150*7c478bd9Sstevel@tonic-gate 			usage();
151*7c478bd9Sstevel@tonic-gate 			break;
152*7c478bd9Sstevel@tonic-gate 		case 't':
153*7c478bd9Sstevel@tonic-gate 			if (strchr(optarg, '=')) {
154*7c478bd9Sstevel@tonic-gate 				pr_msg("Error: invalid value for -t");
155*7c478bd9Sstevel@tonic-gate 				usage();
156*7c478bd9Sstevel@tonic-gate 			}
157*7c478bd9Sstevel@tonic-gate 			mount_timeout = atoi(optarg);
158*7c478bd9Sstevel@tonic-gate 			break;
159*7c478bd9Sstevel@tonic-gate 		case 'v':
160*7c478bd9Sstevel@tonic-gate 			verbose++;
161*7c478bd9Sstevel@tonic-gate 			break;
162*7c478bd9Sstevel@tonic-gate 		default:
163*7c478bd9Sstevel@tonic-gate 			usage();
164*7c478bd9Sstevel@tonic-gate 			break;
165*7c478bd9Sstevel@tonic-gate 		}
166*7c478bd9Sstevel@tonic-gate 	}
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate 	if (optind < argc) {
169*7c478bd9Sstevel@tonic-gate 		pr_msg("%s: command line mountpoints/maps "
170*7c478bd9Sstevel@tonic-gate 			"no longer supported",
171*7c478bd9Sstevel@tonic-gate 			argv[optind]);
172*7c478bd9Sstevel@tonic-gate 		usage();
173*7c478bd9Sstevel@tonic-gate 	}
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 	current_mounts = getmntlist();
176*7c478bd9Sstevel@tonic-gate 	if (current_mounts == NULL) {
177*7c478bd9Sstevel@tonic-gate 		pr_msg("Couldn't establish current mounts");
178*7c478bd9Sstevel@tonic-gate 		exit(1);
179*7c478bd9Sstevel@tonic-gate 	}
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate 	(void) umask(0);
182*7c478bd9Sstevel@tonic-gate 	ns_setup(stack, &stkptr);
183*7c478bd9Sstevel@tonic-gate 
184*7c478bd9Sstevel@tonic-gate 	openlog("automount", LOG_PID, LOG_DAEMON);
185*7c478bd9Sstevel@tonic-gate 	(void) loadmaster_map(master_map, "", stack, &stkptr);
186*7c478bd9Sstevel@tonic-gate 	if (dir_head != NULL) {
187*7c478bd9Sstevel@tonic-gate 		/*
188*7c478bd9Sstevel@tonic-gate 		 * automount maps found. enable services as needed.
189*7c478bd9Sstevel@tonic-gate 		 */
190*7c478bd9Sstevel@tonic-gate 		_check_services(service_list);
191*7c478bd9Sstevel@tonic-gate 	}
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate 	closelog();
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate 	if (uname(&utsname) < 0) {
196*7c478bd9Sstevel@tonic-gate 		pr_msg("uname: %m");
197*7c478bd9Sstevel@tonic-gate 		exit(1);
198*7c478bd9Sstevel@tonic-gate 	}
199*7c478bd9Sstevel@tonic-gate 	(void) strcpy(autofs_addr, utsname.nodename);
200*7c478bd9Sstevel@tonic-gate 	(void) strcat(autofs_addr, ".autofs");
201*7c478bd9Sstevel@tonic-gate 	ai.addr.buf	= autofs_addr;
202*7c478bd9Sstevel@tonic-gate 	ai.addr.len	= strlen(ai.addr.buf);
203*7c478bd9Sstevel@tonic-gate 	ai.addr.maxlen	= ai.addr.len;
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate 	ai.mount_to	= mount_timeout;
206*7c478bd9Sstevel@tonic-gate 	ai.rpc_to	= AUTOFS_RPC_TIMEOUT;
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate 	/*
209*7c478bd9Sstevel@tonic-gate 	 * Mount the daemon at its mount points.
210*7c478bd9Sstevel@tonic-gate 	 */
211*7c478bd9Sstevel@tonic-gate 	for (dir = dir_head; dir; dir = dir->dir_next) {
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate 		/*
214*7c478bd9Sstevel@tonic-gate 		 * Skip null entries
215*7c478bd9Sstevel@tonic-gate 		 */
216*7c478bd9Sstevel@tonic-gate 		if (strcmp(dir->dir_map, "-null") == 0)
217*7c478bd9Sstevel@tonic-gate 			continue;
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate 		/*
220*7c478bd9Sstevel@tonic-gate 		 * Skip null'ed entries
221*7c478bd9Sstevel@tonic-gate 		 */
222*7c478bd9Sstevel@tonic-gate 		null = 0;
223*7c478bd9Sstevel@tonic-gate 		for (d = dir->dir_prev; d; d = d->dir_prev) {
224*7c478bd9Sstevel@tonic-gate 			if (strcmp(dir->dir_name, d->dir_name) == 0)
225*7c478bd9Sstevel@tonic-gate 				null = 1;
226*7c478bd9Sstevel@tonic-gate 		}
227*7c478bd9Sstevel@tonic-gate 		if (null)
228*7c478bd9Sstevel@tonic-gate 			continue;
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate 		/*
231*7c478bd9Sstevel@tonic-gate 		 * Check whether there's already an entry
232*7c478bd9Sstevel@tonic-gate 		 * in the mnttab for this mountpoint.
233*7c478bd9Sstevel@tonic-gate 		 */
234*7c478bd9Sstevel@tonic-gate 		if (mntp = find_mount(dir->dir_name, 1)) {
235*7c478bd9Sstevel@tonic-gate 			/*
236*7c478bd9Sstevel@tonic-gate 			 * If it's not an autofs mount - don't
237*7c478bd9Sstevel@tonic-gate 			 * mount over it.
238*7c478bd9Sstevel@tonic-gate 			 */
239*7c478bd9Sstevel@tonic-gate 			if (strcmp(mntp->mnt_fstype, MNTTYPE_AUTOFS) != 0) {
240*7c478bd9Sstevel@tonic-gate 				pr_msg("%s: already mounted",
241*7c478bd9Sstevel@tonic-gate 					mntp->mnt_mountp);
242*7c478bd9Sstevel@tonic-gate 				continue;
243*7c478bd9Sstevel@tonic-gate 			}
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate 			/*
246*7c478bd9Sstevel@tonic-gate 			 * Compare the mnttab entry with the master map
247*7c478bd9Sstevel@tonic-gate 			 * entry.  If the map or mount options are
248*7c478bd9Sstevel@tonic-gate 			 * different, then update this information
249*7c478bd9Sstevel@tonic-gate 			 * with a remount.
250*7c478bd9Sstevel@tonic-gate 			 */
251*7c478bd9Sstevel@tonic-gate 			if (strcmp(mntp->mnt_special, dir->dir_map) == 0 &&
252*7c478bd9Sstevel@tonic-gate 				compare_opts(dir->dir_opts,
253*7c478bd9Sstevel@tonic-gate 					mntp->mnt_mntopts) == 0) {
254*7c478bd9Sstevel@tonic-gate 				continue;	/* no change */
255*7c478bd9Sstevel@tonic-gate 			}
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate 			/*
258*7c478bd9Sstevel@tonic-gate 			 * Check for an overlaid direct autofs mount.
259*7c478bd9Sstevel@tonic-gate 			 * Cannot remount since it's inaccessible.
260*7c478bd9Sstevel@tonic-gate 			 */
261*7c478bd9Sstevel@tonic-gate 			omntp = (struct mnttab *)mntp;
262*7c478bd9Sstevel@tonic-gate 			if (hasmntopt(omntp, "direct") != NULL) {
263*7c478bd9Sstevel@tonic-gate 				mntp = find_mount(dir->dir_name, 0);
264*7c478bd9Sstevel@tonic-gate 				omntp = (struct mnttab *)mntp;
265*7c478bd9Sstevel@tonic-gate 				if (hasmntopt(omntp, "direct") == NULL) {
266*7c478bd9Sstevel@tonic-gate 					if (verbose)
267*7c478bd9Sstevel@tonic-gate 						pr_msg("%s: cannot remount",
268*7c478bd9Sstevel@tonic-gate 							dir->dir_name);
269*7c478bd9Sstevel@tonic-gate 					continue;
270*7c478bd9Sstevel@tonic-gate 				}
271*7c478bd9Sstevel@tonic-gate 			}
272*7c478bd9Sstevel@tonic-gate 
273*7c478bd9Sstevel@tonic-gate 			dir->dir_remount = 1;
274*7c478bd9Sstevel@tonic-gate 		}
275*7c478bd9Sstevel@tonic-gate 
276*7c478bd9Sstevel@tonic-gate 		/*
277*7c478bd9Sstevel@tonic-gate 		 * Create a mount point if necessary
278*7c478bd9Sstevel@tonic-gate 		 * If the path refers to an existing symbolic
279*7c478bd9Sstevel@tonic-gate 		 * link, refuse to mount on it.  This avoids
280*7c478bd9Sstevel@tonic-gate 		 * future problems.
281*7c478bd9Sstevel@tonic-gate 		 */
282*7c478bd9Sstevel@tonic-gate 		if (lstat(dir->dir_name, &stbuf) == 0) {
283*7c478bd9Sstevel@tonic-gate 			if ((stbuf.st_mode & S_IFMT) != S_IFDIR) {
284*7c478bd9Sstevel@tonic-gate 				pr_msg("%s: Not a directory", dir->dir_name);
285*7c478bd9Sstevel@tonic-gate 				continue;
286*7c478bd9Sstevel@tonic-gate 			}
287*7c478bd9Sstevel@tonic-gate 		} else {
288*7c478bd9Sstevel@tonic-gate 			if (mkdir_r(dir->dir_name)) {
289*7c478bd9Sstevel@tonic-gate 				pr_msg("%s: %m", dir->dir_name);
290*7c478bd9Sstevel@tonic-gate 				continue;
291*7c478bd9Sstevel@tonic-gate 			}
292*7c478bd9Sstevel@tonic-gate 		}
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 		ai.path 	= dir->dir_name;
295*7c478bd9Sstevel@tonic-gate 		ai.opts		= dir->dir_opts;
296*7c478bd9Sstevel@tonic-gate 		ai.map		= dir->dir_map;
297*7c478bd9Sstevel@tonic-gate 		ai.subdir	= "";
298*7c478bd9Sstevel@tonic-gate 		ai.direct 	= dir->dir_direct;
299*7c478bd9Sstevel@tonic-gate 		if (dir->dir_direct)
300*7c478bd9Sstevel@tonic-gate 			ai.key = dir->dir_name;
301*7c478bd9Sstevel@tonic-gate 		else
302*7c478bd9Sstevel@tonic-gate 			ai.key = "";
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate 		(void) sprintf(mntopts, "ignore,%s",
305*7c478bd9Sstevel@tonic-gate 			dir->dir_direct  ? "direct" : "indirect");
306*7c478bd9Sstevel@tonic-gate 		if (dir->dir_opts && *dir->dir_opts) {
307*7c478bd9Sstevel@tonic-gate 			(void) strcat(mntopts, ",");
308*7c478bd9Sstevel@tonic-gate 			(void) strcat(mntopts, dir->dir_opts);
309*7c478bd9Sstevel@tonic-gate 		}
310*7c478bd9Sstevel@tonic-gate 		mntflgs = MS_OPTIONSTR | (dir->dir_remount ? MS_REMOUNT : 0);
311*7c478bd9Sstevel@tonic-gate 		if (mount(dir->dir_map, dir->dir_name, MS_DATA | mntflgs,
312*7c478bd9Sstevel@tonic-gate 				MNTTYPE_AUTOFS, &ai, sizeof (ai), mntopts,
313*7c478bd9Sstevel@tonic-gate 				MAX_MNTOPT_STR) < 0) {
314*7c478bd9Sstevel@tonic-gate 			pr_msg("mount %s: %m", dir->dir_name);
315*7c478bd9Sstevel@tonic-gate 			continue;
316*7c478bd9Sstevel@tonic-gate 		}
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate 		count++;
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate 		if (verbose) {
321*7c478bd9Sstevel@tonic-gate 			if (dir->dir_remount)
322*7c478bd9Sstevel@tonic-gate 				pr_msg("%s remounted", dir->dir_name);
323*7c478bd9Sstevel@tonic-gate 			else
324*7c478bd9Sstevel@tonic-gate 				pr_msg("%s mounted", dir->dir_name);
325*7c478bd9Sstevel@tonic-gate 		}
326*7c478bd9Sstevel@tonic-gate 	}
327*7c478bd9Sstevel@tonic-gate 
328*7c478bd9Sstevel@tonic-gate 	if (verbose && count == 0)
329*7c478bd9Sstevel@tonic-gate 		pr_msg("no mounts");
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate 	/*
332*7c478bd9Sstevel@tonic-gate 	 * Now compare the /etc/mnttab with the master
333*7c478bd9Sstevel@tonic-gate 	 * map.  Any autofs mounts in the /etc/mnttab
334*7c478bd9Sstevel@tonic-gate 	 * that are not in the master map must be
335*7c478bd9Sstevel@tonic-gate 	 * unmounted
336*7c478bd9Sstevel@tonic-gate 	 */
337*7c478bd9Sstevel@tonic-gate 	do_unmounts();
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate 	return (0);
340*7c478bd9Sstevel@tonic-gate }
341*7c478bd9Sstevel@tonic-gate 
342*7c478bd9Sstevel@tonic-gate /*
343*7c478bd9Sstevel@tonic-gate  * Find a mount entry given
344*7c478bd9Sstevel@tonic-gate  * the mountpoint path.
345*7c478bd9Sstevel@tonic-gate  * Optionally return the first
346*7c478bd9Sstevel@tonic-gate  * or last entry.
347*7c478bd9Sstevel@tonic-gate  */
348*7c478bd9Sstevel@tonic-gate static struct extmnttab *
349*7c478bd9Sstevel@tonic-gate find_mount(mntpnt, first)
350*7c478bd9Sstevel@tonic-gate 	char *mntpnt;
351*7c478bd9Sstevel@tonic-gate 	int first;
352*7c478bd9Sstevel@tonic-gate {
353*7c478bd9Sstevel@tonic-gate 	struct mntlist *mntl;
354*7c478bd9Sstevel@tonic-gate 	struct extmnttab *found = NULL;
355*7c478bd9Sstevel@tonic-gate 
356*7c478bd9Sstevel@tonic-gate 	for (mntl = current_mounts; mntl; mntl = mntl->mntl_next) {
357*7c478bd9Sstevel@tonic-gate 
358*7c478bd9Sstevel@tonic-gate 		if (strcmp(mntpnt, mntl->mntl_mnt->mnt_mountp) == 0) {
359*7c478bd9Sstevel@tonic-gate 			found = mntl->mntl_mnt;
360*7c478bd9Sstevel@tonic-gate 			if (first)
361*7c478bd9Sstevel@tonic-gate 				break;
362*7c478bd9Sstevel@tonic-gate 		}
363*7c478bd9Sstevel@tonic-gate 	}
364*7c478bd9Sstevel@tonic-gate 
365*7c478bd9Sstevel@tonic-gate 	return (found);
366*7c478bd9Sstevel@tonic-gate }
367*7c478bd9Sstevel@tonic-gate 
368*7c478bd9Sstevel@tonic-gate static char *ignore_opts[] = {"ignore", "direct", "indirect", "dev", NULL};
369*7c478bd9Sstevel@tonic-gate 
370*7c478bd9Sstevel@tonic-gate /*
371*7c478bd9Sstevel@tonic-gate  * Compare mount options
372*7c478bd9Sstevel@tonic-gate  * ignoring "ignore", "direct", "indirect"
373*7c478bd9Sstevel@tonic-gate  * and "dev=".
374*7c478bd9Sstevel@tonic-gate  */
375*7c478bd9Sstevel@tonic-gate static int
376*7c478bd9Sstevel@tonic-gate compare_opts(opts, mntopts)
377*7c478bd9Sstevel@tonic-gate 	char *opts, *mntopts;
378*7c478bd9Sstevel@tonic-gate {
379*7c478bd9Sstevel@tonic-gate 	char optbuf1[MAX_MNTOPT_STR], *s = optbuf1;
380*7c478bd9Sstevel@tonic-gate 	char optbuf2[MAX_MNTOPT_STR];
381*7c478bd9Sstevel@tonic-gate 	char **opttbl1, **opttbl2;
382*7c478bd9Sstevel@tonic-gate 	int nopts1, nopts2;
383*7c478bd9Sstevel@tonic-gate 	char *ostart, *optr, *valp;
384*7c478bd9Sstevel@tonic-gate 	int j, i, notsame;
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate 	opttbl1 = opttbl2 = NULL;
387*7c478bd9Sstevel@tonic-gate 	/*
388*7c478bd9Sstevel@tonic-gate 	 * Parse the two option strings to split them both into
389*7c478bd9Sstevel@tonic-gate 	 * lists of individual options.
390*7c478bd9Sstevel@tonic-gate 	 */
391*7c478bd9Sstevel@tonic-gate 	if (mntopts != NULL)
392*7c478bd9Sstevel@tonic-gate 		(void) strcpy(s, mntopts);
393*7c478bd9Sstevel@tonic-gate 	else
394*7c478bd9Sstevel@tonic-gate 		*s = '\0';
395*7c478bd9Sstevel@tonic-gate 	if (*s != '\0')
396*7c478bd9Sstevel@tonic-gate 		nopts1 = 1;
397*7c478bd9Sstevel@tonic-gate 	else
398*7c478bd9Sstevel@tonic-gate 		nopts1 = 0;
399*7c478bd9Sstevel@tonic-gate 	for (s = strchr(s, ','); s != NULL; s = strchr(s, ',')) {
400*7c478bd9Sstevel@tonic-gate 		nopts1++;
401*7c478bd9Sstevel@tonic-gate 		s++;
402*7c478bd9Sstevel@tonic-gate 	}
403*7c478bd9Sstevel@tonic-gate 	if (nopts1)
404*7c478bd9Sstevel@tonic-gate 		if ((opttbl1 = memalign(sizeof (char *),
405*7c478bd9Sstevel@tonic-gate 			nopts1 * sizeof (char *))) == NULL)
406*7c478bd9Sstevel@tonic-gate 			return (1);
407*7c478bd9Sstevel@tonic-gate 	nopts1 = 0;
408*7c478bd9Sstevel@tonic-gate 	s = optbuf1;
409*7c478bd9Sstevel@tonic-gate 	for (ostart = optr = s; *optr != '\0'; ostart = optr) {
410*7c478bd9Sstevel@tonic-gate 		if (getsubopt(&optr, ignore_opts, &valp) == -1) {
411*7c478bd9Sstevel@tonic-gate 			opttbl1[nopts1++] = ostart;
412*7c478bd9Sstevel@tonic-gate 		}
413*7c478bd9Sstevel@tonic-gate 	}
414*7c478bd9Sstevel@tonic-gate 	s = optbuf2;
415*7c478bd9Sstevel@tonic-gate 	if (opts != NULL)
416*7c478bd9Sstevel@tonic-gate 		(void) strcpy(s, opts);
417*7c478bd9Sstevel@tonic-gate 	else
418*7c478bd9Sstevel@tonic-gate 		*s = '\0';
419*7c478bd9Sstevel@tonic-gate 	if (*s != '\0')
420*7c478bd9Sstevel@tonic-gate 		nopts2 = 1;
421*7c478bd9Sstevel@tonic-gate 	else
422*7c478bd9Sstevel@tonic-gate 		nopts2 = 0;
423*7c478bd9Sstevel@tonic-gate 	for (s = strchr(s, ','); s != NULL; s = strchr(s, ',')) {
424*7c478bd9Sstevel@tonic-gate 		nopts2++;
425*7c478bd9Sstevel@tonic-gate 		s++;
426*7c478bd9Sstevel@tonic-gate 	}
427*7c478bd9Sstevel@tonic-gate 	if (nopts2)
428*7c478bd9Sstevel@tonic-gate 		if ((opttbl2 = memalign(sizeof (char *),
429*7c478bd9Sstevel@tonic-gate 			nopts2 * sizeof (char *))) == NULL) {
430*7c478bd9Sstevel@tonic-gate 			notsame = 1;
431*7c478bd9Sstevel@tonic-gate 			goto done;
432*7c478bd9Sstevel@tonic-gate 		}
433*7c478bd9Sstevel@tonic-gate 	nopts2 = 0;
434*7c478bd9Sstevel@tonic-gate 	s = optbuf2;
435*7c478bd9Sstevel@tonic-gate 	for (ostart = optr = s; *optr != '\0'; ostart = optr) {
436*7c478bd9Sstevel@tonic-gate 		if (getsubopt(&optr, ignore_opts, &valp) == -1) {
437*7c478bd9Sstevel@tonic-gate 			opttbl2[nopts2++] = ostart;
438*7c478bd9Sstevel@tonic-gate 		}
439*7c478bd9Sstevel@tonic-gate 	}
440*7c478bd9Sstevel@tonic-gate 	if (nopts2 != nopts1) {
441*7c478bd9Sstevel@tonic-gate 		notsame = 1;
442*7c478bd9Sstevel@tonic-gate 		goto done;
443*7c478bd9Sstevel@tonic-gate 	}
444*7c478bd9Sstevel@tonic-gate 	notsame = 0;
445*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < nopts1; i++) {
446*7c478bd9Sstevel@tonic-gate 		notsame = 1;
447*7c478bd9Sstevel@tonic-gate 		for (j = 0; j < nopts2; j++) {
448*7c478bd9Sstevel@tonic-gate 			if (strcmp(opttbl1[i], opttbl2[j]) == 0) {
449*7c478bd9Sstevel@tonic-gate 				notsame = 0;
450*7c478bd9Sstevel@tonic-gate 				break;
451*7c478bd9Sstevel@tonic-gate 			}
452*7c478bd9Sstevel@tonic-gate 		}
453*7c478bd9Sstevel@tonic-gate 		if (notsame)
454*7c478bd9Sstevel@tonic-gate 			break;
455*7c478bd9Sstevel@tonic-gate 	}
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate done:
458*7c478bd9Sstevel@tonic-gate 	if (opttbl1 != NULL)
459*7c478bd9Sstevel@tonic-gate 		free(opttbl1);
460*7c478bd9Sstevel@tonic-gate 	if (opttbl2 != NULL)
461*7c478bd9Sstevel@tonic-gate 		free(opttbl2);
462*7c478bd9Sstevel@tonic-gate 	return (notsame);
463*7c478bd9Sstevel@tonic-gate }
464*7c478bd9Sstevel@tonic-gate 
465*7c478bd9Sstevel@tonic-gate static void
466*7c478bd9Sstevel@tonic-gate usage()
467*7c478bd9Sstevel@tonic-gate {
468*7c478bd9Sstevel@tonic-gate 	pr_msg("Usage: automount  [ -v ]  [ -t duration ]");
469*7c478bd9Sstevel@tonic-gate 	exit(1);
470*7c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
471*7c478bd9Sstevel@tonic-gate }
472*7c478bd9Sstevel@tonic-gate 
473*7c478bd9Sstevel@tonic-gate /*
474*7c478bd9Sstevel@tonic-gate  * Unmount any autofs mounts that
475*7c478bd9Sstevel@tonic-gate  * aren't in the master map
476*7c478bd9Sstevel@tonic-gate  */
477*7c478bd9Sstevel@tonic-gate static void
478*7c478bd9Sstevel@tonic-gate do_unmounts()
479*7c478bd9Sstevel@tonic-gate {
480*7c478bd9Sstevel@tonic-gate 	struct mntlist *mntl;
481*7c478bd9Sstevel@tonic-gate 	struct extmnttab *mnt;
482*7c478bd9Sstevel@tonic-gate 	struct mnttab *omnt;
483*7c478bd9Sstevel@tonic-gate 	struct autodir *dir;
484*7c478bd9Sstevel@tonic-gate 	int current;
485*7c478bd9Sstevel@tonic-gate 	int count = 0;
486*7c478bd9Sstevel@tonic-gate 	struct zone_summary *zsp;
487*7c478bd9Sstevel@tonic-gate 
488*7c478bd9Sstevel@tonic-gate 	zsp = fs_get_zone_summaries();
489*7c478bd9Sstevel@tonic-gate 	if (zsp == NULL) {
490*7c478bd9Sstevel@tonic-gate 		pr_msg("Couldn't establish active zones");
491*7c478bd9Sstevel@tonic-gate 		exit(1);
492*7c478bd9Sstevel@tonic-gate 	}
493*7c478bd9Sstevel@tonic-gate 	for (mntl = current_mounts; mntl; mntl = mntl->mntl_next) {
494*7c478bd9Sstevel@tonic-gate 		mnt = mntl->mntl_mnt;
495*7c478bd9Sstevel@tonic-gate 		omnt = (struct mnttab *)mnt;
496*7c478bd9Sstevel@tonic-gate 		if (strcmp(mnt->mnt_fstype, MNTTYPE_AUTOFS) != 0)
497*7c478bd9Sstevel@tonic-gate 			continue;
498*7c478bd9Sstevel@tonic-gate 		if (fs_mount_in_other_zone(zsp, mnt->mnt_mountp))
499*7c478bd9Sstevel@tonic-gate 			continue;
500*7c478bd9Sstevel@tonic-gate 		/*
501*7c478bd9Sstevel@tonic-gate 		 * Don't unmount autofs mounts done
502*7c478bd9Sstevel@tonic-gate 		 * from the autofs mount command.
503*7c478bd9Sstevel@tonic-gate 		 * How do we tell them apart ?
504*7c478bd9Sstevel@tonic-gate 		 * Autofs mounts not eligible for auto-unmount
505*7c478bd9Sstevel@tonic-gate 		 * have the "nest" pseudo-option.
506*7c478bd9Sstevel@tonic-gate 		 */
507*7c478bd9Sstevel@tonic-gate 		if (hasmntopt(omnt, "nest") != NULL)
508*7c478bd9Sstevel@tonic-gate 			continue;
509*7c478bd9Sstevel@tonic-gate 
510*7c478bd9Sstevel@tonic-gate 		current = 0;
511*7c478bd9Sstevel@tonic-gate 		for (dir = dir_head; dir; dir = dir->dir_next) {
512*7c478bd9Sstevel@tonic-gate 			if (strcmp(dir->dir_name, mnt->mnt_mountp) == 0) {
513*7c478bd9Sstevel@tonic-gate 				current = strcmp(dir->dir_map, "-null");
514*7c478bd9Sstevel@tonic-gate 				break;
515*7c478bd9Sstevel@tonic-gate 			}
516*7c478bd9Sstevel@tonic-gate 		}
517*7c478bd9Sstevel@tonic-gate 		if (current)
518*7c478bd9Sstevel@tonic-gate 			continue;
519*7c478bd9Sstevel@tonic-gate 
520*7c478bd9Sstevel@tonic-gate 
521*7c478bd9Sstevel@tonic-gate 		if (umount(mnt->mnt_mountp) == 0) {
522*7c478bd9Sstevel@tonic-gate 			if (verbose) {
523*7c478bd9Sstevel@tonic-gate 				pr_msg("%s unmounted",
524*7c478bd9Sstevel@tonic-gate 					mnt->mnt_mountp);
525*7c478bd9Sstevel@tonic-gate 			}
526*7c478bd9Sstevel@tonic-gate 			count++;
527*7c478bd9Sstevel@tonic-gate 		}
528*7c478bd9Sstevel@tonic-gate 	}
529*7c478bd9Sstevel@tonic-gate 	if (verbose && count == 0)
530*7c478bd9Sstevel@tonic-gate 		pr_msg("no unmounts");
531*7c478bd9Sstevel@tonic-gate }
532*7c478bd9Sstevel@tonic-gate 
533*7c478bd9Sstevel@tonic-gate static int
534*7c478bd9Sstevel@tonic-gate mkdir_r(dir)
535*7c478bd9Sstevel@tonic-gate 	char *dir;
536*7c478bd9Sstevel@tonic-gate {
537*7c478bd9Sstevel@tonic-gate 	int err;
538*7c478bd9Sstevel@tonic-gate 	char *slash;
539*7c478bd9Sstevel@tonic-gate 
540*7c478bd9Sstevel@tonic-gate 	if (mkdir(dir, 0555) == 0 || errno == EEXIST)
541*7c478bd9Sstevel@tonic-gate 		return (0);
542*7c478bd9Sstevel@tonic-gate 	if (errno != ENOENT)
543*7c478bd9Sstevel@tonic-gate 		return (-1);
544*7c478bd9Sstevel@tonic-gate 	slash = strrchr(dir, '/');
545*7c478bd9Sstevel@tonic-gate 	if (slash == NULL)
546*7c478bd9Sstevel@tonic-gate 		return (-1);
547*7c478bd9Sstevel@tonic-gate 	*slash = '\0';
548*7c478bd9Sstevel@tonic-gate 	err = mkdir_r(dir);
549*7c478bd9Sstevel@tonic-gate 	*slash++ = '/';
550*7c478bd9Sstevel@tonic-gate 	if (err || !*slash)
551*7c478bd9Sstevel@tonic-gate 		return (err);
552*7c478bd9Sstevel@tonic-gate 	return (mkdir(dir, 0555));
553*7c478bd9Sstevel@tonic-gate }
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate /*
556*7c478bd9Sstevel@tonic-gate  * Print an error.
557*7c478bd9Sstevel@tonic-gate  * Works like printf (fmt string and variable args)
558*7c478bd9Sstevel@tonic-gate  * except that it will subsititute an error message
559*7c478bd9Sstevel@tonic-gate  * for a "%m" string (like syslog).
560*7c478bd9Sstevel@tonic-gate  */
561*7c478bd9Sstevel@tonic-gate /* VARARGS1 */
562*7c478bd9Sstevel@tonic-gate void
563*7c478bd9Sstevel@tonic-gate pr_msg(const char *fmt, ...)
564*7c478bd9Sstevel@tonic-gate {
565*7c478bd9Sstevel@tonic-gate 	va_list ap;
566*7c478bd9Sstevel@tonic-gate 	char buf[BUFSIZ], *p2;
567*7c478bd9Sstevel@tonic-gate 	char *p1;
568*7c478bd9Sstevel@tonic-gate 	char *nfmt;
569*7c478bd9Sstevel@tonic-gate 
570*7c478bd9Sstevel@tonic-gate 	(void) strcpy(buf, "automount: ");
571*7c478bd9Sstevel@tonic-gate 	p2 = buf + strlen(buf);
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate 	nfmt = gettext(fmt);
574*7c478bd9Sstevel@tonic-gate 
575*7c478bd9Sstevel@tonic-gate 	for (p1 = nfmt; *p1; p1++) {
576*7c478bd9Sstevel@tonic-gate 		if (*p1 == '%' && *(p1+1) == 'm') {
577*7c478bd9Sstevel@tonic-gate 			if (errno < sys_nerr) {
578*7c478bd9Sstevel@tonic-gate 				(void) strcpy(p2, sys_errlist[errno]);
579*7c478bd9Sstevel@tonic-gate 				p2 += strlen(p2);
580*7c478bd9Sstevel@tonic-gate 			}
581*7c478bd9Sstevel@tonic-gate 			p1++;
582*7c478bd9Sstevel@tonic-gate 		} else {
583*7c478bd9Sstevel@tonic-gate 			*p2++ = *p1;
584*7c478bd9Sstevel@tonic-gate 		}
585*7c478bd9Sstevel@tonic-gate 	}
586*7c478bd9Sstevel@tonic-gate 	if (p2 > buf && *(p2-1) != '\n')
587*7c478bd9Sstevel@tonic-gate 		*p2++ = '\n';
588*7c478bd9Sstevel@tonic-gate 	*p2 = '\0';
589*7c478bd9Sstevel@tonic-gate 
590*7c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
591*7c478bd9Sstevel@tonic-gate 	(void) vfprintf(stderr, buf, ap);
592*7c478bd9Sstevel@tonic-gate 	va_end(ap);
593*7c478bd9Sstevel@tonic-gate }
594