Import of Erez Zadok's am-utils

This commit is contained in:
christos 1997-07-24 21:19:53 +00:00
parent 5dbbebc601
commit 5feec48523
61 changed files with 19444 additions and 0 deletions

67
usr.sbin/amd/AUTHORS Normal file
View File

@ -0,0 +1,67 @@
# -*- text -*-
PRIMARY AUTHORS AND MAJOR CONTRIBUTORS TO AM_UTILS:
Original authors of amd were the Berkeley team and especially Jan-Simon
Pendry. Since then many people have contributed patches.
This file lists the ones who contributed major code changes, and I thank
them all. This is of course not to diminish the smaller contributes of the
many others. Thank you all.
* Erez Zadok <ezk@cs.columbia.edu>
The most significant changes were made by Erez Zadok in terms of bug fixes,
ports, and new features added. Erez Zadok is the current maintainer of
am-utils, as of January 1997.
There is a mailing list dedicated to developers of am-utils. To subscribe
to it, send mail to majordomo@majordomo.cs.columbia.edu, with the body of
the message having the single line "subscribe amd-dev".
* Randall S. Winchester <rsw@glue.umd.edu>
May 7, 1997: contributed a special version of upl102 that included NFS V.3
support. Some of the code was contributed by Christos Zoulas
<christos@deshaw.com>. I (Erez) ported these changes to am-utils.
* Hannes Reinecke <hare@MathI.UNI-Heidelberg.DE>
Back in 1995, contributed code for linux. A new parser for file system
specific options that only exist under linux.
* Leif Johansson <leifj@matematik.su.se>
June 22, 1997: minor patch to ensure that systems without an RE library work.
June 23, 1997: mount options should be properly comma limited.
July 10, 1997: info_ldap.c and prototype changes to all map _init and _mtime
functions. Contributed scripts/amd2ldif.pl.
* Andreas Stolcke <stolcke@speech.sri.com>
June 22, 1997: patches to ensure that proto= and vers= options work
properly in mount tables and can be overridden. Later on, more code
contribued to optimize the best combination of proto/vers.
July 4, 1997: patches to get NFS V.3 working under irix5.
* Danny Braniss <danny@cs.huji.ac.il>
July, 6 1997: contributed patches to hesiod on bsdi3.
* Tom Schmidt <tschmidt@micron.com>
July 10, 1997: Recommdation to include libgdbm if libc has no dbm_open.
Patches for netgrp(host) command. Mods to aux/config.guess to recognize
sun3.
* Daniel S. Riley <dsr@mail.lns.cornell.edu>
July 11, 1997: fixes to DU-4.0 to support string POSIX.1 signals, and struct
sockaddr with sa_len field.
July 13, 1997: Move amd.conf parsing to before switch_option() on log/debug
options. Minor type wrt "ro" option in libamu/mount_fs.c. Added more
fillers of mnttab options, for acdirmax, acdirmin, acregmax, acregmin, noac,
grpid, nosuid, and actimo.

36
usr.sbin/amd/COPYING Normal file
View File

@ -0,0 +1,36 @@
Copyright (c) 1997 Erez Zadok
Copyright (c) 1989 Jan-Simon Pendry
Copyright (c) 1989 Imperial College of Science, Technology & Medicine
Copyright (c) 1989 The Regents of the University of California.
All rights reserved.
This code is derived from software contributed to Berkeley by
Jan-Simon Pendry at Imperial College, London.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by the University of
California, Berkeley and its contributors.
4. Neither the name of the University nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

148
usr.sbin/amd/amd/amq_svc.c Normal file
View File

@ -0,0 +1,148 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amq_svc.c,v 1.1.1.1 1997/07/24 21:20:37 christos Exp $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
void
amq_program_1(struct svc_req *rqstp, SVCXPRT *transp)
{
union {
amq_string amqproc_mnttree_1_arg;
amq_string amqproc_umnt_1_arg;
amq_setopt amqproc_setopt_1_arg;
amq_string amqproc_mount_1_arg;
} argument;
char *result;
bool_t(*xdr_argument) (), (*xdr_result) ();
char *(*local) ();
switch (rqstp->rq_proc) {
case AMQPROC_NULL:
xdr_argument = xdr_void;
xdr_result = xdr_void;
local = (char *(*)()) amqproc_null_1_svc;
break;
case AMQPROC_MNTTREE:
xdr_argument = xdr_amq_string;
xdr_result = xdr_amq_mount_tree_p;
local = (char *(*)()) amqproc_mnttree_1_svc;
break;
case AMQPROC_UMNT:
xdr_argument = xdr_amq_string;
xdr_result = xdr_void;
local = (char *(*)()) amqproc_umnt_1_svc;
break;
case AMQPROC_STATS:
xdr_argument = xdr_void;
xdr_result = xdr_amq_mount_stats;
local = (char *(*)()) amqproc_stats_1_svc;
break;
case AMQPROC_EXPORT:
xdr_argument = xdr_void;
xdr_result = xdr_amq_mount_tree_list;
local = (char *(*)()) amqproc_export_1_svc;
break;
case AMQPROC_SETOPT:
xdr_argument = xdr_amq_setopt;
xdr_result = xdr_int;
local = (char *(*)()) amqproc_setopt_1_svc;
break;
case AMQPROC_GETMNTFS:
xdr_argument = xdr_void;
xdr_result = xdr_amq_mount_info_qelem;
local = (char *(*)()) amqproc_getmntfs_1_svc;
break;
case AMQPROC_MOUNT:
xdr_argument = xdr_amq_string;
xdr_result = xdr_int;
local = (char *(*)()) amqproc_mount_1_svc;
break;
case AMQPROC_GETVERS:
xdr_argument = xdr_void;
xdr_result = xdr_amq_string;
local = (char *(*)()) amqproc_getvers_1_svc;
break;
default:
svcerr_noproc(transp);
return;
}
memset((char *) &argument, 0, sizeof(argument));
if (!svc_getargs(transp,
(XDRPROC_T_TYPE) xdr_argument,
(SVC_IN_ARG_TYPE) & argument)) {
svcerr_decode(transp);
return;
}
result = (*local) (&argument, rqstp);
if (result != NULL && !svc_sendreply(transp,
(XDRPROC_T_TYPE) xdr_result,
result)) {
svcerr_systemerr(transp);
}
if (!svc_freeargs(transp,
(XDRPROC_T_TYPE) xdr_argument,
(SVC_IN_ARG_TYPE) & argument)) {
plog(XLOG_FATAL, "unable to free rpc arguments in amqprog_1");
going_down(1);
}
}

469
usr.sbin/amd/amd/autil.c Normal file
View File

@ -0,0 +1,469 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: autil.c,v 1.1.1.1 1997/07/24 21:20:37 christos Exp $
*
*/
/*
* utilities specified to amd, taken out of the older amd/util.c.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
int NumChild = 0; /* number of children of primary amd */
static char invalid_keys[] = "\"'!;@ \t\n";
#ifdef HAVE_TRANSPORT_TYPE_TLI
# define PARENT_USLEEP_TIME 100000 /* 0.1 seconds */
#endif /* HAVE_TRANSPORT_TYPE_TLI */
char *
strealloc(char *p, char *s)
{
int len = strlen(s) + 1;
p = (char *) xrealloc((voidp) p, len);
strcpy(p, s);
#ifdef DEBUG_MEM
malloc_verify();
#endif /* DEBUG_MEM */
return p;
}
char **
strsplit(char *s, int ch, int qc)
{
char **ivec;
int ic = 0;
int done = 0;
ivec = (char **) xmalloc((ic + 1) * sizeof(char *));
while (!done) {
char *v;
/*
* skip to split char
*/
while (*s && (ch == ' ' ? (isascii(*s) && isspace(*s)) : *s == ch))
*s++ = '\0';
/*
* End of string?
*/
if (!*s)
break;
/*
* remember start of string
*/
v = s;
/*
* skip to split char
*/
while (*s && !(ch == ' ' ? (isascii(*s) && isspace(*s)) : *s == ch)) {
if (*s++ == qc) {
/*
* Skip past string.
*/
s++;
while (*s && *s != qc)
s++;
if (*s == qc)
s++;
}
}
if (!*s)
done = 1;
*s++ = '\0';
/*
* save string in new ivec slot
*/
ivec[ic++] = v;
ivec = (char **) xrealloc((voidp) ivec, (ic + 1) * sizeof(char *));
#ifdef DEBUG
amuDebug(D_STR)
plog(XLOG_DEBUG, "strsplit saved \"%s\"", v);
#endif /* DEBUG */
}
#ifdef DEBUG
amuDebug(D_STR)
plog(XLOG_DEBUG, "strsplit saved a total of %d strings", ic);
#endif /* DEBUG */
ivec[ic] = 0;
return ivec;
}
/*
* Strip off the trailing part of a domain
* to produce a short-form domain relative
* to the local host domain.
* Note that this has no effect if the domain
* names do not have the same number of
* components. If that restriction proves
* to be a problem then the loop needs recoding
* to skip from right to left and do partial
* matches along the way -- ie more expensive.
*/
static void
domain_strip(char *otherdom, char *localdom)
{
char *p1, *p2;
if ((p1 = strchr(otherdom, '.')) &&
(p2 = strchr(localdom, '.')) &&
STREQ(p1 + 1, p2 + 1))
*p1 = '\0';
}
/*
* Normalize a host name
*/
void
host_normalize(char **chp)
{
/*
* Normalize hosts is used to resolve host name aliases
* and replace them with the standard-form name.
* Invoked with "-n" command line option.
*/
if (gopt.flags & CFM_NORMALIZE_HOSTNAMES) {
struct hostent *hp;
clock_valid = 0;
hp = gethostbyname(*chp);
if (hp && hp->h_addrtype == AF_INET) {
#ifdef DEBUG
dlog("Hostname %s normalized to %s", *chp, hp->h_name);
#endif /* DEBUG */
*chp = strealloc(*chp, (char *) hp->h_name);
}
}
domain_strip(*chp, hostd);
}
/*
* Keys are not allowed to contain " ' ! or ; to avoid
* problems with macro expansions.
*/
int
valid_key(char *key)
{
while (*key)
if (strchr(invalid_keys, *key++))
return FALSE;
return TRUE;
}
void
forcibly_timeout_mp(am_node *mp)
{
mntfs *mf = mp->am_mnt;
/*
* Arrange to timeout this node
*/
if (mf && ((mp->am_flags & AMF_ROOT) ||
(mf->mf_flags & (MFF_MOUNTING | MFF_UNMOUNTING)))) {
if (!(mf->mf_flags & MFF_UNMOUNTING))
plog(XLOG_WARNING, "ignoring timeout request for active node %s", mp->am_path);
} else {
plog(XLOG_INFO, "\"%s\" forcibly timed out", mp->am_path);
mp->am_flags &= ~AMF_NOTIMEOUT;
mp->am_ttl = clocktime();
reschedule_timeout_mp();
}
}
void
mf_mounted(mntfs *mf)
{
int quoted;
int wasmounted = mf->mf_flags & MFF_MOUNTED;
if (!wasmounted) {
/*
* If this is a freshly mounted
* filesystem then update the
* mntfs structure...
*/
mf->mf_flags |= MFF_MOUNTED;
mf->mf_error = 0;
/*
* Do mounted callback
*/
if (mf->mf_ops->mounted) {
(*mf->mf_ops->mounted) (mf);
}
mf->mf_fo = 0;
}
/*
* Log message
*/
quoted = strchr(mf->mf_info, ' ') != 0;
plog(XLOG_INFO, "%s%s%s %s fstype %s on %s",
quoted ? "\"" : "",
mf->mf_info,
quoted ? "\"" : "",
wasmounted ? "referenced" : "mounted",
mf->mf_ops->fs_type, mf->mf_mount);
}
void
am_mounted(am_node *mp)
{
mntfs *mf = mp->am_mnt;
mf_mounted(mf);
/*
* Patch up path for direct mounts
*/
if (mp->am_parent && mp->am_parent->am_mnt->mf_ops == &dfs_ops)
mp->am_path = str3cat(mp->am_path, mp->am_parent->am_path, "/", ".");
/*
* Check whether this mount should be cached permanently
*/
if (mf->mf_ops->fs_flags & FS_NOTIMEOUT) {
mp->am_flags |= AMF_NOTIMEOUT;
} else if (mf->mf_mount[1] == '\0' && mf->mf_mount[0] == '/') {
mp->am_flags |= AMF_NOTIMEOUT;
} else {
mntent_t mnt;
if (mf->mf_mopts) {
mnt.mnt_opts = mf->mf_mopts;
if (hasmntopt(&mnt, "nounmount"))
mp->am_flags |= AMF_NOTIMEOUT;
if ((mp->am_timeo = hasmntval(&mnt, "utimeout")) == 0)
mp->am_timeo = gopt.am_timeo;
}
}
/*
* If this node is a symlink then
* compute the length of the returned string.
*/
if (mp->am_fattr.na_type == NFLNK)
mp->am_fattr.na_size = strlen(mp->am_link ? mp->am_link : mp->am_mnt->mf_mount);
/*
* Record mount time
*/
mp->am_fattr.na_mtime.nt_seconds = mp->am_stats.s_mtime = clocktime();
new_ttl(mp);
/*
* Update mtime of parent node
*/
if (mp->am_parent && mp->am_parent->am_mnt)
mp->am_parent->am_fattr.na_mtime.nt_seconds = mp->am_stats.s_mtime;
/*
* Now, if we can, do a reply to our NFS client here
* to speed things up.
*/
quick_reply(mp, 0);
/*
* Update stats
*/
amd_stats.d_mok++;
}
int
mount_node(am_node *mp)
{
mntfs *mf = mp->am_mnt;
int error;
mf->mf_flags |= MFF_MOUNTING;
error = (*mf->mf_ops->mount_fs) (mp);
mf = mp->am_mnt;
if (error >= 0)
mf->mf_flags &= ~MFF_MOUNTING;
if (!error && !(mf->mf_ops->fs_flags & FS_MBACKGROUND)) {
/* ...but see ifs_mount */
am_mounted(mp);
}
return error;
}
void
am_unmounted(am_node *mp)
{
mntfs *mf = mp->am_mnt;
if (!foreground) /* firewall - should never happen */
return;
/*
* Do unmounted callback
*/
if (mf->mf_ops->umounted)
(*mf->mf_ops->umounted) (mp);
/*
* Update mtime of parent node
*/
if (mp->am_parent && mp->am_parent->am_mnt)
mp->am_parent->am_fattr.na_mtime.nt_seconds = clocktime();
free_map(mp);
}
int
auto_fmount(am_node *mp)
{
mntfs *mf = mp->am_mnt;
return (*mf->mf_ops->fmount_fs) (mf);
}
int
auto_fumount(am_node *mp)
{
mntfs *mf = mp->am_mnt;
return (*mf->mf_ops->fumount_fs) (mf);
}
/*
* Fork the automounter
*
* TODO: Need a better strategy for handling errors
*/
static int
dofork(void)
{
int pid;
top:
pid = fork();
if (pid < 0) { /* fork error, retry in 1 second */
sleep(1);
goto top;
}
if (pid == 0) { /* child process (foreground==false) */
mypid = getpid();
foreground = 0;
#ifdef HAVE_TRANSPORT_TYPE_TLI_off
/*
* The sleep() right here is a hacky solution to some race conditions on
* some systems, esp. Solaris with TLI on fast CPUs. Without it, all
* top-level mounts bombard the system very fast, and some of them,
* possibly the non-blocking RPCs, get lost. It is not guaranteed who
* and how many get lost; sometimes none, sometimes all but one. I've
* seen things like that under older systems like Mach-3 Either way.
* This hack seems to solve the problem. Note that the sleep() is
* progressively greater as there are more children, so as to
* "randomize" the order in which they will reply back to the parent amd
* process. It helps in getting the replies delivered back in order.
* These hopefully don't slow down amd by much overall. For the time
* being, I'm going to make this code dependent on TLI, because I have
* no evidence that it is needed on any other system. Anyone is welcome
* to figure out the bug or race condition.
*
* It is also possible that if there are too many children sending out
* their (unreliable) UDP datagrams over the fwd_sock, that some of them
* simply get lost. Then there's always the possibility that this is a
* kernel networking bug.
*
* -Erez Zadok <ezk@cs.columbia.edu>
*/
if (NumChild > 0) {
plog(XLOG_INFO,"too many background children(%d). sleep %d mSec...",
NumChild, PARENT_USLEEP_TIME*NumChild);
usleep(PARENT_USLEEP_TIME*NumChild);
}
#endif /* HAVE_TRANSPORT_TYPE_TLI */
} else { /* parent process, has one more child */
NumChild++;
#ifdef HAVE_TRANSPORT_TYPE_TLI_off
if (NumChild > 1) {
plog(XLOG_INFO,"parent sleeps for %d mSec...",
PARENT_USLEEP_TIME*NumChild);
usleep(PARENT_USLEEP_TIME*NumChild);
}
#endif /* HAVE_TRANSPORT_TYPE_TLI */
}
return pid;
}
int
background(void)
{
int pid = dofork();
if (pid == 0) {
#ifdef DEBUG
dlog("backgrounded");
#endif /* DEBUG */
foreground = 0;
}
return pid;
}

View File

@ -0,0 +1,3 @@
/* do not edit this file by hand */
/* auto-generated by update_build_version script */
#define AMU_BUILD_VERSION 1

767
usr.sbin/amd/amd/conf.c Normal file
View File

@ -0,0 +1,767 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: conf.c,v 1.1.1.1 1997/07/24 21:20:42 christos Exp $
*
*/
/*
* Functions to handle the configuration file.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/*
* MACROS:
*/
/* Turn on to show some info about maps being configured */
/* #define DEBUG_CONF */
/*
* TYPEDEFS:
*/
typedef int (*OptFuncPtr)(const char *);
/*
* STRUCTURES:
*/
struct _func_map {
char *name;
OptFuncPtr func;
};
/*
* FORWARD DECLARATIONS:
*/
static int gopt_arch(const char *val);
static int gopt_auto_dir(const char *val);
static int gopt_browsable_dirs(const char *val);
static int gopt_cache_duration(const char *val);
static int gopt_cluster(const char *val);
static int gopt_debug_options(const char *val);
static int gopt_dismount_interval(const char *val);
static int gopt_karch(const char *val);
static int gopt_ldap_base(const char *val);
static int gopt_ldap_hostports(const char *val);
static int gopt_local_domain(const char *val);
static int gopt_log_file(const char *val);
static int gopt_log_options(const char *val);
static int gopt_map_options(const char *val);
static int gopt_map_type(const char *val);
static int gopt_mount_type(const char *val);
static int gopt_nfs_retransmit_counter(const char *val);
static int gopt_nfs_retry_interval(const char *val);
static int gopt_nis_domain(const char *val);
static int gopt_normalize_hostnames(const char *val);
static int gopt_os(const char *val);
static int gopt_osver(const char *val);
static int gopt_plock(const char *val);
static int gopt_print_pid(const char *val);
static int gopt_print_version(const char *val);
static int gopt_restart_mounts(const char *val);
static int gopt_search_path(const char *val);
static int gopt_selectors_on_default(const char *val);
static int process_global_option(const char *key, const char *val);
static int process_regular_map(cf_map_t *cfm);
static int process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm);
static int ropt_browsable_dirs(const char *val, cf_map_t *cfm);
static int ropt_map_name(const char *val, cf_map_t *cfm);
static int ropt_map_options(const char *val, cf_map_t *cfm);
static int ropt_map_type(const char *val, cf_map_t *cfm);
static int ropt_mount_type(const char *val, cf_map_t *cfm);
static int ropt_search_path(const char *val, cf_map_t *cfm);
static int ropt_tag(const char *val, cf_map_t *cfm);
static void reset_cf_map(cf_map_t *cfm);
/*
* STATIC VARIABLES:
*/
static cf_map_t cur_map;
static struct _func_map glob_functable[] = {
{"arch", gopt_arch},
{"auto_dir", gopt_auto_dir},
{"browsable_dirs", gopt_browsable_dirs},
{"cache_duration", gopt_cache_duration},
{"cluster", gopt_cluster},
{"debug_options", gopt_debug_options},
{"dismount_interval", gopt_dismount_interval},
{"karch", gopt_karch},
{"ldap_base", gopt_ldap_base},
{"ldap_hostports", gopt_ldap_hostports},
{"local_domain", gopt_local_domain},
{"log_file", gopt_log_file},
{"log_options", gopt_log_options},
{"map_options", gopt_map_options},
{"map_type", gopt_map_type},
{"mount_type", gopt_mount_type},
{"nfs_retransmit_counter", gopt_nfs_retransmit_counter},
{"nfs_retry_interval", gopt_nfs_retry_interval},
{"nis_domain", gopt_nis_domain},
{"normalize_hostnames", gopt_normalize_hostnames},
{"os", gopt_os},
{"osver", gopt_osver},
{"plock", gopt_plock},
{"print_pid", gopt_print_pid},
{"print_version", gopt_print_version},
{"restart_mounts", gopt_restart_mounts},
{"search_path", gopt_search_path},
{"selectors_on_default", gopt_selectors_on_default},
{NULL, NULL}
};
/*
* Reset a map.
*/
static void
reset_cf_map(cf_map_t *cfm)
{
if (!cfm)
return;
if (cfm->cfm_dir) {
free(cfm->cfm_dir);
cfm->cfm_dir = NULL;
}
if (cfm->cfm_name) {
free(cfm->cfm_name);
cfm->cfm_name = NULL;
}
/*
* reset/initialize a regular map's flags and other variables from the
* global ones, so that they are applied to all maps. Of course, each map
* can then override the flags individually.
*
* NOTES:
* (1): Will only work for maps that appear after [global].
* (2): Also be careful not to free() a global option.
* (3): I'm doing direct char* pointer comparison, and not strcmp(). This
* is correct!
*/
/* initialize map_type from [global] */
if (cfm->cfm_type && cfm->cfm_type != gopt.map_type)
free(cfm->cfm_type);
cfm->cfm_type = gopt.map_type;
/* initialize map_opts from [global] */
if (cfm->cfm_opts && cfm->cfm_opts != gopt.map_options)
free(cfm->cfm_opts);
cfm->cfm_opts = gopt.map_options;
/* initialize search_path from [global] */
if (cfm->cfm_search_path && cfm->cfm_search_path != gopt.search_path)
free(cfm->cfm_search_path);
cfm->cfm_search_path = gopt.search_path;
/*
* Initialize flags that are common both to [global] and a local map.
*/
cfm->cfm_flags = gopt.flags & (CFM_BROWSABLE_DIRS |
CFM_MOUNT_TYPE_AUTOFS |
CFM_ENABLE_DEFAULT_SELECTORS);
}
/*
* Process configuration file options.
* Return 0 if OK, 1 otherwise.
*/
int
set_conf_kv(const char *section, const char *key, const char *val)
{
int ret;
#ifdef DEBUG_CONF
fprintf(stderr,"set_conf_kv: section=%s, key=%s, val=%s\n",
section, key, val);
#endif /* DEBUG_CONF */
/*
* If global section, process them one at a time.
*/
if (STREQ(section, "global")) {
/*
* Check if a regular map was configured before "global",
* and process it as needed.
*/
if (cur_map.cfm_dir) {
fprintf(stderr,"processing regular map \"%s\" before global one.\n",
section);
ret = process_regular_map(&cur_map); /* will reset map */
if (ret != 0)
return ret;
}
/* process the global option first */
ret = process_global_option(key, val);
/* reset default options for regular maps from just updated globals */
if (ret == 0)
reset_cf_map(&cur_map);
/* return status from the processing of the global option */
return ret;
}
/*
* otherwise save options and process a single map all at once.
*/
/* check if we found a new map, so process one already collected */
if (cur_map.cfm_dir && !STREQ(cur_map.cfm_dir, section)) {
ret = process_regular_map(&cur_map); /* will reset map */
if (ret != 0)
return ret;
}
/* now process a single entry of a regular map */
return process_regular_option(section, key, val, &cur_map);
}
/*
* Process global section of configuration file options.
* Return 0 upon success, 1 otherwise.
*/
static int
process_global_option(const char *key, const char *val)
{
struct _func_map *gfp;
/* ensure that val is valid */
if (!val || val[0] == '\0')
return 1;
/*
* search for global function.
*/
for (gfp = glob_functable; gfp->name; gfp++)
if (FSTREQ(gfp->name, key))
return (gfp->func)(val);
fprintf(stderr, "conf: unknown global key: \"%s\"\n", key);
return 1; /* failed to match any command */
}
static int
gopt_arch(const char *val)
{
gopt.arch = strdup((char *)val);
return 0;
}
static int
gopt_auto_dir(const char *val)
{
gopt.auto_dir = strdup((char *)val);
return 0;
}
static int
gopt_browsable_dirs(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_BROWSABLE_DIRS;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_BROWSABLE_DIRS;
return 0;
}
fprintf(stderr, "conf: unknown value to browsable_dirs \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_cache_duration(const char *val)
{
gopt.am_timeo = atoi(val);
if (gopt.am_timeo <= 0)
gopt.am_timeo = AM_TTL;
return 0;
}
static int
gopt_cluster(const char *val)
{
gopt.cluster = strdup((char *)val);
return 0;
}
static int
gopt_debug_options(const char *val)
{
#ifdef DEBUG
usage += debug_option(strdup((char *)val));
return 0;
#else /* not DEBUG */
fprintf(stderr, "%s: not compiled with DEBUG option -- sorry.\n",
progname);
return 1;
#endif /* not DEBUG */
}
static int
gopt_dismount_interval(const char *val)
{
gopt.am_timeo_w = atoi(val);
if (gopt.am_timeo_w <= 0)
gopt.am_timeo_w = AM_TTL_W;
return 0;
}
static int
gopt_karch(const char *val)
{
gopt.karch = strdup((char *)val);
return 0;
}
static int
gopt_local_domain(const char *val)
{
gopt.sub_domain = strdup((char *)val);
return 0;
}
static int
gopt_ldap_base(const char *val)
{
#ifdef HAVE_MAP_LDAP
gopt.ldap_base = strdup((char *)val);
return 0;
#else /* not HAVE_MAP_LDAP */
fprintf(stderr, "conf: ldap_base option ignored. No LDAP support available.\n");
return 1;
#endif /* not HAVE_MAP_LDAP */
}
static int
gopt_ldap_hostports(const char *val)
{
#ifdef HAVE_MAP_LDAP
gopt.ldap_hostports = strdup((char *)val);
return 0;
#else /* not HAVE_MAP_LDAP */
fprintf(stderr, "conf: ldap_hostports option ignored. No LDAP support available.\n");
return 1;
#endif /* not HAVE_MAP_LDAP */
}
static int
gopt_log_file(const char *val)
{
gopt.logfile = strdup((char *)val);
return 0;
}
static int
gopt_log_options(const char *val)
{
usage += switch_option(strdup((char *)val));
return 0;
}
static int
gopt_map_options(const char *val)
{
gopt.map_options = strdup((char *)val);
return 0;
}
static int
gopt_map_type(const char *val)
{
gopt.map_type = strdup((char *)val);
return 0;
}
static int
gopt_mount_type(const char *val)
{
if (STREQ(val, "autofs")) {
gopt.flags |= CFM_MOUNT_TYPE_AUTOFS;
return 0;
} else if (STREQ(val, "nfs")) {
gopt.flags &= ~CFM_MOUNT_TYPE_AUTOFS;
return 0;
}
fprintf(stderr, "conf: unknown value to mount_type \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_nfs_retransmit_counter(const char *val)
{
gopt.afs_retrans = atoi(val);
return 0;
}
static int
gopt_nfs_retry_interval(const char *val)
{
gopt.afs_timeo = atoi(val);
return 0;
}
static int
gopt_nis_domain(const char *val)
{
#ifdef HAVE_MAP_NIS
gopt.nis_domain = strdup((char *)val);
return 0;
#else /* not HAVE_MAP_NIS */
fprintf(stderr, "conf: nis_domain option ignored. No NIS support available.\n");
return 1;
#endif /* not HAVE_MAP_NIS */
}
static int
gopt_normalize_hostnames(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_NORMALIZE_HOSTNAMES;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_NORMALIZE_HOSTNAMES;
return 0;
}
fprintf(stderr, "conf: unknown value to normalize_hostnames \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_os(const char *val)
{
gopt.op_sys = strdup((char *)val);
return 0;
}
static int
gopt_osver(const char *val)
{
gopt.op_sys_ver = strdup((char *)val);
return 0;
}
static int
gopt_plock(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_NOSWAP;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_NOSWAP;
return 0;
}
fprintf(stderr, "conf: unknown value to plock \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_print_pid(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_PRINT_PID;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_PRINT_PID;
return 0;
}
fprintf(stderr, "conf: unknown value to print_pid \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_print_version(const char *val)
{
if (STREQ(val, "yes")) {
fputs(get_version_string(), stderr);
return 0;
} else if (STREQ(val, "no")) {
return 0;
}
fprintf(stderr, "conf: unknown value to print_version \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_restart_mounts(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_RESTART_EXISTING_MOUNTS;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_RESTART_EXISTING_MOUNTS;
return 0;
}
fprintf(stderr, "conf: unknown value to restart_mounts \"%s\"\n", val);
return 1; /* unknown value */
}
static int
gopt_search_path(const char *val)
{
gopt.search_path = strdup((char *)val);
return 0;
}
static int
gopt_selectors_on_default(const char *val)
{
if (STREQ(val, "yes")) {
gopt.flags |= CFM_ENABLE_DEFAULT_SELECTORS;
return 0;
} else if (STREQ(val, "no")) {
gopt.flags &= ~CFM_ENABLE_DEFAULT_SELECTORS;
return 0;
}
fprintf(stderr, "conf: unknown value to enable_default_selectors \"%s\"\n", val);
return 1; /* unknown value */
}
/*
* Collect one entry for a regular map
*/
static int
process_regular_option(const char *section, const char *key, const char *val, cf_map_t *cfm)
{
/* ensure that val is valid */
if (!section || section[0] == '\0' ||
!key || key[0] == '\0' ||
!val || val[0] == '\0' ||
!cfm) {
fprintf(stderr, "conf: process_regular_option: null entries\n");
return 1;
}
/* check if initializing a new map */
if (!cfm->cfm_dir)
cfm->cfm_dir = strdup((char *)section);
/* check for each possible field */
if (STREQ(key, "browsable_dirs"))
return ropt_browsable_dirs(val, cfm);
if (STREQ(key, "map_name"))
return ropt_map_name(val, cfm);
if (STREQ(key, "map_options"))
return ropt_map_options(val, cfm);
if (STREQ(key, "map_type"))
return ropt_map_type(val, cfm);
if (STREQ(key, "mount_type"))
return ropt_mount_type(val, cfm);
if (STREQ(key, "search_path"))
return ropt_search_path(val, cfm);
if (STREQ(key, "tag"))
return ropt_tag(val, cfm);
fprintf(stderr, "conf: unknown regular key \"%s\" for section \"%s\"\n",
key, section);
return 1; /* failed to match any command */
}
static int
ropt_browsable_dirs(const char *val, cf_map_t *cfm)
{
if (STREQ(val, "yes")) {
cfm->cfm_flags |= CFM_BROWSABLE_DIRS;
return 0;
} else if (STREQ(val, "no")) {
cfm->cfm_flags &= ~CFM_BROWSABLE_DIRS;
return 0;
}
fprintf(stderr, "conf: unknown value to browsable_dirs \"%s\"\n", val);
return 1; /* unknown value */
}
static int
ropt_map_name(const char *val, cf_map_t *cfm)
{
cfm->cfm_name = strdup((char *)val);
return 0;
}
static int
ropt_map_options(const char *val, cf_map_t *cfm)
{
cfm->cfm_opts = strdup((char *)val);
return 0;
}
static int
ropt_map_type(const char *val, cf_map_t *cfm)
{
cfm->cfm_type = strdup((char *)val);
return 0;
}
static int
ropt_mount_type(const char *val, cf_map_t *cfm)
{
if (STREQ(val, "autofs")) {
cfm->cfm_flags |= CFM_MOUNT_TYPE_AUTOFS;
return 0;
} else if (STREQ(val, "nfs")) {
cfm->cfm_flags &= ~CFM_MOUNT_TYPE_AUTOFS;
return 0;
}
fprintf(stderr, "conf: unknown value to mount_type \"%s\"\n", val);
return 1; /* unknown value */
}
static int
ropt_search_path(const char *val, cf_map_t *cfm)
{
cfm->cfm_search_path = strdup((char *)val);
return 0;
}
static int
ropt_tag(const char *val, cf_map_t *cfm)
{
cfm->cfm_tag = strdup((char *)val);
return 0;
}
/*
* Process one collected map.
*/
static int
process_regular_map(cf_map_t *cfm)
{
if (!cfm->cfm_name) {
fprintf(stderr, "conf: map_name must be defined for map \"%s\"\n", cfm->cfm_dir);
return 1;
}
/*
* If map has no tag defined, process the map.
* If no conf_tag was set in amd -T, process all untagged entries.
* If a tag is defined, then process it only if it matches the map tag.
*/
if (!cfm->cfm_tag ||
(conf_tag && STREQ(cfm->cfm_tag, conf_tag))) {
#ifdef DEBUG_CONF
fprintf(stderr, "processing map %s (flags=0x%x)...\n",
cfm->cfm_dir, cfm->cfm_flags);
#endif /* DEBUG_CONF */
root_newmap(cfm->cfm_dir,
cfm->cfm_opts ? cfm->cfm_opts : "",
cfm->cfm_name,
cfm);
} else {
fprintf(stderr, "skipping map %s...\n", cfm->cfm_dir);
}
reset_cf_map(cfm);
return 0;
}
/*
* Process last map in conf file
*/
int
process_last_regular_map(void)
{
return process_regular_map(&cur_map);
}

View File

@ -0,0 +1,159 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: conf_parse.y,v 1.1.1.1 1997/07/24 21:22:27 christos Exp $
*
*/
%{
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
extern char *yytext;
extern int yylineno;
extern int yylex(void);
static int yyerror(const char *s);
static int retval;
static char *header_section = NULL; /* start with no header section */
#define YYDEBUG 1
#define PARSE_DEBUG 0
#if PARSE_DEBUG
# define dprintf(f,s) fprintf(stderr, (f), yylineno, (s))
# define amu_return(v)
#else
# define dprintf(f,s)
# define amu_return(v) return((v))
#endif /* PARSE_DEBUG */
%}
%union {
char *strtype;
}
%token LEFT_BRACKET RIGHT_BRACKET EQUAL
%token NEWLINE
%token <strtype> NONWS_STRING
%token <strtype> NONWSEQ_STRING
%token <strtype> QUOTED_NONWSEQ_STRING
%start file
%%
/****************************************************************************/
file : { yydebug = PARSE_DEBUG; } newlines map_sections
| { yydebug = PARSE_DEBUG; } map_sections
;
newlines : NEWLINE
| NEWLINE newlines
;
map_sections : map_section
| map_section map_sections
;
map_section : sec_header kv_pairs
;
sec_header : LEFT_BRACKET NONWS_STRING RIGHT_BRACKET NEWLINE
{
if (yydebug)
fprintf(stderr, "sec_header1 = \"%s\"\n", $2);
header_section = $2;
}
;
kv_pairs : kv_pair
| kv_pair kv_pairs
;
kv_pair : NONWS_STRING EQUAL NONWS_STRING NEWLINE
{
if (yydebug)
fprintf(stderr,"parse1: key=\"%s\", val=\"%s\"\n", $1, $3);
retval = set_conf_kv(header_section, $1, $3);
if (retval != 0) {
yyerror("syntax error");
YYABORT;
}
}
| NONWS_STRING EQUAL NONWSEQ_STRING NEWLINE
{
if (yydebug)
fprintf(stderr,"parse2: key=\"%s\", val=\"%s\"\n", $1, $3);
retval = set_conf_kv(header_section, $1, $3);
if (retval != 0) {
yyerror("syntax error");
YYABORT;
}
}
| NONWS_STRING EQUAL QUOTED_NONWSEQ_STRING NEWLINE
{
if (yydebug)
fprintf(stderr,"parse3: key=\"%s\", val=\"%s\"\n", $1, $3);
retval = set_conf_kv(header_section, $1, $3);
if (retval != 0) {
yyerror("syntax error");
YYABORT;
}
}
| NEWLINE
;
/****************************************************************************/
%%
static int
yyerror(const char *s)
{
fprintf(stderr, "AMDCONF: %s on line %d (section %s)\n",
s, yylineno,
(header_section ? header_section : "null"));
exit(1);
return 1; /* to full compilers that insist on a return statement */
}

165
usr.sbin/amd/amd/conf_tok.l Normal file
View File

@ -0,0 +1,165 @@
%{
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: conf_tok.l,v 1.1.1.1 1997/07/24 21:22:27 christos Exp $
*
*/
/*
* Lexical analyzer for AMD configuration parser.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
/*
* Some systems include a definition for the macro ECHO in <sys/ioctl.h>,
* and their (bad) version of lex defines it too at the very beginning of
* the generated lex.yy.c file (before it can be easily undefined),
* resulting in a conflict. So undefine it here before needed.
* Luckily, it does not appear that this macro is actually used in the rest
* of the generated lex.yy.c file.
*/
#ifdef ECHO
# undef ECHO
#endif /* ECHO */
#include <am_defs.h>
#include <amd.h>
#include <conf_parse.h>
/*
* There are some things that need to be defined only if useing GNU flex.
* These must not be defined if using standard lex
*/
#ifdef FLEX_SCANNER
int yylineno = 0;
#endif /* FLEX_SCANNER */
int yylex(void);
int yywrap(void);
#define TOK_DEBUG 0
#if TOK_DEBUG
# define dprintf(f,s) fprintf(stderr, (f), yylineno, (s))
# define amu_return(v)
#else
# define dprintf(f,s)
# define amu_return(v) return((v))
#endif /* TOK_DEBUG */
/* no need to use yyunput() or yywrap() */
#define YY_NO_UNPUT
#define YY_SKIP_YYWRAP
%}
DIGIT [0-9]
ALPHA [A-Za-z]
ALPHANUM [A-Za-z0-9]
SYMBOL [A-Za-z0-9_-]
PATH [A-Za-z0-9_-/]
NONWSCHAR [^ \t\n\[\]=]
NONWSEQCHAR [^ \t\n\[\]]
NONNL [^\n]
NONQUOTE [^\"]
%%
\n {
yylineno++;
amu_return(NEWLINE);
}
\[ {
dprintf("%8d: Left bracket \"%s\"\n", yytext);
yylval.strtype = strdup(yytext);
amu_return(LEFT_BRACKET);
}
\] {
dprintf("%8d: Right bracket \"%s\"\n", yytext);
yylval.strtype = strdup(yytext);
amu_return(RIGHT_BRACKET);
}
= {
dprintf("%8d: Equal \"%s\"\n", yytext);
yylval.strtype = strdup(yytext);
amu_return(EQUAL);
}
[ \t]* {
dprintf("%8d: Whitespace \"%s\"\n", yytext);
}
"#"[^\n]*\n {
/* a comment line includes the terminating \n */
yylineno++;
yytext[strlen(yytext)-1] = '\0';
dprintf("%8d: Comment \"%s\"\n", yytext);
}
{NONWSCHAR}{NONWSCHAR}* {
dprintf("%8d: Non-WS string \"%s\"\n", yytext);
yylval.strtype = strdup(yytext);
amu_return(NONWS_STRING);
}
\"{NONQUOTE}{NONQUOTE}*\" {
dprintf("%8d: QUOTED-Non-WS-EQ string \"%s\"\n", yytext);
/* must strip quotes */
yytext[strlen(yytext)-1] = '\0';
yylval.strtype = strdup(&yytext[1]);
amu_return(QUOTED_NONWSEQ_STRING);
}
{NONWSEQCHAR}{NONWSEQCHAR}* {
dprintf("%8d: Non-WS-EQ string \"%s\"\n", yytext);
yylval.strtype = strdup(yytext);
amu_return(NONWSEQ_STRING);
}
%%
int yywrap(void)
{
return 1;
}

View File

@ -0,0 +1,245 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: nfs_prot_svc.c,v 1.1.1.1 1997/07/24 21:21:27 christos Exp $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
extern void * nfsproc_null_2_svc(void *, struct svc_req *);
extern nfsattrstat * nfsproc_getattr_2_svc(am_nfs_fh *, struct svc_req *);
extern nfsattrstat * nfsproc_setattr_2_svc(nfssattrargs *, struct svc_req *);
extern void * nfsproc_root_2_svc(void *, struct svc_req *);
extern nfsdiropres * nfsproc_lookup_2_svc(nfsdiropargs *, struct svc_req *);
extern nfsreadlinkres * nfsproc_readlink_2_svc(am_nfs_fh *, struct svc_req *);
extern nfsreadres * nfsproc_read_2_svc(nfsreadargs *, struct svc_req *);
extern void * nfsproc_writecache_2_svc(void *, struct svc_req *);
extern nfsattrstat * nfsproc_write_2_svc(nfswriteargs *, struct svc_req *);
extern nfsdiropres * nfsproc_create_2_svc(nfscreateargs *, struct svc_req *);
extern nfsstat * nfsproc_remove_2_svc(nfsdiropargs *, struct svc_req *);
extern nfsstat * nfsproc_rename_2_svc(nfsrenameargs *, struct svc_req *);
extern nfsstat * nfsproc_link_2_svc(nfslinkargs *, struct svc_req *);
extern nfsstat * nfsproc_symlink_2_svc(nfssymlinkargs *, struct svc_req *);
extern nfsdiropres * nfsproc_mkdir_2_svc(nfscreateargs *, struct svc_req *);
extern nfsstat * nfsproc_rmdir_2_svc(nfsdiropargs *, struct svc_req *);
extern nfsreaddirres * nfsproc_readdir_2_svc(nfsreaddirargs *, struct svc_req *);
extern nfsstatfsres * nfsproc_statfs_2_svc(am_nfs_fh *, struct svc_req *);
SVCXPRT *nfs_program_2_transp;
void
nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
{
union {
am_nfs_fh nfsproc_getattr_2_arg;
nfssattrargs nfsproc_setattr_2_arg;
nfsdiropargs nfsproc_lookup_2_arg;
am_nfs_fh nfsproc_readlink_2_arg;
nfsreadargs nfsproc_read_2_arg;
nfswriteargs nfsproc_write_2_arg;
nfscreateargs nfsproc_create_2_arg;
nfsdiropargs nfsproc_remove_2_arg;
nfsrenameargs nfsproc_rename_2_arg;
nfslinkargs nfsproc_link_2_arg;
nfssymlinkargs nfsproc_symlink_2_arg;
nfscreateargs nfsproc_mkdir_2_arg;
nfsdiropargs fsproc_rmdir_2_arg;
nfsreaddirargs nfsproc_readdir_2_arg;
am_nfs_fh nfsproc_statfs_2_arg;
} argument;
char *result;
bool_t(*xdr_argument) (), (*xdr_result) ();
char *(*local) ();
nfs_program_2_transp = NULL;
switch (rqstp->rq_proc) {
case NFSPROC_NULL:
xdr_argument = xdr_void;
xdr_result = xdr_void;
local = (char *(*)()) nfsproc_null_2_svc;
break;
case NFSPROC_GETATTR:
xdr_argument = xdr_nfs_fh;
xdr_result = xdr_attrstat;
local = (char *(*)()) nfsproc_getattr_2_svc;
break;
case NFSPROC_SETATTR:
xdr_argument = xdr_sattrargs;
xdr_result = xdr_attrstat;
local = (char *(*)()) nfsproc_setattr_2_svc;
break;
case NFSPROC_ROOT:
xdr_argument = xdr_void;
xdr_result = xdr_void;
local = (char *(*)()) nfsproc_root_2_svc;
break;
case NFSPROC_LOOKUP:
xdr_argument = xdr_diropargs;
xdr_result = xdr_diropres;
local = (char *(*)()) nfsproc_lookup_2_svc;
/*
* Cheap way to pass transp down to afs_lookuppn so it can
* be stored in the am_node structure and later used for
* quick_reply().
*/
nfs_program_2_transp = transp;
break;
case NFSPROC_READLINK:
xdr_argument = xdr_nfs_fh;
xdr_result = xdr_readlinkres;
local = (char *(*)()) nfsproc_readlink_2_svc;
break;
case NFSPROC_READ:
xdr_argument = xdr_readargs;
xdr_result = xdr_readres;
local = (char *(*)()) nfsproc_read_2_svc;
break;
case NFSPROC_WRITECACHE:
xdr_argument = xdr_void;
xdr_result = xdr_void;
local = (char *(*)()) nfsproc_writecache_2_svc;
break;
case NFSPROC_WRITE:
xdr_argument = xdr_writeargs;
xdr_result = xdr_attrstat;
local = (char *(*)()) nfsproc_write_2_svc;
break;
case NFSPROC_CREATE:
xdr_argument = xdr_createargs;
xdr_result = xdr_diropres;
local = (char *(*)()) nfsproc_create_2_svc;
break;
case NFSPROC_REMOVE:
xdr_argument = xdr_diropargs;
xdr_result = xdr_nfsstat;
local = (char *(*)()) nfsproc_remove_2_svc;
break;
case NFSPROC_RENAME:
xdr_argument = xdr_renameargs;
xdr_result = xdr_nfsstat;
local = (char *(*)()) nfsproc_rename_2_svc;
break;
case NFSPROC_LINK:
xdr_argument = xdr_linkargs;
xdr_result = xdr_nfsstat;
local = (char *(*)()) nfsproc_link_2_svc;
break;
case NFSPROC_SYMLINK:
xdr_argument = xdr_symlinkargs;
xdr_result = xdr_nfsstat;
local = (char *(*)()) nfsproc_symlink_2_svc;
break;
case NFSPROC_MKDIR:
xdr_argument = xdr_createargs;
xdr_result = xdr_diropres;
local = (char *(*)()) nfsproc_mkdir_2_svc;
break;
case NFSPROC_RMDIR:
xdr_argument = xdr_diropargs;
xdr_result = xdr_nfsstat;
local = (char *(*)()) nfsproc_rmdir_2_svc;
break;
case NFSPROC_READDIR:
xdr_argument = xdr_readdirargs;
xdr_result = xdr_readdirres;
local = (char *(*)()) nfsproc_readdir_2_svc;
break;
case NFSPROC_STATFS:
xdr_argument = xdr_nfs_fh;
xdr_result = xdr_statfsres;
local = (char *(*)()) nfsproc_statfs_2_svc;
break;
default:
svcerr_noproc(transp);
return;
}
memset((char *) &argument, 0, sizeof(argument));
if (!svc_getargs(transp,
(XDRPROC_T_TYPE) xdr_argument,
(SVC_IN_ARG_TYPE) & argument)) {
plog(XLOG_ERROR,
"NFS xdr decode failed for %d %d %d",
rqstp->rq_prog, rqstp->rq_vers, rqstp->rq_proc);
svcerr_decode(transp);
return;
}
result = (*local) (&argument, rqstp);
nfs_program_2_transp = NULL;
if (result != NULL && !svc_sendreply(transp,
(XDRPROC_T_TYPE) xdr_result,
result)) {
svcerr_systemerr(transp);
}
if (!svc_freeargs(transp,
(XDRPROC_T_TYPE) xdr_argument,
(SVC_IN_ARG_TYPE) & argument)) {
plog(XLOG_FATAL, "unable to free rpc arguments in nfs_program_1");
going_down(1);
}
}

2127
usr.sbin/amd/amd/ops_afs.c Normal file

File diff suppressed because it is too large Load Diff

166
usr.sbin/amd/amd/ops_cdfs.c Normal file
View File

@ -0,0 +1,166 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_cdfs.c,v 1.1.1.1 1997/07/24 21:21:42 christos Exp $
*
*/
/*
* High Sierra (CD-ROM) file system
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
static char *cdfs_match(am_opts *fo);
static int cdfs_fmount(mntfs *mf);
static int cdfs_fumount(mntfs *mf);
am_node *efs_lookuppn(am_node *mp, char *fname, int *error_return, int op);
fserver *find_afs_srvr(mntfs *mf);
int auto_fmount(am_node *mp);
int auto_fumount(am_node *mp);
int efs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, int count);
/*
* Ops structure
*/
am_ops cdfs_ops =
{
MNTTAB_TYPE_CDFS,
cdfs_match,
0, /* cdfs_init */
auto_fmount,
cdfs_fmount,
auto_fumount,
cdfs_fumount,
efs_lookuppn,
efs_readdir,
0, /* cdfs_readlink */
0, /* cdfs_mounted */
0, /* cdfs_umounted */
find_afs_srvr,
FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO
};
/*
* CDFS needs remote filesystem.
*/
static char *
cdfs_match(am_opts *fo)
{
if (!fo->opt_dev) {
plog(XLOG_USER, "cdfs: no source device specified");
return 0;
}
#ifdef DEBUG
dlog("CDFS: mounting device \"%s\" on \"%s\"",
fo->opt_dev, fo->opt_fs);
#endif /* DEBUG */
/*
* Determine magic cookie to put in mtab
*/
return strdup(fo->opt_dev);
}
static int
mount_cdfs(char *dir, char *fs_name, char *opts)
{
cdfs_args_t cdfs_args;
mntent_t mnt;
int flags;
/*
* Figure out the name of the file system type.
*/
MTYPE_TYPE type = MOUNT_TYPE_CDFS;
memset((voidp) &cdfs_args, 0, sizeof(cdfs_args)); /* Paranoid */
/*
* Fill in the mount structure
*/
mnt.mnt_dir = dir;
mnt.mnt_fsname = fs_name;
mnt.mnt_type = MNTTAB_TYPE_CDFS;
mnt.mnt_opts = opts;
flags = compute_mount_flags(&mnt);
cdfs_args.fspec = fs_name;
#ifdef HAVE_FIELD_CDFS_ARGS_T_NORRIP
/* XXX: need to provide norrip mount opt */
cdfs_args.norrip = 0; /* use Rock-Ridge Protocol extensions */
#endif /* HAVE_FIELD_CDFS_ARGS_T_NORRIP */
/*
* Call generic mount routine
*/
return mount_fs(&mnt, flags, (caddr_t) &cdfs_args, 0, type, 0, NULL);
}
static int
cdfs_fmount(mntfs *mf)
{
int error;
error = mount_cdfs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_cdfs: %m");
return error;
}
return 0;
}
static int
cdfs_fumount(mntfs *mf)
{
return UMOUNT_FS(mf->mf_mount);
}

152
usr.sbin/amd/amd/ops_efs.c Normal file
View File

@ -0,0 +1,152 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_efs.c,v 1.1.1.1 1997/07/24 21:21:42 christos Exp $
*
*/
/*
* Error file system.
* This is used as a last resort catchall if
* nothing else worked. EFS just returns lots
* of error codes, except for unmount which
* always works of course.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
am_node *efs_lookuppn(am_node *mp, char *fname, int *error_return, int op);
int efs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, int count);
static char * efs_match(am_opts *fo);
static int efs_fmount(mntfs *mf);
static int efs_fumount(mntfs *mf);
static void efs_umounted(am_node *mp);
/*
* Ops structure
*/
am_ops efs_ops =
{
"error",
efs_match,
0, /* efs_init */
auto_fmount,
efs_fmount,
auto_fumount,
efs_fumount,
efs_lookuppn,
efs_readdir,
0, /* efs_readlink */
0, /* efs_mounted */
efs_umounted,
find_afs_srvr,
FS_DISCARD
};
/*
* EFS file system always matches
*/
static char *
efs_match(am_opts *fo)
{
return strdup("(error-hook)");
}
static int
efs_fmount(mntfs *mf)
{
return ENOENT;
}
static int
efs_fumount(mntfs *mf)
{
/*
* Always succeed
*/
return 0;
}
/*
* EFS interface to RPC lookup() routine.
* Should never get here in the automounter.
* If we do then just give an error.
*/
am_node *
efs_lookuppn(am_node *mp, char *fname, int *error_return, int op)
{
*error_return = ESTALE;
return 0;
}
/*
* EFS interface to RPC readdir() routine.
* Should never get here in the automounter.
* If we do then just give an error.
*/
int
efs_readdir(am_node *mp, nfscookie cookie, nfsdirlist *dp, nfsentry *ep, int count)
{
return ESTALE;
}
/*
* umounted() callback for EFS.
*
* This prevents core-dumps on callbacks to error file-systems from
* nfsx_fumount.
*/
static void
efs_umounted(am_node *mp)
{
/* nothing to do */
}

678
usr.sbin/amd/amd/ops_host.c Normal file
View File

@ -0,0 +1,678 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_host.c,v 1.1.1.1 1997/07/24 21:21:43 christos Exp $
*
*/
/*
* NFS host file system.
* Mounts all exported filesystems from a given host.
* This has now degenerated into a mess but will not
* be rewritten. Amd 6 will support the abstractions
* needed to make this work correctly.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
static char *host_match(am_opts *fo);
static int host_fmount(mntfs *mf);
static int host_fumount(mntfs *mf);
static int host_init(mntfs *mf);
static void host_umounted(am_node *mp);
/*
* Ops structure
*/
am_ops host_ops =
{
"host",
host_match,
host_init,
auto_fmount,
host_fmount,
auto_fumount,
host_fumount,
efs_lookuppn,
efs_readdir,
0, /* host_readlink */
0, /* host_mounted */
host_umounted,
find_nfs_srvr,
FS_MKMNT | FS_BACKGROUND | FS_AMQINFO
};
/*
* Determine the mount point:
*
* The next change we put in to better handle PCs. This is a bit
* disgusting, so you'd better sit down. We change the make_mntpt function
* to look for exported file systems without a leading '/'. If they don't
* have a leading '/', we add one. If the export is 'a:' through 'z:'
* (without a leading slash), we change it to 'a%' (or b% or z%). This
* allows the entire PC disk to be mounted.
*/
static void
make_mntpt(char *mntpt, const exports ex, const mntfs *mf)
{
if (ex->ex_dir[0] == '/') {
if (ex->ex_dir[1] == 0)
strcpy(mntpt, (mf)->mf_mount);
else
sprintf(mntpt, "%s%s", mf->mf_mount, ex->ex_dir);
} else if (ex->ex_dir[0] >= 'a' &&
ex->ex_dir[0] <= 'z' &&
ex->ex_dir[1] == ':' &&
ex->ex_dir[2] == '/' &&
ex->ex_dir[3] == 0)
sprintf(mntpt, "%s/%c%%", mf->mf_mount, ex->ex_dir[0]);
else
sprintf(mntpt, "%s/%s", mf->mf_mount, ex->ex_dir);
}
/*
* Execute needs the same as NFS plus a helper command
*/
static char *
host_match(am_opts *fo)
{
extern am_ops nfs_ops;
/*
* Make sure rfs is specified to keep nfs_match happy...
*/
if (!fo->opt_rfs)
fo->opt_rfs = "/";
return (*nfs_ops.fs_match) (fo);
}
static int
host_init(mntfs *mf)
{
fserver *fs;
u_short port;
if (strchr(mf->mf_info, ':') == 0)
return ENOENT;
/*
* This is primarily to schedule a wakeup so that as soon
* as our fileserver is ready, we can continue setting up
* the host filesystem. If we don't do this, the standard
* afs code will set up a fileserver structure, but it will
* have to wait for another nfs request from the client to come
* in before finishing. Our way is faster since we don't have
* to wait for the client to resend its request (which could
* take a second or two).
*/
/*
* First, we find the fileserver for this mntfs and then call
* nfs_srvr_port with our mntfs passed as the wait channel.
* nfs_srvr_port will check some things and then schedule
* it so that when the fileserver is ready, a wakeup is done
* on this mntfs. afs_cont() is already sleeping on this mntfs
* so as soon as that wakeup happens afs_cont() is called and
* this mount is retried.
*/
if ((fs = mf->mf_server))
/*
* We don't really care if there's an error returned.
* Since this is just to help speed things along, the
* error will get handled properly elsewhere.
*/
(void) nfs_srvr_port(fs, &port, (voidp) mf);
return 0;
}
static int
do_mount(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *mf)
{
struct stat stb;
#ifdef DEBUG
dlog("host: mounting fs %s on %s\n", fs_name, dir);
#endif /* DEBUG */
(void) mkdirs(dir, 0555);
if (stat(dir, &stb) < 0 || (stb.st_mode & S_IFMT) != S_IFDIR) {
plog(XLOG_ERROR, "No mount point for %s - skipping", dir);
return ENOENT;
}
return mount_nfs_fh(fhp, dir, fs_name, opts, mf);
}
static int
sortfun(const voidp x, const voidp y)
{
exports *a = (exports *) x;
exports *b = (exports *) y;
return strcmp((*a)->ex_dir, (*b)->ex_dir);
}
/*
* Get filehandle
*/
static int
fetch_fhandle(CLIENT * client, char *dir, am_nfs_handle_t *fhp, u_long nfs_version)
{
struct timeval tv;
enum clnt_stat clnt_stat;
/*
* Pick a number, any number...
*/
tv.tv_sec = 20;
tv.tv_usec = 0;
#ifdef DEBUG
dlog("Fetching fhandle for %s", dir);
#endif /* DEBUG */
/*
* Call the mount daemon on the remote host to
* get the filehandle. Use NFS version specific call.
*/
plog(XLOG_INFO, "fetch_fhandle: NFS version %d", nfs_version);
#ifdef HAVE_FS_NFS3
if (nfs_version == NFS_VERSION3) {
memset((char *) &fhp->v3, 0, sizeof(fhp->v3));
clnt_stat = clnt_call(client,
MOUNTPROC_MNT,
(XDRPROC_T_TYPE) xdr_dirpath,
(SVC_IN_ARG_TYPE) &dir,
(XDRPROC_T_TYPE) xdr_mountres3,
(SVC_IN_ARG_TYPE) &fhp->v3,
tv);
if (clnt_stat != RPC_SUCCESS) {
plog(XLOG_ERROR, "mountd rpc failed: %s", clnt_sperrno(clnt_stat));
return EIO;
}
/* Check the status of the filehandle */
if ((errno = fhp->v3.fhs_status)) {
#ifdef DEBUG
dlog("fhandle fetch for mount version 3 failed: %m");
#endif /* DEBUG */
return errno;
}
} else { /* not NFS_VERSION3 mount */
#endif /* HAVE_FS_NFS3 */
clnt_stat = clnt_call(client,
MOUNTPROC_MNT,
(XDRPROC_T_TYPE) xdr_dirpath,
(SVC_IN_ARG_TYPE) &dir,
(XDRPROC_T_TYPE) xdr_fhstatus,
(SVC_IN_ARG_TYPE) &fhp->v2,
tv);
if (clnt_stat != RPC_SUCCESS) {
char *msg = clnt_sperrno(clnt_stat);
plog(XLOG_ERROR, "mountd rpc failed: %s", msg);
return EIO;
}
/* Check status of filehandle */
if (fhp->v2.fhs_status) {
errno = fhp->v2.fhs_status;
#ifdef DEBUG
dlog("fhandle fetch for mount version 1 failed: %m");
#endif /* DEBUG */
return errno;
}
#ifdef HAVE_FS_NFS3
} /* end of "if (nfs_version == NFS_VERSION3)" statement */
#endif /* HAVE_FS_NFS3 */
/* all is well */
return 0;
}
/*
* Scan mount table to see if something already mounted
*/
static int
already_mounted(mntlist *mlist, char *dir)
{
mntlist *ml;
for (ml = mlist; ml; ml = ml->mnext)
if (STREQ(ml->mnt->mnt_dir, dir))
return 1;
return 0;
}
/*
* Mount the export tree from a host
*/
static int
host_fmount(mntfs *mf)
{
struct timeval tv2;
CLIENT *client;
enum clnt_stat clnt_stat;
int n_export;
int j, k;
exports exlist = 0, ex;
exports *ep = 0;
am_nfs_handle_t *fp = 0;
char *host;
int error = 0;
struct sockaddr_in sin;
int sock = RPC_ANYSOCK;
int ok = FALSE;
mntlist *mlist;
char fs_name[MAXPATHLEN], *rfs_dir;
char mntpt[MAXPATHLEN];
struct timeval tv;
u_long mnt_version;
/*
* Read the mount list
*/
mlist = read_mtab(mf->mf_mount);
#ifdef MOUNT_TABLE_ON_FILE
/*
* Unlock the mount list
*/
unlock_mntlist();
#endif /* MOUNT_TABLE_ON_FILE */
/*
* Take a copy of the server hostname, address, and nfs version
* to mount version conversion.
*/
host = mf->mf_server->fs_host;
sin = *mf->mf_server->fs_ip;
plog(XLOG_INFO, "host_fmount: NFS version %d", mf->mf_server->fs_version);
#ifdef HAVE_FS_NFS3
if (mf->mf_server->fs_version == NFS_VERSION3)
mnt_version = MOUNTVERS3;
else
#endif /* HAVE_FS_NFS3 */
mnt_version = MOUNTVERS;
/*
* The original 10 second per try timeout is WAY too large, especially
* if we're only waiting 10 or 20 seconds max for the response.
* That would mean we'd try only once in 10 seconds, and we could
* lose the transmitt or receive packet, and never try again.
* A 2-second per try timeout here is much more reasonable.
* 09/28/92 Mike Mitchell, mcm@unx.sas.com
*/
tv.tv_sec = 2;
tv.tv_usec = 0;
/*
* Create a client attached to mountd
*/
client = get_mount_client(host, &sin, &tv, &sock, mnt_version);
if (client == NULL) {
plog(XLOG_ERROR, "get_mount_client failed for %s: %s",
host, clnt_spcreateerror(""));
error = EIO;
goto out;
}
if (!nfs_auth) {
error = make_nfs_auth();
if (error)
goto out;
}
client->cl_auth = nfs_auth;
#ifdef DEBUG
dlog("Fetching export list from %s", host);
#endif /* DEBUG */
/*
* Fetch the export list
*/
tv2.tv_sec = 10;
tv2.tv_usec = 0;
clnt_stat = clnt_call(client,
MOUNTPROC_EXPORT,
(XDRPROC_T_TYPE) xdr_void,
0,
(XDRPROC_T_TYPE) xdr_exports,
(SVC_IN_ARG_TYPE) & exlist,
tv2);
if (clnt_stat != RPC_SUCCESS) {
char *msg = clnt_sperrno(clnt_stat);
plog(XLOG_ERROR, "host_fmount rpc failed: %s", msg);
/* clnt_perror(client, "rpc"); */
error = EIO;
goto out;
}
/*
* Figure out how many exports were returned
*/
for (n_export = 0, ex = exlist; ex; ex = ex->ex_next) {
/* printf("export %s\n", ex->ex_dir); */
n_export++;
}
/*
* Allocate an array of pointers into the list
* so that they can be sorted. If the filesystem
* is already mounted then ignore it.
*/
ep = (exports *) xmalloc(n_export * sizeof(exports));
for (j = 0, ex = exlist; ex; ex = ex->ex_next) {
make_mntpt(mntpt, ex, mf);
if (!already_mounted(mlist, mntpt))
ep[j++] = ex;
}
n_export = j;
/*
* Sort into order.
* This way the mounts are done in order down the tree,
* instead of any random order returned by the mount
* daemon (the protocol doesn't specify...).
*/
qsort(ep, n_export, sizeof(exports), sortfun);
/*
* Allocate an array of filehandles
*/
fp = (am_nfs_handle_t *) xmalloc(n_export * sizeof(am_nfs_handle_t));
/*
* Try to obtain filehandles for each directory.
* If a fetch fails then just zero out the array
* reference but discard the error.
*/
for (j = k = 0; j < n_export; j++) {
/* Check and avoid a duplicated export entry */
if (j > k && ep[k] && STREQ(ep[j]->ex_dir, ep[k]->ex_dir)) {
#ifdef DEBUG
dlog("avoiding dup fhandle requested for %s", ep[j]->ex_dir);
#endif /* DEBUG */
ep[j] = 0;
} else {
k = j;
error = fetch_fhandle(client, ep[j]->ex_dir, &fp[j],
mf->mf_server->fs_version);
if (error)
ep[j] = 0;
}
}
/*
* Mount each filesystem for which we have a filehandle.
* If any of the mounts succeed then mark "ok" and return
* error code 0 at the end. If they all fail then return
* the last error code.
*/
strncpy(fs_name, mf->mf_info, sizeof(fs_name));
if ((rfs_dir = strchr(fs_name, ':')) == (char *) 0) {
plog(XLOG_FATAL, "host_fmount: mf_info has no colon");
error = EINVAL;
goto out;
}
++rfs_dir;
for (j = 0; j < n_export; j++) {
ex = ep[j];
if (ex) {
strcpy(rfs_dir, ex->ex_dir);
make_mntpt(mntpt, ex, mf);
if (do_mount(&fp[j], mntpt, fs_name, mf->mf_mopts, mf) == 0)
ok = TRUE;
}
}
/*
* Clean up and exit
*/
out:
discard_mntlist(mlist);
if (ep)
free(ep);
if (fp)
free(fp);
if (sock != RPC_ANYSOCK)
(void) amu_close(sock);
if (client)
clnt_destroy(client);
if (exlist)
xdr_pri_free((XDRPROC_T_TYPE) xdr_exports, (caddr_t) &exlist);
if (ok)
return 0;
return error;
}
/*
* Return true if pref is a directory prefix of dir.
*
* XXX TODO:
* Does not work if pref is "/".
*/
static int
directory_prefix(char *pref, char *dir)
{
int len = strlen(pref);
if (strncmp(pref, dir, len) != 0)
return FALSE;
if (dir[len] == '/' || dir[len] == '\0')
return TRUE;
return FALSE;
}
/*
* Unmount a mount tree
*/
static int
host_fumount(mntfs *mf)
{
mntlist *ml, *mprev;
int xerror = 0;
/*
* Read the mount list
*/
mntlist *mlist = read_mtab(mf->mf_mount);
#ifdef MOUNT_TABLE_ON_FILE
/*
* Unlock the mount list
*/
unlock_mntlist();
#endif /* MOUNT_TABLE_ON_FILE */
/*
* Reverse list...
*/
ml = mlist;
mprev = 0;
while (ml) {
mntlist *ml2 = ml->mnext;
ml->mnext = mprev;
mprev = ml;
ml = ml2;
}
mlist = mprev;
/*
* Unmount all filesystems...
*/
for (ml = mlist; ml && !xerror; ml = ml->mnext) {
char *dir = ml->mnt->mnt_dir;
if (directory_prefix(mf->mf_mount, dir)) {
int error;
#ifdef DEBUG
dlog("host: unmounts %s", dir);
#endif /* DEBUG */
/*
* Unmount "dir"
*/
error = UMOUNT_FS(dir);
/*
* Keep track of errors
*/
if (error) {
if (!xerror)
xerror = error;
if (error != EBUSY) {
errno = error;
plog(XLOG_ERROR, "Tree unmount of %s failed: %m", ml->mnt->mnt_dir);
}
} else {
(void) rmdirs(dir);
}
}
}
/*
* Throw away mount list
*/
discard_mntlist(mlist);
/*
* Try to remount, except when we are shutting down.
*/
if (xerror && amd_state != Finishing) {
xerror = host_fmount(mf);
if (!xerror) {
/*
* Don't log this - it's usually too verbose
plog(XLOG_INFO, "Remounted host %s", mf->mf_info);
*/
xerror = EBUSY;
}
}
return xerror;
}
/*
* Tell mountd we're done.
* This is not quite right, because we may still
* have other filesystems mounted, but the existing
* mountd protocol is badly broken anyway.
*/
static void
host_umounted(am_node *mp)
{
mntfs *mf = mp->am_mnt;
char *host;
CLIENT *client;
enum clnt_stat clnt_stat;
struct sockaddr_in sin;
int sock = RPC_ANYSOCK;
struct timeval tv;
u_long mnt_version;
if (mf->mf_error || mf->mf_refc > 1 || !mf->mf_server)
return;
/*
* Take a copy of the server hostname, address, and NFS version
* to mount version conversion.
*/
host = mf->mf_server->fs_host;
sin = *mf->mf_server->fs_ip;
plog(XLOG_INFO, "host_umounted: NFS version %d", mf->mf_server->fs_version);
#ifdef HAVE_FS_NFS3
if (mf->mf_server->fs_version == NFS_VERSION3)
mnt_version = MOUNTVERS3;
else
#endif /* HAVE_FS_NFS3 */
mnt_version = MOUNTVERS;
/*
* Create a client attached to mountd
*/
tv.tv_sec = 10;
tv.tv_usec = 0;
client = get_mount_client(host, &sin, &tv, &sock, mnt_version);
if (client == NULL) {
plog(XLOG_ERROR, "get_mount_client failed for %s: %s",
host, clnt_spcreateerror(""));
goto out;
}
if (!nfs_auth) {
if (make_nfs_auth())
goto out;
}
client->cl_auth = nfs_auth;
#ifdef DEBUG
dlog("Unmounting all from %s", host);
#endif /* DEBUG */
clnt_stat = clnt_call(client,
MOUNTPROC_UMNTALL,
(XDRPROC_T_TYPE) xdr_void,
0,
(XDRPROC_T_TYPE) xdr_void,
0,
tv);
if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_SYSTEMERROR) {
/* RPC_SYSTEMERROR seems to be returned for no good reason ... */
char *msg = clnt_sperrno(clnt_stat);
plog(XLOG_ERROR, "unmount all from %s rpc failed: %s", host, msg, clnt_stat);
goto out;
}
out:
if (sock != RPC_ANYSOCK)
(void) amu_close(sock);
if (client)
clnt_destroy(client);
}

200
usr.sbin/amd/amd/ops_ifs.c Normal file
View File

@ -0,0 +1,200 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_ifs.c,v 1.1.1.1 1997/07/24 21:21:43 christos Exp $
*
*/
/*
* Inheritance file system.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/*
* This implements a filesystem restart.
*
* This is a *gross* hack - it knows far too
* much about the way other parts of the
* system work. See restart.c too.
*/
static char *ifs_match(am_opts *fo);
static int ifs_fmount(mntfs *mf);
static int ifs_fumount(mntfs *mf);
static int ifs_init(mntfs *mf);
static int ifs_mount(am_node *mp);
/*
* Ops structure
*/
am_ops ifs_ops =
{
"inherit",
ifs_match,
ifs_init,
ifs_mount,
ifs_fmount,
auto_fumount,
ifs_fumount,
efs_lookuppn,
efs_readdir,
0, /* ifs_readlink */
0, /* ifs_mounted */
0, /* ifs_umounted */
find_afs_srvr,
FS_DISCARD
};
/*
* This should never be called.
*/
static char *
ifs_match(am_opts *fo)
{
plog(XLOG_FATAL, "ifs_match called!");
return 0;
}
static int
ifs_init(mntfs *mf)
{
mntfs *mf_link = (mntfs *) mf->mf_private;
if (mf_link == 0) {
plog(XLOG_ERROR, "Remount collision on %s?", mf->mf_mount);
plog(XLOG_FATAL, "Attempting to init not-a-filesystem");
return EINVAL;
}
if (mf_link->mf_ops->fs_init)
return (*mf_link->mf_ops->fs_init) (mf_link);
return 0;
}
/*
* Take the linked mount point and
* propogate.
*/
static mntfs *
ifs_inherit(mntfs *mf)
{
mntfs *mf_link = (mntfs *) mf->mf_private;
if (mf_link == 0) {
plog(XLOG_FATAL, "Attempting to inherit not-a-filesystem");
return 0; /* XXX */
}
mf_link->mf_fo = mf->mf_fo;
/*
* Discard the old map.
* Don't call am_unmounted since this
* node was never really mounted in the
* first place.
*/
mf->mf_private = 0;
free_mntfs(mf);
/*
* Free the dangling reference
* to the mount link.
*/
free_mntfs(mf_link);
/*
* Get a hold of the other entry
*/
mf_link->mf_flags &= ~MFF_RESTART;
/* Say what happened */
plog(XLOG_INFO, "restarting %s on %s", mf_link->mf_info, mf_link->mf_mount);
return mf_link;
}
static int
ifs_mount(am_node *mp)
{
mntfs *newmf = ifs_inherit(mp->am_mnt);
if (newmf) {
mp->am_mnt = newmf;
/*
* XXX - must do the am_mounted call here
*/
if (newmf->mf_ops->fs_flags & FS_MBACKGROUND)
am_mounted(mp);
new_ttl(mp);
return 0;
}
return EINVAL;
}
static int
ifs_fmount(mntfs *mf)
{
am_node *mp = find_mf(mf);
if (mp)
return ifs_mount(mp);
return ifs_inherit(mf) ? 0 : EINVAL;
}
static int
ifs_fumount(mntfs *mf)
{
/*
* Always succeed
*/
return 0;
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_mfs.c,v 1.1.1.1 1997/07/24 21:21:44 christos Exp $
*
*/
/*
* Memory file system (RAM filesystem)
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* FEEL FREE TO INPLEMENT THIS... :-) */

1023
usr.sbin/amd/amd/ops_nfs.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_nfs3.c,v 1.1.1.1 1997/07/24 21:21:44 christos Exp $
*
*/
/*
* Network file system version 3.0
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* FEEL FREE TO INPLEMENT THIS... :-) */

532
usr.sbin/amd/amd/ops_nfsx.c Normal file
View File

@ -0,0 +1,532 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_nfsx.c,v 1.1.1.1 1997/07/24 21:21:45 christos Exp $
*
*/
/*
* NFS hierarchical mounts
*
* TODO: Re-implement.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/*
* The rfs field contains a list of mounts to be done from
* the remote host.
*/
typedef struct nfsx_mnt {
mntfs *n_mnt;
int n_error;
} nfsx_mnt;
struct nfsx {
int nx_c; /* Number of elements in nx_v */
nfsx_mnt *nx_v; /* Underlying mounts */
nfsx_mnt *nx_try;
};
/* forward definitions */
static char * nfsx_match(am_opts *fo);
static int nfsx_fmount (mntfs *);
static int nfsx_fmount(mntfs *mf);
static int nfsx_fumount(mntfs *mf);
static int nfsx_init(mntfs *mf);
/*
* Ops structure
*/
am_ops nfsx_ops =
{
"nfsx",
nfsx_match,
nfsx_init,
auto_fmount,
nfsx_fmount,
auto_fumount,
nfsx_fumount,
efs_lookuppn,
efs_readdir,
0, /* nfsx_readlink */
0, /* nfsx_mounted */
0, /* nfsx_umounted */
find_nfs_srvr, /* XXX */
/* FS_UBACKGROUND| */ FS_AMQINFO
};
static char *
nfsx_match(am_opts *fo)
{
char *xmtab;
char *ptr;
int len;
if (!fo->opt_rfs) {
plog(XLOG_USER, "nfsx: no remote filesystem specified");
return FALSE;
}
if (!fo->opt_rhost) {
plog(XLOG_USER, "nfsx: no remote host specified");
return FALSE;
}
/* set default sublink */
if (fo->opt_sublink == 0) {
ptr = strchr(fo->opt_rfs, ',');
if (ptr && ptr != (fo->opt_rfs + 1))
fo->opt_sublink = strnsave(fo->opt_rfs + 1, ptr - fo->opt_rfs - 1);
}
/*
* Remove trailing ",..." from ${fs}
* After deslashifying, overwrite the end of ${fs} with "/"
* to make sure it is unique.
*/
if ((ptr = strchr(fo->opt_fs, ',')))
*ptr = '\0';
deslashify(fo->opt_fs);
/*
* Bump string length to allow trailing /
*/
len = strlen(fo->opt_fs);
fo->opt_fs = xrealloc(fo->opt_fs, len + 1 + 1);
ptr = fo->opt_fs + len;
/*
* Make unique...
*/
*ptr++ = '/';
*ptr = '\0';
/*
* Determine magic cookie to put in mtab
*/
xmtab = str3cat((char *) 0, fo->opt_rhost, ":", fo->opt_rfs);
#ifdef DEBUG
dlog("NFS: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"",
fo->opt_rhost, fo->opt_rfs, fo->opt_fs);
#endif /* DEBUG */
return xmtab;
}
static void
nfsx_prfree(voidp vp)
{
struct nfsx *nx = (struct nfsx *) vp;
int i;
for (i = 0; i < nx->nx_c; i++) {
mntfs *m = nx->nx_v[i].n_mnt;
if (m)
free_mntfs(m);
}
free((voidp) nx->nx_v);
free((voidp) nx);
}
static int
nfsx_init(mntfs *mf)
{
/*
* mf_info has the form:
* host:/prefix/path,sub,sub,sub
*/
int i;
int glob_error;
struct nfsx *nx;
int asked_for_wakeup = 0;
nx = (struct nfsx *) mf->mf_private;
if (nx == 0) {
char **ivec;
char *info = 0;
char *host;
char *pref;
int error = 0;
info = strdup(mf->mf_info);
host = strchr(info, ':');
if (!host) {
error = EINVAL;
goto errexit;
}
pref = host +1;
host = info;
/*
* Split the prefix off from the suffices
*/
ivec = strsplit(pref, ',', '\'');
/*
* Count array size
*/
for (i = 0; ivec[i]; i++) ;
nx = ALLOC(struct nfsx);
mf->mf_private = (voidp) nx;
mf->mf_prfree = nfsx_prfree;
nx->nx_c = i - 1; /* i-1 because we don't want the prefix */
nx->nx_v = (nfsx_mnt *) xmalloc(nx->nx_c * sizeof(nfsx_mnt));
{
char *mp = 0;
char *xinfo = 0;
char *fs = mf->mf_fo->opt_fs;
char *rfs = 0;
for (i = 0; i < nx->nx_c; i++) {
char *path = ivec[i + 1];
rfs = str3cat(rfs, pref, "/", path);
/*
* Determine the mount point.
* If this is the root, then don't remove
* the trailing slash to avoid mntfs name clashes.
*/
mp = str3cat(mp, fs, "/", rfs);
normalize_slash(mp);
deslashify(mp);
/*
* Determine the mount info
*/
xinfo = str3cat(xinfo, host, *path == '/' ? "" : "/", path);
normalize_slash(xinfo);
if (pref[1] != '\0')
deslashify(xinfo);
#ifdef DEBUG
dlog("nfsx: init mount for %s on %s", xinfo, mp);
#endif /* DEBUG */
nx->nx_v[i].n_error = -1;
nx->nx_v[i].n_mnt = find_mntfs(&nfs_ops, mf->mf_fo, mp, xinfo, "", mf->mf_mopts, mf->mf_remopts);
}
if (rfs)
free(rfs);
if (mp)
free(mp);
if (xinfo)
free(xinfo);
}
free((voidp) ivec);
errexit:
if (info)
free(info);
if (error)
return error;
}
/*
* Iterate through the mntfs's and call
* the underlying init routine on each
*/
glob_error = 0;
for (i = 0; i < nx->nx_c; i++) {
nfsx_mnt *n = &nx->nx_v[i];
mntfs *m = n->n_mnt;
int error = (*m->mf_ops->fs_init) (m);
/*
* if you just "return error" here, you will have made a failure
* in any submounts to fail the whole group. There was old unused code
* here before.
*/
if (error > 0)
n->n_error = error;
else if (error < 0) {
glob_error = -1;
if (!asked_for_wakeup) {
asked_for_wakeup = 1;
sched_task(wakeup_task, (voidp) mf, (voidp) m);
}
}
}
return glob_error;
}
static void
nfsx_cont(int rc, int term, voidp closure)
{
mntfs *mf = (mntfs *) closure;
struct nfsx *nx = (struct nfsx *) mf->mf_private;
nfsx_mnt *n = nx->nx_try;
n->n_mnt->mf_flags &= ~(MFF_ERROR | MFF_MOUNTING);
mf->mf_flags &= ~MFF_ERROR;
/*
* Wakeup anything waiting for this mount
*/
wakeup((voidp) n->n_mnt);
if (rc || term) {
if (term) {
/*
* Not sure what to do for an error code.
*/
plog(XLOG_ERROR, "mount for %s got signal %d", n->n_mnt->mf_mount, term);
n->n_error = EIO;
} else {
/*
* Check for exit status
*/
errno = rc; /* XXX */
plog(XLOG_ERROR, "%s: mount (nfsx_cont): %m", n->n_mnt->mf_mount);
n->n_error = rc;
}
free_mntfs(n->n_mnt);
n->n_mnt = new_mntfs();
n->n_mnt->mf_error = n->n_error;
n->n_mnt->mf_flags |= MFF_ERROR;
} else {
/*
* The mount worked.
*/
mf_mounted(n->n_mnt);
n->n_error = 0;
}
/*
* Do the remaining bits
*/
if (nfsx_fmount(mf) >= 0) {
wakeup((voidp) mf);
mf->mf_flags &= ~MFF_MOUNTING;
mf_mounted(mf);
}
}
static int
try_nfsx_mount(voidp mv)
{
mntfs *mf = (mntfs *) mv;
int error;
mf->mf_flags |= MFF_MOUNTING;
error = (*mf->mf_ops->fmount_fs) (mf);
mf->mf_flags &= ~MFF_MOUNTING;
return error;
}
static int
nfsx_remount(mntfs *mf, int fg)
{
struct nfsx *nx = (struct nfsx *) mf->mf_private;
nfsx_mnt *n;
int glob_error = -1;
for (n = nx->nx_v; n < nx->nx_v + nx->nx_c; n++) {
mntfs *m = n->n_mnt;
if (n->n_error < 0) {
if (!(m->mf_flags & MFF_MKMNT) && m->mf_ops->fs_flags & FS_MKMNT) {
int error = mkdirs(m->mf_mount, 0555);
if (!error)
m->mf_flags |= MFF_MKMNT;
}
}
}
/*
* Iterate through the mntfs's and mount each filesystem
* which is not yet mounted.
*/
for (n = nx->nx_v; n < nx->nx_v + nx->nx_c; n++) {
mntfs *m = n->n_mnt;
if (n->n_error < 0) {
/*
* Check fmount entry pt. exists
* and then mount...
*/
if (!m->mf_ops->fmount_fs) {
n->n_error = EINVAL;
} else {
#ifdef DEBUG
dlog("calling underlying fmount on %s", m->mf_mount);
#endif /* DEBUG */
if (!fg && foreground && (m->mf_ops->fs_flags & FS_MBACKGROUND)) {
m->mf_flags |= MFF_MOUNTING; /* XXX */
#ifdef DEBUG
dlog("backgrounding mount of \"%s\"", m->mf_info);
#endif /* DEBUG */
nx->nx_try = n;
run_task(try_nfsx_mount, (voidp) m, nfsx_cont, (voidp) mf);
n->n_error = -1;
return -1;
} else {
#ifdef DEBUG
dlog("foreground mount of \"%s\" ...", mf->mf_info);
#endif /* DEBUG */
n->n_error = (*m->mf_ops->fmount_fs) (m);
}
}
#ifdef DEBUG
if (n->n_error > 0) {
errno = n->n_error; /* XXX */
dlog("underlying fmount of %s failed: %m", m->mf_mount);
}
#endif /* DEBUG */
if (n->n_error == 0) {
glob_error = 0;
} else if (glob_error < 0) {
glob_error = n->n_error;
}
}
}
return glob_error < 0 ? 0 : glob_error;
}
static int
nfsx_fmount(mntfs *mf)
{
return nfsx_remount(mf, FALSE);
}
/*
* Unmount an NFS hierarchy.
* Note that this is called in the foreground
* and so may hang under extremely rare conditions.
*/
static int
nfsx_fumount(mntfs *mf)
{
struct nfsx *nx = (struct nfsx *) mf->mf_private;
nfsx_mnt *n;
int glob_error = 0;
/*
* Iterate in reverse through the mntfs's and unmount each filesystem
* which is mounted.
*/
for (n = nx->nx_v + nx->nx_c - 1; n >= nx->nx_v; --n) {
mntfs *m = n->n_mnt;
/*
* If this node has not been messed with
* and there has been no error so far
* then try and unmount.
* If an error had occured then zero
* the error code so that the remount
* only tries to unmount those nodes
* which had been successfully unmounted.
*/
if (n->n_error == 0) {
#ifdef DEBUG
dlog("calling underlying fumount on %s", m->mf_mount);
#endif /* DEBUG */
n->n_error = (*m->mf_ops->fumount_fs) (m);
if (n->n_error) {
glob_error = n->n_error;
n->n_error = 0;
} else {
/*
* Make sure remount gets this node
*/
n->n_error = -1;
}
}
}
/*
* If any unmounts failed then remount the
* whole lot...
*/
if (glob_error) {
glob_error = nfsx_remount(mf, TRUE);
if (glob_error) {
errno = glob_error; /* XXX */
plog(XLOG_USER, "nfsx: remount of %s failed: %m", mf->mf_mount);
}
glob_error = EBUSY;
} else {
/*
* Remove all the mount points
*/
for (n = nx->nx_v; n < nx->nx_v + nx->nx_c; n++) {
mntfs *m = n->n_mnt;
am_node am;
/*
* XXX: all the umounted handler needs is a
* mntfs pointer, so pass an am_node with the right
* pointer in it.
*/
memset((voidp) &am, 0, sizeof(am));
am.am_mnt = m;
#ifdef DEBUG
dlog("calling underlying umounted on %s", m->mf_mount);
#endif /* DEBUG */
(*m->mf_ops->umounted) (&am);
if (n->n_error < 0) {
if (m->mf_ops->fs_flags & FS_MKMNT) {
(void) rmdirs(m->mf_mount);
m->mf_flags &= ~MFF_MKMNT;
}
}
free_mntfs(m);
n->n_mnt = 0;
n->n_error = -1;
}
}
return glob_error;
}

166
usr.sbin/amd/amd/ops_pcfs.c Normal file
View File

@ -0,0 +1,166 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_pcfs.c,v 1.1.1.1 1997/07/24 21:21:45 christos Exp $
*
*/
/*
* PC (MS-DOS) file system
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* forward definitions */
static char *pcfs_match(am_opts *fo);
static int pcfs_fmount(mntfs *mf);
static int pcfs_fumount(mntfs *mf);
/*
* Ops structure
*/
am_ops pcfs_ops =
{
"pcfs",
pcfs_match,
0, /* pcfs_init */
auto_fmount,
pcfs_fmount,
auto_fumount,
pcfs_fumount,
efs_lookuppn,
efs_readdir,
0, /* pcfs_readlink */
0, /* pcfs_mounted */
0, /* pcfs_umounted */
find_afs_srvr,
FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO
};
/*
* PCFS needs remote filesystem.
*/
static char *
pcfs_match(am_opts *fo)
{
if (!fo->opt_dev) {
plog(XLOG_USER, "pcfs: no source device specified");
return 0;
}
#ifdef DEBUG
dlog("PCFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
#endif /* DEBUG */
/*
* Determine magic cookie to put in mtab
*/
return strdup(fo->opt_dev);
}
static int
mount_pcfs(char *dir, char *fs_name, char *opts)
{
pcfs_args_t pcfs_args;
mntent_t mnt;
int flags;
/*
* Figure out the name of the file system type.
*/
MTYPE_TYPE type = MOUNT_TYPE_PCFS;
memset((voidp) &pcfs_args, 0, sizeof(pcfs_args)); /* Paranoid */
/*
* Fill in the mount structure
*/
mnt.mnt_dir = dir;
mnt.mnt_fsname = fs_name;
mnt.mnt_type = MNTTAB_TYPE_PCFS;
mnt.mnt_opts = opts;
flags = compute_mount_flags(&mnt);
#ifdef HAVE_FIELD_PCFS_ARGS_T_FSPEC
pcfs_args.fspec = fs_name;
#endif /* HAVE_FIELD_PCFS_ARGS_T_FSPEC */
#ifdef HAVE_FIELD_PCFS_ARGS_T_SECONDSWEST
pcfs_args.secondswest = 0; /* XXX: fill in correct values */
#endif /* HAVE_FIELD_PCFS_ARGS_T_SECONDSWEST */
#ifdef HAVE_FIELD_PCFS_ARGS_T_DSTTIME
pcfs_args.dsttime = 0; /* XXX: fill in correct values */
#endif /* HAVE_FIELD_PCFS_ARGS_T_DSTTIME */
/*
* Call generic mount routine
*/
return mount_fs(&mnt, flags, (caddr_t) & pcfs_args, 0, type, 0, NULL);
}
static int
pcfs_fmount(mntfs *mf)
{
int error;
error = mount_pcfs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_pcfs: %m");
return error;
}
return 0;
}
static int
pcfs_fumount(mntfs *mf)
{
return UMOUNT_FS(mf->mf_mount);
}

191
usr.sbin/amd/amd/ops_pfs.c Normal file
View File

@ -0,0 +1,191 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_pfs.c,v 1.1.1.1 1997/07/24 21:21:46 christos Exp $
*
*/
/*
* Program file system
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
/* forward definitions */
static char *pfs_match(am_opts *fo);
static int pfs_fmount(mntfs *mf);
static int pfs_fumount(mntfs *mf);
static int pfs_init(mntfs *mf);
/*
* Ops structure
*/
am_ops pfs_ops =
{
"program",
pfs_match,
pfs_init,
auto_fmount,
pfs_fmount,
auto_fumount,
pfs_fumount,
efs_lookuppn,
efs_readdir,
0, /* pfs_readlink */
0, /* pfs_mounted */
0, /* pfs_umounted */
find_afs_srvr,
FS_BACKGROUND | FS_AMQINFO
};
/*
* Execute needs a mount and unmount command.
*/
static char *
pfs_match(am_opts *fo)
{
char *prog;
if (!fo->opt_mount || !fo->opt_unmount) {
plog(XLOG_USER, "program: no mount/unmount specified");
return 0;
}
prog = strchr(fo->opt_mount, ' ');
return strdup(prog ? prog + 1 : fo->opt_mount);
}
static int
pfs_init(mntfs *mf)
{
/*
* Save unmount command
*/
if (mf->mf_refc == 1) {
mf->mf_private = (voidp) strdup(mf->mf_fo->opt_unmount);
mf->mf_prfree = (void (*)()) free;
}
return 0;
}
static int
pfs_exec(char *info)
{
char **xivec;
int error;
/*
* Split copy of command info string
*/
info = strdup(info);
if (info == 0)
return ENOBUFS;
xivec = strsplit(info, ' ', '\'');
/*
* Put stdout to stderr
*/
(void) fclose(stdout);
(void) dup(fileno(logfp));
if (fileno(logfp) != fileno(stderr)) {
(void) fclose(stderr);
(void) dup(fileno(logfp));
}
/*
* Try the exec
*/
#ifdef DEBUG
amuDebug(D_FULL) {
char **cp = xivec;
plog(XLOG_DEBUG, "executing (un)mount command...");
while (*cp) {
plog(XLOG_DEBUG, "arg[%d] = '%s'", cp - xivec, *cp);
cp++;
}
}
#endif /* DEBUG */
if (xivec[0] == 0 || xivec[1] == 0) {
errno = EINVAL;
plog(XLOG_USER, "1st/2nd args missing to (un)mount program");
} else {
(void) execv(xivec[0], xivec + 1);
}
/*
* Save error number
*/
error = errno;
plog(XLOG_ERROR, "exec failed: %m");
/*
* Free allocate memory
*/
free((voidp) info);
free((voidp) xivec);
/*
* Return error
*/
return error;
}
static int
pfs_fmount(mntfs *mf)
{
return pfs_exec(mf->mf_fo->opt_mount);
}
static int
pfs_fumount(mntfs *mf)
{
return pfs_exec((char *) mf->mf_private);
}

142
usr.sbin/amd/amd/ops_sfs.c Normal file
View File

@ -0,0 +1,142 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_sfs.c,v 1.1.1.1 1997/07/24 21:21:46 christos Exp $
*
*/
/*
* Symbol-link file system
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
static int sfs_fmount(mntfs *mf);
/*
* Ops structures
*/
am_ops sfs_ops =
{
"link",
sfs_match,
0, /* sfs_init */
auto_fmount,
sfs_fmount,
auto_fumount,
sfs_fumount,
efs_lookuppn,
efs_readdir,
0, /* sfs_readlink */
0, /* sfs_mounted */
0, /* sfs_umounted */
find_afs_srvr,
0
};
/*
* SFS needs a link.
*/
char *
sfs_match(am_opts *fo)
{
if (!fo->opt_fs) {
plog(XLOG_USER, "link: no fs specified");
return 0;
}
/*
* Bug report (14/12/89) from Jay Plett <jay@princeton.edu>
* If an automount point has the same name as an existing
* link type mount Amd hits a race condition and either hangs
* or causes a symlink loop.
*
* If fs begins with a '/' change the opt_fs & opt_sublink
* fields so that the fs option doesn't end up pointing at
* an existing symlink.
*
* If sublink is nil then set sublink to fs
* else set sublink to fs / sublink
*
* Finally set fs to ".".
*/
if (*fo->opt_fs == '/') {
char *fullpath;
char *link = fo->opt_sublink;
if (link) {
if (*link == '/')
fullpath = strdup(link);
else
fullpath = str3cat((char *) 0, fo->opt_fs, "/", link);
} else {
fullpath = strdup(fo->opt_fs);
}
if (fo->opt_sublink)
free(fo->opt_sublink);
fo->opt_sublink = fullpath;
fo->opt_fs = str3cat(fo->opt_fs, ".", fullpath, "");
}
return strdup(fo->opt_fs);
}
static int
sfs_fmount(mntfs *mf)
{
/*
* Wow - this is hard to implement! :-)
*/
return 0;
}
int
sfs_fumount(mntfs *mf)
{
return 0;
}

100
usr.sbin/amd/amd/ops_sfsx.c Normal file
View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_sfsx.c,v 1.1.1.1 1997/07/24 21:21:47 christos Exp $
*
*/
/*
* Symbol-link file system, with test that the target of the link exists.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
static int sfsx_mount(am_node *mp);
struct am_ops sfsx_ops =
{
"linkx",
sfs_match,
0, /* sfsx_init */
sfsx_mount,
0,
auto_fumount,
sfs_fumount,
efs_lookuppn,
efs_readdir,
0, /* sfsx_readlink */
0, /* sfsx_mounted */
0, /* sfsx_umounted */
find_afs_srvr,
FS_MBACKGROUND
};
static int
sfsx_mount(am_node *mp)
{
/*
* Check for existence of target.
*/
struct stat stb;
char *ln;
if (mp->am_link)
ln = mp->am_link;
else /* should never occur */
ln = mp->am_mnt->mf_mount;
/*
* Use lstat, not stat, since we don't
* want to know if the ultimate target of
* a symlink chain exists, just the first.
*/
if (lstat(ln, &stb) < 0)
return errno;
return 0;
}

163
usr.sbin/amd/amd/ops_ufs.c Normal file
View File

@ -0,0 +1,163 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: ops_ufs.c,v 1.1.1.1 1997/07/24 21:21:47 christos Exp $
*
*/
/*
* UN*X file system
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amd.h>
static char * ufs_match(am_opts *fo);
static int ufs_fmount(mntfs *mf);
static int ufs_fumount(mntfs *mf);
/*
* Ops structure
*/
am_ops ufs_ops =
{
"ufs",
ufs_match,
0, /* ufs_init */
auto_fmount,
ufs_fmount,
auto_fumount,
ufs_fumount,
efs_lookuppn,
efs_readdir,
0, /* ufs_readlink */
0, /* ufs_mounted */
0, /* ufs_umounted */
find_afs_srvr,
FS_MKMNT | FS_NOTIMEOUT | FS_UBACKGROUND | FS_AMQINFO
};
/*
* UFS needs local filesystem and device.
*/
static char *
ufs_match(am_opts *fo)
{
if (!fo->opt_dev) {
plog(XLOG_USER, "ufs: no device specified");
return 0;
}
#ifdef DEBUG
dlog("UFS: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
#endif /* DEBUG */
/*
* Determine magic cookie to put in mtab
*/
return strdup(fo->opt_dev);
}
static int
mount_ufs(char *dir, char *fs_name, char *opts)
{
ufs_args_t ufs_args;
mntent_t mnt;
int flags;
/*
* Figure out the name of the file system type.
*/
MTYPE_TYPE type = MOUNT_TYPE_UFS;
memset((voidp) &ufs_args, 0, sizeof(ufs_args)); /* Paranoid */
/*
* Fill in the mount structure
*/
mnt.mnt_dir = dir;
mnt.mnt_fsname = fs_name;
mnt.mnt_type = MNTTAB_TYPE_UFS;
mnt.mnt_opts = opts;
flags = compute_mount_flags(&mnt);
#ifdef HAVE_FIELD_UFS_ARGS_T_FLAGS
ufs_args.flags = 0; /* XXX: fix this to correct flags */
#endif /* HAVE_FIELD_UFS_ARGS_T_FLAGS */
#ifdef HAVE_FIELD_UFS_ARGS_T_FSPEC
ufs_args.fspec = fs_name;
#endif /* HAVE_FIELD_UFS_ARGS_T_FSPEC */
/*
* Call generic mount routine
*/
return mount_fs(&mnt, flags, (caddr_t) &ufs_args, 0, type, 0, NULL);
}
static int
ufs_fmount(mntfs *mf)
{
int error;
error = mount_ufs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
if (error) {
errno = error;
plog(XLOG_ERROR, "mount_ufs: %m");
return error;
}
return 0;
}
static int
ufs_fumount(mntfs *mf)
{
return UMOUNT_FS(mf->mf_mount);
}

2180
usr.sbin/amd/amd2netbsd Normal file

File diff suppressed because it is too large Load Diff

62
usr.sbin/amd/amq/amq.h Normal file
View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amq.h,v 1.1.1.1 1997/07/24 21:22:53 christos Exp $
*
*/
#ifndef _AMQ_H
#define _AMQ_H
/*
* external definitions for building amq
*/
extern voidp amqproc_null_1(voidp argp, CLIENT *rqstp);
extern amq_mount_tree_p *amqproc_mnttree_1(amq_string *argp, CLIENT *rqstp);
extern voidp amqproc_umnt_1(amq_string *argp, CLIENT *rqstp);
extern amq_mount_stats *amqproc_stats_1(voidp argp, CLIENT *rqstp);
extern amq_mount_tree_list *amqproc_export_1(voidp argp, CLIENT *rqstp);
extern int *amqproc_setopt_1(amq_setopt *argp, CLIENT *rqstp);
extern amq_mount_info_list *amqproc_getmntfs_1(voidp argp, CLIENT *rqstp);
extern int *amqproc_mount_1(voidp argp, CLIENT *rqstp);
extern amq_string *amqproc_getvers_1(voidp argp, CLIENT *rqstp);
#endif /* not _AMQ_H */

259
usr.sbin/amd/amq/amq_xdr.c Normal file
View File

@ -0,0 +1,259 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amq_xdr.c,v 1.1.1.1 1997/07/24 21:22:53 christos Exp $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amq.h>
bool_t
xdr_time_type(XDR *xdrs, time_type *objp)
{
if (!xdr_long(xdrs, (long *) objp)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp)
{
if (!xdr_amq_string(xdrs, &objp->mt_mountinfo)) {
return (FALSE);
}
if (!xdr_amq_string(xdrs, &objp->mt_directory)) {
return (FALSE);
}
if (!xdr_amq_string(xdrs, &objp->mt_mountpoint)) {
return (FALSE);
}
if (!xdr_amq_string(xdrs, &objp->mt_type)) {
return (FALSE);
}
if (!xdr_time_type(xdrs, &objp->mt_mounttime)) {
return (FALSE);
}
if (!xdr_u_short(xdrs, &objp->mt_mountuid)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->mt_getattr)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->mt_lookup)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->mt_readdir)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->mt_readlink)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->mt_statfs)) {
return (FALSE);
}
if (!xdr_pointer(xdrs, (char **) &objp->mt_next, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
return (FALSE);
}
if (!xdr_pointer(xdrs, (char **) &objp->mt_child, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_amq_mount_tree_p(XDR *xdrs, amq_mount_tree_p *objp)
{
if (!xdr_pointer(xdrs, (char **) objp, sizeof(amq_mount_tree), (XDRPROC_T_TYPE) xdr_amq_mount_tree)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_amq_mount_info(XDR *xdrs, amq_mount_info *objp)
{
if (!xdr_amq_string(xdrs, &objp->mi_type)) {
return (FALSE);
}
if (!xdr_amq_string(xdrs, &objp->mi_mountpt)) {
return (FALSE);
}
if (!xdr_amq_string(xdrs, &objp->mi_mountinfo)) {
return (FALSE);
}
if (!xdr_amq_string(xdrs, &objp->mi_fserver)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->mi_error)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->mi_refc)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->mi_up)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_amq_mount_info_list(XDR *xdrs, amq_mount_info_list *objp)
{
if (!xdr_array(xdrs,
(char **) &objp->amq_mount_info_list_val,
(u_int *) &objp->amq_mount_info_list_len,
~0,
sizeof(amq_mount_info),
(XDRPROC_T_TYPE) xdr_amq_mount_info)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_amq_mount_tree_list(XDR *xdrs, amq_mount_tree_list *objp)
{
if (!xdr_array(xdrs,
(char **) &objp->amq_mount_tree_list_val,
(u_int *) &objp->amq_mount_tree_list_len,
~0,
sizeof(amq_mount_tree_p),
(XDRPROC_T_TYPE) xdr_amq_mount_tree_p)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_amq_mount_stats(XDR *xdrs, amq_mount_stats *objp)
{
if (!xdr_int(xdrs, &objp->as_drops)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->as_stale)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->as_mok)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->as_merr)) {
return (FALSE);
}
if (!xdr_int(xdrs, &objp->as_uerr)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_amq_opt(XDR *xdrs, amq_opt *objp)
{
if (!xdr_enum(xdrs, (enum_t *) objp)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_amq_setopt(XDR *xdrs, amq_setopt *objp)
{
if (!xdr_amq_opt(xdrs, &objp->as_opt)) {
return (FALSE);
}
if (!xdr_amq_string(xdrs, &objp->as_str)) {
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_pri_free(XDRPROC_T_TYPE xdr_args, caddr_t args_ptr)
{
XDR xdr;
xdr.x_op = XDR_FREE;
return ((*xdr_args) (&xdr, (caddr_t *) args_ptr));
}

View File

@ -0,0 +1,7 @@
# $NetBSD: Makefile,v 1.1.1.1 1997/07/24 21:24:12 christos Exp $
PROG= fixmount
SRCS= check_mount.c fixmount.c
MAN+= fixmount.8
.include <bsd.prog.mk>

View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: check_mount.c,v 1.1.1.1 1997/07/24 21:24:12 christos Exp $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
extern int is_same_host(char *name1, char *name2, struct in_addr addr2);
int
fixmount_check_mount(char *host, struct in_addr hostaddr, char *path)
{
struct statfs *mntbufp, *mntp;
int nloc, i;
char *colon;
/* read mount table from kernel */
nloc = getmntinfo(&mntbufp, MNT_NOWAIT);
if (nloc <= 0) {
perror("getmntinfo");
exit(1);
}
mntp = mntbufp;
for (i=0; i<nloc; ++i) {
if ((colon = strchr(mntp->f_mntfromname, ':'))) {
*colon = '\0';
if (STREQ(colon + 1, path) &&
is_same_host(mntp->f_mntfromname, host, hostaddr))
return 1;
}
}
return 0;
}

View File

@ -0,0 +1,121 @@
.\" $Id: fixmount.8,v 1.1.1.1 1997/07/24 21:24:12 christos Exp $
.TH FIXMOUNT 8L "26 Feb 1993"
.SH NAME
fixmount \- fix remote mount entries
.SH SYNOPSIS
.B /usr/local/etc/fixmount
[
.B \-adervq
]
[
.B \-h
.I name
]
.I host
\&...
.SH DESCRIPTION
.IX "fixmount command" "" "\fLfixmount\fP \(em fix remote mount entries"
.LP
.B fixmount
is a variant of
.BR showmount (8)
that can delete bogus mount entries in remote
.BR mountd (8C)
daemons.
The actions specified by the options are performed for each
.I host
in turn.
.SH OPTIONS
The
.BR \-a ,
.BR \-d ,
and
.B \-e
options work as in
.BR showmount (8)
except that only entries pertaining to the local host are printed.
.TP
.B \-r
Removes those remote mount entries on
.I host
that do not correspond to current mounts, i.e., which are left-over
from a crash or are the result of improper mount protocol.
The actuality of mounts is verified using the entries in
.BR /etc/mtab .
.TP
.B \-v
Verify remote mounts. Similar to
.B \-r
except that only a notification message is printed for each bogus entry
found. The remote mount table is not changed.
.TP
.B \-A
Issues a command to the remote mountd declaring that ALL of its filesystems
have been unmounted. This should be used with caution, as it removes all
remote mount entries pertaining to the local system, whether or not any
filesystems are still mounted locally.
.TP
.B \-q
Be quiet.
Suppresses error messages due to timeouts and "Program not registered",
i.e., due to remote hosts not supporting RPC or not running mountd.
.TP
.BI \-h \ name
Pretend the local hostname is
.IR name .
This is useful after the local hostname has been changed and rmtab entries
using the old name remain on a remote machine.
Unfortunately, most mountd's won't be able to successfully handle removal
of such entries, so this option is useful in combination with
.B \-v
only.
.br
This option also saves time as comparisons of remotely recorded and local
hostnames by address are avoided.
.SH FILES
.PD 0
.TP 20
.B /etc/mtab
List of current mounts.
.TP
.B /etc/rmtab
Backup file for remote mount entries on NFS server.
.PD
.SH "SEE ALSO"
showmount(8),
mtab(5),
rmtab(5),
mountd(8C)
.SH BUGS
No attempt is made to verify the information in
.B /etc/mtab
itself.
.PP
Since swap file mounts are not recorded in
.BR /etc/mtab ,
a heuristic specific to SunOS is used to determine whether such a mount
is actual (replacing the string "swap" with "root" and verifying the resulting
path).
.PP
Symbolic links on the server will cause the path in the remote entry to differ
from the one in
.BR /etc/mtab .
To catch those cases, a filesystem is also deemed mounted if its
.I local
mount point is identical to the remote entry.
I.e., on a SunOS diskless client,
.B server:/export/share/sunos.4.1.1
is actually
.BR /usr/share .
Since the local mount point is
.B /usr/share
as well this will be handled correctly.
.PP
There is no way to clear a stale entry in a remote mountd after the
local hostname (or whatever reverse name resolution returns for it)
has been changed. To take care of these cases,
the remote /etc/rmtab file has to be edited and mountd restarted.
.PP
The RPC timeouts for mountd calls can only be changed by recompiling.
The defaults are 2 seconds for client handle creation and 5 seconds for
RPC calls.

View File

@ -0,0 +1,513 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: fixmount.c,v 1.1.1.1 1997/07/24 21:24:11 christos Exp $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#define CREATE_TIMEOUT 2 /* seconds */
#define CALL_TIMEOUT 5 /* seconds */
#ifndef INADDR_NONE
# define INADDR_NONE 0xffffffff
#endif /* not INADDR_NONE */
/* Constant defs */
#define ALL 1
#define DIRS 2
#define DODUMP 0x1
#define DOEXPORTS 0x2
#define DOREMOVE 0x4
#define DOVERIFY 0x8
#define DOREMALL 0x10
static CLIENT *clnt_create_timeout();
static char dir_path[NFS_MAXPATHLEN];
static char thishost[MAXHOSTNAMELEN] = "";
static exports mntexports;
static int quiet = 0;
static int type = 0;
static jmp_buf before_rpc;
static mountlist mntdump;
static struct in_addr thisaddr;
extern int fixmount_check_mount(char *host, struct in_addr hostaddr, char *path);
/* dummy variables */
char *progname;
char hostname[MAXHOSTNAMELEN];
int orig_umask, foreground, debug_flags;
pid_t mypid;
serv_state amd_state;
void
usage(void)
{
fprintf(stderr, "usage: fixmount [-adervAqf] [-h hostname] host ...\n");
exit(1);
}
/*
* Check hostname against other name and its IP address
*/
int
is_same_host(char *name1, char *name2, struct in_addr addr2)
{
if (strcasecmp(name1, name2) == 0) {
return 1;
} else if (addr2.s_addr == INADDR_NONE) {
return 0;
} else {
static char lasthost[MAXHOSTNAMELEN] = "";
static struct in_addr addr1;
struct hostent *he;
/*
* To save nameserver lookups, and because this function
* is typically called repeatedly on the same names,
* cache the last lookup result and reuse it if possible.
*/
if (strcasecmp(name1, lasthost) == 0) {
return (addr1.s_addr == addr2.s_addr);
} else if (!(he = gethostbyname(name1))) {
return 0;
} else {
strncpy(lasthost, name1, sizeof(lasthost) - 1);
memcpy(&addr1, he->h_addr, sizeof(addr1));
return (addr1.s_addr == addr2.s_addr);
}
}
}
/*
* Print the binary tree in inorder so that output is sorted.
*/
void
print_dump(mountlist mp)
{
if (mp == NULL)
return;
if (is_same_host(mp->ml_hostname, thishost, thisaddr)) {
switch (type) {
case ALL:
printf("%s:%s\n", mp->ml_hostname, mp->ml_directory);
break;
case DIRS:
printf("%s\n", mp->ml_directory);
break;
default:
printf("%s\n", mp->ml_hostname);
break;
};
}
if (mp->ml_next)
print_dump(mp->ml_next);
}
/*
* remove entry from remote rmtab
*/
int
remove_mount(CLIENT *client, char *host, mountlist ml, int fixit)
{
enum clnt_stat estat;
struct timeval tv;
char *pathp = dir_path;
strncpy(dir_path, ml->ml_directory, sizeof(dir_path));
if (!fixit) {
printf("%s: bogus mount %s:%s\n", host, ml->ml_hostname, ml->ml_directory);
fflush(stdout);
} else {
printf("%s: removing %s:%s\n", host, ml->ml_hostname, ml->ml_directory);
fflush(stdout);
tv.tv_sec = CALL_TIMEOUT;
tv.tv_usec = 0;
if ((estat = clnt_call(client,
MOUNTPROC_UMNT,
(XDRPROC_T_TYPE) xdr_dirpath,
(char *) &pathp,
(XDRPROC_T_TYPE) xdr_void,
(char *) 0,
tv)) != RPC_SUCCESS) {
fprintf(stderr, "%s:%s MOUNTPROC_UMNT: ",
host, ml->ml_directory);
clnt_perrno(estat);
fflush(stderr);
return -1;
}
}
return 0;
}
/*
* fix mount list on remote host
*/
void
fix_rmtab(CLIENT *client, char *host, mountlist mp, int fixit, int force)
{
mountlist p;
struct hostent *he;
struct in_addr hostaddr;
/*
* Obtain remote address for comparisons
*/
if ((he = gethostbyname(host))) {
memcpy(&hostaddr, he->h_addr, sizeof(hostaddr));
} else {
hostaddr.s_addr = INADDR_NONE;
}
for (p = mp; p; p = p->ml_next) {
if (is_same_host(p->ml_hostname, thishost, thisaddr)) {
if (force || !fixmount_check_mount(host, hostaddr, p->ml_directory))
remove_mount(client, host, p, fixit);
}
}
}
/*
* remove all entries from remote rmtab
*/
int
remove_all(CLIENT *client, char *host)
{
enum clnt_stat estat;
struct timeval tv;
printf("%s: removing ALL\n", host);
fflush(stdout);
tv.tv_sec = CALL_TIMEOUT;
tv.tv_usec = 0;
if ((estat = clnt_call(client,
MOUNTPROC_UMNTALL,
(XDRPROC_T_TYPE) xdr_void,
(char *) 0,
(XDRPROC_T_TYPE) xdr_void,
(char *) 0,
tv)) != RPC_SUCCESS) {
/*
* RPC_SYSTEMERROR is returned even if all went well
*/
if (estat != RPC_SYSTEMERROR) {
fprintf(stderr, "%s MOUNTPROC_UMNTALL: ", host);
clnt_perrno(estat);
fflush(stderr);
return -1;
}
}
return 0;
}
/*
* This command queries the NFS mount daemon for it's mount list and/or
* it's exports list and prints them out.
* See "NFS: Network File System Protocol Specification, RFC1094, Appendix A"
* for detailed information on the protocol.
*/
int
main(int argc, char *argv[])
{
AUTH *auth;
CLIENT *client;
char *host;
enum clnt_stat estat;
exports exp;
extern char *optarg;
extern int optind;
groups grp;
int ch;
int force = 0;
int morethanone;
register int rpcs = 0;
struct timeval tv;
while ((ch = getopt(argc, argv, "adervAqfh:")) != EOF)
switch ((char) ch) {
case 'a':
if (type == 0) {
type = ALL;
rpcs |= DODUMP;
} else
usage();
break;
case 'd':
if (type == 0) {
type = DIRS;
rpcs |= DODUMP;
} else
usage();
break;
case 'e':
rpcs |= DOEXPORTS;
break;
case 'r':
rpcs |= DOREMOVE;
break;
case 'A':
rpcs |= DOREMALL;
break;
case 'v':
rpcs |= DOVERIFY;
break;
case 'q':
quiet = 1;
break;
case 'f':
force = 1;
break;
case 'h':
strncpy(thishost, optarg, sizeof(thishost));
thishost[sizeof(thishost) - 1] = '\0';
break;
case '?':
default:
usage();
}
if (optind == argc)
usage();
if (rpcs == 0)
rpcs = DODUMP;
if (!*thishost) {
struct hostent *he;
if (gethostname(thishost, sizeof(thishost)) < 0) {
perror("gethostname");
exit(1);
}
/*
* We need the hostname as it appears to the other side's
* mountd, so get our own hostname by reverse address
* resolution.
*/
if (!(he = gethostbyname(thishost))) {
fprintf(stderr, "gethostbyname failed on %s\n",
thishost);
exit(1);
}
memcpy(&thisaddr, he->h_addr, sizeof(thisaddr));
if (!(he = gethostbyaddr((char *) &thisaddr, sizeof(thisaddr),
he->h_addrtype))) {
fprintf(stderr, "gethostbyaddr failed on %s\n",
inet_ntoa(thisaddr));
exit(1);
}
strncpy(thishost, he->h_name, sizeof(thishost));
thishost[sizeof(thishost) - 1] = '\0';
} else {
thisaddr.s_addr = INADDR_NONE;
}
if (!(auth = authunix_create_default())) {
fprintf(stderr, "couldn't create authentication handle\n");
exit(1);
}
morethanone = (optind + 1 < argc);
for (; optind < argc; optind++) {
host = argv[optind];
tv.tv_sec = CREATE_TIMEOUT;
tv.tv_usec = 0;
if (!(client = clnt_create_timeout(host, &tv)))
continue;
client->cl_auth = auth;
tv.tv_sec = CALL_TIMEOUT;
tv.tv_usec = 0;
if (rpcs & (DODUMP | DOREMOVE | DOVERIFY))
if ((estat = clnt_call(client,
MOUNTPROC_DUMP,
(XDRPROC_T_TYPE) xdr_void,
(char *) 0,
(XDRPROC_T_TYPE) xdr_mountlist,
(char *) &mntdump,
tv)) != RPC_SUCCESS) {
fprintf(stderr, "%s: MOUNTPROC_DUMP: ", host);
clnt_perrno(estat);
fflush(stderr);
mntdump = NULL;
goto next;
}
if (rpcs & DOEXPORTS)
if ((estat = clnt_call(client,
MOUNTPROC_EXPORT,
(XDRPROC_T_TYPE) xdr_void,
(char *) 0,
(XDRPROC_T_TYPE) xdr_exports,
(char *) &mntexports,
tv)) != RPC_SUCCESS) {
fprintf(stderr, "%s: MOUNTPROC_EXPORT: ", host);
clnt_perrno(estat);
fflush(stderr);
mntexports = NULL;
goto next;
}
/* Now just print out the results */
if ((rpcs & (DODUMP | DOEXPORTS)) &&
morethanone) {
printf(">>> %s <<<\n", host);
fflush(stdout);
}
if (rpcs & DODUMP) {
print_dump(mntdump);
}
if (rpcs & DOEXPORTS) {
exp = mntexports;
while (exp) {
printf("%-35s", exp->ex_dir);
grp = exp->ex_groups;
if (grp == NULL) {
printf("Everyone\n");
} else {
while (grp) {
printf("%s ", grp->gr_name);
grp = grp->gr_next;
}
printf("\n");
}
exp = exp->ex_next;
}
}
if (rpcs & DOVERIFY)
fix_rmtab(client, host, mntdump, 0, force);
if (rpcs & DOREMOVE)
fix_rmtab(client, host, mntdump, 1, force);
if (rpcs & DOREMALL)
remove_all(client, host);
next:
if (mntdump)
(void) clnt_freeres(client,
(XDRPROC_T_TYPE) xdr_mountlist,
(char *) &mntdump);
if (mntexports)
(void) clnt_freeres(client,
(XDRPROC_T_TYPE) xdr_exports,
(char *) &mntexports);
clnt_destroy(client);
}
exit(0);
return 0; /* should never reach here */
}
RETSIGTYPE
create_timeout(int sig)
{
signal(SIGALRM, SIG_DFL);
longjmp(before_rpc, 1);
}
static CLIENT *
clnt_create_timeout(char *host, struct timeval *to)
{
CLIENT *client;
if (setjmp(before_rpc)) {
if (!quiet) {
fprintf(stderr, "%s: ", host);
clnt_perrno(RPC_TIMEDOUT);
fprintf(stderr, "\n");
fflush(stderr);
}
return NULL;
}
signal(SIGALRM, create_timeout);
ualarm(to->tv_sec * 1000000 + to->tv_usec, 0);
/*
* Try TCP first (in case return data is large), then UDP
*/
if (!(client = clnt_create(host, MOUNTPROG, MOUNTVERS, "tcp")) &&
! (client = clnt_create(host, MOUNTPROG, MOUNTVERS, "udp"))) {
ualarm(0, 0);
if (!quiet) {
clnt_pcreateerror(host);
fflush(stderr);
}
return NULL;
}
ualarm(0, 0);
return client;
}

View File

@ -0,0 +1,7 @@
# $NetBSD: Makefile,v 1.1.1.1 1997/07/24 21:22:43 christos Exp $
PROG= hlfsd
SRCS= stubs.c nfs_prot_svc.c homedir.c hlfsd.c
MAN+= hlfsd.8
.include <bsd.prog.mk>

287
usr.sbin/amd/hlfsd/hlfsd.8 Normal file
View File

@ -0,0 +1,287 @@
.\"
.\" Copyright (c) 1989 Jan-Simon Pendry
.\" Copyright (c) 1989 Imperial College of Science, Technology & Medicine
.\" Copyright (c) 1989 The Regents of the University of California.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" Jan-Simon Pendry at Imperial College, London.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: hlfsd.8,v 1.1.1.1 1997/07/24 21:22:43 christos Exp $
.\"
.\" HLFSD was written at Columbia University Computer Science Department, by
.\" Erez Zadok <ezk@cs.columbia.edu> and Alexander Dupuy <dupuy@smarts.com>
.\" It is distributed under the same terms and conditions as AMD.
.\"
.TH HLFSD 8 "14 September 1993"
.SH NAME
hlfsd \- home-link file system daemon
.SH SYNOPSIS
.B hlfsd
[
.B \-Cfhnpv
] [
.BI \-a " alt_dir"
] [
.BI \-c " cache-interval"
] [
.BI \-g " group"
] [
.BI \-i " reload-interval"
] [
.BI \-l " logfile"
] [
.BI \-o " mount-options"
] [
.BI \-x " log-options"
] [
.BI \-D " debug-options"
]
[
.I linkname
.RI [ " subdir " ]
]
.SH DESCRIPTION
.B Hlfsd
is a daemon which implements a filesystem containing a symbolic link to
subdirectory within a user's home directory, depending on the user
which accessed that link. It was primarily designed to redirect
incoming mail to users' home directories, so that it can read from
anywhere.
.LP
.B Hlfsd
operates by mounting itself as an
.SM NFS
server for the directory containing
.IR linkname ,
which defaults to
.BR /hlfs/home .
Lookups within that directory are handled by
.BR hlfsd ,
which uses the password map to determine how to resolve the lookup.
The directory will be created if it doesn't already exist. The symbolic link will be to the accessing user's home directory, with
.I subdir
appended to it. If not specified,
.I subdir
defaults to
.BR .hlfsdir .
This directory will also be created if it does not already exist.
.LP
A SIGTERM sent to
.B hlfsd
will cause it to shutdown. A SIGHUP will flush the internal
caches, and reload the password map. It will also close and
reopen the log file, to enable the original log file to be
removed or rotated.
.SH OPTIONS
.TP
.BI \-a " alt_dir"
Alternate directory. The name of the directory to which
the symbolic link returned by
.B hlfsd
will point, if it cannot access the home directory of the user. This
defaults to
.BR /var/hlfs .
This directory will be created if it doesn't exist. It is expected
that either users will read these files, or the system administrators
will run a script to resend this "lost mail" to its owner.
.TP
.BI \-C
Force
.B hlfsd
to run on systems that cannot turn off the NFS attribute-cache. Use of
this option on those systems is discouraged, as it may result in loss
or misdelivery of mail. The option is ignored on systems that can turn
off the attribute-cache.
.TP
.BI \-c " cache-interval"
Caching interval.
.B Hlfsd
will cache the validity of home directories for this interval, in
seconds. Entries which have been verified within the last
.I cache-interval
seconds will not be verified again, since the operation could
be expensive, and the entries are most likely still valid.
After the interval has expired,
.B hlfsd
will re-verify the validity of the user's home directory, and
reset the cache time-counter. The default value for
.I cache-interval
is 300 seconds (5 minutes).
.TP
.B \-f
Force fast startup. This option tells
.B hlfsd
to skip startup-time consistency checks such as existence of mount
directory, alternate spool directory, symlink to be hidden under the
mount directory, their permissions and validity.
.TP
.BI \-g " group"
Set the special group HLFS_GID to
.IR group .
Programs such as
.B from
or
.BR comsat ,
which access the mailboxes of other users) must be setgid HLFS_GID to
work properly. The default group is "hlfs". If no group is provided,
and there is no group "hlfs", this feature is disabled.
.TP
.B \-h
Help. Print a brief help message, and exit.
.TP
.BI \-i " reload-interval"
Map-reloading interval. Each
.I reload-interval
seconds,
.B hlfsd
will reload the password map.
.B Hlfsd
needs the password map for the UIDs and home directory pathnames.
.B Hlfsd
schedules a SIGALRM to reload the password maps. A SIGHUP sent to
.B hlfsd
will force it to reload the maps immediately. The default
value for
.I reload-interval
is 900 seconds (15 minutes.)
.TP
.BI \-l " logfile"
Specify a log file to which
.B hlfsd
will record events. If
.I logfile
is the string
.B syslog
then the log messages will be sent to the system log daemon by
.IR syslog (3),
using the LOG_DAEMON facility.
This is also the default.
.TP
.B \-n
No verify.
.B Hlfsd
will not verify the validity of the symbolic link it will be
returning, or that the user's home directory contains
sufficient disk-space for spooling. This can speed up
.B hlfsd
at the cost of possibly returning symbolic links to home
directories which are not currently accessible or are full.
By default,
.B hlfsd
validates the symbolic-link in the background.
The
.B \-n
option overrides the meaning of the
.B \-c
option, since no caching is necessary.
.TP
.BI \-o " mount-options"
Mount options. Mount options which
.B hlfsd
will use to mount itself on top of
.I dirname.
By default,
.IR mount-options
is set to "ro", unless M_CACHE is defined, in which case it is
set to "ro,nocache".
.TP
.B \-p
Print PID.
Outputs the process-id of
.B hlfsd
to standard output where it can be saved into a file.
.TP
.B \-v
Version. Displays version information to standard error.
.TP
.BI \-x " log-options"
Specify run-time logging options. The options are a comma separated
list chosen from: fatal, error, user, warn, info, map, stats, all.
.TP
.BI \-D " log-options"
Select from a variety of debugging options. Prefixing an
option with the string
.B no
reverses the effect of that option. Options are cumulative.
The most useful option is
.BR all .
Since this option is only used for debugging other options are not
documented here. A fuller description is available in the program
source. A SIGUSR1 sent to
.B hlfsd
will cause it to dump its internal password map to the file
.BR /tmp/hlfsdump .
.SH FILES
.PD 0
.TP 5
.B /hlfs
directory under which
.B hlfsd
mounts itself and manages the symbolic link
.BR home .
.TP 5
.B .hlfsdir
default sub-directory in the user's home directory, to which the
.B home
symbolic link returned by
.B hlfsd
points.
.TP 5
.B /var/hlfs
directory to which
.B home
symbolic link returned by
.B hlfsd
points if it is unable to verify the that
user's home directory is accessible.
.SH "SEE ALSO"
.BR amd (8),
.BR automount (8),
.BR cron(8),
.BR getgrent (3),
.BR getpwent (3),
.BR mail(1),
.BR mount (8),
.BR mtab (5),
.BR passwd (5),
.BR sendmail (8),
.BR umount (8).
.LP
.IR "HLFSD: Delivering Email to Your $HOME" ,
in
.IR "Proc. LISA-VII, The 7th Usenix System Administration Conference" ,
November 1993.
.SH AUTHORS
Erez Zadok <ezk@cs.columbia.edu>, Computer Science Department,
Columbia University, New York City, New York, USA, and
Alexander Dupuy <dupuy@smarts.com>, System Management ARTS,
White Plains, New York, USA.

999
usr.sbin/amd/hlfsd/hlfsd.c Normal file
View File

@ -0,0 +1,999 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: hlfsd.c,v 1.1.1.1 1997/07/24 21:22:40 christos Exp $
*
* HLFSD was written at Columbia University Computer Science Department, by
* Erez Zadok <ezk@cs.columbia.edu> and Alexander Dupuy <dupuy@cs.columbia.edu>
* It is being distributed under the same terms and conditions as amd does.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <hlfsd.h>
/*
* STATIC VARIABLES:
*/
static RETSIGTYPE proceed(int);
static RETSIGTYPE reaper(int);
static RETSIGTYPE reload(int);
static char *hlfs_group = DEFAULT_HLFS_GROUP;
static char default_dir_name[] = DEFAULT_DIRNAME;
static char *dir_name = default_dir_name;
static int printpid = 0;
static int stoplight = 0;
static void hlfsd_init(P_void);
static void usage(P_void);
static struct itimerval reloadinterval = {
{DEFAULT_INTERVAL, 0},
{DEFAULT_INTERVAL, 0}
};
/*
* default mount options.
*/
static char default_mntopts[] = "ro,noac";
/*
* GLOBALS:
*/
SVCXPRT *nfsxprt;
char *alt_spooldir = ALT_SPOOLDIR;
char *home_subdir = HOME_SUBDIR;
char *logfile = DEFAULT_LOGFILE;
char *progname;
char *slinkname = 0;
char hostname[MAXHOSTNAMELEN] = "localhost";
int cache_interval = DEFAULT_CACHE_INTERVAL;
int foreground = 1; /* This is the top-level server */
int hlfs_gid = -3;
int masterpid = 0;
int noverify = 0;
int orig_umask;
int serverpid = 0;
nfstime startup;
pid_t mypid; /* Current process id */
serv_state amd_state;
u_short nfs_port;
#ifdef MOUNT_TABLE_ON_FILE
char *mtab = MNTTAB_FILE_NAME;
#endif /* MOUNT_TABLE_ON_FILE */
#ifdef DEBUG
int debug_flags = 0;
#endif /* DEBUG */
static void
usage(void)
{
fprintf(stderr,
"Usage: %s [-Cfhnpv] [-a altdir] [-c cache-interval] [-g group]\n",
progname);
fprintf(stderr, "\t[-i interval] [-l logfile] [-o mntopts]\n");
show_opts('x', xlog_opt);
#ifdef DEBUG
show_opts('D', dbg_opt);
#endif /* DEBUG */
fprintf(stderr, "\t[dir_name [subdir]]\n");
exit(2);
}
int
main(int argc, char *argv[])
{
char *dot;
char *mntopts = (char *) NULL;
char hostpid_fs[MAXHOSTNAMELEN + 1 + 16]; /* room for ":(pid###)" */
char progpid_fs[PROGNAMESZ + 1 + 11]; /* room for ":pid" */
char preopts[128];
int forcecache = 0;
int forcefast = 0;
int mntflags = 0;
int opt, ret;
int opterrs = 0;
int retry;
int soNFS; /* NFS socket */
mntent_t mnt;
nfs_args_t mountargs;
struct dirent *direntry;
struct group *grp;
struct stat stmodes;
DIR *mountdir;
MTYPE_TYPE type = MOUNT_TYPE_NFS;
#ifdef HAVE_SIGACTION
struct sigaction sa;
#endif /* not HAVE_SIGACTION */
#ifndef HAVE_TRANSPORT_TYPE_TLI
struct sockaddr_in localsocket;
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
/* ensure that only root can run hlfsd */
if (geteuid()) {
fprintf(stderr, "hlfsd can only be run as root\n");
exit(1);
}
setbuf(stdout, (char *) NULL);
umask(0);
/* get program name and truncate so we don't overflow progpid_fs */
if ((progname = strrchr(argv[0], '/')) != NULL)
progname++;
else
progname = argv[0];
if ((int) strlen(progname) > PROGNAMESZ) /* truncate to reasonable size */
progname[PROGNAMESZ] = '\0';
while ((opt = getopt(argc, argv, "a:c:CD:fg:hi:l:no:px:v")) != EOF)
switch (opt) {
case 'a':
if (!optarg || optarg[0] != '/') {
printf("%s: invalid directory for -a: %s\n",
progname, optarg);
exit(3);
}
alt_spooldir = optarg;
break;
case 'c':
if (!atoi(optarg)) {
printf("%s: invalid interval for -c: %s\n",
progname, optarg);
exit(3);
}
cache_interval = atoi(optarg);
break;
case 'C':
forcecache++;
break;
case 'f':
forcefast++;
break;
case 'g':
hlfs_group = optarg;
break;
case 'i':
if (!atoi(optarg)) {
printf("%s: invalid interval for -i: %s\n",
progname, optarg);
exit(3);
}
reloadinterval.it_interval.tv_sec = atoi(optarg);
reloadinterval.it_value.tv_sec = atoi(optarg);
break;
case 'l':
logfile = optarg;
break;
case 'n':
noverify++;
break;
case 'o':
mntopts = optarg;
break;
case 'p':
printpid++;
break;
case 'v':
fprintf(stderr, "%s\n", HLFSD_VERSION);
exit(0);
case 'x':
opterrs += switch_option(optarg);
break;
case 'D':
#ifdef DEBUG
opterrs += debug_option(optarg);
#else /* not DEBUG */
fprintf(stderr, "%s: not compiled with DEBUG -- sorry.\n", progname);
#endif /* not DEBUG */
break;
case 'h':
case '?':
opterrs++;
}
/* set some default debugging options */
if (xlog_level_init == ~0)
switch_option("");
/* need my pid before any dlog/plog */
mypid = getpid();
#ifdef DEBUG
switch_option("debug");
#endif /* DEBUG */
/*
* Terminate if did not ask to forcecache (-C) and hlfsd would not be able
* to set the minimum cache intervals.
*/
#if !defined(MNT2_NFS_OPT_ACREGMIN) || !defined(MNT2_NFS_OPT_ACDIRMIN)
if (!forcecache) {
fprintf(stderr, "%s: will not be able to turn off attribute caches.\n", progname);
exit(1);
}
#endif /* !defined(MNT2_NFS_OPT_ACREGMIN) || !defined(MNT2_NFS_OPT_ACDIRMIN) */
switch (argc - optind) {
case 2:
home_subdir = argv[optind + 1];
case 1:
dir_name = argv[optind];
case 0:
break;
default:
opterrs++;
}
if (opterrs)
usage();
/* find gid for hlfs_group */
if ((grp = getgrnam(hlfs_group)) == (struct group *) NULL) {
fprintf(stderr, "%s: cannot get gid for group \"%s\".\n",
progname, hlfs_group);
} else {
hlfs_gid = grp->gr_gid;
}
/* get hostname for logging and open log before we reset umask */
gethostname(hostname, MAXHOSTNAMELEN);
if ((dot = strchr(hostname, '.')) != NULL)
*dot = '\0';
if (logfile)
switch_to_logfile(logfile);
orig_umask = umask(0);
#if defined(DEBUG) && !defined(MOUNT_TABLE_ON_FILE)
if (debug_flags & D_MTAB)
dlog("-D mtab option ignored");
#endif /* defined(DEBUG) && !defined(MOUNT_TABLE_ON_FILE) */
/* avoid hanging on other NFS servers if started elsewhere */
if (chdir("/") < 0)
fatal("cannot chdir to /: %m");
if (geteuid() != 0)
fatal("must be root to mount filesystems");
/*
* dir_name must match "^(/.*)/([^/]+)$", and is split at last '/' with
* slinkname = `basename $dir_name` - requires dir_name be writable
*/
if (dir_name[0] != '/'
|| ((slinkname = strrchr(dir_name, '/')), *slinkname++ = '\0',
(dir_name[0] == '\0' || slinkname[0] == '\0'))) {
if (slinkname)
*--slinkname = '/';
printf("%s: invalid mount directory/link %s\n",
progname, dir_name);
exit(3);
}
if (!forcefast) {
/* make sure mount point exists and is at least mode 555 */
if (stat(dir_name, &stmodes) < 0)
if (errno != ENOENT || mkdirs(dir_name, 0555) < 0
|| stat(dir_name, &stmodes) < 0)
fatalerror(dir_name);
if ((stmodes.st_mode & 0555) != 0555) {
fprintf(stderr, "%s: directory %s not read/executable\n",
progname, dir_name);
plog(XLOG_WARNING, "directory %s not read/executable",
dir_name);
}
/* warn if extraneous stuff will be hidden by mount */
if ((mountdir = opendir(dir_name)) == NULL)
fatalerror(dir_name);
while ((direntry = readdir(mountdir)) != NULL) {
if (strncmp(".", direntry->d_name,
NAMLEN(direntry)) &&
strncmp("..", direntry->d_name,
NAMLEN(direntry)) &&
strncmp(slinkname, direntry->d_name,
NAMLEN(direntry)))
break;
}
if (direntry != NULL) {
fprintf(stderr, "%s: %s/%s will be hidden by mount\n",
progname, dir_name, direntry->d_name);
plog(XLOG_WARNING, "%s/%s will be hidden by mount\n",
dir_name, direntry->d_name);
}
closedir(mountdir);
/* make sure alternate spool dir exists */
if ((errno = mkdirs(alt_spooldir, OPEN_SPOOLMODE))) {
fprintf(stderr, "%s: cannot create alternate dir ",
progname);
perror(alt_spooldir);
plog(XLOG_ERROR, "cannot create alternate dir %s: %m",
alt_spooldir);
}
chmod(alt_spooldir, OPEN_SPOOLMODE);
/* create failsafe link to alternate spool directory */
slinkname[-1] = '/'; /* unsplit dir_name to include link */
if (lstat(dir_name, &stmodes) == 0 &&
(stmodes.st_mode & S_IFMT) != S_IFLNK) {
fprintf(stderr, "%s: failsafe %s not a symlink\n",
progname, dir_name);
plog(XLOG_WARNING, "failsafe %s not a symlink\n",
dir_name);
} else {
unlink(dir_name);
if (symlink(alt_spooldir, dir_name) < 0) {
fprintf(stderr,
"%s: cannot create failsafe symlink %s -> ",
progname, dir_name);
perror(alt_spooldir);
plog(XLOG_WARNING,
"cannot create failsafe symlink %s -> %s: %m",
dir_name, alt_spooldir);
}
}
slinkname[-1] = '\0'; /* resplit dir_name */
} /* end of "if (!forcefast) {" */
/*
* Register hlfsd as an nfs service with the portmapper.
*/
#ifdef HAVE_TRANSPORT_TYPE_TLI
ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
#else /* not HAVE_TRANSPORT_TYPE_TLI */
ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
if (ret != 0)
fatal("cannot create NFS service");
#ifdef HAVE_SIGACTION
sa.sa_handler = proceed;
sa.sa_flags = 0;
sigemptyset(&(sa.sa_mask));
sigaddset(&(sa.sa_mask), SIGUSR2);
sigaction(SIGUSR2, &sa, NULL);
#else /* not HAVE_SIGACTION */
signal(SIGUSR2, proceed);
#endif /* not HAVE_SIGACTION */
plog(XLOG_INFO, "Initializing hlfsd...");
hlfsd_init(); /* start up child (forking) to run svc_run */
#ifdef HAVE_SIGACTION
sa.sa_handler = reaper;
sa.sa_flags = 0;
sigemptyset(&(sa.sa_mask));
sigaddset(&(sa.sa_mask), SIGCHLD);
sigaction(SIGCHLD, &sa, NULL);
#else /* not HAVE_SIGACTION */
signal(SIGCHLD, reaper);
#endif /* not HAVE_SIGACTION */
#ifdef DEBUG
/*
* In the parent, if -D nodaemon (or -D daemon) , we don't need to
* set this signal handler.
*/
amuDebug(D_DAEMON) {
#endif /* DEBUG */
/* XXX: port to use pure svr4 signals */
while (stoplight != SIGUSR2) {
int s = -99;
plog(XLOG_INFO, "parent waits for child to setup");
s = sigpause(0); /* wait for child to set up */
}
#ifdef DEBUG
}
#endif /* DEBUG */
/*
* setup options to mount table (/etc/{mtab,mnttab}) entry
*/
sprintf(hostpid_fs, "%s:(pid%d)", hostname, masterpid);
memset((char *) &mnt, 0, sizeof(mnt));
mnt.mnt_dir = dir_name; /* i.e., "/mail" */
mnt.mnt_fsname = hostpid_fs;
if (mntopts) {
mnt.mnt_opts = mntopts;
} else {
strcpy(preopts, default_mntopts);
/*
* Turn off all kinds of attribute and symlink caches as
* much as possible. Also make sure that mount does not
* show up to df.
*/
#ifdef MNTTAB_OPT_INTR
strcat(preopts, ",");
strcat(preopts, MNTTAB_OPT_INTR);
#endif /* MNTTAB_OPT_INTR */
#ifdef MNTTAB_OPT_IGNORE
strcat(preopts, ",");
strcat(preopts, MNTTAB_OPT_IGNORE);
#endif /* MNTTAB_OPT_IGNORE */
#ifdef MNT2_GEN_OPT_CACHE
strcat(preopts, ",nocache");
#endif /* MNT2_GEN_OPT_CACHE */
#ifdef MNT2_NFS_OPT_SYMTTL
strcat(preopts, ",symttl=0");
#endif /* MNT2_NFS_OPT_SYMTTL */
mnt.mnt_opts = preopts;
}
/*
* Make sure that amd's top-level NFS mounts are hidden by default
* from df.
* If they don't appear to support the either the "ignore" mnttab
* option entry, or the "auto" one, set the mount type to "nfs".
*/
mnt.mnt_type = HIDE_MOUNT_TYPE;
/*
* Set the address field of the nfs_args structure.
*/
memset((char *) &mountargs, 0, sizeof(mountargs));
#ifdef HAVE_TRANSPORT_TYPE_TLI
mountargs.addr = &nfsxprt->xp_ltaddr;
/*
* set up knconf field.
* the allocated mountargs.knconf is not freed via free_knetconfig().
*/
if (get_knetconfig(&mountargs.knconf, nfsncp, NULL) < 0) {
plog(XLOG_ERROR, "cannot fill knetconfig structure for mountargs");
}
/*
* set up syncaddr field
*/
mountargs.syncaddr = (struct netbuf *) NULL;
#else /* not HAVE_TRANSPORT_TYPE_TLI */
amu_get_myaddress(&localsocket.sin_addr);
localsocket.sin_family = AF_INET;
localsocket.sin_port = nfsxprt->xp_port;
NFS_SA_DREF(mountargs, &localsocket);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
/*
* Update filehandle field
*/
NFS_FH_DREF(mountargs.NFS_FH_FIELD, root_fhp);
#ifdef HAVE_FIELD_NFS_ARGS_T_FHSIZE
mountargs.fhsize = FHSIZE;
#endif /* HAVE_FIELD_NFS_ARGS_T_FHSIZE */
/*
* Update hostname field.
* Make some name prog:pid (i.e., hlfsd:174) for hostname
*/
sprintf(progpid_fs, "%s:%d", progname, masterpid);
/* Most kernels have a name length restriction. */
if ((int) strlen(progpid_fs) >= (int) MAXHOSTNAMELEN)
strcpy(progpid_fs + MAXHOSTNAMELEN - 3, "..");
NFS_HN_DREF(mountargs.hostname, progpid_fs);
/*
* General mount options
*/
#ifdef HAVE_TRANSPORT_TYPE_TLI
mountargs.flags |= MNT2_NFS_OPT_KNCONF;
#endif /* HAVE_TRANSPORT_TYPE_TLI */
#ifdef MNT2_NFS_OPT_FSNAME
mountargs.fsname = hostpid_fs;
mountargs.flags |= MNT2_NFS_OPT_FSNAME;
#endif /* MNT2_NFS_OPT_FSNAME */
#ifdef MNT2_NFS_OPT_HOSTNAME
mountargs.flags |= MNT2_NFS_OPT_HOSTNAME;
#endif /* MNT2_NFS_OPT_HOSTNAME */
mountargs.timeo = hasmntval(&mnt, MNTTAB_OPT_TIMEO);
#ifdef MNT2_NFS_OPT_TIMEO
if (mountargs.timeo)
mountargs.flags |= MNT2_NFS_OPT_TIMEO;
#endif /* MNT2_NFS_OPT_TIMEO */
mountargs.retrans = hasmntval(&mnt, MNTTAB_OPT_RETRANS);
#ifdef MNT2_NFS_OPT_RETRANS
if (mountargs.retrans)
mountargs.flags |= MNT2_NFS_OPT_RETRANS;
#endif /* MNT2_NFS_OPT_RETRANS */
if (hasmntopt(&mnt, MNTTAB_OPT_SOFT) != NULL)
mountargs.flags |= MNT2_NFS_OPT_SOFT;
#ifdef MNTTAB_OPT_INT
if (hasmntopt(&mnt, MNTTAB_OPT_INTR) != NULL)
mountargs.flags |= MNT2_NFS_OPT_INT;
#endif /* MNTTAB_OPT_INT */
#ifdef MNT2_NFS_OPT_BIODS
if (mountargs.biods = hasmntval(&mnt, MNTTAB_OPT_BIODS))
mountargs.flags |= MNT2_NFS_OPT_BIODS;
#endif /* MNT2_NFS_OPT_BIODS */
#ifdef MNT2_NFS_OPT_DUMBTIMR
mountargs.flags |= MNT2_NFS_OPT_DUMBTIMR;
#endif /* MNT2_NFS_OPT_DUMBTIMR */
#ifdef MNT2_NFS_OPT_NOAC
mountargs.flags |= MNT2_NFS_OPT_NOAC;
#endif /* MNT2_NFS_OPT_NOAC */
#ifdef MNT2_NFS_OPT_ACREGMIN
mountargs.flags |= MNT2_NFS_OPT_ACREGMIN;
mountargs.acregmin = SYMTTL_ATTR_CACHE_VALUE;
#endif /* MNT2_NFS_OPT_ACREGMIN */
#ifdef MNT2_NFS_OPT_ACREGMAX
mountargs.flags |= MNT2_NFS_OPT_ACREGMAX;
mountargs.acregmax = SYMTTL_ATTR_CACHE_VALUE;
#endif /* MNT2_NFS_OPT_ACREGMAX */
#ifdef MNT2_NFS_OPT_ACDIRMIN
mountargs.flags |= MNT2_NFS_OPT_ACDIRMIN;
mountargs.acdirmin = SYMTTL_ATTR_CACHE_VALUE;
#endif /* MNT2_NFS_OPT_ACDIRMIN */
#ifdef MNT2_NFS_OPT_ACDIRMAX
mountargs.flags |= MNT2_NFS_OPT_ACDIRMAX;
mountargs.acdirmax = SYMTTL_ATTR_CACHE_VALUE;
#endif /* MNT2_NFS_OPT_ACDIRMAX */
#ifdef MNT2_NFS_OPT_SYMTTL
mountargs.flags |= MNT2_NFS_OPT_SYMTTL;
mountargs.symttl = 0;
#endif /* MNT2_NFS_OPT_SYMTTL */
#if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX)
if (hasmntopt(&mnt, MNTTAB_OPT_POSIX) != NULL) {
mountargs.flags |= MNT2_NFS_OPT_POSIX;
mountargs.pathconf = NULL;
}
#endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */
mntflags = compute_mount_flags(&mnt);
#if defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY)
/*
* Overlay this amd mount (presumably on another amd which died
* before and left the machine hung). This will allow a new amd or
* hlfsd to be remounted on top of another one.
* -Erez Zadok <ezk@cs.columbia.edu>
*/
if (hasmntopt(&mnt, MNTTAB_OPT_OVERLAY) != NULL) {
mntflags |= MNT2_GEN_OPT_OVERLAY;
plog(XLOG_INFO, "using and overlay mount");
}
#endif /* defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY) */
retry = hasmntval(&mnt, MNTTAB_OPT_RETRY);
/*
* The following code could be cleverly ifdef-ed, but I duplicated the
* mount_fs call three times for simplicity and readability.
*/
#ifdef DEBUG
/*
* For some reason, this mount may have to be done in the background, if I am
* using -D nodebug. I suspect that the actual act of mounting requires
* calling to hlfsd itself to invoke one or more of its nfs calls, to stat
* /mail. That means that even if you say -D nodaemon, at least the mount
* of hlfsd itself on top of /mail will be done in the background.
* The other alternative I have is to run svc_run, but set a special
* signal handler to perform the mount in N seconds via some alarm.
* -Erez Zadok.
*/
if (debug_flags & D_DAEMON) { /* asked for -D daemon */
if (mount_fs(&mnt, mntflags, (caddr_t) & mountargs, retry, type, 0, NULL) < 0)
fatal("nfsmount: %m");
} else { /* asked for -D nodaemon */
if (fork() == 0) { /* child runs mount */
if (mount_fs(&mnt, mntflags, (caddr_t) & mountargs, retry, type, 0, NULL) < 0)
fatal("nfsmount: %m");
exit(0); /* all went well */
}
}
#else /* not DEBUG */
if (mount_fs(&mnt, mntflags, (caddr_t) & mountargs, retry, type, 0, NULL) < 0)
fatal("nfsmount: %m");
#endif /* not DEBUG */
if (printpid)
printf("%d\n", masterpid);
plog(XLOG_INFO, "hlfsd ready to serve");
#ifdef DEBUG
/*
* If asked not to fork a daemon (-D nodaemon), then hlfsd_init()
* will not run svc_run. We must start svc_run here.
*/
dlog("starting no-daemon debugging svc_run");
amuDebugNo(D_DAEMON)
svc_run();
#endif /* DEBUG */
cleanup(0); /* should never happen here */
return (0); /* everything went fine? */
}
static void
hlfsd_init(void)
{
int child = 0;
#ifdef HAVE_SIGACTION
struct sigaction sa;
#endif /* HAVE_SIGACTION */
#ifndef HAVE_SETPGRP
int tty;
#endif /* not HAVE_SETPGRP */
#ifdef DEBUG
/*
* If -D daemon then we must fork.
*/
amuDebug(D_DAEMON)
#endif /* DEBUG */
child = fork();
if (child < 0)
fatal("fork: %m");
if (child != 0) { /* parent process - save child pid */
masterpid = child;
mypid = getpid(); /* for AMD routines */
return;
}
/*
* CHILD CODE:
* initialize server
*/
plog(XLOG_INFO, "initializing home directory database");
init_homedir();
plog(XLOG_INFO, "home directory database initialized");
masterpid = serverpid = mypid = getpid();
/*
* SIGALRM/SIGHUP: reload password database if timer expired
* or user sent HUP signal.
*/
#ifdef HAVE_SIGACTION
sa.sa_handler = reload;
sa.sa_flags = 0;
sigemptyset(&(sa.sa_mask));
sigaddset(&(sa.sa_mask), SIGALRM);
sigaddset(&(sa.sa_mask), SIGHUP);
sigaction(SIGALRM, &sa, NULL);
sigaction(SIGHUP, &sa, NULL);
#else /* not HAVE_SIGACTION */
signal(SIGALRM, reload);
signal(SIGHUP, reload);
#endif /* not HAVE_SIGACTION */
/*
* SIGTERM: cleanup and exit.
*/
#ifdef HAVE_SIGACTION
sa.sa_handler = cleanup;
sa.sa_flags = 0;
sigemptyset(&(sa.sa_mask));
sigaddset(&(sa.sa_mask), SIGTERM);
sigaction(SIGTERM, &sa, NULL);
#else /* not HAVE_SIGACTION */
signal(SIGTERM, cleanup);
#endif /* not HAVE_SIGACTION */
/*
* SIGCHLD: interlock sycronization and testing
*/
#ifdef HAVE_SIGACTION
sa.sa_handler = interlock;
sa.sa_flags = 0;
sigemptyset(&(sa.sa_mask));
sigaddset(&(sa.sa_mask), SIGCHLD);
sigaction(SIGCHLD, &sa, NULL);
#else /* not HAVE_SIGACTION */
signal(SIGCHLD, interlock);
#endif /* not HAVE_SIGACTION */
/*
* SIGUSR1: dump internal hlfsd maps/cache to file
*/
#ifdef HAVE_SIGACTION
# if defined(DEBUG) || defined(DEBUG_PRINT)
sa.sa_handler = plt_print;
# else /* not defined(DEBUG) || defined(DEBUG_PRINT) */
sa.sa_handler = SIG_IGN;
# endif /* not defined(DEBUG) || defined(DEBUG_PRINT) */
sa.sa_flags = 0;
sigemptyset(&(sa.sa_mask));
sigaddset(&(sa.sa_mask), SIGUSR1);
sigaction(SIGUSR1, &sa, NULL);
#else /* not HAVE_SIGACTION */
# if defined(DEBUG) || defined(DEBUG_PRINT)
signal(SIGUSR1, plt_print);
# else /* not defined(DEBUG) || defined(DEBUG_PRINT) */
signal(SIGUSR1, SIG_IGN);
# endif /* not defined(DEBUG) || defined(DEBUG_PRINT) */
#endif /* not HAVE_SIGACTION */
if (setitimer(ITIMER_REAL, &reloadinterval, (struct itimerval *) 0) < 0)
fatal("setitimer: %m");
gettimeofday((struct timeval *) &startup, (struct timezone *) 0);
#ifdef DEBUG
/*
* If -D daemon, then start serving here in the child,
* and the parent will exit. But if -D nodaemon, then
* skip this code and make sure svc_run is entered elsewhere.
*/
amuDebug(D_DAEMON) {
#endif /* DEBUG */
#ifdef HAVE_SETPGID
setpgid(getpid(), getpid());
#else /* not HAVE_SETPGID */
# ifdef HAVE_SETPGRP
setpgrp();
# else /* not HAVE_SETPGRP */
if ((tty = open("/dev/tty", O_RDWR)) < 0) {
/* not an error if already no ctty */
if (errno != ENXIO)
plog(XLOG_WARNING,
"Could not open controlling tty: %m");
} else {
if (ioctl(tty, TIOCNOTTY, 0) < 0 && errno != ENOTTY)
plog(XLOG_WARNING,
"Could not disassociate tty (TIOCNOTTY): %m");
close(tty);
}
# endif /* not HAVE_SETPGRP */
#endif /* not HAVE_SETPGID */
/*
* signal parent we are ready. parent should
* mount(2) and die.
*/
if (kill(getppid(), SIGUSR2) < 0)
fatal("kill: %m");
plog(XLOG_INFO, "starting svc_run");
svc_run();
cleanup(0); /* should never happen, just in case */
#ifdef DEBUG
} /* end of code that runs iff hlfsd daemonizes */
#endif /* DEBUG */
}
static RETSIGTYPE
proceed(int signum)
{
stoplight = signum;
}
static RETSIGTYPE
reload(int signum)
{
int child;
int status;
if (getpid() != masterpid)
return;
/*
* If received a SIGHUP, close and reopen the log file (so that it
* can be rotated)
*/
if (signum == SIGHUP && logfile)
switch_to_logfile(logfile);
if ((child = fork()) > 0) {
serverpid = child;
init_homedir();
if (kill(child, SIGKILL) < 0) {
plog(XLOG_ERROR, "kill child: %m");
} else { /* wait for child to die before continue */
if (wait(&status) != child) {
/*
* I took out this line because it generates
* annoying output. It indicates a very
* small bug in hlfsd which is totally
* harmless. It causes hlfsd to work a bit
* harder than it should. Nevertheless, I
* intend on fixing it in a future release.
* Erez Zadok <ezk@cs.columbia.edu>
*/
/* plog(XLOG_ERROR, "unknown child"); */
}
}
serverpid = masterpid;
} else if (child < 0) {
plog(XLOG_ERROR, "unable to fork: %m");
} else /* let child handle requests while we reload */
serverpid = getpid();
}
RETSIGTYPE
cleanup(int signum)
{
struct stat stbuf;
int umount_result;
#ifdef DEBUG
amuDebug(D_DAEMON)
#endif /* DEBUG */
if (getpid() != masterpid)
return;
#ifdef DEBUG
amuDebug(D_DAEMON)
#endif /* DEBUG */
if (fork() != 0) {
masterpid = 0;
return;
}
mypid = getpid();
for (;;) {
while ((umount_result = UMOUNT_FS(dir_name)) == EBUSY) {
#ifdef DEBUG
dlog("cleanup(): umount delaying for 10 seconds");
#endif /* DEBUG */
sleep(10);
}
if (stat(dir_name, &stbuf) == 0 && stbuf.st_ino == ROOTID) {
plog(XLOG_ERROR, "unable to unmount %s", dir_name);
plog(XLOG_ERROR, "suspending, unmount before terminating");
kill(mypid, SIGSTOP);
continue; /* retry unmount */
}
break;
}
#ifdef DEBUG
dlog("cleanup(): killing processes and terminating");
amuDebug(D_DAEMON)
#endif /* DEBUG */
kill(masterpid, SIGKILL);
#ifdef DEBUG
amuDebug(D_DAEMON)
#endif /* DEBUG */
kill(serverpid, SIGKILL);
plog(XLOG_INFO, "hlfsd terminating with status 0\n");
exit(0);
}
static RETSIGTYPE
reaper(int signum)
{
int result;
if (wait(&result) == masterpid) {
exit(4);
}
}
void
hlfsd_going_down(int rc)
{
int mypid = getpid();
if (mypid == masterpid)
cleanup(0);
else if (mypid == serverpid)
kill(masterpid, SIGTERM);
exit(rc);
}
void
fatal(char *mess)
{
if (logfile && !STREQ(logfile, "stderr")) {
char lessmess[128];
int messlen;
messlen = strlen(mess);
if (!STREQ(&mess[messlen + 1 - sizeof(ERRM)], ERRM))
fprintf(stderr, "%s: %s\n", progname, mess);
else {
strcpy(lessmess, mess);
lessmess[messlen - 4] = '\0';
if (errno < sys_nerr)
fprintf(stderr, "%s: %s: %s\n", progname,
lessmess, sys_errlist[errno]);
else
fprintf(stderr, "%s: %s: Error %d\n",
progname, lessmess, errno);
}
}
plog(XLOG_FATAL, mess);
hlfsd_going_down(1);
}

148
usr.sbin/amd/hlfsd/hlfsd.h Normal file
View File

@ -0,0 +1,148 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: hlfsd.h,v 1.1.1.1 1997/07/24 21:22:42 christos Exp $
*
* HLFSD was written at Columbia University Computer Science Department, by
* Erez Zadok <ezk@cs.columbia.edu> and Alexander Dupuy <dupuy@cs.columbia.edu>
* It is being distributed under the same terms and conditions as amd does.
*/
#ifndef _HLFSD_HLFS_H
#define _HLFSD_HLFS_H
/*
* MACROS AND CONSTANTS:
*/
#define HLFSD_VERSION "hlfsd 1.1 (March 4, 1997)"
#define PERS_SPOOLMODE 0755
#define OPEN_SPOOLMODE 01777
#define ROOTID -1 /* don't change this from being -1 */
#define SLINKID -2 /* don't change this from being -2 */
#define DOTSTRING "."
#define DOTCOOKIE 1
#define DOTDOTCOOKIE 2
#define SLINKCOOKIE 3
#define ALT_SPOOLDIR "/var/hlfs" /* symlink to use if others fail */
#define HOME_SUBDIR ".hlfsdir" /* dirname in user's home dir */
#define DEFAULT_DIRNAME "/hlfs/home"
#define DEFAULT_INTERVAL 900 /* secs b/t re-reads of the password maps */
#define DEFAULT_CACHE_INTERVAL 300 /* secs during which assume a link is up */
#define DEFAULT_HLFS_GROUP "hlfs" /* Group name for special hlfs_gid */
#define PROGNAMESZ (MAXHOSTNAMELEN - 5)
#ifdef MNT2_NFS_OPT_SYMTTL
# define SYMTTL_ATTR_CACHE_VALUE 0
#else /* MNT2_NFS_OPT_SYMTTL */
# define SYMTTL_ATTR_CACHE_VALUE 1
#endif /* MNT2_NFS_OPT_SYMTTL */
#ifdef HAVE_SYSLOG
# define DEFAULT_LOGFILE "syslog"
#else /* not HAVE)_SYSLOG */
# define DEFAULT_LOGFILE 0
#endif /* not HAVE)_SYSLOG */
#define ERRM ": %m"
#define fatalerror(str) \
(fatal (strcat (strnsave ((str), strlen ((str)) + sizeof (ERRM) - 1), ERRM)))
/*
* TYPDEFS:
*/
typedef struct uid2home_t uid2home_t;
typedef struct username2uid_t username2uid_t;
/*
* STRUCTURES:
*/
struct uid2home_t {
uid_t uid;
pid_t child;
char *home;
char *uname;
u_long last_access_time;
int last_status; /* 0=used $HOME/.hlfsspool; !0=used alt dir */
};
struct username2uid_t {
char *username;
uid_t uid;
char *home;
};
/*
* EXTERNALS:
*/
extern RETSIGTYPE cleanup(int);
extern RETSIGTYPE interlock(int);
extern SVCXPRT *nfs_program_2_transp; /* For quick_reply() */
extern SVCXPRT *nfsxprt;
extern char *alt_spooldir;
extern char *home_subdir;
extern char *homedir(int);
extern char *mailbox(int, char *);
extern char *slinkname;
extern char mboxfile[];
extern int cache_interval;
extern int hlfs_gid;
extern int noverify;
extern int serverpid;
extern int sys_nerr;
extern int untab_index(char *username);
extern am_nfs_fh *root_fhp;
extern am_nfs_fh root;
extern nfstime startup;
extern uid2home_t *plt_search(int);
extern username2uid_t *untab; /* user name table */
extern void fatal(char *);
extern void init_homedir(void);
#if defined(DEBUG) || defined(DEBUG_PRINT)
extern void plt_dump(uid2home_t *, pid_t);
extern void plt_print(int);
#endif /* defined(DEBUG) || defined(DEBUG_PRINT) */
#endif /* _HLFSD_HLFS_H */

View File

@ -0,0 +1,655 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: homedir.c,v 1.1.1.1 1997/07/24 21:22:41 christos Exp $
*
* HLFSD was written at Columbia University Computer Science Department, by
* Erez Zadok <ezk@cs.columbia.edu> and Alexander Dupuy <dupuy@cs.columbia.edu>
* It is being distributed under the same terms and conditions as amd does.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <hlfsd.h>
/*
* STATIC VARIABLES:
*/
static hlfsd_diskspace(char *);
static hlfsd_stat(char *, struct stat *);
static int cur_pwtab_num = 0, max_pwtab_num = 0;
static int plt_reset(void);
static uid2home_t *lastchild;
static uid2home_t *pwtab;
static void delay(uid2home_t *, int);
static void plt_init(void);
static void table_add(int, char *, char *);
/*
* GLOBALS:
*/
username2uid_t *untab; /* user name table */
char mboxfile[MAXPATHLEN];
/*
* read and hash the passwd file or NIS map
*/
void
init_homedir(void)
{
plt_init();
}
/*
* Return the home directory pathname for the user with uid "userid".
*/
char *
homedir(int userid)
{
static char linkval[MAXPATHLEN + 1];
static struct timeval tp;
uid2home_t *found;
char *homename;
struct stat homestat;
if ((int) userid == 0) { /* force superuser to use "/" as home */
sprintf(linkval, "/%s", home_subdir);
return linkval;
}
if ((found = plt_search(userid)) == (uid2home_t *) NULL) {
return alt_spooldir; /* use alt spool for unknown uid */
}
homename = found->home;
if (homename[0] != '/' || homename[1] == '\0') {
found->last_status = 1;
return alt_spooldir; /* use alt spool for / or rel. home */
}
sprintf(linkval, "%s/%s", homename, home_subdir);
if (noverify) {
found->last_status = 0;
return linkval;
}
/*
* To optimize hlfsd, we don't actually check the validity of the
* symlink if it has been in checked in the last N seconds. It is
* very likely that the link, machine, and filesystem are still
* valid, as long as N is small. But if N ls large, that may not be
* true. That's why the default N is 5 minutes, but we allow the
* user to override this value via a command line option. Note that
* we do not update the last_access_time each time it is accessed,
* but only once every N seconds.
*/
if (gettimeofday(&tp, (struct timezone *) NULL) < 0) {
tp.tv_sec = 0;
} else {
if ((tp.tv_sec - found->last_access_time) < cache_interval) {
if (found->last_status == 0) {
return linkval;
} else {
return alt_spooldir;
}
} else {
found->last_access_time = tp.tv_sec;
}
}
#ifdef DEBUG
/*
* only run this forking code if asked for -D fork
* or if did not ask for -D nofork
*/
amuDebug(D_FORK) {
#endif /* DEBUG */
/* fork child to process request if none in progress */
if (found->child && kill(found->child, 0))
found->child = 0;
if (found->child)
delay(found, 5); /* wait a bit if in progress */
if (found->child) { /* better safe than sorry - maybe */
found->last_status = 1;
return alt_spooldir;
}
if ((found->child = fork()) < 0) {
found->last_status = 1;
return alt_spooldir;
}
if (found->child) {
/* parent */
#ifdef DEBUG
if (lastchild)
plog(XLOG_INFO, "cache spill uid = %d, pid = %d, home = %s",
lastchild->uid, lastchild->child,
lastchild->home);
#endif /* DEBUG */
lastchild = found;
return (char *) NULL; /* return NULL to parent, so it can continue */
}
#ifdef DEBUG
} /* end of Debug(D_FORK) */
#endif /* DEBUG */
/*
* CHILD: (or parent if -D nofork)
*
* Check and create dir if needed.
* Check disk space and/or quotas too.
*
* We don't need to set the _last_status field of found after the fork
* in the child, b/c that information would be later determined in
* nfsproc_readlink_2() and the correct exit status would be returned
* to the parent upon SIGCHLD in interlock().
*
*/
if (seteuid(userid) < 0) {
plog(XLOG_WARNING, "could not seteuid to %d", userid);
return linkval;
}
if (hlfsd_stat(linkval, &homestat) < 0) {
if (errno == ENOENT) { /* make the spool dir if possible */
/* don't use recursive mkdirs here */
if (mkdir(linkval, PERS_SPOOLMODE) < 0) {
seteuid(0);
plog(XLOG_WARNING, "can't make directory %s: %m", linkval);
return alt_spooldir;
}
/* fall through to testing the disk space / quota */
} else { /* the home dir itself must not exist then */
seteuid(0);
plog(XLOG_WARNING, "bad link to %s: %m", linkval);
return alt_spooldir;
}
}
/*
* If gets here, then either the spool dir in the home dir exists,
* or it was just created. In either case, we now need to
* test if we can create a small file and write at least one
* byte into it. This will test that we have both enough inodes
* and disk blocks to spare, or they fall within the user's quotas too.
* We are still seteuid to the user at this point.
*/
if (hlfsd_diskspace(linkval) < 0) {
seteuid(0);
plog(XLOG_WARNING, "no more space in %s: %m", linkval);
return alt_spooldir;
} else {
seteuid(0);
return linkval;
}
}
static int
hlfsd_diskspace(char *path)
{
char buf[MAXPATHLEN];
int fd, len;
sprintf(buf, "%s/._hlfstmp_%lu", path, getpid());
if ((fd = open(buf, O_RDWR | O_CREAT, 0600)) < 0) {
plog(XLOG_ERROR, "cannot open %s: %m", buf);
return -1;
}
len = strlen(buf);
if (write(fd, buf, len) < len) {
plog(XLOG_ERROR, "cannot write \"%s\" (%d bytes) to %s : %m", buf, len, buf);
close(fd);
unlink(buf); /* cleanup just in case */
return -1;
}
if (unlink(buf) < 0) {
plog(XLOG_ERROR, "cannot unlink %s : %m", buf);
}
close(fd);
return 0;
}
static int
hlfsd_stat(char *path, struct stat *statp)
{
if (stat(path, statp) < 0)
return -1;
else if (!S_ISDIR(statp->st_mode)) {
errno = ENOTDIR;
return -1;
}
return 0;
}
static void
delay(uid2home_t *found, int secs)
{
struct timeval tv;
#ifdef DEBUG
if (found)
dlog("delaying on child %d for %d seconds", found->child, secs);
#endif /* DEBUG */
tv.tv_usec = 0;
do {
tv.tv_sec = secs;
if (select(0, 0, 0, 0, &tv) == 0)
break;
} while (--secs && found->child);
}
/*
* This function is called when a child has terminated after
* servicing an nfs request. We need to check the exit status and
* update the last_status field of the requesting user.
*/
RETSIGTYPE
interlock(int signum)
{
int child;
uid2home_t *lostchild;
#ifdef HAVE_SIGACTION
int status;
#else /* not HAVE_SIGACTION */
union wait status;
#endif /* not HAVE_SIGACTION */
#ifdef HAVE_WAITPID
while ((child = waitpid((pid_t) -1, &status, WNOHANG)) > 0) {
#else /* not HAVE_WAITPID */
while ((child = wait3(&status, WNOHANG, (struct rusage *) 0)) > 0) {
#endif /* not HAVE_WAITPID */
/* high chances this was the last child forked */
if (lastchild && lastchild->child == child) {
lastchild->child = 0;
#ifdef HAVE_SIGACTION
if (WIFEXITED(status))
lastchild->last_status = WEXITSTATUS(status);
#else /* not HAVE_SIGACTION */
if (status.w_retcode)
lastchild->last_status = status.w_retcode;
#endif /* not HAVE_SIGACTION */
lastchild = (uid2home_t *) NULL;
} else {
/* and if not, we have to search for it... */
for (lostchild = pwtab; lostchild < &pwtab[cur_pwtab_num]; lostchild++) {
if (lostchild->child == child) {
#ifdef HAVE_SIGACTION
if (WIFEXITED(status))
lostchild->last_status = WEXITSTATUS(status);
#else /* not HAVE_SIGACTION */
if (status.w_retcode)
lostchild->last_status = status.w_retcode;
#endif /* not HAVE_SIGACTION */
lostchild->child = 0;
break;
}
}
}
}
}
/*
* PASSWORD AND USERNAME LOOKUP TABLES FUNCTIONS
*/
/*
* get index of UserName table entry which matches username.
* must not return uid_t because we want to return a negative number.
*/
int
untab_index(char *username)
{
int max, min, mid, cmp;
max = cur_pwtab_num - 1;
min = 0;
do {
mid = (max + min) / 2;
cmp = strcmp(untab[mid].username, username);
if (cmp == 0) /* record found! */
return mid;
if (cmp > 0)
max = mid;
else
min = mid;
} while (max > min + 1);
if (STREQ(untab[max].username, username))
return max;
if (STREQ(untab[min].username, username))
return min;
/* if gets here then record was not found */
return -1;
}
/*
* Don't make this return a uid_t, because we need to return negative
* numbers as well (error codes.)
*/
int
uidof(char *username)
{
int idx;
if ((idx = untab_index(username)) < 0) /* not found */
return -3; /* an invalid user id */
return untab[idx].uid;
}
/*
* Don't make this return a uid_t, because we need to return negative
* numbers as well (error codes.)
*/
char *
homeof(char *username)
{
int idx;
if ((idx = untab_index(username)) < 0) /* not found */
return (char *) NULL; /* an invalid user id */
return untab[idx].home;
}
char *
mailbox(int uid, char *username)
{
char *home;
if (uid < 0)
return (char *) NULL; /* not found */
if ((home = homeof(username)) == (char *) NULL)
return (char *) NULL;
if (STREQ(home, "/"))
sprintf(mboxfile, "/%s/%s", home_subdir, username);
else
sprintf(mboxfile, "%s/%s/%s", home, home_subdir, username);
return mboxfile;
}
static int
plt_compare_fxn(const voidp x, const voidp y)
{
uid2home_t *i = (uid2home_t *) x;
uid2home_t *j = (uid2home_t *) y;
return i->uid - j->uid;
}
static int
unt_compare_fxn(const voidp x, const voidp y)
{
username2uid_t *i = (username2uid_t *) x;
username2uid_t *j = (username2uid_t *) y;
return strcmp(i->username, j->username);
}
static void
plt_init(void)
{
struct passwd *pent_p;
if (plt_reset() < 0) /* could not reset table. skip. */
return;
plog(XLOG_INFO, "reading password map");
setpwent(); /* prepare to read passwd entries */
while ((pent_p = getpwent()) != (struct passwd *) NULL) {
table_add(pent_p->pw_uid, pent_p->pw_dir, pent_p->pw_name);
}
endpwent();
qsort((char *) pwtab, cur_pwtab_num, sizeof(uid2home_t),
plt_compare_fxn);
qsort((char *) untab, cur_pwtab_num, sizeof(username2uid_t),
unt_compare_fxn);
plog(XLOG_INFO, "password map read and sorted");
}
/*
* This is essentially so that we don't reset known good lookup tables when a
* YP server goes down.
*/
static int
plt_reset(void)
{
int i;
setpwent();
if (getpwent() == (struct passwd *) NULL) {
endpwent();
return -1; /* did not reset table */
}
endpwent();
lastchild = (uid2home_t *) NULL;
if (max_pwtab_num > 0) /* was used already. cleanup old table */
for (i = 0; i < cur_pwtab_num; ++i) {
if (pwtab[i].home)
free(pwtab[i].home);
pwtab[i].home = (char *) NULL;
pwtab[i].uid = -3; /* not a valid uid (yet...) */
pwtab[i].child = (pid_t) 0;
pwtab[i].uname = (char *) NULL; /* only a ptr to untab[i].username */
if (untab[i].username)
free(untab[i].username);
untab[i].username = (char *) NULL;
untab[i].uid = -3; /* invalid uid */
untab[i].home = (char *) NULL; /* only a ptr to pwtab[i].home */
}
cur_pwtab_num = 0; /* zero current size */
return 0; /* resetting ok */
}
/*
* u: uid number
* h: home directory
* n: user ID name
*/
static void
table_add(int u, char *h, char *n)
{
if (max_pwtab_num <= 0) { /* was never initialized */
max_pwtab_num = 1;
pwtab = (uid2home_t *) xmalloc(max_pwtab_num *
sizeof(uid2home_t));
untab = (username2uid_t *) xmalloc(max_pwtab_num *
sizeof(username2uid_t));
}
/* check if need more space. */
if (cur_pwtab_num + 1 > max_pwtab_num) {
/* need more space in table */
max_pwtab_num *= 2;
pwtab = (uid2home_t *) xrealloc(pwtab,
sizeof(uid2home_t) * max_pwtab_num);
untab = (username2uid_t *) xrealloc(untab,
sizeof(username2uid_t) *
max_pwtab_num);
}
/* add new password entry */
pwtab[cur_pwtab_num].home = xmalloc((strlen(h) + 1) * sizeof(char));
strcpy(pwtab[cur_pwtab_num].home, h);
pwtab[cur_pwtab_num].child = 0;
pwtab[cur_pwtab_num].last_access_time = 0;
pwtab[cur_pwtab_num].last_status = 0; /* assume best: used homedir */
pwtab[cur_pwtab_num].uid = u;
/* add new userhome entry */
untab[cur_pwtab_num].username = xmalloc((strlen(n) + 1) * sizeof(char));
strcpy(untab[cur_pwtab_num].username, n);
/* just a second pointer */
pwtab[cur_pwtab_num].uname = untab[cur_pwtab_num].username;
untab[cur_pwtab_num].uid = u;
untab[cur_pwtab_num].home = pwtab[cur_pwtab_num].home; /* a ptr */
++cur_pwtab_num; /* increment counter */
}
/*
* return entry in lookup table
*/
uid2home_t *
plt_search(int u)
{
int max, min, mid;
/*
* empty table should not happen,
* but I have a bug with signals to trace...
*/
if (pwtab == (uid2home_t *) NULL)
return (uid2home_t *) NULL;
max = cur_pwtab_num - 1;
min = 0;
do {
mid = (max + min) / 2;
if (pwtab[mid].uid == u) /* record found! */
return &pwtab[mid];
if (pwtab[mid].uid > u)
max = mid;
else
min = mid;
} while (max > min + 1);
if (pwtab[max].uid == u)
return &pwtab[max];
if (pwtab[min].uid == u)
return &pwtab[min];
/* if gets here then record was not found */
return (uid2home_t *) NULL;
}
#if defined(DEBUG) || defined(DEBUG_PRINT)
void
plt_print(int signum)
{
FILE *dumpfile;
int i;
if ((dumpfile = fopen("/tmp/hlfsdump", "a")) != NULL) {
fprintf(dumpfile, "\n\nNew plt_dump():\n");
for (i = 0; i < cur_pwtab_num; ++i)
fprintf(dumpfile,
"%4d %5lu %10lu %1d %4lu \"%s\" uname=\"%s\"\n",
i,
pwtab[i].child,
pwtab[i].last_access_time,
pwtab[i].last_status,
pwtab[i].uid,
pwtab[i].home,
pwtab[i].uname);
fprintf(dumpfile, "\nUserName table by plt_print():\n");
for (i = 0; i < cur_pwtab_num; ++i)
fprintf(dumpfile, "%4d : \"%s\" %4lu \"%s\"\n", i,
untab[i].username, untab[i].uid, untab[i].home);
fclose(dumpfile);
}
}
void
plt_dump(uid2home_t *lastc, pid_t this)
{
FILE *dumpfile;
int i;
if ((dumpfile = fopen("/var/tmp/hlfsdump", "a")) != NULL) {
fprintf(dumpfile, "\n\nNEW PLT_DUMP -- ");
fprintf(dumpfile, "lastchild->child=%d ",
(int) (lastc ? lastc->child : -999));
fprintf(dumpfile, ", child from wait3=%lu:\n", this);
for (i = 0; i < cur_pwtab_num; ++i)
fprintf(dumpfile, "%4d %5lu: %4lu \"%s\" uname=\"%s\"\n", i,
pwtab[i].child, pwtab[i].uid, pwtab[i].home, pwtab[i].uname);
fprintf(dumpfile, "\nUserName table by plt_dump():\n");
for (i = 0; i < cur_pwtab_num; ++i)
fprintf(dumpfile, "%4d : \"%s\" %4lu \"%s\"\n", i,
untab[i].username, untab[i].uid, untab[i].home);
fprintf(dumpfile, "ezk: ent=%d, uid=%lu, home=\"%s\"\n",
untab_index("ezk"),
untab[untab_index("ezk")].uid,
pwtab[untab[untab_index("ezk")].uid].home);
fprintf(dumpfile, "rezk: ent=%d, uid=%lu, home=\"%s\"\n",
untab_index("rezk"),
untab[untab_index("rezk")].uid,
pwtab[untab[untab_index("rezk")].uid].home);
fclose(dumpfile);
}
}
#endif /* defined(DEBUG) || defined(DEBUG_PRINT) */

View File

@ -0,0 +1,245 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: nfs_prot_svc.c,v 1.1.1.1 1997/07/24 21:22:41 christos Exp $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <hlfsd.h>
extern void * nfsproc_null_2_svc(void *, struct svc_req *);
extern nfsattrstat * nfsproc_getattr_2_svc(am_nfs_fh *, struct svc_req *);
extern nfsattrstat * nfsproc_setattr_2_svc(nfssattrargs *, struct svc_req *);
extern void * nfsproc_root_2_svc(void *, struct svc_req *);
extern nfsdiropres * nfsproc_lookup_2_svc(nfsdiropargs *, struct svc_req *);
extern nfsreadlinkres * nfsproc_readlink_2_svc(am_nfs_fh *, struct svc_req *);
extern nfsreadres * nfsproc_read_2_svc(nfsreadargs *, struct svc_req *);
extern void * nfsproc_writecache_2_svc(void *, struct svc_req *);
extern nfsattrstat * nfsproc_write_2_svc(nfswriteargs *, struct svc_req *);
extern nfsdiropres * nfsproc_create_2_svc(nfscreateargs *, struct svc_req *);
extern nfsstat * nfsproc_remove_2_svc(nfsdiropargs *, struct svc_req *);
extern nfsstat * nfsproc_rename_2_svc(nfsrenameargs *, struct svc_req *);
extern nfsstat * nfsproc_link_2_svc(nfslinkargs *, struct svc_req *);
extern nfsstat * nfsproc_symlink_2_svc(nfssymlinkargs *, struct svc_req *);
extern nfsdiropres * nfsproc_mkdir_2_svc(nfscreateargs *, struct svc_req *);
extern nfsstat * nfsproc_rmdir_2_svc(nfsdiropargs *, struct svc_req *);
extern nfsreaddirres * nfsproc_readdir_2_svc(nfsreaddirargs *, struct svc_req *);
extern nfsstatfsres * nfsproc_statfs_2_svc(am_nfs_fh *, struct svc_req *);
SVCXPRT *nfs_program_2_transp;
void
nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
{
union {
am_nfs_fh nfsproc_getattr_2_arg;
nfssattrargs nfsproc_setattr_2_arg;
nfsdiropargs nfsproc_lookup_2_arg;
am_nfs_fh nfsproc_readlink_2_arg;
nfsreadargs nfsproc_read_2_arg;
nfswriteargs nfsproc_write_2_arg;
nfscreateargs nfsproc_create_2_arg;
nfsdiropargs nfsproc_remove_2_arg;
nfsrenameargs nfsproc_rename_2_arg;
nfslinkargs nfsproc_link_2_arg;
nfssymlinkargs nfsproc_symlink_2_arg;
nfscreateargs nfsproc_mkdir_2_arg;
nfsdiropargs nfsproc_rmdir_2_arg;
nfsreaddirargs nfsproc_readdir_2_arg;
am_nfs_fh nfsproc_statfs_2_arg;
} argument;
char *result;
bool_t(*xdr_argument) (), (*xdr_result) ();
char *(*local) ();
nfs_program_2_transp = NULL;
switch (rqstp->rq_proc) {
case NFSPROC_NULL:
xdr_argument = xdr_void;
xdr_result = xdr_void;
local = (char *(*)()) nfsproc_null_2_svc;
break;
case NFSPROC_GETATTR:
xdr_argument = xdr_nfs_fh;
xdr_result = xdr_attrstat;
local = (char *(*)()) nfsproc_getattr_2_svc;
break;
case NFSPROC_SETATTR:
xdr_argument = xdr_sattrargs;
xdr_result = xdr_attrstat;
local = (char *(*)()) nfsproc_setattr_2_svc;
break;
case NFSPROC_ROOT:
xdr_argument = xdr_void;
xdr_result = xdr_void;
local = (char *(*)()) nfsproc_root_2_svc;
break;
case NFSPROC_LOOKUP:
xdr_argument = xdr_diropargs;
xdr_result = xdr_diropres;
local = (char *(*)()) nfsproc_lookup_2_svc;
/*
* Cheap way to pass transp down to afs_lookuppn so it can
* be stored in the am_node structure and later used for
* quick_reply().
*/
nfs_program_2_transp = transp;
break;
case NFSPROC_READLINK:
xdr_argument = xdr_nfs_fh;
xdr_result = xdr_readlinkres;
local = (char *(*)()) nfsproc_readlink_2_svc;
break;
case NFSPROC_READ:
xdr_argument = xdr_readargs;
xdr_result = xdr_readres;
local = (char *(*)()) nfsproc_read_2_svc;
break;
case NFSPROC_WRITECACHE:
xdr_argument = xdr_void;
xdr_result = xdr_void;
local = (char *(*)()) nfsproc_writecache_2_svc;
break;
case NFSPROC_WRITE:
xdr_argument = xdr_writeargs;
xdr_result = xdr_attrstat;
local = (char *(*)()) nfsproc_write_2_svc;
break;
case NFSPROC_CREATE:
xdr_argument = xdr_createargs;
xdr_result = xdr_diropres;
local = (char *(*)()) nfsproc_create_2_svc;
break;
case NFSPROC_REMOVE:
xdr_argument = xdr_diropargs;
xdr_result = xdr_nfsstat;
local = (char *(*)()) nfsproc_remove_2_svc;
break;
case NFSPROC_RENAME:
xdr_argument = xdr_renameargs;
xdr_result = xdr_nfsstat;
local = (char *(*)()) nfsproc_rename_2_svc;
break;
case NFSPROC_LINK:
xdr_argument = xdr_linkargs;
xdr_result = xdr_nfsstat;
local = (char *(*)()) nfsproc_link_2_svc;
break;
case NFSPROC_SYMLINK:
xdr_argument = xdr_symlinkargs;
xdr_result = xdr_nfsstat;
local = (char *(*)()) nfsproc_symlink_2_svc;
break;
case NFSPROC_MKDIR:
xdr_argument = xdr_createargs;
xdr_result = xdr_diropres;
local = (char *(*)()) nfsproc_mkdir_2_svc;
break;
case NFSPROC_RMDIR:
xdr_argument = xdr_diropargs;
xdr_result = xdr_nfsstat;
local = (char *(*)()) nfsproc_rmdir_2_svc;
break;
case NFSPROC_READDIR:
xdr_argument = xdr_readdirargs;
xdr_result = xdr_readdirres;
local = (char *(*)()) nfsproc_readdir_2_svc;
break;
case NFSPROC_STATFS:
xdr_argument = xdr_nfs_fh;
xdr_result = xdr_statfsres;
local = (char *(*)()) nfsproc_statfs_2_svc;
break;
default:
svcerr_noproc(transp);
return;
}
memset((char *) &argument, 0, sizeof(argument));
if (!svc_getargs(transp,
(XDRPROC_T_TYPE) xdr_argument,
(SVC_IN_ARG_TYPE) & argument)) {
plog(XLOG_ERROR,
"NFS xdr decode failed for %d %d %d",
rqstp->rq_prog, rqstp->rq_vers, rqstp->rq_proc);
svcerr_decode(transp);
return;
}
result = (*local) (&argument, rqstp);
nfs_program_2_transp = NULL;
if (result != NULL && !svc_sendreply(transp,
(XDRPROC_T_TYPE) xdr_result,
result)) {
svcerr_systemerr(transp);
}
if (!svc_freeargs(transp,
(XDRPROC_T_TYPE) xdr_argument,
(SVC_IN_ARG_TYPE) & argument)) {
plog(XLOG_FATAL, "unable to free rpc arguments in nfs_program_1");
going_down(1);
}
}

506
usr.sbin/amd/hlfsd/stubs.c Normal file
View File

@ -0,0 +1,506 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: stubs.c,v 1.1.1.1 1997/07/24 21:22:42 christos Exp $
*
* HLFSD was written at Columbia University Computer Science Department, by
* Erez Zadok <ezk@cs.columbia.edu> and Alexander Dupuy <dupuy@cs.columbia.edu>
* It is being distributed under the same terms and conditions as amd does.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <hlfsd.h>
/*
* STATIC VARIABLES:
*/
static nfsfattr rootfattr = {NFDIR, 0040555, 2, 0, 0, 512, 512, 0,
1, 0, ROOTID};
static nfsfattr slinkfattr = {NFLNK, 0120777, 1, 0, 0, NFS_MAXPATHLEN, 512, 0,
(NFS_MAXPATHLEN + 1) / 512, 0, SLINKID};
/* user name file attributes */
static nfsfattr un_fattr = {NFLNK, 0120777, 1, 0, 0, NFS_MAXPATHLEN, 512, 0,
(NFS_MAXPATHLEN + 1) / 512, 0, -3};
static int getcreds(struct svc_req *, uid_t *, int *);
static int started;
static am_nfs_fh slink = {{SLINKID}};
static am_nfs_fh un_fhandle = {{-3}};
/*
* GLOBALS:
*/
am_nfs_fh root = {{ROOTID}};
am_nfs_fh *root_fhp = &root;
voidp
nfsproc_null_2_svc(voidp argp, struct svc_req *rqstp)
{
static char res;
return (voidp) &res;
}
/* compare if two filehandles are equal */
static int
eq_fh(const am_nfs_fh *fh1, const am_nfs_fh *fh2)
{
return (!memcmp((char *) fh1, (char *) fh2, sizeof(am_nfs_fh)));
}
nfsattrstat *
nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
{
static nfsattrstat res;
uid_t uid = -3;
int gid = -3;
if (!started) {
started++;
rootfattr.na_ctime = startup;
rootfattr.na_mtime = startup;
slinkfattr.na_ctime = startup;
slinkfattr.na_mtime = startup;
un_fattr.na_ctime = startup;
un_fattr.na_mtime = startup;
}
if (eq_fh(argp, &root)) {
res.ns_status = NFS_OK;
res.ns_u.ns_attr_u = rootfattr;
} else if (eq_fh(argp, &slink)) {
#ifndef MNT2_NFS_OPT_SYMTTL
/*
* This code is needed to defeat Solaris 2.4's (and newer) symlink
* values cache. It forces the last-modifed time of the symlink to be
* current. It is not needed if the O/S has an nfs flag to turn off the
* symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez.
*/
if (++slinkfattr.na_mtime.nt_useconds == 0)
++slinkfattr.na_mtime.nt_seconds;
#endif /* not MNT2_NFS_OPT_SYMTTL */
res.ns_status = NFS_OK;
res.ns_u.ns_attr_u = slinkfattr;
} else {
if (getcreds(rqstp, &uid, &gid) < 0) {
res.ns_status = NFSERR_STALE;
return &res;
}
if (gid != hlfs_gid) {
res.ns_status = NFSERR_STALE;
} else {
memset((char *) &uid, 0, sizeof(int));
uid = *(u_int *) argp->fh_data;
if (plt_search(uid) != (uid2home_t *) NULL) {
res.ns_status = NFS_OK;
un_fattr.na_fileid = uid;
res.ns_u.ns_attr_u = un_fattr;
#ifdef DEBUG
dlog("nfs_getattr: succesful search for uid=%d, gid=%d", uid, gid);
#endif /* DEBUG */
} else { /* not found */
res.ns_status = NFSERR_STALE;
}
}
}
return &res;
}
nfsattrstat *
nfsproc_setattr_2_svc(nfssattrargs *argp, struct svc_req *rqstp)
{
static nfsattrstat res = {NFSERR_ROFS};
return &res;
}
voidp
nfsproc_root_2_svc(voidp argp, struct svc_req *rqstp)
{
static char res;
return (voidp) &res;
}
nfsdiropres *
nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
{
static nfsdiropres res;
int idx;
uid_t uid = -3;
int gid = -3;
if (!started) {
started++;
rootfattr.na_ctime = startup;
rootfattr.na_mtime = startup;
slinkfattr.na_ctime = startup;
slinkfattr.na_mtime = startup;
un_fattr.na_ctime = startup;
un_fattr.na_mtime = startup;
}
if (eq_fh(&argp->da_fhandle, &slink)) {
res.dr_status = NFSERR_NOTDIR;
return &res;
}
if (eq_fh(&argp->da_fhandle, &root)) {
if (argp->da_name[0] == '.' &&
(argp->da_name[1] == '\0' ||
(argp->da_name[1] == '.' &&
argp->da_name[2] == '\0'))) {
res.dr_u.dr_drok_u.drok_fhandle = root;
res.dr_u.dr_drok_u.drok_attributes = rootfattr;
res.dr_status = NFS_OK;
return &res;
}
if (STREQ(argp->da_name, slinkname)) {
res.dr_u.dr_drok_u.drok_fhandle = slink;
res.dr_u.dr_drok_u.drok_attributes = slinkfattr;
res.dr_status = NFS_OK;
return &res;
}
if (getcreds(rqstp, &uid, &gid) < 0 || gid != hlfs_gid) {
res.dr_status = NFSERR_NOENT;
return &res;
}
/* if get's here, gid == hlfs_gid */
if ((idx = untab_index(argp->da_name)) < 0) {
res.dr_status = NFSERR_NOENT;
return &res;
} else { /* entry found and gid is permitted */
un_fattr.na_fileid = untab[idx].uid;
res.dr_u.dr_drok_u.drok_attributes = un_fattr;
memset((char *) &un_fhandle, 0, sizeof(am_nfs_fh));
*(u_int *) un_fhandle.fh_data = (u_int) untab[idx].uid;
strncpy((char *) &un_fhandle.fh_data[sizeof(int)],
untab[idx].username,
sizeof(am_nfs_fh) - sizeof(int));
res.dr_u.dr_drok_u.drok_fhandle = un_fhandle;
res.dr_status = NFS_OK;
#ifdef DEBUG
dlog("nfs_lookup: succesful lookup for uid=%d, gid=%d: username=%s",
uid, gid, untab[idx].username);
#endif /* DEBUG */
return &res;
}
} /* end of "if (eq_fh(argp->dir.data, root.data)) {" */
res.dr_status = NFSERR_STALE;
return &res;
}
static int
getcreds(struct svc_req *rp, uid_t *u, int *g)
{
struct authunix_parms *aup = (struct authunix_parms *) NULL;
#ifdef HAVE_RPC_AUTH_DES_H
struct authdes_cred *adp;
#endif /* HAVE_RPC_AUTH_DES_H */
switch (rp->rq_cred.oa_flavor) {
case AUTH_UNIX:
aup = (struct authunix_parms *) rp->rq_clntcred;
*u = aup->aup_uid;
*g = aup->aup_gid;
break;
#ifdef HAVE_RPC_AUTH_DES_H
case AUTH_DES:
adp = (struct authdes_cred *) rp->rq_clntcred;
*g = -3; /* some unknown group id */
if (sscanf(adp->adc_fullname.name, "unix.%lu@", u) == 1)
break;
/* fall through */
#endif /* HAVE_RPC_AUTH_DES_H */
default:
*u = *g = -3; /* just in case */
svcerr_weakauth(nfsxprt);
return -1;
}
return 0; /* everything is ok */
}
nfsreadlinkres *
nfsproc_readlink_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
{
static nfsreadlinkres res;
uid_t userid = -3;
int groupid = hlfs_gid + 1; /* anything not hlfs_gid */
int retval = 0;
char *path_val = (char *) NULL;
char *username;
if (eq_fh(argp, &root)) {
res.rlr_status = NFSERR_ISDIR;
} else if (eq_fh(argp, &slink)) {
if (getcreds(rqstp, &userid, &groupid) < 0)
return (nfsreadlinkres *) NULL;
gettimeofday((struct timeval *) &slinkfattr.na_atime, (struct timezone *) 0);
res.rlr_status = NFS_OK;
if (groupid == hlfs_gid) {
res.rlr_u.rlr_data_u = DOTSTRING;
} else if (!(res.rlr_u.rlr_data_u = path_val = homedir(userid))) {
/*
* parent process (fork in homedir()) continues
* processing, by getting a NULL returned as a
* "special". Child returns result.
*/
return (nfsreadlinkres *) NULL;
}
} else { /* check if asked for user mailbox */
if (getcreds(rqstp, &userid, &groupid) < 0) {
return (nfsreadlinkres *) NULL;
}
if (groupid == hlfs_gid) {
memset((char *) &userid, 0, sizeof(int));
userid = *(u_int *) argp->fh_data;
username = (char *) &argp->fh_data[sizeof(int)];
if (!(res.rlr_u.rlr_data_u = mailbox(userid, username)))
return (nfsreadlinkres *) NULL;
} else {
res.rlr_status = NFSERR_STALE;
}
}
#ifdef DEBUG
dlog("nfs_readlink: mailbox for uid=%d, gid=%d is %s",
userid, groupid, (char *) res.rlr_u.rlr_data_u);
#endif /* DEBUG */
/* I don't think will pass this if -D nofork */
if (serverpid == getpid())
return &res;
if (!svc_sendreply(nfsxprt, (XDRPROC_T_TYPE) xdr_readlinkres, (SVC_IN_ARG_TYPE) &res))
svcerr_systemerr(nfsxprt);
/*
* Child exists here. We need to determine which
* exist status to return. The exit status
* is gathered using wait() and determines
* if we returned $HOME/.hlfsspool or $ALTDIR. The parent
* needs this info so it can update the lookup table.
*/
if (path_val && alt_spooldir && STREQ(path_val, alt_spooldir))
retval = 1; /* could not get real home dir (or uid 0 user) */
else
retval = 0;
#ifdef DEBUG
/*
* If asked for -D nofork, then must return the value,
* NOT exit, or else the main hlfsd server exits.
* Bug where is that status information being collected?
*/
amuDebugNo(D_FORK)
return &res;
#endif /* DEBUG */
exit(retval);
}
nfsreadres *
nfsproc_read_2_svc(nfsreadargs *argp, struct svc_req *rqstp)
{
static nfsreadres res = {NFSERR_ACCES};
return &res;
}
voidp
nfsproc_writecache_2_svc(voidp argp, struct svc_req *rqstp)
{
static char res;
return (voidp) &res;
}
nfsattrstat *
nfsproc_write_2_svc(nfswriteargs *argp, struct svc_req *rqstp)
{
static nfsattrstat res = {NFSERR_ROFS};
return &res;
}
nfsdiropres *
nfsproc_create_2_svc(nfscreateargs *argp, struct svc_req *rqstp)
{
static nfsdiropres res = {NFSERR_ROFS};
return &res;
}
nfsstat *
nfsproc_remove_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
{
static nfsstat res = {NFSERR_ROFS};
return &res;
}
nfsstat *
nfsproc_rename_2_svc(nfsrenameargs *argp, struct svc_req *rqstp)
{
static nfsstat res = {NFSERR_ROFS};
return &res;
}
nfsstat *
nfsproc_link_2_svc(nfslinkargs *argp, struct svc_req *rqstp)
{
static nfsstat res = {NFSERR_ROFS};
return &res;
}
nfsstat *
nfsproc_symlink_2_svc(nfssymlinkargs *argp, struct svc_req *rqstp)
{
static nfsstat res = {NFSERR_ROFS};
return &res;
}
nfsdiropres *
nfsproc_mkdir_2_svc(nfscreateargs *argp, struct svc_req *rqstp)
{
static nfsdiropres res = {NFSERR_ROFS};
return &res;
}
nfsstat *
nfsproc_rmdir_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
{
static nfsstat res = {NFSERR_ROFS};
return &res;
}
nfsreaddirres *
nfsproc_readdir_2_svc(nfsreaddirargs *argp, struct svc_req *rqstp)
{
static nfsreaddirres res;
static nfsentry slinkent = {SLINKID, 0, {SLINKCOOKIE}};
static nfsentry dotdotent = {ROOTID, "..", {DOTDOTCOOKIE}, &slinkent};
static nfsentry dotent = {ROOTID, ".", {DOTCOOKIE}, &dotdotent};
slinkent.ne_name = slinkname;
if (eq_fh(&argp->rda_fhandle, &slink)) {
res.rdr_status = NFSERR_NOTDIR;
} else if (eq_fh(&argp->rda_fhandle, &root)) {
gettimeofday((struct timeval *) &rootfattr.na_atime, (struct timezone *) 0);
res.rdr_status = NFS_OK;
switch (argp->rda_cookie[0]) {
case 0:
res.rdr_u.rdr_reply_u.dl_entries = &dotent;
break;
case DOTCOOKIE:
res.rdr_u.rdr_reply_u.dl_entries = &dotdotent;
break;
case DOTDOTCOOKIE:
res.rdr_u.rdr_reply_u.dl_entries = &slinkent;
break;
case SLINKCOOKIE:
res.rdr_u.rdr_reply_u.dl_entries = (nfsentry *) 0;
break;
}
res.rdr_u.rdr_reply_u.dl_eof = TRUE;
} else {
res.rdr_status = NFSERR_STALE;
}
return &res;
}
nfsstatfsres *
nfsproc_statfs_2_svc(am_nfs_fh *argp, struct svc_req *rqstp)
{
static nfsstatfsres res = {NFS_OK};
res.sfr_u.sfr_reply_u.sfrok_tsize = 1024;
res.sfr_u.sfr_reply_u.sfrok_bsize = 1024;
/* set to 1 if want non-empty automounts */
res.sfr_u.sfr_reply_u.sfrok_blocks = 0;
res.sfr_u.sfr_reply_u.sfrok_bfree = 0;
res.sfr_u.sfr_reply_u.sfrok_bavail = 0;
return &res;
}

View File

@ -0,0 +1,194 @@
/*
* am_compat.h:
*
* This file contains compatibility functions and macros, all of which
* should be auto-discovered, but for one reason or another (mostly
* brain-damage on the part of system designers and header files) they cannot.
*
* Each compatibility macro/function must include instructions on how/when
* it can be removed the am-utils code.
*
*/
#ifndef _AM_COMPAT_H
/*
* incomplete mount options definitions (sunos4, irix6, linux, etc.)
*/
/*
* Complete MNTTAB_OPT_* options based on MNT2_NFS_OPT_* mount options.
*/
#if defined(MNT2_NFS_OPT_ACDIRMAX) && !defined(MNTTAB_OPT_ACDIRMAX)
# define MNTTAB_OPT_ACDIRMAX "acdirmax"
#endif /* defined(MNT2_NFS_OPT_ACDIRMAX) && !defined(MNTTAB_OPT_ACDIRMAX) */
#if defined(MNT2_NFS_OPT_ACDIRMIN) && !defined(MNTTAB_OPT_ACDIRMIN)
# define MNTTAB_OPT_ACDIRMIN "acdirmin"
#endif /* defined(MNT2_NFS_OPT_ACDIRMIN) && !defined(MNTTAB_OPT_ACDIRMIN) */
#if defined(MNT2_NFS_OPT_ACREGMAX) && !defined(MNTTAB_OPT_ACREGMAX)
# define MNTTAB_OPT_ACREGMAX "acregmax"
#endif /* defined(MNT2_NFS_OPT_ACREGMAX) && !defined(MNTTAB_OPT_ACREGMAX) */
#if defined(MNT2_NFS_OPT_ACREGMIN) && !defined(MNTTAB_OPT_ACREGMIN)
# define MNTTAB_OPT_ACREGMIN "acregmin"
#endif /* defined(MNT2_NFS_OPT_ACREGMIN) && !defined(MNTTAB_OPT_ACREGMIN) */
#if !defined(MNTTAB_OPT_IGNORE)
/* SunOS 4.1.x and others define "noauto" option, but not "auto" */
# if defined(MNTTAB_OPT_NOAUTO) && !defined(MNTTAB_OPT_AUTO)
# define MNTTAB_OPT_AUTO "auto"
# endif /* defined(MNTTAB_OPT_NOAUTO) && !defined(MNTTAB_OPT_AUTO) */
#endif /* !defined(MNTTAB_OPT_IGNORE) */
#if defined(MNT2_NFS_OPT_NOAC) && !defined(MNTTAB_OPT_NOAC)
# define MNTTAB_OPT_NOAC "noac"
#endif /* defined(MNT2_NFS_OPT_NOAC) && !defined(MNTTAB_OPT_NOAC) */
#if defined(MNT2_NFS_OPT_OVERLAY) && !defined(MNTTAB_OPT_OVERLAY)
# define MNTTAB_OPT_OVERLAY "overlay"
#endif /* defined(MNT2_NFS_OPT_OVERLAY) && !defined(MNTTAB_OPT_OVERLAY) */
#if defined(MNT2_NFS_OPT_RETRANS) && !defined(MNTTAB_OPT_RETRANS)
# define MNTTAB_OPT_RETRANS "retrans"
#endif /* defined(MNT2_NFS_OPT_RETRANS) && !defined(MNTTAB_OPT_RETRANS) */
#if defined(MNT2_NFS_OPT_RSIZE) && !defined(MNTTAB_OPT_RSIZE)
# define MNTTAB_OPT_RSIZE "rsize"
#endif /* defined(MNT2_NFS_OPT_RSIZE) && !defined(MNTTAB_OPT_RSIZE) */
#if defined(MNT2_NFS_OPT_SOFT) && !defined(MNTTAB_OPT_SOFT)
# define MNTTAB_OPT_SOFT "soft"
#endif /* defined(MNT2_NFS_OPT_SOFT) && !defined(MNTTAB_OPT_SOFT) */
#if defined(MNT2_NFS_OPT_TIMEO) && !defined(MNTTAB_OPT_TIMEO)
# define MNTTAB_OPT_TIMEO "timeo"
#endif /* defined(MNT2_NFS_OPT_TIMEO) && !defined(MNTTAB_OPT_TIMEO) */
#if defined(MNT2_NFS_OPT_WSIZE) && !defined(MNTTAB_OPT_WSIZE)
# define MNTTAB_OPT_WSIZE "wsize"
#endif /* defined(MNT2_NFS_OPT_WSIZE) && !defined(MNTTAB_OPT_WSIZE) */
/*
* Complete MNTTAB_OPT_* options based on MNT2_GEN_OPT_* mount options.
*/
#if defined(MNT2_GEN_OPT_GRPID) && !defined(MNTTAB_OPT_GRPID)
# define MNTTAB_OPT_GRPID "grpid"
#endif /* defined(MNT2_GEN_OPT_GRPID) && !defined(MNTTAB_OPT_GRPID) */
#if defined(MNT2_GEN_OPT_NOSUID) && !defined(MNTTAB_OPT_NOSUID)
# define MNTTAB_OPT_NOSUID "nosuid"
#endif /* defined(MNT2_GEN_OPT_NOSUID) && !defined(MNTTAB_OPT_NOSUID) */
/*
* Complete MNTTAB_OPT_* options and their inverse based on MNT2_GEN_OPT_*
* options.
*/
#if defined(MNT2_GEN_OPT_NODEV) && !defined(MNTTAB_OPT_NODEV)
# define MNTTAB_OPT_NODEV "nodev"
/* this is missing under some versions of Linux */
# ifndef MNTTAB_OPT_DEV
# define MNTTAB_OPT_DEV "dev"
# endif /* not MNTTAB_OPT_DEV */
#endif /* defined(MNT2_GEN_OPT_NODEV) && !defined(MNTTAB_OPT_NODEV) */
#if defined(MNT2_GEN_OPT_NOEXEC) && !defined(MNTTAB_OPT_NOEXEC)
# define MNTTAB_OPT_NOEXEC "noexec"
/* this is missing under some versions of Linux */
# ifndef MNTTAB_OPT_EXEC
# define MNTTAB_OPT_EXEC "exec"
# endif /* not MNTTAB_OPT_EXEC */
#endif /* defined(MNT2_GEN_OPT_NOEXEC) && !defined(MNTTAB_OPT_NOEXEC) */
/*
* Add missing MNTTAB_OPT_* options.
*/
#ifndef MNTTAB_OPT_ACTIMEO
# define MNTTAB_OPT_ACTIMEO "actimeo"
#endif /* not MNTTAB_OPT_ACTIMEO */
#ifndef MNTTAB_OPT_INTR
# define MNTTAB_OPT_INTR "intr"
#endif /* not MNTTAB_OPT_INTR */
#ifndef MNTTAB_OPT_PORT
# define MNTTAB_OPT_PORT "port"
#endif /* not MNTTAB_OPT_PORT */
#ifndef MNTTAB_OPT_RETRANS
# define MNTTAB_OPT_RETRANS "retrans"
#endif /* not MNTTAB_OPT_RETRANS */
#ifndef MNTTAB_OPT_RETRY
# define MNTTAB_OPT_RETRY "retry"
#endif /* not MNTTAB_OPT_RETRY */
#ifndef MNTTAB_OPT_RO
# define MNTTAB_OPT_RO "ro"
#endif /* not MNTTAB_OPT_RO */
#ifndef MNTTAB_OPT_RSIZE
# define MNTTAB_OPT_RSIZE "rsize"
#endif /* not MNTTAB_OPT_RSIZE */
#ifndef MNTTAB_OPT_RW
# define MNTTAB_OPT_RW "rw"
#endif /* not MNTTAB_OPT_RW */
#ifndef MNTTAB_OPT_RO
# define MNTTAB_OPT_RO "ro"
#endif /* not MNTTAB_OPT_RO */
#ifndef MNTTAB_OPT_TIMEO
# define MNTTAB_OPT_TIMEO "timeo"
#endif /* not MNTTAB_OPT_TIMEO */
#ifndef MNTTAB_OPT_WSIZE
# define MNTTAB_OPT_WSIZE "wsize"
#endif /* not MNTTAB_OPT_WSIZE */
/*
* Incomplete filesystem definitions (sunos4, irix6)
*/
#if defined(HAVE_FS_CDFS) && defined(MOUNT_TYPE_CDFS) && !defined(MNTTYPE_CDFS)
# define MNTTYPE_CDFS "hsfs"
#endif /* defined(HAVE_FS_CDFS) && defined(MOUNT_TYPE_CDFS) && !defined(MNTTYPE_CDFS) */
#ifndef cdfs_args_t
/*
* Solaris has an HSFS filesystem, but does not define hsfs_args.
* XXX: the definition here for solaris is wrong, since under solaris,
* hsfs_args should be a single integer used as a bit-field for options.
* so this code has to be fixed later. -Erez.
*/
struct hsfs_args {
char *fspec; /* name of filesystem to mount */
int norrip;
};
# define cdfs_args_t struct hsfs_args
# define HAVE_FIELD_CDFS_ARGS_T_NORRIP
#endif /* not cdfs_args_t */
/*
* if does not define struct pc_args, assume integer bit-field (irix6)
*/
#if defined(HAVE_FS_PCFS) && !defined(pcfs_args_t)
# define pcfs_args_t u_int
#endif /* defined(HAVE_FS_PCFS) && !defined(pcfs_args_t) */
/*
* if does not define struct ufs_args, assume integer bit-field (linux)
*/
#if defined(HAVE_FS_UFS) && !defined(ufs_args_t)
# define ufs_args_t u_int
#endif /* defined(HAVE_FS_UFS) && !defined(ufs_args_t) */
#define _AM_COMPAT_H
#endif /* not _AM_COMPAT_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,877 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: am_utils.h,v 1.1.1.1 1997/07/24 21:20:14 christos Exp $
*
*/
/*
* Definitions that are specific to the am-utils package.
*/
#ifndef _AM_UTILS_H
#define _AM_UTILS_H
/**************************************************************************/
/*** MACROS ***/
/**************************************************************************/
/*
* General macros.
*/
#ifndef FALSE
# define FALSE 0
#endif /* not FALSE */
#ifndef TRUE
# define TRUE 1
#endif /* not TRUE */
#ifndef MAX
# define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif /* not MAX */
#ifndef MIN
# define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif /* not MIN */
#define ONE_HOUR (60 * 60) /* One hour in seconds */
#ifndef MAXHOSTNAMELEN
# ifdef HOSTNAMESZ
# define MAXHOSTNAMELEN HOSTNAMESZ
# else /* not HOSTNAMESZ */
# define MAXHOSTNAMELEN 64
# endif /* not HOSTNAMESZ */
#endif /* not MAXHOSTNAMELEN */
/*
* String comparison macros
*/
#define STREQ(s1, s2) (strcmp((s1), (s2)) == 0)
#define STREQ(s1, s2) (strcmp((s1), (s2)) == 0)
#define FSTREQ(s1, s2) ((*(s1) == *(s2)) && STREQ((s1),(s2)))
/*
* Logging options/flags
*/
#define XLOG_FATAL 0x0001
#define XLOG_ERROR 0x0002
#define XLOG_USER 0x0004
#define XLOG_WARNING 0x0008
#define XLOG_INFO 0x0010
#define XLOG_DEBUG 0x0020
#define XLOG_MAP 0x0040
#define XLOG_STATS 0x0080
#define XLOG_DEFSTR "all,nomap,nostats" /* Default log options */
#define XLOG_ALL (XLOG_FATAL|XLOG_ERROR|XLOG_USER|XLOG_WARNING|XLOG_INFO|XLOG_MAP|XLOG_STATS)
#define clocktime() (clock_valid ? clock_valid : time(&clock_valid))
#ifndef ROOT_MAP
# define ROOT_MAP "\"root\""
#endif /* not ROOT_MAP */
#define NO_SUBNET "notknown" /* default subnet name for no subnet */
#define NEXP_AP (1022) /* gdmr: was 254 */
#define NEXP_AP_MARGIN (128)
#define MAX_READDIR_ENTRIES 16
/*
* Linked list macros
*/
#define AM_FIRST(ty, q) ((ty *) ((q)->q_forw))
#define AM_LAST(ty, q) ((ty *) ((q)->q_back))
#define NEXT(ty, q) ((ty *) (((qelem *) q)->q_forw))
#define PREV(ty, q) ((ty *) (((qelem *) q)->q_back))
#define HEAD(ty, q) ((ty *) q)
#define ITER(v, ty, q) \
for ((v) = AM_FIRST(ty,(q)); (v) != HEAD(ty,(q)); (v) = NEXT(ty,(v)))
/* allocate anything of type ty */
#define ALLOC(ty) ((ty *) xmalloc(sizeof(ty)))
#define CALLOC(ty) ((ty *) xcalloc(1, sizeof(ty)))
/* converting am-filehandles to mount-points */
#define fh_to_mp2(fhp, rp) fh_to_mp3(fhp, rp, VLOOK_CREATE)
/*
* Systems which have the mount table in a file need to read it before
* they can perform an unmount() system call.
*/
#define UMOUNT_FS(dir) umount_fs(dir)
extern int umount_fs(char *fs_name); /* imported via $srcdir/conf/umount */
/*
* macros for automounter vfs/vnode operations.
*/
#define VLOOK_CREATE 0x1
#define VLOOK_DELETE 0x2
#define FS_DIRECTORY 0x0001 /* This looks like a dir, not a link */
#define FS_MBACKGROUND 0x0002 /* Should background this mount */
#define FS_NOTIMEOUT 0x0004 /* Don't bother with timeouts */
#define FS_MKMNT 0x0008 /* Need to make the mount point */
#define FS_UBACKGROUND 0x0010 /* Unmount in background */
#define FS_BACKGROUND (FS_MBACKGROUND|FS_UBACKGROUND)
#define FS_DISCARD 0x0020 /* Discard immediately on last reference */
#define FS_AMQINFO 0x0040 /* Amq is interested in this fs type */
/*
* macros for struct fserver.
*/
#define FSF_VALID 0x0001 /* Valid information available */
#define FSF_DOWN 0x0002 /* This fileserver is thought to be down */
#define FSF_ERROR 0x0004 /* Permanent error has occured */
#define FSF_WANT 0x0008 /* Want a wakeup call */
#define FSF_PINGING 0x0010 /* Already doing pings */
#define FSRV_ISDOWN(fs) (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_DOWN|FSF_VALID))
#define FSRV_ISUP(fs) (((fs)->fs_flags & (FSF_DOWN|FSF_VALID)) == (FSF_VALID))
/*
* macros for struct mntfs (list of mounted filesystems)
*/
#define MFF_MOUNTED 0x0001 /* Node is mounted */
#define MFF_MOUNTING 0x0002 /* Mount is in progress */
#define MFF_UNMOUNTING 0x0004 /* Unmount is in progress */
#define MFF_RESTART 0x0008 /* Restarted node */
#define MFF_MKMNT 0x0010 /* Delete this node's am_mount */
#define MFF_ERROR 0x0020 /* This node failed to mount */
#define MFF_LOGDOWN 0x0040 /* Logged that this mount is down */
#define MFF_RSTKEEP 0x0080 /* Don't timeout this filesystem - restarted */
#define MFF_WANTTIMO 0x0100 /* Need a timeout call when not busy */
/*
* macros for struct am_node (map of auto-mount points).
*/
#define AMF_NOTIMEOUT 0x0001 /* This node never times out */
#define AMF_ROOT 0x0002 /* This is a root node */
/*
* The following values can be tuned...
*/
#define ALLOWED_MOUNT_TIME 40 /* 40s for a mount */
#define AM_TTL (5 * 60) /* Default cache period */
#define AM_TTL_W (2 * 60) /* Default unmount interval */
#define AM_PINGER 30 /* NFS ping interval for live systems */
#define AFS_TIMEO 8 /* Default afs timeout - .8s */
/*
* default afs retrans - 1/10th seconds
*/
#define AFS_RETRANS ((ALLOWED_MOUNT_TIME*10+5*gopt.afs_timeo)/gopt.afs_timeo * 2)
/*
* RPC-related macros.
*/
#define RPC_XID_PORTMAP 0
#define RPC_XID_MOUNTD 1
#define RPC_XID_NFSPING 2
#define RPC_XID_MASK (0x0f) /* 16 id's for now */
#define MK_RPC_XID(type_id, uniq) ((type_id) | ((uniq) << 4))
/*
* What level of AMD are we backward compatible with?
* This only applies to externally visible characteristics.
* Rev.Minor.Branch.Patch (2 digits each)
*/
#define AMD_COMPAT 5000000 /* 5.0 */
/**************************************************************************/
/*** STRUCTURES AND TYPEDEFS ***/
/**************************************************************************/
/* some typedefs must come first */
typedef char *amq_string;
typedef struct mntfs mntfs;
typedef struct am_opts am_opts;
typedef struct am_ops am_ops;
typedef struct am_node am_node;
typedef struct _qelem qelem;
typedef struct mntlist mntlist;
typedef struct fserver fserver;
/*
* Linked list
* (the name 'struct qelem' conflicts with linux's unistd.h)
*/
struct _qelem {
qelem *q_forw;
qelem *q_back;
};
/*
* Option tables
*/
struct opt_tab {
char *opt;
int flag;
};
/*
* Server states
*/
typedef enum {
Start,
Run,
Finishing,
Quit,
Done
} serv_state;
/*
* Options
*/
struct am_opts {
char *fs_glob; /* Smashed copy of global options */
char *fs_local; /* Expanded copy of local options */
char *fs_mtab; /* Mount table entry */
/* Other options ... */
char *opt_dev;
char *opt_delay;
char *opt_dir;
char *opt_fs;
char *opt_group;
char *opt_mount;
char *opt_opts;
char *opt_remopts;
char *opt_pref;
char *opt_autopref;
char *opt_cache;
char *opt_rfs;
char *opt_rhost;
char *opt_sublink;
char *opt_type;
char *opt_unmount;
char *opt_user;
char *opt_maptype; /* map type: file, nis, hesiod, etc. */
};
/*
* List of mounted filesystems
*/
struct mntfs {
qelem mf_q; /* List of mounted filesystems */
am_ops *mf_ops; /* Operations on this mountpoint */
am_opts *mf_fo; /* File opts */
char *mf_mount; /* "/a/kiska/home/kiska" */
char *mf_info; /* Mount info */
char *mf_auto; /* Automount opts */
char *mf_mopts; /* FS mount opts */
char *mf_remopts; /* Remote FS mount opts */
fserver *mf_server; /* File server */
int mf_flags; /* Flags */
int mf_error; /* Error code from background mount */
int mf_refc; /* Number of references to this node */
int mf_cid; /* Callout id */
void (*mf_prfree) (); /* Free private space */
voidp mf_private; /* Private - per-fs data */
};
/*
* File Handle
*
* This is interpreted by indexing the exported array
* by fhh_id.
*
* The whole structure is mapped onto a standard fhandle_t
* when transmitted.
*/
struct am_fh {
int fhh_pid; /* process id */
int fhh_id; /* map id */
int fhh_gen; /* generation number */
};
/*
* Multi-protocol NFS file handle
*/
union am_nfs_handle {
/* placeholder for V4 file handle */
#ifdef HAVE_FS_NFS3
struct mountres3 v3; /* NFS version 3 handle */
#endif /* HAVE_FS_NFS3 */
struct fhstatus v2; /* NFS version 2 handle */
};
typedef union am_nfs_handle am_nfs_handle_t;
/*
* automounter vfs/vnode operations.
*/
typedef char *(*vfs_match) (am_opts *);
typedef int (*vfs_init) (mntfs *);
typedef int (*vmount_fs) (am_node *);
typedef int (*vfmount_fs) (mntfs *);
typedef int (*vumount_fs) (am_node *);
typedef int (*vfumount_fs) (mntfs *);
typedef am_node *(*vlookuppn) (am_node *, char *, int *, int);
typedef int (*vreaddir) (am_node *, nfscookie, nfsdirlist *, nfsentry *, int);
typedef am_node *(*vreadlink) (am_node *, int *);
typedef void (*vmounted) (mntfs *);
typedef void (*vumounted) (am_node *);
typedef fserver *(*vffserver) (mntfs *);
struct am_ops {
char *fs_type; /* type of filesystems "nfsx" */
vfs_match fs_match; /* fxn: match */
vfs_init fs_init; /* fxn: initialization */
vmount_fs mount_fs; /* fxn: mount vnode */
vfmount_fs fmount_fs; /* fxn: mount VFS */
vumount_fs umount_fs; /* fxn: unmount vnode */
vfumount_fs fumount_fs; /* fxn: unmount VFS */
vlookuppn lookuppn; /* fxn: lookup path-name */
vreaddir readdir; /* fxn: read directory */
vreadlink readlink; /* fxn: read link */
vmounted mounted; /* fxn: */
vumounted umounted; /* fxn: */
vffserver ffserver; /* fxn: find a file server */
int fs_flags; /* filesystem flags FS_* */
};
typedef int (*task_fun) (voidp);
typedef void (*cb_fun) (int, int, voidp);
typedef void (*fwd_fun) P((voidp, int, struct sockaddr_in *,
struct sockaddr_in *, voidp, int));
/*
* Am-utils' internal mount entry structure
* XXX: one day, nuke this thing. -Erez.
*/
struct _am_utils_mntent_dontuse {
char *mnt_fsname; /* name of mounted file system */
char *mnt_dir; /* file system path prefix */
char *mnt_type; /* MOUNT_TYPE_* */
char *mnt_opts; /* MNTTAB_OPT* */
int mnt_freq; /* dump frequency, in days */
int mnt_passno; /* pass number on parallel fsck */
#ifdef HAVE_FIELD_MNTENT_T_MNT_CNODE
int mnt_cnode; /* cluster node */
#endif /* HAVE_FIELD_MNTENT_T_MNT_CNODE */
#ifdef HAVE_FIELD_MNTENT_T_MNT_RO
int mnt_ro; /* read-only mount option */
#endif /* HAVE_FIELD_MNTENT_T_MNT_RO */
#ifdef HAVE_FIELD_MNTENT_T_MNT_TIME
# ifdef HAVE_FIELD_MNTENT_T_TIME_STRING
char *mnt_time; /* time filesystem was mounted */
# else /* not HAVE_FIELD_MNTENT_T_TIME_STRING */
long mnt_time; /* time filesystem was mounted */
# endif /* not HAVE_FIELD_MNTENT_T_TIME_STRING */
#endif /* HAVE_FIELD_MNTENT_T_MNT_TIME */
};
/*
* List of mount table entries
*/
struct mntlist {
struct mntlist *mnext;
mntent_t *mnt;
};
/*
* Mount map
*/
typedef struct mnt_map mnt_map;
/*
* Per-mountpoint statistics
*/
struct am_stats {
time_t s_mtime; /* Mount time */
u_short s_uid; /* Uid of mounter */
int s_getattr; /* Count of getattrs */
int s_lookup; /* Count of lookups */
int s_readdir; /* Count of readdirs */
int s_readlink; /* Count of readlinks */
int s_statfs; /* Count of statfs */
};
typedef struct am_stats am_stats;
/*
* System statistics
*/
struct amd_stats {
int d_drops; /* Dropped requests */
int d_stale; /* Stale NFS handles */
int d_mok; /* Succesful mounts */
int d_merr; /* Failed mounts */
int d_uerr; /* Failed unmounts */
};
extern struct amd_stats amd_stats;
/*
* List of fileservers
*/
struct fserver {
qelem fs_q; /* List of fileservers */
int fs_refc; /* Number of references to this node */
char *fs_host; /* Normalized hostname of server */
struct sockaddr_in *fs_ip; /* Network address of server */
int fs_cid; /* Callout id */
int fs_pinger; /* Ping (keepalive) interval */
int fs_flags; /* Flags */
char *fs_type; /* File server type */
u_long fs_version; /* NFS version of server (2, 3, etc.)*/
char *fs_proto; /* NFS protocol of server (tcp, udp, etc.) */
voidp fs_private; /* Private data */
void (*fs_prfree) (); /* Free private data */
};
/*
* Map of auto-mount points.
*/
struct am_node {
int am_mapno; /* Map number */
mntfs *am_mnt; /* Mounted filesystem */
char *am_name; /* "kiska" Name of this node */
char *am_path; /* "/home/kiska" Path of this node's mount */
/* point */
char *am_link; /* "/a/kiska/home/kiska/this/that" Link to */
/* sub-directory */
am_node *am_parent; /* Parent of this node */
am_node *am_ysib; /* Younger sibling of this node */
am_node *am_osib; /* Older sibling of this node */
am_node *am_child; /* First child of this node */
nfsattrstat am_attr; /* File attributes */
#define am_fattr am_attr.ns_u.ns_attr_u
int am_flags; /* Boolean flags */
int am_error; /* Specific mount error */
time_t am_ttl; /* Time to live */
int am_timeo_w; /* Wait interval */
int am_timeo; /* Timeout interval */
u_int am_gen; /* Generation number */
char *am_pref; /* Mount info prefix */
am_stats am_stats; /* Statistics gathering */
SVCXPRT *am_transp; /* Info for quick reply */
};
/**************************************************************************/
/*** EXTERNALS ***/
/**************************************************************************/
/*
* Useful constants
*/
extern char *mtab; /* Mount table */
extern char *cpu; /* "CPU type" */
extern char *endian; /* "big" */
extern char *hostdomain; /* "southseas.nz" */
extern char copyright[]; /* Copyright info */
extern char hostd[]; /* "kiska.southseas.nz" */
extern char pid_fsname[]; /* kiska.southseas.nz:(pid%d) */
extern char version[]; /* Version info */
/*
* Global variables.
*/
extern AUTH *nfs_auth; /* Dummy uthorisation for remote servers */
extern FILE *logfp; /* Log file */
extern am_node **exported_ap; /* List of nodes */
extern am_node *root_node; /* Node for "root" */
extern char *PrimNetName; /* Name of primary connected network */
extern char *PrimNetNum; /* Name of primary connected network */
extern char *SubsNetName; /* Name of subsidiary connected network */
extern char *SubsNetNum; /* Name of subsidiary connected network */
extern char *progname; /* "amd"|"mmd" */
extern char hostname[]; /* "kiska" */
extern int first_free_map; /* First free node */
extern int foreground; /* Foreground process */
extern int immediate_abort; /* Should close-down unmounts be retried */
extern int last_used_map; /* Last map being used for mounts */
extern int orig_umask; /* umask() on startup */
extern int task_notify_todo; /* Task notifier needs running */
extern int xlog_level; /* Logging level */
extern int xlog_level_init;
extern pid_t mypid; /* Current process id */
extern serv_state amd_state; /* Should we go now */
extern struct in_addr myipaddr; /* (An) IP address of this host */
extern struct opt_tab xlog_opt[];
extern time_t clock_valid; /* Clock needs recalculating */
extern time_t do_mapc_reload; /* Flush & reload mount map cache */
extern time_t next_softclock; /* Time to call softclock() */
extern u_short nfs_port; /* Our NFS service port */
/*
* Global routines
*/
extern CLIENT *get_mount_client(char *unused_host, struct sockaddr_in *sin, struct timeval *tv, int *sock, u_long mnt_version);
extern RETSIGTYPE sigchld(int);
extern SVCXPRT *nfsxprt;
extern am_node *efs_lookuppn(am_node *, char *, int *, int);
extern am_node *exported_ap_alloc(void);
extern am_node *fh_to_mp(am_nfs_fh *);
extern am_node *fh_to_mp3(am_nfs_fh *, int *, int);
extern am_node *find_ap(char *);
extern am_node *find_mf(mntfs *);
extern am_node *next_map(int *);
extern am_node *root_ap(char *, int);
extern am_ops *ops_match(am_opts *, char *, char *, char *, char *, char *);
extern bool_t xdr_amq_string(XDR *xdrs, amq_string *objp);
extern bool_t xdr_dirpath(XDR *xdrs, dirpath *objp);
extern char **strsplit(char *, int, int);
extern char *expand_key(char *);
extern char *get_version_string(void);
extern char *inet_dquad(char *, u_long);
extern char *str3cat(char *, char *, char *, char *);
extern char *strealloc(char *, char *);
extern char *strip_selectors(char *, char *);
extern char *strnsave(const char *, int);
extern fserver *dup_srvr(fserver *);
extern int amu_close(int fd);
extern int auto_fmount(am_node *mp);
extern int auto_fumount(am_node *mp);
extern int background(void);
extern int bind_resv_port(int, u_short *);
extern int cmdoption(char *, struct opt_tab *, int *);
extern int compute_mount_flags(mntent_t *);
extern int efs_readdir(am_node *, nfscookie, nfsdirlist *, nfsentry *, int);
extern int eval_fs_opts(am_opts *, char *, char *, char *, char *, char *);
extern int fwd_init(void);
extern int fwd_packet(int, voidp, int, struct sockaddr_in *, struct sockaddr_in *, voidp, fwd_fun);
extern int hasmntval(mntent_t *, char *);
extern int islocalnet(u_long);
extern int make_nfs_auth(void);
extern int make_rpc_packet(char *, int, u_long, struct rpc_msg *, voidp, XDRPROC_T_TYPE, AUTH *);
extern int mapc_keyiter(mnt_map *, void(*)(char *, voidp), voidp);
extern int mapc_search(mnt_map *, char *, char **);
extern int mkdirs(char *, int);
extern int mount_auto_node(char *, voidp);
extern int mount_automounter(int);
extern int mount_exported(void);
extern int mount_fs(mntent_t *, int, caddr_t, int, MTYPE_TYPE, u_long, const char *);
extern int mount_node(am_node *);
extern int nfs_srvr_port(fserver *, u_short *, voidp);
extern int pickup_rpc_reply(voidp, int, voidp, XDRPROC_T_TYPE);
extern int root_keyiter(void(*)(char *, voidp), voidp);
extern int softclock(void);
extern int switch_option(char *);
extern int switch_to_logfile(char *);
extern int timeout(u_int, void(*fn)(), voidp);
extern int umount_fs(char *);
extern int valid_key(char *);
extern mnt_map *mapc_find(char *, char *, const char *);
extern mntfs *dup_mntfs(mntfs *);
extern mntfs *find_mntfs(am_ops *, am_opts *, char *, char *, char *, char *, char *);
extern mntfs *new_mntfs(void);
extern mntfs *realloc_mntfs(mntfs *, am_ops *, am_opts *, char *, char *, char *, char *, char *);
extern mntlist *read_mtab(char *);
extern struct sockaddr_in *amu_svc_getcaller(SVCXPRT *xprt);
extern time_t time(time_t *);
extern void am_mounted(am_node *);
extern void am_unmounted(am_node *);
extern void amq_program_1(struct svc_req *rqstp, SVCXPRT * transp);
extern void amu_get_myaddress(struct in_addr *iap);
extern void deslashify(char *);
extern void discard_mntlist(mntlist *mp);
extern void do_task_notify(void);
extern void flush_mntfs(void);
extern void flush_nfs_fhandle_cache(fserver *);
extern void forcibly_timeout_mp(am_node *);
extern void free_map(am_node *);
extern void free_mntfs(mntfs *);
extern void free_mntlist(mntlist *);
extern void free_opts(am_opts *);
extern void free_srvr(fserver *);
extern void fwd_reply(void);
extern void get_args(int, char *[]);
extern void getwire(char **, char **, char **, char **);
extern void going_down(int);
extern void host_normalize(char **);
extern void init_map(am_node *, char *);
extern void ins_que(qelem *, qelem *);
extern void insert_am(am_node *, am_node *);
extern void make_root_node(void);
extern void map_flush_srvr(fserver *);
extern void mapc_add_kv(mnt_map *, char *, char *);
extern void mapc_free(mnt_map *);
extern void mapc_reload(void);
extern void mapc_showtypes(char *buf);
extern void mk_fattr(am_node *, nfsftype);
extern void mnt_free(mntent_t *);
extern void mp_to_fh(am_node *, am_nfs_fh *);
extern void new_ttl(am_node *);
extern void nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp);
extern void normalize_slash(char *);
extern void ops_showamfstypes(char *buf);
extern void ops_showfstypes(char *outbuf);
extern void plog(int, char *,...);
extern void rem_que(qelem *);
extern void reschedule_timeout_mp(void);
extern void restart(void);
extern void rmdirs(char *);
extern void rpc_msg_init(struct rpc_msg *, u_long, u_long, u_long);
extern void run_task(task_fun, voidp, cb_fun, voidp);
extern void sched_task(cb_fun, voidp, voidp);
extern void show_opts(int ch, struct opt_tab *);
extern void show_rcs_info(const char *, char *);
extern void srvrlog(fserver *, char *);
extern void timeout_mp(void);
extern void umount_exported(void);
extern void unregister_amq(void);
extern void untimeout(int);
extern void wakeup(voidp);
extern void wakeup_srvr(fserver *);
extern void wakeup_task(int, int, voidp);
extern void write_mntent(mntent_t *);
extern voidp xmalloc(int);
extern voidp xrealloc(voidp, int);
extern u_long get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const char *proto);
#ifdef MOUNT_TABLE_ON_FILE
extern void rewrite_mtab(mntlist *);
extern void unlock_mntlist(void);
#endif /* MOUNT_TABLE_ON_FILE */
#if defined(HAVE_SYSLOG_H) || defined(HAVE_SYS_SYSLOG_H)
extern int syslogging;
#endif /* defined(HAVE_SYSLOG_H) || defined(HAVE_SYS_SYSLOG_H) */
#ifdef HAVE_TRANSPORT_TYPE_TLI
extern int create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, struct netconfig **udp_amqncpp, int *tcp_soAMQp, SVCXPRT **tcp_amqpp, struct netconfig **tcp_amqncpp);
extern int create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp));
extern int get_knetconfig(struct knetconfig **kncpp, struct netconfig *in_ncp, char *nc_protoname);
extern struct netconfig *nfsncp;
extern void free_knetconfig(struct knetconfig *kncp);
#else /* not HAVE_TRANSPORT_TYPE_TLI */
extern int create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, int *tcp_soAMQp, SVCXPRT **tcp_amqpp);
extern int create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp));
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
#ifndef HAVE_FIELD_STRUCT_FHSTATUS_FHS_FH
# define fhs_fh fhstatus_u.fhs_fhandle
#endif /* not HAVE_FIELD_STRUCT_FHSTATUS_FHS_FH */
/**************************************************************************/
/*** Generic file-system types, implemented as part of the native O/S. ***/
/**************************************************************************/
/*
* Loopback File System
* Many systems can't support this, and in any case most of the
* functionality is available with Symlink FS.
*/
#ifdef HAVE_FS_LOFS
extern am_ops lofs_ops;
#endif /* HAVE_FS_LOFS */
/*
* CD-ROM File System (CD-ROM)
* (HSFS: High Sierra F/S on some machines)
* Many systems can't support this, and in any case most of the
* functionality is available with program FS.
*/
#ifdef HAVE_FS_CDFS
extern am_ops cdfs_ops;
#endif /* HAVE_FS_CDFS */
/*
* PC File System (MS-DOS)
* Many systems can't support this, and in any case most of the
* functionality is available with program FS.
*/
#ifdef HAVE_FS_PCFS
extern am_ops pcfs_ops;
#endif /* HAVE_FS_PCFS */
/*
* Network File System
* Good, slow, NFS V.2.
*/
#ifdef HAVE_FS_NFS
extern am_ops nfs_ops; /* NFS */
extern qelem nfs_srvr_list;
extern fserver *find_nfs_srvr (mntfs *);
#endif /* HAVE_FS_NFS */
/*
* Network File System: the new generation
* NFS V.3
*/
#ifdef HAVE_FS_NFS3
# ifndef NFS_VERSION3
# define NFS_VERSION3 ((u_int) 3)
# endif /* not NFS_VERSION3 */
#endif /* HAVE_FS_NFS3 */
/*
* Un*x File System
* Normal local disk file system.
*/
#ifdef HAVE_FS_UFS
extern am_ops ufs_ops; /* Un*x file system */
#endif /* HAVE_FS_UFS */
/**************************************************************************/
/*** Automounter file-system types, implemented by amd. ***/
/**************************************************************************/
/*
* Automount File System
*/
#ifdef HAVE_AM_FS_AFS
extern am_ops afs_ops; /* Automount file system (this!) */
extern am_ops toplvl_ops; /* Top-level automount file system */
extern am_ops root_ops; /* Root file system */
extern qelem afs_srvr_list;
extern fserver *find_afs_srvr (mntfs *);
#endif /* HAVE_AM_FS_AFS */
/*
* Direct Automount File System
*/
#ifdef HAVE_AM_FS_DFS
extern am_ops dfs_ops; /* Direct Automount file system (this too) */
#endif /* HAVE_AM_FS_DFS */
/*
* Error File System
*/
#ifdef HAVE_AM_FS_EFS
extern am_ops efs_ops; /* Error file system */
#endif /* HAVE_AM_FS_EFS */
/*
* Inheritance File System
*/
#ifdef HAVE_AM_FS_IFS
extern am_ops ifs_ops; /* Inheritance file system */
#endif /* HAVE_AM_FS_IFS */
/*
* Multi-nfs mounts.
*/
#ifdef HAVE_AM_FS_NFSX
extern am_ops nfsx_ops; /* NFS X */
#endif /* HAVE_AM_FS_NFSX */
/*
* NFS host - a whole tree.
*/
#ifdef HAVE_AM_FS_HOST
extern am_ops host_ops; /* NFS host */
#endif /* HAVE_AM_FS_HOST */
/*
* Program File System
* This is useful for things like RVD.
*/
#ifdef HAVE_AM_FS_PFS
extern am_ops pfs_ops; /* PFS */
#endif /* HAVE_AM_FS_PFS */
/*
* Symbolic-link file system.
* A "filesystem" which is just a symbol link.
*/
#ifdef HAVE_AM_FS_SFS
extern am_ops sfs_ops; /* Symlink FS */
#endif /* HAVE_AM_FS_SFS */
/*
* Symbolic-link file syste, which also checks that the target of
* the symlink exists.
* A "filesystem" which is just a symbol link.
*/
#ifdef HAVE_AM_FS_SFSX
extern am_ops sfsx_ops; /* Symlink FS with existence check */
#endif /* HAVE_AM_FS_SFSX */
/*
* Union file system
*/
#ifdef HAVE_AM_FS_UNION
extern am_ops union_ops; /* Union FS */
#endif /* HAVE_AM_FS_UNION */
/**************************************************************************/
/*** DEBUGGING ***/
/**************************************************************************/
/*
* DEBUGGING:
*/
#ifdef DEBUG
# define D_ALL (~0)
# define D_DAEMON 0x0001 /* Enter daemon mode */
# define D_TRACE 0x0002 /* Do protocol trace */
# define D_FULL 0x0004 /* Do full trace */
# define D_MTAB 0x0008 /* Use local mtab */
# define D_AMQ 0x0010 /* Register amq program */
# define D_STR 0x0020 /* Debug string munging */
# ifdef DEBUG_MEM
# define D_MEM 0x0040 /* Trace memory allocations */
# endif /* DEBUG_MEM */
# define D_FORK 0x0080 /* Fork server */
/*
* Normally, don't enter daemon mode, and don't register amq
*/
# ifdef DEBUG_MEM
# define D_TEST (~(D_DAEMON|D_MEM|D_STR))
# else /* not DEBUG_MEM */
# define D_TEST (~(D_DAEMON|D_STR))
# endif /* not DEBUG_MEM */
# define amuDebug(x) if (!(debug_flags & (x))) ; else
# define dlog amuDebug(D_FULL) dplog
# define amuDebugNo(x) if (debug_flags & (x)) ; else
/* debugging mount-table file to use */
# ifndef DEBUG_MNTTAB
# define DEBUG_MNTTAB "./mnttab"
# endif /* not DEBUG_MNTTAB */
# ifdef DEBUG_MEM
# define free(x) xfree(__FILE__,__LINE__,x)
# endif /* DEBUG_MEM */
#endif /* DEBUG */
extern int debug_flags; /* Debug options */
extern int debug_option (char *);
extern struct opt_tab dbg_opt[];
extern void dplog(char *fmt, ...);
/**************************************************************************/
/*** MISC (stuff left to autoconfiscate) ***/
/**************************************************************************/
#endif /* not _AM_UTILS_H */

222
usr.sbin/amd/include/amd.h Normal file
View File

@ -0,0 +1,222 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amd.h,v 1.1.1.1 1997/07/24 21:20:15 christos Exp $
*
*/
#ifndef _AMD_H
#define _AMD_H
/*
* MACROS:
*/
/* options for amd.conf */
#define CFM_BROWSABLE_DIRS 0x0001
#define CFM_MOUNT_TYPE_AUTOFS 0x0002
#define CFM_ENABLE_DEFAULT_SELECTORS 0x0004
#define CFM_NORMALIZE_HOSTNAMES 0x0008
#define CFM_NOSWAP 0x0010
#define CFM_PRINT_PID 0x0020
#define CFM_RESTART_EXISTING_MOUNTS 0x0040
/* some systems (SunOS 4.x) neglect to define the mount null message */
#ifndef MOUNTPROC_NULL
# define MOUNTPROC_NULL ((u_long)(0))
#endif /* not MOUNTPROC_NULL */
/* Hash table size */
#define NKVHASH (1 << 2) /* Power of two */
/*
* TYPEDEFS:
*/
typedef struct cf_map cf_map_t;
typedef struct kv kv;
/*
* Cache map operations
*/
typedef void add_fn(mnt_map *, char *, char *);
typedef int init_fn(mnt_map *, char *, time_t *);
typedef int mtime_fn(mnt_map *, char *, time_t *);
typedef int reload_fn(mnt_map *, char *, add_fn *);
typedef int search_fn(mnt_map *, char *, char *, char **, time_t *);
/*
* STRUCTURES:
*/
/* global amd options that are manipulated by conf.c */
struct amu_global_options {
char *arch; /* name of current architecture */
char *auto_dir; /* automounter temp dir */
char *cluster; /* cluster name */
char *karch; /* kernel architecture */
char *logfile; /* amd log file */
char *op_sys; /* operating system name */
char *op_sys_ver; /* OS version */
char *sub_domain; /* local domain */
char *map_options; /* global map options */
char *map_type; /* global map type */
char *search_path; /* search path for maps */
char *mount_type; /* mount type for map */
u_int flags; /* various CFM_* flags */
int afs_retrans; /* NFS retransmit counter */
int afs_timeo; /* NFS retry interval */
int am_timeo; /* cache duration */
int am_timeo_w; /* dismount interval */
#ifdef HAVE_MAP_LDAP
char *ldap_base; /* LDAP base */
char *ldap_hostports; /* LDAP host ports */
#endif /* HAVE_MAP_LDAP */
#ifdef HAVE_MAP_NIS
char *nis_domain; /* YP domain name */
#endif /* HAVE_MAP_NIS */
};
struct cf_map {
char *cfm_dir; /* /home, /u, /src */
char *cfm_name; /* amd.home, /etc/amd.home ... */
char *cfm_type; /* file, hesiod, ndbm, nis ... */
char *cfm_opts; /* -cache:=all, etc. */
char *cfm_search_path; /* /etc/local:/etc/amdmaps:/misc/yp */
char *cfm_tag; /* optional map tag for amd -T */
u_int cfm_flags; /* browsable_dirs? mount_type? */
};
/*
* Key-value pair
*/
struct kv {
kv *next;
char *key;
#ifdef HAVE_REGEXEC
regex_t re; /* store the regexp from regcomp() */
#endif /* HAVE_REGEXEC */
char *val;
};
struct mnt_map {
qelem hdr;
int refc; /* Reference count */
short flags; /* Allocation flags */
short alloc; /* Allocation mode */
time_t modify; /* Modify time of map */
char *map_name; /* Name of this map */
char *wildcard; /* Wildcard value */
reload_fn *reload; /* Function to be used for reloads */
search_fn *search; /* Function to be used for searching */
mtime_fn *mtime; /* Modify time function */
kv *kvhash[NKVHASH]; /* Cached data */
/* options available via amd conf file */
char *cf_map_type; /* file, hesiod, ndbm, nis, etc. */
char *cf_search_path; /* /etc/local:/etc/amdmaps:/misc/yp */
u_int cf_flags; /* browsable_dirs? mount_type? */
void *map_data; /* Map data black box */
};
/*
* EXTERNALS:
*/
/* amd global functions */
extern amq_mount_info_list *amqproc_getmntfs_1_svc(voidp argp, struct svc_req *rqstp);
extern amq_mount_stats *amqproc_stats_1_svc(voidp argp, struct svc_req *rqstp);
extern amq_mount_tree_list *amqproc_export_1_svc(voidp argp, struct svc_req *rqstp);
extern amq_mount_tree_p *amqproc_mnttree_1_svc(voidp argp, struct svc_req *rqstp);
extern amq_string *amqproc_getvers_1_svc(voidp argp, struct svc_req *rqstp);
extern int *amqproc_mount_1_svc(voidp argp, struct svc_req *rqstp);
extern int *amqproc_setopt_1_svc(voidp argp, struct svc_req *rqstp);
extern voidp amqproc_null_1_svc(voidp argp, struct svc_req *rqstp);
extern voidp amqproc_umnt_1_svc(voidp argp, struct svc_req *rqstp);
extern SVCXPRT *nfs_program_2_transp; /* For quick_reply() */
extern am_nfs_fh *root_fh(char *dir);
extern bool_t xdr_amq_mount_info_qelem(XDR *xdrs, qelem *qhead);
extern fserver *find_nfs_srvr(mntfs *mf);
extern int mount_nfs_fh(am_nfs_handle_t *fhp, char *dir, char *fs_name, char *opts, mntfs *mf);
extern int process_last_regular_map(void);
extern int set_conf_kv(const char *section, const char *k, const char *v);
extern nfsentry *make_entry_chain(am_node *mp, const nfsentry *current_chain);
extern void flush_srvr_nfs_cache(void);
extern void mf_mounted(mntfs *mf);
extern void quick_reply(am_node *mp, int error);
/* amd global variables */
extern struct amu_global_options gopt; /* where global options are stored */
extern FILE *yyin;
extern am_ops cdfs_ops;
extern am_ops lofs_ops;
extern am_ops nfs_ops;
extern am_ops pcfs_ops;
extern am_ops ufs_ops;
extern char *conf_tag;
extern int NumChild;
extern int fwd_sock;
extern int select_intr_valid;
extern int usage;
extern int use_conf_file; /* use amd configuration file */
extern int yyparse (void);
extern jmp_buf select_intr;
extern qelem mfhead;
extern void root_newmap(const char *, const char *, const char *, const cf_map_t *);
#ifdef HAVE_SIGACTION
extern sigset_t masked_sigs;
#endif /* HAVE_SIGACTION */
#if defined(HAVE_AM_FS_SFS) || defined(HAVE_AM_FS_SFSX)
extern char * sfs_match(am_opts *fo);
extern int sfs_fumount(mntfs *mf);
#endif /* defined(HAVE_AM_FS_SFS) || defined(HAVE_AM_FS_SFSX) */
#if defined(HAVE_FS_NFS3) && !defined(HAVE_XDR_MOUNTRES3)
extern bool_t xdr_mountres3(XDR *xdrs, mountres3 *objp);
#endif /* defined(HAVE_FS_NFS3) && !defined(HAVE_XDR_MOUNTRES3) */
#endif /* not _AMD_H */

View File

@ -0,0 +1,156 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amq_defs.h,v 1.1.1.1 1997/07/24 21:20:15 christos Exp $
*
*/
#ifndef _AMQ_DEFS_H
#define _AMQ_DEFS_H
/*
* MACROS
*/
#ifndef AMQ_SIZE
# define AMQ_SIZE 16384
#endif /* not AMQ_SIZE */
#define AMQ_STRLEN 1024
#define AMQ_PROGRAM ((u_long)300019)
#define AMQ_VERSION ((u_long)1)
#define AMQPROC_NULL ((u_long)0)
#define AMQPROC_MNTTREE ((u_long)1)
#define AMQPROC_UMNT ((u_long)2)
#define AMQPROC_STATS ((u_long)3)
#define AMQPROC_EXPORT ((u_long)4)
#define AMQPROC_SETOPT ((u_long)5)
#define AMQPROC_GETMNTFS ((u_long)6)
#define AMQPROC_MOUNT ((u_long)7)
#define AMQPROC_GETVERS ((u_long)8)
/*
* TYPEDEFS
*/
typedef long *time_type;
typedef struct amq_mount_info amq_mount_info;
typedef struct amq_mount_stats amq_mount_stats;
typedef struct amq_mount_tree amq_mount_tree;
typedef struct amq_setopt amq_setopt;
typedef amq_mount_tree *amq_mount_tree_p;
/*
* STRUCTURES:
*/
struct amq_mount_tree {
amq_string mt_mountinfo;
amq_string mt_directory;
amq_string mt_mountpoint;
amq_string mt_type;
time_type mt_mounttime;
u_short mt_mountuid;
int mt_getattr;
int mt_lookup;
int mt_readdir;
int mt_readlink;
int mt_statfs;
struct amq_mount_tree *mt_next;
struct amq_mount_tree *mt_child;
};
struct amq_mount_info {
amq_string mi_type;
amq_string mi_mountpt;
amq_string mi_mountinfo;
amq_string mi_fserver;
int mi_error;
int mi_refc;
int mi_up;
};
typedef struct {
u_int amq_mount_info_list_len;
amq_mount_info *amq_mount_info_list_val;
} amq_mount_info_list;
typedef struct {
u_int amq_mount_tree_list_len;
amq_mount_tree_p *amq_mount_tree_list_val;
} amq_mount_tree_list;
struct amq_mount_stats {
int as_drops;
int as_stale;
int as_mok;
int as_merr;
int as_uerr;
};
enum amq_opt {
AMOPT_DEBUG = 0,
AMOPT_LOGFILE = 1,
AMOPT_XLOG = 2,
AMOPT_FLUSHMAPC = 3
};
typedef enum amq_opt amq_opt; /* enum typedefs should be after enum */
struct amq_setopt {
amq_opt as_opt;
amq_string as_str;
};
/*
* EXTERNALS:
*
* external definitions for amqproc_*_1() have been moved off to private
* headers in lib/amu.h, amd/amd.h, etc. They have to be private since the
* same named functions appear in different places with different prototypes
* an functionality.
*/
extern bool_t xdr_amq_mount_info(XDR *xdrs, amq_mount_info *objp);
extern bool_t xdr_amq_mount_info_list(XDR *xdrs, amq_mount_info_list *objp);
extern bool_t xdr_amq_mount_stats(XDR *xdrs, amq_mount_stats *objp);
extern bool_t xdr_amq_mount_tree(XDR *xdrs, amq_mount_tree *objp);
extern bool_t xdr_amq_mount_tree_list(XDR *xdrs, amq_mount_tree_list *objp);
extern bool_t xdr_amq_mount_tree_p(XDR *xdrs, amq_mount_tree_p *objp);
extern bool_t xdr_amq_opt(XDR *xdrs, amq_opt *objp);
extern bool_t xdr_amq_setopt(XDR *xdrs, amq_setopt *objp);
extern bool_t xdr_pri_free(XDRPROC_T_TYPE xdr_args, caddr_t args_ptr);
extern bool_t xdr_time_type(XDR *xdrs, time_type *objp);
#endif /* not _AMQ_DEFS_H */

View File

@ -0,0 +1,211 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amu_nfs_prot.h,v 1.1.1.1 1997/07/24 21:20:15 christos Exp $
*
*/
#ifndef _AMU_NFS_PROT_H
#define _AMU_NFS_PROT_H
#ifdef HAVE_RPCSVC_NFS_PROT_H
# include <rpcsvc/nfs_prot.h>
#endif /* HAVE_RPCSVC_NFS_PROT_H */
#ifdef HAVE_NFS_RPCV2_H
# include <nfs/rpcv2.h>
#endif /* HAVE_NFS_RPCV2_H */
#ifndef NFS_NPROCS
# define NFS_NPROCS 26
#endif /* not NFS_NPROCS */
#ifdef HAVE_NFS_NFS_H
# include <nfs/nfs.h>
#endif /* HAVE_NFS_NFS_H */
/*
* MACROS:
*/
#define dr_drok_u diropres
#define ca_where where
#define da_fhandle dir
#define da_name name
#define dl_entries entries
#define dl_eof eof
#define dr_status status
#define dr_u diropres_u
#define drok_attributes attributes
#define drok_fhandle file
#define fh_data data
#define la_fhandle from
#define la_to to
#define na_atime atime
#define na_ctime ctime
#define na_fileid fileid
#define na_fsid fsid
#define na_mode mode
#define na_mtime mtime
#define na_nlink nlink
#define na_size size
#define na_type type
#define ne_cookie cookie
#define ne_fileid fileid
#define ne_name name
#define ne_nextentry nextentry
#define ns_attr_u attributes
#define ns_status status
#define ns_u attrstat_u
#define nt_seconds seconds
#define nt_useconds useconds
#define rda_cookie cookie
#define rda_count count
#define rda_fhandle dir
#define rdr_reply_u reply
#define rdr_status status
#define rdr_u readdirres_u
#define rlr_data_u data
#define rlr_status status
#define rlr_u readlinkres_u
#define rna_from from
#define rna_to to
#define rr_status status
#define sag_fhandle file
#define sfr_reply_u reply
#define sfr_status status
#define sfr_u statfsres_u
#define sfrok_bavail bavail
#define sfrok_bfree bfree
#define sfrok_blocks blocks
#define sfrok_bsize bsize
#define sfrok_tsize tsize
#define sla_from from
#define wra_fhandle file
/*
* TYPEDEFS:
*/
typedef attrstat nfsattrstat;
typedef createargs nfscreateargs;
typedef dirlist nfsdirlist;
typedef diropargs nfsdiropargs;
typedef diropres nfsdiropres;
typedef entry nfsentry;
typedef fattr nfsfattr;
typedef ftype nfsftype;
typedef linkargs nfslinkargs;
typedef readargs nfsreadargs;
typedef readdirargs nfsreaddirargs;
typedef readdirres nfsreaddirres;
typedef readlinkres nfsreadlinkres;
typedef readres nfsreadres;
typedef renameargs nfsrenameargs;
typedef sattrargs nfssattrargs;
typedef statfsokres nfsstatfsokres;
typedef statfsres nfsstatfsres;
typedef symlinkargs nfssymlinkargs;
typedef writeargs nfswriteargs;
/*
*
* NetBSD 1.2 has NFS V3, but it is undefined in the header files.
* so I define everything that's neede for NFS V3 here.
*/
#ifdef NFSMNT_NFSV3
# define MOUNT_NFS3 MOUNT_NFS
# define MNTOPT_NFS3 "nfs"
#define FHSIZE3 64 /* size in bytes of a file handle (v3) */
#define NFS3_FHSIZE 64
#define MOUNTVERS3 ((unsigned long)(3))
#define NFS_V3 ((unsigned long)(3))
typedef struct {
u_int fhandle3_len;
char *fhandle3_val;
} fhandle3;
enum mountstat3 {
MNT3_OK = 0,
MNT3ERR_PERM = 1,
MNT3ERR_NOENT = 2,
MNT3ERR_IO = 5,
MNT3ERR_ACCES = 13,
MNT3ERR_NOTDIR = 20,
MNT3ERR_INVAL = 22,
MNT3ERR_NAMETOOLONG = 63,
MNT3ERR_NOTSUPP = 10004,
MNT3ERR_SERVERFAULT = 10006
};
typedef enum mountstat3 mountstat3;
struct mountres3_ok {
fhandle3 fhandle;
struct {
u_int auth_flavors_len;
int *auth_flavors_val;
} auth_flavors;
};
typedef struct mountres3_ok mountres3_ok;
struct mountres3 {
mountstat3 fhs_status;
union {
mountres3_ok mountinfo;
} mountres3_u;
};
typedef struct mountres3 mountres3;
struct nfs_fh3 {
u_int fh3_length;
union nfs_fh3_u {
struct nfs_fh3_i {
fhandle_t fh3_i;
} nfs_fh3_i;
char data[NFS3_FHSIZE];
} fh3_u;
};
typedef struct nfs_fh3 nfs_fh3;
#endif /* NFSMNT_NFSV3 */
#endif /* not _AMU_NFS_PROT_H */

View File

@ -0,0 +1,69 @@
/*
* aux_conf.h:
* This file gets "filled in" for each architecture.
* Generated automatically from aux_conf.h.in by configure.
*/
#ifndef _AUX_CONF_H
#define _AUX_CONF_H
/*
* The next line is a literal inclusion of a file which includes a
* definition for the MOUNT_TRAP macro for a particular architecture.
* If it defines the wrong entry, check the AC_CHECK_MOUNT_TRAP m4 macro
* in $srcdir/aux/macros.
*/
/* $srcdir/conf/trap/trap_default.h */
#define MOUNT_TRAP(type, mnt, flags, mnt_data) mount(type, mnt->mnt_dir, flags, mnt_data)
/* End of included MOUNT_TRAP macro definition file */
/*
* The next line is a literal replacement of a variable which defines the
* the UNMOUNT_TRAP macro for a particular architecture.
* If it defines the wrong entry, check the AC_CHECK_UNMOUNT_CALL m4 macro
* in $srcdir/aclocal.m4. If the arguments are being defined wrong, check
* the macro AC_CHECK_UNMOUNT_ARGS in $srcdir/aux/macros.
*/
#define UNMOUNT_TRAP(mnt) unmount(mnt->mnt_dir)
/* End of replaced UNMOUNT_TRAP macro definition */
/*
* The next line is a literal inclusion of a file which includes a
* definition for the NFS_FH_DREF macro for a particular architecture.
* If it defines the wrong entry, check the AC_CHECK_NFS_FH_DREF m4 macro
* in $srcdir/aux/macros.
*/
/* $srcdir/conf/fh_dref/fh_dref_freebsd22.h */
#define NFS_FH_DREF(dst, src) (dst) = (u_char *) (src)
/* End of included NFS_FH_DREF macro definition file */
/*
* The next line is a literal inclusion of a file which includes a
* definition for the NFS_SA_DREF macro for a particular architecture.
* If it defines the wrong entry, check the AC_CHECK_NFS_SA_DREF m4 macro
* in $srcdir/aux/macros.
*/
/* $srcdir/conf/sa_dref/sa_dref_bsd44.h */
#define NFS_SA_DREF(dst, src) { \
(dst).addr = (struct sockaddr *) (src); \
(dst).addrlen = sizeof(*src); \
(dst).sotype = SOCK_DGRAM; \
(dst).proto = 0; \
}
/* End of included NFS_SA_DREF macro definition file */
/*
* The next line is a literal inclusion of a file which includes a
* definition for the NFS_HN_DREF macro for a particular architecture.
* If it defines the wrong entry, check the AC_CHECK_NFS_HN_DREF m4 macro
* in $srcdir/aux/macros.
*/
/* $srcdir/conf/hn_dref/hn_dref_default.h */
#define NFS_HN_DREF(dst, src) (dst) = (src)
/* End of included NFS_HN_DREF macro definition file */
#endif /* not _AUX_CONF_H */

View File

@ -0,0 +1,14 @@
# $NetBSD: Makefile,v 1.1.1.1 1997/07/24 21:20:11 christos Exp $
LIB= amu
SRCS= mtabutil.c tranputil.c umount_fs.c xutil.c xdr_mountres3.c wire.c \
util.c nfs_prot_xdr.c mtab.c mount_fs.c misc_rpc.c hasmntopt.c
config_local.h: mkconf
@rm -f ${.TARGET}
sh ${.ALLSRC} > ${.TARGET}
.include <bsd.lib.mk>
LDADD=
DPADD=
${OBJS}: config_local.h

78
usr.sbin/amd/libamu/amu.h Normal file
View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: amu.h,v 1.1.1.1 1997/07/24 21:20:10 christos Exp $
*
*/
#ifndef _AMU_H
#define _AMU_H
/*
* Decide what maximum level of NFS server to try and mount with.
*/
#ifdef HAVE_FS_NFS3
# define NFS_VERS_MAX NFS_VERSION3
#else /* not HAVE_FS_NFS3 */
# define NFS_VERS_MAX NFS_VERSION
#endif /* not HAVE_FS_NFS3 */
/* some systems like ncr2 do not define this in <rpcsvc/mount.h> */
#ifndef MNTPATHLEN
# define MNTPATHLEN 1024
#endif /* not MNTPATHLEN */
#ifndef MNTNAMLEN
# define MNTNAMLEN 255
#endif /* not MNTNAMLEN */
/*
* external definitions for building libamu.a
*/
extern voidp amqproc_null_1(voidp argp, CLIENT *rqstp);
extern amq_mount_tree_p *amqproc_mnttree_1(amq_string *argp, CLIENT *rqstp);
extern voidp amqproc_umnt_1(amq_string *argp, CLIENT *rqstp);
extern amq_mount_stats *amqproc_stats_1(voidp argp, CLIENT *rqstp);
extern amq_mount_tree_list *amqproc_export_1(voidp argp, CLIENT *rqstp);
extern int *amqproc_setopt_1(amq_setopt *argp, CLIENT *rqstp);
extern amq_mount_info_list *amqproc_getmntfs_1(voidp argp, CLIENT *rqstp);
extern int *amqproc_mount_1(voidp argp, CLIENT *rqstp);
extern amq_string *amqproc_getvers_1(voidp argp, CLIENT *rqstp);
#endif /* not _AMU_H */

View File

@ -0,0 +1,18 @@
/* Define user name */
#define USER_NAME "christos"
/* Define configuration date */
#define CONFIG_DATE "Thu Jul 24 12:25:26 EDT 1997"
/* Define name of host */
#define HOST_NAME "borken.nyc.deshaw.com"
/* Define only version of host machine (eg. 2.5.1) */
#define HOST_OS_VERSION "1.2G"
/* Define only name of host machine OS (eg. solaris2) */
#define HOST_OS_NAME "netbsd1"
#define HOST_OS "netbsd1.2G"

View File

@ -0,0 +1,119 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
n * modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: hasmntopt.c,v 1.1.1.1 1997/07/24 21:20:07 christos Exp $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amu.h>
#ifndef MNTMAXSTR
# define MNTMAXSTR 128
#endif /* not MNTMAXSTR */
/*
* Some systems don't provide these to the user,
* but amd needs them, so...
*
* From: Piete Brooks <pb@cl.cam.ac.uk>
*/
static char *
nextmntopt(char **p)
{
char *cp = *p;
char *rp;
/*
* Skip past white space
*/
while (*cp && isspace(*cp))
cp++;
/*
* Word starts here
*/
rp = cp;
/*
* Scan to send of string or separator
*/
while (*cp && *cp != ',')
cp++;
/*
* If separator found the overwrite with nul char.
*/
if (*cp) {
*cp = '\0';
cp++;
}
/*
* Return value for next call
*/
*p = cp;
return rp;
}
/*
* replacement for hasmntopt if the system does not have it.
*/
char *
hasmntopt(mntent_t *mnt, char *opt)
{
char t[MNTMAXSTR];
char *f;
char *o = t;
int l = strlen(opt);
strcpy(t, mnt->mnt_opts);
while (*(f = nextmntopt(&o)))
if (strncmp(opt, f, l) == 0)
return f - t + mnt->mnt_opts;
return 0;
}

View File

@ -0,0 +1,168 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: misc_rpc.c,v 1.1.1.1 1997/07/24 21:20:07 christos Exp $
*
*/
/*
* Additions to Sun RPC.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amu.h>
/*
* Some systems renamed _seterr_reply to __seterr_reply (with two
* leading underscores)
*/
#if !defined(HAVE__SETERR_REPLY) && defined(HAVE___SETERR_REPLY)
# define _seterr_reply __seterr_reply
#endif /* !defined(HAVE__SETERR_REPLY) && defined(HAVE___SETERR_REPLY) */
void
rpc_msg_init(struct rpc_msg *mp, u_long prog, u_long vers, u_long proc)
{
/*
* Initialise the message
*/
memset((voidp) mp, 0, sizeof(*mp));
mp->rm_xid = 0;
mp->rm_direction = CALL;
mp->rm_call.cb_rpcvers = RPC_MSG_VERSION;
mp->rm_call.cb_prog = prog;
mp->rm_call.cb_vers = vers;
mp->rm_call.cb_proc = proc;
}
/*
* Field reply to call to mountd
*/
int
pickup_rpc_reply(voidp pkt, int len, voidp where, XDRPROC_T_TYPE where_xdr)
{
XDR reply_xdr;
int ok;
struct rpc_err err;
struct rpc_msg reply_msg;
int error = 0;
/* memset((voidp) &err, 0, sizeof(err)); */
memset((voidp) &reply_msg, 0, sizeof(reply_msg));
memset((voidp) &reply_xdr, 0, sizeof(reply_xdr));
reply_msg.acpted_rply.ar_results.where = (caddr_t) where;
reply_msg.acpted_rply.ar_results.proc = where_xdr;
xdrmem_create(&reply_xdr, pkt, len, XDR_DECODE);
ok = xdr_replymsg(&reply_xdr, &reply_msg);
if (!ok) {
error = EIO;
goto drop;
}
_seterr_reply(&reply_msg, &err);
if (err.re_status != RPC_SUCCESS) {
error = EIO;
goto drop;
}
drop:
if (reply_msg.rm_reply.rp_stat == MSG_ACCEPTED &&
reply_msg.acpted_rply.ar_verf.oa_base) {
reply_xdr.x_op = XDR_FREE;
(void) xdr_opaque_auth(&reply_xdr,
&reply_msg.acpted_rply.ar_verf);
}
xdr_destroy(&reply_xdr);
return error;
}
int
make_rpc_packet(char *buf, int buflen, u_long proc, struct rpc_msg *mp, voidp arg, XDRPROC_T_TYPE arg_xdr, AUTH *auth)
{
XDR msg_xdr;
int len;
xdrmem_create(&msg_xdr, buf, buflen, XDR_ENCODE);
/*
* Basic protocol header
*/
if (!xdr_callhdr(&msg_xdr, mp))
return -EIO;
/*
* Called procedure number
*/
if (!xdr_enum(&msg_xdr, (enum_t *) & proc))
return -EIO;
/*
* Authorization
*/
if (!AUTH_MARSHALL(auth, &msg_xdr))
return -EIO;
/*
* Arguments
*/
if (!(*arg_xdr) (&msg_xdr, arg))
return -EIO;
/*
* Determine length
*/
len = xdr_getpos(&msg_xdr);
/*
* Throw away xdr
*/
xdr_destroy(&msg_xdr);
return len;
}

View File

@ -0,0 +1,24 @@
# $NetBSD: mkconf,v 1.1.1.1 1997/07/24 21:20:12 christos Exp $
# mkconf
# Generate local configuration parameters for amd
#
cat << __EOF
/* Define user name */
#define USER_NAME "`whoami`"
/* Define configuration date */
#define CONFIG_DATE "`date`"
/* Define name of host */
#define HOST_NAME "`hostname`"
/* Define only version of host machine (eg. 2.5.1) */
#define HOST_OS_VERSION "`uname -r`"
/* Define only name of host machine OS (eg. solaris2) */
#define HOST_OS_NAME "`uname -s | tr '[A-Z]' '[a-z]'``uname -r | cut -d. -f 1`"
#define HOST_OS "`uname -s | tr '[A-Z]' '[a-z]'``uname -r`"
__EOF

View File

@ -0,0 +1,290 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: mount_fs.c,v 1.1.1.1 1997/07/24 21:20:08 christos Exp $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amu.h>
/* ensure that mount table options are delimited by a comma */
#define append_opts(old, new) { \
if (*(old) != '\0') strcat(old, ","); \
strcat(old, new); }
/*
* Standard mount flags
*/
struct opt_tab mnt_flags[] =
{
#if defined(MNT2_GEN_OPT_RDONLY) && defined(MNTTAB_OPT_RO)
{MNTTAB_OPT_RO, MNT2_GEN_OPT_RDONLY},
#endif /* defined(MNT2_GEN_OPT_RDONLY) && defined(MNTTAB_OPT_RO) */
#if defined(MNT2_GEN_OPT_NOCACHE) && defined(MNTTAB_OPT_NOCACHE)
{MNTTAB_OPT_NOCACHE, MNT2_GEN_OPT_NOCACHE},
#endif /* defined(MNT2_GEN_OPT_NOCACHE) && defined(MNTTAB_OPT_NOCACHE) */
#if defined(MNT2_GEN_OPT_GRPID) && defined(MNTTAB_OPT_GRPID)
{MNTTAB_OPT_GRPID, MNT2_GEN_OPT_GRPID},
#endif /* defined(MNT2_GEN_OPT_GRPID) && defined(MNTTAB_OPT_GRPID) */
#if defined(MNT2_GEN_OPT_MULTI) && defined(MNTTAB_OPT_MULTI)
{MNTTAB_OPT_MULTI, MNT2_GEN_OPT_MULTI},
#endif /* defined(MNT2_GEN_OPT_MULTI) && defined(MNTTAB_OPT_MULTI) */
#if defined(MNT2_GEN_OPT_NODEV) && defined(MNTTAB_OPT_NODEV)
{MNTTAB_OPT_NODEV, MNT2_GEN_OPT_NODEV},
#endif /* defined(MNT2_GEN_OPT_NODEV) && defined(MNTTAB_OPT_NODEV) */
#if defined(MNT2_GEN_OPT_NOEXEC) && defined(MNTTAB_OPT_NOEXEC)
{MNTTAB_OPT_NOEXEC, MNT2_GEN_OPT_NOEXEC},
#endif /* defined(MNT2_GEN_OPT_NOEXEC) && defined(MNTTAB_OPT_NOEXEC) */
#if defined(MNT2_GEN_OPT_NOSUB) && defined(MNTTAB_OPT_NOSUB)
{MNTTAB_OPT_NOSUB, MNT2_GEN_OPT_NOSUB},
#endif /* defined(MNT2_GEN_OPT_NOSUB) && defined(MNTTAB_OPT_NOSUB) */
#if defined(MNT2_GEN_OPT_NOSUID) && defined(MNTTAB_OPT_NOSUID)
{MNTTAB_OPT_NOSUID, MNT2_GEN_OPT_NOSUID},
#endif /* defined(MNT2_GEN_OPT_NOSUID) && defined(MNTTAB_OPT_NOSUID) */
#if defined(MNT2_GEN_OPT_SYNC) && defined(MNTTAB_OPT_SYNC)
{MNTTAB_OPT_SYNC, MNT2_GEN_OPT_SYNC},
#endif /* defined(MNT2_GEN_OPT_SYNC) && defined(MNTTAB_OPT_SYNC) */
#if defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY)
{MNTTAB_OPT_OVERLAY, MNT2_GEN_OPT_OVERLAY},
#endif /* defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY) */
{0, 0}
};
int
compute_mount_flags(mntent_t *mnt)
{
struct opt_tab *opt;
int flags;
#ifdef MNT2_GEN_OPT_NEWTYPE
flags = MNT2_GEN_OPT_NEWTYPE;
#else /* not MNT2_GEN_OPT_NEWTYPE */
/* Not all machines have MNT2_GEN_OPT_NEWTYPE (HP-UX 9.01) */
flags = 0;
#endif /* not MNT2_GEN_OPT_NEWTYPE */
/*
* Crack basic mount options
*/
for (opt = mnt_flags; opt->opt; opt++)
flags |= hasmntopt(mnt, opt->opt) ? opt->flag : 0;
return flags;
}
int
mount_fs(mntent_t *mnt, int flags, caddr_t mnt_data, int retry, MTYPE_TYPE type, u_long nfs_version, const char *nfs_proto)
{
int error = 0;
#if defined(MNTTAB_OPT_DEV) || defined(MNTTAB_OPT_FSID)
struct stat stb;
#endif /* defined(MNTTAB_OPT_DEV) || defined(MNTTAB_OPT_FSID) */
#ifdef MOUNT_TABLE_ON_FILE
char *zopts = NULL, *xopts = NULL;
# if defined(MNTTAB_OPT_DEV) || defined(HAVE_FS_NFS3) || defined(MNTTAB_OPT_VERS) || defined(MNTTAB_OPT_PROTO)
char optsbuf[48];
# endif /* defined(MNTTAB_OPT_DEV) || defined(HAVE_FS_NFS3) || defined(MNTTAB_OPT_VERS) || defined(MNTTAB_OPT_PROTO) */
#endif /* MOUNT_TABLE_ON_FILE */
#ifdef DEBUG
char buf[80]; /* buffer for sprintf */
#endif /* DEBUG */
#ifdef DEBUG
sprintf(buf, "%s%s%s",
"%s fstype ", MTYPE_PRINTF_TYPE, " (%s) flags %#x (%s)");
dlog(buf, mnt->mnt_dir, type, mnt->mnt_type, flags, mnt->mnt_opts);
#endif /* DEBUG */
again:
clock_valid = 0;
error = MOUNT_TRAP(type, mnt, flags, mnt_data);
if (error < 0) {
plog(XLOG_ERROR, "%s: mount: %m", mnt->mnt_dir);
/*
* The following code handles conditions which shouldn't
* occur. They are possible either because amd screws up
* in preparing for the mount, or because some human
* messed with the mount point. Both have been known to
* happen. -- stolcke 2/22/95
*/
if (errno == ENOENT) {
/*
* Occasionally the mount point vanishes, probably
* due to some race condition. Just recreate it
* as necessary.
*/
errno = mkdirs(mnt->mnt_dir, 0555);
if (errno != 0 && errno != EEXIST)
plog(XLOG_ERROR, "%s: mkdirs: %m", mnt->mnt_dir);
else {
plog(XLOG_WARNING, "extra mkdirs required for %s",
mnt->mnt_dir);
error = MOUNT_TRAP(type, mnt, flags, mnt_data);
}
} else if (errno == EBUSY) {
/*
* Also, sometimes unmount isn't called, e.g., because
* our mountlist is garbled. This leaves old mount
* points around which need to be removed before we
* can mount something new in their place.
*/
errno = umount_fs(mnt->mnt_dir);
if (errno != 0)
plog(XLOG_ERROR, "%s: umount: %m", mnt->mnt_dir);
else {
plog(XLOG_WARNING, "extra umount required for %s",
mnt->mnt_dir);
error = MOUNT_TRAP(type, mnt, flags, mnt_data);
}
}
}
if (error < 0 && --retry > 0) {
sleep(1);
goto again;
}
if (error < 0) {
return errno;
}
#ifdef MOUNT_TABLE_ON_FILE
/*
* Allocate memory for options:
* dev=..., vers={2,3}, proto={tcp,udp}
*/
zopts = (char *) xmalloc(strlen(mnt->mnt_opts) + 48);
/* copy standard options */
xopts = mnt->mnt_opts;
strcpy(zopts, xopts);
# ifdef MNTTAB_OPT_DEV
/* add the extra dev= field to the mount table */
if (lstat(mnt->mnt_dir, &stb) == 0) {
if (sizeof(stb.st_dev) == 2) /* e.g. SunOS 4.1 */
sprintf(optsbuf, "%s=%04lx",
MNTTAB_OPT_DEV, (u_long) stb.st_dev & 0xffff);
else /* e.g. System Vr4 */
sprintf(optsbuf, "%s=%08lx",
MNTTAB_OPT_DEV, (u_long) stb.st_dev);
append_opts(zopts, optsbuf);
}
# endif /* MNTTAB_OPT_DEV */
# if defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)
/*
* add the extra vers={2,3} field to the mount table,
* unless already specified by user
*/
if (nfs_version == NFS_VERSION3 &&
hasmntval(mnt, MNTTAB_OPT_VERS) != NFS_VERSION3) {
sprintf(optsbuf, "%s=%d", MNTTAB_OPT_VERS, NFS_VERSION3);
append_opts(zopts, optsbuf);
}
# endif /* defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS) */
# ifdef MNTTAB_OPT_PROTO
/*
* add the extra proto={tcp,udp} field to the mount table,
* unless already specified by user.
*/
if (nfs_proto && !hasmntopt(mnt, MNTTAB_OPT_PROTO)) {
sprintf(optsbuf, "%s=%s", MNTTAB_OPT_PROTO, nfs_proto);
append_opts(zopts, optsbuf);
}
# endif /* MNTTAB_OPT_PROTO */
/* finally, store the options into the mount table structure */
mnt->mnt_opts = zopts;
/*
* Additional fields in mntent_t
* are fixed up here
*/
# ifdef HAVE_FIELD_MNTENT_T_CNODE
mnt->mnt_cnode = 0;
# endif /* HAVE_FIELD_MNTENT_T_CNODE */
# ifdef HAVE_FIELD_MNTENT_T_RO
mnt->mnt_ro = (hasmntopt(mnt, MNTTAB_OPT_RO) != NULL);
# endif /* HAVE_FIELD_MNTENT_T_RO */
# ifdef HAVE_FIELD_MNTENT_T_TIME
# ifdef HAVE_FIELD_MNTENT_T_TIME_STRING
{ /* allocate enough space for a long */
char *str = (char *) xmalloc(13 * sizeof(char));
sprintf(str, "%ld", time((time_t *) NULL));
mnt->mnt_time = str;
}
# else /* not HAVE_FIELD_MNTENT_T_TIME_STRING */
mnt->mnt_time = time((time_t *) NULL);
# endif /* not HAVE_FIELD_MNTENT_T_TIME_STRING */
# endif /* HAVE_FIELD_MNTENT_T_TIME */
write_mntent(mnt);
# ifdef MNTTAB_OPT_DEV
if (xopts) {
free(mnt->mnt_opts);
mnt->mnt_opts = xopts;
}
# endif /* MNTTAB_OPT_DEV */
#endif /* MOUNT_TABLE_ON_FILE */
return 0;
}

121
usr.sbin/amd/libamu/mtab.c Normal file
View File

@ -0,0 +1,121 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: mtab.c,v 1.1.1.1 1997/07/24 21:20:08 christos Exp $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amu.h>
/*
* Firewall /etc/mtab entries
*/
void
mnt_free(mntent_t *mp)
{
free(mp->mnt_fsname);
free(mp->mnt_dir);
free(mp->mnt_type);
free(mp->mnt_opts);
#ifdef HAVE_FIELD_MNTENT_T_TIME
# ifdef HAVE_FIELD_MNTENT_T_TIME_STRING
free(mp->mnt_time);
# endif /* HAVE_FIELD_MNTENT_T_TIME_STRING */
#endif /* HAVE_FIELD_MNTENT_T_TIME */
free((voidp) mp);
}
/*
* Discard memory allocated for mount list
*/
void
discard_mntlist(mntlist *mp)
{
mntlist *mp2;
while ((mp2 = mp)) {
mp = mp->mnext;
if (mp2->mnt)
mnt_free(mp2->mnt);
free((voidp) mp2);
}
}
/*
* Throw away a mount list
*/
void
free_mntlist(mntlist *mp)
{
discard_mntlist(mp);
#ifdef MOUNT_TABLE_ON_FILE
unlock_mntlist();
#endif /* MOUNT_TABLE_ON_FILE */
}
/*
* Utility routine which determines the value of a
* numeric option in the mount options (such as port=%d).
* Returns 0 if the option is not specified.
*/
int
hasmntval(mntent_t *mnt, char *opt)
{
char *str = hasmntopt(mnt, opt);
if (str) {
char *eq = strchr(str, '=');
if (eq)
return atoi(eq + 1);
else
plog(XLOG_USER, "bad numeric option \"%s\" in \"%s\"", opt, str);
}
return 0;
}

View File

@ -0,0 +1,145 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: mtabutil.c,v 1.1.1.1 1997/07/24 21:20:11 christos Exp $
*
*/
/*
* BSD 4.4 systems don't write their mount tables on a file. Instead, they
* use a (better) system where the kernel keeps this state, and you access
* the mount tables via a known interface.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amu.h>
static mntent_t *
mnt_dup(struct statfs *mp)
{
mntent_t *new_mp = ALLOC(mntent_t);
char *ty;
new_mp->mnt_fsname = strdup(mp->f_mntfromname);
new_mp->mnt_dir = strdup(mp->f_mntonname);
#ifdef HAVE_FIELD_STRUCT_STATFS_F_FSTYPENAME
ty = mp->f_fstypename;
#else /* not HAVE_FIELD_STRUCT_STATFS_F_FSTYPENAME */
switch (mp->f_type) {
# if defined(MOUNT_UFS) && defined(MNTTAB_TYPE_UFS)
case MOUNT_UFS:
ty = MNTTAB_TYPE_UFS;
break;
# endif /* defined(MOUNT_UFS) && defined(MNTTAB_TYPE_UFS) */
# if defined(MOUNT_NFS) && defined(MNTTAB_TYPE_NFS)
case MOUNT_NFS:
ty = MNTTAB_TYPE_NFS;
break;
# endif /* defined(MOUNT_NFS) && defined(MNTTAB_TYPE_NFS) */
# if defined(MOUNT_MFS) && defined(MNTTAB_TYPE_MFS)
case MOUNT_MFS:
ty = MNTTAB_TYPE_MFS;
break;
# endif /* defined(MOUNT_MFS) && defined(MNTTAB_TYPE_MFS) */
default:
ty = "unknown";
break;
}
#endif /* not HAVE_FIELD_STRUCT_STATFS_F_FSTYPENAME */
new_mp->mnt_type = strdup(ty);
new_mp->mnt_opts = strdup("unset");
new_mp->mnt_freq = 0;
new_mp->mnt_passno = 0;
return new_mp;
}
/*
* Read a mount table into memory
*/
mntlist *
read_mtab(char *fs)
{
mntlist **mpp, *mhp;
struct statfs *mntbufp, *mntp;
int nloc = getmntinfo(&mntbufp, MNT_NOWAIT);
if (nloc == 0) {
plog(XLOG_ERROR, "Can't read mount table");
return 0;
}
mpp = &mhp;
for (mntp = mntbufp; mntp < mntbufp + nloc; mntp++) {
/*
* Allocate a new slot
*/
*mpp = ALLOC(struct mntlist);
/*
* Copy the data returned by getmntent
*/
(*mpp)->mnt = mnt_dup(mntp);
/*
* Move to next pointer
*/
mpp = &(*mpp)->mnext;
}
/*
* Terminate the list
*/
*mpp = 0;
return mhp;
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: nfs_prot_xdr.c,v 1.1.1.1 1997/07/24 21:20:08 christos Exp $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amu.h>
bool_t
xdr_amq_string(XDR *xdrs, amq_string *objp)
{
if (!xdr_string(xdrs, objp, AMQ_STRLEN)) {
return (FALSE);
}
return (TRUE);
}

View File

@ -0,0 +1,2 @@
major=0
minor=0

View File

@ -0,0 +1,329 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: tranputil.c,v 1.1.1.1 1997/07/24 21:20:10 christos Exp $
*
* Socket specific utilities.
* -Erez Zadok <ezk@cs.columbia.edu>
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amu.h>
/*
* find the IP address that can be used to connect to the local host
*/
void
amu_get_myaddress(struct in_addr *iap)
{
struct sockaddr_in sin;
memset((char *) &sin, 0, sizeof(sin));
get_myaddress(&sin);
iap->s_addr = sin.sin_addr.s_addr;
}
/*
* How to bind to reserved ports.
*/
int
bind_resv_port(int so, u_short *pp)
{
struct sockaddr_in sin;
int rc;
u_short port;
memset((voidp) &sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
port = IPPORT_RESERVED;
do {
--port;
sin.sin_port = htons(port);
rc = bind(so, (struct sockaddr *) &sin, sizeof(sin));
} while (rc < 0 && (int) port > IPPORT_RESERVED / 2);
if (pp && rc == 0)
*pp = port;
return rc;
}
/*
* close a descriptot, Sockets style
*/
int
amu_close(int fd)
{
return close(fd);
}
/*
* Create an rpc client attached to the mount daemon.
*/
CLIENT *
get_mount_client(char *unused_host, struct sockaddr_in *sin, struct timeval *tv, int *sock, u_long mnt_version)
{
CLIENT *client;
/*
* First try a TCP socket
*/
if ((*sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) > 0) {
/*
* Bind to a privileged port
*/
if (bind_resv_port(*sock, (u_short *) 0) < 0)
plog(XLOG_ERROR, "can't bind privileged port");
/*
* Find mountd port to connect to.
* Connect to mountd.
* Create a tcp client.
*/
if ((sin->sin_port = htons(pmap_getport(sin, MOUNTPROG, mnt_version, IPPROTO_TCP))) != 0) {
if (connect(*sock, (struct sockaddr *) sin, sizeof(*sin)) >= 0
&& ((client = clnttcp_create(sin, MOUNTPROG, mnt_version, sock, 0, 0)) != NULL))
return client;
}
/*
* Failed so close socket
*/
(void) close(*sock);
} /* tcp socket opened */
/* TCP failed so try UDP */
if ((*sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
plog(XLOG_ERROR, "Can't create socket to connect to mountd: %m");
*sock = RPC_ANYSOCK;
return NULL;
}
/*
* Bind to a privileged port
*/
if (bind_resv_port(*sock, (u_short *) 0) < 0)
plog(XLOG_ERROR, "can't bind privileged port");
/*
* Zero out the port - make sure we recompute
*/
sin->sin_port = 0;
/*
* Make a UDP client
*/
if ((client = clntudp_create(sin, MOUNTPROG, mnt_version, *tv, sock)) == NULL) {
(void) close(*sock);
*sock = RPC_ANYSOCK;
return NULL;
}
#ifdef DEBUG
dlog("get_mount_client: Using udp, port %d", sin->sin_port);
#endif /* DEBUG */
return client;
}
/*
* find the address of the caller of an RPC procedure.
*/
struct sockaddr_in *
amu_svc_getcaller(SVCXPRT *xprt)
{
return svc_getcaller(xprt);
}
/*
* Bind NFS to a reserved port.
*/
static int
bindnfs_port(int so, u_short *nfs_portp)
{
u_short port;
int error = bind_resv_port(so, &port);
if (error == 0)
*nfs_portp = port;
return error;
}
/*
* Create the nfs service for amd
*/
int
create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp))
{
*soNFSp = socket(AF_INET, SOCK_DGRAM, 0);
if (*soNFSp < 0 || bindnfs_port(*soNFSp, nfs_portp) < 0) {
plog(XLOG_FATAL, "Can't create privileged nfs port");
return 1;
}
if ((*nfs_xprtp = svcudp_create(*soNFSp)) == NULL) {
plog(XLOG_FATAL, "cannot create rpc/udp service");
return 2;
}
if (!svc_register(*nfs_xprtp, NFS_PROGRAM, NFS_VERSION, dispatch_fxn, 0)) {
plog(XLOG_FATAL, "unable to register (NFS_PROGRAM, NFS_VERSION, 0)");
return 3;
}
return 0; /* all is well */
}
/*
* Create the amq service for amd (both TCP and UDP)
*/
int
create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, int *tcp_soAMQp, SVCXPRT **tcp_amqpp)
{
/* first create TCP service */
if (tcp_soAMQp) {
*tcp_soAMQp = socket(AF_INET, SOCK_STREAM, 0);
if (*tcp_soAMQp < 0) {
plog(XLOG_FATAL, "cannot create tcp socket for amq service: %m");
return 1;
}
/* now create RPC service handle for amq */
if (tcp_amqpp &&
(*tcp_amqpp = svctcp_create(*tcp_soAMQp, AMQ_SIZE, AMQ_SIZE)) == NULL) {
plog(XLOG_FATAL, "cannot create tcp service for amq: soAMQp=%d", *tcp_soAMQp);
return 2;
}
}
/* next create UDP service */
if (udp_soAMQp) {
*udp_soAMQp = socket(AF_INET, SOCK_DGRAM, 0);
if (*udp_soAMQp < 0) {
plog(XLOG_FATAL, "cannot create udp socket for amq service: %m");
return 3;
}
/* now create RPC service handle for amq */
if (udp_amqpp &&
(*udp_amqpp = svcudp_bufcreate(*udp_soAMQp, AMQ_SIZE, AMQ_SIZE)) == NULL) {
plog(XLOG_FATAL, "cannot create udp service for amq: soAMQp=%d", *udp_soAMQp);
return 4;
}
}
return 0; /* all is well */
}
/*
* Find the best NFS version for a host and protocol.
*/
u_long
get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_version, const char *proto)
{
CLIENT *clnt;
int again = 0;
enum clnt_stat clnt_stat;
struct timeval tv;
int sock;
/*
* If not set or set wrong, then try from NFS_VERS_MAX on down. If
* set, then try from nfs_version on down.
*/
if (nfs_version <= 0 || nfs_version > NFS_VERS_MAX) {
nfs_version = NFS_VERS_MAX;
again = 1;
}
tv.tv_sec = 2;
tv.tv_usec = 0;
try_again:
sock = RPC_ANYSOCK;
if (STREQ(proto, "tcp"))
clnt = clnttcp_create(sin, NFS_PROGRAM, nfs_version, &sock, 0, 0);
else if (STREQ(proto, "udp"))
clnt = clntudp_create(sin, NFS_PROGRAM, nfs_version, tv, &sock);
else
clnt = NULL;
if (clnt == NULL) {
plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s :%s",
nfs_version, proto, host, clnt_spcreateerror(""));
return 0;
}
/* Try a couple times to verify the CLIENT handle. */
tv.tv_sec = 6;
clnt_stat = clnt_call(clnt, NFSPROC_NULL, (xdrproc_t) xdr_void, 0,
(xdrproc_t) xdr_void, 0, tv);
close(sock);
clnt_destroy(clnt);
if (clnt_stat != RPC_SUCCESS) {
if (again) {
#ifdef HAVE_FS_NFS3
if (nfs_version == NFS_VERSION3) {
plog(XLOG_INFO, "get_nfs_version trying a lower version");
nfs_version = NFS_VERSION;
again = 0;
}
goto try_again;
#endif /* HAVE_FS_NFS3 */
}
plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s",
nfs_version, proto, host);
return 0;
}
plog(XLOG_INFO, "get_nfs_version: returning (%d,%s) on host %s",
nfs_version, proto, host);
return nfs_version;
}

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: umount_fs.c,v 1.1.1.1 1997/07/24 21:20:10 christos Exp $
*
*/
/*
* Unmounting filesystems under BSD 4.4.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amu.h>
int
umount_fs(char *fs_name)
{
int error;
eintr:
error = unmount(fs_name, 0);
if (error < 0)
error = errno;
switch (error) {
case EINVAL:
case ENOTBLK:
case ENOENT:
plog(XLOG_WARNING, "unmount: %s is not mounted", fs_name);
error = 0; /* Not really an error */
break;
case EINTR:
#ifdef DEBUG
/* not sure why this happens, but it does. ask kirk one day... */
dlog("%s: unmount: %m", fs_name);
#endif /* DEBUG */
goto eintr;
#ifdef DEBUG
default:
dlog("%s: unmount: %m", fs_name);
break;
#endif /* DEBUG */
}
return error;
}

176
usr.sbin/amd/libamu/util.c Normal file
View File

@ -0,0 +1,176 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: util.c,v 1.1.1.1 1997/07/24 21:20:08 christos Exp $
*
*/
/*
* General Utilitiles.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amu.h>
char *
strnsave(const char *str, int len)
{
char *sp = (char *) xmalloc(len + 1);
memmove(sp, str, len);
sp[len] = 0;
return sp;
}
/*
* Concatenate three strings and store in buffer pointed to
* by p, making p large enough to hold the strings
*/
char *
str3cat(char *p, char *s1, char *s2, char *s3)
{
int l1 = strlen(s1);
int l2 = strlen(s2);
int l3 = strlen(s3);
p = (char *) xrealloc(p, l1 + l2 + l3 + 1);
memmove(p, s1, l1);
memmove(p + l1, s2, l2);
memmove(p + l1 + l2, s3, l3 + 1);
return p;
}
/*
* Make all the directories in the path.
*/
int
mkdirs(char *path, int mode)
{
/*
* take a copy in case path is in readonly store
*/
char *p2 = strdup(path);
char *sp = p2;
struct stat stb;
int error_so_far = 0;
/*
* Skip through the string make the directories.
* Mostly ignore errors - the result is tested at the end.
*
* This assumes we are root so that we can do mkdir in a
* mode 555 directory...
*/
while ((sp = strchr(sp + 1, '/'))) {
*sp = '\0';
if (mkdir(p2, mode) < 0) {
error_so_far = errno;
} else {
#ifdef DEBUG
dlog("mkdir(%s)", p2);
#endif /* DEBUG */
}
*sp = '/';
}
if (mkdir(p2, mode) < 0) {
error_so_far = errno;
} else {
#ifdef DEBUG
dlog("mkdir(%s)", p2);
#endif /* DEBUG */
}
free(p2);
return stat(path, &stb) == 0 &&
(stb.st_mode & S_IFMT) == S_IFDIR ? 0 : error_so_far;
}
/*
* Remove as many directories in the path as possible.
* Give up if the directory doesn't appear to have
* been created by Amd (not mode dr-x) or an rmdir
* fails for any reason.
*/
void
rmdirs(char *dir)
{
char *xdp = strdup(dir);
char *dp;
do {
struct stat stb;
/*
* Try to find out whether this was
* created by amd. Do this by checking
* for owner write permission.
*/
if (stat(xdp, &stb) == 0 && (stb.st_mode & 0200) == 0) {
if (rmdir(xdp) < 0) {
if (errno != ENOTEMPTY &&
errno != EBUSY &&
errno != EEXIST &&
errno != EINVAL)
plog(XLOG_ERROR, "rmdir(%s): %m", xdp);
break;
} else {
#ifdef DEBUG
dlog("rmdir(%s)", xdp);
#endif /* DEBUG */
}
} else {
break;
}
dp = strrchr(xdp, '/');
if (dp)
*dp = '\0';
} while (dp && dp > xdp);
free(xdp);
}

342
usr.sbin/amd/libamu/wire.c Normal file
View File

@ -0,0 +1,342 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: wire.c,v 1.1.1.1 1997/07/24 21:20:09 christos Exp $
*
*/
/*
* This function returns the subnet (address&netmask) for the primary network
* interface. If the resulting address has an entry in the hosts file, the
* corresponding name is retuned, otherwise the address is returned in
* standard internet format.
* As a side-effect, a list of local IP/net address is recorded for use
* by the islocalnet() function.
*
* Derived from original by Paul Anderson (23/4/90)
* Updates from Dirk Grunwald (11/11/91)
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amu.h>
/*
* List of locally connected networks
*/
typedef struct addrlist addrlist;
struct addrlist {
addrlist *ip_next;
u_long ip_addr;
u_long ip_mask;
};
static addrlist *localnets = 0;
#if defined(IFF_LOCAL_LOOPBACK) && !defined(IFF_LOOPBACK)
# define IFF_LOOPBACK IFF_LOCAL_LOOPBACK
#endif /* defined(IFF_LOCAL_LOOPBACK) && !defined(IFF_LOOPBACK) */
#if defined(HAVE_FIELD_STRUCT_IFREQ_IFR_ADDR) && defined(HAVE_FIELD_STRUCT_SOCKADDR_SA_LEN)
# define SIZE(ifr) (MAX((ifr)->ifr_addr.sa_len, sizeof((ifr)->ifr_addr)) + sizeof(ifr->ifr_name))
#else /* not defined(HAVE_FIELD_STRUCT_IFREQ_IFR_ADDR) && defined(HAVE_FIELD_STRUCT_SOCKADDR_SA_LEN) */
# define SIZE(ifr) sizeof(*ifr)
#endif /* not defined(HAVE_FIELD_STRUCT_IFREQ_IFR_ADDR) && defined(HAVE_FIELD_STRUCT_SOCKADDR_SA_LEN) */
#define C(x) ((x) & 0xff)
#define GFBUFLEN 1024
#define clist (ifc.ifc_ifcu.ifcu_req)
#define count (ifc.ifc_len/sizeof(struct ifreq))
void
getwire(char **name1, char **number1, char **name2, char **number2)
{
struct hostent *hp;
struct netent *np;
struct ifconf ifc;
struct ifreq *ifr;
caddr_t cp, cplim;
u_long address, netmask, subnet;
char buf[GFBUFLEN], *s;
int fd = -1;
u_long net;
u_long mask;
u_long subnetshift;
char netNumberBuf[64];
#ifndef SIOCGIFFLAGS
/* if cannot get interface flags, return nothing */
*name1 = strdup("no_subnet_known");
*number1 = "0.0.0.0";
*name2 = 0;
*number2 = 0;
return;
#endif /* not SIOCGIFFLAGS */
*name1 = 0;
*number1 = 0;
*name2 = 0;
*number2 = 0;
/*
* Get suitable socket
*/
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
goto out;
/*
* Fill in ifconf details
*/
memset(&buf[0], 0, GFBUFLEN);
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
/*
* Get network interface configurations
*/
if (ioctl(fd, SIOCGIFCONF, (caddr_t) & ifc) < 0)
goto out;
/*
* Upper bound on array
*/
cplim = buf + ifc.ifc_len;
/*
* This is some magic to cope with both "traditional" and the
* new 4.4BSD-style struct sockaddrs. The new structure has
* variable length and a size field to support longer addresses.
* AF_LINK is a new definition for 4.4BSD.
*/
/*
* Scan the list looking for a suitable interface
*/
for (cp = buf; cp < cplim; cp += SIZE(ifr)) {
addrlist *al;
ifr = (struct ifreq *) cp;
if (ifr->ifr_addr.sa_family != AF_INET)
continue;
else
address = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
/*
* Get interface flags
*/
if (ioctl(fd, SIOCGIFFLAGS, (caddr_t) ifr) < 0)
continue;
/*
* If the interface is a loopback, or its not running
* then ignore it.
*/
#ifdef IFF_LOOPBACK
if ((ifr->ifr_flags & IFF_LOOPBACK) != 0)
continue;
#endif /* IFF_LOOPBACK */
/* if the interface is not UP or not RUNNING, skip it */
if ((ifr->ifr_flags & IFF_RUNNING) == 0 ||
(ifr->ifr_flags & IFF_UP) == 0)
continue;
/*
* Get the netmask of this interface
*/
if (ioctl(fd, SIOCGIFNETMASK, (caddr_t) ifr) < 0)
continue;
netmask = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
/*
* Add interface to local network list
*/
al = ALLOC(struct addrlist);
al->ip_addr = address;
al->ip_mask = netmask;
al->ip_next = localnets;
localnets = al;
/*
* Figure out the subnet's network address
*/
subnet = address & netmask;
#ifdef IN_CLASSA
subnet = htonl(subnet);
if (IN_CLASSA(subnet)) {
mask = IN_CLASSA_NET;
subnetshift = 8;
} else if (IN_CLASSB(subnet)) {
mask = IN_CLASSB_NET;
subnetshift = 8;
} else {
mask = IN_CLASSC_NET;
subnetshift = 4;
}
/*
* If there are more bits than the standard mask
* would suggest, subnets must be in use.
* Guess at the subnet mask, assuming reasonable
* width subnet fields.
* XXX: Or-in at least 1 byte's worth of 1s to make
* sure the top bits remain set.
*/
while (subnet & ~mask)
mask = (mask >> subnetshift) | 0xff000000;
net = subnet & mask;
while ((mask & 1) == 0)
mask >>= 1, net >>= 1;
/*
* Now get a usable name.
* First use the network database,
* then the host database,
* and finally just make a dotted quad.
*/
np = getnetbyaddr(net, AF_INET);
/* the network address has been masked off */
if ((subnet & 0xffffff) == 0) {
sprintf(netNumberBuf, "%lu", C(subnet >> 24));
} else if ((subnet & 0xffff) == 0) {
sprintf(netNumberBuf, "%lu.%lu",
C(subnet >> 24), C(subnet >> 16));
} else if ((subnet & 0xff) == 0) {
sprintf(netNumberBuf, "%lu.%lu.%lu",
C(subnet >> 24), C(subnet >> 16),
C(subnet >> 8));
} else {
sprintf(netNumberBuf, "%lu.%lu.%lu.%lu",
C(subnet >> 24), C(subnet >> 16),
C(subnet >> 8), C(subnet));
}
if (!*number1) {
*number1 = strdup(netNumberBuf);
} else if (!*number2) {
*number2 = strdup(netNumberBuf);
} else {
plog(XLOG_INFO, "Another unused interface discovered: netnumber %s", netNumberBuf);
}
#else /* not IN_CLASSA */
/* This is probably very wrong. */
np = getnetbyaddr(subnet, AF_INET);
#endif /* not IN_CLASSA */
if (np)
s = np->n_name;
else {
subnet = address & netmask;
hp = gethostbyaddr((char *) &subnet, 4, AF_INET);
if (hp)
s = (char *) hp->h_name;
else
s = inet_dquad(buf, subnet);
}
if (!*name1) {
*name1 = strdup(s);
} else if (!*name2) {
*name2 = strdup(s);
} else {
plog(XLOG_INFO, "Another unused interface discovered: netname %s", s);
}
}
out:
if (fd >= 0)
(void) close(fd);
if (!*name1)
*name1 = strdup(NO_SUBNET);
if (!*number1)
*number1 = "0.0.0.0";
if (!*name2)
*name2 = strdup(NO_SUBNET);
if (!*number2)
*number2 = "0.0.0.0";
}
/*
* Make a dotted quad from a 32bit IP address
* addr is in network byte order.
* sizeof(buf) needs to be at least 16.
*/
char *
inet_dquad(char *buf, u_long addr)
{
addr = ntohl(addr);
sprintf(buf, "%ld.%ld.%ld.%ld",
((addr >> 24) & 0xff),
((addr >> 16) & 0xff),
((addr >> 8) & 0xff),
((addr >> 0) & 0xff));
return buf;
}
/*
* Determine whether a network is on a local network
* (addr) is in network byte order.
*/
int
islocalnet(u_long addr)
{
addrlist *al;
#ifdef DEBUG
char buf[16];
#endif /* DEBUG */
for (al = localnets; al; al = al->ip_next)
if (((addr ^ al->ip_addr) & al->ip_mask) == 0)
return TRUE;
#ifdef DEBUG
plog(XLOG_INFO, "%s is on a remote network", inet_dquad(buf, addr));
#endif /* DEBUG */
return FALSE;
}

View File

@ -0,0 +1,117 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: xdr_mountres3.c,v 1.1.1.1 1997/07/24 21:20:09 christos Exp $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amu.h>
/*
* This ifdef is a hack: this whole file needs to be compiled
* only if the system has NFS V3 and does not have the xdr_mountres3
* function. Autoconf should pick this source file to compile only
* if these two conditions apply.
*/
#ifdef HAVE_FS_NFS3
bool_t
xdr_fhandle3(XDR *xdrs, fhandle3 *objp)
{
long *buf;
if (!xdr_bytes(xdrs,
(char **) &objp->fhandle3_val,
(u_int *) &objp->fhandle3_len,
FHSIZE3))
return (FALSE);
return (TRUE);
}
bool_t
xdr_mountstat3(XDR *xdrs, mountstat3 *objp)
{
long *buf;
if (!xdr_enum(xdrs, (enum_t *)objp))
return (FALSE);
return (TRUE);
}
bool_t
xdr_mountres3_ok(XDR *xdrs, mountres3_ok *objp)
{
long *buf;
if (!xdr_fhandle3(xdrs, &objp->fhandle))
return (FALSE);
if (!xdr_array(xdrs,
(char **)&objp->auth_flavors.auth_flavors_val,
(u_int *) &objp->auth_flavors.auth_flavors_len,
~0,
sizeof (int),
(xdrproc_t) xdr_int))
return (FALSE);
return (TRUE);
}
bool_t
xdr_mountres3(XDR *xdrs, mountres3 *objp)
{
long *buf;
if (!xdr_mountstat3(xdrs, &objp->fhs_status))
return (FALSE);
switch (objp->fhs_status) {
case 0: /* 0 == MNT_OK or MNT3_OK */
if (!xdr_mountres3_ok(xdrs, &objp->mountres3_u.mountinfo))
return (FALSE);
break;
}
return (TRUE);
}
#endif /* HAVE_FS_NFS3 */

587
usr.sbin/amd/libamu/xutil.c Normal file
View File

@ -0,0 +1,587 @@
/*
* Copyright (c) 1997 Erez Zadok
* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: xutil.c,v 1.1.1.1 1997/07/24 21:20:09 christos Exp $
*
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <am_defs.h>
#include <amu.h>
FILE *logfp = stderr; /* Log errors to stderr initially */
#ifdef HAVE_SYSLOG
int syslogging;
#endif /* HAVE_SYSLOG */
int xlog_level = XLOG_ALL & ~XLOG_MAP & ~XLOG_STATS;
int xlog_level_init = ~0;
time_t clock_valid = 0;
time_t xclock_valid = 0;
#ifdef DEBUG_MEM
static int mem_bytes;
static int orig_mem_bytes;
#endif /* DEBUG_MEM */
/* forward definitions */
static void real_plog(int lvl, char *fmt, va_list vargs);
#ifdef DEBUG
/*
* List of debug options.
*/
struct opt_tab dbg_opt[] =
{
{"all", D_ALL}, /* All */
{"amq", D_AMQ}, /* Register for AMQ program */
{"daemon", D_DAEMON}, /* Enter daemon mode */
{"fork", D_FORK}, /* Fork server (nofork = don't fork) */
{"full", D_FULL}, /* Program trace */
# ifdef DEBUG_MEM
{"mem", D_MEM}, /* Trace memory allocations */
# endif /* DEBUG_MEM */
{"mtab", D_MTAB}, /* Use local mtab file */
{"str", D_STR}, /* Debug string munging */
{"test", D_TEST}, /* Full debug - but no daemon */
{"trace", D_TRACE}, /* Protocol trace */
{0, 0}
};
#endif /* DEBUG */
/*
* List of log options
*/
struct opt_tab xlog_opt[] =
{
{"all", XLOG_ALL}, /* All messages */
#ifdef DEBUG
{"debug", XLOG_DEBUG}, /* Debug messages */
#endif /* DEBUG */ /* DEBUG */
{"error", XLOG_ERROR}, /* Non-fatal system errors */
{"fatal", XLOG_FATAL}, /* Fatal errors */
{"info", XLOG_INFO}, /* Information */
{"map", XLOG_MAP}, /* Map errors */
{"stats", XLOG_STATS}, /* Additional statistical information */
{"user", XLOG_USER}, /* Non-fatal user errors */
{"warn", XLOG_WARNING}, /* Warnings */
{"warning", XLOG_WARNING}, /* Warnings */
{0, 0}
};
voidp
xmalloc(int len)
{
voidp p;
int retries = 600;
/*
* Avoid malloc's which return NULL for malloc(0)
*/
if (len == 0)
len = 1;
do {
p = (voidp) malloc((unsigned) len);
if (p) {
#if defined(DEBUG) && defined(DEBUG_MEM)
amuDebug(D_MEM) plog(XLOG_DEBUG, "Allocated size %d; block %#x", len, p);
#endif /* defined(DEBUG) && defined(DEBUG_MEM) */
return p;
}
if (retries > 0) {
plog(XLOG_ERROR, "Retrying memory allocation");
sleep(1);
}
} while (--retries);
plog(XLOG_FATAL, "Out of memory");
going_down(1);
abort();
return 0;
}
voidp
xrealloc(voidp ptr, int len)
{
#if defined(DEBUG) && defined(DEBUG_MEM)
amuDebug(D_MEM) plog(XLOG_DEBUG, "Reallocated size %d; block %#x", len, ptr);
#endif /* defined(DEBUG) && defined(DEBUG_MEM) */
if (len == 0)
len = 1;
if (ptr)
ptr = (voidp) realloc(ptr, (unsigned) len);
else
ptr = (voidp) xmalloc((unsigned) len);
if (!ptr) {
plog(XLOG_FATAL, "Out of memory in realloc");
going_down(1);
abort();
}
return ptr;
}
#if defined(DEBUG) && defined(DEBUG_MEM)
void
xfree(char *f, int l, voidp p)
{
amuDebug(D_MEM) plog(XLOG_DEBUG, "Free in %s:%d: block %#x", f, l, p);
free(p);
}
#endif /* defined(DEBUG) && defined(DEBUG_MEM) */
#ifdef DEBUG_MEM
static void
checkup_mem(P_void)
{
extern struct mallinfo __mallinfo;
if (mem_bytes != __mallinfo.uordbytes) {
if (orig_mem_bytes == 0)
mem_bytes = orig_mem_bytes = __mallinfo.uordbytes;
else {
fprintf(logfp, "%s[%d]: ", progname, mypid);
if (mem_bytes < __mallinfo.uordbytes) {
fprintf(logfp, "ALLOC: %d bytes",
__mallinfo.uordbytes - mem_bytes);
} else {
fprintf(logfp, "FREE: %d bytes",
mem_bytes - __mallinfo.uordbytes);
}
mem_bytes = __mallinfo.uordbytes;
fprintf(logfp, ", making %d missing\n",
mem_bytes - orig_mem_bytes);
}
}
malloc_verify();
}
#endif /* DEBUG_MEM */
/*
* Take a log format string and expand occurences of %m
* with the current error code take from errno.
*/
static void
expand_error(char *f, char *e)
{
extern int sys_nerr;
char *p;
int error = errno;
for (p = f; (*e = *p); e++, p++) {
if (p[0] == '%' && p[1] == 'm') {
const char *errstr;
if (error < 0 || error >= sys_nerr)
errstr = NULL;
else
errstr = sys_errlist[error];
if (errstr)
strcpy(e, errstr);
else
sprintf(e, "Error %d", error);
e += strlen(e) - 1;
p++;
}
}
}
/*
* Output the time of day and hostname to the logfile
*/
static void
show_time_host_and_name(int lvl)
{
static time_t last_t = 0;
static char *last_ctime = 0;
time_t t = clocktime();
char *sev;
if (t != last_t) {
last_ctime = ctime(&t);
last_t = t;
}
switch (lvl) {
case XLOG_FATAL:
sev = "fatal:";
break;
case XLOG_ERROR:
sev = "error:";
break;
case XLOG_USER:
sev = "user: ";
break;
case XLOG_WARNING:
sev = "warn: ";
break;
case XLOG_INFO:
sev = "info: ";
break;
case XLOG_DEBUG:
sev = "debug:";
break;
case XLOG_MAP:
sev = "map: ";
break;
case XLOG_STATS:
sev = "stats:";
break;
default:
sev = "hmm: ";
break;
}
fprintf(logfp, "%15.15s %s %s[%ld]/%s ",
last_ctime + 4, hostname,
progname,
mypid,
sev);
}
#ifdef DEBUG
/*
* Switch on/off debug options
*/
int
debug_option(char *opt)
{
return cmdoption(opt, dbg_opt, &debug_flags);
}
void
dplog(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
real_plog(XLOG_DEBUG, fmt, ap);
va_end(ap);
}
#endif /* DEBUG */
void
plog(int lvl, char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
real_plog(lvl, fmt, ap);
va_end(ap);
}
static void
real_plog(int lvl, char *fmt, va_list vargs)
{
char msg[1024];
char efmt[1024];
char *ptr = msg;
if (!(xlog_level & lvl))
return;
#ifdef DEBUG_MEM
checkup_mem();
#endif /* DEBUG_MEM */
expand_error(fmt, efmt);
vsprintf(ptr, efmt, vargs);
ptr += strlen(ptr);
if (ptr[-1] == '\n')
*--ptr = '\0';
#ifdef HAVE_SYSLOG
if (syslogging) {
switch (lvl) { /* from mike <mcooper@usc.edu> */
case XLOG_FATAL:
lvl = LOG_CRIT;
break;
case XLOG_ERROR:
lvl = LOG_ERR;
break;
case XLOG_USER:
lvl = LOG_WARNING;
break;
case XLOG_WARNING:
lvl = LOG_WARNING;
break;
case XLOG_INFO:
lvl = LOG_INFO;
break;
case XLOG_DEBUG:
lvl = LOG_DEBUG;
break;
case XLOG_MAP:
lvl = LOG_DEBUG;
break;
case XLOG_STATS:
lvl = LOG_INFO;
break;
default:
lvl = LOG_ERR;
break;
}
syslog(lvl, "%s", msg);
return;
}
#endif /* HAVE_SYSLOG */
*ptr++ = '\n';
*ptr = '\0';
/*
* Mimic syslog header
*/
show_time_host_and_name(lvl);
fwrite(msg, ptr - msg, 1, logfp);
fflush(logfp);
}
/*
* Display current debug options
*/
void
show_opts(int ch, struct opt_tab *opts)
{
int i;
int s = '{';
fprintf(stderr, "\t[-%c {no}", ch);
for (i = 0; opts[i].opt; i++) {
fprintf(stderr, "%c%s", s, opts[i].opt);
s = ',';
}
fputs("}]\n", stderr);
}
int
cmdoption(char *s, struct opt_tab *optb, int *flags)
{
char *p = s;
int errs = 0;
while (p && *p) {
int neg;
char *opt;
struct opt_tab *dp, *dpn = 0;
s = p;
p = strchr(p, ',');
if (p)
*p = '\0';
/* check for "no" prefix to options */
if (s[0] == 'n' && s[1] == 'o') {
opt = s + 2;
neg = 1;
} else {
opt = s;
neg = 0;
}
/*
* Scan the array of debug options to find the
* corresponding flag value. If it is found
* then set (or clear) the flag (depending on
* whether the option was prefixed with "no").
*/
for (dp = optb; dp->opt; dp++) {
if (STREQ(opt, dp->opt))
break;
if (opt != s && !dpn && STREQ(s, dp->opt))
dpn = dp;
}
if (dp->opt || dpn) {
if (!dp->opt) {
dp = dpn;
neg = !neg;
}
if (neg)
*flags &= ~dp->flag;
else
*flags |= dp->flag;
} else {
/*
* This will log to stderr when parsing the command line
* since any -l option will not yet have taken effect.
*/
plog(XLOG_USER, "option \"%s\" not recognised", s);
errs++;
}
/*
* Put the comma back
*/
if (p)
*p++ = ',';
}
return errs;
}
/*
* Switch on/off logging options
*/
int
switch_option(char *opt)
{
int xl = xlog_level;
int rc = cmdoption(opt, xlog_opt, &xl);
if (rc) {
rc = EINVAL;
} else {
/*
* Keep track of initial log level, and
* don't allow options to be turned off.
*/
if (xlog_level_init == ~0)
xlog_level_init = xl;
else
xl |= xlog_level_init;
xlog_level = xl;
}
return rc;
}
/*
* Change current logfile
*/
int
switch_to_logfile(char *logfile)
{
FILE *new_logfp = stderr;
if (logfile) {
#ifdef HAVE_SYSLOG
syslogging = 0;
#endif /* HAVE_SYSLOG */
if (STREQ(logfile, "/dev/stderr"))
new_logfp = stderr;
else if (STREQ(logfile, "syslog")) {
#ifdef HAVE_SYSLOG
syslogging = 1;
new_logfp = stderr;
openlog(progname, LOG_PID | LOG_CONS | LOG_NOWAIT ,LOG_DAEMON);
#else /* not HAVE_SYSLOG */
plog(XLOG_WARNING, "syslog option not supported, logging unchanged");
#endif /* not HAVE_SYSLOG */
} else {
(void) umask(orig_umask);
new_logfp = fopen(logfile, "a");
umask(0);
}
}
/*
* If we couldn't open a new file, then continue using the old.
*/
if (!new_logfp && logfile) {
plog(XLOG_USER, "%s: Can't open logfile: %m", logfile);
return 1;
}
/*
* Close the previous file
*/
if (logfp && logfp != stderr)
(void) fclose(logfp);
logfp = new_logfp;
return 0;
}
void
unregister_amq(void)
{
#ifdef DEBUG
amuDebug(D_AMQ)
#endif /* DEBUG */
/*
* If pmap_unset fails, then try out the TLI version.
(void) rpcb_unset(AMQ_PROGRAM, AMQ_VERSION, (struct netconfig *) NULL);
*/
(void) pmap_unset(AMQ_PROGRAM, AMQ_VERSION);
}
void
going_down(int rc)
{
if (foreground) {
if (amd_state != Start) {
if (amd_state != Done)
return;
unregister_amq();
}
}
if (foreground) {
plog(XLOG_INFO, "Finishing with status %d", rc);
} else {
#ifdef DEBUG
dlog("background process exiting with status %d", rc);
#endif /* DEBUG */
}
exit(rc);
}