xref: /illumos-gate/usr/src/cmd/fs.d/autofs/mount.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  *	autofs mount.c
27  *
28  */
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #include <stdio.h>
33 #include <unistd.h>
34 #include <stdlib.h>
35 #include <ctype.h>
36 #include <sys/param.h>
37 #include <sys/stat.h>
38 #include <sys/mntent.h>
39 #include <sys/mnttab.h>
40 #include <sys/mount.h>
41 #include <sys/utsname.h>
42 #include <sys/tiuser.h>
43 #include <string.h>
44 #include <fslib.h>
45 #include <errno.h>
46 #include <rpcsvc/daemon_utils.h>
47 #include "automount.h"
48 
49 #define	MNTTAB_OPTS	"ignore,nest"
50 
51 static void usage();
52 static void process_opts(char *options, int *directp);
53 static char *concat_opts(const char *opts1, const char *opts2);
54 static int  ro_given(char *options);
55 
56 /*
57  * list of support services needed
58  */
59 static char	*service_list[] = { AUTOMOUNTD, NULL };
60 
61 int
62 main(int argc, char *argv[])
63 {
64 	int error;
65 	int c;
66 	int mntflags = 0;
67 	int nmflg = 0;
68 	int roflg = 0;
69 	char *mntpnt, *mapname;
70 	struct utsname utsname;
71 	char autofs_addr[MAXADDRLEN];
72 	struct autofs_args fni;
73 	char *options = "";
74 	int mount_timeout = AUTOFS_MOUNT_TIMEOUT;
75 	char obuf[MAX_MNTOPT_STR];
76 
77 	while ((c = getopt(argc, argv, "o:mrq")) != EOF) {
78 		switch (c) {
79 		case '?':
80 			usage();
81 			exit(1);
82 			/* NOTREACHED */
83 
84 		case 'o':
85 			options = optarg;
86 			break;
87 
88 		case 'm':
89 			nmflg++;
90 			break;
91 		case 'r':	/* converted to -o ro always */
92 			roflg++;
93 			break;
94 		/*
95 		 *  The "quiet" flag can be ignored, since this
96 		 *  program never complains about invalid -o options
97 		 *  anyway.
98 		 */
99 		case 'q':
100 			break;
101 
102 		default:
103 			usage();
104 		}
105 	}
106 	if (argc - optind != 2)
107 		usage();
108 
109 	mapname = argv[optind];
110 	mntpnt  = argv[optind + 1];
111 
112 	if (strcmp(mntpnt, "/-") == 0) {
113 		(void) fprintf(stderr, "invalid mountpoint: /-\n");
114 		exit(1);
115 	}
116 
117 	if (uname(&utsname) < 0) {
118 		perror("uname");
119 		exit(1);
120 	}
121 	(void) strcpy(autofs_addr, utsname.nodename);
122 	(void) strcat(autofs_addr, ".autofs");
123 
124 	process_opts(options, &fni.direct);
125 
126 	if (roflg && !ro_given(options))
127 		options = concat_opts(options, "ro");
128 
129 	fni.addr.buf	= autofs_addr;
130 	fni.addr.len	= strlen(fni.addr.buf);
131 	fni.addr.maxlen	= fni.addr.len;
132 	fni.path	= mntpnt;
133 	fni.opts	= options;
134 	fni.map		= mapname;
135 	fni.subdir	= "";
136 	if (fni.direct)
137 		fni.key = mntpnt;
138 	else
139 		fni.key	= "";
140 	fni.mount_to	= mount_timeout;
141 	fni.rpc_to	= AUTOFS_RPC_TIMEOUT;
142 
143 	strcpy(obuf, options);
144 	if (*obuf != '\0')
145 		strcat(obuf, ",");
146 	strcat(obuf,
147 		fni.direct ? MNTTAB_OPTS ",direct" : MNTTAB_OPTS ",indirect");
148 
149 	/*
150 	 * enable services as needed.
151 	 */
152 	_check_services(service_list);
153 
154 	error = mount(fni.map, mntpnt, mntflags | MS_DATA | MS_OPTIONSTR,
155 		MNTTYPE_AUTOFS, &fni, sizeof (fni), obuf, MAX_MNTOPT_STR);
156 	if (error < 0) {
157 		perror("autofs mount");
158 		exit(1);
159 	}
160 	return (0);
161 }
162 
163 static void
164 usage()
165 {
166 	(void) fprintf(stderr,
167 	    "Usage: autofs mount [-r] [-o opts]  map  dir\n");
168 	exit(1);
169 }
170 
171 /*
172  * Remove pseudo-options "direct", "indirect", "nest", and "ignore" from
173  * option list.  Set *directp to 1 if "direct" is found, and 0 otherwise
174  * (mounts are indirect by default).  If both "direct" and "indirect" are
175  * found, the last one wins.
176  */
177 static void
178 process_opts(char *options, int *directp)
179 {
180 	char *opt;
181 	char *opts;
182 
183 	if ((opts = strdup(options)) == NULL) {
184 		(void) fprintf(stderr,
185 				"autofs mount: memory allocation failed\n");
186 		exit(1);
187 	}
188 	options[0] = '\0';
189 	*directp = 0;
190 
191 	while ((opt = strtok(opts, ",")) != NULL) {
192 		opts = NULL;
193 		while (isspace(*opt)) {
194 			opt++;
195 		}
196 		if (strcmp(opt, "direct") == 0) {
197 			*directp = 1;
198 		} else if (strcmp(opt, "indirect") == 0) {
199 			*directp = 0;
200 		} else if ((strcmp(opt, "nest") != 0) &&
201 				(strcmp(opt, "ignore") != 0)) {
202 			if (options[0] != '\0') {
203 				(void) strcat(options, ",");
204 			}
205 			(void) strcat(options, opt);
206 		}
207 	};
208 }
209 
210 /*
211  * Concatenate two options strings, with a comma between them.
212  */
213 static char *
214 concat_opts(const char *opts1, const char *opts2)
215 {
216 	char *opts = malloc(strlen(opts1) + strlen(opts2) + 2);
217 	if (opts == NULL) {
218 		(void) fprintf(stderr,
219 			"autofs mount: memory allocation failed\n");
220 		exit(1);
221 	}
222 	strcpy(opts, opts1);
223 	if (opts1[0] != '\0' && opts2[0] != '\0') {
224 		strcat(opts, ",");
225 	}
226 	return (strcat(opts, opts2));
227 }
228 
229 /*
230  * check the options string for 'ro' options
231  * if present returns 1 otherwise return 0;
232  */
233 
234 static int
235 ro_given(char *options)
236 {
237 	char	*op = options;
238 
239 	if (!*op)
240 		return (0);
241 
242 	while (op != 0) {
243 		if (*op == 'r' && *(op+1) == 'o' &&
244 			(*(op+2) == ',' || *(op+2) == '\0'))
245 			return (1);
246 
247 		if ((op = strchr(op, ',')) != NULL)
248 			op++;
249 	}
250 
251 
252 	return (0);
253 }
254