/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * autofs mount.c * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "automount.h" #define MNTTAB_OPTS "ignore,nest" static void usage(); static void process_opts(char *options, int *directp); static char *concat_opts(const char *opts1, const char *opts2); static int ro_given(char *options); /* * list of support services needed */ static char *service_list[] = { AUTOMOUNTD, NULL }; int main(int argc, char *argv[]) { int error; int c; int mntflags = 0; int nmflg = 0; int roflg = 0; char *mntpnt, *mapname; struct utsname utsname; char autofs_addr[MAXADDRLEN]; struct autofs_args fni; char *options = ""; int mount_timeout = AUTOFS_MOUNT_TIMEOUT; char obuf[MAX_MNTOPT_STR]; while ((c = getopt(argc, argv, "o:mrq")) != EOF) { switch (c) { case '?': usage(); exit(1); /* NOTREACHED */ case 'o': options = optarg; break; case 'm': nmflg++; break; case 'r': /* converted to -o ro always */ roflg++; break; /* * The "quiet" flag can be ignored, since this * program never complains about invalid -o options * anyway. */ case 'q': break; default: usage(); } } if (argc - optind != 2) usage(); mapname = argv[optind]; mntpnt = argv[optind + 1]; if (strcmp(mntpnt, "/-") == 0) { (void) fprintf(stderr, "invalid mountpoint: /-\n"); exit(1); } if (uname(&utsname) < 0) { perror("uname"); exit(1); } (void) strcpy(autofs_addr, utsname.nodename); (void) strcat(autofs_addr, ".autofs"); process_opts(options, &fni.direct); if (roflg && !ro_given(options)) options = concat_opts(options, "ro"); fni.addr.buf = autofs_addr; fni.addr.len = strlen(fni.addr.buf); fni.addr.maxlen = fni.addr.len; fni.path = mntpnt; fni.opts = options; fni.map = mapname; fni.subdir = ""; if (fni.direct) fni.key = mntpnt; else fni.key = ""; fni.mount_to = mount_timeout; fni.rpc_to = AUTOFS_RPC_TIMEOUT; strcpy(obuf, options); if (*obuf != '\0') strcat(obuf, ","); strcat(obuf, fni.direct ? MNTTAB_OPTS ",direct" : MNTTAB_OPTS ",indirect"); /* * enable services as needed. */ _check_services(service_list); error = mount(fni.map, mntpnt, mntflags | MS_DATA | MS_OPTIONSTR, MNTTYPE_AUTOFS, &fni, sizeof (fni), obuf, MAX_MNTOPT_STR); if (error < 0) { perror("autofs mount"); exit(1); } return (0); } static void usage() { (void) fprintf(stderr, "Usage: autofs mount [-r] [-o opts] map dir\n"); exit(1); } /* * Remove pseudo-options "direct", "indirect", "nest", and "ignore" from * option list. Set *directp to 1 if "direct" is found, and 0 otherwise * (mounts are indirect by default). If both "direct" and "indirect" are * found, the last one wins. */ static void process_opts(char *options, int *directp) { char *opt; char *opts; if ((opts = strdup(options)) == NULL) { (void) fprintf(stderr, "autofs mount: memory allocation failed\n"); exit(1); } options[0] = '\0'; *directp = 0; while ((opt = strtok(opts, ",")) != NULL) { opts = NULL; while (isspace(*opt)) { opt++; } if (strcmp(opt, "direct") == 0) { *directp = 1; } else if (strcmp(opt, "indirect") == 0) { *directp = 0; } else if ((strcmp(opt, "nest") != 0) && (strcmp(opt, "ignore") != 0)) { if (options[0] != '\0') { (void) strcat(options, ","); } (void) strcat(options, opt); } }; } /* * Concatenate two options strings, with a comma between them. */ static char * concat_opts(const char *opts1, const char *opts2) { char *opts = malloc(strlen(opts1) + strlen(opts2) + 2); if (opts == NULL) { (void) fprintf(stderr, "autofs mount: memory allocation failed\n"); exit(1); } strcpy(opts, opts1); if (opts1[0] != '\0' && opts2[0] != '\0') { strcat(opts, ","); } return (strcat(opts, opts2)); } /* * check the options string for 'ro' options * if present returns 1 otherwise return 0; */ static int ro_given(char *options) { char *op = options; if (!*op) return (0); while (op != 0) { if (*op == 'r' && *(op+1) == 'o' && (*(op+2) == ',' || *(op+2) == '\0')) return (1); if ((op = strchr(op, ',')) != NULL) op++; } return (0); }