summaryrefslogtreecommitdiffstats
path: root/support
diff options
context:
space:
mode:
Diffstat (limited to 'support')
-rw-r--r--support/Makefile9
-rw-r--r--support/export/Makefile27
-rw-r--r--support/export/client.c298
-rw-r--r--support/export/export.c259
-rw-r--r--support/export/hostname.c262
-rw-r--r--support/export/keys.c72
-rw-r--r--support/export/mount.x345
-rw-r--r--support/export/nfsctl.c105
-rw-r--r--support/export/rmtab.c79
-rw-r--r--support/export/xtab.c133
-rw-r--r--support/include/Makefile16
-rw-r--r--support/include/config.h.in25
-rw-r--r--support/include/exportfs.h80
-rw-r--r--support/include/misc.h24
-rw-r--r--support/include/nfs/debug.h75
-rw-r--r--support/include/nfs/export.h26
-rw-r--r--support/include/nfs/nfs.h145
-rw-r--r--support/include/nfslib.h125
-rw-r--r--support/include/rpcdispatch.h57
-rw-r--r--support/include/rpcmisc.h58
-rw-r--r--support/include/rpcsec.h39
-rw-r--r--support/include/rpcsvc/nfs_prot.h661
-rw-r--r--support/include/sys/fs/ext2fs.h42
-rw-r--r--support/include/version.h1
-rw-r--r--support/include/xio.h26
-rw-r--r--support/include/xlog.h40
-rw-r--r--support/include/xmalloc.h16
-rw-r--r--support/include/ypupdate.h16
-rw-r--r--support/lib/Makefile13
-rw-r--r--support/nfs/Makefile13
-rw-r--r--support/nfs/clients.c324
-rw-r--r--support/nfs/exports.c440
-rw-r--r--support/nfs/getfh.c55
-rw-r--r--support/nfs/keytab.c129
-rw-r--r--support/nfs/lockdsvc.c20
-rw-r--r--support/nfs/nfsclient.c32
-rw-r--r--support/nfs/nfsctl.c24
-rw-r--r--support/nfs/nfsexport.c32
-rw-r--r--support/nfs/nfssvc.c22
-rw-r--r--support/nfs/rmtab.c122
-rw-r--r--support/nfs/rpcdispatch.c112
-rw-r--r--support/nfs/rpcmisc.c230
-rw-r--r--support/nfs/wildmat.c177
-rw-r--r--support/nfs/xio.c151
-rw-r--r--support/nfs/xlog.c189
-rw-r--r--support/nfs/xmalloc.c48
-rw-r--r--support/nfs/ypupdate_xdr.c29
47 files changed, 5223 insertions, 0 deletions
diff --git a/support/Makefile b/support/Makefile
new file mode 100644
index 0000000..6b8598b
--- /dev/null
+++ b/support/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for linux-nfs/support
+#
+
+SUBDIRS = include nfs export lib
+.DEFAULT: all
+
+include $(TOP)rules.mk
+
diff --git a/support/export/Makefile b/support/export/Makefile
new file mode 100644
index 0000000..1243305
--- /dev/null
+++ b/support/export/Makefile
@@ -0,0 +1,27 @@
+#
+# libexport.a
+# Miscellaneous utility functions related to exporting and mounting
+# of NFS volumes.
+#
+
+LIBNAME = libexport.a
+SRCS = $(RPCSRCS) client.c export.c hostname.c nfsctl.c rmtab.c \
+ xtab.c
+OBJS = $(SRCS:.c=.o)
+
+RPCSRCS = mount_clnt.c mount_xdr.c
+RPCHDRS = mount.h
+
+include $(TOP)rules.mk
+
+$(RPCHDRS) $(RPCSRCS): mount.x
+ $(RM) $(RPCHDRS) $(RPCSRCS)
+ $(RPCGEN) -h -o mount.h $<
+ $(RPCGEN) -l -o mount_clnt.c $<
+ $(RPCGEN) -c -o mount_xdr.c $<
+
+clean distclean::
+ $(RM) $(RPCHDRS) $(RPCSRCS)
+
+install::
+ @:
diff --git a/support/export/client.c b/support/export/client.c
new file mode 100644
index 0000000..8c5200a
--- /dev/null
+++ b/support/export/client.c
@@ -0,0 +1,298 @@
+/*
+ * support/export/client.c
+ *
+ * Maintain list of nfsd clients.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+#include "xmalloc.h"
+#include "misc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+
+/* netgroup stuff never seems to be defined in any header file. Linux is
+ * not alone in this.
+ */
+#if !defined(__GLIBC__) || __GLIBC__ < 2
+extern int innetgr(char *netgr, char *host, char *, char *);
+#endif
+static void client_init(nfs_client *clp, const char *hname,
+ struct hostent *hp);
+static int client_checkaddr(nfs_client *clp, struct in_addr addr);
+
+nfs_client *clientlist[MCL_MAXTYPES] = { NULL, };
+
+
+nfs_client *
+client_lookup(char *hname)
+{
+ nfs_client *clp = NULL;
+ int htype;
+ struct hostent *hp = NULL;
+
+ htype = client_gettype(hname);
+
+ if (htype == MCL_FQDN) {
+ hp = gethostbyname(hname);
+ if (hp == NULL || hp->h_addrtype != AF_INET) {
+ xlog(L_ERROR, "%s has non-inet addr", hname);
+ return NULL;
+ }
+ hp = hostent_dup (hp);
+ hname = (char *) hp->h_name;
+
+ for (clp = clientlist[htype]; clp; clp = clp->m_next) {
+ if (client_check(clp, hp))
+ break;
+ }
+ } else {
+ for (clp = clientlist[htype]; clp; clp = clp->m_next) {
+ if (strcmp(hname, clp->m_hostname)==0)
+ break;
+ }
+ }
+
+ if (!clp) {
+ clp = (nfs_client *) xmalloc(sizeof(*clp));
+ memset(clp, 0, sizeof(*clp));
+ clp->m_type = htype;
+ client_init(clp, hname, NULL);
+ client_add(clp);
+ }
+
+ if (htype == MCL_FQDN && clp->m_naddr == 0 && hp != NULL) {
+ char **ap = hp->h_addr_list;
+ int i;
+
+ for (i = 0; *ap && i < NFSCLNT_ADDRMAX; i++, ap++)
+ clp->m_addrlist[i] = *(struct in_addr *)*ap;
+ clp->m_naddr = i;
+ }
+
+ if (hp)
+ free (hp);
+
+ return clp;
+}
+
+nfs_client *
+client_dup(nfs_client *clp, struct hostent *hp)
+{
+ nfs_client *new;
+
+ new = (nfs_client *) xmalloc(sizeof(*new));
+ memcpy(new, clp, sizeof(*new));
+ new->m_type = MCL_FQDN;
+
+ client_init(new, (char *) hp->h_name, hp);
+ client_add(new);
+ return new;
+}
+
+static void
+client_init(nfs_client *clp, const char *hname, struct hostent *hp)
+{
+ if (hp) {
+ strncpy(clp->m_hostname, hp->h_name,
+ sizeof (clp->m_hostname) - 1);
+ } else {
+ strncpy(clp->m_hostname, hname,
+ sizeof (clp->m_hostname) - 1);
+ }
+ clp->m_hostname[sizeof (clp->m_hostname) - 1] = '\0';
+
+ clp->m_exported = 0;
+ clp->m_count = 0;
+
+ if (clp->m_type == MCL_SUBNETWORK) {
+ char *cp = strchr(clp->m_hostname, '/');
+
+ *cp = '\0';
+ clp->m_addrlist[0].s_addr = inet_addr(clp->m_hostname);
+ clp->m_addrlist[1].s_addr = inet_addr(cp+1);
+ *cp = '/';
+ clp->m_naddr = 0;
+ } else if (!hp) {
+ clp->m_naddr = 0;
+ } else {
+ char **ap = hp->h_addr_list;
+ int i;
+
+ for (i = 0; *ap && i < NFSCLNT_ADDRMAX; i++, ap++) {
+ clp->m_addrlist[i] = *(struct in_addr *)*ap;
+ }
+ clp->m_naddr = i;
+ }
+}
+
+void
+client_add(nfs_client *clp)
+{
+ nfs_client **cpp;
+
+ if (clp->m_type < 0 || clp->m_type >= MCL_MAXTYPES)
+ xlog(L_FATAL, "unknown client type in client_add");
+ cpp = clientlist + clp->m_type;
+ while (*cpp)
+ cpp = &((*cpp)->m_next);
+ clp->m_next = NULL;
+ *cpp = clp;
+}
+
+void
+client_release(nfs_client *clp)
+{
+ if (clp->m_count <= 0)
+ xlog(L_FATAL, "client_free: m_count <= 0!");
+ clp->m_count--;
+}
+
+void
+client_freeall(void)
+{
+ nfs_client *clp, **head;
+ int i;
+
+ for (i = 0; i < MCL_MAXTYPES; i++) {
+ head = clientlist + i;
+ while (*head) {
+ *head = (clp = *head)->m_next;
+ xfree(clp);
+ }
+ }
+}
+
+nfs_client *
+client_find(struct hostent *hp)
+{
+ nfs_client *clp;
+ int i;
+
+ for (i = 0; i < MCL_MAXTYPES; i++) {
+ for (clp = clientlist[i]; clp; clp = clp->m_next) {
+ if (!client_check(clp, hp))
+ continue;
+#ifdef notdef
+ if (clp->m_type == MCL_FQDN)
+ return clp;
+ return client_dup(clp, hp);
+#else
+ return clp;
+#endif
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Match a host (given its hostent record) to a client record. This
+ * is usually called from mountd.
+ */
+int
+client_check(nfs_client *clp, struct hostent *hp)
+{
+ char *hname = (char *) hp->h_name;
+ char *cname = clp->m_hostname;
+ char **ap;
+
+ switch (clp->m_type) {
+ case MCL_FQDN:
+ case MCL_SUBNETWORK:
+ for (ap = hp->h_addr_list; *ap; ap++) {
+ if (client_checkaddr(clp, *(struct in_addr *) *ap))
+ return 1;
+ }
+ return 0;
+ case MCL_WILDCARD:
+ if (wildmat(hname, cname))
+ return 1;
+ else {
+ for (ap = hp->h_aliases; *ap; ap++)
+ if (wildmat(*ap, cname))
+ return 1;
+ }
+ return 0;
+ case MCL_NETGROUP:
+#ifdef HAVE_INNETGR
+ {
+ char *dot;
+ int match;
+
+ /* First, try to match the hostname without
+ * splitting off the domain */
+ if (innetgr(cname+1, hname, NULL, NULL))
+ return 1;
+
+ /* Okay, strip off the domain (if we have one) */
+ if ((dot = strchr(hname, '.')) == NULL)
+ return 0;
+
+ *dot = '\0';
+ match = innetgr(cname+1, hname, NULL, dot + 1);
+ *dot = '.';
+
+ return match;
+ }
+#else
+ return 0;
+#endif
+ case MCL_ANONYMOUS:
+ return 1;
+ default:
+ xlog(L_FATAL, "internal: bad client type %d", clp->m_type);
+ }
+
+ return 0;
+}
+
+static int
+client_checkaddr(nfs_client *clp, struct in_addr addr)
+{
+ int i;
+
+ switch (clp->m_type) {
+ case MCL_FQDN:
+ for (i = 0; i < clp->m_naddr; i++) {
+ if (clp->m_addrlist[i].s_addr == addr.s_addr)
+ return 1;
+ }
+ return 0;
+ case MCL_SUBNETWORK:
+ return !((clp->m_addrlist[0].s_addr ^ addr.s_addr)
+ & clp->m_addrlist[1].s_addr);
+ }
+ return 0;
+}
+
+int
+client_gettype(char *ident)
+{
+ char *sp;
+
+ if (ident[0] == '\0')
+ return MCL_ANONYMOUS;
+ if (ident[0] == '@') {
+#ifndef HAVE_INNETGR
+ xlog(L_WARNING, "netgroup support not compiled in");
+#endif
+ return MCL_NETGROUP;
+ }
+ for (sp = ident; *sp; sp++) {
+ if (*sp == '*' || *sp == '?' || *sp == '[')
+ return MCL_WILDCARD;
+ if (*sp == '/')
+ return MCL_SUBNETWORK;
+ if (*sp == '\\' && sp[1])
+ sp++;
+ }
+ return MCL_FQDN;
+}
diff --git a/support/export/export.c b/support/export/export.c
new file mode 100644
index 0000000..09efaa8
--- /dev/null
+++ b/support/export/export.c
@@ -0,0 +1,259 @@
+/*
+ * support/export/export.c
+ *
+ * Maintain list of exported file systems.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include "xmalloc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+
+nfs_export *exportlist[MCL_MAXTYPES] = { NULL, };
+
+static void export_init(nfs_export *exp, nfs_client *clp,
+ struct exportent *nep);
+static int export_check(nfs_export *, struct hostent *, char *);
+static nfs_export *
+ export_allowed_internal(struct hostent *hp, char *path);
+
+int
+export_read(char *fname)
+{
+ struct exportent *eep;
+ nfs_export *exp;
+
+ setexportent(fname, "r");
+ while ((eep = getexportent()) != NULL) {
+ exp = export_lookup(eep->e_hostname, eep->e_path);
+ if (!exp)
+ export_create(eep);
+ else {
+ if (exp->m_export.e_flags != eep->e_flags) {
+ xlog(L_ERROR, "incompatible dupilcated export entries:");
+ xlog(L_ERROR, "\t%s:%s (0x%x) [IGNORED]", eep->e_hostname,
+ eep->e_path, eep->e_flags);
+ xlog(L_ERROR, "\t%s:%s (0x%x)", exp->m_export.e_hostname,
+ exp->m_export.e_path, exp->m_export.e_flags);
+ }
+ else {
+ xlog(L_ERROR, "dupilcated export entries:");
+ xlog(L_ERROR, "\t%s:%s", eep->e_hostname, eep->e_path);
+ xlog(L_ERROR, "\t%s:%s", exp->m_export.e_hostname,
+ exp->m_export.e_path);
+ }
+ }
+ }
+ endexportent();
+
+ return 0;
+}
+
+/*
+ * Create an in-core export struct from an export entry.
+ */
+nfs_export *
+export_create(struct exportent *xep)
+{
+ nfs_client *clp;
+ nfs_export *exp;
+
+ if (!(clp = client_lookup(xep->e_hostname))) {
+ /* bad export entry; complaint already logged */
+ return NULL;
+ }
+ exp = (nfs_export *) xmalloc(sizeof(*exp));
+ export_init(exp, clp, xep);
+ export_add(exp);
+
+ return exp;
+}
+
+static void
+export_init(nfs_export *exp, nfs_client *clp, struct exportent *nep)
+{
+ struct exportent *e = &exp->m_export;
+
+ dupexportent(e, nep);
+
+ exp->m_exported = 0;
+ exp->m_xtabent = 0;
+ exp->m_mayexport = 0;
+ exp->m_changed = 0;
+ exp->m_client = clp;
+ clp->m_count++;
+}
+
+/*
+ * Duplicate exports data. The in-core export struct retains the
+ * original hostname from /etc/exports, while the in-core client struct
+ * gets the newly found FQDN.
+ */
+nfs_export *
+export_dup(nfs_export *exp, struct hostent *hp)
+{
+ nfs_export *new;
+ nfs_client *clp;
+
+ new = (nfs_export *) xmalloc(sizeof(*new));
+ memcpy(new, exp, sizeof(*new));
+ dupexportent(&new->m_export, &exp->m_export);
+ clp = client_dup(exp->m_client, hp);
+ clp->m_count++;
+ new->m_client = clp;
+ new->m_mayexport = exp->m_mayexport;
+ new->m_exported = 0;
+ new->m_xtabent = 0;
+ new->m_changed = 0;
+ export_add(new);
+
+ return new;
+}
+
+void
+export_add(nfs_export *exp)
+{
+ nfs_export **epp;
+ int type = exp->m_client->m_type;
+ int slen = strlen(exp->m_export.e_path);
+
+ if (type < 0 || type >= MCL_MAXTYPES)
+ xlog(L_FATAL, "unknown client type in export_add");
+
+ epp = exportlist + type;
+ while (*epp && slen < strlen((*epp)->m_export.e_path))
+ epp = &((*epp)->m_next);
+ exp->m_next = *epp;
+ *epp = exp;
+}
+
+nfs_export *
+export_find(struct hostent *hp, char *path)
+{
+ nfs_export *exp;
+ int i;
+
+ for (i = 0; i < MCL_MAXTYPES; i++) {
+ for (exp = exportlist[i]; exp; exp = exp->m_next) {
+ if (!export_check(exp, hp, path))
+ continue;
+ if (exp->m_client->m_type == MCL_FQDN)
+ return exp;
+ return export_dup(exp, hp);
+ }
+ }
+
+ return NULL;
+}
+
+static nfs_export *
+export_allowed_internal (struct hostent *hp, char *path)
+{
+ nfs_export *exp;
+ int i;
+
+ for (i = 0; i < MCL_MAXTYPES; i++) {
+ for (exp = exportlist[i]; exp; exp = exp->m_next) {
+ if (!exp->m_mayexport ||
+ !export_check(exp, hp, path))
+ continue;
+ return exp;
+ }
+ }
+
+ return NULL;
+}
+
+struct exportent *
+export_allowed(struct hostent *hp, char *path)
+{
+ static struct exportent ee;
+ nfs_export *exp;
+ char epath[MAXPATHLEN+1];
+ char *p = NULL;
+
+ if (path [0] != '/') return NULL;
+
+ strncpy(epath, path, sizeof (epath) - 1);
+ epath[sizeof (epath) - 1] = '\0';
+
+ /* Try the longest matching exported pathname. */
+ while (1) {
+ exp = export_allowed_internal (hp, epath);
+ if (exp) {
+ dupexportent(&ee, &exp->m_export);
+ return &ee;
+ }
+ /* We have to treat the root, "/", specially. */
+ if (p == &epath[1]) break;
+ p = strrchr(epath, '/');
+ if (p == epath) p++;
+ *p = '\0';
+ }
+
+ return NULL;
+}
+
+nfs_export *
+export_lookup(char *hname, char *path)
+{
+ nfs_client *clp;
+ nfs_export *exp;
+
+ if (!(clp = client_lookup(hname)))
+ return NULL;
+ for (exp = exportlist[clp->m_type]; exp; exp = exp->m_next)
+ if (exp->m_client == clp && !strcmp(exp->m_export.e_path, path))
+ return exp;
+ return NULL;
+}
+
+static int
+export_check(nfs_export *exp, struct hostent *hp, char *path)
+{
+ if (strcmp(path, exp->m_export.e_path))
+ return 0;
+
+ return client_check(exp->m_client, hp);
+}
+
+void
+export_freeall(void)
+{
+ nfs_export *exp, *nxt;
+ int i;
+
+ for (i = 0; i < MCL_MAXTYPES; i++) {
+ for (exp = exportlist[i]; exp; exp = nxt) {
+ nxt = exp->m_next;
+ client_release(exp->m_client);
+ if (exp->m_export.e_squids)
+ xfree(exp->m_export.e_squids);
+ if (exp->m_export.e_sqgids)
+ xfree(exp->m_export.e_sqgids);
+ xfree(exp);
+ }
+ exportlist[i] = NULL;
+ }
+ client_freeall();
+}
+
+void
+export_reset(nfs_export *exp)
+{
+ if (!exp)
+ return;
+
+ /* Restore m_path. */
+ strncpy(exp->m_export.m_path, exp->m_export.e_path,
+ sizeof (exp->m_export.m_path) - 1);
+ exp->m_export.m_path[sizeof (exp->m_export.m_path) - 1] = '\0';
+}
diff --git a/support/export/hostname.c b/support/export/hostname.c
new file mode 100644
index 0000000..a37d4de
--- /dev/null
+++ b/support/export/hostname.c
@@ -0,0 +1,262 @@
+/*
+ * support/export/hostname.c
+ *
+ * Functions for hostname.
+ *
+ */
+
+#include "config.h"
+
+/*
+#define TEST
+*/
+
+#include <string.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#ifdef TEST
+#define xmalloc malloc
+#else
+#include "xmalloc.h"
+#include "misc.h"
+#endif
+
+#define ALIGNMENT sizeof (char *)
+
+static int
+align (int len, int al)
+{
+ int i;
+ i = len % al;
+ if (i)
+ len += al - i;
+ return len;
+}
+
+struct hostent *
+get_hostent (const char *addr, int len, int type)
+{
+ struct hostent *cp;
+ int len_ent;
+ const char *name;
+ int len_name;
+ int num_aliases = 1;
+ int len_aliases = sizeof (char *);
+ int num_addr_list = 1;
+ int len_addr_list = sizeof (char *);
+ int pos;
+ struct in_addr *ipv4;
+
+ switch (type)
+ {
+ case AF_INET:
+ ipv4 = (struct in_addr *) addr;
+ name = inet_ntoa (*ipv4);
+ break;
+
+ default:
+ return NULL;
+ }
+
+ len_ent = align (sizeof (*cp), ALIGNMENT);
+ len_name = align (strlen (name) + 1, ALIGNMENT);
+
+ num_addr_list++;
+ len_addr_list += align (len, ALIGNMENT) + sizeof (char *);
+
+ cp = (struct hostent *) xmalloc (len_ent + len_name + len_aliases
+ + len_addr_list);
+
+ cp->h_addrtype = type;
+ cp->h_length = len;
+ pos = len_ent;
+ cp->h_name = (char *) &(((char *) cp) [pos]);
+ strcpy (cp->h_name, name);
+
+ pos += len_name;
+ cp->h_aliases = (char **) &(((char *) cp) [pos]);
+ pos += num_aliases * sizeof (char *);
+ cp->h_aliases [0] = NULL;
+
+ pos = len_ent + len_name + len_aliases;
+ cp->h_addr_list = (char **) &(((char *) cp) [pos]);
+ pos += num_addr_list * sizeof (char *);
+ cp->h_addr_list [0] = (char *) &(((char *) cp) [pos]);
+ memcpy (cp->h_addr_list [0], addr, cp->h_length);
+ pos += align (cp->h_length, ALIGNMENT);
+ cp->h_addr_list [1] = NULL;
+
+ return cp;
+}
+
+struct hostent *
+hostent_dup (struct hostent *hp)
+{
+ int len_ent = align (sizeof (*hp), ALIGNMENT);
+ int len_name = align (strlen (hp->h_name) + 1, ALIGNMENT);
+ int num_aliases = 1;
+ int len_aliases = sizeof (char *);
+ int num_addr_list = 1;
+ int len_addr_list = sizeof (char *);
+ int pos, i;
+ char **sp;
+ struct hostent *cp;
+
+ for (sp = hp->h_aliases; *sp; sp++)
+ {
+ num_aliases++;
+ len_aliases += align (strlen (*sp) + 1, ALIGNMENT)
+ + sizeof (char *);
+ }
+
+ for (sp = hp->h_addr_list; *sp; sp++)
+ {
+ num_addr_list++;
+ len_addr_list += align (hp->h_length, ALIGNMENT)
+ + sizeof (char *);
+ }
+
+ cp = (struct hostent *) xmalloc (len_ent + len_name + len_aliases
+ + len_addr_list);
+
+ *cp = *hp;
+ pos = len_ent;
+ cp->h_name = (char *) &(((char *) cp) [pos]);
+ strcpy (cp->h_name, hp->h_name);
+
+ pos += len_name;
+ cp->h_aliases = (char **) &(((char *) cp) [pos]);
+ pos += num_aliases * sizeof (char *);
+ for (sp = hp->h_aliases, i = 0; i < num_aliases; i++, sp++)
+ if (*sp)
+ {
+ cp->h_aliases [i] = (char *) &(((char *) cp) [pos]);
+ strcpy (cp->h_aliases [i], *sp);
+ pos += align (strlen (*sp) + 1, ALIGNMENT);
+ }
+ else
+ cp->h_aliases [i] = *sp;
+
+ pos = len_ent + len_name + len_aliases;
+ cp->h_addr_list = (char **) &(((char *) cp) [pos]);
+ pos += num_addr_list * sizeof (char *);
+ for (sp = hp->h_addr_list, i = 0; i < num_addr_list; i++, sp++)
+ if (*sp)
+ {
+ cp->h_addr_list [i] = (char *) &(((char *) cp) [pos]);
+ memcpy (cp->h_addr_list [i], *sp, hp->h_length);
+ pos += align (hp->h_length, ALIGNMENT);
+ }
+ else
+ cp->h_addr_list [i] = *sp;
+
+ return cp;
+}
+
+static int
+is_hostname(const char *sp)
+{
+ if (*sp == '\0' || *sp == '@')
+ return 0;
+
+ for (; *sp; sp++)
+ {
+ if (*sp == '*' || *sp == '?' || *sp == '[' || *sp == '/')
+ return 0;
+ if (*sp == '\\' && sp[1])
+ sp++;
+ }
+
+ return 1;
+}
+
+int
+matchhostname (const char *h1, const char *h2)
+{
+ struct hostent *hp1, *hp2;
+ int status;
+
+ if (strcasecmp (h1, h2) == 0)
+ return 1;
+
+ if (!is_hostname (h1) || !is_hostname (h2))
+ return 0;
+
+ hp1 = gethostbyname (h1);
+ if (hp1 == NULL)
+ return 0;
+
+ hp1 = hostent_dup (hp1);
+
+ hp2 = gethostbyname (h2);
+ if (hp2)
+ {
+ if (strcasecmp (hp1->h_name, hp2->h_name) == 0)
+ status = 1;
+ else
+ {
+ char **ap1, **ap2;
+
+ status = 0;
+ for (ap1 = hp1->h_addr_list; *ap1 && status == 0; ap1++)
+ for (ap2 = hp2->h_addr_list; *ap2; ap2++)
+ if (memcmp (*ap1, *ap2, sizeof (struct in_addr)) == 0)
+ {
+ status = 1;
+ break;
+ }
+ }
+ }
+ else
+ status = 0;
+
+ free (hp1);
+ return status;
+}
+
+#ifdef TEST
+void
+print_host (struct hostent *hp)
+{
+ char **sp;
+
+ if (hp)
+ {
+ printf ("official hostname: %s\n", hp->h_name);
+ printf ("aliases:\n");
+ for (sp = hp->h_aliases; *sp; sp++)
+ printf (" %s\n", *sp);
+ printf ("IP addresses:\n");
+ for (sp = hp->h_addr_list; *sp; sp++)
+ printf (" %s\n", inet_ntoa (*(struct in_addr *) *sp));
+ }
+ else
+ printf ("Not host information\n");
+}
+
+int
+main (int argc, char **argv)
+{
+ struct hostent *hp = gethostbyname (argv [1]);
+ struct hostent *cp;
+ struct in_addr addr;
+
+ print_host (hp);
+
+ if (hp)
+ {
+ cp = hostent_dup (hp);
+ print_host (cp);
+ free (cp);
+ }
+ printf ("127.0.0.1 == %s: %d\n", argv [1],
+ matchhostname ("127.0.0.1", argv [1]));
+ addr.s_addr = inet_addr(argv [2]);
+ printf ("%s\n", inet_ntoa (addr));
+ cp = get_hostent ((const char *)&addr, sizeof(addr), AF_INET);
+ print_host (cp);
+ return 0;
+}
+#endif
diff --git a/support/export/keys.c b/support/export/keys.c
new file mode 100644
index 0000000..4814808
--- /dev/null
+++ b/support/export/keys.c
@@ -0,0 +1,72 @@
+/*
+ * keys.c Key management for nfsd. Currently, keys
+ * are kept in a single file only, but eventually,
+ * support for a key server should be added.
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <sys/stat.h>
+#include "nfslib.h"
+#include "exportfs.h"
+#include "xmalloc.h"
+
+struct keycache {
+ struct keycache * k_next;
+ struct nfskeyent k_data;
+};
+
+static struct keycache * keycache = NULL;
+static time_t lastmod = 0;
+
+static void key_reload(void);
+
+
+struct nfskey *
+key_lookup(char *hname)
+{
+ struct keycache *kc;
+
+ key_reload();
+
+ for (kc = keycache; kc; kc = kc->k_next) {
+#if 0
+ if (matchhostname(kc->k_data.k_hostname, hname))
+#else
+ if (!strcmp(kc->k_data.k_hostname, hname))
+#endif
+ return &kc->k_data.k_key;
+ }
+
+ return NULL;
+}
+
+static void
+key_reload(void)
+{
+ struct stat stb;
+ struct keycache *cp;
+ struct nfskeyent *kp;
+
+ if (stat(_PATH_NFSKEYS, &stb) >= 0 && stb.st_mtime == lastmod)
+ return;
+
+ while (keycache) {
+ cp = keycache->k_next;
+ xfree(keycache);
+ keycache = cp;
+ }
+
+ setnfskeyent(_PATH_NFSKEYS);
+ while ((kp = getnfskeyent()) != NULL) {
+ cp = (struct keycache *) xmalloc(sizeof(*cp));
+ cp->k_data = *kp;
+ cp->k_next = keycache;
+ keycache = cp;
+ }
+ endnfskeyent();
+
+ lastmod = stb.st_mtime;
+}
diff --git a/support/export/mount.x b/support/export/mount.x
new file mode 100644
index 0000000..f504e7c
--- /dev/null
+++ b/support/export/mount.x
@@ -0,0 +1,345 @@
+%/*
+% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+% * unrestricted use provided that this legend is included on all tape
+% * media and as a part of the software program in whole or part. Users
+% * may copy or modify Sun RPC without charge, but are not authorized
+% * to license or distribute it to anyone else except as part of a product or
+% * program developed by the user or with the express written consent of
+% * Sun Microsystems, Inc.
+% *
+% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+% *
+% * Sun RPC is provided with no support and without any obligation on the
+% * part of Sun Microsystems, Inc. to assist in its use, correction,
+% * modification or enhancement.
+% *
+% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+% * OR ANY PART THEREOF.
+% *
+% * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+% * or profits or other special, indirect and consequential damages, even if
+% * Sun has been advised of the possibility of such damages.
+% *
+% * Sun Microsystems, Inc.
+% * 2550 Garcia Avenue
+% * Mountain View, California 94043
+% */
+
+%/*
+% * Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
+% */
+%
+%/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */
+
+/*
+ * Protocol description for the mount program
+ */
+
+#ifdef RPC_HDR
+%#ifndef _rpcsvc_mount_h
+%#define _rpcsvc_mount_h
+%#include <memory.h>
+#endif
+
+const MNTPATHLEN = 1024; /* maximum bytes in a pathname argument */
+const MNTNAMLEN = 255; /* maximum bytes in a name argument */
+const FHSIZE = 32; /* size in bytes of a file handle */
+
+/*
+ * The fhandle is the file handle that the server passes to the client.
+ * All file operations are done using the file handles to refer to a file
+ * or a directory. The file handle can contain whatever information the
+ * server needs to distinguish an individual file.
+ */
+typedef opaque fhandle[FHSIZE];
+
+/*
+ * If a status of zero is returned, the call completed successfully, and
+ * a file handle for the directory follows. A non-zero status indicates
+ * some sort of error. The status corresponds with UNIX error numbers.
+ */
+union fhstatus switch (unsigned fhs_status) {
+case 0:
+ fhandle fhs_fhandle;
+default:
+ void;
+};
+
+/*
+ * The type dirpath is the pathname of a directory
+ */
+typedef string dirpath<MNTPATHLEN>;
+
+/*
+ * The type name is used for arbitrary names (hostnames, groupnames)
+ */
+typedef string name<MNTNAMLEN>;
+
+/*
+ * A list of who has what mounted
+ */
+typedef struct mountbody *mountlist;
+struct mountbody {
+ name ml_hostname;
+ dirpath ml_directory;
+ mountlist ml_next;
+};
+
+/*
+ * A list of netgroups
+ */
+typedef struct groupnode *groups;
+struct groupnode {
+ name gr_name;
+ groups gr_next;
+};
+
+/*
+ * A list of what is exported and to whom
+ */
+typedef struct exportnode *exports;
+struct exportnode {
+ dirpath ex_dir;
+ groups ex_groups;
+ exports ex_next;
+};
+
+/*
+ * POSIX pathconf information
+ */
+struct ppathcnf {
+ int pc_link_max; /* max links allowed */
+ short pc_max_canon; /* max line len for a tty */
+ short pc_max_input; /* input a tty can eat all at once */
+ short pc_name_max; /* max file name length (dir entry) */
+ short pc_path_max; /* max path name length (/x/y/x/.. ) */
+ short pc_pipe_buf; /* size of a pipe (bytes) */
+ u_char pc_vdisable; /* safe char to turn off c_cc[i] */
+ char pc_xxx; /* alignment padding; cc_t == char */
+ short pc_mask[2]; /* validity and boolean bits */
+};
+
+/*
+ * NFSv3 file handle
+ */
+const FHSIZE3 = 64; /* max size of NFSv3 file handle in bytes */
+typedef opaque fhandle3<FHSIZE3>;
+
+/*
+ * NFSv3 mount status
+ */
+enum mountstat3 {
+ MNT_OK = 0, /* no error */
+ MNT3ERR_PERM = 1, /* not owner */
+ MNT3ERR_NOENT = 2, /* no such file or directory */
+ MNT3ERR_IO = 5, /* I/O error */
+ MNT3ERR_ACCES = 13, /* Permission denied */
+ MNT3ERR_NOTDIR = 20, /* Not a directory */
+ MNT3ERR_INVAL = 22, /* Invalid argument */
+ MNT3ERR_NAMETOOLONG = 63, /* File name too long */
+ MNT3ERR_NOTSUPP = 10004,/* Operation not supported */
+ MNT3ERR_SERVERFAULT = 10006 /* A failure on the server */
+};
+
+/*
+ * NFSv3 mount result
+ */
+struct mountres3_ok {
+ fhandle3 fhandle;
+ int auth_flavors<>;
+};
+
+union mountres3 switch (mountstat3 fhs_status) {
+case MNT_OK:
+ mountres3_ok mountinfo; /* File handle and supported flavors */
+default:
+ void;
+};
+
+program MOUNTPROG {
+ /*
+ * Version one of the mount protocol communicates with version two
+ * of the NFS protocol. The only connecting point is the fhandle
+ * structure, which is the same for both protocols.
+ */
+ version MOUNTVERS {
+ /*
+ * Does no work. It is made available in all RPC services
+ * to allow server reponse testing and timing
+ */
+ void
+ MOUNTPROC_NULL(void) = 0;
+
+ /*
+ * If fhs_status is 0, then fhs_fhandle contains the
+ * file handle for the directory. This file handle may
+ * be used in the NFS protocol. This procedure also adds
+ * a new entry to the mount list for this client mounting
+ * the directory.
+ * Unix authentication required.
+ */
+ fhstatus
+ MOUNTPROC_MNT(dirpath) = 1;
+
+ /*
+ * Returns the list of remotely mounted filesystems. The
+ * mountlist contains one entry for each hostname and
+ * directory pair.
+ */
+ mountlist
+ MOUNTPROC_DUMP(void) = 2;
+
+ /*
+ * Removes the mount list entry for the directory
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC_UMNT(dirpath) = 3;
+
+ /*
+ * Removes all of the mount list entries for this client
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC_UMNTALL(void) = 4;
+
+ /*
+ * Returns a list of all the exported filesystems, and which
+ * machines are allowed to import it.
+ */
+ exports
+ MOUNTPROC_EXPORT(void) = 5;
+
+ /*
+ * Identical to MOUNTPROC_EXPORT above
+ */
+ exports
+ MOUNTPROC_EXPORTALL(void) = 6;
+ } = 1;
+
+ /*
+ * Version two of the mount protocol communicates with version two
+ * of the NFS protocol.
+ * The only difference from version one is the addition of a POSIX
+ * pathconf call.
+ */
+ version MOUNTVERS_POSIX {
+ /*
+ * Does no work. It is made available in all RPC services
+ * to allow server reponse testing and timing
+ */
+ void
+ MOUNTPROC_NULL(void) = 0;
+
+ /*
+ * If fhs_status is 0, then fhs_fhandle contains the
+ * file handle for the directory. This file handle may
+ * be used in the NFS protocol. This procedure also adds
+ * a new entry to the mount list for this client mounting
+ * the directory.
+ * Unix authentication required.
+ */
+ fhstatus
+ MOUNTPROC_MNT(dirpath) = 1;
+
+ /*
+ * Returns the list of remotely mounted filesystems. The
+ * mountlist contains one entry for each hostname and
+ * directory pair.
+ */
+ mountlist
+ MOUNTPROC_DUMP(void) = 2;
+
+ /*
+ * Removes the mount list entry for the directory
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC_UMNT(dirpath) = 3;
+
+ /*
+ * Removes all of the mount list entries for this client
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC_UMNTALL(void) = 4;
+
+ /*
+ * Returns a list of all the exported filesystems, and which
+ * machines are allowed to import it.
+ */
+ exports
+ MOUNTPROC_EXPORT(void) = 5;
+
+ /*
+ * Identical to MOUNTPROC_EXPORT above
+ */
+ exports
+ MOUNTPROC_EXPORTALL(void) = 6;
+
+ /*
+ * POSIX pathconf info (Sun hack)
+ */
+ ppathcnf
+ MOUNTPROC_PATHCONF(dirpath) = 7;
+ } = 2;
+
+ /*
+ * Version 3 of the protocol is for NFSv3
+ */
+ version MOUNTVERS_NFSV3 {
+ /*
+ * Does no work. It is made available in all RPC services
+ * to allow server reponse testing and timing
+ */
+ void
+ MOUNTPROC3_NULL(void) = 0;
+
+ /*
+ * If fhs_status is 0, then fhs_fhandle contains the
+ * file handle for the directory. This file handle may
+ * be used in the NFS protocol. This procedure also adds
+ * a new entry to the mount list for this client mounting
+ * the directory.
+ * Unix authentication required.
+ */
+ mountres3
+ MOUNTPROC3_MNT(dirpath) = 1;
+
+ /*
+ * Returns the list of remotely mounted filesystems. The
+ * mountlist contains one entry for each hostname and
+ * directory pair.
+ */
+ mountlist
+ MOUNTPROC3_DUMP(void) = 2;
+
+ /*
+ * Removes the mount list entry for the directory
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC3_UMNT(dirpath) = 3;
+
+ /*
+ * Removes all of the mount list entries for this client
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC3_UMNTALL(void) = 4;
+
+ /*
+ * Returns a list of all the exported filesystems, and which
+ * machines are allowed to import it.
+ */
+ exports
+ MOUNTPROC3_EXPORT(void) = 5;
+ } = 3;
+} = 100005;
+
+#ifdef RPC_HDR
+%#endif /*!_rpcsvc_mount_h*/
+#endif
diff --git a/support/export/nfsctl.c b/support/export/nfsctl.c
new file mode 100644
index 0000000..6612a76
--- /dev/null
+++ b/support/export/nfsctl.c
@@ -0,0 +1,105 @@
+/*
+ * support/export/nfsctl.c
+ *
+ * Communicate export information to knfsd.
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "nfslib.h"
+#include "exportfs.h"
+#include "xio.h"
+
+static int expsetup(struct nfsctl_export *exparg, nfs_export *exp);
+static int cltsetup(struct nfsctl_client *cltarg, nfs_client *clp);
+
+int
+export_export(nfs_export *exp)
+{
+ nfs_client * clp = exp->m_client;
+ struct nfsctl_export exparg;
+ struct nfsctl_client cltarg;
+
+ if (!clp->m_exported) {
+ if (!cltsetup(&cltarg, clp))
+ return 0;
+ if (nfsaddclient(&cltarg) < 0)
+ return 0;
+ clp->m_exported = 1;
+ }
+ if (!expsetup(&exparg, exp))
+ return 0;
+ if (nfsexport(&exparg) < 0)
+ return 0;
+ exp->m_exported = 1;
+ return 1;
+}
+
+int
+export_unexport(nfs_export *exp)
+{
+ struct nfsctl_export exparg;
+
+ if (!expsetup(&exparg, exp) || nfsunexport(&exparg) < 0)
+ return 0;
+ exp->m_exported = 0;
+ return 1;
+}
+
+static void
+str_tolower(char *s)
+{
+ for ( ; *s; s++)
+ if (isupper(*s))
+ *s = tolower(*s);
+}
+
+static int
+cltsetup(struct nfsctl_client *cltarg, nfs_client *clp)
+{
+ int i;
+
+ if (clp->m_type != MCL_FQDN) {
+ xlog(L_ERROR, "internal: can't export non-FQDN host");
+ return 0;
+ }
+ memset(cltarg, 0, sizeof(*cltarg));
+ strncpy(cltarg->cl_ident, clp->m_hostname,
+ sizeof (cltarg->cl_ident) - 1);
+ str_tolower(cltarg->cl_ident);
+ cltarg->cl_naddr = clp->m_naddr;
+ for (i = 0; i < cltarg->cl_naddr && i < NFSCLNT_ADDRMAX; i++)
+ cltarg->cl_addrlist[i] = clp->m_addrlist[i];
+
+ return 1;
+}
+
+static int
+expsetup(struct nfsctl_export *exparg, nfs_export *exp)
+{
+ nfs_client *clp = exp->m_client;
+ struct stat stb;
+
+ if (stat(exp->m_export.m_path, &stb) < 0)
+ return 0;
+
+ memset(exparg, 0, sizeof(*exparg));
+ strncpy(exparg->ex_path, exp->m_export.m_path,
+ sizeof (exparg->ex_path) - 1);
+ strncpy(exparg->ex_client, clp->m_hostname,
+ sizeof (exparg->ex_client) - 1);
+ str_tolower(exparg->ex_client);
+ exparg->ex_flags = exp->m_export.e_flags;
+ exparg->ex_dev = stb.st_dev;
+ exparg->ex_ino = stb.st_ino;
+ exparg->ex_anon_uid = exp->m_export.e_anonuid;
+ exparg->ex_anon_gid = exp->m_export.e_anongid;
+
+ return 1;
+}
diff --git a/support/export/rmtab.c b/support/export/rmtab.c
new file mode 100644
index 0000000..44a0edc
--- /dev/null
+++ b/support/export/rmtab.c
@@ -0,0 +1,79 @@
+/*
+ * support/export/rmntab.c
+ *
+ * Interface to the rmnt file.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "xmalloc.h"
+#include "misc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+#include "xio.h"
+#include "xlog.h"
+
+int
+rmtab_read(void)
+{
+ struct rmtabent *rep;
+ nfs_export *exp;
+
+ setrmtabent("r");
+ while ((rep = getrmtabent(1)) != NULL) {
+ exp = export_lookup(rep->r_client, rep->r_path);
+ if (!exp) {
+ struct exportent *xp;
+ struct hostent *hp;
+ int htype;
+
+ htype = client_gettype(rep->r_client);
+ if (htype == MCL_FQDN
+ && (hp = gethostbyname (rep->r_client), hp)
+ && (hp = hostent_dup (hp),
+ xp = export_allowed (hp, rep->r_path))) {
+ strncpy (xp->e_hostname, rep->r_client,
+ sizeof (xp->e_hostname) - 1);
+ xp->e_hostname[sizeof (xp->e_hostname) -1] = '\0';
+ exp = export_create(xp);
+ free (hp);
+ }
+
+ if (!exp)
+ continue;
+ exp->m_mayexport = 1;
+ }
+ }
+ if (errno == EINVAL) {
+ /* Something goes wrong. We need to fix the rmtab
+ file. */
+ int lockid;
+ FILE *fp;
+ if ((lockid = xflock(_PATH_RMTAB, "w")) < 0)
+ return -1;
+ rewindrmtabent();
+ if (!(fp = fsetrmtabent(_PATH_RMTABTMP, "w"))) {
+ endrmtabent ();
+ xfunlock(lockid);
+ return -1;
+ }
+ while ((rep = getrmtabent(0)) != NULL) {
+ fputrmtabent(fp, rep);
+ }
+ if (rename(_PATH_RMTABTMP, _PATH_RMTAB) < 0) {
+ xlog(L_ERROR, "couldn't rename %s to %s",
+ _PATH_RMTABTMP, _PATH_RMTAB);
+ }
+ endrmtabent();
+ fendrmtabent(fp);
+ xfunlock(lockid);
+ }
+ else {
+ endrmtabent();
+ }
+ return 0;
+}
diff --git a/support/export/xtab.c b/support/export/xtab.c
new file mode 100644
index 0000000..4289d7c
--- /dev/null
+++ b/support/export/xtab.c
@@ -0,0 +1,133 @@
+/*
+ * support/export/xtab.c
+ *
+ * Interface to the xtab file.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <sys/fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include "xmalloc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+#include "xio.h"
+#include "xlog.h"
+
+static int
+xtab_read(char *xtab, int is_export)
+{
+ struct exportent *xp;
+ nfs_export *exp;
+ int lockid;
+
+ if ((lockid = xflock(xtab, "r")) < 0)
+ return 0;
+ setexportent(xtab, "r");
+ while ((xp = getexportent()) != NULL) {
+ if (!(exp = export_lookup(xp->e_hostname, xp->e_path)) &&
+ !(exp = export_create(xp))) {
+ continue;
+ }
+ if (is_export) {
+ exp->m_xtabent = 1;
+ exp->m_mayexport = 1;
+ } else
+ exp->m_exported = 1;
+ }
+ endexportent();
+ xfunlock(lockid);
+
+ return 0;
+}
+
+int
+xtab_mount_read(void)
+{
+ int fd;
+ if ((fd=open(_PATH_PROC_EXPORTS, O_RDONLY))>=0) {
+ close(fd);
+ return xtab_read(_PATH_PROC_EXPORTS, 0);
+ } else
+ return xtab_read(_PATH_XTAB, 0);
+}
+
+int
+xtab_export_read(void)
+{
+ return xtab_read(_PATH_ETAB, 1);
+}
+
+static int
+xtab_write(char *xtab, char *xtabtmp, int is_export)
+{
+ struct exportent xe;
+ nfs_export *exp;
+ int lockid, i;
+
+ if ((lockid = xflock(xtab, "w")) < 0) {
+ xlog(L_ERROR, "can't lock %s for writing", xtab);
+ return 0;
+ }
+ setexportent(xtabtmp, "w");
+
+ for (i = 0; i < MCL_MAXTYPES; i++) {
+ for (exp = exportlist[i]; exp; exp = exp->m_next) {
+ if (is_export && !exp->m_xtabent)
+ continue;
+ if (!is_export && ! exp->m_exported)
+ continue;
+
+ /* write out the export entry using the FQDN */
+ xe = exp->m_export;
+ strncpy(xe.e_hostname,
+ exp->m_client->m_hostname,
+ sizeof (xe.e_hostname) - 1);
+ xe.e_hostname[sizeof (xe.e_hostname) - 1] = '\0';
+ putexportent(&xe);
+ }
+ }
+ endexportent();
+
+ rename(xtabtmp, xtab);
+
+ xfunlock(lockid);
+
+ return 1;
+}
+
+int
+xtab_export_write()
+{
+ return xtab_write(_PATH_ETAB, _PATH_ETABTMP, 1);
+}
+
+int
+xtab_mount_write()
+{
+ return xtab_write(_PATH_XTAB, _PATH_XTABTMP, 0);
+}
+
+void
+xtab_append(nfs_export *exp)
+{
+ struct exportent xe;
+ int lockid;
+
+ if ((lockid = xflock(_PATH_XTAB, "w")) < 0)
+ return;
+ setexportent(_PATH_XTAB, "a");
+ xe = exp->m_export;
+ strncpy(xe.e_hostname, exp->m_client->m_hostname,
+ sizeof (xe.e_hostname) - 1);
+ xe.e_hostname[sizeof (xe.e_hostname) - 1] = '\0';
+ putexportent(&xe);
+ endexportent();
+ xfunlock(lockid);
+ exp->m_xtabent = 1;
+}
+
diff --git a/support/include/Makefile b/support/include/Makefile
new file mode 100644
index 0000000..e1cbfc4
--- /dev/null
+++ b/support/include/Makefile
@@ -0,0 +1,16 @@
+#
+# Makefile for linux-nfs/support
+#
+
+include $(TOP)rules.mk
+
+all install:: mount.h
+ @:
+
+distclean::
+ $(RM) mount.h config.h
+
+mount.h:
+ $(LN_S) ../export/mount.h .
+
+# .EXPORT_ALL_VARIABLES:
diff --git a/support/include/config.h.in b/support/include/config.h.in
new file mode 100644
index 0000000..f8c1497
--- /dev/null
+++ b/support/include/config.h.in
@@ -0,0 +1,25 @@
+/* Define this if you have standard C headers
+ */
+#undef STDC_HEADERS
+
+/* Define this if you have string.h */
+#undef HAVE_STRING_H
+
+/* Define this if you have netgroup support
+ */
+#undef HAVE_INNETGR
+
+/* Define this if you want NFSv3 support compiled in
+ */
+#undef NFS3_SUPPORTED
+
+/* This defines the location of the NFS state files
+ * Warning: these must match definitions in config.mk!
+ */
+#define NFS_STATEDIR "/var/lib/nfs"
+
+/* Define this if you want to enable various security
+ * checks in statd. These checks basically keep anyone
+ * but lockd from using this service.
+ */
+#undef RESTRICTED_STATD
diff --git a/support/include/exportfs.h b/support/include/exportfs.h
new file mode 100644
index 0000000..d440dc1
--- /dev/null
+++ b/support/include/exportfs.h
@@ -0,0 +1,80 @@
+/*
+ * support/include/exportfs.h
+ *
+ * Declarations for exportfs and mountd
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef EXPORTFS_H
+#define EXPORTFS_H
+
+#include <netdb.h>
+#include "nfslib.h"
+
+enum {
+ MCL_FQDN = 0,
+ MCL_SUBNETWORK,
+ MCL_IPADDR = MCL_SUBNETWORK,
+ MCL_WILDCARD,
+ MCL_NETGROUP,
+ MCL_ANONYMOUS,
+ MCL_MAXTYPES
+};
+
+typedef struct mclient {
+ struct mclient * m_next;
+ char m_hostname[NFSCLNT_IDMAX+1];
+ int m_type;
+ int m_naddr;
+ struct in_addr m_addrlist[NFSCLNT_ADDRMAX];
+ int m_exported; /* exported to nfsd */
+ int m_count;
+} nfs_client;
+
+typedef struct mexport {
+ struct mexport * m_next;
+ struct mclient * m_client;
+ struct exportent m_export;
+ int m_exported : 1, /* known to knfsd */
+ m_xtabent : 1, /* xtab entry exists */
+ m_mayexport: 1, /* derived from xtabbed */
+ m_changed : 1; /* options (may) have changed */
+} nfs_export;
+
+extern nfs_client * clientlist[MCL_MAXTYPES];
+extern nfs_export * exportlist[MCL_MAXTYPES];
+
+nfs_client * client_lookup(char *hname);
+nfs_client * client_find(struct hostent *);
+void client_add(nfs_client *);
+nfs_client * client_dup(nfs_client *, struct hostent *);
+int client_gettype(char *hname);
+int client_check(nfs_client *, struct hostent *);
+int client_match(nfs_client *, char *hname);
+void client_release(nfs_client *);
+void client_freeall(void);
+
+int export_read(char *fname);
+void export_add(nfs_export *);
+void export_reset(nfs_export *);
+nfs_export * export_lookup(char *hname, char *path);
+nfs_export * export_find(struct hostent *, char *path);
+struct exportent * export_allowed(struct hostent *, char *path);
+nfs_export * export_create(struct exportent *);
+nfs_export * export_dup(nfs_export *, struct hostent *);
+void export_freeall(void);
+int export_export(nfs_export *);
+int export_unexport(nfs_export *);
+
+int xtab_mount_read(void);
+int xtab_export_read(void);
+int xtab_mount_write(void);
+int xtab_export_write(void);
+void xtab_append(nfs_export *);
+
+int rmtab_read(void);
+
+struct nfskey * key_lookup(char *hname);
+
+#endif /* EXPORTFS_H */
diff --git a/support/include/misc.h b/support/include/misc.h
new file mode 100644
index 0000000..a3cdcfd
--- /dev/null
+++ b/support/include/misc.h
@@ -0,0 +1,24 @@
+/*
+ * misc.h All that didn't fit elsewhere.
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef MISC_H
+#define MISC_H
+
+/*
+ * Generate random key, returning the length of the result. Currently,
+ * weakrandomkey generates a maximum of 20 bytes are generated, but this
+ * may change with future implementations.
+ */
+int randomkey(unsigned char *keyout, int len);
+int weakrandomkey(unsigned char *keyout, int len);
+
+int matchhostname(const char *h1, const char *h2);
+
+struct hostent;
+struct hostent *hostent_dup(struct hostent *hp);
+struct hostent *get_hostent (const char *addr, int len, int type);
+
+#endif /* MISC_H */
diff --git a/support/include/nfs/debug.h b/support/include/nfs/debug.h
new file mode 100644
index 0000000..876b5db
--- /dev/null
+++ b/support/include/nfs/debug.h
@@ -0,0 +1,75 @@
+#ifndef _NFS_DEBUG_H
+#define _NFS_DEBUG_H
+
+/*
+ * RPC debug facilities
+ */
+#define RPCDBG_XPRT 0x0001
+#define RPCDBG_CALL 0x0002
+#define RPCDBG_DEBUG 0x0004
+#define RPCDBG_NFS 0x0008
+#define RPCDBG_AUTH 0x0010
+#define RPCDBG_PMAP 0x0020
+#define RPCDBG_SCHED 0x0040
+#define RPCDBG_SVCSOCK 0x0100
+#define RPCDBG_SVCDSP 0x0200
+#define RPCDBG_MISC 0x0400
+#define RPCDBG_ALL 0x7fff
+
+/*
+ * Declarations for the sysctl debug interface, which allows to read or
+ * change the debug flags for rpc, nfs, nfsd, and lockd. Since the sunrpc
+ * module currently registers its sysctl table dynamically, the sysctl path
+ * for module FOO is <CTL_SUNRPC, CTL_FOODEBUG>.
+ */
+#define CTL_SUNRPC 7249 /* arbitrary and hopefully unused */
+
+enum {
+ CTL_RPCDEBUG = 1,
+ CTL_NFSDEBUG,
+ CTL_NFSDDEBUG,
+ CTL_NLMDEBUG,
+};
+
+
+/*
+ * knfsd debug flags
+ */
+#define NFSDDBG_SOCK 0x0001
+#define NFSDDBG_FH 0x0002
+#define NFSDDBG_EXPORT 0x0004
+#define NFSDDBG_SVC 0x0008
+#define NFSDDBG_PROC 0x0010
+#define NFSDDBG_FILEOP 0x0020
+#define NFSDDBG_AUTH 0x0040
+#define NFSDDBG_REPCACHE 0x0080
+#define NFSDDBG_XDR 0x0100
+#define NFSDDBG_LOCKD 0x0200
+#define NFSDDBG_ALL 0x7FFF
+#define NFSDDBG_NOCHANGE 0xFFFF
+
+/*
+ * Debug flags
+ */
+#define NLMDBG_SVC 0x0001
+#define NLMDBG_CLIENT 0x0002
+#define NLMDBG_CLNTLOCK 0x0004
+#define NLMDBG_SVCLOCK 0x0008
+#define NLMDBG_MONITOR 0x0010
+#define NLMDBG_CLNTSUBS 0x0020
+#define NLMDBG_SVCSUBS 0x0040
+#define NLMDBG_HOSTCACHE 0x0080
+#define NLMDBG_ALL 0x7fff
+
+
+#define NFSDBG_VFS 0x0001
+#define NFSDBG_DIRCACHE 0x0002
+#define NFSDBG_LOOKUPCACHE 0x0004
+#define NFSDBG_PAGECACHE 0x0008
+#define NFSDBG_PROC 0x0010
+#define NFSDBG_XDR 0x0020
+#define NFSDBG_FILE 0x0040
+#define NFSDBG_ROOT 0x0080
+#define NFSDBG_ALL 0xFFFF
+
+#endif /* _NFS_DEBUG_H */
diff --git a/support/include/nfs/export.h b/support/include/nfs/export.h
new file mode 100644
index 0000000..80d23fd
--- /dev/null
+++ b/support/include/nfs/export.h
@@ -0,0 +1,26 @@
+#ifndef _NSF_EXPORT_H
+#define _NSF_EXPORT_H
+
+/*
+ * Important limits for the exports stuff.
+ */
+#define NFSCLNT_IDMAX 1024
+#define NFSCLNT_ADDRMAX 16
+#define NFSCLNT_KEYMAX 32
+
+/*
+ * Export flags.
+ */
+#define NFSEXP_READONLY 0x0001
+#define NFSEXP_INSECURE_PORT 0x0002
+#define NFSEXP_ROOTSQUASH 0x0004
+#define NFSEXP_ALLSQUASH 0x0008
+#define NFSEXP_ASYNC 0x0010
+#define NFSEXP_GATHERED_WRITES 0x0020
+#define NFSEXP_UIDMAP 0x0040
+#define NFSEXP_KERBEROS 0x0080 /* not available */
+#define NFSEXP_SUNSECURE 0x0100
+#define NFSEXP_CROSSMNT 0x0200 /* not available */
+#define NFSEXP_ALLFLAGS 0x03FF
+
+#endif /* _NSF_EXPORT_H */
diff --git a/support/include/nfs/nfs.h b/support/include/nfs/nfs.h
new file mode 100644
index 0000000..0cfed07
--- /dev/null
+++ b/support/include/nfs/nfs.h
@@ -0,0 +1,145 @@
+#ifndef _NFS_NFS_H
+#define _NFS_NFS_H
+
+#include <linux/posix_types.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <rpcsvc/nfs_prot.h>
+#include <nfs/export.h>
+
+struct dentry;
+
+/*
+ * This is the new "dentry style" Linux NFSv2 file handle.
+ *
+ * The xino and xdev fields are currently used to transport the
+ * ino/dev of the exported inode.
+ */
+struct nfs_fhbase {
+ struct dentry * fb_dentry; /* dentry cookie */
+ u_int32_t fb_ino; /* our inode number */
+ u_int32_t fb_dirino; /* dir inode number */
+ u_int32_t fb_dev; /* our device */
+ u_int32_t fb_xdev;
+ u_int32_t fb_xino;
+};
+
+#define NFS_FH_PADDING (NFS_FHSIZE - sizeof(struct nfs_fhbase))
+struct knfs_fh {
+ struct nfs_fhbase fh_base;
+ u_int8_t fh_cookie[NFS_FH_PADDING];
+};
+
+#define fh_dcookie fh_base.fb_dentry
+#define fh_ino fh_base.fb_ino
+#define fh_dirino fh_base.fb_dirino
+#define fh_dev fh_base.fb_dev
+#define fh_xdev fh_base.fb_xdev
+#define fh_xino fh_base.fb_xino
+
+/*
+ * Version of the syscall interface
+ */
+#define NFSCTL_VERSION 0x0201
+
+/*
+ * These are the commands understood by nfsctl().
+ */
+#define NFSCTL_SVC 0 /* This is a server process. */
+#define NFSCTL_ADDCLIENT 1 /* Add an NFS client. */
+#define NFSCTL_DELCLIENT 2 /* Remove an NFS client. */
+#define NFSCTL_EXPORT 3 /* export a file system. */
+#define NFSCTL_UNEXPORT 4 /* unexport a file system. */
+#define NFSCTL_UGIDUPDATE 5 /* update a client's uid/gid map. */
+#define NFSCTL_GETFH 6 /* get an fh (used by mountd) */
+#define NFSCTL_GETFD 7 /* get an fh by path (used by mountd) */
+
+/* Above this is for lockd. */
+#define NFSCTL_LOCKD 0x10000
+#define LOCKDCTL_SVC NFSCTL_LOCKD
+
+
+
+/* SVC */
+struct nfsctl_svc {
+ unsigned short svc_port;
+ int svc_nthreads;
+};
+
+/* ADDCLIENT/DELCLIENT */
+struct nfsctl_client {
+ char cl_ident[NFSCLNT_IDMAX+1];
+ int cl_naddr;
+ struct in_addr cl_addrlist[NFSCLNT_ADDRMAX];
+ int cl_fhkeytype;
+ int cl_fhkeylen;
+ unsigned char cl_fhkey[NFSCLNT_KEYMAX];
+};
+
+/* EXPORT/UNEXPORT */
+struct nfsctl_export {
+ char ex_client[NFSCLNT_IDMAX+1];
+ char ex_path[NFS_MAXPATHLEN+1];
+ __kernel_dev_t ex_dev;
+ __kernel_ino_t ex_ino;
+ int ex_flags;
+ __kernel_uid_t ex_anon_uid;
+ __kernel_gid_t ex_anon_gid;
+};
+
+/* UGIDUPDATE */
+struct nfsctl_uidmap {
+ char * ug_ident;
+ __kernel_uid_t ug_uidbase;
+ int ug_uidlen;
+ __kernel_uid_t * ug_udimap;
+ __kernel_gid_t ug_gidbase;
+ int ug_gidlen;
+ __kernel_gid_t * ug_gdimap;
+};
+
+/* GETFH */
+struct nfsctl_fhparm {
+ struct sockaddr gf_addr;
+ __kernel_dev_t gf_dev;
+ __kernel_ino_t gf_ino;
+ int gf_version;
+};
+
+/* GETFD */
+struct nfsctl_fdparm {
+ struct sockaddr gd_addr;
+ char gd_path[NFS_MAXPATHLEN+1];
+ int gd_version;
+};
+
+/*
+ * This is the argument union.
+ */
+struct nfsctl_arg {
+ int ca_version; /* safeguard */
+ union {
+ struct nfsctl_svc u_svc;
+ struct nfsctl_client u_client;
+ struct nfsctl_export u_export;
+ struct nfsctl_uidmap u_umap;
+ struct nfsctl_fhparm u_getfh;
+ struct nfsctl_fdparm u_getfd;
+ unsigned int u_debug;
+ } u;
+#define ca_svc u.u_svc
+#define ca_client u.u_client
+#define ca_export u.u_export
+#define ca_umap u.u_umap
+#define ca_getfh u.u_getfh
+#define ca_getfd u.u_getfd
+#define ca_authd u.u_authd
+#define ca_debug u.u_debug
+};
+
+union nfsctl_res {
+ struct knfs_fh cr_getfh;
+ unsigned int cr_debug;
+};
+
+#endif /* _NFS_NFS_H */
diff --git a/support/include/nfslib.h b/support/include/nfslib.h
new file mode 100644
index 0000000..d8be926
--- /dev/null
+++ b/support/include/nfslib.h
@@ -0,0 +1,125 @@
+/*
+ * support/include/nfslib.h
+ *
+ * General support functions for NFS user-space programs.
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef NFSLIB_H
+#define NFSLIB_H
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <paths.h>
+#include <rpcsvc/nfs_prot.h>
+#include <nfs/nfs.h>
+#include "xlog.h"
+
+#ifndef _PATH_EXPORTS
+#define _PATH_EXPORTS "/etc/exports"
+#endif
+#ifndef _PATH_XTAB
+#define _PATH_XTAB NFS_STATEDIR "/xtab"
+#endif
+#ifndef _PATH_XTABTMP
+#define _PATH_XTABTMP NFS_STATEDIR "/xtab.tmp"
+#endif
+#ifndef _PATH_ETAB
+#define _PATH_ETAB NFS_STATEDIR "/etab"
+#endif
+#ifndef _PATH_ETABTMP
+#define _PATH_ETABTMP NFS_STATEDIR "/etab.tmp"
+#endif
+#ifndef _PATH_RMTAB
+#define _PATH_RMTAB NFS_STATEDIR "/rmtab"
+#endif
+#ifndef _PATH_RMTABTMP
+#define _PATH_RMTABTMP _PATH_RMTAB ".tmp"
+#endif
+#ifndef _PATH_PROC_EXPORTS
+#define _PATH_PROC_EXPORTS "/proc/fs/nfs/exports"
+#endif
+
+enum cle_maptypes {
+ CLE_MAP_IDENT = 0,
+ CLE_MAP_FILE,
+ CLE_MAP_UGIDD,
+};
+
+/*
+ * Data related to a single exports entry as returned by getexportent.
+ * FIXME: export options should probably be parsed at a later time to
+ * allow overrides when using exportfs.
+ */
+struct exportent {
+ char e_hostname[NFSCLNT_IDMAX+1];
+ char e_path[NFS_MAXPATHLEN+1];
+ /* The mount path may be different from the exported path due
+ to submount. It may change for every mount. The idea is we
+ set m_path every time when we process a mount. We should not
+ use it for anything else. */
+ char m_path[NFS_MAXPATHLEN+1];
+ int e_flags;
+ int e_maptype;
+ int e_anonuid;
+ int e_anongid;
+ int * e_squids;
+ int e_nsquids;
+ int * e_sqgids;
+ int e_nsqgids;
+};
+
+struct rmtabent {
+ char r_client[NFSCLNT_IDMAX+1];
+ char r_path[NFS_MAXPATHLEN+1];
+};
+
+/*
+ * configuration file parsing
+ */
+void setexportent(char *fname, char *type);
+struct exportent * getexportent(void);
+void putexportent(struct exportent *xep);
+void endexportent(void);
+struct exportent * mkexportent(char *hname, char *path, char *opts);
+void dupexportent(struct exportent *dst,
+ struct exportent *src);
+int updateexportent(struct exportent *eep, char *options);
+
+int setrmtabent(char *type);
+struct rmtabent * getrmtabent(int log);
+void putrmtabent(struct rmtabent *xep);
+void endrmtabent(void);
+void rewindrmtabent(void);
+FILE * fsetrmtabent(char *fname, char *type);
+struct rmtabent * fgetrmtabent(FILE *fp, int log);
+void fputrmtabent(FILE *fp, struct rmtabent *xep);
+void fendrmtabent(FILE *fp);
+void frewindrmtabent(FILE *fp);
+
+/*
+ * wildmat borrowed from INN
+ */
+int wildmat(char *text, char *pattern);
+
+/*
+ * nfsd library functions.
+ */
+int nfsctl(int, struct nfsctl_arg *, union nfsctl_res *);
+int nfssvc(int port, int nrservs);
+int nfsaddclient(struct nfsctl_client *clp);
+int nfsdelclient(struct nfsctl_client *clp);
+int nfsexport(struct nfsctl_export *exp);
+int nfsunexport(struct nfsctl_export *exp);
+struct knfs_fh * getfh_old(struct sockaddr *addr, dev_t dev, ino_t ino);
+struct knfs_fh * getfh(struct sockaddr *addr, const char *);
+
+/* lockd. */
+int lockdsvc();
+
+#endif /* NFSLIB_H */
diff --git a/support/include/rpcdispatch.h b/support/include/rpcdispatch.h
new file mode 100644
index 0000000..866d4bf
--- /dev/null
+++ b/support/include/rpcdispatch.h
@@ -0,0 +1,57 @@
+/*
+ * nlm_dispatch This is a generic RPC call dispatcher.
+ * It is loosely based on the dispatch mechanism I
+ * first encountered in the UNFSD source.
+ *
+ * Cyopright (C) 1995, Olaf Kirch <okir@monad.swb.de>
+ *
+ * 24.05.95 okir
+ *
+ */
+
+#ifndef RPCDISPATCH_H
+#define RPCDISPATCH_H
+
+#include <rpc/rpc.h>
+
+#ifdef __STDC__
+# define CONCAT(a,b) a##b
+# define CONCAT3(a,b,c) a##b##c
+# define STRING(a) #a
+#else
+# define CONCAT(a,b) a/**/b
+# define CONCAT3(a,b,c) a/**/b/**/c
+# define STRING(a) "a"
+#endif
+
+#ifdef __STDC__
+typedef bool_t (*rpcsvc_fn_t)(struct svc_req *, void *argp, void *resp);
+#else
+typedef bool_t (*rpcsvc_fn_t)();
+#endif
+
+#define table_ent(func, vers, arg_type, res_type) \
+ { STRING(func), \
+ (rpcsvc_fn_t)CONCAT(func,_svc), vers,\
+ (xdrproc_t)CONCAT(xdr_, arg_type), sizeof(arg_type), \
+ (xdrproc_t)CONCAT(xdr_, res_type), sizeof(res_type), \
+ }
+#define nlm_undef_svc NULL
+#define xdr_nlm_void xdr_void
+
+struct dispatch_entry {
+ const char *name;
+ rpcsvc_fn_t func;
+ unsigned int versions; /* bitmap of versions */
+ xdrproc_t xdr_arg_fn; /* argument XDR */
+ size_t xdr_arg_size;
+ xdrproc_t xdr_res_fn; /* result XDR */
+ size_t xdr_res_size;
+};
+
+void rpc_dispatch(struct svc_req *rq, SVCXPRT *tp,
+ struct dispatch_entry *dtable, int nproc,
+ void *argp, void *resp);
+void rpc_svcrun(void);
+
+#endif /* RPCDISPATCH_H */
diff --git a/support/include/rpcmisc.h b/support/include/rpcmisc.h
new file mode 100644
index 0000000..06970cd
--- /dev/null
+++ b/support/include/rpcmisc.h
@@ -0,0 +1,58 @@
+/*
+ * rpcmisc Support for RPC startup, dispatching and logging.
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef RPCMISC_H
+#define RPCMISC_H
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+
+#ifdef __STDC__
+# define CONCAT(a,b) a##b
+# define STRING(a) #a
+#else
+# define CONCAT(a,b) a/**/b
+# define STRING(a) "a"
+#endif
+
+typedef bool_t (*rpcsvc_fn_t)(struct svc_req *, void *argp, void *resp);
+
+struct rpc_dentry {
+ const char *name;
+ rpcsvc_fn_t func;
+ xdrproc_t xdr_arg_fn; /* argument XDR */
+ size_t xdr_arg_size;
+ xdrproc_t xdr_res_fn; /* result XDR */
+ size_t xdr_res_size;
+};
+
+struct rpc_dtable {
+ struct rpc_dentry *entries;
+ int nproc;
+};
+
+#define dtable_ent(func, vers, arg_type, res_type) \
+ { STRING(func), \
+ (rpcsvc_fn_t)func##_##vers##_svc, \
+ (xdrproc_t)xdr_##arg_type, sizeof(arg_type), \
+ (xdrproc_t)xdr_##res_type, sizeof(res_type), \
+ }
+
+void rpc_init(char *name, int prog, int vers,
+ void (*dispatch)(struct svc_req *, SVCXPRT *),
+ int defport, int bufsize);
+void rpc_svcrun(void);
+void rpc_dispatch(struct svc_req *rq, SVCXPRT *xprt,
+ struct rpc_dtable *dtable, int nvers,
+ void *argp, void *resp);
+void rpc_logcall(struct svc_req *, char *xname, char *args);
+
+extern int _rpcpmstart;
+extern int _rpcfdtype;
+extern int _rpcsvcdirty;
+
+
+#endif /* RPCMISC_H */
diff --git a/support/include/rpcsec.h b/support/include/rpcsec.h
new file mode 100644
index 0000000..84d4497
--- /dev/null
+++ b/support/include/rpcsec.h
@@ -0,0 +1,39 @@
+/*
+ * Declarations needed for the authdes library. Some of the functions
+ * mentioned herein have been omitted from the Linux libc header files
+ */
+
+#ifndef RPCSEC_H
+#define RPCSEC_H
+
+int netname2user(char *netname, int *uidp, int *gidp,
+ int *gidlenp, int *gidlist);
+int netname2host(char *netname, char *hostname, int hostlen);
+int getnetname(char *name);
+int user2netname(char *netname, int uid, char *domain);
+int host2netname(char *netname, char *hostname, char *domain);
+void passwd2des(char *pw, char *key);
+int getsecretkey(char *netname, char *secretkey, char *passwd);
+int getpublickey(char *hostname, char *publickey);
+int yp_update(char *domain, char *map, unsigned int ypop,
+ char *key, int keylen, char *data, int datalen);
+int key_setsecret(char *secret);
+int xencrypt(char *secret, char *passwd);
+int xdecrypt(char *secret, char *passwd);
+
+
+#define PUBLICKEY_MAP "publickey.byname"
+#define NETID_MAP "netid.byname"
+
+#ifndef DEBUG
+#define RPCSEC_BASE "/etc/"
+#else
+#define RPCSEC_BASE "/tmp/"
+#endif
+
+#define PUBLICKEY_FILE RPCSEC_BASE "publickey"
+#define PUBLICKEY_LOCK RPCSEC_BASE "publickey.lock"
+#define ROOTKEY_FILE RPCSEC_BASE ".rootkey"
+#define KEYSTORE_FILE RPCSEC_BASE "keystore"
+
+#endif /* RPCSEC_H */
diff --git a/support/include/rpcsvc/nfs_prot.h b/support/include/rpcsvc/nfs_prot.h
new file mode 100644
index 0000000..9311341
--- /dev/null
+++ b/support/include/rpcsvc/nfs_prot.h
@@ -0,0 +1,661 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#ifndef _NFS_PROT_H_RPCGEN
+#define _NFS_PROT_H_RPCGEN
+
+#include <rpc/rpc.h>
+
+#define NFS_PORT 2049
+#define NFS_MAXDATA 8192
+#define NFS_MAXPATHLEN 1024
+#define NFS_MAXNAMLEN 255
+#define NFS_FHSIZE 32
+#define NFS_COOKIESIZE 4
+#define NFS_FIFO_DEV -1
+#define NFSMODE_FMT 0170000
+#define NFSMODE_DIR 0040000
+#define NFSMODE_CHR 0020000
+#define NFSMODE_BLK 0060000
+#define NFSMODE_REG 0100000
+#define NFSMODE_LNK 0120000
+#define NFSMODE_SOCK 0140000
+#define NFSMODE_FIFO 0010000
+
+enum nfsstat {
+ NFS_OK = 0,
+ NFSERR_PERM = 1,
+ NFSERR_NOENT = 2,
+ NFSERR_IO = 5,
+ NFSERR_NXIO = 6,
+ NFSERR_ACCES = 13,
+ NFSERR_EXIST = 17,
+ NFSERR_NODEV = 19,
+ NFSERR_NOTDIR = 20,
+ NFSERR_ISDIR = 21,
+ NFSERR_FBIG = 27,
+ NFSERR_NOSPC = 28,
+ NFSERR_ROFS = 30,
+ NFSERR_NAMETOOLONG = 63,
+ NFSERR_NOTEMPTY = 66,
+ NFSERR_DQUOT = 69,
+ NFSERR_STALE = 70,
+ NFSERR_WFLUSH = 99,
+};
+typedef enum nfsstat nfsstat;
+#ifdef __cplusplus
+extern "C" bool_t xdr_nfsstat(XDR *, nfsstat*);
+#elif __STDC__
+extern bool_t xdr_nfsstat(XDR *, nfsstat*);
+#else /* Old Style C */
+bool_t xdr_nfsstat();
+#endif /* Old Style C */
+
+
+enum ftype {
+ NFNON = 0,
+ NFREG = 1,
+ NFDIR = 2,
+ NFBLK = 3,
+ NFCHR = 4,
+ NFLNK = 5,
+ NFSOCK = 6,
+ NFBAD = 7,
+ NFFIFO = 8,
+};
+typedef enum ftype ftype;
+#ifdef __cplusplus
+extern "C" bool_t xdr_ftype(XDR *, ftype*);
+#elif __STDC__
+extern bool_t xdr_ftype(XDR *, ftype*);
+#else /* Old Style C */
+bool_t xdr_ftype();
+#endif /* Old Style C */
+
+
+struct nfs_fh {
+ char data[NFS_FHSIZE];
+};
+typedef struct nfs_fh nfs_fh;
+#ifdef __cplusplus
+extern "C" bool_t xdr_nfs_fh(XDR *, nfs_fh*);
+#elif __STDC__
+extern bool_t xdr_nfs_fh(XDR *, nfs_fh*);
+#else /* Old Style C */
+bool_t xdr_nfs_fh();
+#endif /* Old Style C */
+
+
+struct nfstime {
+ u_int seconds;
+ u_int useconds;
+};
+typedef struct nfstime nfstime;
+#ifdef __cplusplus
+extern "C" bool_t xdr_nfstime(XDR *, nfstime*);
+#elif __STDC__
+extern bool_t xdr_nfstime(XDR *, nfstime*);
+#else /* Old Style C */
+bool_t xdr_nfstime();
+#endif /* Old Style C */
+
+
+struct fattr {
+ ftype type;
+ u_int mode;
+ u_int nlink;
+ u_int uid;
+ u_int gid;
+ u_int size;
+ u_int blocksize;
+ u_int rdev;
+ u_int blocks;
+ u_int fsid;
+ u_int fileid;
+ nfstime atime;
+ nfstime mtime;
+ nfstime ctime;
+};
+typedef struct fattr fattr;
+#ifdef __cplusplus
+extern "C" bool_t xdr_fattr(XDR *, fattr*);
+#elif __STDC__
+extern bool_t xdr_fattr(XDR *, fattr*);
+#else /* Old Style C */
+bool_t xdr_fattr();
+#endif /* Old Style C */
+
+
+struct sattr {
+ u_int mode;
+ u_int uid;
+ u_int gid;
+ u_int size;
+ nfstime atime;
+ nfstime mtime;
+};
+typedef struct sattr sattr;
+#ifdef __cplusplus
+extern "C" bool_t xdr_sattr(XDR *, sattr*);
+#elif __STDC__
+extern bool_t xdr_sattr(XDR *, sattr*);
+#else /* Old Style C */
+bool_t xdr_sattr();
+#endif /* Old Style C */
+
+
+typedef char *filename;
+#ifdef __cplusplus
+extern "C" bool_t xdr_filename(XDR *, filename*);
+#elif __STDC__
+extern bool_t xdr_filename(XDR *, filename*);
+#else /* Old Style C */
+bool_t xdr_filename();
+#endif /* Old Style C */
+
+
+typedef char *nfspath;
+#ifdef __cplusplus
+extern "C" bool_t xdr_nfspath(XDR *, nfspath*);
+#elif __STDC__
+extern bool_t xdr_nfspath(XDR *, nfspath*);
+#else /* Old Style C */
+bool_t xdr_nfspath();
+#endif /* Old Style C */
+
+
+struct attrstat {
+ nfsstat status;
+ union {
+ fattr attributes;
+ } attrstat_u;
+};
+typedef struct attrstat attrstat;
+#ifdef __cplusplus
+extern "C" bool_t xdr_attrstat(XDR *, attrstat*);
+#elif __STDC__
+extern bool_t xdr_attrstat(XDR *, attrstat*);
+#else /* Old Style C */
+bool_t xdr_attrstat();
+#endif /* Old Style C */
+
+
+struct sattrargs {
+ nfs_fh file;
+ sattr attributes;
+};
+typedef struct sattrargs sattrargs;
+#ifdef __cplusplus
+extern "C" bool_t xdr_sattrargs(XDR *, sattrargs*);
+#elif __STDC__
+extern bool_t xdr_sattrargs(XDR *, sattrargs*);
+#else /* Old Style C */
+bool_t xdr_sattrargs();
+#endif /* Old Style C */
+
+
+struct diropargs {
+ nfs_fh dir;
+ filename name;
+};
+typedef struct diropargs diropargs;
+#ifdef __cplusplus
+extern "C" bool_t xdr_diropargs(XDR *, diropargs*);
+#elif __STDC__
+extern bool_t xdr_diropargs(XDR *, diropargs*);
+#else /* Old Style C */
+bool_t xdr_diropargs();
+#endif /* Old Style C */
+
+
+struct diropokres {
+ nfs_fh file;
+ fattr attributes;
+};
+typedef struct diropokres diropokres;
+#ifdef __cplusplus
+extern "C" bool_t xdr_diropokres(XDR *, diropokres*);
+#elif __STDC__
+extern bool_t xdr_diropokres(XDR *, diropokres*);
+#else /* Old Style C */
+bool_t xdr_diropokres();
+#endif /* Old Style C */
+
+
+struct diropres {
+ nfsstat status;
+ union {
+ diropokres diropres;
+ } diropres_u;
+};
+typedef struct diropres diropres;
+#ifdef __cplusplus
+extern "C" bool_t xdr_diropres(XDR *, diropres*);
+#elif __STDC__
+extern bool_t xdr_diropres(XDR *, diropres*);
+#else /* Old Style C */
+bool_t xdr_diropres();
+#endif /* Old Style C */
+
+
+struct readlinkres {
+ nfsstat status;
+ union {
+ nfspath data;
+ } readlinkres_u;
+};
+typedef struct readlinkres readlinkres;
+#ifdef __cplusplus
+extern "C" bool_t xdr_readlinkres(XDR *, readlinkres*);
+#elif __STDC__
+extern bool_t xdr_readlinkres(XDR *, readlinkres*);
+#else /* Old Style C */
+bool_t xdr_readlinkres();
+#endif /* Old Style C */
+
+
+struct readargs {
+ nfs_fh file;
+ u_int offset;
+ u_int count;
+ u_int totalcount;
+};
+typedef struct readargs readargs;
+#ifdef __cplusplus
+extern "C" bool_t xdr_readargs(XDR *, readargs*);
+#elif __STDC__
+extern bool_t xdr_readargs(XDR *, readargs*);
+#else /* Old Style C */
+bool_t xdr_readargs();
+#endif /* Old Style C */
+
+
+struct readokres {
+ fattr attributes;
+ struct {
+ u_int data_len;
+ char *data_val;
+ } data;
+};
+typedef struct readokres readokres;
+#ifdef __cplusplus
+extern "C" bool_t xdr_readokres(XDR *, readokres*);
+#elif __STDC__
+extern bool_t xdr_readokres(XDR *, readokres*);
+#else /* Old Style C */
+bool_t xdr_readokres();
+#endif /* Old Style C */
+
+
+struct readres {
+ nfsstat status;
+ union {
+ readokres reply;
+ } readres_u;
+};
+typedef struct readres readres;
+#ifdef __cplusplus
+extern "C" bool_t xdr_readres(XDR *, readres*);
+#elif __STDC__
+extern bool_t xdr_readres(XDR *, readres*);
+#else /* Old Style C */
+bool_t xdr_readres();
+#endif /* Old Style C */
+
+
+struct writeargs {
+ nfs_fh file;
+ u_int beginoffset;
+ u_int offset;
+ u_int totalcount;
+ struct {
+ u_int data_len;
+ char *data_val;
+ } data;
+};
+typedef struct writeargs writeargs;
+#ifdef __cplusplus
+extern "C" bool_t xdr_writeargs(XDR *, writeargs*);
+#elif __STDC__
+extern bool_t xdr_writeargs(XDR *, writeargs*);
+#else /* Old Style C */
+bool_t xdr_writeargs();
+#endif /* Old Style C */
+
+
+struct createargs {
+ diropargs where;
+ sattr attributes;
+};
+typedef struct createargs createargs;
+#ifdef __cplusplus
+extern "C" bool_t xdr_createargs(XDR *, createargs*);
+#elif __STDC__
+extern bool_t xdr_createargs(XDR *, createargs*);
+#else /* Old Style C */
+bool_t xdr_createargs();
+#endif /* Old Style C */
+
+
+struct renameargs {
+ diropargs from;
+ diropargs to;
+};
+typedef struct renameargs renameargs;
+#ifdef __cplusplus
+extern "C" bool_t xdr_renameargs(XDR *, renameargs*);
+#elif __STDC__
+extern bool_t xdr_renameargs(XDR *, renameargs*);
+#else /* Old Style C */
+bool_t xdr_renameargs();
+#endif /* Old Style C */
+
+
+struct linkargs {
+ nfs_fh from;
+ diropargs to;
+};
+typedef struct linkargs linkargs;
+#ifdef __cplusplus
+extern "C" bool_t xdr_linkargs(XDR *, linkargs*);
+#elif __STDC__
+extern bool_t xdr_linkargs(XDR *, linkargs*);
+#else /* Old Style C */
+bool_t xdr_linkargs();
+#endif /* Old Style C */
+
+
+struct symlinkargs {
+ diropargs from;
+ nfspath to;
+ sattr attributes;
+};
+typedef struct symlinkargs symlinkargs;
+#ifdef __cplusplus
+extern "C" bool_t xdr_symlinkargs(XDR *, symlinkargs*);
+#elif __STDC__
+extern bool_t xdr_symlinkargs(XDR *, symlinkargs*);
+#else /* Old Style C */
+bool_t xdr_symlinkargs();
+#endif /* Old Style C */
+
+
+typedef char nfscookie[NFS_COOKIESIZE];
+#ifdef __cplusplus
+extern "C" bool_t xdr_nfscookie(XDR *, nfscookie);
+#elif __STDC__
+extern bool_t xdr_nfscookie(XDR *, nfscookie);
+#else /* Old Style C */
+bool_t xdr_nfscookie();
+#endif /* Old Style C */
+
+
+struct readdirargs {
+ nfs_fh dir;
+ nfscookie cookie;
+ u_int count;
+};
+typedef struct readdirargs readdirargs;
+#ifdef __cplusplus
+extern "C" bool_t xdr_readdirargs(XDR *, readdirargs*);
+#elif __STDC__
+extern bool_t xdr_readdirargs(XDR *, readdirargs*);
+#else /* Old Style C */
+bool_t xdr_readdirargs();
+#endif /* Old Style C */
+
+
+struct entry {
+ u_int fileid;
+ filename name;
+ nfscookie cookie;
+ struct entry *nextentry;
+};
+typedef struct entry entry;
+#ifdef __cplusplus
+extern "C" bool_t xdr_entry(XDR *, entry*);
+#elif __STDC__
+extern bool_t xdr_entry(XDR *, entry*);
+#else /* Old Style C */
+bool_t xdr_entry();
+#endif /* Old Style C */
+
+
+struct dirlist {
+ entry *entries;
+ bool_t eof;
+};
+typedef struct dirlist dirlist;
+#ifdef __cplusplus
+extern "C" bool_t xdr_dirlist(XDR *, dirlist*);
+#elif __STDC__
+extern bool_t xdr_dirlist(XDR *, dirlist*);
+#else /* Old Style C */
+bool_t xdr_dirlist();
+#endif /* Old Style C */
+
+
+struct readdirres {
+ nfsstat status;
+ union {
+ dirlist reply;
+ } readdirres_u;
+};
+typedef struct readdirres readdirres;
+#ifdef __cplusplus
+extern "C" bool_t xdr_readdirres(XDR *, readdirres*);
+#elif __STDC__
+extern bool_t xdr_readdirres(XDR *, readdirres*);
+#else /* Old Style C */
+bool_t xdr_readdirres();
+#endif /* Old Style C */
+
+
+struct statfsokres {
+ u_int tsize;
+ u_int bsize;
+ u_int blocks;
+ u_int bfree;
+ u_int bavail;
+};
+typedef struct statfsokres statfsokres;
+#ifdef __cplusplus
+extern "C" bool_t xdr_statfsokres(XDR *, statfsokres*);
+#elif __STDC__
+extern bool_t xdr_statfsokres(XDR *, statfsokres*);
+#else /* Old Style C */
+bool_t xdr_statfsokres();
+#endif /* Old Style C */
+
+
+struct statfsres {
+ nfsstat status;
+ union {
+ statfsokres reply;
+ } statfsres_u;
+};
+typedef struct statfsres statfsres;
+#ifdef __cplusplus
+extern "C" bool_t xdr_statfsres(XDR *, statfsres*);
+#elif __STDC__
+extern bool_t xdr_statfsres(XDR *, statfsres*);
+#else /* Old Style C */
+bool_t xdr_statfsres();
+#endif /* Old Style C */
+
+
+#define NFS_PROGRAM ((u_long)100003)
+#define NFS_VERSION ((u_long)2)
+
+#ifdef __cplusplus
+#define NFSPROC_NULL ((u_long)0)
+extern "C" void * nfsproc_null_2(void *, CLIENT *);
+extern "C" void * nfsproc_null_2_svc(void *, struct svc_req *);
+#define NFSPROC_GETATTR ((u_long)1)
+extern "C" attrstat * nfsproc_getattr_2(nfs_fh *, CLIENT *);
+extern "C" attrstat * nfsproc_getattr_2_svc(nfs_fh *, struct svc_req *);
+#define NFSPROC_SETATTR ((u_long)2)
+extern "C" attrstat * nfsproc_setattr_2(sattrargs *, CLIENT *);
+extern "C" attrstat * nfsproc_setattr_2_svc(sattrargs *, struct svc_req *);
+#define NFSPROC_ROOT ((u_long)3)
+extern "C" void * nfsproc_root_2(void *, CLIENT *);
+extern "C" void * nfsproc_root_2_svc(void *, struct svc_req *);
+#define NFSPROC_LOOKUP ((u_long)4)
+extern "C" diropres * nfsproc_lookup_2(diropargs *, CLIENT *);
+extern "C" diropres * nfsproc_lookup_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_READLINK ((u_long)5)
+extern "C" readlinkres * nfsproc_readlink_2(nfs_fh *, CLIENT *);
+extern "C" readlinkres * nfsproc_readlink_2_svc(nfs_fh *, struct svc_req *);
+#define NFSPROC_READ ((u_long)6)
+extern "C" readres * nfsproc_read_2(readargs *, CLIENT *);
+extern "C" readres * nfsproc_read_2_svc(readargs *, struct svc_req *);
+#define NFSPROC_WRITECACHE ((u_long)7)
+extern "C" void * nfsproc_writecache_2(void *, CLIENT *);
+extern "C" void * nfsproc_writecache_2_svc(void *, struct svc_req *);
+#define NFSPROC_WRITE ((u_long)8)
+extern "C" attrstat * nfsproc_write_2(writeargs *, CLIENT *);
+extern "C" attrstat * nfsproc_write_2_svc(writeargs *, struct svc_req *);
+#define NFSPROC_CREATE ((u_long)9)
+extern "C" diropres * nfsproc_create_2(createargs *, CLIENT *);
+extern "C" diropres * nfsproc_create_2_svc(createargs *, struct svc_req *);
+#define NFSPROC_REMOVE ((u_long)10)
+extern "C" nfsstat * nfsproc_remove_2(diropargs *, CLIENT *);
+extern "C" nfsstat * nfsproc_remove_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_RENAME ((u_long)11)
+extern "C" nfsstat * nfsproc_rename_2(renameargs *, CLIENT *);
+extern "C" nfsstat * nfsproc_rename_2_svc(renameargs *, struct svc_req *);
+#define NFSPROC_LINK ((u_long)12)
+extern "C" nfsstat * nfsproc_link_2(linkargs *, CLIENT *);
+extern "C" nfsstat * nfsproc_link_2_svc(linkargs *, struct svc_req *);
+#define NFSPROC_SYMLINK ((u_long)13)
+extern "C" nfsstat * nfsproc_symlink_2(symlinkargs *, CLIENT *);
+extern "C" nfsstat * nfsproc_symlink_2_svc(symlinkargs *, struct svc_req *);
+#define NFSPROC_MKDIR ((u_long)14)
+extern "C" diropres * nfsproc_mkdir_2(createargs *, CLIENT *);
+extern "C" diropres * nfsproc_mkdir_2_svc(createargs *, struct svc_req *);
+#define NFSPROC_RMDIR ((u_long)15)
+extern "C" nfsstat * nfsproc_rmdir_2(diropargs *, CLIENT *);
+extern "C" nfsstat * nfsproc_rmdir_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_READDIR ((u_long)16)
+extern "C" readdirres * nfsproc_readdir_2(readdirargs *, CLIENT *);
+extern "C" readdirres * nfsproc_readdir_2_svc(readdirargs *, struct svc_req *);
+#define NFSPROC_STATFS ((u_long)17)
+extern "C" statfsres * nfsproc_statfs_2(nfs_fh *, CLIENT *);
+extern "C" statfsres * nfsproc_statfs_2_svc(nfs_fh *, struct svc_req *);
+
+#elif __STDC__
+#define NFSPROC_NULL ((u_long)0)
+extern void * nfsproc_null_2(void *, CLIENT *);
+extern void * nfsproc_null_2_svc(void *, struct svc_req *);
+#define NFSPROC_GETATTR ((u_long)1)
+extern attrstat * nfsproc_getattr_2(nfs_fh *, CLIENT *);
+extern attrstat * nfsproc_getattr_2_svc(nfs_fh *, struct svc_req *);
+#define NFSPROC_SETATTR ((u_long)2)
+extern attrstat * nfsproc_setattr_2(sattrargs *, CLIENT *);
+extern attrstat * nfsproc_setattr_2_svc(sattrargs *, struct svc_req *);
+#define NFSPROC_ROOT ((u_long)3)
+extern void * nfsproc_root_2(void *, CLIENT *);
+extern void * nfsproc_root_2_svc(void *, struct svc_req *);
+#define NFSPROC_LOOKUP ((u_long)4)
+extern diropres * nfsproc_lookup_2(diropargs *, CLIENT *);
+extern diropres * nfsproc_lookup_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_READLINK ((u_long)5)
+extern readlinkres * nfsproc_readlink_2(nfs_fh *, CLIENT *);
+extern readlinkres * nfsproc_readlink_2_svc(nfs_fh *, struct svc_req *);
+#define NFSPROC_READ ((u_long)6)
+extern readres * nfsproc_read_2(readargs *, CLIENT *);
+extern readres * nfsproc_read_2_svc(readargs *, struct svc_req *);
+#define NFSPROC_WRITECACHE ((u_long)7)
+extern void * nfsproc_writecache_2(void *, CLIENT *);
+extern void * nfsproc_writecache_2_svc(void *, struct svc_req *);
+#define NFSPROC_WRITE ((u_long)8)
+extern attrstat * nfsproc_write_2(writeargs *, CLIENT *);
+extern attrstat * nfsproc_write_2_svc(writeargs *, struct svc_req *);
+#define NFSPROC_CREATE ((u_long)9)
+extern diropres * nfsproc_create_2(createargs *, CLIENT *);
+extern diropres * nfsproc_create_2_svc(createargs *, struct svc_req *);
+#define NFSPROC_REMOVE ((u_long)10)
+extern nfsstat * nfsproc_remove_2(diropargs *, CLIENT *);
+extern nfsstat * nfsproc_remove_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_RENAME ((u_long)11)
+extern nfsstat * nfsproc_rename_2(renameargs *, CLIENT *);
+extern nfsstat * nfsproc_rename_2_svc(renameargs *, struct svc_req *);
+#define NFSPROC_LINK ((u_long)12)
+extern nfsstat * nfsproc_link_2(linkargs *, CLIENT *);
+extern nfsstat * nfsproc_link_2_svc(linkargs *, struct svc_req *);
+#define NFSPROC_SYMLINK ((u_long)13)
+extern nfsstat * nfsproc_symlink_2(symlinkargs *, CLIENT *);
+extern nfsstat * nfsproc_symlink_2_svc(symlinkargs *, struct svc_req *);
+#define NFSPROC_MKDIR ((u_long)14)
+extern diropres * nfsproc_mkdir_2(createargs *, CLIENT *);
+extern diropres * nfsproc_mkdir_2_svc(createargs *, struct svc_req *);
+#define NFSPROC_RMDIR ((u_long)15)
+extern nfsstat * nfsproc_rmdir_2(diropargs *, CLIENT *);
+extern nfsstat * nfsproc_rmdir_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_READDIR ((u_long)16)
+extern readdirres * nfsproc_readdir_2(readdirargs *, CLIENT *);
+extern readdirres * nfsproc_readdir_2_svc(readdirargs *, struct svc_req *);
+#define NFSPROC_STATFS ((u_long)17)
+extern statfsres * nfsproc_statfs_2(nfs_fh *, CLIENT *);
+extern statfsres * nfsproc_statfs_2_svc(nfs_fh *, struct svc_req *);
+
+#else /* Old Style C */
+#define NFSPROC_NULL ((u_long)0)
+extern void * nfsproc_null_2();
+extern void * nfsproc_null_2_svc();
+#define NFSPROC_GETATTR ((u_long)1)
+extern attrstat * nfsproc_getattr_2();
+extern attrstat * nfsproc_getattr_2_svc();
+#define NFSPROC_SETATTR ((u_long)2)
+extern attrstat * nfsproc_setattr_2();
+extern attrstat * nfsproc_setattr_2_svc();
+#define NFSPROC_ROOT ((u_long)3)
+extern void * nfsproc_root_2();
+extern void * nfsproc_root_2_svc();
+#define NFSPROC_LOOKUP ((u_long)4)
+extern diropres * nfsproc_lookup_2();
+extern diropres * nfsproc_lookup_2_svc();
+#define NFSPROC_READLINK ((u_long)5)
+extern readlinkres * nfsproc_readlink_2();
+extern readlinkres * nfsproc_readlink_2_svc();
+#define NFSPROC_READ ((u_long)6)
+extern readres * nfsproc_read_2();
+extern readres * nfsproc_read_2_svc();
+#define NFSPROC_WRITECACHE ((u_long)7)
+extern void * nfsproc_writecache_2();
+extern void * nfsproc_writecache_2_svc();
+#define NFSPROC_WRITE ((u_long)8)
+extern attrstat * nfsproc_write_2();
+extern attrstat * nfsproc_write_2_svc();
+#define NFSPROC_CREATE ((u_long)9)
+extern diropres * nfsproc_create_2();
+extern diropres * nfsproc_create_2_svc();
+#define NFSPROC_REMOVE ((u_long)10)
+extern nfsstat * nfsproc_remove_2();
+extern nfsstat * nfsproc_remove_2_svc();
+#define NFSPROC_RENAME ((u_long)11)
+extern nfsstat * nfsproc_rename_2();
+extern nfsstat * nfsproc_rename_2_svc();
+#define NFSPROC_LINK ((u_long)12)
+extern nfsstat * nfsproc_link_2();
+extern nfsstat * nfsproc_link_2_svc();
+#define NFSPROC_SYMLINK ((u_long)13)
+extern nfsstat * nfsproc_symlink_2();
+extern nfsstat * nfsproc_symlink_2_svc();
+#define NFSPROC_MKDIR ((u_long)14)
+extern diropres * nfsproc_mkdir_2();
+extern diropres * nfsproc_mkdir_2_svc();
+#define NFSPROC_RMDIR ((u_long)15)
+extern nfsstat * nfsproc_rmdir_2();
+extern nfsstat * nfsproc_rmdir_2_svc();
+#define NFSPROC_READDIR ((u_long)16)
+extern readdirres * nfsproc_readdir_2();
+extern readdirres * nfsproc_readdir_2_svc();
+#define NFSPROC_STATFS ((u_long)17)
+extern statfsres * nfsproc_statfs_2();
+extern statfsres * nfsproc_statfs_2_svc();
+#endif /* Old Style C */
+
+#endif /* !_NFS_PROT_H_RPCGEN */
diff --git a/support/include/sys/fs/ext2fs.h b/support/include/sys/fs/ext2fs.h
new file mode 100644
index 0000000..93b3e2b
--- /dev/null
+++ b/support/include/sys/fs/ext2fs.h
@@ -0,0 +1,42 @@
+#ifndef _SYS_FS_EXT2FS_H
+#define _SYS_FS_EXT2FS_H
+
+/*
+ * ioctl commands
+ */
+#define EXT2_IOC_GETFLAGS _IOR('f', 1, long)
+#define EXT2_IOC_SETFLAGS _IOW('f', 2, long)
+#define EXT2_IOC_GETVERSION _IOR('v', 1, long)
+#define EXT2_IOC_SETVERSION _IOW('v', 2, long)
+
+/*
+ * File system states
+ */
+#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */
+#define EXT2_ERROR_FS 0x0002 /* Errors detected */
+
+/*
+ * Mount flags
+ */
+#define EXT2_MOUNT_CHECK_NORMAL 0x0001 /* Do some more checks */
+#define EXT2_MOUNT_CHECK_STRICT 0x0002 /* Do again more checks */
+#define EXT2_MOUNT_CHECK (EXT2_MOUNT_CHECK_NORMAL | \
+ EXT2_MOUNT_CHECK_STRICT)
+#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */
+#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */
+#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */
+#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
+#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
+#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
+
+#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
+#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
+#define test_opt(sb, opt) ((sb)->u.ext2_sb.s_mount_opt & \
+ EXT2_MOUNT_##opt)
+/*
+ * Maximal mount counts between two filesystem checks
+ */
+#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
+#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */
+
+#endif /* _SYS_FS_EXT2FS_H */
diff --git a/support/include/version.h b/support/include/version.h
new file mode 100644
index 0000000..a74ec35
--- /dev/null
+++ b/support/include/version.h
@@ -0,0 +1 @@
+#define VERSION "1.4.7 (0.4.22)"
diff --git a/support/include/xio.h b/support/include/xio.h
new file mode 100644
index 0000000..858f5bb
--- /dev/null
+++ b/support/include/xio.h
@@ -0,0 +1,26 @@
+/*
+ * xio.h Declarations for simple parsing functions.
+ *
+ */
+
+#ifndef XIO_H
+#define XIO_H
+
+#include <stdio.h>
+
+typedef struct XFILE {
+ FILE *x_fp;
+ int x_line;
+} XFILE;
+
+XFILE *xfopen(char *fname, char *type);
+int xflock(char *fname, char *type);
+void xfunlock(int lockid);
+void xfclose(XFILE *xfp);
+int xgettok(XFILE *xfp, char sepa, char *tok, int len);
+char xgetc(XFILE *xfp);
+void xungetc(char c, XFILE *xfp);
+void xskip(XFILE *xfp, char *str);
+char xskipcomment(XFILE *xfp);
+
+#endif /* XIO_H */
diff --git a/support/include/xlog.h b/support/include/xlog.h
new file mode 100644
index 0000000..2a839c7
--- /dev/null
+++ b/support/include/xlog.h
@@ -0,0 +1,40 @@
+/*
+ * xlog Logging functionality
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef XLOG_H
+#define XLOG_H
+
+#define L_FATAL 0x0100
+#define L_ERROR 0x0200
+#define L_WARNING 0x0400
+#define L_NOTICE 0x0800
+#define L_ALL 0xFF00
+
+#define D_GENERAL 0x0001 /* general debug info */
+#define D_CALL 0x0002
+#define D_AUTH 0x0004
+#define D_FAC3 0x0008
+#define D_FAC4 0x0010
+#define D_FAC5 0x0020
+#define D_PARSE 0x0040
+#define D_FAC7 0x0080
+#define D_ALL 0x00FF
+
+/* This can be used to define symbolic log names that can be passed to
+ * xlog_config. */
+struct xlog_debugfac {
+ char *df_name;
+ int df_fac;
+};
+
+void xlog_open(char *progname);
+void xlog_background(void);
+void xlog_config(int fac, int on);
+void xlog_sconfig(char *, int on);
+int xlog_enabled(int fac);
+void xlog(int fac, const char *fmt, ...);
+
+#endif /* XLOG_H */
diff --git a/support/include/xmalloc.h b/support/include/xmalloc.h
new file mode 100644
index 0000000..866cfd8
--- /dev/null
+++ b/support/include/xmalloc.h
@@ -0,0 +1,16 @@
+/*
+ * xmalloc Module for memory allocation. Drop in your
+ * debugging malloc module if you feel like it.
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef XMALLOC_H
+#define XMALLOC_H
+
+void *xmalloc(size_t size);
+void *xrealloc(void *ptr, size_t size);
+char *xstrdup(const char *s);
+void xfree(void *ptr);
+
+#endif /* XMALLOC_H */
diff --git a/support/include/ypupdate.h b/support/include/ypupdate.h
new file mode 100644
index 0000000..e0cee15
--- /dev/null
+++ b/support/include/ypupdate.h
@@ -0,0 +1,16 @@
+/*
+ * ypupdate.h This file contains the public declarations for the
+ * ypupdate client side RPC stubs.
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef YPUPDATE_H
+#define YPUPDATE_H
+
+#include <rpcsvc/ypclnt.h>
+
+int yp_update(char *domain, char *map, unsigned int ypop,
+ char *key, int keylen, char *data, int datalen);
+
+#endif YPUPDATE_H
diff --git a/support/lib/Makefile b/support/lib/Makefile
new file mode 100644
index 0000000..b5fa14a
--- /dev/null
+++ b/support/lib/Makefile
@@ -0,0 +1,13 @@
+
+include $(TOP)rules.mk
+
+LIBS = libnfs.a libexport.a
+
+all install:: $(LIBS)
+ @:
+
+clean distclean::
+ rm -f $(LIBS)
+
+lib%.a:
+ ln -sf ../$*/$@ .
diff --git a/support/nfs/Makefile b/support/nfs/Makefile
new file mode 100644
index 0000000..ed1e1ff
--- /dev/null
+++ b/support/nfs/Makefile
@@ -0,0 +1,13 @@
+#
+# linux-nfs/support/nfs/Makefile
+#
+
+LIBNAME = libnfs.a
+OBJS = exports.o rmtab.o xio.o \
+ rpcmisc.o rpcdispatch.o xlog.o xmalloc.o wildmat.o \
+ nfssvc.o nfsclient.o nfsexport.o getfh.o nfsctl.o lockdsvc.o
+
+include $(TOP)rules.mk
+
+install::
+ @:
diff --git a/support/nfs/clients.c b/support/nfs/clients.c
new file mode 100644
index 0000000..b1970e0
--- /dev/null
+++ b/support/nfs/clients.c
@@ -0,0 +1,324 @@
+/*
+ * support/nfs/nfsclient.c
+ *
+ * Parse the nfsclients file.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <ctype.h>
+#include "xmalloc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+#include "xio.h"
+
+static XFILE *cfp = NULL;
+static int *squash_uids = NULL,
+ *squash_gids = NULL;
+static int squash_uidlen = 0,
+ squash_gidlen = 0;
+static char *hosts = NULL;
+
+static int parsesquash(char *list, int **idp, int *lenp);
+static int parsenum(char **cpp);
+static int parsekey(struct nfskey *keyp, char *str);
+static int hexdigit(char c);
+static int gettag(char *tag, int len);
+static int getattr(char *attr, int alen, char *value, int vlen);
+static void syntaxerr(char *msg);
+
+#ifndef isblank
+#define isblank(c) ((c) == ' ' || (c) == '\t')
+#endif
+
+void
+setnfsclntent(char *fname)
+{
+ if (cfp)
+ xfclose(cfp);
+ if (!fname)
+ fname = _PATH_NFSCLIENTS;
+ if ((cfp = xfopen(fname)) == NULL)
+ xlog(L_ERROR, "can't open %s for reading", fname);
+}
+
+struct nfsclntent *
+getnfsclntent(void)
+{
+ static struct nfsclntent cle;
+ static char *hostptr = NULL;
+ char attr[32], val[512], *sp;
+ int ok;
+
+ if (!cfp)
+ endnfsclntent();
+
+again:
+ if (hosts) {
+ if (hostptr)
+ goto nexthost;
+ xfree(hosts);
+ hosts = NULL;
+ }
+
+ if ((ok = gettag(cle.c_tag, sizeof(cle.c_tag))) < 0)
+ syntaxerr("expected tag");
+ if (ok <= 0)
+ return NULL;
+
+ cle.c_hostname[0] = '\0';
+ cle.c_fhkey.k_type = CLE_KEY_NONE;
+ cle.c_mapping = CLE_MAP_IDENT;
+ cle.c_anonuid = -2;
+ cle.c_anongid = -2;
+
+ if (squash_uids)
+ xfree(squash_uids);
+ if (squash_gids)
+ xfree(squash_gids);
+ squash_uids = squash_gids = NULL;
+ squash_uidlen = squash_gidlen = 0;
+
+ while (ok) {
+ if ((ok = getattr(attr, sizeof(attr), val, sizeof(val))) < 0)
+ return NULL;
+ if (!ok)
+ break;
+ if (attr[0] == 'h' && !strcmp(attr, "hosts")) {
+ int l0 = hosts? strlen(hosts) : 0;
+
+ hosts = (char *) xrealloc(hosts, l0+strlen(val)+2);
+ if (l0)
+ hosts[l0++] = ':';
+ strcpy(hosts+l0, val);
+ } else
+ if (attr[0] == 'f' && !strcmp(attr, "fhmac")) {
+ if (!parsekey(&cle.c_fhkey, val))
+ return NULL;
+ } else
+ if (attr[0] == 'm' && !strcmp(attr, "mapping")) {
+ if (!strcmp(val, "identity"))
+ cle.c_mapping = CLE_MAP_IDENT;
+ else if (!strcmp(val, "file"))
+ cle.c_mapping = CLE_MAP_FILE;
+ else if (!strcmp(val, "daemon"))
+ cle.c_mapping = CLE_MAP_UGIDD;
+ else {
+ syntaxerr("invalid mapping type");
+ return NULL;
+ }
+ } else
+ if (attr[0] == 's' && !strcmp(attr, "squash_uids")) {
+ if (!parsesquash(val, &squash_uids, &squash_uidlen))
+ return NULL;
+ } else
+ if (attr[0] == 's' && !strcmp(attr, "squash_gids")) {
+ if (!parsesquash(val, &squash_gids, &squash_gidlen))
+ return NULL;
+ } else
+ if (attr[0] == 'a' && !strcmp(attr, "anonuid"))
+ cle.c_anonuid = atoi(val);
+ else
+ if (attr[0] == 'a' && !strcmp(attr, "anongid"))
+ cle.c_anongid = atoi(val);
+ else
+ syntaxerr("unknown attribute");
+ }
+
+ cle.c_squashuids = squash_uids;
+ cle.c_squashgids = squash_gids;
+
+ /* This is the anon entry */
+ if (!hosts) {
+ if (strcmp(cle.c_tag, "anonymous")) {
+ xlog(L_ERROR, "nfsclients entry %s allows anonymous "
+ "access. Ignored.", cle.c_tag);
+ goto again;
+ }
+ return &cle;
+ }
+ hostptr = hosts;
+
+nexthost:
+ if (*hostptr == ':' && strcmp(cle.c_tag, "anonymous")) {
+ xlog(L_ERROR, "nfsclients entry %s allows anonymous "
+ "access. Ignored.", cle.c_tag);
+ while (*hostptr == ':')
+ hostptr++;
+ }
+
+ /* Ignore trailing colons */
+ if (!*hostptr) {
+ hostptr = NULL;
+ goto again;
+ }
+
+ sp = hostptr;
+ hostptr = strchr(hostptr, ':');
+ if (hostptr)
+ *hostptr++ = '\0';
+ strncpy(cle.c_hostname, sp, sizeof(cle.c_hostname) - 1);
+ cle.c_hostname [sizeof(cle.c_hostname) - 1] = '\0';
+ return &cle;
+}
+
+void
+endnfsclntent(void)
+{
+ if (cfp)
+ xfclose(cfp);
+ if (squash_uids)
+ xfree(squash_uids);
+ if (squash_gids)
+ xfree(squash_gids);
+ if (hosts)
+ xfree(hosts);
+ cfp = NULL;
+ squash_uids = NULL;
+ squash_gids = NULL;
+ hosts = NULL;
+}
+
+static int
+parsekey(struct nfskey *keyp, char *str)
+{
+ char *sp;
+ int i, l, x0, x1;
+
+
+ if ((sp = strchr(str, ':')) != NULL)
+ *sp++ = '\0';
+ if (!strcmp(str, "null"))
+ keyp->k_type = CLE_KEY_NULL;
+ else if (!strcmp(str, "md5"))
+ keyp->k_type = CLE_KEY_MD5;
+ else if (!strcmp(str, "sha"))
+ keyp->k_type = CLE_KEY_SHA;
+ else {
+ syntaxerr("unknown key type");
+ return 0;
+ }
+ if (keyp->k_type == CLE_KEY_NULL) {
+ keyp->k_len = 0;
+ if (sp)
+ syntaxerr("unexpected key data for null key");
+ return sp? 0 : 1;
+ } else if (sp) {
+ if ((l = strlen(sp)) & 1) {
+ syntaxerr("odd key length");
+ return 0;
+ }
+
+ l >>= 1;
+ for (i = 0; i < l && i < sizeof(keyp->k_key); i++, sp += 2) {
+ if ((x0 = hexdigit(sp[0])) == 0xff ||
+ (x1 = hexdigit(sp[1])) == 0xff) {
+ syntaxerr("bad key digit");
+ return 0;
+ }
+ keyp->k_key[i] = (x0 << 4) | x1;
+ }
+ keyp->k_len = i;
+ return 1;
+ }
+ return 0;
+}
+
+static int
+hexdigit(char c)
+{
+ if ((c = tolower(c)) >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ return 0xff;
+}
+
+static int
+parsesquash(char *list, int **idp, int *lenp)
+{
+ char *cp = list;
+ int id0, id1;
+ int len = *lenp;
+ int *id = *idp;
+
+ do {
+ id0 = parsenum(&cp);
+ if (*cp == '-') {
+ cp++;
+ id1 = parsenum(&cp);
+ } else {
+ id1 = id0;
+ }
+ if (id0 == -1 || id1 == -1) {
+ syntaxerr("uid/gid -1 not permitted");
+ return 0;
+ }
+ if ((len % 8) == 0)
+ id = (int *) xrealloc(id, (len + 9) * sizeof(*id));
+ id[len++] = id0;
+ id[len++] = id1;
+ if (!*cp)
+ break;
+ if (*cp != ',') {
+ syntaxerr("bad uid/gid list");
+ return 0;
+ }
+ cp++;
+ } while(1);
+
+ id[len] = -1;
+ *lenp = len;
+ *idp = id;
+ return 1;
+}
+
+static int
+parsenum(char **cpp)
+{
+ char *cp = *cpp, c;
+ int num = 0;
+
+ if (**cpp == '-')
+ (*cpp)++;
+ while (isdigit(**cpp))
+ (*cpp)++;
+ c = **cpp; **cpp = '\0'; num = atoi(cp); **cpp = c;
+ return num;
+}
+
+static int
+gettag(char *tag, int len)
+{
+ xskip(cfp, " \t\n");
+ return xgettok(cfp, ':', tag, len);
+}
+
+static int
+getattr(char *attr, int alen, char *value, int vlen)
+{
+ int ok;
+
+ xskip(cfp, " \t");
+ if ((ok = xgettok(cfp, '=', attr, alen)) < 0)
+ xlog(L_ERROR, "error parsing attribute");
+ if (ok <= 0)
+ return ok;
+ xskip(cfp, " \t=");
+
+ return xgettok(cfp, 0, value, vlen);
+}
+
+static void
+syntaxerr(char *msg)
+{
+ xlog(L_ERROR, "syntax error in nfsclients file (line %d): %s",
+ cfp->x_line, msg);
+}
+
diff --git a/support/nfs/exports.c b/support/nfs/exports.c
new file mode 100644
index 0000000..21b85be
--- /dev/null
+++ b/support/nfs/exports.c
@@ -0,0 +1,440 @@
+/*
+ * support/nfs/export.c
+ *
+ * Parse the exports file. Derived from the unfsd implementation.
+ *
+ * Authors: Donald J. Becker, <becker@super.org>
+ * Rick Sladkey, <jrs@world.std.com>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Olaf Kirch, <okir@monad.swb.de>
+ * Alexander O. Yuriev, <alex@bach.cis.temple.edu>
+ *
+ * This software maybe be used for any purpose provided
+ * the above copyright notice is retained. It is supplied
+ * as is, with no warranty expressed or implied.
+ */
+
+#include "config.h"
+
+#include <sys/param.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <unistd.h>
+#include "nfslib.h"
+#include "exportfs.h"
+#include "xmalloc.h"
+#include "xlog.h"
+#include "xio.h"
+
+#define EXPORT_DEFAULT_FLAGS \
+ (NFSEXP_ASYNC|NFSEXP_READONLY|NFSEXP_ROOTSQUASH|NFSEXP_GATHERED_WRITES)
+
+static XFILE *efp = NULL;
+static int first;
+static int *squids = NULL, nsquids = 0,
+ *sqgids = NULL, nsqgids = 0;
+
+static int getexport(char *exp, int len);
+static int getpath(char *path, int len);
+static int parseopts(char *cp, struct exportent *ep);
+static int parsesquash(char *list, int **idp, int *lenp, char **ep);
+static int parsenum(char **cpp);
+static int parsemaptype(char *type);
+static void freesquash(void);
+static void syntaxerr(char *msg);
+
+void
+setexportent(char *fname, char *type)
+{
+ if (efp)
+ endexportent();
+ if (!fname)
+ fname = _PATH_EXPORTS;
+ if (!(efp = xfopen(fname, type)))
+ xlog(L_ERROR, "can't open %s for %sing",
+ fname, strcmp(type, "r")? "writ" : "read");
+ first = 1;
+}
+
+struct exportent *
+getexportent(void)
+{
+ static struct exportent ee;
+ char exp[512];
+ char rpath[MAXPATHLEN+1];
+ char *opt, *sp;
+ int ok;
+
+ if (!efp)
+ return NULL;
+
+ freesquash();
+ ee.e_flags = EXPORT_DEFAULT_FLAGS;
+ ee.e_maptype = CLE_MAP_IDENT;
+ ee.e_anonuid = -2;
+ ee.e_anongid = -2;
+ ee.e_squids = NULL;
+ ee.e_sqgids = NULL;
+ ee.e_nsquids = 0;
+ ee.e_nsqgids = 0;
+
+ if (first || (ok = getexport(exp, sizeof(exp))) == 0) {
+ ok = getpath(ee.e_path, sizeof(ee.e_path));
+ if (ok <= 0)
+ return NULL;
+ strncpy (ee.m_path, ee.e_path, sizeof (ee.m_path) - 1);
+ ee.m_path [sizeof (ee.m_path) - 1] = '\0';
+ ok = getexport(exp, sizeof(exp));
+ }
+ if (ok < 0) {
+ xlog(L_ERROR, "expected client(options...)");
+ return NULL;
+ }
+ first = 0;
+
+ /* Check for default client */
+ if (ok == 0)
+ exp[0] = '\0';
+ if ((opt = strchr(exp, '(')) != NULL) {
+ *opt++ = '\0';
+ if (!(sp = strchr(opt, ')')) || sp[1] != '\0') {
+ syntaxerr("bad option list");
+ return NULL;
+ }
+ *sp = '\0';
+ if (parseopts(opt, &ee) < 0)
+ return NULL;
+ }
+ if (strlen(exp) >= sizeof(ee.e_hostname)) {
+ syntaxerr("client name too long");
+ return NULL;
+ }
+ strncpy(ee.e_hostname, exp, sizeof (ee.e_hostname) - 1);
+ ee.e_hostname[sizeof (ee.e_hostname) - 1] = '\0';
+
+ /* resolve symlinks */
+ if (realpath(ee.e_path, rpath) != NULL) {
+ rpath[sizeof (rpath) - 1] = '\0';
+ strncpy(ee.e_path, rpath, sizeof (ee.e_path) - 1);
+ ee.e_path[sizeof (ee.e_path) - 1] = '\0';
+ strncpy (ee.m_path, ee.e_path, sizeof (ee.m_path) - 1);
+ ee.m_path [sizeof (ee.m_path) - 1] = '\0';
+ }
+
+ return &ee;
+}
+
+void
+putexportent(struct exportent *ep)
+{
+ FILE *fp;
+ int *id, i;
+
+ if (!efp)
+ return;
+
+ fp = efp->x_fp;
+ fprintf(fp, "%s\t%s(", ep->e_path, ep->e_hostname);
+ fprintf(fp, "%s,", (ep->e_flags & NFSEXP_READONLY)? "ro" : "rw");
+ fprintf(fp, "%ssync,", (ep->e_flags & NFSEXP_ASYNC)? "a" : "");
+ fprintf(fp, "%swdelay,", (ep->e_flags & NFSEXP_GATHERED_WRITES)?
+ "" : "no_");
+ fprintf(fp, "%ssecure,", (ep->e_flags & NFSEXP_INSECURE_PORT)?
+ "in" : "");
+ fprintf(fp, "%sroot_squash,", (ep->e_flags & NFSEXP_ROOTSQUASH)?
+ "" : "no_");
+ fprintf(fp, "%sall_squash,", (ep->e_flags & NFSEXP_ALLSQUASH)?
+ "" : "no_");
+
+ fprintf(fp, "mapping=");
+ switch (ep->e_maptype) {
+ case CLE_MAP_IDENT:
+ fprintf(fp, "identity,");
+ break;
+ case CLE_MAP_UGIDD:
+ fprintf(fp, "ugidd,");
+ break;
+ case CLE_MAP_FILE:
+ fprintf(fp, "file,");
+ break;
+ default:
+ xlog(L_ERROR, "unknown mapping type for %s:%s",
+ ep->e_hostname, ep->e_path);
+ }
+ if ((id = ep->e_squids) != NULL) {
+ fprintf(fp, "squash_uids=");
+ for (i = 0; i < ep->e_nsquids; i += 2)
+ if (id[i] != id[i+1])
+ fprintf(fp, "%d-%d,", id[i], id[i+1]);
+ else
+ fprintf(fp, "%d,", id[i]);
+ }
+ if ((id = ep->e_sqgids) != NULL) {
+ fprintf(fp, "squash_gids=");
+ for (i = 0; i < ep->e_nsquids; i += 2)
+ if (id[i] != id[i+1])
+ fprintf(fp, "%d-%d,", id[i], id[i+1]);
+ else
+ fprintf(fp, "%d,", id[i]);
+ }
+ fprintf(fp, "anonuid=%d,anongid=%d)\n", ep->e_anonuid, ep->e_anongid);
+}
+
+void
+endexportent(void)
+{
+ if (efp)
+ xfclose(efp);
+ efp = NULL;
+ freesquash();
+}
+
+void
+dupexportent(struct exportent *dst, struct exportent *src)
+{
+ int n;
+
+ *dst = *src;
+ if ((n = src->e_nsquids) != 0) {
+ dst->e_squids = (int *) xmalloc(n * sizeof(int));
+ memcpy(dst->e_squids, src->e_squids, n * sizeof(int));
+ }
+ if ((n = src->e_nsqgids) != 0) {
+ dst->e_sqgids = (int *) xmalloc(n * sizeof(int));
+ memcpy(dst->e_sqgids, src->e_sqgids, n * sizeof(int));
+ }
+}
+
+struct exportent *
+mkexportent(char *hname, char *path, char *options)
+{
+ static struct exportent ee;
+
+ ee.e_flags = EXPORT_DEFAULT_FLAGS;
+ ee.e_maptype = CLE_MAP_IDENT;
+ ee.e_anonuid = -2;
+ ee.e_anongid = -2;
+ ee.e_squids = NULL;
+ ee.e_sqgids = NULL;
+ ee.e_nsquids = 0;
+ ee.e_nsqgids = 0;
+
+ if (strlen(hname) >= sizeof(ee.e_hostname)) {
+ xlog(L_WARNING, "client name %s too long", hname);
+ return NULL;
+ }
+ strncpy(ee.e_hostname, hname, sizeof (ee.e_hostname) - 1);
+ ee.e_hostname[sizeof (ee.e_hostname) - 1] = '\0';
+ if (strlen(path) >= sizeof(ee.e_path)) {
+ xlog(L_WARNING, "path name %s too long", path);
+ return NULL;
+ }
+ strncpy(ee.e_path, path, sizeof (ee.e_path));
+ ee.e_path[sizeof (ee.e_path) - 1] = '\0';
+ strncpy (ee.m_path, ee.e_path, sizeof (ee.m_path) - 1);
+ ee.m_path [sizeof (ee.m_path) - 1] = '\0';
+ if (options && parseopts(options, &ee) < 0)
+ return NULL;
+ return &ee;
+}
+
+int
+updateexportent(struct exportent *eep, char *options)
+{
+ if (options && parseopts(options, eep) < 0)
+ return 0;
+ return 1;
+}
+
+/*
+ * Parse option string pointed to by s and set mount options accordingly.
+ */
+static int
+parseopts(char *cp, struct exportent *ep)
+{
+ char *opt;
+
+ squids = ep->e_squids; nsquids = ep->e_nsquids;
+ sqgids = ep->e_sqgids; nsqgids = ep->e_nsqgids;
+
+ while (isblank(*cp))
+ cp++;
+ while (*cp) {
+ opt = cp;
+ while (*cp && *cp != ',')
+ cp++;
+ if (*cp)
+ *cp++ = '\0';
+
+ /* process keyword */
+ if (strcmp(opt, "ro") == 0)
+ ep->e_flags |= NFSEXP_READONLY;
+ else if (strcmp(opt, "rw") == 0)
+ ep->e_flags &= ~NFSEXP_READONLY;
+ else if (!strcmp(opt, "secure"))
+ ep->e_flags &= ~NFSEXP_INSECURE_PORT;
+ else if (!strcmp(opt, "insecure"))
+ ep->e_flags |= NFSEXP_INSECURE_PORT;
+ else if (!strcmp(opt, "sync"))
+ ep->e_flags &= ~NFSEXP_ASYNC;
+ else if (!strcmp(opt, "async"))
+ ep->e_flags |= NFSEXP_ASYNC;
+ else if (!strcmp(opt, "wdelay"))
+ ep->e_flags |= NFSEXP_GATHERED_WRITES;
+ else if (!strcmp(opt, "no_wdelay"))
+ ep->e_flags &= ~NFSEXP_GATHERED_WRITES;
+ else if (strcmp(opt, "root_squash") == 0)
+ ep->e_flags |= NFSEXP_ROOTSQUASH;
+ else if (!strcmp(opt, "no_root_squash"))
+ ep->e_flags &= ~NFSEXP_ROOTSQUASH;
+ else if (strcmp(opt, "all_squash") == 0)
+ ep->e_flags |= NFSEXP_ALLSQUASH;
+ else if (strcmp(opt, "no_all_squash") == 0)
+ ep->e_flags &= ~NFSEXP_ALLSQUASH;
+ else if (strncmp(opt, "mapping=", 8) == 0)
+ ep->e_maptype = parsemaptype(opt+8);
+ else if (strcmp(opt, "map_identity") == 0) /* old style */
+ ep->e_maptype = CLE_MAP_IDENT;
+ else if (strcmp(opt, "map_daemon") == 0) /* old style */
+ ep->e_maptype = CLE_MAP_UGIDD;
+ else if (strncmp(opt, "anonuid=", 8) == 0)
+ ep->e_anonuid = atoi(opt+8);
+ else if (strncmp(opt, "anongid=", 8) == 0)
+ ep->e_anongid = atoi(opt+8);
+ else if (strncmp(opt, "squash_uids=", 12) == 0) {
+ if (parsesquash(opt+12, &squids, &nsquids, &cp) < 0)
+ return -1;
+ } else if (strncmp(opt, "squash_gids=", 12) == 0) {
+ if (parsesquash(opt+12, &sqgids, &nsqgids, &cp) < 0)
+ return -1;
+ } else {
+ xlog(L_ERROR,
+ "Unknown keyword \"%s\" in export file\n",
+ opt);
+ ep->e_flags |= NFSEXP_ALLSQUASH | NFSEXP_READONLY;
+ return -1;
+ }
+ while (isblank(*cp))
+ cp++;
+ }
+
+ ep->e_squids = squids;
+ ep->e_sqgids = sqgids;
+ ep->e_nsquids = nsquids;
+ ep->e_nsqgids = nsqgids;
+
+ return 1;
+}
+
+static int
+parsesquash(char *list, int **idp, int *lenp, char **ep)
+{
+ char *cp = list;
+ int id0, id1;
+ int len = *lenp;
+ int *id = *idp;
+
+ if (**ep)
+ *--(*ep) = ',';
+
+ do {
+ id0 = parsenum(&cp);
+ if (*cp == '-') {
+ cp++;
+ id1 = parsenum(&cp);
+ } else {
+ id1 = id0;
+ }
+ if (id0 == -1 || id1 == -1) {
+ syntaxerr("uid/gid -1 not permitted");
+ return -1;
+ }
+ if ((len % 8) == 0)
+ id = (int *) xrealloc(id, (len + 8) * sizeof(*id));
+ id[len++] = id0;
+ id[len++] = id1;
+ if (!*cp || *cp == ')' || (*cp == ',' && !isdigit(cp[1])))
+ break;
+ if (*cp != ',') {
+ syntaxerr("bad uid/gid list");
+ return -1;
+ }
+ cp++;
+ } while(1);
+
+ if (*cp == ',') *ep = cp+1;
+
+ *lenp = len;
+ *idp = id;
+ return 1;
+}
+
+static void
+freesquash(void)
+{
+ if (squids) {
+ xfree (squids);
+ squids = NULL;
+ nsquids = 0;
+ }
+ if (sqgids) {
+ xfree (sqgids);
+ sqgids = NULL;
+ nsqgids = 0;
+ }
+}
+
+static int
+parsenum(char **cpp)
+{
+ char *cp = *cpp, c;
+ int num = 0;
+
+ if (**cpp == '-')
+ (*cpp)++;
+ while (isdigit(**cpp))
+ (*cpp)++;
+ c = **cpp; **cpp = '\0'; num = atoi(cp); **cpp = c;
+ return num;
+}
+
+static int
+parsemaptype(char *type)
+{
+ if (!strcmp(type, "identity"))
+ return CLE_MAP_IDENT;
+ if (!strcmp(type, "ugidd"))
+ return CLE_MAP_UGIDD;
+ if (!strcmp(type, "file"))
+ return CLE_MAP_FILE;
+ syntaxerr("invalid map type");
+ return CLE_MAP_IDENT; /* default */
+}
+
+static int
+getpath(char *path, int len)
+{
+ xskip(efp, " \t\n");
+ return xgettok(efp, 0, path, len);
+}
+
+static int
+getexport(char *exp, int len)
+{
+ int ok;
+
+ xskip(efp, " \t");
+ if ((ok = xgettok(efp, 0, exp, len)) < 0)
+ xlog(L_ERROR, "error parsing export entry");
+ return ok;
+}
+
+static void
+syntaxerr(char *msg)
+{
+ xlog(L_ERROR, "syntax error in exports file (line %d): %s",
+ efp->x_line, msg);
+}
+
diff --git a/support/nfs/getfh.c b/support/nfs/getfh.c
new file mode 100644
index 0000000..5a6f1a4
--- /dev/null
+++ b/support/nfs/getfh.c
@@ -0,0 +1,55 @@
+/*
+ * support/nfs/getfh.c
+ *
+ * Get the FH for a given client and directory. This function takes
+ * the NFS protocol version number as an additional argument.
+ *
+ * This function has nothing in common with the SunOS getfh function,
+ * which is a front-end to the RPC mount call.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <sys/types.h>
+#include <errno.h>
+#include "nfslib.h"
+
+struct knfs_fh *
+getfh_old (struct sockaddr *addr, dev_t dev, ino_t ino)
+{
+ static union nfsctl_res res;
+ struct nfsctl_arg arg;
+
+ arg.ca_version = NFSCTL_VERSION;
+ arg.ca_getfh.gf_version = 2; /* obsolete */
+ arg.ca_getfh.gf_dev = dev;
+ arg.ca_getfh.gf_ino = ino;
+ memcpy(&arg.ca_getfh.gf_addr, addr, sizeof(struct sockaddr_in));
+
+ if (nfsctl(NFSCTL_GETFH, &arg, &res) < 0)
+ return NULL;
+
+ return &res.cr_getfh;
+}
+
+struct knfs_fh *
+getfh(struct sockaddr *addr, const char *path)
+{
+ static union nfsctl_res res;
+ struct nfsctl_arg arg;
+
+ arg.ca_version = NFSCTL_VERSION;
+ arg.ca_getfd.gd_version = 2; /* obsolete */
+ strncpy(arg.ca_getfd.gd_path, path,
+ sizeof(arg.ca_getfd.gd_path) - 1);
+ arg.ca_getfd.gd_path[sizeof (arg.ca_getfd.gd_path) - 1] = '\0';
+ memcpy(&arg.ca_getfd.gd_addr, addr, sizeof(struct sockaddr_in));
+
+ if (nfsctl(NFSCTL_GETFD, &arg, &res) < 0)
+ return NULL;
+
+ return &res.cr_getfh;
+}
diff --git a/support/nfs/keytab.c b/support/nfs/keytab.c
new file mode 100644
index 0000000..e33dded
--- /dev/null
+++ b/support/nfs/keytab.c
@@ -0,0 +1,129 @@
+/*
+ * support/nfs/keytab.c
+ *
+ * Manage the nfskeys database.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <ctype.h>
+#include "xmalloc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+#include "xio.h"
+
+static FILE *cfp = NULL;
+
+int
+setnfskeyent(char *fname)
+{
+ if (cfp)
+ fclose(cfp);
+ if (!fname)
+ fname = _PATH_NFSKEYS;
+ cfp = fsetnfskeyent(fname, "r");
+ return cfp != NULL;
+}
+
+FILE *
+fsetnfskeyent(char *fname, char *type)
+{
+#if 0
+ FILE *fp;
+
+ if ((fp = fopen(fname, type)) == NULL)
+ xlog(L_ERROR, "can't open %s for %sing\n",
+ fname, type[0] == 'r'? "read" : "writ");
+ return fp;
+#else
+ return fopen(fname, type);
+#endif
+}
+
+struct nfskeyent *
+getnfskeyent(void)
+{
+ return fgetnfskeyent(cfp);
+}
+
+struct nfskeyent *
+fgetnfskeyent(FILE *fp)
+{
+ static struct nfskeyent ke;
+
+ if (!fp)
+ return NULL;
+
+ do {
+ if (fread(&ke, sizeof(ke), 1, fp) != 1)
+ return NULL;
+ } while(ke.k_hostname[0] == '\0');
+ return &ke;
+}
+
+void
+endnfskeyent(void)
+{
+ if (cfp)
+ fclose(cfp);
+ cfp = NULL;
+}
+
+void
+fendnfskeyent(FILE *fp)
+{
+ if (fp)
+ fclose(fp);
+}
+
+void
+fputnfskeyent(FILE *fp, struct nfskeyent *kep)
+{
+ fwrite(kep, sizeof(*kep), 1, fp);
+}
+
+int
+getnfskeytype(char *st)
+{
+ if (!strcasecmp(st, "null"))
+ return CLE_KEY_NULL;
+ if (!strcasecmp(st, "md5"))
+ return CLE_KEY_MD5;
+ if (!strcasecmp(st, "sha"))
+ return CLE_KEY_SHA;
+ return CLE_KEY_NONE;
+}
+
+char *
+getnfskeyname(int type)
+{
+ switch (type) {
+ case CLE_KEY_NONE:
+ return "none";
+ case CLE_KEY_NULL:
+ return "null";
+ case CLE_KEY_MD5:
+ return "md5";
+ case CLE_KEY_SHA:
+ return "sha";
+ }
+ return "unk";
+}
+
+int
+getnfskeysize(int type)
+{
+ switch (type) {
+ case CLE_KEY_MD5:
+ return 16;
+ case CLE_KEY_SHA:
+ return 20;
+ }
+ return 0;
+}
diff --git a/support/nfs/lockdsvc.c b/support/nfs/lockdsvc.c
new file mode 100644
index 0000000..532e721
--- /dev/null
+++ b/support/nfs/lockdsvc.c
@@ -0,0 +1,20 @@
+/*
+ * support/nfs/nfssvc.c
+ *
+ * Run an NFS daemon.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include "nfslib.h"
+
+int
+lockdsvc()
+{
+ struct nfsctl_arg arg;
+
+ arg.ca_version = NFSCTL_VERSION;
+ return nfsctl(LOCKDCTL_SVC, &arg, NULL);
+}
diff --git a/support/nfs/nfsclient.c b/support/nfs/nfsclient.c
new file mode 100644
index 0000000..5886484
--- /dev/null
+++ b/support/nfs/nfsclient.c
@@ -0,0 +1,32 @@
+/*
+ * support/nfs/client.c
+ *
+ * Add or delete an NFS client in knfsd.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include "nfslib.h"
+
+int
+nfsaddclient(struct nfsctl_client *clp)
+{
+ struct nfsctl_arg arg;
+
+ arg.ca_version = NFSCTL_VERSION;
+ memcpy(&arg.ca_client, clp, sizeof(arg.ca_client));
+ return nfsctl(NFSCTL_ADDCLIENT, &arg, NULL);
+}
+
+int
+nfsdelclient(struct nfsctl_client *clp)
+{
+ struct nfsctl_arg arg;
+
+ arg.ca_version = NFSCTL_VERSION;
+ memcpy(&arg.ca_client, clp, sizeof(arg.ca_client));
+ return nfsctl(NFSCTL_DELCLIENT, &arg, NULL);
+}
diff --git a/support/nfs/nfsctl.c b/support/nfs/nfsctl.c
new file mode 100644
index 0000000..c04588f
--- /dev/null
+++ b/support/nfs/nfsctl.c
@@ -0,0 +1,24 @@
+/*
+ * support/nfs/nfsctl.c
+ *
+ * Central syscall to the nfsd kernel module.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <asm/unistd.h>
+#include "nfslib.h"
+
+/* compatibility hack... */
+#ifndef __NR_nfsctl
+#define __NR_nfsctl __NR_nfsservctl
+#endif
+
+int
+nfsctl (int cmd, struct nfsctl_arg * argp, union nfsctl_res * resp)
+{
+ return syscall (__NR_nfsctl, cmd, argp, resp);
+}
diff --git a/support/nfs/nfsexport.c b/support/nfs/nfsexport.c
new file mode 100644
index 0000000..ce8b867
--- /dev/null
+++ b/support/nfs/nfsexport.c
@@ -0,0 +1,32 @@
+/*
+ * support/nfs/export.c
+ *
+ * Add or delete an NFS export in knfsd.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include "nfslib.h"
+
+int
+nfsexport(struct nfsctl_export *exp)
+{
+ struct nfsctl_arg arg;
+
+ arg.ca_version = NFSCTL_VERSION;
+ memcpy(&arg.ca_export, exp, sizeof(arg.ca_export));
+ return nfsctl(NFSCTL_EXPORT, &arg, NULL);
+}
+
+int
+nfsunexport(struct nfsctl_export *exp)
+{
+ struct nfsctl_arg arg;
+
+ arg.ca_version = NFSCTL_VERSION;
+ memcpy(&arg.ca_export, exp, sizeof(arg.ca_export));
+ return nfsctl(NFSCTL_UNEXPORT, &arg, NULL);
+}
diff --git a/support/nfs/nfssvc.c b/support/nfs/nfssvc.c
new file mode 100644
index 0000000..7419baf
--- /dev/null
+++ b/support/nfs/nfssvc.c
@@ -0,0 +1,22 @@
+/*
+ * support/nfs/nfssvc.c
+ *
+ * Run an NFS daemon.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include "nfslib.h"
+
+int
+nfssvc(int port, int nrservs)
+{
+ struct nfsctl_arg arg;
+
+ arg.ca_version = NFSCTL_VERSION;
+ arg.ca_svc.svc_nthreads = nrservs;
+ arg.ca_svc.svc_port = port;
+ return nfsctl(NFSCTL_SVC, &arg, NULL);
+}
diff --git a/support/nfs/rmtab.c b/support/nfs/rmtab.c
new file mode 100644
index 0000000..b9b5ff1
--- /dev/null
+++ b/support/nfs/rmtab.c
@@ -0,0 +1,122 @@
+/*
+ * support/nfs/rmtab.c
+ *
+ * Handling for rmtab.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <sys/fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include "nfslib.h"
+
+static FILE *rmfp = NULL;
+
+int
+setrmtabent(char *type)
+{
+ if (rmfp)
+ fclose(rmfp);
+ rmfp = fsetrmtabent(_PATH_RMTAB, type);
+ return (rmfp != NULL);
+}
+
+FILE *
+fsetrmtabent(char *fname, char *type)
+{
+ int readonly = !strcmp(type, "r");
+ FILE *fp;
+
+ if (!fname)
+ return NULL;
+ if ((fp = fopen(fname, type)) == NULL) {
+ xlog(L_ERROR, "can't open %s for %sing", fname,
+ readonly ? "read" : "writ");
+ return NULL;
+ }
+ return fp;
+}
+
+struct rmtabent *
+getrmtabent(int log)
+{
+ return fgetrmtabent(rmfp, log);
+}
+
+struct rmtabent *
+fgetrmtabent(FILE *fp, int log)
+{
+ static struct rmtabent re;
+ char buf[2048], *sp;
+
+ errno = 0;
+ if (!fp)
+ return NULL;
+ do {
+ if (fgets(buf, sizeof(buf)-1, fp) == NULL)
+ return NULL;
+ if ((sp = strchr(buf, '\n')) != NULL)
+ *sp = '\0';
+ if (!(sp = strchr(buf, ':'))) {
+ if (log)
+ xlog(L_ERROR, "malformed entry in rmtab file");
+ errno = EINVAL;
+ return NULL;
+ }
+ *sp++ = '\0';
+ } while (0);
+ strncpy(re.r_client, buf, sizeof (re.r_client) - 1);
+ re.r_client[sizeof (re.r_client) - 1] = '\0';
+ strncpy(re.r_path, sp, sizeof (re.r_path) - 1);
+ re.r_path[sizeof (re.r_path) - 1] = '\0';
+ return &re;
+}
+
+void
+putrmtabent(struct rmtabent *rep)
+{
+ fputrmtabent(rmfp, rep);
+}
+
+void
+fputrmtabent(FILE *fp, struct rmtabent *rep)
+{
+ if (!fp)
+ return;
+ fprintf(fp, "%s:%s\n", rep->r_client, rep->r_path);
+}
+
+void
+endrmtabent(void)
+{
+ fendrmtabent(rmfp);
+ rmfp = NULL;
+}
+
+void
+fendrmtabent(FILE *fp)
+{
+ if (fp)
+ fclose(fp);
+}
+
+void
+rewindrmtabent(void)
+{
+ if (rmfp)
+ rewind(rmfp);
+}
+
+void
+frewindrmtabent(FILE *fp)
+{
+ if (fp)
+ rewind (fp);
+}
diff --git a/support/nfs/rpcdispatch.c b/support/nfs/rpcdispatch.c
new file mode 100644
index 0000000..e798ea5
--- /dev/null
+++ b/support/nfs/rpcdispatch.c
@@ -0,0 +1,112 @@
+/*
+ * support/nfs/rcpdispatch.c
+ *
+ * Generic RPC dispatcher.
+ *
+ * Copyright (C) 1995, 1996, Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <signal.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <string.h>
+#include "rpcmisc.h"
+#include "xlog.h"
+
+void
+rpc_dispatch(struct svc_req *rqstp, SVCXPRT *transp,
+ struct rpc_dtable *dtable, int nvers,
+ void *argp, void *resp)
+{
+ struct rpc_dentry *dent;
+
+ if (rqstp->rq_vers > nvers) {
+ svcerr_progvers(transp, 1, nvers);
+ return;
+ }
+ dtable += (rqstp->rq_vers - 1);
+ if (rqstp->rq_proc > dtable->nproc) {
+ svcerr_noproc(transp);
+ return;
+ }
+
+ dent = dtable->entries + rqstp->rq_proc;
+
+ if (dent->func == NULL) {
+ svcerr_noproc(transp);
+ return;
+ }
+
+ memset(argp, 0, dent->xdr_arg_size);
+ memset(resp, 0, dent->xdr_res_size);
+
+ if (!svc_getargs(transp, dent->xdr_arg_fn, argp)) {
+ svcerr_decode(transp);
+ return;
+ }
+
+ if ((dent->func)(rqstp, argp, resp) && resp != 0) {
+ if (!svc_sendreply(transp, dent->xdr_res_fn, (caddr_t)resp))
+ svcerr_systemerr(transp);
+ }
+ if (!svc_freeargs(transp, dent->xdr_arg_fn, argp)) {
+ xlog(L_ERROR, "failed to free RPC arguments");
+ exit (2);
+ }
+}
+
+#if 0
+/*
+ * This is our replacement for svc_run. It turns off some signals while
+ * executing the server procedures to avoid nasty race conditions.
+ */
+void
+rpc_svcrun(fd_set *morefds, void (*func)(int fd))
+{
+ sigset_t block, current;
+ fd_set readfds;
+
+ for (;;) {
+ readfds = svc_fdset;
+ if (morefds) {
+ int i;
+
+ /* most efficient */
+ for (i = 0; i < FD_SETSIZE; i++)
+ if (FD_ISSET(i, morefds))
+ FD_SET(i, &readfs);
+ }
+ switch (select(FD_SETSIZE, &readfds, NULL, NULL, NULL)) {
+ case -1:
+ if (errno == EINTR)
+ continue;
+ xlog(L_ERROR, "svc_run: - select failed");
+ break;
+ case 0:
+ continue;
+ default:
+ if (morefds) {
+ int i;
+
+ /* most efficient */
+ for (i = 0; i < FD_SETSIZE; i++)
+ if (FD_ISSET(i, morefds) &&
+ FD_ISSET(i, &readfds))
+ func(i);
+ }
+ sigemptyset(&block);
+ sigaddset(&block, SIGALRM);
+ sigaddset(&block, SIGVTALRM);
+ sigaddset(&block, SIGIO);
+ sigprocmask(SIG_BLOCK, &block, &current);
+ svc_getreqset(&readfds);
+ sigprocmask(SIG_SETMASK, &current, NULL);
+ }
+ }
+}
+#endif
diff --git a/support/nfs/rpcmisc.c b/support/nfs/rpcmisc.c
new file mode 100644
index 0000000..7b182fd
--- /dev/null
+++ b/support/nfs/rpcmisc.c
@@ -0,0 +1,230 @@
+/*
+ * support/nfs/rpcmisc.c
+ *
+ * Miscellaneous functions for RPC startup and shutdown.
+ * This code is partially snarfed from rpcgen -s tcp -s udp,
+ * partly written by Mark Shand, Donald Becker, and Rick
+ * Sladkey. It was tweaked slightly by Olaf Kirch to be
+ * usable by both unfsd and mountd.
+ *
+ * This software may be used for any purpose provided
+ * the above copyright notice is retained. It is supplied
+ * as is, with no warranty expressed or implied.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <memory.h>
+#include <errno.h>
+#include <unistd.h>
+#include "nfslib.h"
+
+static void closedown(int sig);
+static int makesock(int port, int proto, int socksz);
+
+#define _RPCSVC_CLOSEDOWN 120
+int _rpcpmstart = 0;
+int _rpcfdtype = 0;
+int _rpcsvcdirty = 0;
+
+void
+rpc_init(char *name, int prog, int vers, void (*dispatch)(), int defport,
+ int bufsiz)
+{
+ struct sockaddr_in saddr;
+ SVCXPRT *transp;
+ int sock;
+ int asize;
+
+ asize = sizeof(saddr);
+ sock = 0;
+ _rpcfdtype = 0;
+ if (getsockname(0, (struct sockaddr *) &saddr, &asize) == 0) {
+ int ssize = sizeof (int);
+ if (saddr.sin_family != AF_INET)
+ xlog(L_FATAL, "init: stdin is bound to non-inet addr");
+ if (getsockopt(0, SOL_SOCKET, SO_TYPE,
+ (char *)&_rpcfdtype, &ssize) == -1)
+ xlog(L_FATAL, "getsockopt failed: %s", strerror(errno));
+ _rpcpmstart = 1;
+ } else {
+ pmap_unset(prog, vers);
+ sock = RPC_ANYSOCK;
+ }
+
+ if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) {
+ if (_rpcfdtype == 0 && defport != 0 &&
+ ((sock = makesock(defport, IPPROTO_UDP, bufsiz)) < 0)) {
+ xlog(L_FATAL, "%s: could not make a UDP socket\n",
+ name);
+ }
+ transp = svcudp_create(sock);
+ if (transp == NULL) {
+ xlog(L_FATAL, "cannot create udp service.");
+ }
+ if (!svc_register(transp, prog, vers, dispatch, IPPROTO_UDP)) {
+ xlog(L_FATAL, "unable to register (%s, %d, udp).",
+ name, vers);
+ }
+ }
+
+ if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) {
+ if (_rpcfdtype == 0 && defport != 0 &&
+ ((sock = makesock(defport, IPPROTO_TCP, bufsiz)) < 0)) {
+ xlog(L_FATAL, "%s: could not make a TCP socket\n",
+ name);
+ }
+ transp = svctcp_create(sock, 0, 0);
+ if (transp == NULL) {
+ xlog(L_FATAL, "cannot create tcp service.");
+ }
+ if (!svc_register(transp, prog, vers, dispatch, IPPROTO_TCP)) {
+ xlog(L_FATAL, "unable to register (%s, %d, tcp).",
+ name, vers);
+ }
+ }
+
+ if (_rpcpmstart) {
+ signal (SIGALRM, closedown);
+ alarm (_RPCSVC_CLOSEDOWN);
+ }
+}
+
+static void closedown(sig)
+int sig;
+{
+ (void) signal(sig, closedown);
+ if (_rpcsvcdirty == 0) {
+ extern fd_set svc_fdset;
+ static int size;
+ int i, openfd;
+
+ if (_rpcfdtype == SOCK_DGRAM)
+ exit(0);
+ if (size == 0) {
+ size = getdtablesize();
+ }
+ for (i = 0, openfd = 0; i < size && openfd < 2; i++)
+ if (FD_ISSET(i, &svc_fdset))
+ openfd++;
+ if (openfd <= 1)
+ exit(0);
+ }
+ (void) alarm(_RPCSVC_CLOSEDOWN);
+}
+
+static int makesock(port, proto, socksz)
+int port;
+int proto;
+int socksz;
+{
+ struct sockaddr_in sin;
+ int s;
+ int sock_type;
+ int val;
+
+ sock_type = (proto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
+ s = socket(AF_INET, sock_type, proto);
+ if (s < 0) {
+ xlog(L_FATAL, "Could not make a socket: %s\n",
+ strerror(errno));
+ return (-1);
+ }
+ memset((char *) &sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = INADDR_ANY;
+ sin.sin_port = htons(port);
+
+ val = 1;
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0)
+ xlog(L_ERROR, "setsockopt failed: %s\n", strerror(errno));
+
+#ifdef SO_SNDBUF
+ {
+ int sblen, rblen;
+
+ /* 1024 for rpc & transport overheads */
+ sblen = rblen = socksz + 1024;
+ if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sblen, sizeof sblen) < 0 ||
+ setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rblen, sizeof rblen) < 0)
+ xlog(L_ERROR, "setsockopt failed: %s\n", strerror(errno));
+ }
+#endif /* SO_SNDBUF */
+
+ if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) {
+ xlog(L_FATAL, "Could not bind name to socket: %s\n",
+ strerror(errno));
+ return (-1);
+ }
+ return (s);
+}
+
+
+/* Log an incoming call. */
+void
+rpc_logcall(struct svc_req *rqstp, char *xname, char *arg)
+{
+ char buff[1024];
+ int buflen=sizeof(buff);
+ int len;
+ char *sp;
+ int i;
+
+ if (!xlog_enabled(D_CALL))
+ return;
+
+ sp = buff;
+ switch (rqstp->rq_cred.oa_flavor) {
+ case AUTH_NULL:
+ sprintf(sp, "NULL");
+ break;
+ case AUTH_UNIX: {
+ struct authunix_parms *unix_cred;
+ struct tm *tm;
+
+ unix_cred = (struct authunix_parms *) rqstp->rq_clntcred;
+ tm = localtime(&unix_cred->aup_time);
+ snprintf(sp, buflen, "UNIX %d/%d/%d %02d:%02d:%02d %s %d.%d",
+ tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec,
+ unix_cred->aup_machname,
+ unix_cred->aup_uid,
+ unix_cred->aup_gid);
+ sp[buflen-1] = 0;
+ len = strlen(sp);
+ sp += buflen;
+ buflen -= len;
+ if ((int) unix_cred->aup_len > 0) {
+ snprintf(sp, buflen, "+%d", unix_cred->aup_gids[0]);
+ sp[buflen-1] = 0;
+ len = strlen(sp);
+ sp += buflen;
+ buflen -= len;
+ for (i = 1; i < unix_cred->aup_len; i++) {
+ snprintf(sp, buflen, ",%d",
+ unix_cred->aup_gids[i]);
+ sp[buflen-1] = 0;
+ len = strlen(sp);
+ sp += buflen;
+ buflen -= len;
+ }
+ }
+ }
+ break;
+ default:
+ sprintf(sp, "CRED %d", rqstp->rq_cred.oa_flavor);
+ }
+ xlog(D_CALL, "%s [%s]\n\t%s\n", xname, buff, arg);
+}
diff --git a/support/nfs/wildmat.c b/support/nfs/wildmat.c
new file mode 100644
index 0000000..8f7b760
--- /dev/null
+++ b/support/nfs/wildmat.c
@@ -0,0 +1,177 @@
+/* $Revision: 0.2.18.1 $
+**
+** Do shell-style pattern matching for ?, \, [], and * characters.
+** Might not be robust in face of malformed patterns; e.g., "foo[a-"
+** could cause a segmentation violation. It is 8bit clean.
+**
+** Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
+** Rich $alz is now <rsalz@osf.org>.
+** April, 1991: Replaced mutually-recursive calls with in-line code
+** for the star character.
+**
+** Special thanks to Lars Mathiesen <thorinn@diku.dk> for the ABORT code.
+** This can greatly speed up failing wildcard patterns. For example:
+** pattern: -*-*-*-*-*-*-12-*-*-*-m-*-*-*
+** text 1: -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1
+** text 2: -adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1
+** Text 1 matches with 51 calls, while text 2 fails with 54 calls. Without
+** the ABORT code, it takes 22310 calls to fail. Ugh. The following
+** explanation is from Lars:
+** The precondition that must be fulfilled is that DoMatch will consume
+** at least one character in text. This is true if *p is neither '*' nor
+** '\0'.) The last return has ABORT instead of FALSE to avoid quadratic
+** behaviour in cases like pattern "*a*b*c*d" with text "abcxxxxx". With
+** FALSE, each star-loop has to run to the end of the text; with ABORT
+** only the last one does.
+**
+** Once the control of one instance of DoMatch enters the star-loop, that
+** instance will return either TRUE or ABORT, and any calling instance
+** will therefore return immediately after (without calling recursively
+** again). In effect, only one star-loop is ever active. It would be
+** possible to modify the code to maintain this context explicitly,
+** eliminating all recursive calls at the cost of some complication and
+** loss of clarity (and the ABORT stuff seems to be unclear enough by
+** itself). I think it would be unwise to try to get this into a
+** released version unless you have a good test data base to try it out
+** on.
+*/
+
+#include "config.h"
+
+#include <ctype.h>
+
+#define TRUE 1
+#define FALSE 0
+#define ABORT -1
+
+
+ /* What character marks an inverted character class? */
+#define NEGATE_CLASS '^'
+ /* Is "*" a common pattern? */
+#define OPTIMIZE_JUST_STAR
+ /* Do tar(1) matching rules, which ignore a trailing slash? */
+#undef MATCH_TAR_PATTERN
+
+
+/*
+** Match text and p, return TRUE, FALSE, or ABORT.
+*/
+static int
+DoMatch(text, p)
+ register char *text;
+ register char *p;
+{
+ register int last;
+ register int matched;
+ register int reverse;
+
+ for ( ; *p; text++, p++) {
+ if (*text == '\0' && *p != '*')
+ return ABORT;
+ switch (*p) {
+ case '\\':
+ /* Literal match with following character. */
+ p++;
+ /* FALLTHROUGH */
+ default:
+ if (toupper (*text) != toupper (*p))
+ return FALSE;
+ continue;
+ case '?':
+ /* Match anything. */
+ continue;
+ case '*':
+ while (*++p == '*')
+ /* Consecutive stars act just like one. */
+ continue;
+ if (*p == '\0')
+ /* Trailing star matches everything. */
+ return TRUE;
+ while (*text)
+ if ((matched = DoMatch(text++, p)) != FALSE)
+ return matched;
+ return ABORT;
+ case '[':
+ reverse = p[1] == NEGATE_CLASS ? TRUE : FALSE;
+ if (reverse)
+ /* Inverted character class. */
+ p++;
+ matched = FALSE;
+ if (p[1] == ']' || p[1] == '-')
+ if (toupper (*++p) == toupper(*text))
+ matched = TRUE;
+ for (last = *p; *++p && *p != ']'; last = *p)
+ /* This next line requires a good C compiler. */
+ if (*p == '-' && p[1] != ']'
+ ? *text <= *++p && *text >= last
+ : toupper (*text) == toupper (*p))
+ matched = TRUE;
+ if (matched == reverse)
+ return FALSE;
+ continue;
+ }
+ }
+
+#ifdef MATCH_TAR_PATTERN
+ if (*text == '/')
+ return TRUE;
+#endif /* MATCH_TAR_ATTERN */
+ return *text == '\0';
+}
+
+
+/*
+** User-level routine. Returns TRUE or FALSE.
+*/
+int
+wildmat(text, p)
+ char *text;
+ char *p;
+{
+#ifdef OPTIMIZE_JUST_STAR
+ if (p[0] == '*' && p[1] == '\0')
+ return TRUE;
+#endif /* OPTIMIZE_JUST_STAR */
+ return DoMatch(text, p) == TRUE;
+}
+
+
+
+#if defined(TEST)
+#include <stdio.h>
+
+/* Yes, we use gets not fgets. Sue me. */
+extern char *gets();
+
+
+int
+main()
+{
+ char p[80];
+ char text[80];
+
+ printf("Wildmat tester. Enter pattern, then strings to test.\n");
+ printf("A blank line gets prompts for a new pattern; a blank pattern\n");
+ printf("exits the program.\n");
+
+ for ( ; ; ) {
+ printf("\nEnter pattern: ");
+ (void)fflush(stdout);
+ if (gets(p) == NULL || p[0] == '\0')
+ break;
+ for ( ; ; ) {
+ printf("Enter text: ");
+ (void)fflush(stdout);
+ if (gets(text) == NULL)
+ exit(0);
+ if (text[0] == '\0')
+ /* Blank line; go back and get a new pattern. */
+ break;
+ printf(" %s\n", wildmat(text, p) ? "YES" : "NO");
+ }
+ }
+
+ exit(0);
+ /* NOTREACHED */
+}
+#endif /* defined(TEST) */
diff --git a/support/nfs/xio.c b/support/nfs/xio.c
new file mode 100644
index 0000000..1bcd41b
--- /dev/null
+++ b/support/nfs/xio.c
@@ -0,0 +1,151 @@
+/*
+ * support/nfs/xio.c
+ *
+ * Simple I/O functions for the parsing of /etc/exports and /etc/nfsclients.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <sys/fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+#include <unistd.h>
+#include "xmalloc.h"
+#include "xlog.h"
+#include "xio.h"
+
+XFILE *
+xfopen(char *fname, char *type)
+{
+ XFILE *xfp;
+ FILE *fp;
+
+ if (!(fp = fopen(fname, type)))
+ return NULL;
+ xfp = (XFILE *) xmalloc(sizeof(*xfp));
+ xfp->x_fp = fp;
+ xfp->x_line = 0;
+
+ return xfp;
+}
+
+void
+xfclose(XFILE *xfp)
+{
+ fclose(xfp->x_fp);
+ xfree(xfp);
+}
+
+static void
+doalarm(int sig)
+{
+ return;
+}
+
+int
+xflock(char *fname, char *type)
+{
+ struct sigaction sa, oldsa;
+ int readonly = !strcmp(type, "r");
+ struct flock fl = { readonly? F_RDLCK : F_WRLCK, SEEK_SET, 0, 0, 0 };
+ int fd;
+
+ if ((fd = open(fname, readonly? O_RDONLY : O_RDWR)) < 0) {
+ xlog(L_WARNING, "could not open %s for locking", fname);
+ return -1;
+ }
+ sa.sa_handler = doalarm;
+ sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGALRM, &sa, &oldsa);
+ alarm(10);
+ if (fcntl(fd, F_SETLKW, &fl) < 0) {
+ alarm(0);
+ xlog(L_WARNING, "failed to lock %s", fname);
+ close(fd);
+ fd = 0;
+ } else {
+ alarm(0);
+ }
+ sigaction(SIGALRM, &oldsa, NULL);
+
+ return fd;
+}
+
+void
+xfunlock(int fd)
+{
+ close(fd);
+}
+
+int
+xgettok(XFILE *xfp, char sepa, char *tok, int len)
+{
+ int i = 0;
+ char c = 0;
+
+ while (i < len && (c = xgetc(xfp)) != EOF && c != sepa && !isspace(c))
+ tok[i++] = c;
+ if (c == '\n')
+ ungetc(c, xfp->x_fp);
+ if (!i)
+ return 0;
+ if (i >= len || (sepa && c != sepa))
+ return -1;
+ tok[i] = '\0';
+ return 1;
+}
+
+char
+xgetc(XFILE *xfp)
+{
+ char c = getc(xfp->x_fp);
+
+ if (c == EOF)
+ return c;
+ if (c == '\\') {
+ if ((c = getc(xfp->x_fp)) != '\n') {
+ ungetc(c, xfp->x_fp);
+ return '\\';
+ }
+ xfp->x_line++;
+ while ((c = getc(xfp->x_fp)) == ' ' || c == '\t');
+ ungetc(c, xfp->x_fp);
+ return ' ';
+ }
+ if (c == '#')
+ c = xskipcomment(xfp);
+ if (c == '\n')
+ xfp->x_line++;
+ return c;
+}
+
+void
+xungetc(char c, XFILE *xfp)
+{
+ if (c != EOF)
+ ungetc(c, xfp->x_fp);
+}
+
+void
+xskip(XFILE *xfp, char *str)
+{
+ char c;
+
+ while ((c = xgetc(xfp)) != EOF && strchr(str, c));
+ ungetc(c, xfp->x_fp);
+}
+
+char
+xskipcomment(XFILE *xfp)
+{
+ char c;
+
+ while ((c = getc(xfp->x_fp)) != EOF && c != '\n');
+ return c;
+}
diff --git a/support/nfs/xlog.c b/support/nfs/xlog.c
new file mode 100644
index 0000000..90c7e63
--- /dev/null
+++ b/support/nfs/xlog.c
@@ -0,0 +1,189 @@
+/*
+ * support/nfs/xlog.c
+ *
+ * This module handles the logging of requests.
+ *
+ * TODO: Merge the two "XXX_log() calls.
+ *
+ * Authors: Donald J. Becker, <becker@super.org>
+ * Rick Sladkey, <jrs@world.std.com>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Olaf Kirch, <okir@monad.swb.de>
+ *
+ * This software maybe be used for any purpose provided
+ * the above copyright notice is retained. It is supplied
+ * as is, with no warranty expressed or implied.
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <syslog.h>
+#include "nfslib.h"
+
+#undef VERBOSE_PRINTF
+
+static int foreground = 1; /* not a daemon initially */
+static int logging = 0; /* enable/disable DEBUG logs */
+static int logmask = 0; /* What will be logged */
+static char log_name[256]; /* name of this program */
+static int log_pid = -1; /* PID of this program */
+static FILE *log_fp = (FILE *)NULL; /* fp for the log file */
+
+static void xlog_toggle(int sig);
+static struct xlog_debugfac debugnames[] = {
+ { "general", D_GENERAL, },
+ { "call", D_CALL, },
+ { "auth", D_AUTH, },
+ { "parse", D_PARSE, },
+ { "all", D_ALL, },
+ { NULL, 0, },
+};
+
+void
+xlog_open(char *progname)
+{
+ openlog(progname, LOG_PID, LOG_DAEMON);
+ if (foreground) {
+ log_fp = stderr;
+ if (log_fp != NULL)
+ setbuf(log_fp, NULL);
+ }
+
+ strncpy(log_name, progname, sizeof (log_name) - 1);
+ log_name [sizeof (log_name) - 1] = '\0';
+ log_pid = getpid();
+
+ signal(SIGUSR1, xlog_toggle);
+ signal(SIGUSR2, xlog_toggle);
+}
+
+void
+xlog_background(void)
+{
+ foreground = 0;
+}
+
+static void
+xlog_toggle(int sig)
+{
+ unsigned int tmp, i;
+
+ if (sig == SIGUSR1) {
+ if ((logmask & D_ALL) && !logging) {
+ xlog(D_GENERAL, "turned on logging");
+ logging = 1;
+ return;
+ }
+ tmp = ~logmask;
+ logmask |= ((logmask & D_ALL) << 1) | D_GENERAL;
+ for (i = -1, tmp &= logmask; tmp; tmp >>= 1, i++)
+ if (tmp & 1)
+ xlog(D_GENERAL,
+ "turned on logging level %d", i);
+ } else {
+ xlog(D_GENERAL, "turned off logging");
+ logging = 0;
+ }
+ signal(sig, xlog_toggle);
+}
+
+void
+xlog_config(int fac, int on)
+{
+ if (on)
+ logmask |= fac;
+ else
+ logmask &= ~fac;
+ if (on)
+ logging = 1;
+}
+
+void
+xlog_sconfig(char *kind, int on)
+{
+ struct xlog_debugfac *tbl = debugnames;
+
+ while (tbl->df_name != NULL && strcasecmp(tbl->df_name, kind))
+ tbl++;
+ if (!tbl->df_name) {
+ xlog (L_WARNING, "Invalid debug facility: %s\n", kind);
+ return;
+ }
+ xlog_config(tbl->df_fac, on);
+}
+
+int
+xlog_enabled(int fac)
+{
+ return (logging && (fac & logmask));
+}
+
+
+/* Write something to the system logfile. */
+void
+xlog(int kind, const char *fmt, ...)
+{
+ char buff[1024];
+ va_list args;
+ int logged = 1, n;
+#ifdef VERBOSE_PRINTF
+ time_t now;
+ struct tm *tm;
+#endif
+
+ if (!(kind & (L_ALL)) && !(logging && (kind & logmask)))
+ return;
+
+ va_start(args, fmt);
+ vsnprintf(buff, sizeof (buff), fmt, args);
+ va_end(args);
+ buff[sizeof (buff) - 1] = 0;
+
+ if ((n = strlen(buff)) > 0 && buff[n-1] != '\n') {
+ buff[n++] = '\n'; buff[n++] = '\0';
+ }
+
+ switch (kind) {
+ case L_FATAL:
+ syslog(LOG_ERR, "%s", buff);
+ break;
+ case L_ERROR:
+ syslog(LOG_ERR, "%s", buff);
+ break;
+ case L_WARNING:
+ syslog(LOG_WARNING, "%s", buff);
+ break;
+ case L_NOTICE:
+ syslog(LOG_NOTICE, "%s", buff);
+ break;
+ default:
+ logged = 0;
+ break;
+ }
+ if (!logged || foreground) {
+ if (!logged && log_fp == NULL) {
+ syslog(LOG_DEBUG, "%s", buff);
+ } else if (log_fp != NULL) {
+#ifdef VERBOSE_PRINTF
+ time(&now);
+ tm = localtime(&now);
+ fprintf(log_fp, "%s[%d] %02d/%02d/%02d %02d:%02d %s\n",
+ log_name, log_pid,
+ tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_year, tm->tm_hour, tm->tm_min,
+ buff);
+#else
+ fprintf(log_fp, "%s: %s", log_name, buff);
+#endif
+ }
+ }
+ if (kind == L_FATAL)
+ exit(1);
+}
diff --git a/support/nfs/xmalloc.c b/support/nfs/xmalloc.c
new file mode 100644
index 0000000..9523afc
--- /dev/null
+++ b/support/nfs/xmalloc.c
@@ -0,0 +1,48 @@
+/*
+ * support/nfs/xmalloc.c
+ *
+ * malloc with NULL checking.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include "xmalloc.h"
+#include "xlog.h"
+
+void *
+xmalloc(size_t size)
+{
+ void *ptr;
+
+ if (!(ptr = malloc(size)))
+ xlog(L_FATAL, "malloc: out of memory");
+ return ptr;
+}
+
+void *
+xrealloc(void *ptr, size_t size)
+{
+ if (!(ptr = realloc(ptr, size)))
+ xlog(L_FATAL, "realloc: out of memory");
+ return ptr;
+}
+
+void
+xfree(void *ptr)
+{
+ free(ptr);
+}
+
+char *
+xstrdup(const char *str)
+{
+ char *ret;
+
+ if (!(ret = strdup(str)))
+ xlog(L_FATAL, "strdup: out of memory");
+ return ret;
+}
diff --git a/support/nfs/ypupdate_xdr.c b/support/nfs/ypupdate_xdr.c
new file mode 100644
index 0000000..9fe1098
--- /dev/null
+++ b/support/nfs/ypupdate_xdr.c
@@ -0,0 +1,29 @@
+/*
+ * support/nfs/ypupdate_xdr.c
+ *
+ * This file contains the XDR code for the ypupdate protocol.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <ypupdate.h>
+
+bool_t
+xdr_ypupdate_args(XDR *xdrs, ypupdate_args *objp)
+{
+ return xdr_string(xdrs, &objp->mapname, MAXMAPNAMELEN) &&
+ xdr_bytes(xdrs, &objp->key.yp_buf_val,
+ &objp->key.yp_buf_len, MAXYPDATALEN) &&
+ xdr_bytes(xdrs, &objp->datum.yp_buf_val,
+ &objp->datum.yp_buf_len, MAXYPDATALEN);
+}
+
+bool_t
+xdr_ypdelete_args(XDR *xdrs, ypdelete_args *objp)
+{
+ return xdr_string(xdrs, &objp->mapname, MAXMAPNAMELEN) &&
+ xdr_bytes(xdrs, &objp->key.yp_buf_val,
+ &objp->key.yp_buf_len, MAXYPDATALEN);
+}