summaryrefslogtreecommitdiffstats
path: root/contrib/amd/amq
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>1998-08-23 22:07:21 +0000
committerobrien <obrien@FreeBSD.org>1998-08-23 22:07:21 +0000
commit663d5a0f32ed8dfc091ffb6153161591ac6ba563 (patch)
tree60b090a6cbdb64326bb128ea49a231d08eb2680e /contrib/amd/amq
downloadFreeBSD-src-663d5a0f32ed8dfc091ffb6153161591ac6ba563.zip
FreeBSD-src-663d5a0f32ed8dfc091ffb6153161591ac6ba563.tar.gz
Virgin import of AMD (am-utils) v6.0a16
Diffstat (limited to 'contrib/amd/amq')
-rw-r--r--contrib/amd/amq/amq.8214
-rw-r--r--contrib/amd/amq/amq.c938
-rw-r--r--contrib/amd/amq/amq.h63
-rw-r--r--contrib/amd/amq/amq_clnt.c208
-rw-r--r--contrib/amd/amq/amq_xdr.c259
-rw-r--r--contrib/amd/amq/pawd.172
-rw-r--r--contrib/amd/amq/pawd.c296
7 files changed, 2050 insertions, 0 deletions
diff --git a/contrib/amd/amq/amq.8 b/contrib/amd/amq/amq.8
new file mode 100644
index 0000000..4084cdb
--- /dev/null
+++ b/contrib/amd/amq/amq.8
@@ -0,0 +1,214 @@
+.\"
+.\" Copyright (c) 1997-1998 Erez Zadok
+.\" Copyright (c) 1990 Jan-Simon Pendry
+.\" Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+.\" Copyright (c) 1990 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Jan-Simon Pendry at Imperial College, London.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgment:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" %W% (Berkeley) %G%
+.\"
+.\" $Id: amq.8,v 5.2.2.1 1992/02/09 15:11:15 jsp beta $
+.\"
+.TH AMQ 8 "25 April 1989"
+.SH NAME
+amq \- automounter query tool
+.SH SYNOPSIS
+.B amq
+[
+.BI \-fmpsuvTU
+] [
+.BI \-h " hostname"
+] [
+.BI \-l " log_file"
+] [
+.BI \-x " log_options"
+] [
+.BI \-D " debug_options"
+] [
+.BI \-M " mountmap entry"
+] [
+.BI \-P " program_number"
+] [
+.I directory
+] .\|.\|.
+.SH DESCRIPTION
+.B Amq
+provides a simple way of determining the current state of
+.B amd
+program.
+Communication is by
+.SM RPC.
+Three modes of operation are supported by the current protocol. By default
+a list of mount points and auto-mounted filesystems is output. An
+alternative host can be specified using the
+.I \-h
+option.
+.LP
+If
+.I directory
+names are given, as output by default, then per-filesystem
+information is displayed.
+.SH OPTIONS
+
+.TP
+.B \-f
+Ask the automounter to flush the internal caches.
+
+.TP
+.BI \-h " hostname"
+Specify an alternate host to query. By default the local host is used. In
+an
+.SM HP-UX
+cluster, the root server is queried by default, since that is the system on
+which the automounter is normally run.
+
+.TP
+.BI \-l " log_file"
+Tell amd to use
+.I log_file
+as the log file name. For security reasons, this must be the same log file
+which amd used when started. This option is therefore only useful to
+refresh amd's open file handle on the log file, so that it can be rotated
+and compressed via daily cron jobs.
+
+.TP
+.B \-m
+Ask the automounter to provide a list of mounted filesystems, including the
+number of references to each filesystem and any error which occurred while
+mounting.
+
+.TP
+.B \-p
+Return the process ID of the remote or locally running amd. Useful when you
+need to send a signal to the local amd process, and would rather not have to
+search through the process table. This option is used in the
+.I ctl-amd
+script.
+
+.TP
+.B \-s
+Ask the automounter to provide system-wide mount statistics.
+
+.TP
+.B \-u
+Ask the automounter to unmount the filesystems named in
+.I directory
+instead of providing
+information about them. Unmounts are requested, not forced. They merely
+cause the mounted filesystem to timeout, which will be picked up by
+.BR amd 's
+main scheduler thus causing the normal timeout action to be taken.
+
+.TP
+.B \-v
+Ask the automounter for its version information. This is a subset of the
+information output by
+.BR amd 's
+.I -v
+option.
+
+.TP
+.BI \-x " log_options"
+Ask the automounter to use the logging options specified in
+.I log_options
+from now on.
+
+.TP
+.BI \-D " log_options"
+Ask the automounter to use the debugging options specified in
+.I debug_options
+from now on.
+
+.TP
+.BI \-M " map_ent"
+Pass a mount map entry to
+.B amd
+and wait for it to be evaluated, possible causing a mount. This option is
+highly insecure. By default, amd and amq do not support it. You have to
+configure am-utils with
+.I \-\-enable\-amq\-mount
+to enable this option.
+
+.TP
+.BI \-P " program_number"
+Contact an alternate running amd that had registered itself on a different
+RPC
+.I program_number
+and apply all other operations to that instance of the automounter. This is
+useful when you run multiple copies of amd, and need to manage each
+one separately. If not specified, amq will use the default program number
+for amd, 300019. For security reasons, the only alternate program numbers
+amd can use range from 300019 to 300029, inclusive.
+
+.TP
+.B \-T
+Contact
+.B amd
+using the TCP transport only. Normally
+.B amq
+will try TCP, and if that failed, will try UDP.
+
+.TP
+.B \-U
+Contact
+.B amd
+using UDP (connectionless) transport only. Normally
+.B amq
+will try TCP, and if that failed, will try UDP.
+
+.SH FILES
+.PD 0
+.TP 20
+.B amq.x
+.SM RPC
+protocol description.
+.SH CAVEATS
+.B Amq
+uses a Sun registered
+.SM RPC
+program number (300019 decimal) which may not
+be in the /etc/rpc database.
+.SH "SEE ALSO"
+.BR amd (8),
+.BR ctl-amd (8),
+.BR amd.conf (5).
+.SH AUTHORS
+Jan-Simon Pendry <jsp@doc.ic.ac.uk>, Department of Computing, Imperial College, London, UK.
+.P
+Erez Zadok <ezk@cs.columbia.edu>, Department of Computer Science, Columbia
+University, New York, USA.
+.P
+Other authors and contributors to am-utils are listed in the
+.B AUTHORS
+file distributed with am-utils.
diff --git a/contrib/amd/amq/amq.c b/contrib/amd/amq/amq.c
new file mode 100644
index 0000000..7fba9b1
--- /dev/null
+++ b/contrib/amd/amq/amq.c
@@ -0,0 +1,938 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: amq.c,v 5.2.2.1 1992/02/09 15:09:16 jsp beta $
+ *
+ */
+
+/*
+ * Automounter query tool
+ */
+
+#ifndef lint
+char copyright[] = "\
+@(#)Copyright (c) 1997-1998 Erez Zadok\n\
+@(#)Copyright (c) 1990 Jan-Simon Pendry\n\
+@(#)Copyright (c) 1990 Imperial College of Science, Technology & Medicine\n\
+@(#)Copyright (c) 1990 The Regents of the University of California.\n\
+@(#)All rights reserved.\n";
+#if __GNUC__ < 2
+static char rcsid[] = "$Id: amq.c,v 6.0 1997-1998/01/01 15:09:16 ezk $";
+static char sccsid[] = "%W% (Berkeley) %G%";
+#endif /* __GNUC__ < 2 */
+#endif /* not lint */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amq.h>
+
+/* locals */
+char *progname;
+static int flush_flag;
+static int minfo_flag;
+static int getpid_flag;
+static int unmount_flag;
+static int stats_flag;
+static int getvers_flag;
+static int amd_program_number = AMQ_PROGRAM;
+static int use_tcp_flag, use_udp_flag;
+static char *debug_opts;
+static char *amq_logfile;
+static char *mount_map;
+static char *xlog_optstr;
+static char localhost[] = "localhost";
+static char *def_server = localhost;
+
+/* externals */
+extern int optind;
+extern char *optarg;
+
+/* forward decalrations */
+#ifdef HAVE_TRANSPORT_TYPE_TLI
+static CLIENT *get_secure_amd_client(char *host, struct timeval *tv, int *sock);
+static int amq_bind_resv_port(int td, u_short *pp);
+#else /* not HAVE_TRANSPORT_TYPE_TLI */
+static int privsock(int ty);
+#endif /* not HAVE_TRANSPORT_TYPE_TLI */
+
+/* dummy variables */
+char hostname[MAXHOSTNAMELEN];
+int orig_umask, foreground, debug_flags;
+pid_t mypid;
+serv_state amd_state;
+
+/* structures */
+enum show_opt {
+ Full, Stats, Calc, Short, ShowDone
+};
+
+
+/*
+ * If (e) is Calc then just calculate the sizes
+ * Otherwise display the mount node on stdout
+ */
+static void
+show_mti(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *twid)
+{
+ switch (e) {
+ case Calc:
+ {
+ int mw = strlen(mt->mt_mountinfo);
+ int dw = strlen(mt->mt_directory);
+ int tw = strlen(mt->mt_type);
+ if (mw > *mwid)
+ *mwid = mw;
+ if (dw > *dwid)
+ *dwid = dw;
+ if (tw > *twid)
+ *twid = tw;
+ }
+ break;
+
+ case Full:
+ {
+ struct tm *tp = localtime((time_t *) &mt->mt_mounttime);
+ printf("%-*.*s %-*.*s %-*.*s %s\n\t%-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%02d %02d:%02d:%02d\n",
+ *dwid, *dwid,
+ *mt->mt_directory ? mt->mt_directory : "/", /* XXX */
+ *twid, *twid,
+ mt->mt_type,
+ *mwid, *mwid,
+ mt->mt_mountinfo,
+ mt->mt_mountpoint,
+
+ mt->mt_mountuid,
+ mt->mt_getattr,
+ mt->mt_lookup,
+ mt->mt_readdir,
+ mt->mt_readlink,
+ mt->mt_statfs,
+
+ tp->tm_year > 99 ? tp->tm_year - 100 : tp->tm_year,
+ tp->tm_mon + 1, tp->tm_mday,
+ tp->tm_hour, tp->tm_min, tp->tm_sec);
+ }
+ break;
+
+ case Stats:
+ {
+ struct tm *tp = localtime((time_t *) &mt->mt_mounttime);
+ printf("%-*.*s %-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%02d %02d:%02d:%02d\n",
+ *dwid, *dwid,
+ *mt->mt_directory ? mt->mt_directory : "/", /* XXX */
+
+ mt->mt_mountuid,
+ mt->mt_getattr,
+ mt->mt_lookup,
+ mt->mt_readdir,
+ mt->mt_readlink,
+ mt->mt_statfs,
+
+ tp->tm_year > 99 ? tp->tm_year - 100 : tp->tm_year,
+ tp->tm_mon + 1, tp->tm_mday,
+ tp->tm_hour, tp->tm_min, tp->tm_sec);
+ }
+ break;
+
+ case Short:
+ {
+ printf("%-*.*s %-*.*s %-*.*s %s\n",
+ *dwid, *dwid,
+ *mt->mt_directory ? mt->mt_directory : "/",
+ *twid, *twid,
+ mt->mt_type,
+ *mwid, *mwid,
+ mt->mt_mountinfo,
+ mt->mt_mountpoint);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*
+ * Display a mount tree.
+ */
+static void
+show_mt(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *pwid)
+{
+ while (mt) {
+ show_mti(mt, e, mwid, dwid, pwid);
+ show_mt(mt->mt_next, e, mwid, dwid, pwid);
+ mt = mt->mt_child;
+ }
+}
+
+static void
+show_mi(amq_mount_info_list *ml, enum show_opt e, int *mwid, int *dwid, int *twid)
+{
+ int i;
+
+ switch (e) {
+
+ case Calc:
+ {
+ for (i = 0; i < ml->amq_mount_info_list_len; i++) {
+ amq_mount_info *mi = &ml->amq_mount_info_list_val[i];
+ int mw = strlen(mi->mi_mountinfo);
+ int dw = strlen(mi->mi_mountpt);
+ int tw = strlen(mi->mi_type);
+ if (mw > *mwid)
+ *mwid = mw;
+ if (dw > *dwid)
+ *dwid = dw;
+ if (tw > *twid)
+ *twid = tw;
+ }
+ }
+ break;
+
+ case Full:
+ {
+ for (i = 0; i < ml->amq_mount_info_list_len; i++) {
+ amq_mount_info *mi = &ml->amq_mount_info_list_val[i];
+ printf("%-*.*s %-*.*s %-*.*s %-3d %s is %s",
+ *mwid, *mwid, mi->mi_mountinfo,
+ *dwid, *dwid, mi->mi_mountpt,
+ *twid, *twid, mi->mi_type,
+ mi->mi_refc, mi->mi_fserver,
+ mi->mi_up > 0 ? "up" :
+ mi->mi_up < 0 ? "starting" : "down");
+ if (mi->mi_error > 0) {
+ extern int sys_nerr;
+ if (mi->mi_error < sys_nerr)
+ printf(" (%s)", sys_errlist[mi->mi_error]);
+ else
+ printf(" (Error %d)", mi->mi_error);
+ } else if (mi->mi_error < 0) {
+ fputs(" (in progress)", stdout);
+ }
+ fputc('\n', stdout);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+/*
+ * Display general mount statistics
+ */
+static void
+show_ms(amq_mount_stats *ms)
+{
+ printf("\
+requests stale mount mount unmount\n\
+deferred fhandles ok failed failed\n\
+%-9d %-9d %-9d %-9d %-9d\n",
+ ms->as_drops, ms->as_stale, ms->as_mok, ms->as_merr, ms->as_uerr);
+}
+
+
+#if defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT)
+static char *
+cluster_server(void)
+{
+ struct cct_entry *cp;
+
+ if (cnodeid() == 0) {
+ /*
+ * Not clustered
+ */
+ return def_server;
+ }
+ while (cp = getccent())
+ if (cp->cnode_type == 'r')
+ return cp->cnode_name;
+
+ return def_server;
+}
+#endif /* defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) */
+
+
+/*
+ * MAIN
+ */
+int
+main(int argc, char *argv[])
+{
+ int opt_ch;
+ int errs = 0;
+ char *server;
+ struct sockaddr_in server_addr;
+ int s; /* to pass the Amd security check, we must use a priv port */
+ CLIENT *clnt = NULL;
+ struct hostent *hp;
+ int nodefault = 0;
+ struct timeval tv;
+#ifndef HAVE_TRANSPORT_TYPE_TLI
+ enum clnt_stat cs;
+#endif /* not HAVE_TRANSPORT_TYPE_TLI */
+
+
+ /*
+ * Compute program name
+ */
+ if (argv[0]) {
+ progname = strrchr(argv[0], '/');
+ if (progname && progname[1])
+ progname++;
+ else
+ progname = argv[0];
+ }
+ if (!progname)
+ progname = "amq";
+
+ /*
+ * Parse arguments
+ */
+ while ((opt_ch = getopt(argc, argv, "fh:l:msuvx:D:M:pP:TU")) != EOF)
+ switch (opt_ch) {
+ case 'f':
+ flush_flag = 1;
+ nodefault = 1;
+ break;
+
+ case 'h':
+ def_server = optarg;
+ break;
+
+ case 'l':
+ amq_logfile = optarg;
+ nodefault = 1;
+ break;
+
+ case 'm':
+ minfo_flag = 1;
+ nodefault = 1;
+ break;
+
+ case 'p':
+ getpid_flag = 1;
+ nodefault = 1;
+ break;
+
+ case 's':
+ stats_flag = 1;
+ nodefault = 1;
+ break;
+
+ case 'u':
+ unmount_flag = 1;
+ nodefault = 1;
+ break;
+
+ case 'v':
+ getvers_flag = 1;
+ nodefault = 1;
+ break;
+
+ case 'x':
+ xlog_optstr = optarg;
+ nodefault = 1;
+ break;
+
+ case 'D':
+ debug_opts = optarg;
+ nodefault = 1;
+ break;
+
+ case 'M':
+ mount_map = optarg;
+ nodefault = 1;
+ break;
+
+ case 'P':
+ amd_program_number = atoi(optarg);
+ break;
+
+ case 'T':
+ use_tcp_flag = 1;
+ break;
+
+ case 'U':
+ use_udp_flag = 1;
+ break;
+
+ default:
+ errs = 1;
+ break;
+ }
+
+ if (optind == argc) {
+ if (unmount_flag)
+ errs = 1;
+ }
+ if (errs) {
+ show_usage:
+ fprintf(stderr, "\
+Usage: %s [-h host] [[-f] [-m] [-p] [-v] [-s]] | [[-u] directory ...]]\n\
+\t[-l logfile|\"syslog\"] [-x log_flags] [-D dbg_opts] [-M mapent]\n\
+\t[-P prognum] [-T] [-U]\n", progname);
+ exit(1);
+ }
+
+ /* set use_udp and use_tcp flags both to on if none are defined */
+ if (!use_tcp_flag && !use_udp_flag)
+ use_tcp_flag = use_udp_flag = 1;
+
+#if defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT)
+ /*
+ * Figure out root server of cluster
+ */
+ if (def_server == localhost)
+ server = cluster_server();
+ else
+#endif /* defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) */
+ server = def_server;
+
+ /*
+ * Get address of server
+ */
+ if ((hp = gethostbyname(server)) == 0 && !STREQ(server, localhost)) {
+ fprintf(stderr, "%s: Can't get address of %s\n", progname, server);
+ exit(1);
+ }
+ memset(&server_addr, 0, sizeof server_addr);
+ server_addr.sin_family = AF_INET;
+ if (hp) {
+ memmove((voidp) &server_addr.sin_addr, (voidp) hp->h_addr,
+ sizeof(server_addr.sin_addr));
+ } else {
+ /* fake "localhost" */
+ server_addr.sin_addr.s_addr = htonl(0x7f000001);
+ }
+
+ /*
+ * Create RPC endpoint
+ */
+ tv.tv_sec = 5; /* 5 seconds for timeout or per retry */
+ tv.tv_usec = 0;
+
+#ifdef HAVE_TRANSPORT_TYPE_TLI
+ clnt = get_secure_amd_client(server, &tv, &s);
+ if (!clnt && use_tcp_flag) /* try tcp first */
+ clnt = clnt_create(server, amd_program_number, AMQ_VERSION, "tcp");
+ if (!clnt && use_udp_flag) { /* try udp next */
+ clnt = clnt_create(server, amd_program_number, AMQ_VERSION, "udp");
+ /* if ok, set timeout (valid for connectionless transports only) */
+ if (clnt)
+ clnt_control(clnt, CLSET_RETRY_TIMEOUT, (char *) &tv);
+ }
+#else /* not HAVE_TRANSPORT_TYPE_TLI */
+
+ /* first check if remote portmapper is up */
+ cs = pmap_ping(&server_addr);
+ if (cs == RPC_TIMEDOUT) {
+ fprintf(stderr, "%s: failed to contact portmapper on host \"%s\". %s\n",
+ progname, server, clnt_sperrno(cs));
+ exit(1);
+ }
+
+ /* portmapper exists: get remote amd info from it */
+ if (!clnt && use_tcp_flag) { /* try tcp first */
+ s = RPC_ANYSOCK;
+ clnt = clnttcp_create(&server_addr, amd_program_number,
+ AMQ_VERSION, &s, 0, 0);
+ }
+ if (!clnt && use_udp_flag) { /* try udp next */
+ /* XXX: do we need to close(s) ? */
+ s = privsock(SOCK_DGRAM);
+ clnt = clntudp_create(&server_addr, amd_program_number,
+ AMQ_VERSION, tv, &s);
+ }
+#endif /* not HAVE_TRANSPORT_TYPE_TLI */
+ if (!clnt) {
+ fprintf(stderr, "%s: ", progname);
+ clnt_pcreateerror(server);
+ exit(1);
+ }
+
+ /*
+ * Control debugging
+ */
+ if (debug_opts) {
+ int *rc;
+ amq_setopt opt;
+ opt.as_opt = AMOPT_DEBUG;
+ opt.as_str = debug_opts;
+ rc = amqproc_setopt_1(&opt, clnt);
+ if (rc && *rc < 0) {
+ fprintf(stderr, "%s: daemon not compiled for debug\n", progname);
+ errs = 1;
+ } else if (!rc || *rc > 0) {
+ fprintf(stderr, "%s: debug setting for \"%s\" failed\n", progname, debug_opts);
+ errs = 1;
+ }
+ }
+
+ /*
+ * Control logging
+ */
+ if (xlog_optstr) {
+ int *rc;
+ amq_setopt opt;
+ opt.as_opt = AMOPT_XLOG;
+ opt.as_str = xlog_optstr;
+ rc = amqproc_setopt_1(&opt, clnt);
+ if (!rc || *rc) {
+ fprintf(stderr, "%s: setting log level to \"%s\" failed\n", progname, xlog_optstr);
+ errs = 1;
+ }
+ }
+
+ /*
+ * Control log file
+ */
+ if (amq_logfile) {
+ int *rc;
+ amq_setopt opt;
+ opt.as_opt = AMOPT_LOGFILE;
+ opt.as_str = amq_logfile;
+ rc = amqproc_setopt_1(&opt, clnt);
+ if (!rc || *rc) {
+ fprintf(stderr, "%s: setting logfile to \"%s\" failed\n", progname, amq_logfile);
+ errs = 1;
+ }
+ }
+
+ /*
+ * Flush map cache
+ */
+ if (flush_flag) {
+ int *rc;
+ amq_setopt opt;
+ opt.as_opt = AMOPT_FLUSHMAPC;
+ opt.as_str = "";
+ rc = amqproc_setopt_1(&opt, clnt);
+ if (!rc || *rc) {
+ fprintf(stderr, "%s: amd on %s cannot flush the map cache\n", progname, server);
+ errs = 1;
+ }
+ }
+
+ /*
+ * Mount info
+ */
+ if (minfo_flag) {
+ int dummy;
+ amq_mount_info_list *ml = amqproc_getmntfs_1(&dummy, clnt);
+ if (ml) {
+ int mwid = 0, dwid = 0, twid = 0;
+ show_mi(ml, Calc, &mwid, &dwid, &twid);
+ mwid++;
+ dwid++;
+ twid++;
+ show_mi(ml, Full, &mwid, &dwid, &twid);
+
+ } else {
+ fprintf(stderr, "%s: amd on %s cannot provide mount info\n", progname, server);
+ }
+ }
+
+ /*
+ * Mount map
+ */
+ if (mount_map) {
+ int *rc;
+ do {
+ rc = amqproc_mount_1(&mount_map, clnt);
+ } while (rc && *rc < 0);
+ if (!rc || *rc > 0) {
+ if (rc)
+ errno = *rc;
+ else
+ errno = ETIMEDOUT;
+ fprintf(stderr, "%s: could not start new ", progname);
+ perror("autmount point");
+ }
+ }
+
+ /*
+ * Get Version
+ */
+ if (getvers_flag) {
+ amq_string *spp = amqproc_getvers_1((voidp) 0, clnt);
+ if (spp && *spp) {
+ fputs(*spp, stdout);
+ XFREE(*spp);
+ } else {
+ fprintf(stderr, "%s: failed to get version information\n", progname);
+ errs = 1;
+ }
+ }
+
+ /*
+ * Get PID of amd
+ */
+ if (getpid_flag) {
+ int *ip = amqproc_getpid_1((voidp) 0, clnt);
+ if (ip && *ip) {
+ printf("%d\n", *ip);
+ } else {
+ fprintf(stderr, "%s: failed to get PID of amd\n", progname);
+ errs = 1;
+ }
+ }
+
+ /*
+ * Apply required operation to all remaining arguments
+ */
+ if (optind < argc) {
+ do {
+ char *fs = argv[optind++];
+ if (unmount_flag) {
+ /*
+ * Unmount request
+ */
+ amqproc_umnt_1(&fs, clnt);
+ } else {
+ /*
+ * Stats request
+ */
+ amq_mount_tree_p *mtp = amqproc_mnttree_1(&fs, clnt);
+ if (mtp) {
+ amq_mount_tree *mt = *mtp;
+ if (mt) {
+ int mwid = 0, dwid = 0, twid = 0;
+ show_mt(mt, Calc, &mwid, &dwid, &twid);
+ mwid++;
+ dwid++, twid++;
+ printf("%-*.*s Uid Getattr Lookup RdDir RdLnk Statfs Mounted@\n",
+ dwid, dwid, "What");
+ show_mt(mt, Stats, &mwid, &dwid, &twid);
+ } else {
+ fprintf(stderr, "%s: %s not automounted\n", progname, fs);
+ }
+ xdr_pri_free((XDRPROC_T_TYPE) xdr_amq_mount_tree_p, (caddr_t) mtp);
+ } else {
+ fprintf(stderr, "%s: ", progname);
+ clnt_perror(clnt, server);
+ errs = 1;
+ }
+ }
+ } while (optind < argc);
+
+ } else if (unmount_flag) {
+ goto show_usage;
+
+ } else if (stats_flag) {
+ amq_mount_stats *ms = amqproc_stats_1((voidp) 0, clnt);
+ if (ms) {
+ show_ms(ms);
+ } else {
+ fprintf(stderr, "%s: ", progname);
+ clnt_perror(clnt, server);
+ errs = 1;
+ }
+
+ } else if (!nodefault) {
+ amq_mount_tree_list *mlp = amqproc_export_1((voidp) 0, clnt);
+ if (mlp) {
+ enum show_opt e = Calc;
+ int mwid = 0, dwid = 0, pwid = 0;
+ while (e != ShowDone) {
+ int i;
+ for (i = 0; i < mlp->amq_mount_tree_list_len; i++) {
+ show_mt(mlp->amq_mount_tree_list_val[i],
+ e, &mwid, &dwid, &pwid);
+ }
+ mwid++;
+ dwid++, pwid++;
+ if (e == Calc)
+ e = Short;
+ else if (e == Short)
+ e = ShowDone;
+ }
+
+ } else {
+ fprintf(stderr, "%s: ", progname);
+ clnt_perror(clnt, server);
+ errs = 1;
+ }
+ }
+ exit(errs);
+ return errs; /* should never reache here */
+}
+
+
+#ifdef HAVE_TRANSPORT_TYPE_TLI
+
+/*
+ * How to bind to reserved ports.
+ * TLI handle (socket) and port version.
+ */
+/* defined here so that it does not have to resolve it with libamu.a */
+static int
+amq_bind_resv_port(int td, u_short *pp)
+{
+ int rc = -1, port;
+ struct t_bind *treq, *tret;
+ struct sockaddr_in *sin;
+
+ treq = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR);
+ if (!treq) {
+ plog(XLOG_ERROR, "t_alloc 1");
+ return -1;
+ }
+ tret = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR);
+ if (!tret) {
+ t_free((char *) treq, T_BIND);
+ plog(XLOG_ERROR, "t_alloc 2");
+ return -1;
+ }
+ memset((char *) treq->addr.buf, 0, treq->addr.len);
+ sin = (struct sockaddr_in *) treq->addr.buf;
+ sin->sin_family = AF_INET;
+ treq->qlen = 0;
+ treq->addr.len = treq->addr.maxlen;
+ errno = EADDRINUSE;
+ port = IPPORT_RESERVED;
+
+ do {
+ --port;
+ sin->sin_port = htons(port);
+ rc = t_bind(td, treq, tret);
+ if (rc < 0) {
+ } else {
+ if (memcmp(treq->addr.buf, tret->addr.buf, tret->addr.len) == 0)
+ break;
+ else
+ t_unbind(td);
+ }
+ } while ((rc < 0 || errno == EADDRINUSE) && (int) port > IPPORT_RESERVED / 2);
+
+ if (pp) {
+ if (rc == 0)
+ *pp = port;
+ else
+ plog(XLOG_ERROR, "could not t_bind to any reserved port");
+ }
+ t_free((char *) tret, T_BIND);
+ t_free((char *) treq, T_BIND);
+ return rc;
+}
+
+
+/*
+ * Create a secure rpc client attached to the amd daemon.
+ */
+static CLIENT *
+get_secure_amd_client(char *host, struct timeval *tv, int *sock)
+{
+ CLIENT *client;
+ struct netbuf nb;
+ struct netconfig *nc, *pm_nc;
+ struct sockaddr_in sin;
+
+
+ nb.maxlen = sizeof(sin);
+ nb.buf = (char *) &sin;
+
+ /*
+ * Ensure that remote portmapper is alive
+ * (must use connectionless netconfig).
+ */
+ if ((pm_nc = getnetconfigent(NC_UDP)) != NULL) {
+ enum clnt_stat cs;
+
+ cs = rpcb_rmtcall(pm_nc,
+ host,
+ amd_program_number,
+ AMQ_VERSION,
+ AMQPROC_NULL,
+ (XDRPROC_T_TYPE) xdr_void,
+ NULL,
+ (XDRPROC_T_TYPE) xdr_void,
+ NULL,
+ *tv,
+ NULL);
+ if (cs == RPC_TIMEDOUT) {
+ fprintf(stderr, "%s: failed to contact portmapper on host \"%s\". %s\n",
+ progname, host, clnt_sperrno(cs));
+ exit(1);
+ }
+ }
+
+ /*
+ * First transport type to try: TCP
+ */
+ if (use_tcp_flag) {
+ /* Find amd address on TCP */
+ nc = getnetconfigent(NC_TCP);
+ if (!nc) {
+ fprintf(stderr, "getnetconfig for tcp failed: %s\n", nc_sperror());
+ goto tryudp;
+ }
+
+ if (!rpcb_getaddr(amd_program_number, AMQ_VERSION, nc, &nb, host)) {
+ /*
+ * don't pring error messages here, since amd might legitimately
+ * serve udp only
+ */
+ goto tryudp;
+ }
+ /* Create priviledged TCP socket */
+ *sock = t_open(nc->nc_device, O_RDWR, 0);
+
+ if (*sock < 0) {
+ fprintf(stderr, "t_open %s: %m\n", nc->nc_device);
+ goto tryudp;
+ }
+ if (amq_bind_resv_port(*sock, (u_short *) 0) < 0)
+ goto tryudp;
+
+ client = clnt_vc_create(*sock, &nb, amd_program_number, AMQ_VERSION, 0, 0);
+ if (!client) {
+ fprintf(stderr, "clnt_vc_create failed");
+ t_close(*sock);
+ goto tryudp;
+ }
+ /* tcp succeeded */
+ return client;
+ }
+
+tryudp:
+ /*
+ * TCP failed so try UDP
+ */
+ if (use_udp_flag) {
+ /* find amd address on UDP */
+ nc = getnetconfigent(NC_UDP);
+ if (!nc) {
+ fprintf(stderr, "getnetconfig for udp failed: %s\n", nc_sperror());
+ return NULL;
+ }
+ if (!rpcb_getaddr(amd_program_number, AMQ_VERSION, nc, &nb, host)) {
+ fprintf(stderr, "%s\n",
+ clnt_spcreateerror("couldn't get amd address on udp"));
+ return NULL;
+ }
+ /* create priviledged UDP socket */
+ *sock = t_open(nc->nc_device, O_RDWR, 0);
+
+ if (*sock < 0) {
+ fprintf(stderr, "t_open %s: %m\n", nc->nc_device);
+ return NULL; /* neither tcp not udp succeeded */
+ }
+ if (amq_bind_resv_port(*sock, (u_short *) 0) < 0)
+ return NULL;
+
+ client = clnt_dg_create(*sock, &nb, amd_program_number, AMQ_VERSION, 0, 0);
+ if (!client) {
+ fprintf(stderr, "clnt_dg_create failed\n");
+ t_close(*sock);
+ return NULL; /* neither tcp not udp succeeded */
+ }
+ if (clnt_control(client, CLSET_RETRY_TIMEOUT, (char *) tv) == FALSE) {
+ fprintf(stderr, "clnt_control CLSET_RETRY_TIMEOUT for udp failed\n");
+ clnt_destroy(client);
+ return NULL; /* neither tcp not udp succeeded */
+ }
+ /* udp succeeded */
+ return client;
+ }
+
+ /* should never get here */
+ return NULL;
+}
+
+#else /* not HAVE_TRANSPORT_TYPE_TLI */
+
+/*
+ * inetresport creates a datagram socket and attempts to bind it to a
+ * secure port.
+ * returns: The bound socket, or -1 to indicate an error.
+ */
+static int
+inetresport(int ty)
+{
+ int alport;
+ struct sockaddr_in addr;
+ int fd;
+
+ /* Use internet address family */
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = INADDR_ANY;
+ if ((fd = socket(AF_INET, ty, 0)) < 0)
+ return -1;
+
+ for (alport = IPPORT_RESERVED - 1; alport > IPPORT_RESERVED / 2 + 1; alport--) {
+ addr.sin_port = htons((u_short) alport);
+ if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) >= 0)
+ return fd;
+ if (errno != EADDRINUSE) {
+ close(fd);
+ return -1;
+ }
+ }
+ close(fd);
+ errno = EAGAIN;
+ return -1;
+}
+
+
+/*
+ * Privsock() calls inetresport() to attempt to bind a socket to a secure
+ * port. If inetresport() fails, privsock returns a magic socket number which
+ * indicates to RPC that it should make its own socket.
+ * returns: A privileged socket # or RPC_ANYSOCK.
+ */
+static int
+privsock(int ty)
+{
+ int sock = inetresport(ty);
+
+ if (sock < 0) {
+ errno = 0;
+ /* Couldn't get a secure port, let RPC make an insecure one */
+ sock = RPC_ANYSOCK;
+ }
+ return sock;
+}
+
+#endif /* not HAVE_TRANSPORT_TYPE_TLI */
diff --git a/contrib/amd/amq/amq.h b/contrib/amd/amq/amq.h
new file mode 100644
index 0000000..98f7383
--- /dev/null
+++ b/contrib/amd/amq/amq.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: amq.h,v 1.1 1996/01/13 23:23:39 ezk Exp ezk $
+ *
+ */
+
+#ifndef _AMQ_H
+#define _AMQ_H
+
+/*
+ * external definitions for building amq
+ */
+
+extern voidp amqproc_null_1(voidp argp, CLIENT *rqstp);
+extern amq_mount_tree_p *amqproc_mnttree_1(amq_string *argp, CLIENT *rqstp);
+extern voidp amqproc_umnt_1(amq_string *argp, CLIENT *rqstp);
+extern amq_mount_stats *amqproc_stats_1(voidp argp, CLIENT *rqstp);
+extern amq_mount_tree_list *amqproc_export_1(voidp argp, CLIENT *rqstp);
+extern int *amqproc_setopt_1(amq_setopt *argp, CLIENT *rqstp);
+extern amq_mount_info_list *amqproc_getmntfs_1(voidp argp, CLIENT *rqstp);
+extern int *amqproc_mount_1(voidp argp, CLIENT *rqstp);
+extern amq_string *amqproc_getvers_1(voidp argp, CLIENT *rqstp);
+extern int *amqproc_getpid_1(voidp argp, CLIENT *rqstp);
+
+#endif /* not _AMQ_H */
diff --git a/contrib/amd/amq/amq_clnt.c b/contrib/amd/amq/amq_clnt.c
new file mode 100644
index 0000000..7220cec
--- /dev/null
+++ b/contrib/amd/amq/amq_clnt.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: amq_clnt.c,v 5.2.2.1 1992/02/09 15:09:24 jsp beta $
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amq.h>
+
+
+static struct timeval TIMEOUT = {ALLOWED_MOUNT_TIME, 0};
+
+
+voidp
+amqproc_null_1(voidp argp, CLIENT *clnt)
+{
+ static char res;
+
+ memset((char *) &res, 0, sizeof(res));
+ if (clnt_call(clnt, AMQPROC_NULL,
+ (XDRPROC_T_TYPE) xdr_void, argp,
+ (XDRPROC_T_TYPE) xdr_void, &res, TIMEOUT)
+ != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return ((voidp) &res);
+}
+
+
+amq_mount_tree_p *
+amqproc_mnttree_1(amq_string *argp, CLIENT *clnt)
+{
+ static amq_mount_tree_p res;
+
+ memset((char *) &res, 0, sizeof(res));
+ if (clnt_call(clnt, AMQPROC_MNTTREE,
+ (XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) argp,
+ (XDRPROC_T_TYPE) xdr_amq_mount_tree_p, (SVC_IN_ARG_TYPE) & res,
+ TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+
+voidp
+amqproc_umnt_1(amq_string *argp, CLIENT *clnt)
+{
+ static char res;
+
+ memset((char *) &res, 0, sizeof(res));
+ if (clnt_call(clnt, AMQPROC_UMNT,
+ (XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) argp,
+ (XDRPROC_T_TYPE) xdr_void, &res,
+ TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return ((voidp) &res);
+}
+
+
+amq_mount_stats *
+amqproc_stats_1(voidp argp, CLIENT *clnt)
+{
+ static amq_mount_stats res;
+
+ memset((char *) &res, 0, sizeof(res));
+ if (clnt_call(clnt, AMQPROC_STATS,
+ (XDRPROC_T_TYPE) xdr_void, argp,
+ (XDRPROC_T_TYPE) xdr_amq_mount_stats,
+ (SVC_IN_ARG_TYPE) & res,
+ TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+
+amq_mount_tree_list *
+amqproc_export_1(voidp argp, CLIENT *clnt)
+{
+ static amq_mount_tree_list res;
+
+ memset((char *) &res, 0, sizeof(res));
+ if (clnt_call(clnt, AMQPROC_EXPORT,
+ (XDRPROC_T_TYPE) xdr_void, argp,
+ (XDRPROC_T_TYPE) xdr_amq_mount_tree_list,
+ (SVC_IN_ARG_TYPE) & res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+
+int *
+amqproc_setopt_1(amq_setopt *argp, CLIENT *clnt)
+{
+ static int res;
+
+ memset((char *) &res, 0, sizeof(res));
+ if (clnt_call(clnt, AMQPROC_SETOPT, (XDRPROC_T_TYPE) xdr_amq_setopt,
+ (SVC_IN_ARG_TYPE) argp, (XDRPROC_T_TYPE) xdr_int,
+ (SVC_IN_ARG_TYPE) & res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+
+amq_mount_info_list *
+amqproc_getmntfs_1(voidp argp, CLIENT *clnt)
+{
+ static amq_mount_info_list res;
+
+ memset((char *) &res, 0, sizeof(res));
+ if (clnt_call(clnt, AMQPROC_GETMNTFS, (XDRPROC_T_TYPE) xdr_void, argp,
+ (XDRPROC_T_TYPE) xdr_amq_mount_info_list,
+ (SVC_IN_ARG_TYPE) & res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+
+int *
+amqproc_mount_1(voidp argp, CLIENT *clnt)
+{
+ static int res;
+
+ memset((char *) &res, 0, sizeof(res));
+ if (clnt_call(clnt, AMQPROC_MOUNT, (XDRPROC_T_TYPE) xdr_amq_string, argp,
+ (XDRPROC_T_TYPE) xdr_int, (SVC_IN_ARG_TYPE) & res,
+ TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+
+amq_string *
+amqproc_getvers_1(voidp argp, CLIENT *clnt)
+{
+ static amq_string res;
+
+ memset((char *) &res, 0, sizeof(res));
+ if (clnt_call(clnt, AMQPROC_GETVERS, (XDRPROC_T_TYPE) xdr_void, argp,
+ (XDRPROC_T_TYPE) xdr_amq_string, (SVC_IN_ARG_TYPE) & res,
+ TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+
+int *
+amqproc_getpid_1(voidp argp, CLIENT *clnt)
+{
+ static int res;
+
+ memset((char *) &res, 0, sizeof(res));
+ if (clnt_call(clnt, AMQPROC_GETPID, (XDRPROC_T_TYPE) xdr_void, argp,
+ (XDRPROC_T_TYPE) xdr_int, (SVC_IN_ARG_TYPE) & res,
+ TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
diff --git a/contrib/amd/amq/amq_xdr.c b/contrib/amd/amq/amq_xdr.c
new file mode 100644
index 0000000..79a7294
--- /dev/null
+++ b/contrib/amd/amq/amq_xdr.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: amq_xdr.c,v 5.2.2.1 1992/02/09 15:09:23 jsp beta $
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amq.h>
+
+
+bool_t
+xdr_time_type(XDR *xdrs, time_type *objp)
+{
+ if (!xdr_long(xdrs, (long *) objp)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+bool_t
+xdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp)
+{
+
+ if (!xdr_amq_string(xdrs, &objp->mt_mountinfo)) {
+ return (FALSE);
+ }
+
+ if (!xdr_amq_string(xdrs, &objp->mt_directory)) {
+ return (FALSE);
+ }
+
+ if (!xdr_amq_string(xdrs, &objp->mt_mountpoint)) {
+ return (FALSE);
+ }
+
+ if (!xdr_amq_string(xdrs, &objp->mt_type)) {
+ return (FALSE);
+ }
+
+ if (!xdr_time_type(xdrs, &objp->mt_mounttime)) {
+ return (FALSE);
+ }
+
+ if (!xdr_u_short(xdrs, &objp->mt_mountuid)) {
+ return (FALSE);
+ }
+
+ if (!xdr_int(xdrs, &objp->mt_getattr)) {
+ return (FALSE);
+ }
+
+ if (!xdr_int(xdrs, &objp->mt_lookup)) {
+ return (FALSE);
+ }
+
+ if (!xdr_int(xdrs, &objp->mt_readdir)) {
+ return (FALSE);
+ }
+
+ if (!xdr_int(xdrs, &objp->mt_readlink)) {
+ return (FALSE);
+ }
+
+ if (!xdr_int(xdrs, &objp->mt_statfs)) {
+ return (FALSE);
+ }
+
+ if (!xdr_pointer(xdrs, (char **) &objp->mt_next, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
+ return (FALSE);
+ }
+
+ if (!xdr_pointer(xdrs, (char **) &objp->mt_child, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+
+bool_t
+xdr_amq_mount_tree_p(XDR *xdrs, amq_mount_tree_p *objp)
+{
+ if (!xdr_pointer(xdrs, (char **) objp, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+bool_t
+xdr_amq_mount_info(XDR *xdrs, amq_mount_info *objp)
+{
+
+ if (!xdr_amq_string(xdrs, &objp->mi_type)) {
+ return (FALSE);
+ }
+
+ if (!xdr_amq_string(xdrs, &objp->mi_mountpt)) {
+ return (FALSE);
+ }
+
+ if (!xdr_amq_string(xdrs, &objp->mi_mountinfo)) {
+ return (FALSE);
+ }
+
+ if (!xdr_amq_string(xdrs, &objp->mi_fserver)) {
+ return (FALSE);
+ }
+
+ if (!xdr_int(xdrs, &objp->mi_error)) {
+ return (FALSE);
+ }
+
+ if (!xdr_int(xdrs, &objp->mi_refc)) {
+ return (FALSE);
+ }
+
+ if (!xdr_int(xdrs, &objp->mi_up)) {
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+
+bool_t
+xdr_amq_mount_info_list(XDR *xdrs, amq_mount_info_list *objp)
+{
+ if (!xdr_array(xdrs,
+ (char **) &objp->amq_mount_info_list_val,
+ (u_int *) &objp->amq_mount_info_list_len,
+ ~0,
+ sizeof(amq_mount_info),
+ (XDRPROC_T_TYPE) xdr_amq_mount_info)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+bool_t
+xdr_amq_mount_tree_list(XDR *xdrs, amq_mount_tree_list *objp)
+{
+ if (!xdr_array(xdrs,
+ (char **) &objp->amq_mount_tree_list_val,
+ (u_int *) &objp->amq_mount_tree_list_len,
+ ~0,
+ sizeof(amq_mount_tree_p),
+ (XDRPROC_T_TYPE) xdr_amq_mount_tree_p)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+bool_t
+xdr_amq_mount_stats(XDR *xdrs, amq_mount_stats *objp)
+{
+
+ if (!xdr_int(xdrs, &objp->as_drops)) {
+ return (FALSE);
+ }
+
+ if (!xdr_int(xdrs, &objp->as_stale)) {
+ return (FALSE);
+ }
+
+ if (!xdr_int(xdrs, &objp->as_mok)) {
+ return (FALSE);
+ }
+
+ if (!xdr_int(xdrs, &objp->as_merr)) {
+ return (FALSE);
+ }
+
+ if (!xdr_int(xdrs, &objp->as_uerr)) {
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+
+bool_t
+xdr_amq_opt(XDR *xdrs, amq_opt *objp)
+{
+ if (!xdr_enum(xdrs, (enum_t *) objp)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+bool_t
+xdr_amq_setopt(XDR *xdrs, amq_setopt *objp)
+{
+
+ if (!xdr_amq_opt(xdrs, &objp->as_opt)) {
+ return (FALSE);
+ }
+
+ if (!xdr_amq_string(xdrs, &objp->as_str)) {
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+
+bool_t
+xdr_pri_free(XDRPROC_T_TYPE xdr_args, caddr_t args_ptr)
+{
+ XDR xdr;
+
+ xdr.x_op = XDR_FREE;
+ return ((*xdr_args) (&xdr, (caddr_t *) args_ptr));
+}
diff --git a/contrib/amd/amq/pawd.1 b/contrib/amd/amq/pawd.1
new file mode 100644
index 0000000..d047372
--- /dev/null
+++ b/contrib/amd/amq/pawd.1
@@ -0,0 +1,72 @@
+.\"
+.\" Copyright (c) 1997-1998 Erez Zadok
+.\" Copyright (c) 1990 Jan-Simon Pendry
+.\" Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+.\" Copyright (c) 1990 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Jan-Simon Pendry at Imperial College, London.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgment:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" %W% (Berkeley) %G%
+.\"
+.\" $Id: pawd.1,v 5.2.2.1 1992/02/09 15:11:15 jsp beta $
+.\"
+.TH PAWD 1 "6 Jan 1998"
+.SH NAME
+pawd \- print automounter working directory
+.SH SYNOPSIS
+.B pawd
+[
+.I path ...
+]
+.SH DESCRIPTION
+.LP
+.B pawd
+is used to print the current working directory, adjusted to reflect proper
+paths that can be reused to go through the automounter for the shortest
+possible path. In particular, the path printed back does not include any
+of
+.BR Amd 's
+local mount points. Using them is unsafe, because
+.B Amd
+may unmount managed file systems from the mount points, and thus including
+them in paths may not always find the files within.
+.P
+Without any arguments,
+.B pawd
+will print the automounter adjusted current working directory. With any
+number of arguments, it will print the adjusted path of each one of the
+arguments.
+.SH "SEE ALSO"
+.BR amd (8),
+.BR amq (8),
+.BR pwd (1).
diff --git a/contrib/amd/amq/pawd.c b/contrib/amd/amq/pawd.c
new file mode 100644
index 0000000..86ed55f
--- /dev/null
+++ b/contrib/amd/amq/pawd.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 1997-1998 Erez Zadok
+ * Copyright (c) 1990 Jan-Simon Pendry
+ * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry at Imperial College, London.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * %W% (Berkeley) %G%
+ *
+ * $Id: pawd.c,v 5.2.2.1 1992/02/09 15:09:16 jsp beta $
+ *
+ */
+
+/*
+ * pawd is similar to pwd, except that it returns more "natural" versions of
+ * pathnames for directories automounted with the amd automounter. If any
+ * arguments are given, the "more natural" form of the given pathnames are
+ * printed.
+ *
+ * Paul Anderson (paul@ed.lfcs)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+#include <am_defs.h>
+#include <amq.h>
+
+/* dummy variables */
+char *progname;
+char hostname[MAXHOSTNAMELEN];
+int orig_umask, foreground, debug_flags;
+pid_t mypid;
+serv_state amd_state;
+
+/* statics */
+static char *localhost="localhost";
+static char newdir[MAXPATHLEN];
+static char transform[MAXPATHLEN];
+
+static int
+find_mt(amq_mount_tree *mt, char *dir)
+{
+ while (mt) {
+ if (STREQ(mt->mt_type, "link") || STREQ(mt->mt_type, "nfs")) {
+ int len = strlen(mt->mt_mountpoint);
+ if (NSTREQ(mt->mt_mountpoint, dir, len) &&
+ ((dir[len] == '\0') || (dir[len] == '/'))) {
+ char tmp_buf[MAXPATHLEN];
+ strcpy(tmp_buf, mt->mt_directory);
+ strcat(tmp_buf, &dir[len]);
+ strcpy(newdir, tmp_buf);
+ return 1;
+ }
+ }
+ if (find_mt(mt->mt_next,dir))
+ return 1;
+ mt = mt->mt_child;
+ }
+ return 0;
+}
+
+
+static int
+find_mlp(amq_mount_tree_list *mlp, char *dir)
+{
+ int i;
+
+ for (i = 0; i < mlp->amq_mount_tree_list_len; i++) {
+ if (find_mt(mlp->amq_mount_tree_list_val[i], dir))
+ return 1;
+ }
+ return 0;
+}
+
+
+#ifdef HAVE_CNODEID
+static char *
+cluster_server(void)
+{
+# ifdef HAVE_EXTERN_GETCCENT
+ struct cct_entry *cp;
+# endif /* HAVE_EXTERN_GETCCENT */
+
+ if (cnodeid() == 0)
+ return localhost;
+
+# ifdef HAVE_EXTERN_GETCCENT
+ while ((cp = getccent()))
+ if (cp->cnode_type == 'r')
+ return cp->cnode_name;
+# endif /* HAVE_EXTERN_GETCCENT */
+
+ return localhost;
+}
+#endif /* HAVE_CNODEID */
+
+
+/* DISK_HOME_HACK added by gdmr */
+#ifdef DISK_HOME_HACK
+static char *
+hack_name(char *dir)
+{
+ char partition[MAXPATHLEN];
+ char username[MAXPATHLEN];
+ char hesiod_lookup[MAXPATHLEN];
+ char *to, *ch, *hes_name, *dot;
+ char **hes;
+
+#ifdef DEBUG
+ fprintf(stderr, "hack_name(%s)\n", dir);
+#endif /* DEBUG */
+
+ if (dir[0] == '/' && dir[1] == 'a' && dir[2] == '/') {
+ /* Could be /a/server/disk/home/partition/user... */
+ ch = dir + 3;
+ while (*ch && *ch != '/') ch++; /* Skip server */
+ if (!NSTREQ(ch, "/disk/home/", 11))
+ return NULL; /* Nope */
+ /* Looking promising, next should be the partition name */
+ ch += 11;
+ to = partition;
+ while (*ch && *ch != '/') *to++ = *ch++;
+ to = '\0';
+ if (!(*ch))
+ return NULL; /* Off the end */
+ /* Now the username */
+ ch++;
+ to = username;
+ while (*ch && *ch != '/') *to++ = *ch++;
+ to = '\0';
+#ifdef DEBUG
+ fprintf(stderr, "partition %s, username %s\n", partition, username);
+#endif /* DEBUG */
+
+ sprintf(hesiod_lookup, "%s.homes-remote", username);
+ hes = hes_resolve(hesiod_lookup, "amd");
+ if (!hes)
+ return NULL;
+#ifdef DEBUG
+ fprintf(stderr, "hesiod -> <%s>\n", *hes);
+#endif /* DEBUG */
+ hes_name = strstr(*hes, "/homes/remote/");
+ if (!hes_name) return NULL;
+ hes_name += 14;
+#ifdef DEBUG
+ fprintf(stderr, "hesiod -> <%s>\n", hes_name);
+#endif /* DEBUG */
+ dot = hes_name;
+ while (*dot && *dot != '.') dot++;
+ *dot = '\0';
+#ifdef DEBUG
+ fprintf(stderr, "hesiod -> <%s>\n", hes_name);
+#endif /* DEBUG */
+
+ if (strcmp(partition, hes_name)) return NULL;
+#ifdef DEBUG
+ fprintf(stderr, "A match, munging....\n");
+#endif /* DEBUG */
+ strcpy(transform, "/home/");
+ strcat(transform, username);
+ if (*ch) strcat(transform, ch);
+#ifdef DEBUG
+ fprintf(stderr, "Munged to <%s>\n", transform);
+#endif /* DEBUG */
+ return transform;
+ }
+ return NULL;
+}
+#endif /* DISK_HOME_HACK */
+
+
+/*
+ * The routine transform_dir(path) transforms pathnames of directories
+ * mounted with the amd automounter to produce a more "natural" version.
+ * The automount table is obtained from the local amd via the rpc interface
+ * and reverse lookups are repeatedly performed on the directory name
+ * substituting the name of the automount link for the value of the link
+ * whenever it occurs as a prefix of the directory name.
+ */
+static char *
+transform_dir(char *dir)
+{
+#ifdef DISK_HOME_HACK
+ char *ch;
+#endif /* DISK_HOME_HACK */
+ char *server;
+ struct sockaddr_in server_addr;
+ int s = RPC_ANYSOCK;
+ CLIENT *clnt;
+ struct hostent *hp;
+ amq_mount_tree_list *mlp;
+ struct timeval tmo = {10, 0};
+
+#ifdef DISK_HOME_HACK
+ if (ch = hack_name(dir))
+ return ch;
+#endif /* DISK_HOME_HACK */
+
+#ifdef HAVE_CNODEID
+ server = cluster_server();
+#else /* not HAVE_CNODEID */
+ server = localhost;
+#endif /* not HAVE_CNODEID */
+
+ if ((hp = gethostbyname(server)) == 0)
+ return dir;
+ memset(&server_addr, 0, sizeof(server_addr));
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_addr = *(struct in_addr *) hp->h_addr;
+
+ clnt = clntudp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, tmo, &s);
+ if (clnt == 0)
+ return dir;
+
+ strcpy(transform,dir);
+ while ( (mlp = amqproc_export_1((voidp)0, clnt)) &&
+ find_mlp(mlp,transform) ) {
+ strcpy(transform,newdir);
+ }
+ return transform;
+}
+
+
+/* getawd() is a substitute for getwd() which transforms the path */
+static char *
+getawd(char *path)
+{
+#ifdef HAVE_GETCWD
+ char *wd = getcwd(path, MAXPATHLEN+1);
+#else /* not HAVE_GETCWD */
+ char *wd = getwd(path);
+#endif /* not HAVE_GETCWD */
+
+ if (wd == NULL) {
+ return NULL;
+ }
+ strcpy(path, transform_dir(wd));
+ return path;
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ char tmp_buf[MAXPATHLEN], *wd;
+
+ if (argc == 1) {
+ wd = getawd(tmp_buf);
+ if (wd == NULL) {
+ fprintf(stderr, "pawd: %s\n", tmp_buf);
+ exit(1);
+ } else {
+ fprintf(stdout, "%s\n", wd);
+ }
+ } else {
+ while (--argc) {
+ wd = transform_dir(*++argv);
+ fprintf(stdout, "%s\n", wd);
+ }
+ }
+ exit(0);
+}
+
OpenPOWER on IntegriCloud