[comp.sources.unix] v15i002: unfsd - user level NFS server, Part02/02

shand@cad.jmrc.eecs.unsw.oz (Mark Shand) (05/25/88)

Submitted by: shand@cad.jmrc.eecs.unsw.oz (Mark Shand)
Posting-number: Volume 15, Issue 2
Archive-name: unfsd/Part02




UNFSD - USER-LEVEL NFS SERVER
=============================

This package implements a simple user level NFS server based on the
sunrpc3.9 package that was posted to the net a few months ago.  The
current version only provides read access from the clients.  It has
been tested between a VAX11/780 running 4.3BSD (the server) and several
diskful SUN3/60 running SunOS 3.4 (the clients) and on a diskless
SUN3/50 running SunOS 3.2 remounting its own root at a lower level of
its file hierarchy.

#--------------------------------CUT HERE-------------------------------------
#! /bin/sh
#
# This is a shell archive.  Save this into a file, edit it
# and delete all lines above this comment.  Then give this
# file to sh by executing the command "sh file".  The files
# will be extracted into the current directory owned by
# you with default permissions.
#
# The files contained herein are:
#
# -rw-rw-r--  1 shand        7684 May 16 02:24 nfs_prot.x
# -rw-r--r--  1 shand         304 May 16 02:24 ugid.x
# -rw-r--r--  1 shand        6206 May 17 02:25 ugid_map.c
# -rw-r--r--  1 shand         863 May 16 02:23 ugidd.8
# -rw-rw-r--  1 shand        3087 May 17 02:25 ugidd.c
# -rw-r--r--  1 shand        1653 May 17 02:02 unfsd.8
# -rw-r--r--  1 shand       12912 May 17 02:25 unfsd.c
# -rw-r--r--  1 shand        1399 May 17 02:25 unfsd.h
# -rw-r--r--  1 shand        2421 May 16 02:23 unfsd_exports.5
# -rw-rw-r--  1 shand        3616 May 17 02:25 unfsmntd.c
#
echo 'x - nfs_prot.x'
if test -f nfs_prot.x; then echo 'shar: not overwriting nfs_prot.x'; else
sed 's/^X//' << '________This_Is_The_END________' > nfs_prot.x
X/* @(#)nfs_prot.x	1.2 87/11/12 3.9 RPCSRC */
X
X/*
X * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
X * unrestricted use provided that this legend is included on all tape
X * media and as a part of the software program in whole or part.  Users
X * may copy or modify Sun RPC without charge, but are not authorized
X * to license or distribute it to anyone else except as part of a product or
X * program developed by the user.
X * 
X * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
X * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
X * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
X * 
X * Sun RPC is provided with no support and without any obligation on the
X * part of Sun Microsystems, Inc. to assist in its use, correction,
X * modification or enhancement.
X * 
X * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
X * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
X * OR ANY PART THEREOF.
X * 
X * In no event will Sun Microsystems, Inc. be liable for any lost revenue
X * or profits or other special, indirect and consequential damages, even if
X * Sun has been advised of the possibility of such damages.
X * 
X * Sun Microsystems, Inc.
X * 2550 Garcia Avenue
X * Mountain View, California  94043
X */
X
X/*
X * nfs_prot.x 1.2 87/10/12
X * Copyright 1987 Sun Microsystems, Inc.
X */
Xconst NFS_PORT          = 2049;
Xconst NFS_MAXDATA       = 8192;
Xconst NFS_MAXPATHLEN    = 1024;
Xconst NFS_MAXNAMLEN	= 255;
Xconst NFS_FHSIZE	= 32;
Xconst NFS_COOKIESIZE	= 4;
Xconst NFS_FIFO_DEV	= -1;	/* size kludge for named pipes */
X
X/*
X * File types
X */
Xconst NFSMODE_FMT  = 0170000;	/* type of file */
Xconst NFSMODE_DIR  = 0040000;	/* directory */
Xconst NFSMODE_CHR  = 0020000;	/* character special */
Xconst NFSMODE_BLK  = 0060000;	/* block special */
Xconst NFSMODE_REG  = 0100000;	/* regular */
Xconst NFSMODE_LNK  = 0120000;	/* symbolic link */
Xconst NFSMODE_SOCK = 0140000;	/* socket */
Xconst NFSMODE_FIFO = 0010000;	/* fifo */
X
X/*
X * Error status
X */
Xenum nfsstat {
X	NFS_OK= 0,		/* no error */
X	NFSERR_PERM=1,		/* Not owner */
X	NFSERR_NOENT=2,		/* No such file or directory */
X	NFSERR_IO=5,		/* I/O error */
X	NFSERR_NXIO=6,		/* No such device or address */
X	NFSERR_ACCES=13,	/* Permission denied */
X	NFSERR_EXIST=17,	/* File exists */
X	NFSERR_NODEV=19,	/* No such device */
X	NFSERR_NOTDIR=20,	/* Not a directory*/
X	NFSERR_ISDIR=21,	/* Is a directory */
X	NFSERR_FBIG=27,		/* File too large */
X	NFSERR_NOSPC=28,	/* No space left on device */
X	NFSERR_ROFS=30,		/* Read-only file system */
X	NFSERR_NAMETOOLONG=63,	/* File name too long */
X	NFSERR_NOTEMPTY=66,	/* Directory not empty */
X	NFSERR_DQUOT=69,	/* Disc quota exceeded */
X	NFSERR_STALE=70,	/* Stale NFS file handle */
X	NFSERR_WFLUSH=99	/* write cache flushed */
X};
X
X/*
X * File types
X */
Xenum ftype {
X	NFNON = 0,	/* non-file */
X	NFREG = 1,	/* regular file */
X	NFDIR = 2,	/* directory */
X	NFBLK = 3,	/* block special */
X	NFCHR = 4,	/* character special */
X	NFLNK = 5,	/* symbolic link */
X	NFSOCK = 6,	/* unix domain sockets */
X	NFBAD = 7,	/* unused */
X	NFFIFO = 8 	/* named pipe */
X};
X
X/*
X * File access handle
X */
Xstruct nfs_fh {
X	opaque data[NFS_FHSIZE];
X};
X
X/* 
X * Timeval
X */
Xstruct nfstime {
X	unsigned seconds;
X	unsigned useconds;
X};
X
X
X/*
X * File attributes
X */
Xstruct fattr {
X	ftype type;		/* file type */
X	unsigned mode;		/* protection mode bits */
X	unsigned nlink;		/* # hard links */
X	unsigned uid;		/* owner user id */
X	unsigned gid;		/* owner group id */
X	unsigned size;		/* file size in bytes */
X	unsigned blocksize;	/* prefered block size */
X	unsigned rdev;		/* special device # */
X	unsigned blocks;	/* Kb of disk used by file */
X	unsigned fsid;		/* device # */
X	unsigned fileid;	/* inode # */
X	nfstime	atime;		/* time of last access */
X	nfstime	mtime;		/* time of last modification */
X	nfstime	ctime;		/* time of last change */
X};
X
X/*
X * File attributes which can be set
X */
Xstruct sattr {
X	unsigned mode;	/* protection mode bits */
X	unsigned uid;	/* owner user id */
X	unsigned gid;	/* owner group id */
X	unsigned size;	/* file size in bytes */
X	nfstime	atime;	/* time of last access */
X	nfstime	mtime;	/* time of last modification */
X};
X
X
Xtypedef string filename<NFS_MAXNAMLEN>; 
Xtypedef string nfspath<NFS_MAXPATHLEN>;
X
X/*
X * Reply status with file attributes
X */
Xunion attrstat switch (nfsstat status) {
Xcase NFS_OK:
X	fattr attributes;
Xdefault:
X	void;
X};
X
Xstruct sattrargs {
X	nfs_fh file;
X	sattr attributes;
X};
X
X/*
X * Arguments for directory operations
X */
Xstruct diropargs {
X	nfs_fh	dir;	/* directory file handle */
X	filename name;		/* name (up to NFS_MAXNAMLEN bytes) */
X};
X
Xstruct diropokres {
X	nfs_fh file;
X	fattr attributes;
X};
X
X/*
X * Results from directory operation
X */
Xunion diropres switch (nfsstat status) {
Xcase NFS_OK:
X	diropokres diropres;
Xdefault:
X	void;
X};
X
Xunion readlinkres switch (nfsstat status) {
Xcase NFS_OK:
X	nfspath data;
Xdefault:
X	void;
X};
X
X/*
X * Arguments to remote read
X */
Xstruct readargs {
X	nfs_fh file;		/* handle for file */
X	unsigned offset;	/* byte offset in file */
X	unsigned count;		/* immediate read count */
X	unsigned totalcount;	/* total read count (from this offset)*/
X};
X
X/*
X * Status OK portion of remote read reply
X */
Xstruct readokres {
X	fattr	attributes;	/* attributes, need for pagin*/
X	opaque data<NFS_MAXDATA>;
X};
X
Xunion readres switch (nfsstat status) {
Xcase NFS_OK:
X	readokres reply;
Xdefault:
X	void;
X};
X
X/*
X * Arguments to remote write 
X */
Xstruct writeargs {
X	nfs_fh	file;		/* handle for file */
X	unsigned beginoffset;	/* beginning byte offset in file */
X	unsigned offset;	/* current byte offset in file */
X	unsigned totalcount;	/* total write count (to this offset)*/
X	opaque data<NFS_MAXDATA>;
X};
X
Xstruct createargs {
X	diropargs where;
X	sattr attributes;
X};
X
Xstruct renameargs {
X	diropargs from;
X	diropargs to;
X};
X
Xstruct linkargs {
X	nfs_fh from;
X	diropargs to;
X};
X
Xstruct symlinkargs {
X	diropargs from;
X	nfspath to;
X	sattr attributes;
X};
X
X
Xtypedef opaque nfscookie[NFS_COOKIESIZE];
X
X/*
X * Arguments to readdir
X */
Xstruct readdirargs {
X	nfs_fh dir;		/* directory handle */
X	nfscookie cookie;
X	unsigned count;		/* number of directory bytes to read */
X};
X
Xstruct entry {
X	unsigned fileid;
X	filename name;
X	nfscookie cookie;
X	entry *nextentry;
X};
X
Xstruct dirlist {
X	entry *entries;
X	bool eof;
X};
X
Xunion readdirres switch (nfsstat status) {
Xcase NFS_OK:
X	dirlist reply;
Xdefault:
X	void;
X};
X
Xstruct statfsokres {
X	unsigned tsize;	/* preferred transfer size in bytes */
X	unsigned bsize;	/* fundamental file system block size */
X	unsigned blocks;	/* total blocks in file system */
X	unsigned bfree;	/* free blocks in fs */
X	unsigned bavail;	/* free blocks avail to non-superuser */
X};
X
Xunion statfsres switch (nfsstat status) {
Xcase NFS_OK:
X	statfsokres reply;
Xdefault:
X	void;
X};
X
X/*
X * Remote file service routines
X */
Xprogram NFS_PROGRAM {
X	version NFS_VERSION {
X		void 
X		NFSPROC_NULL(void) = 0;
X
X		attrstat 
X		NFSPROC_GETATTR(nfs_fh) =	1;
X
X		attrstat 
X		NFSPROC_SETATTR(sattrargs) = 2;
X
X		void 
X		NFSPROC_ROOT(void) = 3;
X
X		diropres 
X		NFSPROC_LOOKUP(diropargs) = 4;
X
X		readlinkres 
X		NFSPROC_READLINK(nfs_fh) = 5;
X
X		readres 
X		NFSPROC_READ(readargs) = 6;
X
X		void 
X		NFSPROC_WRITECACHE(void) = 7;
X
X		attrstat
X		NFSPROC_WRITE(writeargs) = 8;
X
X		diropres
X		NFSPROC_CREATE(createargs) = 9;
X
X		nfsstat
X		NFSPROC_REMOVE(diropargs) = 10;
X
X		nfsstat
X		NFSPROC_RENAME(renameargs) = 11;
X
X		nfsstat
X		NFSPROC_LINK(linkargs) = 12;
X
X		nfsstat
X		NFSPROC_SYMLINK(symlinkargs) = 13;
X
X		diropres
X		NFSPROC_MKDIR(createargs) = 14;
X
X		nfsstat
X		NFSPROC_RMDIR(diropargs) = 15;
X
X		readdirres
X		NFSPROC_READDIR(readdirargs) = 16;
X
X		statfsres
X		NFSPROC_STATFS(nfs_fh) = 17;
X	} = 2;
X} = 100003;
X
________This_Is_The_END________
if test `wc -l < nfs_prot.x` -ne 355; then
	echo 'shar: nfs_prot.x was damaged during transit (should have been 355 bytes)'
fi
fi		; : end of overwriting check
echo 'x - ugid.x'
if test -f ugid.x; then echo 'shar: not overwriting ugid.x'; else
sed 's/^X//' << '________This_Is_The_END________' > ugid.x
Xconst MAXUGLEN = 64;
Xconst NOBODY = -2;
Xconst WILDCARD = -1;
Xtypedef string ugname<MAXUGLEN>;
X
Xprogram UGIDPROG {
X    version UGIDVERS {
X	int AUTHENTICATE(int) = 1;
X	int NAME_UID(ugname) = 2;
X	int GROUP_GID(ugname) = 3;
X	ugname UID_NAME(int) = 4; 
X	ugname GID_GROUP(int) = 5; 
X    } = 1;
X} = 0x2084e581;
________This_Is_The_END________
if test `wc -l < ugid.x` -ne 14; then
	echo 'shar: ugid.x was damaged during transit (should have been 14 bytes)'
fi
fi		; : end of overwriting check
echo 'x - ugid_map.c'
if test -f ugid_map.c; then echo 'shar: not overwriting ugid_map.c'; else
sed 's/^X//' << '________This_Is_The_END________' > ugid_map.c
X/* UNFSD - copyright Mark A Shand, May 1988.
X * This software maybe be used for any purpose provided
X * the above copyright notice is retained.  It is supplied
X * as is, with no warranty expressed or implied.
X */
X
X#include <pwd.h>
X#include <grp.h>
X#include <fcntl.h>
X#include "unfsd.h"
X
Xtypedef struct mapper {
X	struct in_addr	addr;
X	struct idm {
X		int	*known;
X		int	lim;
X	} uid, gid, rev_uid, rev_gid;
X	struct mapper *next;
X} mapper;
X
Xstatic	mapper	*id_maps = NULL;
X
X#ifdef sun
Xvoid xdr_free() {}
X#endif
X
Xstatic mapper *
Xgetmap(xprt)
XSVCXPRT	*xprt;
X{
X	mapper	**mapp;
X	mapper	*map;
X	struct in_addr	caller;
X	static	mapper mfailed;
X	
X	caller = svc_getcaller(xprt)->sin_addr;
X	for (mapp = &id_maps; *mapp != NULL; mapp = &((*mapp)->next))
X		if ((*mapp)->addr.s_addr == caller.s_addr)
X		{
X			/* move to front */
X			if (*mapp != id_maps)
X			{
X				map = *mapp;
X				*mapp = map->next;
X				map->next = id_maps;
X				id_maps = map;
X			}
X			return id_maps;
X		}
X	if ((map = (mapper *) malloc(sizeof *map)) == NULL)
X		return &mfailed;
X	map->next = id_maps;
X	id_maps = map;
X	map->addr.s_addr = caller.s_addr;
X	map->uid.known = NULL;
X	map->uid.lim = 0;
X	map->gid.known = NULL;
X	map->gid.lim = 0;
X	map->rev_uid.known = NULL;
X	map->rev_uid.lim = 0;
X	map->rev_gid.known = NULL;
X	map->rev_gid.lim = 0;
X	return map;
X}
X
Xstatic int
Xgrow_tab(idmp, sz)
Xstruct	idm	*idmp;
Xint		sz;
X{
X	if (idmp->lim == 0)
X		idmp->known = (int *) malloc((sz+1) * sizeof(int));
X	else
X		idmp->known = (int *) realloc((char *) idmp->known, (sz+1) * sizeof(int));
X	if (idmp->known == NULL)
X		idmp->lim = 0;
X	else
X	{
X		while (idmp->lim <= sz)
X			idmp->known[idmp->lim++] = WILDCARD;
X		idmp->known[0] = 0;
X	}
X	return idmp->lim;
X}
X
Xstatic int
Xrlookup(name, id, map, xprt)
Xchar	*name;
Xint	*id;
Xint	map;
XSVCXPRT	*xprt;
X{
X	struct sockaddr_in	addr, callback;
X	int	cb_fd;
X	int	cb_len;
X	int	cb_port;
X	struct timeval	wait;
X	int		sock;
X	CLIENT		*cl;
X	int		*pi;
X	char		**pc;
X	int	server_trusted = 0;
X
X
X	addr = *svc_getcaller(xprt);
X	addr.sin_port = 0;
X	wait.tv_sec = 10;
X	wait.tv_usec = 0;
X	sock = RPC_ANYSOCK;
X
X	if ((cl = clntudp_create(&addr, UGIDPROG, UGIDVERS, wait, &sock)) == NULL)
X		return 0;
X	if ((cb_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
X		goto bad;
X	bzero((char *)&callback, sizeof(callback));
X	callback.sin_port = 0;
X	callback.sin_addr.s_addr = INADDR_ANY;
X	callback.sin_family = AF_INET;
X	if (bind(cb_fd, &callback, sizeof(callback)) < 0)
X		goto bad;
X	cb_len = sizeof callback;
X	if (getsockname(cb_fd, &callback, &cb_len) < 0)
X		goto bad;
X	cb_port = ntohs(callback.sin_port);
X	pi = authenticate_1(&cb_port, cl);
X	if (pi != NULL && *pi == 0)
X	{
X		struct sockaddr_in	serv;
X		int	x;
X		int	serv_len;
X		struct timeval	timeout;
X		fd_set	rset;
X
X		serv_len = sizeof serv;
X		timeout.tv_sec = 5;
X		timeout.tv_usec = 0;
X#ifndef	FD_ZERO
X#define FD_ZERO(p)	bzero((char *) (p), sizeof *(p));
X#define FD_SETSIZE	32
X#define FD_SET(n,p)	((*(int *)(p)) |= 1 << n)
X#endif
X		FD_ZERO(&rset);
X		FD_SET(cb_fd, &rset);
X		if (select(FD_SETSIZE, &rset, NULL, NULL, &timeout) > 0)
X		{
X			recvfrom(cb_fd, &x, sizeof x, 0, &serv, &serv_len);
X			server_trusted = ntohs(serv.sin_port) < IPPORT_RESERVED;
X		}
X	}
X	if (!server_trusted)
X		goto bad;
X	switch (map)
X	{
X		case NAME_UID:
X			pi = name_uid_1(&name, cl);
X			if (pi != NULL)
X				*id = *pi;
X			break;
X		case GROUP_GID:
X			pi = group_gid_1(&name, cl);
X			if (pi != NULL)
X				*id = *pi;
X			break;
X		case UID_NAME:
X			pc = uid_name_1(id, cl);
X			if ((pi = (int *) pc) != NULL)
X				strcpy(name, *pc);
X			break;
X		case GID_GROUP:
X			pc = uid_name_1(id, cl);
X			if ((pi = (int *) pc) != NULL)
X				strcpy(name, *pc);
X			break;
X		default:
X			pi = NULL;
X			break;
X	}
X	clnt_destroy(cl);
X	close(cb_fd);
X	return (pi != NULL);
X    bad:
X	clnt_destroy(cl);
X	close(cb_fd);
X	return 0;
X}
X
Xruid(uid, cp, xprt)
Xint		uid;
Xclnt_param	*cp;
XSVCXPRT		*xprt;
X{
X	struct passwd	*pw;
X	mapper	*m;
X
X	if (uid < 0)
X		return (uid != WILDCARD) ? NOBODY : WILDCARD;
X	if (uid == 0 && cp->o.root_squash)
X		return NOBODY;
X	if (cp->o.uidmap == identity)
X		return uid;
X	m = getmap(xprt);
X	if ((uid < m->uid.lim || grow_tab(&(m->uid), uid))
X		&& m->uid.known[uid] == WILDCARD)
X	{
X		if ((pw = getpwuid(uid)) == NULL)
X			m->uid.known[uid] = NOBODY;
X		else if (!rlookup(pw->pw_name, &(m->uid.known[uid]), NAME_UID, xprt))
X			m->uid.known[uid] = NOBODY;
X	}
X	return (m->uid.lim == 0) ? NOBODY : m->uid.known[uid];
X}
X
Xrgid(gid, cp, xprt)
Xint		gid;
Xclnt_param	*cp;
XSVCXPRT		*xprt;
X{
X	struct group	*gr;
X	mapper	*m;
X
X	if (gid < 0)
X		return (gid != WILDCARD) ? NOBODY : WILDCARD;
X	if (cp->o.uidmap == identity)
X		return gid;
X	m = getmap(xprt);
X	if ((gid < m->gid.lim || grow_tab(&(m->gid), gid))
X		&& m->gid.known[gid] == WILDCARD)
X	{
X		if ((gr = getgrgid(gid)) == NULL)
X			m->gid.known[gid] = NOBODY;
X		else if (!rlookup(gr->gr_name, &(m->gid.known[gid]), GROUP_GID, xprt))
X			m->gid.known[gid] = NOBODY;
X	}
X	return (m->gid.lim == 0) ? NOBODY : m->gid.known[gid];
X}
X
Xluid(uid, cp, xprt)
Xint		uid;
Xclnt_param	*cp;
XSVCXPRT		*xprt;
X{
X	struct passwd	*pw;
X	mapper	*m;
X	char	namebuf[MAXUGLEN];
X
X	if (uid < 0)
X		return (uid != WILDCARD) ? NOBODY : WILDCARD;
X	if (uid == 0 && cp->o.root_squash)
X		return NOBODY;
X	if (cp->o.uidmap == identity)
X		return uid;
X	m = getmap(xprt);
X	if ((uid < m->rev_uid.lim || grow_tab(&(m->rev_uid), uid))
X		&& m->rev_uid.known[uid] == WILDCARD)
X	{
X		if (!rlookup(namebuf, &uid, UID_NAME, xprt))
X			m->rev_uid.known[uid] = NOBODY;
X		else if ((pw = getpwnam(namebuf)) == NULL)
X			m->rev_uid.known[uid] = NOBODY;
X		else
X			m->rev_uid.known[uid] = pw->pw_uid;
X	}
X	return (m->rev_uid.lim == 0) ? NOBODY : m->rev_uid.known[uid];
X}
X
Xlgid(gid, cp, xprt)
Xint		gid;
Xclnt_param	*cp;
XSVCXPRT		*xprt;
X{
X	struct group	*gr;
X	mapper	*m;
X	char	namebuf[MAXUGLEN]; 
X
X	if (gid < 0)
X		return (gid != WILDCARD) ? NOBODY : WILDCARD;
X	if (cp->o.uidmap == identity)
X		return gid;
X	m = getmap(xprt);
X	if ((gid < m->rev_gid.lim || grow_tab(&(m->rev_gid), gid))
X		&& m->rev_gid.known[gid] == WILDCARD)
X	{
X		if (!rlookup(namebuf, &gid, GID_GROUP, xprt)) 
X			m->rev_gid.known[gid] = NOBODY;
X		else if ((gr = getgrnam(namebuf)) == NULL)
X			m->rev_gid.known[gid] = NOBODY;
X		else
X			m->rev_gid.known[gid] = gr->gr_gid;
X	}
X	return (m->rev_gid.lim == 0) ? NOBODY : m->rev_gid.known[gid];
X}
________This_Is_The_END________
if test `wc -l < ugid_map.c` -ne 291; then
	echo 'shar: ugid_map.c was damaged during transit (should have been 291 bytes)'
fi
fi		; : end of overwriting check
echo 'x - ugidd.8'
if test -f ugidd.8; then echo 'shar: not overwriting ugidd.8'; else
sed 's/^X//' << '________This_Is_The_END________' > ugidd.8
X.TH UGIDD 8 "11 May 1988"
X.SH NAME
Xugidd \- uid/gid mapping daemons
X.SH SYNOPSIS
X.nf
X.B /etc/ugidd -d
X.LP
Xor from SunOS inetd(8):
X.B rpc udp /usr/etc/rpc.ugidd 545580417 1
X.fi
X.SH DESCRIPTION
X.IX  "uid/gid mapping daemons"  "ugidd daemon"  ""  "\fLugidd\fP daemon"
X.I ugidd
Xstarts a
Xdaemon that handles rpc requests to map uid/gids to string names and vice versa.
XIt is called by a unfsd(8) server when the client and server do not share
Xthe same passwd file.
X.LP
XThe
X.B -d
Xflag to run as a standalone server.
XOtherwise it assumes it has been started from inetd(8) and communicates on
Xfile descriptor 0.
XWhen started from inetd, the daemon exits after 5 minutes of inactivity.
X.SH "SEE ALSO"
Xunfsd_exports(5)
Xinetd(8)
X.SH BUGS
XThe rpc program number is legal in that it lies in the 0x20000000
Xto 0x3fffffff ``Defined by user'' range, but is completely arbitrary.
________This_Is_The_END________
if test `wc -l < ugidd.8` -ne 30; then
	echo 'shar: ugidd.8 was damaged during transit (should have been 30 bytes)'
fi
fi		; : end of overwriting check
echo 'x - ugidd.c'
if test -f ugidd.c; then echo 'shar: not overwriting ugidd.c'; else
sed 's/^X//' << '________This_Is_The_END________' > ugidd.c
X/* UNFSD - copyright Mark A Shand, May 1988.
X * This software maybe be used for any purpose provided
X * the above copyright notice is retained.  It is supplied
X * as is, with no warranty expressed or implied.
X */
X
X#include <rpc/rpc.h>
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <sys/time.h>
X#include <sys/errno.h>
X#include <sys/ioctl.h>
X#include <netinet/in.h>
X#include <pwd.h>
X#include <grp.h>
X#include <signal.h>
X#include "ugid.h"
X
Xstatic struct timeval TIMEOUT = { 25, 0 };
X
X#define	DAEMON_IDLE_LIMIT	(5*60)
X
Xstatic int	idle_limit = 0;
Xextern	int	errno;
X
Xint
Xrun_mode_from_args(argc, argv)
Xint	argc;
Xchar	**argv;
X{
X	int	i;
X
X	for (i = 1; i < argc && argv[i][0] == '-'; i++)
X		if (argv[i][1] == 'd')
X		{
X#ifndef DEBUG
X			int fd;
X
X			if (fork())
X				exit(0);
X			close(0);
X			close(1);
X			close(2);
X			if ((fd = open("/dev/tty", 2)) >= 0)
X			{
X				ioctl(fd, TIOCNOTTY, (char *)0);
X				(void) close(fd);
X			}
X#endif DEBUG
X			return RPC_ANYSOCK;
X		}
X	/* assume run from inetd */
X	idle_limit = DAEMON_IDLE_LIMIT;
X	alarm(idle_limit);
X	return 0;
X}
X
Xint *
Xauthenticate_1(argp, rqstp)
X	int *argp;
X	struct svc_req *rqstp;
X{
X	static int res;
X	int	s;
X	struct sockaddr_in	sendaddr, destaddr;
X	int	da_len;
X	int	dummy;
X	short	lport;
X
X	bzero(&res, sizeof res);
X	destaddr = *svc_getcaller(rqstp->rq_xprt);
X	destaddr.sin_port = htons(*argp);
X	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
X		goto bad;
X	setsockopt(s, SOL_SOCKET, SO_LINGER, 0, 0);
X	bzero((char *) &sendaddr, sizeof sendaddr);
X	/* find a reserved port */
X	lport = IPPORT_RESERVED - 1;
X	sendaddr.sin_family = AF_INET;
X	sendaddr.sin_addr.s_addr = INADDR_ANY;
X	for (;;)
X	{
X		sendaddr.sin_port = htons((u_short)lport);
X		if (bind(s, &sendaddr, sizeof sendaddr) >= 0)
X			break;
X		if (errno != EADDRINUSE && EADDRNOTAVAIL)
X			goto bad;
X		lport--;
X		if (lport <= IPPORT_RESERVED / 2)
X			/* give up */
X			break;
X	}
X	if (sendto(s, &dummy, sizeof dummy, 0, &destaddr, sizeof destaddr) < 0)
X		goto bad;
X
X	close(s);
X	res = 0;
X	return (&res);
X    bad:
X	close(s);
X	res = errno == 0 ? -1 : errno;
X	return (&res);
X}
X
Xint *
Xname_uid_1(argp, rqstp)
X	ugname *argp;
X	struct svc_req *rqstp;
X{
X	static int res;
X	struct passwd	*pw;
X
X	bzero(&res, sizeof(res));
X	alarm(idle_limit);
X	if ((pw = getpwnam(*argp)) == NULL)
X		res = NOBODY;
X	else
X		res = pw->pw_uid;
X
X	return (&res);
X}
X
X
Xint *
Xgroup_gid_1(argp, rqstp)
X	ugname *argp;
X	struct svc_req *rqstp;
X{
X	static int res;
X	struct group	*gr;
X
X	bzero(&res, sizeof(res));
X	alarm(idle_limit);
X	if ((gr = getgrnam(*argp)) == NULL)
X		res = NOBODY;
X	else
X		res = gr->gr_gid;
X
X	return (&res);
X}
X
X
Xugname *
Xuid_name_1(argp, rqstp)
X	int *argp;
X	struct svc_req *rqstp;
X{
X	static ugname res;
X	struct passwd	*pw;
X
X	bzero(&res, sizeof(res));
X	alarm(idle_limit);
X	if ((pw = getpwuid(*argp)) == NULL)
X		res = NULL;
X	else
X		res = pw->pw_name;
X
X	return (&res);
X}
X
X
Xugname *
Xgid_group_1(argp, rqstp)
X	int *argp;
X	struct svc_req *rqstp;
X{
X	static ugname res;
X	struct group	*gr;
X
X	bzero(&res, sizeof(res));
X	alarm(idle_limit);
X	if ((gr = getgrgid(*argp)) == NULL)
X		res = NULL;
X	else
X		res = gr->gr_name;
X
X	return (&res);
X}
________This_Is_The_END________
if test `wc -l < ugidd.c` -ne 178; then
	echo 'shar: ugidd.c was damaged during transit (should have been 178 bytes)'
fi
fi		; : end of overwriting check
echo 'x - unfsd.8'
if test -f unfsd.8; then echo 'shar: not overwriting unfsd.8'; else
sed 's/^X//' << '________This_Is_The_END________' > unfsd.8
X.TH UNFSD 8 "11 May 1988"
X.SH NAME
Xunfsd, unfsmntd \- user-level NFS daemons
X.SH SYNOPSIS
X.nf
X.B /etc/unfsd [-f exports-file] [-p] [-o option-string]
X.LP
X.ft B
X.B /etc/unfsmntd
X.fi
X.SH DESCRIPTION
X.IX  "user-level network file system"  "unfsd daemon"  ""  "\fLunfsd\fP daemon"
X.IX  "user-level network file system"  "unfsmntd daemon"  ""  "\fLunfsmntd\fP daemon"
X.IX  "user-level unfsd daemon"  ""  "\fLunfsd\fP daemon"
X.IX  "unfsmntd daemon"  ""  "\fLunfsmntd\fP daemon"
X.IX  "daemons"  "unfsd daemon"  ""  "\fLunfsd\fP daemon"
X.IX  "daemons"  "unfsmntd daemon"  ""  "\fLunfsmntd\fP daemon"
X.I unfsd
Xstarts a
Xdaemon that handles client filesystem requests.
XUnlike nfsd(8), unfsd operates as a normal user-level process and can be run
Xon standard 4.3BSD systems.
XThe server also differs from nfsd(8) in that it mounts an entire file
Xhierarchy, not limited by the boundaries of physical file-systems.
XThe currently implementation only allows the clients read access to the
Xfile hierarchy of the server machine.
X.LP
X.I unfsmntd
Xstarts
Xan ancillary user-level mount daemon.
X.LP
X.IR Options .
XThe
X.B -f
Xoption specifies the exports file, listing the clients that this server
Xis prepared to serve and parameters to apply to each such mount (see
Xunfsd_exports(5)).
XBy defualt exports are read from
X.IR /etc/unfsd_exports .
XThe
X.B -p
Xoption puts the server into promiscuous mode where it will serve any host
Xon the network.
XThe
X.B -o
Xoption specifies default mount parameters in the same format as those appearing
Xin the
X.I unfsd_exports
Xfile.
X.SH "SEE ALSO"
Xunfsd_exports(5)
Xugidd(8C)
X.BUGS
XThe current implementation only allows read access to file-systems.
________This_Is_The_END________
if test `wc -l < unfsd.8` -ne 54; then
	echo 'shar: unfsd.8 was damaged during transit (should have been 54 bytes)'
fi
fi		; : end of overwriting check
echo 'x - unfsd.c'
if test -f unfsd.c; then echo 'shar: not overwriting unfsd.c'; else
sed 's/^X//' << '________This_Is_The_END________' > unfsd.c
X/* UNFSD - copyright Mark A Shand, May 1988.
X * This software maybe be used for any purpose provided
X * the above copyright notice is retained.  It is supplied
X * as is, with no warranty expressed or implied.
X */
X
X#include "unfsd.h"
X
Xstatic struct timeval TIMEOUT = { 25, 0 };
X
X/* ====================================================================== */
X#ifdef DEBUG
XFILE *debuglog = NULL;
Xstatic char *pname = "unfsd";
Xstatic char argbuf[1024];
X
Xlogcall(name, arg, rqstp)
Xchar	*name;
Xchar	*arg;
Xstruct svc_req	*rqstp;
X{
X	int	i;
X
X	if (debuglog == NULL)
X	{
X		unsigned long tloc;
X		if ((debuglog = fopen("/tmp/unfsd.log", "w")) == NULL)
X			return;
X		setlinebuf(debuglog);
X		time(&tloc);
X		fprintf(debuglog, "\n\nstarting %s at %s\n", pname, ctime(&tloc));
X	}
X	fprintf(debuglog, "%s [%d ", name, rqstp->rq_cred.oa_flavor);
X	if (rqstp->rq_cred.oa_flavor == AUTH_UNIX)
X	{
X		struct authunix_parms *unix_cred;
X		struct tm *tm;
X		unix_cred = (struct authunix_parms *) rqstp->rq_clntcred;
X		tm = localtime(&unix_cred->aup_time);
X		fprintf(debuglog, "%d/%d/%d %02d:%02d:%02d %s %d.%d",
X			tm->tm_year, tm->tm_mon+1, tm->tm_mday,
X			tm->tm_hour, tm->tm_min, tm->tm_sec,
X			unix_cred->aup_machname,
X			unix_cred->aup_uid,
X			unix_cred->aup_gid);
X		if (unix_cred->aup_len > 0)
X		{
X			fprintf(debuglog, "+%d", unix_cred->aup_gids[0]);
X			for (i = 1; i < unix_cred->aup_len; i++)
X				fprintf(debuglog, ",%d",unix_cred->aup_gids[i]);
X		}
X	}
X	fprintf(debuglog, "]\n\t%s\n", arg);
X}
X
X#else
X#define logcall(name, arg, client)
X#define fh_pr(x)	""
X#endif DEBUG
X/* ====================================================================== */
X
Xextern int errno;
X#ifdef DEBUG
Xextern char *sys_errlist[];
X#endif DEBUG
X
Xextern char	*malloc();
X
X
X
X/* ====================================================================== */
X
Xvoid *
Xnfsproc_null_2(argp, rqstp)
X	void *argp;
X	struct svc_req *rqstp;
X{
X	static char res;
X
X	bzero(&res, sizeof(res));
X	logcall("nfsproc_null", "", rqstp);
X	return ((void *)&res);
X}
X
X
Xstatic void
Xinner_getattr(fh, status, attr, stat_optimize, cp, rqstp)
X	nfs_fh		*fh;
X	nfsstat		*status;
X	fattr		*attr;
X	struct stat	*stat_optimize;
X	clnt_param	*cp;
X	struct svc_req	*rqstp;
X{
X	char	*path;
X	struct stat *s;
X	struct stat sbuf;
X
X#ifdef DEBUG
X	if (debuglog)
X		fprintf(debuglog, " inner_getattr");
X#endif
X	if ((path = fh_path(fh, status)) != 0)
X	{
X		if (stat_optimize != NULL)
X			s = stat_optimize;
X		else
X		{
X			s = &sbuf;
X			if (lstat(path, s) < 0)
X				*status = (nfsstat) errno;
X		}
X			
X		attr->type = ft_map[ft_extr(s->st_mode)];
X		attr->mode = s->st_mode;
X		attr->nlink = s->st_nlink;
X		attr->uid = ruid(s->st_uid, cp, rqstp->rq_xprt);
X		attr->gid = rgid(s->st_gid, cp, rqstp->rq_xprt);
X		attr->size = s->st_size;
X		attr->blocksize = s->st_blksize;
X		attr->rdev = s->st_rdev;
X		attr->blocks = s->st_blocks;
X		attr->fsid = 1;
X		attr->fileid = fh_psi(fh);
X		attr->atime.seconds = s->st_atime;
X		attr->mtime.seconds = s->st_mtime;
X		attr->ctime.seconds = s->st_ctime;
X#ifdef DEBUG
X		if (debuglog)
X		{
X			if (*status == NFS_OK)
X			{
X				fprintf(debuglog, " t=%d, m=%o, lk=%d, u/g=%d/%d, sz=%d, bsz=%d",
X					attr->type, attr->mode, attr->nlink,
X					attr->uid, attr->gid, attr->size,
X					attr->blocksize);
X				if (attr->type == NFCHR || attr->type == NFBLK)
X					fprintf(debuglog, " rdev=%d/%d",
X						(attr->rdev>>8)&0xff, attr->rdev&0xff);
X				fprintf(debuglog, "\n  blks=%d, fsid=%d, psi=%d, at=%d, mt=%d, ct=%d\n",
X					attr->blocks, attr->fsid, attr->fileid,
X					attr->atime.seconds,
X					attr->mtime.seconds,
X					attr->ctime.seconds);
X			}
X			else
X				fprintf(debuglog, " >>> %s\n", sys_errlist[(int) *status]);
X		}
X#endif
X	}
X#ifdef DEBUG
X	else if (debuglog)
X		fprintf(debuglog, " failed!\n");
X#endif
X}
X
X
Xattrstat *
Xnfsproc_getattr_2(argp, rqstp)
X	nfs_fh *argp;
X	struct svc_req *rqstp;
X{
X	static attrstat res;
X	clnt_param	*cp;
X
X	bzero(&res, sizeof(res));
X	logcall("nfsproc_getattr", fh_pr(argp), rqstp);
X	if ((cp = knownclient(rqstp)) == NULL)
X	{
X		res.status = NFSERR_ACCES;
X		return (&res);
X	}
X	inner_getattr(argp, &(res.status),
X		&(res.attrstat_u.attributes), NULL, cp, rqstp);
X	return (&res);
X}
X
X
Xattrstat *
Xnfsproc_setattr_2(argp, rqstp)
X	sattrargs *argp;
X	struct svc_req *rqstp;
X{
X	static attrstat res;
X
X	bzero(&res, sizeof(res));
X	logcall("nfsproc_setattr", "", rqstp);
X	if (knownclient(rqstp) == NULL)
X	{
X		res.status = NFSERR_ACCES;
X		return (&res);
X	}
X#ifdef READ_ONLY
X	res.status = NFSERR_ROFS;
X#else
X	not implemented
X#endif
X	return (&res);
X}
X
X
Xvoid *
Xnfsproc_root_2(argp, rqstp)
X	void *argp;
X	struct svc_req *rqstp;
X{
X	static char res;
X
X	bzero(&res, sizeof(res));
X	logcall("nfsproc_root", "", rqstp);
X	return ((void *)&res);
X}
X
X
Xdiropres *
Xnfsproc_lookup_2(argp, rqstp)
X	diropargs *argp;
X	struct svc_req *rqstp;
X{
X	static diropres res;
X	clnt_param	*cp;
X	struct stat	sbuf;
X	struct stat	*sbp = &sbuf;
X
X	bzero(&res, sizeof(res));
X	logcall("nfsproc_lookup", sprintf(argbuf, "fh=%s n=%s", fh_pr(&(argp->dir)), argp->name), rqstp);
X	if ((cp = knownclient(rqstp)) == NULL)
X	{
X		res.status = NFSERR_ACCES;
X		return (&res);
X	}
X	res.status = fh_compose(argp, &(res.diropres_u.diropres.file), &sbp);
X	if (res.status == NFS_OK)
X	{
X		inner_getattr(&(res.diropres_u.diropres.file), &(res.status),
X			&(res.diropres_u.diropres.attributes), sbp, cp,rqstp);
X#ifdef DEBUG
X		if (debuglog && res.status == NFS_OK)
X			fprintf(debuglog, "\tnew_fh = %s\n", fh_pr(&(res.diropres_u.diropres.file)));
X#endif /* DEBUG */
X	}
X	return (&res);
X}
X
X
Xreadlinkres *
Xnfsproc_readlink_2(argp, rqstp)
X	nfs_fh *argp;
X	struct svc_req *rqstp;
X{
X	static readlinkres res;
X	clnt_param	*cp;
X	char	*path;
X
X	bzero(&res, sizeof(res));
X	logcall("nfsproc_readlink", fh_pr(argp), rqstp);
X	if ((cp = knownclient(rqstp)) == NULL)
X	{
X		res.status = NFSERR_ACCES;
X		return (&res);
X	}
X	if ((path = fh_path(argp, &(res.status))) != 0)
X	{
X		int	cc;
X		static char	linkbuf[NFS_MAXPATHLEN];
X
X		errno = 0;
X		if ((cc = readlink(path, linkbuf, NFS_MAXPATHLEN)) < 0)
X			res.status = (nfsstat) errno;
X		else
X		{
X			res.status = NFS_OK;
X			linkbuf[cc] = '\0';
X			res.readlinkres_u.data = linkbuf;
X			if (cp->o.link_relative && linkbuf[0] == '/')
X			{
X				/* prepend ../ sequence.  Note: relies that
X				 * fh_path returns a path containing real
X				 * directories.
X				 */
X				int	slash_cnt = 0;
X				char	*p, *q;
X				for (p = index(path+1, '/'); p != NULL; p = index(p+1, '/'))
X					slash_cnt++;
X				p = linkbuf + strlen(linkbuf);
X				q = p + 3 * slash_cnt - 1;
X				if (q >= linkbuf + NFS_MAXPATHLEN)
X					res.status = NFSERR_NAMETOOLONG;
X				else
X				{
X					while (p >= linkbuf)
X						*q-- = *p--;
X					p = linkbuf;
X					while (slash_cnt-- > 0)
X					{
X						*p++ = '.';	
X						*p++ = '.';	
X						*p++ = '/';	
X					}
X				}
X			}
X		}
X	}
X#ifdef DEBUG
X	if (debuglog)
X	{
X		if (res.status != NFS_OK)
X			fprintf(debuglog, " >>> %s\n", sys_errlist[(int) res.status]);
X		else
X			fprintf(debuglog, " %s\n", res.readlinkres_u.data);
X	}
X#endif /* DEBUG */
X	return (&res);
X}
X
X
Xstatic char iobuf[NFS_MAXDATA];
X
Xreadres *
Xnfsproc_read_2(argp, rqstp)
X	readargs *argp;
X	struct svc_req *rqstp;
X{
X	static readres res;
X	clnt_param	*cp;
X	int	fd;
X
X	bzero(&res, sizeof(res));
X	logcall("nfsproc_read", sprintf(argbuf, "%s @%d for %d", fh_pr(&(argp->file)), argp->offset, argp->count), rqstp);
X	if ((cp = knownclient(rqstp)) == NULL)
X	{
X		res.status = NFSERR_ACCES;
X		return (&res);
X	}
X	if ((fd = fh_fd(&(argp->file), &(res.status), O_RDONLY)) >= 0)
X	{
X		errno = 0;
X		lseek(fd, (long) argp->offset, L_SET);
X		res.readres_u.reply.data.data_val = iobuf;
X		if (!errno)
X			res.readres_u.reply.data.data_len =
X				read(fd, res.readres_u.reply.data.data_val, argp->count);
X		fd_idle(fd);
X		res.status = (nfsstat) errno;
X		if (!errno)
X			inner_getattr(&(argp->file), &(res.status),
X				&(res.readres_u.reply.attributes), NULL, cp, rqstp);
X	}
X	return (&res);
X}
X
X
Xvoid *
Xnfsproc_writecache_2(argp, rqstp)
X	void *argp;
X	struct svc_req *rqstp;
X{
X	static char res;
X
X	bzero(&res, sizeof(res));
X	logcall("nfsproc_writecache", "", rqstp);
X	return ((void *)&res);
X}
X
X
Xattrstat *
Xnfsproc_write_2(argp, rqstp)
X	writeargs *argp;
X	struct svc_req *rqstp;
X{
X	static attrstat res;
X
X	bzero(&res, sizeof(res));
X	logcall("nfsproc_write", sprintf(argbuf, "%s @%d for %d", fh_pr(&(argp->file)), argp->offset, argp->data.data_len), rqstp);
X	if (knownclient(rqstp) == NULL)
X	{
X		res.status = NFSERR_ACCES;
X		return (&res);
X	}
X#ifdef READ_ONLY
X	res.status = NFSERR_ROFS;
X#else /* READ_ONLY */
X	not implemented
X#endif /* READ_ONLY */
X	return (&res);
X}
X
X
Xdiropres *
Xnfsproc_create_2(argp, rqstp)
X	createargs *argp;
X	struct svc_req *rqstp;
X{
X	static diropres res;
X
X	bzero(&res, sizeof(res));
X	logcall("nfsproc_create", sprintf(argbuf, "fh=%s n=%s m=%0o u/g=%d/%d sz=%d", fh_pr(&(argp->where.dir)), argp->where.name, argp->attributes.mode, argp->attributes.uid, argp->attributes.gid, argp->attributes.size), rqstp);
X	if (knownclient(rqstp) == NULL)
X	{
X		res.status = NFSERR_ACCES;
X		return (&res);
X	}
X#ifdef READ_ONLY
X	res.status = NFSERR_ROFS;
X#else /* READ_ONLY */
X	not implemented
X#endif /* READ_ONLY */
X	return (&res);
X}
X
X
Xnfsstat *
Xnfsproc_remove_2(argp, rqstp)
X	diropargs *argp;
X	struct svc_req *rqstp;
X{
X	static nfsstat res;
X
X	bzero(&res, sizeof(res));
X	logcall("nfsproc_remove", "", rqstp);
X	if (!knownclient(rqstp))
X	{
X		res = NFSERR_ACCES;
X		return (&res);
X	}
X	res = NFSERR_ROFS;
X	return (&res);
X}
X
X
Xnfsstat *
Xnfsproc_rename_2(argp, rqstp)
X	renameargs *argp;
X	struct svc_req *rqstp;
X{
X	static nfsstat res;
X
X	bzero(&res, sizeof(res));
X	logcall("nfsproc_rename", "", rqstp);
X	if (!knownclient(rqstp))
X	{
X		res = NFSERR_ACCES;
X		return (&res);
X	}
X	res = NFSERR_ROFS;
X	return (&res);
X}
X
X
Xnfsstat *
Xnfsproc_link_2(argp, rqstp)
X	linkargs *argp;
X	struct svc_req *rqstp;
X{
X	static nfsstat res;
X
X	bzero(&res, sizeof(res));
X	logcall("nfsproc_link", "", rqstp);
X	if (!knownclient(rqstp))
X	{
X		res = NFSERR_ACCES;
X		return (&res);
X	}
X	res = NFSERR_ROFS;
X	return (&res);
X}
X
X
Xnfsstat *
Xnfsproc_symlink_2(argp, rqstp)
X	symlinkargs *argp;
X	struct svc_req *rqstp;
X{
X	static nfsstat res;
X
X	bzero(&res, sizeof(res));
X	logcall("nfsproc_symlink", "", rqstp);
X	if (!knownclient(rqstp))
X	{
X		res = NFSERR_ACCES;
X		return (&res);
X	}
X	res = NFSERR_ROFS;
X	return (&res);
X}
X
X
Xdiropres *
Xnfsproc_mkdir_2(argp, rqstp)
X	createargs *argp;
X	struct svc_req *rqstp;
X{
X	static diropres res;
X
X	bzero(&res, sizeof(res));
X	logcall("nfsproc_mkdir", "", rqstp);
X	if (!knownclient(rqstp))
X	{
X		res.status = NFSERR_ACCES;
X		return (&res);
X	}
X	res.status = NFSERR_ROFS;
X	return (&res);
X}
X
X
Xnfsstat *
Xnfsproc_rmdir_2(argp, rqstp)
X	diropargs *argp;
X	struct svc_req *rqstp;
X{
X	static nfsstat res;
X
X	bzero(&res, sizeof(res));
X	logcall("nfsproc_rmdir", "", rqstp);
X	if (!knownclient(rqstp))
X	{
X		res = NFSERR_ACCES;
X		return (&res);
X	}
X	res = NFSERR_ROFS;
X	return (&res);
X}
X
Xstatic int
Xdpsize(dp)
Xstruct direct *dp;
X{
X#define DP_SLOP	16
X#define MAX_E_SIZE sizeof(entry) + MAXNAMLEN + DP_SLOP
X	return sizeof(entry) + strlen(dp->d_name) + DP_SLOP;
X}
X
Xreaddirres *
Xnfsproc_readdir_2(argp, rqstp)
X	readdirargs *argp;
X	struct svc_req *rqstp;
X{
X	static readdirres res;
X	entry **e;
X	char	*path;
X
X	/*
X	 * Free previous result
X	 */
X	xdr_free(xdr_readdirres, &res);
X
X	bzero(&res, sizeof(res));
X	logcall("nfsproc_readdir", fh_pr(&(argp->dir)), rqstp);
X	if (!knownclient(rqstp))
X	{
X		res.status = NFSERR_ACCES;
X		return (&res);
X	}
X	if ((path = fh_path(argp, &(res.status))) != 0)
X	{
X		long	dloc;
X		DIR	*dirp;
X		struct direct *dp;
X		struct	stat	sbuf;
X
X		errno = 0;
X		stat(path, &sbuf);
X		if ((dirp = opendir(path)) == NULL)
X		{
X			if (errno != 0)
X				res.status = (nfsstat) errno;
X			else
X				res.status = NFSERR_NAMETOOLONG;
X		}
X		else
X		{
X			int	res_size = 0;
X
X			res.status = NFS_OK;
X			bcopy(argp->cookie, &dloc, sizeof(dloc));
X			if (dloc != 0)
X				seekdir(dirp, dloc);
X			e = &(res.readdirres_u.reply.entries);
X			while (((res_size + MAX_E_SIZE) < argp->count
X					 || e == &(res.readdirres_u.reply.entries))
X				 && (dp = readdir(dirp)) != NULL)
X			{
X				if ((*e = (entry *) malloc(sizeof(entry))) == NULL)
X					mallocfailed();
X				(*e)->fileid = pseudo_inode(dp->d_ino, sbuf.st_dev);
X				if (((*e)->name = malloc(strlen(dp->d_name)+1)) == NULL)
X					mallocfailed();
X				strcpy((*e)->name, dp->d_name);
X				dloc = telldir(dirp);
X				bcopy(&dloc, ((*e)->cookie), sizeof(nfscookie));
X				e = &((*e)->nextentry);
X				res_size += dpsize(dp);
X			}
X			*e = NULL;
X			res.readdirres_u.reply.eof = (dp == NULL);
X			closedir(dirp);
X		}
X	}
X	return (&res);
X}
X
X
Xstatfsres *
Xnfsproc_statfs_2(argp, rqstp)
X	nfs_fh *argp;
X	struct svc_req *rqstp;
X{
X	static statfsres res;
X
X	bzero(&res, sizeof(res));
X	logcall("nfsproc_statfs", fh_pr(argp), rqstp);
X	if (!knownclient(rqstp))
X	{
X		res.status = NFSERR_ACCES;
X		return (&res);
X	}
X	/* no easy way to do this */
X	res.status = NFS_OK;
X	res.statfsres_u.reply.tsize = 4096;
X	res.statfsres_u.reply.bsize = 4096;
X	res.statfsres_u.reply.blocks = 100000;
X	res.statfsres_u.reply.bfree = 80000;
X	res.statfsres_u.reply.bavail = 71000;
X	return (&res);
X}
________This_Is_The_END________
if test `wc -l < unfsd.c` -ne 626; then
	echo 'shar: unfsd.c was damaged during transit (should have been 626 bytes)'
fi
fi		; : end of overwriting check
echo 'x - unfsd.h'
if test -f unfsd.h; then echo 'shar: not overwriting unfsd.h'; else
sed 's/^X//' << '________This_Is_The_END________' > unfsd.h
X/* UNFSD - copyright Mark A Shand, May 1988.
X * This software maybe be used for any purpose provided
X * the above copyright notice is retained.  It is supplied
X * as is, with no warranty expressed or implied.
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <sys/param.h>
X#include <sys/types.h>
X#include <sys/file.h>
X#include <sys/dir.h>
X#include <rpc/rpc.h>
X#include <sys/time.h>
X#include <sys/stat.h>
X#include <sys/socket.h>
X#include <sys/ioctl.h>
X#include <netdb.h>
X#include <strings.h>
X#include <syslog.h>
X
X/* mask SUNOS/BSD4.3 syslog incompatibilities */
X#ifndef LOG_DAEMON
X#define	LOG_DAEMON	0
X#endif /* LOG_DAEMON */
X#ifndef LOG_TIME
X#define	LOG_TIME	0
X#endif /* LOG_TIME */
X
X#include "nfs_prot.h"
X#include "ugid.h"
X#include "fh.h"
X
Xtypedef struct options
X{
X	/* uid/gid mapping functions */
X	enum {map_daemon, identity}	uidmap;
X	int	root_squash;
X	/* client options */
X	int	secure_port;
X	int	read_only;
X	int	link_relative;
X}
X	options;
X
Xtypedef struct clnt_param
X{
X	struct clnt_param	*next;
X
X	struct in_addr	clnt_addr;
X	char	*clnt_name;
X	char	*mount_point;
X	options	o;
X}
X	clnt_param;
X
Xextern ftype ft_map[16];
Xextern int svc_euid;
Xextern int svc_egid;
Xextern int cur_gid;
Xextern int svc_ngids;
Xextern int svc_gids[NGROUPS+2];
X
X#define ft_extr(x)	((x & S_IFMT) >> 12)
X#define in_gid_set(gid)	((gid) == cur_gid || _in_gid_set(gid))
X
Xextern int _in_gid_set();
Xextern clnt_param *knownclient();
________This_Is_The_END________
if test `wc -l < unfsd.h` -ne 68; then
	echo 'shar: unfsd.h was damaged during transit (should have been 68 bytes)'
fi
fi		; : end of overwriting check
echo 'x - unfsd_exports.5'
if test -f unfsd_exports.5; then echo 'shar: not overwriting unfsd_exports.5'; else
sed 's/^X//' << '________This_Is_The_END________' > unfsd_exports.5
X.\" @(#)exports.5 1.3 86/08/02 SMI;
X.TH UNFSD_EXPORTS 5 "11 April 1988"
X.SH NAME
Xunfsd_exports \- NFS file systems being exported by user-level NFS server
X.SH SYNOPSIS
X.B /etc/unfsd_exports
X.SH DESCRIPTION
X.IX  "NFS exported file systems"  ""  "NFS exported file systems \(em \fLexports\fP"
XThe file
X.I /etc/unfsd_exports
Xdescribes the file systems which are being exported to 
Xnfs clients.
XIt is processed by the
X.I user-level NFS
Xdaemon
X.IR unfsd (8C)
Xwhen the daemon is started.
X.PP
XThe file format is similar to that of the SunOS
X.I exports
Xfile.
XThe file is organized by lines.
XA # introduces a comment to the end of the line,
Xa \e preceding a new line disables the line break making the entry of
Xlong input lines more convenient.
XEach line consists of a mount point
Xand list of machine names
Xallowed to remote mount the server's file hierarchy at that mount point.
XA machine name is optionally followed by a list of mount parameters
Xenclosed in parentheses.
XThese are the parameters that are currently recognized.
X.ds d " *
X.ds n " +
X.TP 20
Xsecure\*d
XReject requests that originate on an internet port \(>= IPPORT_RESERVED.
X.TP 20
Xinsecure
XAccept requests originating on any port.
X.TP 20
Xroot_squash
XMap requests from uid 0 on the client to uid -2 on the server.
X.TP 20
Xno_root_squash\*d
XDon't map requests from uid 0.
X.TP 20
Xro\*d
XMount file hierarchy read-only.
X.TP 20
Xrw\*n
XMount file hierarchy read-write.
X.TP 20
Xlink_relative\*d
XConvert symbolic links starting with a slash into relative links
Xby prepending the necessary number of ../'s to get from the link directory
Xto the file hierarchy root on the server.
X.TP 20
Xlink_absolute
XLeave symbolic links starting with a slash as they are.
X.TP 20
Xmap_identity\*d
XAssume the client and server share the same uid/gid space.
X.TP 20
Xmap_daemon
XMap local and remote names and numeric ids using a lname/uid map
Xdaemon on the client from which the NFS
Xrequest originated, to map between the client and server uid spaces
X(see ugidd(8)).
X.PP
X(\*d indicates defaults,\*n indicates currently unimplemented features)
X.SH EXAMPLE
X.PP
X.ft CW
X.nf
X  /     snail whelk(map_identity) tusk(root_squash, map_daemon, ro)
X  /usr  usage(root_squash, map_daemon, ro)
X.fi
X.SH FILES
X/etc/unfsd_exports
X.SH SEE ALSO
Xmountd(8C)
Xunfsd(8C)
Xugidd(8C)
X.SH BUGS
XThe mount point at the start of each line is currently ignored.
XAuthorized clients may mount at any point in the server's hierarchy.
________This_Is_The_END________
if test `wc -l < unfsd_exports.5` -ne 86; then
	echo 'shar: unfsd_exports.5 was damaged during transit (should have been 86 bytes)'
fi
fi		; : end of overwriting check
echo 'x - unfsmntd.c'
if test -f unfsmntd.c; then echo 'shar: not overwriting unfsmntd.c'; else
sed 's/^X//' << '________This_Is_The_END________' > unfsmntd.c
X/* UNFSD - copyright Mark A Shand, May 1988.
X * This software maybe be used for any purpose provided
X * the above copyright notice is retained.  It is supplied
X * as is, with no warranty expressed or implied.
X */
X
X#include <errno.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <rpc/rpc.h>
X#include <sys/time.h>
X#include <sys/ioctl.h>
X#include "mount.h"
X
Xstatic struct timeval TIMEOUT = { 25, 0 };
X
X#ifdef DEBUG
X#include <ctype.h>
X#include <stdio.h>
Xstatic FILE *debuglog = NULL;
Xstatic char *pname = "umountd";
Xstatic char argbuf[512];
X
Xlogcall(name, arg, rqstp)
Xchar	*name;
Xchar	*arg;
Xstruct svc_req	*rqstp;
X{
X	int	i;
X
X	if (debuglog == NULL)
X	{
X		unsigned long tloc;
X		if ((debuglog = fopen("/tmp/umountd.log", "a+")) == NULL)
X			return;
X		time(&tloc);
X		fprintf(debuglog, "\n\nstarting %s at %s\n", pname, ctime(&tloc));
X	}
X	fprintf(debuglog, "%s [ %d %d ",
X		name,
X		rqstp->rq_cred.oa_flavor,
X		rqstp->rq_cred.oa_length);
X	if (rqstp->rq_cred.oa_flavor == AUTH_UNIX)
X	{
X		struct authunix_parms *unix_cred;
X		unix_cred = (struct authunix_parms *) rqstp->rq_clntcred;
X		fprintf(debuglog, "%.24s %s %d.%d ",
X			ctime(&unix_cred->aup_time),
X			unix_cred->aup_machname,
X			unix_cred->aup_uid,
X			unix_cred->aup_gid);
X		if (unix_cred->aup_len > 0)
X		{
X			for (i = 0; i < unix_cred->aup_len; i++)
X				fprintf(debuglog, "%c%d", (i==0?'(':','),
X					unix_cred->aup_gids[i]);
X			fprintf(debuglog, ") ");
X		}
X	}
X	fprintf(debuglog, "]\n\t%s\n", arg);
X	fflush(debuglog);
X	return 0;
X}
X#else
X#define logcall(name, arg, client)
X#endif DEBUG
X
Xint
Xunfsmntd_init()
X{
X#ifndef DEBUG
X	int fd;
X
X	if (fork())
X		exit(0);
X	close(0);
X	close(1);
X	close(2);
X	if ((fd = open("/dev/tty", 2)) >= 0)
X	{
X		ioctl(fd, TIOCNOTTY, (char *)0);
X		(void) close(fd);
X	}
X#endif DEBUG
X	fh_init();
X}
X
Xvoid *
Xmountproc_null_1(argp, rqstp)
X	void *argp;
X	struct svc_req *rqstp;
X{
X	static char res;
X
X	bzero(&res, sizeof(res));
X	logcall("mountproc_null_1", "", rqstp);
X	return ((void *)&res);
X}
X
X
Xfhstatus *
Xmountproc_mnt_1(argp, rqstp)
X	dirpath *argp;
X	struct svc_req *rqstp;
X{
X	static fhstatus res;
X	struct stat stbuf;
X	extern int errno;
X
X	bzero(&res, sizeof(res));
X	logcall("mountproc_mnt_1", sprintf(argbuf, "%s", *argp), rqstp);
X	if (stat(*argp, &stbuf) < 0)
X		res.fhs_status = errno;
X	else if ((stbuf.st_mode & S_IFMT) != S_IFDIR)
X		res.fhs_status = ENOTDIR;
X	else
X	{
X		res.fhs_status = 0;
X		res.fhs_status = fh_create(&(res.fhstatus_u.fhs_fhandle),*argp);
X	}
X	return (&res);
X}
X
X
Xmountlist *
Xmountproc_dump_1(argp, rqstp)
X	void *argp;
X	struct svc_req *rqstp;
X{
X	static mountlist res;
X
X	bzero(&res, sizeof(res));
X	logcall("mountproc_dump_1", "", rqstp);
X	return (&res);
X}
X
X
Xvoid *
Xmountproc_umnt_1(argp, rqstp)
X	dirpath *argp;
X	struct svc_req *rqstp;
X{
X	static char res;
X
X	bzero(&res, sizeof(res));
X	logcall("mountproc_umnt_1", sprintf(argbuf, "%s", *argp), rqstp);
X	return ((void *)&res);
X}
X
X
Xvoid *
Xmountproc_umntall_1(argp, rqstp)
X	void *argp;
X	struct svc_req *rqstp;
X{
X	static char res;
X
X	bzero(&res, sizeof(res));
X	logcall("mountproc_umntall_1", "", rqstp);
X	return ((void *)&res);
X}
X
X
Xexports *
Xmountproc_export_1(argp, rqstp)
X	void *argp;
X	struct svc_req *rqstp;
X{
X	static exports res;
X	static groupnode resgr;
X
X	bzero(&res, sizeof(res));
X	logcall("mountproc_export_1", "", rqstp);
X	res.ex_dir = "/";
X	res.ex_groups = &resgr;
X	bzero(&resgr, sizeof(resgr));
X	resgr.gr_name = "mollusca";
X	resgr.gr_next = (groups *) 0;
X	res.ex_next = (exports *) 0;
X	return (&res);
X}
X
X
Xexports *
Xmountproc_exportall_1(argp, rqstp)
X	void *argp;
X	struct svc_req *rqstp;
X{
X	logcall("mountproc_exportall_1", "", rqstp);
X	return (mountproc_export_1(argp, rqstp));
X}
________This_Is_The_END________
if test `wc -l < unfsmntd.c` -ne 191; then
	echo 'shar: unfsmntd.c was damaged during transit (should have been 191 bytes)'
fi
fi		; : end of overwriting check
exit 0