#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/mntent.h>
#include <sys/mnttab.h>
#include <sys/mount.h>
#include <sys/utsname.h>
#include <sys/tiuser.h>
#include <string.h>
#include <fslib.h>
#include <errno.h>
#include <rpcsvc/daemon_utils.h>
#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);
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);
case 'o':
options = optarg;
break;
case 'm':
nmflg++;
break;
case 'r':
roflg++;
break;
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");
_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);
}
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);
}
};
}
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));
}
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);
}