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