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