135b98
autofs-5.1.4 - add mount.fedfs.c
135b98
135b98
From: Ian Kent <raven@themaw.net>
135b98
135b98
Add build and install of the mount.fedfs binary.
135b98
135b98
Signed-off-by: Ian Kent <raven@themaw.net>
135b98
---
135b98
 CHANGELOG                |    1 
135b98
 Makefile                 |    3 
135b98
 Makefile.rules           |    2 
135b98
 autofs.spec              |    1 
135b98
 fedfs/Makefile           |   36 +++
135b98
 fedfs/fedfs-gpl-boiler.h |   40 ++++
135b98
 fedfs/fedfs-nls.h        |   38 ++++
135b98
 fedfs/mount.fedfs.c      |  485 ++++++++++++++++++++++++++++++++++++++++++++++
135b98
 8 files changed, 605 insertions(+), 1 deletion(-)
135b98
 create mode 100644 fedfs/Makefile
135b98
 create mode 100644 fedfs/fedfs-gpl-boiler.h
135b98
 create mode 100644 fedfs/fedfs-nls.h
135b98
 create mode 100644 fedfs/mount.fedfs.c
135b98
135b98
diff --git a/CHANGELOG b/CHANGELOG
135b98
index 8d6c737c..88992147 100644
135b98
--- a/CHANGELOG
135b98
+++ b/CHANGELOG
135b98
@@ -15,6 +15,7 @@ xx/xx/2018 autofs-5.1.5
135b98
 - dont allow trailing slash in master map mount points.
135b98
 - fix libresolv configure check.
135b98
 - add fedfs-getsrvinfo.c.
135b98
+- add mount.fedfs.c.
135b98
 
135b98
 19/12/2017 autofs-5.1.4
135b98
 - fix spec file url.
135b98
diff --git a/Makefile b/Makefile
135b98
index e560a7cb..99db2c75 100644
135b98
--- a/Makefile
135b98
+++ b/Makefile
135b98
@@ -19,6 +19,9 @@ kernel:
135b98
 samples:
135b98
 	set -e; if [ -d samples ]; then $(MAKE) -C samples all; fi
135b98
 
135b98
+fedfs:
135b98
+	set -e; if [ -d fedfs ]; then $(MAKE) -C fedfs all; fi
135b98
+
135b98
 clean:
135b98
 	for i in $(SUBDIRS) samples; do \
135b98
 		if [ -d $$i ]; then $(MAKE) -C $$i clean; fi; done 	
135b98
diff --git a/Makefile.rules b/Makefile.rules
135b98
index 4deab3b9..fc9f6019 100644
135b98
--- a/Makefile.rules
135b98
+++ b/Makefile.rules
135b98
@@ -3,7 +3,7 @@
135b98
 #
135b98
 
135b98
 # Root directory contents
135b98
-SUBDIRS = lib daemon modules man
135b98
+SUBDIRS = lib daemon fedfs modules man
135b98
 INCDIRS = include
135b98
 INCFILES = COPYING COPYRIGHT NEWS README* TODO Makefile Makefile.rules \
135b98
 	   Makefile.conf.in .version .autofs-* configure.in aclocal.m4 \
135b98
diff --git a/autofs.spec b/autofs.spec
135b98
index 2464e741..2cc0e38f 100644
135b98
--- a/autofs.spec
135b98
+++ b/autofs.spec
135b98
@@ -191,6 +191,7 @@ fi
135b98
 %config(noreplace) /etc/sysconfig/autofs
135b98
 %config(noreplace) /etc/autofs_ldap_auth.conf
135b98
 %{_sbindir}/automount
135b98
+%{_sbindir}/mount.fedfs
135b98
 %dir %{_libdir}/autofs
135b98
 %{_libdir}/autofs/*
135b98
 %{_mandir}/*/*
135b98
diff --git a/fedfs/Makefile b/fedfs/Makefile
135b98
new file mode 100644
135b98
index 00000000..cb325bed
135b98
--- /dev/null
135b98
+++ b/fedfs/Makefile
135b98
@@ -0,0 +1,36 @@
135b98
+#
135b98
+# Makefile for mount.fedfs
135b98
+#
135b98
+
135b98
+-include ../Makefile.conf
135b98
+include ../Makefile.rules
135b98
+
135b98
+SRCS = mount.fedfs.c
135b98
+HDRS = fedfs-getsrvinfo.h fedfs-gpl-boiler.h fedfs-nls.h
135b98
+
135b98
+fedfs-getsrvinfo_OBJ = fedfs-getsrvinfo.o
135b98
+
135b98
+mount_fedfs_OBJ = mount.fedfs.o
135b98
+
135b98
+version := $(shell cat ../.version)
135b98
+
135b98
+CFLAGS += -rdynamic $(DAEMON_CFLAGS) -D_GNU_SOURCE -I../include
135b98
+CFLAGS += -DVERSION_STRING=\"$(version)\"
135b98
+LDFLAGS += -rdynamic
135b98
+
135b98
+all: mount.fedfs
135b98
+
135b98
+mount.fedfs: $(mount_fedfs_OBJ) $(fedfs-getsrvinfo_OBJ) $(HDRS)
135b98
+	$(CC) -o mount.fedfs \
135b98
+	       $(mount_fedfs_OBJ) $(fedfs-getsrvinfo_OBJ) \
135b98
+	       $(LDFLAGS) $(LIBRESOLV) $(LIBS)
135b98
+
135b98
+clean:
135b98
+	rm -f *.o *.s *~ mount.fedfs
135b98
+
135b98
+install: all
135b98
+	install -d -m 755 $(INSTALLROOT)$(sbindir)
135b98
+	if ! test -x $(INSTALLROOT)$(sbindir)/mount.fedfs; \
135b98
+	then \
135b98
+		install -c mount.fedfs -m 755 $(INSTALLROOT)$(sbindir); \
135b98
+	fi
135b98
diff --git a/fedfs/fedfs-gpl-boiler.h b/fedfs/fedfs-gpl-boiler.h
135b98
new file mode 100644
135b98
index 00000000..1353e736
135b98
--- /dev/null
135b98
+++ b/fedfs/fedfs-gpl-boiler.h
135b98
@@ -0,0 +1,40 @@
135b98
+/*
135b98
+ * Copyright 2011 Oracle.  All rights reserved.
135b98
+ *
135b98
+ * This file is part of fedfs-utils.
135b98
+ *
135b98
+ * fedfs-utils is free software; you can redistribute it and/or modify
135b98
+ * it under the terms of the GNU General Public License version 2.0 as
135b98
+ * published by the Free Software Foundation.
135b98
+ *
135b98
+ * fedfs-utils is distributed in the hope that it will be useful, but
135b98
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
135b98
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
135b98
+ * GNU General Public License version 2.0 for more details.
135b98
+ *
135b98
+ * You should have received a copy of the GNU General Public License
135b98
+ * version 2.0 along with fedfs-utils.  If not, see:
135b98
+ *
135b98
+ *	http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
135b98
+ */
135b98
+
135b98
+#ifndef _GPL_BOILER_H_
135b98
+#define _GPL_BOILER_H_
135b98
+
135b98
+#ifdef HAVE_CONFIG_H
135b98
+#include <config.h>
135b98
+#endif
135b98
+
135b98
+/**
135b98
+ * GPLv2 boilerplate for usage messages
135b98
+ */
135b98
+static const char *fedfs_gpl_boilerplate =
135b98
+		"\nCopyright 2010, 2011, 2012, 2013 Oracle.  "
135b98
+		"All rights reserved.\n\n"
135b98
+		"License GPLv2: "
135b98
+		"<http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>\n"
135b98
+		"This is free software.  "
135b98
+			"You are free to change and redistribute it.\n"
135b98
+		"There is NO WARRANTY, to the extent permitted by law.\n";
135b98
+
135b98
+#endif	/* !_GPL_BOILER_H_ */
135b98
diff --git a/fedfs/fedfs-nls.h b/fedfs/fedfs-nls.h
135b98
new file mode 100644
135b98
index 00000000..92f968d3
135b98
--- /dev/null
135b98
+++ b/fedfs/fedfs-nls.h
135b98
@@ -0,0 +1,38 @@
135b98
+/*
135b98
+ * From util-linux/include/nls.h (GPLv2)
135b98
+ */
135b98
+
135b98
+#ifndef UTIL_LINUX_NLS_H
135b98
+#define UTIL_LINUX_NLS_H
135b98
+
135b98
+int main(int argc, char *argv[]);
135b98
+
135b98
+#ifndef LOCALEDIR
135b98
+#define LOCALEDIR "/usr/share/locale"
135b98
+#endif
135b98
+
135b98
+#ifdef HAVE_LOCALE_H
135b98
+# include <locale.h>
135b98
+#else
135b98
+# undef setlocale
135b98
+# define setlocale(Category, Locale) ({}) /* empty */
135b98
+#endif
135b98
+
135b98
+#ifdef ENABLE_NLS
135b98
+# include <libintl.h>
135b98
+# define _(Text) gettext (Text)
135b98
+# ifdef gettext_noop
135b98
+#  define N_(String) gettext_noop (String)
135b98
+# else
135b98
+#  define N_(String) (String)
135b98
+# endif
135b98
+#else
135b98
+# undef bindtextdomain
135b98
+# define bindtextdomain(Domain, Directory) /* empty */
135b98
+# undef textdomain
135b98
+# define textdomain(Domain) /* empty */
135b98
+# define _(Text) (Text)
135b98
+# define N_(Text) (Text)
135b98
+#endif
135b98
+
135b98
+#endif /* UTIL_LINUX_NLS_H */
135b98
diff --git a/fedfs/mount.fedfs.c b/fedfs/mount.fedfs.c
135b98
new file mode 100644
135b98
index 00000000..bd434395
135b98
--- /dev/null
135b98
+++ b/fedfs/mount.fedfs.c
135b98
@@ -0,0 +1,485 @@
135b98
+/*
135b98
+ * Copyright 2011 Oracle.  All rights reserved.
135b98
+ *
135b98
+ * This file is part of fedfs-utils.
135b98
+ *
135b98
+ * fedfs-utils is free software; you can redistribute it and/or modify
135b98
+ * it under the terms of the GNU General Public License version 2.0 as
135b98
+ * published by the Free Software Foundation.
135b98
+ *
135b98
+ * fedfs-utils is distributed in the hope that it will be useful, but
135b98
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
135b98
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
135b98
+ * GNU General Public License version 2.0 for more details.
135b98
+ *
135b98
+ * You should have received a copy of the GNU General Public License
135b98
+ * version 2.0 along with fedfs-utils.  If not, see:
135b98
+ *
135b98
+ *	http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
135b98
+ */
135b98
+
135b98
+#include <sys/types.h>
135b98
+#include <sys/stat.h>
135b98
+#include <sys/socket.h>
135b98
+#include <sys/mount.h>
135b98
+#include <sys/wait.h>
135b98
+
135b98
+#include <stdbool.h>
135b98
+#include <string.h>
135b98
+#include <stdlib.h>
135b98
+#include <unistd.h>
135b98
+#include <stdio.h>
135b98
+#include <libgen.h>
135b98
+#include <errno.h>
135b98
+#include <getopt.h>
135b98
+#include <locale.h>
135b98
+#include <netdb.h>
135b98
+#include <langinfo.h>
135b98
+
135b98
+#include "fedfs-nls.h"
135b98
+#include "fedfs-getsrvinfo.h"
135b98
+#include "fedfs-gpl-boiler.h"
135b98
+
135b98
+/**
135b98
+ * Top-level directory on client under which we mount NFSv4 domain roots
135b98
+ */
135b98
+#define FEDFS_NFS4_TLDIR		"nfs4"
135b98
+
135b98
+/**
135b98
+ * Name of SRV record containing NFSv4 FedFS root
135b98
+ */
135b98
+#define FEDFS_NFS_DOMAINROOT	"_nfs-domainroot._tcp"
135b98
+
135b98
+/**
135b98
+ * Export path of NFSv4 FedFS root
135b98
+ */
135b98
+#define FEDFS_NFS_EXPORTPATH	"/.domainroot"
135b98
+
135b98
+/**
135b98
+ * Pathname to mount.nfs
135b98
+ */
135b98
+#define MOUNT_NFS_EXECUTABLE		"/sbin/mount.nfs"
135b98
+
135b98
+/**
135b98
+ * Mount status values, lifted from util-linux
135b98
+ */
135b98
+enum {
135b98
+	EX_SUCCESS	= 0,
135b98
+	EX_USAGE	= 1,
135b98
+	EX_FAIL		= 32,
135b98
+};
135b98
+
135b98
+static char *progname;
135b98
+static int nomtab;
135b98
+static int verbose;
135b98
+static _Bool readonly;
135b98
+static _Bool sloppy;
135b98
+static _Bool fake;
135b98
+
135b98
+/**
135b98
+ * Short form command line options
135b98
+ */
135b98
+static const char fedfs_opts[] = "fhno:rsvVw";
135b98
+
135b98
+/**
135b98
+ * Long form command line options
135b98
+ */
135b98
+static const struct option fedfs_longopts[] =
135b98
+{
135b98
+	{ "fake", 0, NULL, 'f' },
135b98
+	{ "help", 0, NULL, 'h' },
135b98
+	{ "no-mtab", 0, NULL, 'n' },
135b98
+	{ "options", 1, NULL, 'o' },
135b98
+	{ "read-only", 0, NULL, 'r' },
135b98
+	{ "read-write", 0, NULL, 'w' },
135b98
+	{ "ro", 0, NULL, 'r' },
135b98
+	{ "rw", 0, NULL, 'w' },
135b98
+	{ "sloppy", 0, NULL, 's' },
135b98
+	{ "verbose", 0, NULL, 'v' },
135b98
+	{ "version", 0, NULL, 'V' },
135b98
+	{ NULL, 0, NULL, 0 }
135b98
+};
135b98
+
135b98
+/**
135b98
+ * Display mount.fedfs usage message
135b98
+ */
135b98
+static void
135b98
+mount_usage(void)
135b98
+{
135b98
+	printf(_("\nUsage: %s remotedir localdir [-fhnrsvVw]\n\n"), progname);
135b98
+	printf(_("options:\n"));
135b98
+	printf(_("\t-f\t\tFake mount, do not actually mount\n"));
135b98
+	printf(_("\t-h\t\tPrint this help\n"));
135b98
+	printf(_("\t-n\t\tDo not update /etc/mtab\n"));
135b98
+	printf(_("\t-r\t\tMount file system readonly\n"));
135b98
+	printf(_("\t-s\t\tTolerate sloppy mount options\n"));
135b98
+	printf(_("\t-v\t\tVerbose\n"));
135b98
+	printf(_("\t-V\t\tPrint version\n"));
135b98
+	printf(_("\t-w\t\tMount file system read-write\n"));
135b98
+
135b98
+	printf("%s", fedfs_gpl_boilerplate);
135b98
+}
135b98
+
135b98
+/**
135b98
+ * Concatenate three strings
135b98
+ *
135b98
+ * @param s NUL-terminated C string
135b98
+ * @param t NUL-terminated C string
135b98
+ * @param u NUL-terminated C string
135b98
+ * @return pointer to NUL-terminated C string or NULL
135b98
+ *
135b98
+ * Caller must free the returned string with free(3).  Always frees
135b98
+ * its first arg - typical use: s = xstrconcat3(s,t,u);
135b98
+ *
135b98
+ * Lifted from util-linux.
135b98
+ */
135b98
+static char *
135b98
+xstrconcat3(char *s, const char *t, const char *u)
135b98
+{
135b98
+	_Bool free_s = true;
135b98
+	char *result;
135b98
+
135b98
+	if (s == NULL) {
135b98
+		s = "";
135b98
+		free_s = false;
135b98
+	}
135b98
+	if (t == NULL)
135b98
+		t = "";
135b98
+	if (u == NULL)
135b98
+		u = "";
135b98
+	result = malloc(strlen(s) + strlen(t) + strlen(u) + 1);
135b98
+	if (result == NULL)
135b98
+		goto out;
135b98
+
135b98
+	strcpy(result, s);
135b98
+	strcat(result, t);
135b98
+	strcat(result, u);
135b98
+
135b98
+out:
135b98
+	if (free_s)
135b98
+		free(s);
135b98
+	return result;
135b98
+}
135b98
+
135b98
+/**
135b98
+ * Exec mount.nfs
135b98
+ *
135b98
+ * @param server NUL-terminated C string containing name of NFS server
135b98
+ * @param port server port to use when mounting
135b98
+ * @param domainname NUL-terminated C string containing FedFS domain name
135b98
+ * @param export_path NUL-terminated C string containing server export path
135b98
+ * @param mounted_on_dir NUL-terminated C string containing local mounted-on directory
135b98
+ * @param text_options NUL-terminated C string containing user's mount options
135b98
+ *
135b98
+ */
135b98
+static void
135b98
+exec_mount_nfs4(const char *server, unsigned short port,
135b98
+		const char *domainname, const char *export_path,
135b98
+		const char *mounted_on_dir, const char *text_options)
135b98
+{
135b98
+	static char special[2048];
135b98
+	static char options[2048];
135b98
+	char *args[16];
135b98
+	int count = 0;
135b98
+
135b98
+	snprintf(special, sizeof(special), "%s:%s/%s%s", server,
135b98
+			FEDFS_NFS_EXPORTPATH, domainname, export_path);
135b98
+
135b98
+	if (text_options != NULL && strcmp(text_options, "") != 0)
135b98
+		snprintf(options, sizeof(options), "%s,vers=4,fg,port=%u",
135b98
+				text_options, port);
135b98
+	else
135b98
+		snprintf(options, sizeof(options), "vers=4,fg,port=%u", port);
135b98
+
135b98
+	if (verbose) {
135b98
+		printf(_("%s: Special device:       %s\n"),
135b98
+			progname, special);
135b98
+		printf(_("%s: Mounted-on directory: %s\n"),
135b98
+			progname, mounted_on_dir);
135b98
+		printf(_("%s: Mount options:        %s\n"),
135b98
+			progname, options);
135b98
+	}
135b98
+
135b98
+	args[count++] = MOUNT_NFS_EXECUTABLE;
135b98
+	args[count++] = special;
135b98
+	args[count++] = (char *)mounted_on_dir;
135b98
+	if (verbose)
135b98
+		args[count++] = "-v";
135b98
+	if (fake)
135b98
+		args[count++] = "-f";
135b98
+	if (nomtab)
135b98
+		args[count++] = "-n";
135b98
+	if (readonly)
135b98
+		args[count++] = "-r";
135b98
+	if (sloppy)
135b98
+		args[count++] = "-s";
135b98
+	args[count++] = "-o";
135b98
+	args[count++] = options;
135b98
+
135b98
+	args[count] = NULL;
135b98
+	execv(args[0], args);
135b98
+}
135b98
+
135b98
+/**
135b98
+ * Mount a FedFS domain root via NFSv4
135b98
+ *
135b98
+ * @param domainname NUL-terminated C string containing FedFS domain name
135b98
+ * @param export_path NUL-terminated C string containing server export path
135b98
+ * @param mounted_on_dir NUL-terminated C string containing local mounted-on directory
135b98
+ * @param text_options NUL-terminated C string containing user's mount options
135b98
+ * @return exit status code from the mount.nfs command
135b98
+ *
135b98
+ * Construct the server:/export string and the mounted-on directory string
135b98
+ * based on the DNS SRV query results, then fork and exec mount.nfs to do
135b98
+ * the actual mount request.
135b98
+ */
135b98
+static int
135b98
+nfs4_mount(const char *domainname, const char *export_path,
135b98
+		const char *mounted_on_dir, const char *text_options)
135b98
+{
135b98
+	struct srvinfo *tmp, *si = NULL;
135b98
+	int error, status;
135b98
+
135b98
+	status = EX_FAIL;
135b98
+
135b98
+	error = getsrvinfo(FEDFS_NFS_DOMAINROOT, domainname, &si);
135b98
+	switch (error) {
135b98
+	case ESI_SUCCESS:
135b98
+		break;
135b98
+	case ESI_NONAME:
135b98
+		fprintf(stderr, _("%s: Domain name %s not found\n"),
135b98
+			progname, domainname);
135b98
+		goto out;
135b98
+	case ESI_SERVICE:
135b98
+		fprintf(stderr, _("%s: No FedFS domain root available for %s\n"),
135b98
+			progname, domainname);
135b98
+		goto out;
135b98
+	default:
135b98
+		fprintf(stderr, _("%s: Failed to resolve %s: %s\n"),
135b98
+			progname, domainname, gsi_strerror(error));
135b98
+		goto out;
135b98
+	}
135b98
+
135b98
+	/*
135b98
+	 * The srvinfo list is already in RFC 2782 sorted order.  Try each
135b98
+	 * SRV record once, in the foreground.  Go with the first one that
135b98
+	 * works.
135b98
+	 */
135b98
+	for (tmp = si; tmp != NULL; tmp = tmp->si_next) {
135b98
+		pid_t pid;
135b98
+
135b98
+		pid = fork();
135b98
+		switch (pid) {
135b98
+		case 0:
135b98
+			exec_mount_nfs4(tmp->si_target, tmp->si_port,
135b98
+					domainname, export_path, mounted_on_dir,
135b98
+					text_options);
135b98
+			/*NOTREACHED*/
135b98
+			fprintf(stderr, _("%s: Failed to exec: %s\n"),
135b98
+				progname, strerror(errno));
135b98
+			exit(EX_FAIL);
135b98
+		case -1:
135b98
+			fprintf(stderr, _("%s: Failed to fork: %s\n"),
135b98
+				progname, strerror(errno));
135b98
+			goto out;
135b98
+		default:
135b98
+			waitpid(pid, &status, 0);
135b98
+			if (status == EX_SUCCESS)
135b98
+				goto out;
135b98
+		}
135b98
+	}
135b98
+
135b98
+out:
135b98
+	freesrvinfo(si);
135b98
+	return status;
135b98
+}
135b98
+
135b98
+/**
135b98
+ * Try one mount request
135b98
+ *
135b98
+ * @param source NUL-terminated C string containing name of "special device"
135b98
+ * @param target NUL-terminated C string containing local mounted-on directory
135b98
+ * @param text_options NUL-terminated C string containing user's mount options
135b98
+ * @return an exit status code
135b98
+ *
135b98
+ * Parse the pathname in "source."  It contains the file system protocol
135b98
+ * and FedFS domain name.  Then pass these arguments to the appropriate
135b98
+ * mount helper subcommand.
135b98
+ */
135b98
+static int
135b98
+try_mount(const char *source, const char *target, const char *text_options)
135b98
+{
135b98
+	char *global_name, *topdir, *domainname, *remaining;
135b98
+	int result;
135b98
+
135b98
+	remaining = NULL;
135b98
+	result = EX_FAIL;
135b98
+
135b98
+	global_name = strdup(source);
135b98
+	if (global_name == NULL) {
135b98
+		fprintf(stderr, _("%s: Unable to parse globally useful name\n"),
135b98
+				progname);
135b98
+		goto out;
135b98
+	}
135b98
+
135b98
+	topdir = strtok(global_name, "/");
135b98
+	if (topdir == NULL) {
135b98
+		fprintf(stderr, _("%s: Invalid globally useful name: %s\n"),
135b98
+			progname, source);
135b98
+		goto out;
135b98
+	}
135b98
+	if (verbose)
135b98
+		printf(_("%s: Top-level directory:  %s\n"),
135b98
+			progname, topdir);
135b98
+
135b98
+	domainname = strtok(NULL, "/");
135b98
+	if (domainname == NULL) {
135b98
+		fprintf(stderr, _("%s: Missing domain name in globally "
135b98
+				"useful name: %s\n"), progname, source);
135b98
+		goto out;
135b98
+	}
135b98
+	if (verbose)
135b98
+		printf(_("%s: Domain name:          %s\n"),
135b98
+			progname, domainname);
135b98
+
135b98
+	remaining = strtok(NULL, "/");
135b98
+	if (remaining == NULL) {
135b98
+		remaining = strdup("/");
135b98
+		if (remaining == NULL) {
135b98
+			fprintf(stderr, _("%s: No memory\n"), progname);
135b98
+			goto out;
135b98
+		}
135b98
+	} else {
135b98
+		char *tmp;
135b98
+
135b98
+		tmp = malloc(strlen(remaining) + 1);
135b98
+		if (tmp == NULL) {
135b98
+			fprintf(stderr, _("%s: No memory\n"), progname);
135b98
+			remaining = NULL;
135b98
+			goto out;
135b98
+		}
135b98
+		strcpy(tmp, "/");
135b98
+		strcat(tmp, remaining);
135b98
+		remaining = tmp;
135b98
+	}
135b98
+	if (verbose)
135b98
+		printf(_("%s: Export path:          %s\n"),
135b98
+			progname, remaining);
135b98
+
135b98
+	if (strcmp(topdir, FEDFS_NFS4_TLDIR) == 0)
135b98
+		result = nfs4_mount(domainname, remaining, target, text_options);
135b98
+#if 0
135b98
+	/* example: SMB support plugs in here */
135b98
+	else if (strcmp(topdir, FEDFS_SMB_TLDIR) == 0)
135b98
+		result = smb_mount(domainname, remaining, target, text_options);
135b98
+#endif
135b98
+	else
135b98
+		fprintf(stderr, _("%s: Unrecognized file system protocol\n"), progname);
135b98
+
135b98
+out:
135b98
+	free(global_name);
135b98
+	free(remaining);
135b98
+
135b98
+	return result;
135b98
+}
135b98
+
135b98
+/**
135b98
+ * Program entry point
135b98
+ *
135b98
+ * @param argc count of command line arguments
135b98
+ * @param argv array of NUL-terminated C strings containing command line arguments
135b98
+ * @return program exit status
135b98
+ */
135b98
+int main(int argc, char *argv[])
135b98
+{
135b98
+	char *source, *target, *text_options;
135b98
+	int c, mnt_err;
135b98
+
135b98
+	(void)setlocale(LC_ALL, "");
135b98
+
135b98
+	progname = basename(argv[0]);
135b98
+
135b98
+	if (argv[1] && argv[1][0] == '-') {
135b98
+		if(argv[1][1] == 'V')
135b98
+			printf("%s (VERSION_STRING)\n", progname);
135b98
+		else
135b98
+			mount_usage();
135b98
+		exit(EX_SUCCESS);
135b98
+	}
135b98
+
135b98
+	if (argc < 3) {
135b98
+		mount_usage();
135b98
+		exit(EX_USAGE);
135b98
+	}
135b98
+
135b98
+	source = argv[1];
135b98
+	target = argv[2];
135b98
+
135b98
+	mnt_err = EX_USAGE;
135b98
+	text_options = NULL;
135b98
+	readonly = false;
135b98
+	sloppy = false;
135b98
+	fake = false;
135b98
+	argv[2] = argv[0]; /* so that getopt error messages are correct */
135b98
+	while ((c = getopt_long(argc - 2, argv + 2, fedfs_opts,
135b98
+				fedfs_longopts, NULL)) != -1) {
135b98
+		switch (c) {
135b98
+		case 'f':
135b98
+			fake = true;
135b98
+			break;
135b98
+		case 'n':
135b98
+			++nomtab;
135b98
+			break;
135b98
+		case 'o':
135b98
+			/* Ugh. */
135b98
+			if (text_options != NULL)
135b98
+				text_options = xstrconcat3(text_options, ",", optarg);
135b98
+			else
135b98
+				text_options = strdup(optarg);
135b98
+			if (text_options == NULL) {
135b98
+				fprintf(stderr, _("%s: No memory\n"), progname);
135b98
+				goto out;
135b98
+			}
135b98
+			break;
135b98
+		case 'r':
135b98
+			readonly = true;
135b98
+			break;
135b98
+		case 's':
135b98
+			sloppy = true;
135b98
+			break;
135b98
+		case 'v':
135b98
+			++verbose;
135b98
+			break;
135b98
+		case 'V':
135b98
+			printf("%s: (VERSION_STRING)\n", progname);
135b98
+			mnt_err = EX_SUCCESS;
135b98
+			goto out;
135b98
+		case 'w':
135b98
+			readonly = false;
135b98
+			break;
135b98
+		case 'h':
135b98
+		default:
135b98
+			mount_usage();
135b98
+			goto out;
135b98
+		}
135b98
+	}
135b98
+
135b98
+	/* Extra non-option words at the end are bogus...  */
135b98
+	if (optind != argc - 2) {
135b98
+		mount_usage();
135b98
+		goto out;
135b98
+	}
135b98
+
135b98
+	if (getuid() != 0 && geteuid() != 0) {
135b98
+		fprintf(stderr, _("%s: Not installed setuid - "
135b98
+			    "\"user\" FedFS mounts are not supported\n"), progname);
135b98
+		mnt_err = EX_FAIL;
135b98
+		goto out;
135b98
+	}
135b98
+
135b98
+	mnt_err = try_mount(source, target, text_options);
135b98
+
135b98
+out:
135b98
+	free(text_options);
135b98
+	exit(mnt_err);
135b98
+}