v21i095: An Automounter for NFS systems, Part07/13
Rich Salz
rsalz at uunet.uu.net
Wed Apr 11 05:46:04 AEST 1990
Submitted-by: Jan-Simon Pendry <jsp at 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 at 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 at uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.
More information about the Comp.sources.unix
mailing list