[comp.sources.unix] v21i095: An Automounter for NFS systems, Part07/13

rsalz@uunet.uu.net (Rich Salz) (04/11/90)

Submitted-by: Jan-Simon Pendry <jsp@doc.ic.ac.uk>
Posting-number: Volume 21, Issue 95
Archive-name: amd/part07

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 7 (of 13)."
# Contents:  Makefile.com amq.c get_args.c mapc.c
# Wrapped by rsalz@papaya.bbn.com on Tue Apr 10 15:12:08 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile.com' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile.com'\"
else
echo shar: Extracting \"'Makefile.com'\" \(9964 characters\)
sed "s/^X//" >'Makefile.com' <<'END_OF_FILE'
X#
X# $Id: Makefile.com,v 5.1.1.2 90/01/11 16:46:47 jsp Exp Locker: jsp $
X#
X# Copyright (c) 1990 Jan-Simon Pendry
X# Copyright (c) 1990 Imperial College of Science, Technology & Medicine
X# Copyright (c) 1990 The Regents of the University of California.
X# All rights reserved.
X#
X# This code is derived from software contributed to Berkeley by
X# Jan-Simon Pendry at Imperial College, London.
X#
X# Redistribution and use in source and binary forms are permitted
X# provided that the above copyright notice and this paragraph are
X# duplicated in all such forms and that any documentation,
X# advertising materials, and other materials related to such
X# distribution and use acknowledge that the software was developed
X# by Imperial College of Science, Technology and Medicine, London, UK.
X# The names of the College and University may not be used to endorse
X# or promote products derived from this software without specific
X# prior written permission.
X# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X#
X#	%W% (Berkeley) %G%
X#
X
X#
X# -------- Users may care to override these values --------
X#
X# Any of these values can be overridden by redefining them
X# in a file called Makefile.local or Makefile.local.foo (where
X# "foo" is the OS name)
X#
X
X# Where to install amd
XETC = /usr/local/etc
X
X# With what to install amd
XINSTALL = install
XINSTALL_BIN = ${INSTALL} -c -m 711 -o root
X
X# Uncomment the next CC line if you want to use GNU CC
X# Better yet - put the definition in Makefile.local.<foo>
X#CC = gcc ${GCCOPTS}
XGCCOPTS = -fcombine-regs -W -Wunused -fstrength-reduce #-finline-functions
X
X# Basic C compiler options
XCCOPTS = -O
X
X# These are for testing/debugging...
X# Best to put your own definitions in Makefile.local.<foo>
X#CCOPTS =  -g
X# Turn on -DDEBUG if you want a running commentary
X#DEBUG = -DDEBUG
X
X# Define RPCINC if Sun RPC header files are not in the standard place
XRPCINC = #-I../../rpc
X
X# Define RPCGEN as the name of your Sun *RPC/4* RPCGEN program (not RPC/3)
XRPCGEN = rpcgen
X
X# System C Compiler - one that is FULLY call compatible with your C libraries
XSYSCC = cc
XSYSCCFLAGS = ${CFLAGS}
X
X# For old makes
XSHELL = /bin/sh
X
X# -------- YOU SHOULD NOT NEED TO CHANGE ANYTHING BELOW THIS LINE --------
X
X# Magic
XOS_HDR = os-${OS}.h
XOSDEF = -DOS_HDR=\"${OS_HDR}\" -DOS_REP=\"${OS}\" -DARCH_REP=\"${ARCH}\"
XCFLAGS = ${CCOPTS} ${DEBUG} ${OSDEF} -I..
X
X# Basename of the program we are trying to build
XAMD = amd
XAMQ = amq
XMKMAP = mk-amd-map
X
XCC_COMPILE = ${CC} -c ${CFLAGS} ${RPCINC} ${CONFIG}
XSYSCC_COMPILE = ${SYSCC} -c ${SYSCCFLAGS} ${RPCINC} ${CONFIG}
X
X#
X# Keeps sysV make happy:
X#
XVPATH = ..
X
X#
X# Autmounter modules
X#
XMOUNTOBJ = \
X	afs_ops.o am_ops.o clock.o efs_ops.o \
X	mapc.o info_file.o info_hes.o info_ndbm.o info_yp.o map.o \
X	srvr_afs.o srvr_nfs.o \
X	mntfs.o misc_rpc.o mount_fs.o mount_xdr.o \
X	mtab.o nfs_ops.o nfs_prot_svc.o \
X	nfs_start.o nfs_stubs.o nfs_prot_xdr.o \
X	opts.o pfs_ops.o rpc_fwd.o \
X	sched.o sfs_ops.o \
X	amq_svc.o amq_subr.o umount_fs.o util.o \
X	ufs_ops.o ifs_ops.o am.o get_args.o \
X	rcs_info.o restart.o
X
XAMQOBJ = \
X	amq.o amq_clnt.o amq_xdr.o misc_rpc.o
X
XMAPOBJ = \
X	mk-amd-map.o
X
X#
X# Files defining different O/S flavors
X#
XOS_FILES = \
X	os-acis43.h \
X	os-aux.h \
X	os-bsd44.h Makefile.bsd44 \
X	os-concentrix.h \
X	os-defaults.h \
X	os-hlh42.h \
X	os-hpux.h Makefile.hpux hpux.h \
X	os-riscix.h \
X	os-sos3.h \
X	os-sos4.h \
X	os-u2_2.h u2_2-nfs.h \
X	os-u3_0.h \
X	os-umax43.h \
X	os-utx32.h \
X	os-xinu43.h
X
X# Experimental...
XEXPERIMENTAL_OS_FILES = os-aix2.h Makefile.aix2
X
X#
X# Other files that need to be shipped
X#
XBITS	= \
X	RELEASE \
X	COPYRIGHT \
X	Configure \
X	ChangeLog \
X	INSTALL \
X	Makefile \
X	Makefile.com \
X	Makefile.config \
X	patchlevel.h \
X	newvers.sh \
X	README \
X	WishList \
X	a_master \
X	amd-man \
X	amq-man \
X	amd.start.ex \
X	arch \
X	os-type
X
X#
X# Files to ship
X#
XSHIP	= \
X	afs_ops.c am.c am.h am_ops.c amq.c amq.h amq.x amq_clnt.c \
X	amq_subr.c amq_svc.c amq_xdr.c clock.c \
X	efs_ops.c fs.h get_args.c ifs_ops.c info_file.c info_hes.c \
X	info_ndbm.c info_yp.c map.c mapc.c misc_rpc.c mk-amd-map.c \
X	mntfs.c mount.h mount.x mount_fs.c mount_xdr.c mtab.c nfs_ops.c \
X	nfs_prot.h nfs_prot.x nfs_prot_svc.c nfs_prot_xdr.c nfs_start.c \
X	nfs_stubs.c opts.c pfs_ops.c rcs_info.c restart.c rpc_fwd.c sched.c \
X	sfs_ops.c srvr_afs.c srvr_nfs.c ufs_ops.c umount_fs.c util.c uwait.h \
X	${OS_FILES} ${BITS}
X
XDOCS	= \
X	doc/nh.sty doc/nh.doc \
X	doc/amd.bbl doc/amd.bib \
X	doc/amd.tex
X
XEXAMPLES = \
X	examples/am.master examples/amd.home \
X	examples/amd.homes examples/amd.vol
X
XSCRIPTS = \
X	scripts/build-userinfo \
X	scripts/get-homes \
X	scripts/mk-home-maps \
X	scripts/auto-banner
X
X#
X# Files to print
X#
XPRINT	= ${SHIP} ${SCRIPTS}
X
X#
X# What to build
X#
Xall: ${AMQ} ${AMD} ${MKMAP}
X
X${AMD}: ${MOUNTOBJ} version.${AMD}
X	@sh ../newvers.sh $@
X	${CC_COMPILE} vers.$@.c
X	@rm -f $@
X	${CC} -o $@ ${CFLAGS} ${MOUNTOBJ} vers.$@.o ${XLIBDIR} ${DBM} ${RPCLIB} ${RESOLV}
X
X${AMQ}: ${AMQOBJ}
X	@rm -f $@
X	${CC} -o $@ ${CFLAGS} ${AMQOBJ} ${RPCLIB} ${XLIBDIR} ${RESOLV}
X
X${MKMAP}: ${MAPOBJ}
X	@rm -f $@
X	${CC} -o $@ ${CFLAGS} ${MAPOBJ} ${DBM}
X
Xversion.${AMD}: ../RELEASE
X#	@echo Starting ${AMD} versions from zero ...
X	@rm -f $@
X	@echo 0 > $@
X
Xlint:
X	@for i in ${MOUNTOBJ:.o=.c}; do \
X		c="$$c ../$$i"; \
X	done; \
X	echo lint -chaax ${CFLAGS} $$c; \
X	lint -chaax ${CFLAGS} $$c
X
Xcount:
X	cat ${MOUNTOBJ:.o=.c} | grep -v '^#' | /lib/cpp | \
X	sed -e 's/[ 	]*$$//' -e '/^$$/d' | \
X	wc
X
XFRC:
X
X${MOUNTOBJ}: ../am.h ../${OS_HDR} ../os-defaults.h ../fs.h ../Makefile.config
X${AMQOBJ}: ../amq.h ../${OS_HDR} ../os-defaults.h
X${MAPOBJ}: ../am.h ../${OS_HDR} ../os-defaults.h
X
Xnfs_start.o: ../amq.h
X../amq.c ../amq_clnt.c ../amq_xdr.c ../amq_svc.c ../amq_subr.c: ../amq.h
X
X# We can't use gcc here (at least on sparc) ....
Xamq.o: ../amq.c; ${SYSCC_COMPILE} ../amq.c
Xamq_clnt.o: ../amq_clnt.c; ${SYSCC_COMPILE} ../amq_clnt.c
Xinfo_ndbm.o: ../info_ndbm.c; ${SYSCC_COMPILE} ../info_ndbm.c
Xmk-amd-map.o: ../mk-amd-map.c; ${SYSCC_COMPILE} ../mk-amd-map.c
X
X#amq.h: amq.x
X#	${RPCGEN} -h -o $@ amq.x
X#	@echo amq.h is out of date wrt amq.x - please fix by hand
X
X#amq_xdr.c: amq.x
X#	${RPCGEN} -c -o $@ amq.x
X#	@echo amq_xdr.c is out of date wrt amq.x - please fix by hand
X
X#amq_svc.c: amq.x
X#	${RPCGEN} -m -o $@ amq.x
X#	@echo amq_svc.c is out of date wrt amq.x - please fix by hand
X
X#amq_clnt.c: amq.x
X#	${RPCGEN} -l -o $@ amq.x
X#	@echo amq_clnt.c is out of date wrt amq.x - please fix by hand
X
X#
X# Don't really need the next two
X#
X#mount_xdr.c: mount.x
X#	${RPCGEN} -c -o $@ amq.x
X#	@echo mount_xdr.c is out of date wrt mount.x - please fix by hand
X
X#mount.h: mount.x
X#	${RPCGEN} -h -o $@ mount.x
X#	@echo mount.h is out of date wrt mount.x - please fix by hand
X
Xprint: ${PRINT}
X	enscript -2Grf Courier7 ${PRINT}
X
Xsharfile: ${AMD}.shar
X${AMD}.shar: ${SHIP} ${DOCS} ${EXAMPLES} ${SCRIPTS}
X	shar -o $@ ${SHIP} doc ${DOCS} examples ${EXAMPLES} scripts ${SCRIPTS}
X
Xtarfile: ${AMD}.tar.Z
X${AMD}.tar.Z: ${SHIP} ${DOCS} ${EXAMPLES} ${SCRIPTS}
X	tar cf - ${SHIP} ${DOCS} ${EXAMPLES} ${SCRIPTS} | compress > $@
X
Xuufile: tarfile
X	uuencode < ${AMD}.tar.Z ${AMD}.tar.Z > ${AMD}.tar.Z.UU
X
Xinstall: all
X	${INSTALL_BIN} ${AMD} ${ETC}/${AMD}
X	${INSTALL_BIN} ${AMQ} ${ETC}/${AMQ}
X	${INSTALL_BIN} ${MKMAP} ${ETC}/${MKMAP}
X	@echo Please install the manual pages by hand
X
Xclean:
X	-rm -f ${AMD} ${AMQ} ${MKMAP} *.o a.out core #mtab
X
X#co:
X#	co -l -r${REL} ${SHIP}
X#
X#release:
X#	ci -u -r${REL} -f -m'Version ${VER}' -n${NAME} -s'${NAME}' ${SHIP}
X
Xpat:
X	@touch RELEASE
X	pat -n
X
Xdiffs:
X	@rcsdiff -q -c2 -r${NAME} ${SHIP} | \
X		grep -v '^No differences encountered$$'
X
Xafs_ops.o: ../afs_ops.c; ${CC_COMPILE} ../afs_ops.c
Xam.o: ../am.c; ${CC_COMPILE} ../am.c
Xam_ops.o: ../am_ops.c; ${CC_COMPILE} ../am_ops.c
Xclock.o: ../clock.c; ${CC_COMPILE} ../clock.c
Xget_args.o: ../get_args.c; ${CC_COMPILE} ../get_args.c
Xefs_ops.o: ../efs_ops.c; ${CC_COMPILE} ../efs_ops.c
Xifs_ops.o: ../ifs_ops.c; ${CC_COMPILE} ../ifs_ops.c
Xinfo_file.o: ../info_file.c; ${CC_COMPILE} ../info_file.c
Xinfo_hes.o: ../info_hes.c; ${CC_COMPILE} ../info_hes.c
X#info_ndbm.o: ../info_ndbm.c; ${CC_COMPILE} ../info_ndbm.c
Xinfo_yp.o: ../info_yp.c; ${CC_COMPILE} ../info_yp.c
Xmap.o: ../map.c; ${CC_COMPILE} ../map.c
Xmapc.o: ../mapc.c; ${CC_COMPILE} ../mapc.c
Xmisc_rpc.o: ../misc_rpc.c; ${CC_COMPILE} ../misc_rpc.c
X#mk-amd-map.o: ../mk-amd-map.c; ${CC_COMPILE} ../mk-amd-map.c
Xmntfs.o: ../mntfs.c; ${CC_COMPILE} ../mntfs.c
Xmount_fs.o: ../mount_fs.c; ${CC_COMPILE} ../mount_fs.c
Xmount_xdr.o: ../mount_xdr.c; ${CC_COMPILE} ../mount_xdr.c
Xmtab.o: ../mtab.c; ${CC_COMPILE} ../mtab.c
Xnfs_ops.o: ../nfs_ops.c; ${CC_COMPILE} ../nfs_ops.c
Xnfs_prot_svc.o: ../nfs_prot_svc.c; ${CC_COMPILE} ../nfs_prot_svc.c
Xnfs_start.o: ../nfs_start.c; ${CC_COMPILE} ../nfs_start.c
Xnfs_stubs.o: ../nfs_stubs.c; ${CC_COMPILE} ../nfs_stubs.c
Xnfs_prot_xdr.o: ../nfs_prot_xdr.c; ${CC_COMPILE} ../nfs_prot_xdr.c
Xopts.o: ../opts.c; ${CC_COMPILE} ../opts.c
Xpfs_ops.o: ../pfs_ops.c; ${CC_COMPILE} ../pfs_ops.c
Xrcs_info.o: ../rcs_info.c; ${CC_COMPILE} ../rcs_info.c
Xrestart.o: ../restart.c; ${CC_COMPILE} ../restart.c
Xrpc_fwd.o: ../rpc_fwd.c; ${CC_COMPILE} ../rpc_fwd.c
Xsched.o: ../sched.c; ${CC_COMPILE} ../sched.c
Xsfs_ops.o: ../sfs_ops.c; ${CC_COMPILE} ../sfs_ops.c
Xsrvr_afs.o: ../srvr_afs.c; ${CC_COMPILE} ../srvr_afs.c
Xsrvr_nfs.o: ../srvr_nfs.c; ${CC_COMPILE} ../srvr_nfs.c
X#svc_udp2.o: ../svc_udp2.c; ${CC_COMPILE} ../svc_udp2.c
X#tfs_ops.o: ../tfs_ops.c; ${CC_COMPILE} ../tfs_ops.c
Xufs_ops.o: ../ufs_ops.c; ${CC_COMPILE} ../ufs_ops.c
Xumount_fs.o: ../umount_fs.c; ${CC_COMPILE} ../umount_fs.c
Xutil.o: ../util.c; ${CC_COMPILE} ../util.c
Xversion.o: ../version.c; ${CC_COMPILE} ../version.c
Xamq_svc.o: ../amq_svc.c; ${CC_COMPILE} ../amq_svc.c
Xamq_subr.o: ../amq_subr.c; ${CC_COMPILE} ../amq_subr.c
X#amq.o: ../amq.c; ${CC_COMPILE} ../amq.c
X#amq_clnt.o: ../amq_clnt.c; ${CC_COMPILE} ../amq_clnt.c
Xamq_xdr.o: ../amq_xdr.c; ${CC_COMPILE} ../amq_xdr.c
END_OF_FILE
if test 9964 -ne `wc -c <'Makefile.com'`; then
    echo shar: \"'Makefile.com'\" unpacked with wrong size!
fi
# end of 'Makefile.com'
fi
if test -f 'amq.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'amq.c'\"
else
echo shar: Extracting \"'amq.c'\" \(11634 characters\)
sed "s/^X//" >'amq.c' <<'END_OF_FILE'
X/*
X * $Id: amq.c,v 5.1.1.2 90/01/11 17:01:11 jsp Exp Locker: jsp $
X *
X * Copyright (c) 1990 Jan-Simon Pendry
X * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
X * Copyright (c) 1990 The Regents of the University of California.
X * All rights reserved.
X *
X * This code is derived from software contributed to Berkeley by
X * Jan-Simon Pendry at Imperial College, London.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Imperial College of Science, Technology and Medicine, London, UK.
X * The names of the College and University may not be used to endorse
X * or promote products derived from this software without specific
X * prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
X/*
X * Automounter query tool
X */
X
X#ifndef lint
Xchar copyright[] = "\
X@(#)Copyright (c) 1990 Jan-Simon Pendry\n\
X@(#)Copyright (c) 1990 Imperial College of Science, Technology & Medicine\n\
X@(#)Copyright (c) 1990 The Regents of the University of California.\n\
X@(#)All rights reserved.\n";
X#endif /* not lint */
X
X#ifndef lint
Xstatic char rcsid[] = "$Id: amq.c,v 5.1.1.2 90/01/11 17:01:11 jsp Exp Locker: jsp $";
Xstatic char sccsid[] = "%W% (Berkeley) %G%";
X#endif /* not lint */
X
X#include "am.h"
X#include "amq.h"
X#include <stdio.h>
X#include <fcntl.h>
X#include <netdb.h>
X
Xchar *progname;
Xstatic int flush_flag;
Xstatic int minfo_flag;
Xstatic int unmount_flag;
Xstatic int stats_flag;
Xstatic char *debug_opts;
Xstatic char *logfile;
Xstatic char *xlog_opt;
Xstatic char localhost[] = "localhost";
Xstatic char *def_server = localhost;
X
Xextern int optind;
Xextern char *optarg;
X
Xstatic struct timeval tmo = { 10, 0 };
X#define	TIMEOUT tmo
X
Xenum show_opt { Full, Stats, Calc, Short, ShowDone };
X
X/*
X * If (e) is Calc then just calculate the sizes
X * Otherwise display the mount node on stdout
X */
Xstatic void show_mti(mt, e, mwid, dwid, twid)
Xamq_mount_tree *mt;
Xenum show_opt e;
Xint *mwid;
Xint *dwid;
Xint *twid;
X{
X	switch (e) {
X	case Calc: {
X		int mw = strlen(mt->mt_mountinfo);
X		int dw = strlen(mt->mt_directory);
X		int tw = strlen(mt->mt_type);
X		if (mw > *mwid) *mwid = mw;
X		if (dw > *dwid) *dwid = dw;
X		if (tw > *twid) *twid = tw;
X	} break;
X
X	case Full: {
X		struct tm *tp = localtime(&mt->mt_mounttime);
Xprintf("%-*.*s %-*.*s %-*.*s %s\n\t%-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%02d %02d:%02d:%02d\n",
X			*dwid, *dwid,
X			*mt->mt_directory ? mt->mt_directory : "/",	/* XXX */
X			*twid, *twid,
X			mt->mt_type,
X			*mwid, *mwid, 
X			mt->mt_mountinfo,
X			mt->mt_mountpoint,
X
X			mt->mt_mountuid,
X			mt->mt_getattr,
X			mt->mt_lookup,
X			mt->mt_readdir,
X			mt->mt_readlink,
X			mt->mt_statfs,
X
X			tp->tm_year > 99 ? tp->tm_year - 100 : tp->tm_year,
X			tp->tm_mon+1, tp->tm_mday,
X			tp->tm_hour, tp->tm_min, tp->tm_sec);
X	} break;
X
X	case Stats: {
X		struct tm *tp = localtime(&mt->mt_mounttime);
Xprintf("%-*.*s %-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%02d %02d:%02d:%02d\n",
X			*dwid, *dwid,
X			*mt->mt_directory ? mt->mt_directory : "/",	/* XXX */
X
X			mt->mt_mountuid,
X			mt->mt_getattr,
X			mt->mt_lookup,
X			mt->mt_readdir,
X			mt->mt_readlink,
X			mt->mt_statfs,
X
X			tp->tm_year > 99 ? tp->tm_year - 100 : tp->tm_year,
X			tp->tm_mon+1, tp->tm_mday,
X			tp->tm_hour, tp->tm_min, tp->tm_sec);
X	} break;
X
X	case Short: {
X		printf("%-*.*s %-*.*s %-*.*s %s\n",
X			*dwid, *dwid,
X			*mt->mt_directory ? mt->mt_directory : "/",
X			*twid, *twid,
X			mt->mt_type,
X			*mwid, *mwid,
X			mt->mt_mountinfo,
X			mt->mt_mountpoint);
X	} break;
X	}
X}
X
X/*
X * Display a mount tree.
X */
Xstatic void show_mt(mt, e, mwid, dwid, pwid)
Xamq_mount_tree *mt;
Xenum show_opt e;
Xint *mwid;
Xint *dwid;
Xint *pwid;
X{
X	while (mt) {
X		show_mti(mt, e, mwid, dwid, pwid);
X		show_mt(mt->mt_next, e, mwid, dwid, pwid);
X		mt = mt->mt_child;
X	}
X}
X
Xstatic void show_mi(ml, e, mwid, dwid, twid)
Xamq_mount_info_list *ml;
Xenum show_opt e;
Xint *mwid;
Xint *dwid;
Xint *twid;
X{
X	int i;
X	switch (e) {
X	case Calc: {
X		for (i = 0; i < ml->amq_mount_info_list_len; i++) {
X			amq_mount_info *mi = &ml->amq_mount_info_list_val[i];
X			int mw = strlen(mi->mi_mountinfo);
X			int dw = strlen(mi->mi_mountpt);
X			int tw = strlen(mi->mi_type);
X			if (mw > *mwid) *mwid = mw;
X			if (dw > *dwid) *dwid = dw;
X			if (tw > *twid) *twid = tw;
X		}
X	} break;
X
X	case Full: {
X		for (i = 0; i < ml->amq_mount_info_list_len; i++) {
X			amq_mount_info *mi = &ml->amq_mount_info_list_val[i];
X			printf("%-*.*s %-*.*s %-*.*s %-3d %s is %s",
X						*mwid, *mwid, mi->mi_mountinfo,
X						*dwid, *dwid, mi->mi_mountpt,
X						*twid, *twid, mi->mi_type,
X						mi->mi_refc, mi->mi_fserver,
X						mi->mi_up > 0 ? "up" :
X						mi->mi_up < 0 ? "starting" : "down");
X			if (mi->mi_error > 0) {
X				extern char *sys_errlist[];
X				extern int sys_nerr;
X				if (mi->mi_error < sys_nerr)
X					printf(" (%s)", sys_errlist[mi->mi_error]);
X				else
X					printf(" (Error %d)", mi->mi_error);
X			} else if (mi->mi_error < 0) {
X				fputs(" (in progress)", stdout);
X			}
X			fputc('\n', stdout);
X		}
X	} break;
X	}
X}
X
X/*
X * Display general mount statistics
X */
Xstatic void show_ms(ms)
Xamq_mount_stats *ms;
X{
X	printf("\
Xrequests  stale     mount     mount     unmount\n\
Xdeferred  fhandles  ok        failed    failed\n\
X%-9d %-9d %-9d %-9d %-9d\n",
X	ms->as_drops, ms->as_stale, ms->as_mok, ms->as_merr, ms->as_uerr);
X}
X
Xstatic bool_t
Xxdr_pri_free(xdr_args, args_ptr)
Xxdrproc_t xdr_args;
Xcaddr_t args_ptr;
X{
X	XDR xdr;
X	xdr.x_op = XDR_FREE;
X	return ((*xdr_args)(&xdr, args_ptr));
X}
X
X#ifdef hpux
X#include <cluster.h>
Xstatic char *cluster_server()
X{
X	struct cct_entry *cp;
X
X	if (cnodeid() == 0) {
X		/*
X		 * Not clustered
X		 */
X		return def_server;
X	}
X
X	while (cp = getccent())
X		if (cp->cnode_type == 'r')
X			return cp->cnode_name;
X
X
X	return def_server;
X}
X#endif
X
X/*
X * MAIN
X */
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	int opt_ch;
X	int errs = 0;
X	char *server;
X	struct sockaddr_in server_addr;
X	int s = RPC_ANYSOCK;
X	CLIENT *clnt;
X	struct hostent *hp;
X	int nodefault = 0;
X
X	/*
X	 * Compute program name
X	 */
X	if (argv[0]) {
X		progname = strrchr(argv[0], '/');
X		if (progname && progname[1])
X			progname++;
X		else
X			progname = argv[0];
X	}
X	if (!progname)
X		progname = "amq";
X
X	/*
X	 * Parse arguments
X	 */
X	while ((opt_ch = getopt(argc, argv, "fh:l:msux:D:")) != EOF)
X	switch (opt_ch) {
X	case 'f':
X		flush_flag = 1;
X		break;
X
X	case 'h':
X		def_server = optarg;
X		break;
X
X	case 'l':
X		logfile = optarg;
X		nodefault = 1;
X		break;
X
X	case 'm':
X		minfo_flag = 1;
X		nodefault = 1;
X		break;
X
X	case 's':
X		stats_flag = 1;
X		break;
X
X	case 'u':
X		unmount_flag = 1;
X		break;
X
X	case 'x':
X		xlog_opt = optarg;
X		nodefault = 1;
X		break;
X
X	case 'D':
X		debug_opts = optarg;
X		nodefault = 1;
X		break;
X
X	default:
X		errs = 1;
X		break;
X	}
X
X	if (errs) {
Xshow_usage:
X		fprintf(stderr, "\
XUsage: %s [-h host] [[-f] [-m] | | [-s] | [[-u] directory ...]] |\n\
X\t[-l logfile|\"syslog\"] [-x log_flags] [-D dbg_opts]\n", progname);
X		exit(1);
X	}
X
X#ifdef hpux
X	/*
X	 * Figure out root server of cluster
X	 */
X	if (def_server == localhost)
X		server = cluster_server();
X	else
X#endif
X	server = def_server;
X
X	/*
X	 * Get address of server
X	 */
X	if ((hp = gethostbyname(server)) == 0) {
X		fprintf(stderr, "%s: Can't get address of %s\n", progname, server);
X		exit(1);
X	}
X	bzero(&server_addr, sizeof server_addr);
X	server_addr.sin_family = AF_INET;
X	server_addr.sin_addr = *(struct in_addr *) hp->h_addr;
X
X	/*
X	 * Create RPC endpoint
X	 */
X	clnt = clntudp_create(&server_addr, AMQ_PROGRAM, AMQ_VERSION, TIMEOUT, &s);
X	if (clnt == 0) {
X		fprintf(stderr, "%s: ", progname);
X		clnt_pcreateerror(server);
X		exit(1);
X	}
X
X	/*
X	 * Control debugging
X	 */
X	if (debug_opts) {
X		int *rc;
X		amq_setopt opt;
X		opt.as_opt = AMOPT_DEBUG;
X		opt.as_str = debug_opts;
X		rc = amqproc_setopt_1(&opt, clnt);
X		if (rc && *rc < 0) {
X			fprintf(stderr, "%s: daemon not compiled for debug", progname);
X			errs = 1;
X		} else if (!rc || *rc > 0) {
X			fprintf(stderr, "%s: debug setting for \"%s\" failed\n", progname, debug_opts);
X			errs = 1;
X		}
X	}
X
X	/*
X	 * Control logging
X	 */
X	if (xlog_opt) {
X		int *rc;
X		amq_setopt opt;
X		opt.as_opt = AMOPT_XLOG;
X		opt.as_str = xlog_opt;
X		rc = amqproc_setopt_1(&opt, clnt);
X		if (!rc || *rc) {
X			fprintf(stderr, "%s: setting log level to \"%s\" failed\n", progname, xlog_opt);
X			errs = 1;
X		}
X	}
X
X	/*
X	 * Control log file
X	 */
X	if (logfile) {
X		int *rc;
X		amq_setopt opt;
X		opt.as_opt = AMOPT_LOGFILE;
X		opt.as_str = logfile;
X		rc = amqproc_setopt_1(&opt, clnt);
X		if (!rc || *rc) {
X			fprintf(stderr, "%s: setting logfile to \"%s\" failed\n", progname, logfile);
X			errs = 1;
X		}
X	}
X
X	/*
X	 * Flush map cache
X	 */
X	if (logfile) {
X		int *rc;
X		amq_setopt opt;
X		opt.as_opt = AMOPT_FLUSHMAPC;
X		opt.as_str = "";
X		rc = amqproc_setopt_1(&opt, clnt);
X		if (!rc || *rc) {
X			fprintf(stderr, "%s: amd on %s cannot flush the map cache\n", progname, server);
X			errs = 1;
X		}
X	}
X
X	/*
X	 * Mount info
X	 */
X	if (minfo_flag) {
X		int dummy;
X		amq_mount_info_list *ml = amqproc_getmntfs_1(&dummy, clnt);
X		if (ml) {
X			int mwid = 0, dwid = 0, twid = 0;
X			show_mi(ml, Calc, &mwid, &dwid, &twid);
X			mwid++; dwid++; twid++;
X			show_mi(ml, Full, &mwid, &dwid, &twid);
X
X		} else {
X			fprintf(stderr, "%s: amd on %s cannot provide mount info\n", progname, server);
X		}
X	}
X
X	/*
X	 * Apply required operation to all remaining arguments
X	 */
X	if (optind < argc) {
X		do {
X			char *fs = argv[optind++];
X			if (unmount_flag) {
X				/*
X				 * Unmount request
X				 */
X				amqproc_umnt_1(&fs, clnt);
X			} else {
X				/*
X				 * Stats request
X				 */
X				amq_mount_tree_p *mtp = amqproc_mnttree_1(&fs, clnt);
X				if (mtp) {
X					amq_mount_tree *mt = *mtp;
X					if (mt) {
X						int mwid = 0, dwid = 0, twid = 0;
X						show_mt(mt, Calc, &mwid, &dwid, &twid);
X						mwid++; dwid++, twid++;
X#ifdef notdef
X		printf("\t%s\n%-*.*s %-*.*s %-*.*s %s\n",
X		"Uid   Getattr Lookup RdDir   RdLnk   Statfs Mounted@",
X		      dwid, dwid, "What", twid, twid, "Type", mwid, mwid, "Info", "Where");
X						show_mt(mt, Full, &mwid, &dwid, &twid);
X#endif
X		printf("%-*.*s Uid   Getattr Lookup RdDir   RdLnk   Statfs Mounted@\n",
X			dwid, dwid, "What");
X						show_mt(mt, Stats, &mwid, &dwid, &twid);
X					} else {
X						fprintf(stderr, "%s: %s not automounted\n", progname, fs);
X					}
X					xdr_pri_free(xdr_amq_mount_tree_p, (caddr_t) mtp);
X				} else {
X					fprintf(stderr, "%s: ", progname);
X					clnt_perror(clnt, server);
X					errs = 1;
X				}
X			}
X		} while (optind < argc);
X	} else if (unmount_flag) {
X		goto show_usage;
X	} else if (stats_flag) {
X		amq_mount_stats *ms = amqproc_stats_1((voidp) 0, clnt);
X		if (ms) {
X			show_ms(ms);
X		} else {
X			fprintf(stderr, "%s: ", progname);
X			clnt_perror(clnt, server);
X			errs = 1;
X		}
X	} else if (!nodefault) {
X		amq_mount_tree_list *mlp = amqproc_export_1((voidp) 0, clnt);
X		if (mlp) {
X			enum show_opt e = Calc;
X			int mwid = 0, dwid = 0, pwid = 0;
X			while (e != ShowDone) {
X				int i;
X				for (i = 0; i < mlp->amq_mount_tree_list_len; i++) {
X					show_mt(mlp->amq_mount_tree_list_val[i],
X						 e, &mwid, &dwid, &pwid);
X				}
X				mwid++; dwid++, pwid++;
X				if (e == Calc) e = Short;
X				else if (e == Short) e = ShowDone;
X			}
X		} else {
X			fprintf(stderr, "%s: ", progname);
X			clnt_perror(clnt, server);
X			errs = 1;
X		}
X	}
X
X	exit(errs);
X}
X
X#ifdef DEBUG
Xxfree(f, l, p)
Xchar *f, *l;
Xvoidp p;
X{
X	free(p);
X}
X#endif
END_OF_FILE
if test 11634 -ne `wc -c <'amq.c'`; then
    echo shar: \"'amq.c'\" unpacked with wrong size!
fi
# end of 'amq.c'
fi
if test -f 'get_args.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'get_args.c'\"
else
echo shar: Extracting \"'get_args.c'\" \(10282 characters\)
sed "s/^X//" >'get_args.c' <<'END_OF_FILE'
X/*
X * $Id: get_args.c,v 5.1.1.2 90/01/11 17:06:42 jsp Exp Locker: jsp $
X *
X * Copyright (c) 1990 Jan-Simon Pendry
X * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
X * Copyright (c) 1990 The Regents of the University of California.
X * All rights reserved.
X *
X * This code is derived from software contributed to Berkeley by
X * Jan-Simon Pendry at Imperial College, London.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Imperial College of Science, Technology and Medicine, London, UK.
X * The names of the College and University may not be used to endorse
X * or promote products derived from this software without specific
X * prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X *	%W% (Berkeley) %G%
X */
X
X/*
X * Argument decode
X */
X
X#include "am.h"
X#ifdef HAS_SYSLOG
X#include <syslog.h>
X#endif
X#include <sys/stat.h>
X
Xextern int optind;
Xextern char *optarg;
X
X#if defined(DEBUG) && defined(PARANOID)
Xchar **gargv;
X#endif
Xint restart_existing_mounts;
Xint print_pid;
Xint normalize_hosts;
Xchar *karch;			/* Kernel architecture */
Xchar *cluster;			/* Cluster name */
X#ifdef HAS_YP_MAPS
Xchar *domain;			/* YP domain */
X#endif
X#ifdef UPDATE_MTAB
Xchar *mtab;
X#endif
XFILE *logfp = stderr;		/* Log errors to stderr initially */
X#ifdef HAS_SYSLOG
Xint syslogging;
X#endif
Xint afs_timeo = -1;
Xint afs_retrans = -1;
Xint am_timeo = AM_TTL;
Xint am_timeo_w = AM_TTL_W;
Xint xlog_level = 0;
Xint xlog_level_init = ~0;
X
Xstruct opt_tab {
X	char *opt;
X	int flag;
X};
X
X/*
X * List of log options
X */
Xstatic struct opt_tab xlog_opt[] = {
X	{ "all", XLOG_ALL },		/* All messages */
X#ifdef DEBUG
X	{ "debug", XLOG_DEBUG },	/* Debug messages */
X#endif
X	{ "error", XLOG_ERROR },	/* Non-fatal system errors */
X	{ "fatal", XLOG_FATAL },	/* Fatal errors */
X	{ "info", XLOG_INFO },		/* Information */
X	{ "map", XLOG_MAP },		/* Map errors */
X	{ "stats", XLOG_STATS },	/* Additional statistical information */
X	{ "user", XLOG_USER },		/* Non-fatal user errors */
X	{ "warn", XLOG_WARNING },	/* Warnings */
X	{ "warning", XLOG_WARNING },	/* Warnings */
X	{ 0, 0 }
X};
X
X#ifdef DEBUG
X/*
X * List of debug options.
X */
Xstatic struct opt_tab dbg_opt[] = {
X	{ "all", D_ALL },		/* All */
X	{ "amq", D_AMQ },		/* Register for AMQ program */
X	{ "daemon", D_DAEMON },		/* Enter daemon mode */
X	{ "full", D_FULL },		/* Program trace */
X	{ "mem", D_MEM },		/* Trace memory allocations */
X	{ "mtab", D_MTAB },		/* Use local mtab file */
X	{ "str", D_STR },		/* Debug string munging */
X	{ "test", D_TEST },		/* Full debug - but no daemon */
X	{ "trace", D_TRACE },		/* Protocol trace */
X	{ 0, 0 }
X};
X
Xint debug_flags = D_AMQ			/* Register AMQ */
X		 |D_DAEMON		/* Enter daemon mode */
X		 ;
X#endif
X
Xstatic void show_opts(ch, opts)
Xint ch;
Xstruct opt_tab *opts;
X{
X	/*
X	 * Display current debug options
X	 */
X	int i;
X	int s = '{';
X	fprintf(stderr, "\t[-%c {no}", ch);
X	for (i = 0; opts[i].opt; i++) {
X		fprintf(stderr, "%c%s", s, opts[i].opt);
X		s = ',';
X	}
X	fputs("}]\n", stderr);
X}
X
Xstatic int option(s, optb, flags)
Xchar *s;
Xstruct opt_tab *optb;
Xint *flags;
X{
X	char *p = s;
X	int errs = 0;
X
X	while (p && *p) {
X		int neg;
X		char *opt;
X		struct opt_tab *dp;
X
X		s = p;
X		p = strchr(p, ',');
X		if (p)
X			*p = '\0';
X
X		if (s[0] == 'n' && s[1] == 'o') {
X			opt = s + 2;
X			neg = 1;
X		} else {
X			opt = s;
X			neg = 0;
X		}
X
X		/*
X		 * Scan the array of debug options to find the
X		 * corresponding flag value.  If it is found
X		 * then set (or clear) the flag (depending on
X		 * whether the option was prefixed with "no").
X		 */
X		for (dp = optb; dp->opt; dp++) {
X			if (strcmp(opt, dp->opt) == 0) {
X				if (neg)
X					*flags &= ~dp->flag;
X				else
X					*flags |= dp->flag;
X				break;
X			}
X		}
X
X		if (dp->opt == 0) {
X			/*
X			 * This will log to stderr when parsing the command line
X			 * since any -l option will not yet have taken effect.
X			 */
X			plog(XLOG_USER, "option \"%s\" not recognised", s);
X			errs++;
X		}
X		/*
X		 * Put the comma back
X		 */
X		if (p)
X			*p++ = ',';
X	}
X
X	return errs;
X}
X
X/*
X * Switch on/off logging options
X */
Xint switch_option(opt)
Xchar *opt;
X{
X	int xl = xlog_level;
X	int rc = option(opt, xlog_opt, &xl);
X	if (rc) {
X		rc = EINVAL;
X	} else {
X		/*
X		 * Keep track of initial log level, and
X		 * don't allow options to be turned off.
X		 */
X		if (xlog_level_init == ~0)
X			xlog_level_init = xl;
X		else
X			xl |= xlog_level_init;
X		xlog_level = xl;
X	}
X	return rc;
X}
X
X#ifdef DEBUG
X/*
X * Switch on/off debug options
X */
Xint debug_option(opt)
Xchar *opt;
X{
X	return option(opt, dbg_opt, &debug_flags);
X}
X#endif
X
X/*
X * Change current logfile
X */
Xint switch_to_logfile(logfile)
Xchar *logfile;
X{
X	FILE *new_logfp = stderr;
X
X	if (logfile) {
X#ifdef HAS_SYSLOG
X		syslogging = 0;
X#endif
X		if (strcmp(logfile, "/dev/stderr") == 0)
X			new_logfp = stderr;
X		else if (strcmp(logfile, "syslog") == 0) {
X#ifdef HAS_SYSLOG
X			syslogging = 1;
X			new_logfp = stderr;
X#ifdef LOG_CONS
X			openlog(progname, LOG_PID|LOG_CONS|LOG_NOWAIT,
X				LOG_DAEMON);
X#else
X			/* 4.2 compat mode - XXX */
X			openlog(progname, LOG_PID);
X#endif
X#else
X			plog(XLOG_WARNING, "syslog option not supported, logging unchanged");
X#endif
X		} else {
X			(void) umask(orig_umask);
X			new_logfp = fopen(logfile, "a");
X			umask(0);
X		}
X	}
X
X	/*
X	 * If we couldn't open a new file, then continue using the old.
X	 */
X	if (!new_logfp && logfile) {
X		plog(XLOG_USER, "%s: Can't open logfile: %m", logfile);
X		return 1;
X	}
X	/*
X	 * Close the previous file
X	 */
X	if (logfp && logfp != stderr)
X		(void) fclose(logfp);
X	logfp = new_logfp;
X	return 0;
X}
X
Xvoid get_args(c, v)
Xint c;
Xchar *v[];
X{
X	int opt_ch;
X	int usage = 0;
X	char *logfile = 0;
X	char *sub_domain = 0;
X
X#if defined(DEBUG) && defined(PARANOID)
X	gargv = v;
X	progname = v[0];		/* Use argv[0] to try to solve Piete's problem */
X#else
X	if (v[0]) {
X		progname = strrchr(v[0], '/');
X		if (progname && progname[1])
X			progname++;
X		else
X			progname = v[0];
X	}
X#endif
X	if (!progname)
X		progname = "amd";
X
X	while ((opt_ch = getopt(c, v, "mnprva:c:d:k:l:t:w:x:y:D:")) != EOF)
X	switch (opt_ch) {
X	case 'a':
X		if (*optarg != '/') {
X			fprintf(stderr, "%s: -a option must begin with a '/'\n",
X					progname);
X			exit(1);
X		}
X		auto_dir = optarg;
X		break;
X
X	case 'c':
X		am_timeo = atoi(optarg);
X		if (am_timeo <= 0)
X			am_timeo = AM_TTL;
X		break;
X
X	case 'd':
X		sub_domain = optarg;
X		break;
X
X	case 'k':
X		karch = optarg;
X		break;
X
X	case 'l':
X		logfile = optarg;
X		break;
X
X	case 'm':
X		plog(XLOG_USER, "The -m option is no longer supported.");
X		plog(XLOG_USER, "... Use `ypcat -k am.master` on the command line instead");
X		break;
X
X	case 'n':
X		normalize_hosts = 1;
X		break;
X
X	case 'p':
X		print_pid = 1;
X		break;
X
X	case 'r':
X		restart_existing_mounts = 1;
X		break;
X
X	case 't':
X		/* timeo.retrans */
X		{ char *dot = strchr(optarg, '.');
X		  if (dot) *dot = '\0';
X		  if (*optarg) {
X			afs_timeo = atoi(optarg);
X		  }
X		  if (dot) {
X		  	afs_retrans = atoi(dot+1);
X			*dot = '.';
X		  }
X		}
X		break;
X
X	case 'v':
X		{ char buf[256];
X		  show_rcs_info(version, buf);
X		  fputs(buf, stderr);
X		}
X		fprintf(stderr,
X			" for a%s %s running %s (%s-endian)\n",
X					strchr("aeiou", arch[0]) ? "n" : "",
X					arch, op_sys, endian);
X		fputs("Map support for: ", stderr);
X		mapc_showtypes(stderr);
X		fputs(".\n", stderr);
X		exit(0);
X		break;
X
X	case 'w':
X		am_timeo_w = atoi(optarg);
X		if (am_timeo_w <= 0)
X			am_timeo_w = AM_TTL_W;
X		break;
X
X	case 'x':
X		usage += switch_option(optarg);
X		break;
X
X	case 'y':
X#ifdef HAS_YP_MAPS
X		domain = optarg;
X#else
X		plog(XLOG_USER, "-y: option ignored.  No YP support available.");
X#endif
X		break;
X
X	case 'C':
X		cluster = optarg;
X		break;
X
X	case 'D':
X#ifdef DEBUG
X		usage += debug_option(optarg);
X#else
X		fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n", progname);
X#endif
X		break;
X
X	default:
X		usage = 1;
X		break;
X	}
X
X	if (xlog_level == 0) {
X		/* Take copy to avoid writable-strings problem */
X		char *dfstr = strdup(XLOG_DEFSTR);
X		usage += switch_option(dfstr);
X		free((voidp) dfstr);
X#ifdef DEBUG
X		usage += switch_option("debug");
X#endif
X	} else {
X#ifdef DEBUG
X		usage += switch_option("debug");
X#endif
X	}
X
X	if (usage)
X		goto show_usage;
X
X	while (optind <= c-2) {
X		char *dir = v[optind++];
X		char *map = v[optind++];
X		char *opts = "";
X		if (v[optind] && *v[optind] == '-')
X			opts = &v[optind++][1];
X
X		root_newmap(dir, opts, map);
X	}
X
X	if (optind == c) {
X#ifdef hpux
X		/*
X		 * HP-UX can't handle ./mtab
X		 * That system is sick - really.
X		 */
X#ifdef	DEBUG
X		debug_option("nomtab");
X#endif	/* DEBUG */
X#endif	/* hpux */
X
X		/*
X		 * Append domain name to hostname.
X		 * sub_domain overrides hostdomain
X		 * if given.
X		 */
X		if (sub_domain)
X			hostdomain = sub_domain;
X		if (*hostdomain == '.')
X			hostdomain++;
X		strcat(hostd,  ".");
X		strcat(hostd, hostdomain);
X
X#ifdef UPDATE_MTAB
X#ifdef DEBUG
X		if (debug_flags & D_MTAB)
X			mtab = DEBUG_MTAB;
X		else
X#endif /* DEBUG */
X		mtab = MOUNTED;
X#else
X#ifdef DEBUG
X		{ if (debug_flags & D_MTAB) {
X			dlog("-D mtab option ignored");
X		} }
X#endif /* DEBUG */
X#endif /* UPDATE_MTAB */
X
X		if (switch_to_logfile(logfile) != 0)
X			plog(XLOG_USER, "Cannot switch logfile");
X
X		/*
X		 * If the kernel architecture was not specified
X		 * then use the machine architecture.
X		 */
X		if (karch == 0)
X			karch = arch;
X
X		if (cluster == 0)
X			cluster = hostdomain;
X
X		if (afs_timeo <= 0)
X			afs_timeo = AFS_TIMEO;
X		if (afs_retrans <= 0)
X			afs_retrans = AFS_RETRANS;
X		if (afs_retrans <= 0)
X			afs_retrans = 3;	/* XXX */
X		return;
X	}
X
Xshow_usage:
X	fprintf(stderr,
X"Usage: %s [-mnprv] [-a mnt_point] [-c cache_time] [-d domain]\n\
X\t[-k kernel_arch] [-l logfile|\"syslog\"] [-t afs_timeout]\n\
X\t[-w wait_timeout] [-C cluster_name]", progname);
X
X#ifdef HAS_YP_MAPS
X	fputs(" [-y yp-domain]\n", stderr);
X#else
X	fputc('\n', stderr);
X#endif
X
X	show_opts('x', xlog_opt);
X#ifdef DEBUG
X	show_opts('D', dbg_opt);
X#endif
X	fprintf(stderr, "\t{directory mapname [-map_options]} ...\n");
X	exit(1);
X}
END_OF_FILE
if test 10282 -ne `wc -c <'get_args.c'`; then
    echo shar: \"'get_args.c'\" unpacked with wrong size!
fi
# end of 'get_args.c'
fi
if test -f 'mapc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mapc.c'\"
else
echo shar: Extracting \"'mapc.c'\" \(11592 characters\)
sed "s/^X//" >'mapc.c' <<'END_OF_FILE'
X/*
X * $Id: mapc.c,v 5.1.1.1 89/11/28 17:52:47 jsp Exp Locker: jsp $
X *
X * Copyright (c) 1989 Jan-Simon Pendry
X * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
X * Copyright (c) 1989 The Regents of the University of California.
X * All rights reserved.
X *
X * This code is derived from software contributed to Berkeley by
X * Jan-Simon Pendry at Imperial College, London.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Imperial College of Science, Technology and Medicine, London, UK.
X * The names of the College and University may not be used to endorse
X * or promote products derived from this software without specific
X * prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X *	%W% (Berkeley) %G%
X */
X
X/*
X * Mount map cache
X */
X
X#include "am.h"
X
X/*
X * Hash table size
X */
X#define	NKVHASH	(1 << 2)		/* Power of two */
X
X/*
X * Wildcard key
X */
Xstatic char wildcard[] = "*";
X
X/*
X * Map cache types
X * default, none, incremental, all
X */
X#define	MAPC_DFLT	-1
X#define	MAPC_NONE	0
X#define	MAPC_INC	1
X#define	MAPC_ALL	2
X
X/*
X * Do a map reload
X */
X#define mapc_reload_map(m) \
X	((*(m)->reload)(m, m->map_name, mapc_add_kv))
X
X/*
X * Cache map operations
X */
Xtypedef void add_fn P((mnt_map*, char*, char*));
Xtypedef int init_fn P((char*));
Xtypedef int search_fn P((mnt_map*, char*, char*, char**, time_t*));
Xtypedef int reload_fn P((mnt_map*, char*, add_fn*));
X
Xstatic void mapc_sync P((mnt_map*));
X
X/*
X * Map type
X */
Xtypedef struct map_type map_type;
Xstruct map_type {
X	char *name;			/* Name of this map type */
X	init_fn *init;			/* Initialisation */
X	reload_fn *reload;		/* Reload or fill */
X	search_fn *search;		/* Search for new entry */
X	int def_alloc;			/* Default allocation mode */
X};
X
X/*
X * Key-value pair
X */
Xtypedef struct kv kv;
Xstruct kv {
X	kv *next;
X	char *key;
X	char *val;
X};
X
Xstruct mnt_map {
X	qelem hdr;
X	int refc;			/* Reference count */
X	int alloc;			/* Allocation mode */
X	time_t modify;			/* Modify time of map */
X	char *map_name;			/* Name of this map */
X	char *wildcard;			/* Wildcard value */
X	reload_fn *reload;		/* Function to be used for reloads */
X	search_fn *search;		/* Function to be used for searching */
X	kv *kvhash[NKVHASH];		/* Cached data */
X};
X
X/*
X * Map for root node
X */
Xstatic mnt_map *root_map;
X
X/*
X * List of known maps
X */
Xextern qelem map_list_head;
Xqelem map_list_head = { &map_list_head, &map_list_head };
X
X/*
X * Configuration
X */
X 
X/* ROOT MAP */
Xstatic int root_init P((char*));
X
X/* FILE MAPS */
X#ifdef HAS_FILE_MAPS
Xextern int file_init P((char*));
Xextern int file_reload P((mnt_map*, char*, add_fn*));
Xextern int file_search P((mnt_map*, char*, char*, char**, time_t*));
X#endif
X
X/* YELLOW PAGES MAPS */
X#ifdef HAS_YP_MAPS
Xextern int yp_init P((char*));
Xextern int yp_search P((mnt_map*, char*, char*, char**, time_t*));
X#endif
X
X/* GDBM MAPS */
X#ifdef HAS_GDBM_MAPS
X#define HAS_DATABASE
X#undef HAS_NDBM_MAPS
Xextern int gdbm_init P((char*));
Xextern int gdbm_search P((mnt_map*, char*, char*, char**, time_t*));
X#endif
X
X/* NDBM MAPS */
X#ifndef HAS_DATABASE
X#ifdef HAS_NDBM_MAPS
X#ifdef OS_HAS_NDBM
X#define	HAS_DATABASE
X#undef HAS_GDBM_MAPS
Xextern int ndbm_init P((char*));
Xextern int ndbm_search P((mnt_map*, char*, char*, char**, time_t*));
X#endif
X#endif
X#endif
X
X/* HESIOD MAPS */
X#ifdef HAS_HESIOD_MAPS
Xextern int hesiod_init P((char*));
Xextern int hesiod_search P((mnt_map*, char*, char*, char**, time_t*));
X#endif
X
X/* ERROR MAP */
Xstatic int error_init P((char*));
Xstatic int error_reload P((mnt_map*, char*, add_fn*));
Xstatic int error_search P((mnt_map*, char*, char*, char**, time_t*));
X
Xstatic map_type maptypes[] = {
X	{ "root", root_init, error_reload, error_search, MAPC_ALL },
X
X#ifdef HAS_HESIOD_MAPS
X	{ "hesiod", hesiod_init, error_reload, hesiod_search, MAPC_INC },
X#endif
X
X#ifdef HAS_YP_MAPS
X	{ "yp", yp_init, error_reload, yp_search, MAPC_INC },
X#endif
X
X#ifdef HAS_NDBM_MAPS
X	{ "ndbm", ndbm_init, error_reload, ndbm_search, MAPC_INC },
X#endif
X
X#ifdef HAS_GDBM_MAPS
X	{ "gdbm", gdbm_init, error_reload, gdbm_search, MAPC_INC },
X#endif
X
X#ifdef HAS_FILE_MAPS
X	{ "file", file_init, file_reload, file_search, MAPC_ALL },
X#endif
X
X	{ "error", error_init, error_reload, error_search, MAPC_NONE },
X};
X
X/*
X * Hash function
X */
Xstatic unsigned int kvhash_of(key)
Xchar *key;
X{
X	unsigned int i, j;
X
X	for (i = 0; j = *key++; i += j)
X		;
X
X	return i % NKVHASH;
X}
X
Xvoid mapc_showtypes(fp)
XFILE *fp;
X{
X	map_type *mt;
X	char *sep = "";
X	for (mt = maptypes; mt < maptypes+sizeof(maptypes)/sizeof(maptypes[0]); mt++) {
X		fprintf(fp, "%s%s", sep, mt->name);
X		sep = ", ";
X	}
X}
X
X/*
X * Add key and val to the map m.
X * key and val are assumed to be safe copies
X */
Xvoid mapc_add_kv(m, key, val)
Xmnt_map *m;
Xchar *key;
Xchar *val;
X{
X	kv **h = &m->kvhash[kvhash_of(key)];
X	kv *n = ALLOC(kv);
X	n->key = key;
X	n->val = val;
X	n->next = *h;
X	*h = n;
X}
X
Xstatic int search_map(m, key, valp)
Xmnt_map *m;
Xchar *key;
Xchar **valp;
X{
X	int rc;
X	do {
X		rc = (*m->search)(m, m->map_name, key, valp, &m->modify);
X		if (rc < 0) {
X			plog(XLOG_MAP, "Re-synchronizing cache for map %s", m->map_name);
X			mapc_sync(m);
X		}
X	} while (rc < 0);
X
X	return rc;
X}
X
X/*
X * Do a wildcard lookup in the map and
X * save the result.
X */
Xstatic void mapc_find_wildcard(m)
Xmnt_map *m;
X{
X	/*
X	 * Attempt to find the wildcard entry
X	 */
X	int rc = search_map(m, wildcard, &m->wildcard);
X
X	if (rc != 0)
X		m->wildcard = 0;
X}
X
X/*
X * Make a duplicate reference to an existing map
X */
X#define mapc_dup(m) ((m)->refc++, (m))
X
X/*
X * Create a new map
X */
Xstatic mnt_map *mapc_create(map, opt)
Xchar *map;
Xchar *opt;
X{
X	mnt_map *m = ALLOC(mnt_map);
X	map_type *mt;
X	int alloc = STREQ(opt, "all") ? MAPC_ALL :
X		    (STREQ(opt, "inc") ? MAPC_INC :
X		    ((STREQ(opt, "default") || STREQ(opt, "mapdefault")) ? MAPC_DFLT :
X		    MAPC_NONE));
X
X	for (mt = maptypes; mt < maptypes+sizeof(maptypes)/sizeof(maptypes[0]); mt++)
X		if ((*mt->init)(map) == 0)
X			break;
X
X#ifdef DEBUG
X	dlog("Map for %s coming from maptype %s", map, mt->name);
X#endif
X	/*
X	 * If there is no support for reload and it was requested
X	 * then back off to incremental instead.
X	 */
X	if (mt->reload == error_reload && alloc == MAPC_ALL && mt->def_alloc != MAPC_ALL) {
X		plog(XLOG_WARNING, "Map type \"%s\" does not support cache type \"all\"",
X					mt->name);
X		alloc = MAPC_INC;
X	} else if (alloc == MAPC_DFLT)
X		alloc = mt->def_alloc;
X	m->alloc = alloc;
X	m->reload = mt->reload;
X	m->modify = clocktime();
X	m->search = alloc == MAPC_ALL ? error_search : mt->search;
X	bzero((voidp) m->kvhash, sizeof(m->kvhash));
X	m->map_name = strdup(map);
X	m->refc = 1;
X	/*
X	 * Attempt to find the wildcard entry
X	 */
X	mapc_find_wildcard(m);
X
X	if (alloc == MAPC_ALL) {
X		/*
X		 * If cache all is specified then load the cache
X		 */
X		if (mapc_reload_map(m)) {
X			/*
X			 * If that doesn't work then fallback to
X			 * incremental cache mode
X			 */
X			m->alloc = MAPC_INC;
X		}
X	}
X	return m;
X}
X
X/*
X * Free the cached data in a map
X */
Xstatic void mapc_clear(m)
Xmnt_map *m;
X{
X	int i;
X
X	/*
X	 * For each of the hash slots, chain
X	 * along free'ing the data.
X	 */
X	for (i = 0; i < NKVHASH; i++) {
X		kv *k = m->kvhash[i];
X		while (k) {
X			kv *n = k->next;
X			free(k->key);
X			if (k->val)
X				free(k->val);
X			free(k);
X			k = n;
X		}
X	}
X	/*
X	 * Zero the hash slots
X	 */
X	bzero((voidp) m->kvhash, sizeof(m->kvhash));
X	/*
X	 * Free the wildcard if it exists
X	 */
X	if (m->wildcard) {
X		free(m->wildcard);
X		m->wildcard = 0;
X	}
X}
X
X/*
X * Find a map, or create one if it does not exist
X */
Xmnt_map *mapc_find(map, opt)
Xchar *map;
Xchar *opt;
X{
X	mnt_map *m;
X
X	/*
X	 * Search the list of known maps to see if
X	 * it has already been loaded.  If it is found
X	 * then return a duplicate reference to it.
X	 * Otherwise make a new map as required and
X	 * add it to the list of maps
X	 */
X	ITER(m, mnt_map, &map_list_head)
X		if (STREQ(m->map_name, map))
X			return mapc_dup(m);
X
X	m = mapc_create(map, opt);
X	ins_que(&m->hdr, &map_list_head);
X	return m;
X}
X
X/*
X * Free a map.
X */
Xvoid mapc_free(m)
Xmnt_map *m;
X{
X	/*
X	 * Decrement the reference count.
X	 * If the reference count hits zero
X	 * then throw the map away.
X	 */
X	if (--m->refc == 0) {
X		mapc_clear(m);
X		free(m->map_name);
X		rem_que(&m->hdr);
X		free(m);
X	}
X}
X
X/*
X * Search the map for the key.
X * Put a safe copy in *pval or return
X * an error code
X */
Xint mapc_search(m, key, pval)
Xmnt_map *m;
Xchar *key;
Xchar **pval;
X{
X	int error = 0;
X	kv *k;
X
X	/*
X	 * Compute the hash table offset
X	 */
X	k = m->kvhash[kvhash_of(key)];
X
X	/*
X	 * Scan the linked list for the key
X	 */
X	while (k && !FSTREQ(k->key, key))
X		k = k->next;
X
X	/*
X	 * If found then take a copy
X	 */
X	if (k) {
X		if (k->val)
X			*pval = strdup(k->val);
X		else
X			error = ENOENT;
X	} else if (m->alloc == MAPC_ALL) {
X		/*
X		 * If the entire map is cached then this
X		 * key does not exist.
X		 */
X		error = ENOENT;
X	} else {
X		/*
X		 * Otherwise search the map.  If we are
X		 * in incremental mode then add the key
X		 * to the cache.
X		 */
X		error = search_map(m, key, pval);
X		if (!error && m->alloc == MAPC_INC)
X			mapc_add_kv(m, strdup(key), strdup(*pval));
X	}
X
X	/*
X	 * If an error, and a wildcard exists,
X	 * and the key is not internal then
X	 * return a copy of the wildcard.
X	 */
X	if (error && m->wildcard && *key != '/') {
X		*pval = strdup(m->wildcard);
X		return 0;
X	}
X
X	return error;
X}
X
Xstatic void mapc_sync(m)
Xmnt_map *m;
X{
X	mapc_clear(m);
X
X	if (m->alloc == MAPC_ALL)
X		if (mapc_reload_map(m))
X			m->alloc = MAPC_INC;
X	mapc_find_wildcard(m);
X}
X
X/*
X * Reload all the maps
X * Called when amd gets hit by a SIGHUP.
X */
Xvoid mapc_reload()
X{
X	mnt_map *m;
X
X	/*
X	 * For all the maps,
X	 * Throw away the existing information.
X	 * Do a reload
X	 * Find the wildcard
X	 */
X	ITER(m, mnt_map, &map_list_head)
X		mapc_sync(m);
X}
X
X/*
X * Root map.
X * The root map is used to bootstrap amd.
X * All the require top-level mounts are added
X * into the root map and then the map is iterated
X * and a lookup is done on all the mount points.
X * This causes the top level mounts to be automounted.
X */
X
Xstatic int root_init(map)
Xchar *map;
X{
X	return strcmp(map, ROOT_MAP) == 0 ? 0 : ENOENT;
X}
X
X/*
X * Add a new entry to the root map
X *
X * dir - directory (key)
X * opts - mount options
X * map - map name
X */
Xvoid root_newmap(dir, opts, map)
Xchar *dir;
Xchar *opts;
Xchar *map;
X{
X	char str[MAXPATHLEN];
X
X	if (!root_map)
X		root_map = mapc_find(ROOT_MAP, "all");
X
X	dir = strdup(dir);
X	sprintf(str, "cache:=none;type:=auto;fs:=\"%s\";%s", map, opts ? opts : "");
X	mapc_add_kv(root_map, dir, strdup(str));
X}
X
X/*
X * Iterate of the the root map
X * and call (*fn)() on the key
X * of all the nodes.
X * Finally throw away the root map.
X */
Xint root_keyiter(fn)
Xvoid (*fn)P((char*));
X{
X	int i;
X	int c = 0;
X
X	if (root_map) {
X		for (i = 0; i < NKVHASH; i++) {
X			kv *k = root_map->kvhash[i];
X			while (k) {
X				(*fn)(k->key);
X				k = k->next;
X				c++;
X			}
X		}
X		mapc_free(root_map);
X		root_map = 0;
X	}
X	return c;
X}
X
X/*
X * Error map
X */
Xstatic int error_init(map)
Xchar *map;
X{
X	return 0;
X}
X
X/*ARGSUSED*/
Xstatic int error_search(m, map, key, pval, tp)
Xmnt_map *m;
Xchar *map;
Xchar *key;
Xchar **pval;
Xtime_t *tp;
X{
X	return ENOENT;
X}
X
X/*ARGSUSED*/
Xstatic int error_reload(m, map, fn)
Xmnt_map *m;
Xchar *map;
Xadd_fn *fn;
X{
X	return ENOENT;
X}
END_OF_FILE
if test 11592 -ne `wc -c <'mapc.c'`; then
    echo shar: \"'mapc.c'\" unpacked with wrong size!
fi
# end of 'mapc.c'
fi
echo shar: End of archive 7 \(of 13\).
cp /dev/null ark7isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 13 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.