diff options
Diffstat (limited to 'contrib/amd/amq')
-rw-r--r-- | contrib/amd/amq/amq.8 | 214 | ||||
-rw-r--r-- | contrib/amd/amq/amq.c | 938 | ||||
-rw-r--r-- | contrib/amd/amq/amq.h | 63 | ||||
-rw-r--r-- | contrib/amd/amq/amq_clnt.c | 208 | ||||
-rw-r--r-- | contrib/amd/amq/amq_xdr.c | 259 | ||||
-rw-r--r-- | contrib/amd/amq/pawd.1 | 72 | ||||
-rw-r--r-- | contrib/amd/amq/pawd.c | 296 |
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); +} + |