xref: /illumos-gate/usr/src/cmd/fs.d/autofs/mount.c (revision 7a6d80f1660abd4755c68cbd094d4a914681d26e)
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 #include <stdio.h>
31 #include <unistd.h>
32 #include <stdlib.h>
33 #include <ctype.h>
34 #include <sys/param.h>
35 #include <sys/stat.h>
36 #include <sys/mntent.h>
37 #include <sys/mnttab.h>
38 #include <sys/mount.h>
39 #include <sys/utsname.h>
40 #include <sys/tiuser.h>
41 #include <string.h>
42 #include <fslib.h>
43 #include <errno.h>
44 #include <rpcsvc/daemon_utils.h>
45 #include "automount.h"
46 
47 #define	MNTTAB_OPTS	"ignore,nest"
48 
49 static void usage();
50 static void process_opts(char *options, int *directp);
51 static char *concat_opts(const char *opts1, const char *opts2);
52 static int  ro_given(char *options);
53 
54 /*
55  * list of support services needed
56  */
57 static char	*service_list[] = { AUTOMOUNTD, NULL };
58 
59 int
60 main(int argc, char *argv[])
61 {
62 	int error;
63 	int c;
64 	int mntflags = 0;
65 	int nmflg = 0;
66 	int roflg = 0;
67 	char *mntpnt, *mapname;
68 	struct utsname utsname;
69 	char autofs_addr[MAXADDRLEN];
70 	struct autofs_args fni;
71 	char *options = "";
72 	int mount_timeout = AUTOFS_MOUNT_TIMEOUT;
73 	char obuf[MAX_MNTOPT_STR];
74 
75 	while ((c = getopt(argc, argv, "o:mrq")) != EOF) {
76 		switch (c) {
77 		case '?':
78 			usage();
79 			exit(1);
80 			/* NOTREACHED */
81 
82 		case 'o':
83 			options = optarg;
84 			break;
85 
86 		case 'm':
87 			nmflg++;
88 			break;
89 		case 'r':	/* converted to -o ro always */
90 			roflg++;
91 			break;
92 		/*
93 		 *  The "quiet" flag can be ignored, since this
94 		 *  program never complains about invalid -o options
95 		 *  anyway.
96 		 */
97 		case 'q':
98 			break;
99 
100 		default:
101 			usage();
102 		}
103 	}
104 	if (argc - optind != 2)
105 		usage();
106 
107 	mapname = argv[optind];
108 	mntpnt  = argv[optind + 1];
109 
110 	if (strcmp(mntpnt, "/-") == 0) {
111 		(void) fprintf(stderr, "invalid mountpoint: /-\n");
112 		exit(1);
113 	}
114 
115 	if (uname(&utsname) < 0) {
116 		perror("uname");
117 		exit(1);
118 	}
119 	(void) strcpy(autofs_addr, utsname.nodename);
120 	(void) strcat(autofs_addr, ".autofs");
121 
122 	process_opts(options, &fni.direct);
123 
124 	if (roflg && !ro_given(options))
125 		options = concat_opts(options, "ro");
126 
127 	fni.addr.buf	= autofs_addr;
128 	fni.addr.len	= strlen(fni.addr.buf);
129 	fni.addr.maxlen	= fni.addr.len;
130 	fni.path	= mntpnt;
131 	fni.opts	= options;
132 	fni.map		= mapname;
133 	fni.subdir	= "";
134 	if (fni.direct)
135 		fni.key = mntpnt;
136 	else
137 		fni.key	= "";
138 	fni.mount_to	= mount_timeout;
139 	fni.rpc_to	= AUTOFS_RPC_TIMEOUT;
140 
141 	strcpy(obuf, options);
142 	if (*obuf != '\0')
143 		strcat(obuf, ",");
144 	strcat(obuf,
145 		fni.direct ? MNTTAB_OPTS ",direct" : MNTTAB_OPTS ",indirect");
146 
147 	/*
148 	 * enable services as needed.
149 	 */
150 	_check_services(service_list);
151 
152 	error = mount(fni.map, mntpnt, mntflags | MS_DATA | MS_OPTIONSTR,
153 		MNTTYPE_AUTOFS, &fni, sizeof (fni), obuf, MAX_MNTOPT_STR);
154 	if (error < 0) {
155 		perror("autofs mount");
156 		exit(1);
157 	}
158 	return (0);
159 }
160 
161 static void
162 usage()
163 {
164 	(void) fprintf(stderr,
165 	    "Usage: autofs mount [-r] [-o opts]  map  dir\n");
166 	exit(1);
167 }
168 
169 /*
170  * Remove pseudo-options "direct", "indirect", "nest", and "ignore" from
171  * option list.  Set *directp to 1 if "direct" is found, and 0 otherwise
172  * (mounts are indirect by default).  If both "direct" and "indirect" are
173  * found, the last one wins.
174  */
175 static void
176 process_opts(char *options, int *directp)
177 {
178 	char *opt;
179 	char *opts;
180 
181 	if ((opts = strdup(options)) == NULL) {
182 		(void) fprintf(stderr,
183 				"autofs mount: memory allocation failed\n");
184 		exit(1);
185 	}
186 	options[0] = '\0';
187 	*directp = 0;
188 
189 	while ((opt = strtok(opts, ",")) != NULL) {
190 		opts = NULL;
191 		while (isspace(*opt)) {
192 			opt++;
193 		}
194 		if (strcmp(opt, "direct") == 0) {
195 			*directp = 1;
196 		} else if (strcmp(opt, "indirect") == 0) {
197 			*directp = 0;
198 		} else if ((strcmp(opt, "nest") != 0) &&
199 				(strcmp(opt, "ignore") != 0)) {
200 			if (options[0] != '\0') {
201 				(void) strcat(options, ",");
202 			}
203 			(void) strcat(options, opt);
204 		}
205 	};
206 }
207 
208 /*
209  * Concatenate two options strings, with a comma between them.
210  */
211 static char *
212 concat_opts(const char *opts1, const char *opts2)
213 {
214 	char *opts = malloc(strlen(opts1) + strlen(opts2) + 2);
215 	if (opts == NULL) {
216 		(void) fprintf(stderr,
217 			"autofs mount: memory allocation failed\n");
218 		exit(1);
219 	}
220 	strcpy(opts, opts1);
221 	if (opts1[0] != '\0' && opts2[0] != '\0') {
222 		strcat(opts, ",");
223 	}
224 	return (strcat(opts, opts2));
225 }
226 
227 /*
228  * check the options string for 'ro' options
229  * if present returns 1 otherwise return 0;
230  */
231 
232 static int
233 ro_given(char *options)
234 {
235 	char	*op = options;
236 
237 	if (!*op)
238 		return (0);
239 
240 	while (op != 0) {
241 		if (*op == 'r' && *(op+1) == 'o' &&
242 			(*(op+2) == ',' || *(op+2) == '\0'))
243 			return (1);
244 
245 		if ((op = strchr(op, ',')) != NULL)
246 			op++;
247 	}
248 
249 
250 	return (0);
251 }
252