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.