Blame SOURCES/autofs-5.1.4-add-mount_fedfs_c.patch

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