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
main(int argc,char * argv[])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
usage()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
process_opts(char * options,int * directp)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 *
concat_opts(const char * opts1,const char * opts2)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
ro_given(char * options)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