Home | History | Annotate | Download | only in autofs
      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