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