Intial commit

This commit is contained in:
Mario Fetka
2024-05-27 16:13:40 +02:00
parent f8dc12b10a
commit d71d446104
2495 changed files with 539746 additions and 0 deletions

7
prospero/lib/FILES Normal file
View File

@@ -0,0 +1,7 @@
FILES
FILES.ftp-only
ardp
filters
pcompat
pfs
psrv

View File

@@ -0,0 +1,4 @@
FILES.ftp-only
ardp
pfs
psrv

1
prospero/lib/ardp/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
Makefile

32
prospero/lib/ardp/FILES Normal file
View File

@@ -0,0 +1,32 @@
FILES
Makefile
ardp.doc
ardp_abort.c
ardp_accept.c
ardp_add2req.c
ardp_breply.c
ardp_error.c
ardp_get_nxt.c
ardp_headers.c
ardp_int_err.c
ardp_mutexes.c
ardp_perrno.c
ardp_pr_actv.c
ardp_ptalloc.c
ardp_reply.c
ardp_respond.c
ardp_retriev.c
ardp_rqalloc.c
ardp_send.c
ardp_showbuf.c
ardp_snd_pkt.c
ardp_srv_ini.c
ardp_xmit.c
dnscache_alloc.c
dnscache_alloc.h
flocks.c
flocks.h
hostname2adr.c
p__th_self_num.c
unixerrstr.c
usc_lic_str.c

246
prospero/lib/ardp/Makefile.in Executable file
View File

@@ -0,0 +1,246 @@
#
# Makefile for Prospero Directory Service ARDP library.
SOURCEBASE = ../..
include $(SOURCEBASE)/Makefile.config
CFLAGS += -I$(ARCHIE_ROOT)/include
CFILES = ardp_abort.c \
ardp_accept.c \
ardp_add2req.c \
ardp_breply.c \
ardp_error.c \
ardp_get_nxt.c \
ardp_headers.c \
ardp_int_err.c \
ardp_mutexes.c \
ardp_perrno.c \
ardp_pr_actv.c \
ardp_ptalloc.c \
ardp_reply.c \
ardp_respond.c \
ardp_retriev.c \
ardp_rqalloc.c \
ardp_send.c \
ardp_showbuf.c \
ardp_snd_pkt.c \
ardp_srv_ini.c \
ardp_xmit.c \
dnscache_alloc.c \
flocks.c \
hostname2adr.c \
p__th_self_num.c \
restrict.c \
unixerrstr.c \
usc_lic_str.c
OBJECTS = ardp_abort.o \
ardp_accept.o \
ardp_add2req.o \
ardp_breply.o \
ardp_error.o \
ardp_get_nxt.o \
ardp_headers.o \
ardp_int_err.o \
ardp_mutexes.o \
ardp_perrno.o \
ardp_pr_actv.o \
ardp_ptalloc.o \
ardp_reply.o \
ardp_respond.o \
ardp_retriev.o \
ardp_rqalloc.o \
ardp_send.o \
ardp_showbuf.o \
ardp_snd_pkt.o \
ardp_srv_ini.o \
ardp_xmit.o \
dnscache_alloc.o \
flocks.o \
hostname2adr.o \
p__th_self_num.o \
restrict.o \
unixerrstr.o \
usc_lic_str.o
all: ${RDP_LIB}
install:
cp ${RDP_LIB} ${P_BINARIES}/${RDP_LIB}
$(RANLIB) ${P_BINARIES}/${RDP_LIB}
${RDP_LIB}: ${OBJECTS}
rm -f ${RDP_LIB}
ar r${AR_FLAGS} ${RDP_LIB} ${OBJECTS}
$(RANLIB) ${RDP_LIB}
# Dependencies
ardp_abort.o : ../../include/posix_signal.h \
../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h ../../include/implicit_fixes.h \
../../include/ardp.h \
../../include/../lib/ardp/flocks.h \
../../include/pfs.h ../../include/pmachine.h
ardp_accept.o : \
../../include/ardp.h \
../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/pserver.h ../../include/plog.h \
../../include/pprot.h
ardp_add2req.o : \
../../include/ardp.h \
../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h
ardp_breply.o : \
../../include/ardp.h ../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h
ardp_error.o : ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/perrno.h
ardp_get_nxt.o : \
../../include/ardp.h ../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h
ardp_headers.o : \
../../include/ardp.h ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h
ardp_int_err.o : ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h
ardp_mutexes.o : ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/ardp.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h
ardp_perrno.o : ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h
ardp_pr_actv.o : \
../../include/ardp.h \
../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/perrno.h
ardp_ptalloc.o : \
../../include/ardp.h \
../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/mitra_macros.h
ardp_reply.o : \
../../include/ardp.h ../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h
ardp_respond.o : \
../../include/ardp.h \
../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/plog.h
ardp_retriev.o : \
../../include/ardp.h ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/perrno.h
ardp_rqalloc.o : \
../../include/ardp.h ../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h
ardp_send.o : \
../../include/ardp.h ../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/perrno.h ../../include/pcompat.h
ardp_showbuf.o :
ardp_snd_pkt.o : \
../../include/ardp.h ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/plog.h \
../../include/perrno.h
ardp_srv_ini.o : \
../../include/ardp.h \
../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/plog.h
ardp_xmit.o : \
../../include/ardp.h \
../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h
dnscache_alloc.o : dnscache_alloc.h ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/mitra_macros.h
flocks.o : ../../include/pfs.h ../../include/pfs_utils.h \
../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/plog.h \
flocks.h ../../include/mitra_macros.h
hostname2adr.o : ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/perrno.h ../../include/string_with_strcasecmp.h \
../../include/pserver.h dnscache_alloc.h ../../include/pcompat.h \
../../include/mitra_macros.h
p__th_self_num.o : ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/ardp.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h
unixerrstr.o : ../../include/pmachine.h
usc_lic_str.o :

85
prospero/lib/ardp/Makefile.tmp Executable file
View File

@@ -0,0 +1,85 @@
#
# Makefile for Prospero Directory Service ARDP library.
SOURCEBASE = ../..
include $(SOURCEBASE)/Makefile.config
CFILES = ardp_abort.c \
ardp_accept.c \
ardp_add2req.c \
ardp_breply.c \
ardp_error.c \
ardp_get_nxt.c \
ardp_headers.c \
ardp_int_err.c \
ardp_mutexes.c \
ardp_perrno.c \
ardp_pr_actv.c \
ardp_ptalloc.c \
ardp_reply.c \
ardp_respond.c \
ardp_retriev.c \
ardp_rqalloc.c \
ardp_send.c \
ardp_showbuf.c \
ardp_snd_pkt.c \
ardp_srv_ini.c \
ardp_xmit.c \
dnscache_alloc.c \
flocks.c \
hostname2adr.c \
p__th_self_num.c \
unixerrstr.c \
usc_lic_str.c
OBJECTS = ardp_abort.o \
ardp_accept.o \
ardp_add2req.o \
ardp_breply.o \
ardp_error.o \
ardp_get_nxt.o \
ardp_headers.o \
ardp_int_err.o \
ardp_mutexes.o \
ardp_perrno.o \
ardp_pr_actv.o \
ardp_ptalloc.o \
ardp_reply.o \
ardp_respond.o \
ardp_retriev.o \
ardp_rqalloc.o \
ardp_send.o \
ardp_showbuf.o \
ardp_snd_pkt.o \
ardp_srv_ini.o \
ardp_xmit.o \
dnscache_alloc.o \
flocks.o \
hostname2adr.o \
p__th_self_num.o \
unixerrstr.o \
usc_lic_str.o
all: ${RDP_LIB}
install:
cp ${RDP_LIB} ${P_BINARIES}/${RDP_LIB}
$(RANLIB) ${P_BINARIES}/${RDP_LIB}
${RDP_LIB}: ${OBJECTS}
rm -f ${RDP_LIB}
ar r${AR_FLAGS} ${RDP_LIB} ${OBJECTS}
$(RANLIB) ${RDP_LIB}
# Dependencies
setdependencies:
gcc -M $(CFLAGS) $(CFILES) | sed \
-e 's, [^ ]*\.c,,' \
-e 's, /local/gnu/[^ ]*,,g' \
-e 's, /usr/include/[^ ]*,,g' \
-e 's, [./]*include/pthread\.h,,' \
-e 's, [./]*include/pthread/[^ ]*,,g' \
-e 's, [^ ]*/fsu_pthreads/include/[^ ]*,,g' \
-e 's, [./]*include/usc-copyr\.h,,' \
-e 's, [./]*include/usc-license\.h,,' \
-e 's, [./]*include/uw-copyright\.h,,' \
-e '/^[ ]*\\$$/d' | fixdep > dependency.list

262
prospero/lib/ardp/ardp.doc Normal file
View File

@@ -0,0 +1,262 @@
To use the library, include the file <ardp.h>.
The current release has dependencies upon Prospero in a few places:
If you will not be using the Prospero pauth structure, undefine
PROSPERO in ardp.h. The RREQ structure includes a reference to PAUTH
by default.
The ARDP library server routines currently call the Prospero function
plog(). A useful future direction is to make the logging function
application-specific, and inactive by default.
The ardp_reply_bst() function depends upon Propero bstrings. It will
not be included in the library if PROSPERO is not defined in ardp.h.
---
Error handling: ARDP library functions return error codes between 1
and 20. A return value of 0 is ARDP_SUCCESS. In addition, the global
variable
extern int perrno;
is generally set to the number of the error. (We haven't actually
checked every function in the ARDP library to guarantee this). This
global variable is used in the ARDP library, and in the PFS library.
The function p_clear_errors() should be called from your application
to clear this error indication. If you've linked with the PFS library
version, then p_clear_errors() will also clear Prospero error and
warning indications. This function is defined both in the PFS library
and in the ARDP library; if you're a PFS library and an ARDP library
user, place the PFS library version first in your link path. Its
declaration is:
extern void p_clear_errors(void);
Printed strings associated with these errors can be found in
lib/pfs/perrmesg.c. These are not currently available through the
ARDP library interface, although it does not depend upon them being
present. A future direction is to make these strings available
through the RDP library interface.
--
The ARDP library is now completely safe for sending arbitrary
length-coded binary data. (Until Prospero release Alpha.5.3, this was
not the case -- the server library used to append nulls to packets.)
--
Notes on the PTEXT structure:
The PTEXT structure has two members, ->text and ->start. On the user
side, they are currently always the same; however, this is not always
guaranteed to be the case in future releases of the ARDP library.
->text is used for the start of data to be parsed by the higher-level
application (e.g., Prospero). The ->length member of the PTEXT
structure is relative to ->start, which in this case is the same as
->text, but which is not guaranted to be so. Thus, if you need the
length of the text (relative to the start of ->text), it is ->length -
(->text - ->start).
--
Notes on the functions:
In the functions that follow, more details on the function can be
found in the header preceding the function in the source code. This
documentation is solely for the purpose of helping you decide which
functions to look at. (Another way of saying that we are well aware
that this manual is pretty sketchy.) Functions in the library that
are not described here should be considered internal and should not be
called by the application.
The following functions are exported by the ardp library for use by
the client side of a connection:
ardp_abort(req) Aborts the specified request, sending an
abort message to the server if currently
active. If req is null, will send aborts
to servers for all active requests.
ardp_abort_on_int() Sets interrupt handler to abort any
pending requests.
ardp_pr_active() Processes new responses to active requests.
If making an asynchronous request (i.e. ttwait
does not equal ARDP_WAIT_TILL_TO), then this
function must be called periodically, either
automatically within ardp_retrieve, explicitly,
or initiated by an interrupt when
a response becomes available on the UDP port.
ardp_retrieve(req,ttwait)
Poll for, or wait for a pending request to
complete.
ardp_send(req,dname,dest,ttwait)
Sends request to host with domain name
or socket address dest, and waits ttwait
microseconds for response (-1 means till timeout).
ardp_set_retry(to,rt) Set retry time out (seconds) and count
The following functions are exported by the ardp library for use by
the server side of a connection:
ardp_accept() Accepts new requests and places on appropriate
queues for subsequent processing. This must
be called periodically, either explicitly, or
initiated by an interrupt when a request
becomes available on the UDP port.
ardp_bind_port(portname)
Takes the name of (or #number) of a port to
be opened, on which the server will listen
for requests.
RREQ ardp_get_nxt() Returns the next request to be processed.
If none available, it will block until
one is received.
ardp_redirect(req,target)
Sends a redirect to the client indicating the
the request should be sent to a new target
server identified in the second argument.
ardp_respond(req,opt) Used by a server to send the current response
packet once filled in. It will add the packet
to the transmission queue, and send it. To
indicate completion of a response, the
ARDP_RESP_COMPLETE option should be specified.
If the ARDP_RESP_NOSEND option is specified,
the packet will be added to the transmission queue
but not sent.
ardp_refuse(req) Causes the specified request to be refused and
notification sent to the client.
ardp_reply(req,flags,message)
Queues message (appending it to the req structure)
and possibly sends it and other queued data to the
client. Will call ardp_respond() if any
completed packets can be sent (i.e., sends a
partial response to speed up client/server
interaction). Message is a null-terminated buffer.
Can't use this interface to send binary data
that might contain nulls; see
ardp_reply_bst() below.
ardp_rwait(req,timetowait,qpos,stime)
This function is called by a server to specify
a server requested time to wait for a response.
This value is returned to the client which
will treat it as an acknowledgment and will
defer subsequent timeouts and retries until
waiting the specified period. Non-zero values
for qpos and stime will cause the current
the specified queue position and expected
system time to be provided to the client in
the same message.
ardp_set_queuing_policy(pf,override)
Sets a function used to determine queue
ordering on the server.
ardp_set_prvport(fd) Sets a file descriptor that has already been
opened as the input port on which the server
will listen for requests.
The following functions are exported by the ardp library for use by
both the client and server sides of a connection:
ardp_add2req(req,flags,buf,len)
Adds text to a request which will subsequently
be sent to the peer, and returns.
RREQ ardp_rqalloc() Allocate a new request structure
ardp_rqfree(req) Free a request structure
ardp_rqlfree(req) Free a list of request structures
PTEXT ardp_ptalloc() Allocate a new packet structure
ardp_ptfree(pkt) Free a packet structure
ardp_ptlfree(pkt) Free a list of packet structures
/********************/
Internal functions:
ardp_showbuf() is used to display buffers that might contain
nulls.
/******************/
Eventually to be built on top of the above:
rd_sbuf Synchronously send a buffer to a destination
rd_sbufa Asynchronously send a buffer to a destination
rd_sync Wait until all pending requests are complete
/********************/
The ARDP library respects the global integer variable pfs_debug.
Levels of 9 or above cause the text of packets sent across the network
to be displayed to stderr.
As of Prospero Alpha.5.3 release, an ARDP library pfs_debug level of
11 or greater will cause \n and \t and \r to be printed as \n and \t
and \r in the display of the contents of ARDP packets. Levels 9 and
10 cause them to be displayed as themselves. All other control
characters in packets are now displayed as a \ followed by the
character's octal code. (In previous releases, they were displayed as
literal text, and nulls in the packet caused the display of the packet
text to be ignored.)
/*************/
The new ARDP_REPLY_BST() function accepts a Prospero BSTRING as its
argument. This violates modularity of the ARDP library, since it
requires the ARDP library to know about the bstrings layer. We need a
new interface to ardp_reply() that will accept a length-coded buffer,
and then a wrapper around it in the pfs library that will accept the
bstring. Future directions for this function are noted at ISI in
/nfs/pfs/notes/ardp-directions.
ardp_reply_bst(RREQ req, /* Request to which this is a response */
int flags, /* Whether this is the final message */
char *message) /* The data to be sent. Must be a bstring. */
/**** BUGS & future directions *****/
ardp_retrieve() and ardp_send() both call p_clear_errors() internally.
This is inconsistent with the behavior of the rest of the ARDP library
and of most of the PFs library, which do not clear error indications
themselves.
Look over ardp.h.
-Make it independent of Prospero directory service: Put authentication
stuff into ardp.h as a formal library. Alternatively, make the
directory service use the 'app' optional member. (at least until the
authentication stuff is better defined).
Make sure the app optional member is defined and explained in the ARDP stuff.
-Get rid of #define PROSPERO in ardp.h
-ARDP_DEFAULT_PEER and ARDP_DEFAULT_PORT must become optional
constants.
Change the ardp library interface so that the logging function is
specified at runtime initialization.
ardp_reply should have the interface changed to accept a message
length, just like ardp_add2req() does. Ditto any other functions in the
libardp interface that expect just null terminated buffers. The ARDP
library should be better documented for potential programmers.
Fix bug: ardp_respond() expects trailing null on buffer
ardp_add2req() hands. (this is on the SWA todo list as a separate
item).
SWA has rewritten ardp_add2req on paper; need to type in these
simplifying changes.

View File

@@ -0,0 +1,109 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-copyr.h>.
*
* Written by bcn 1/93 to abort pending requests
*/
#include <usc-copyr.h>
#include <posix_signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pfs_threads.h>
#include <list_macros.h>
#include <implicit_fixes.h>
#include <ardp.h>
#include <pmachine.h>
extern RREQ ardp_activeQ; /* Info about active requests */
extern int ardp_port; /* Opened UDP port */
extern int pfs_debug; /* Debug level */
extern int ardp_activeQ_len; /* Length of ardp_activeQ */
/*
* ardp_abort - abort a pending request
*
* ardp_abort takes a pointer to a request structure of a request to
* be aborted, sends an abort request to the server handling the pending,
* request, and immediately returns. If the request is null (NOREQ), then
* all requests on the ardp_activeQ are aborted.
*/
int
ardp_abort(req)
RREQ req; /* Request to be aborted */
{
PTEXT ptmp = NOPKT; /* Abort packet to be sent */
RREQ rtmp = NOREQ; /* Current request to abort */
int ns; /* Number of bytes actually sent */
if(req && (req->status != ARDP_STATUS_ACTIVE)) return(ARDP_BAD_REQ);
if(req) rtmp = req;
else rtmp = ardp_activeQ;
ptmp = ardp_ptalloc();
/* Add header */
ptmp->start -= 13;
ptmp->length += 13;
*(ptmp->start) = (char) 13;
/* An unsequenced control packet */
bzero(ptmp->start+3,10);
/* Cancel flag */
*(ptmp->start+12) = 0x01;
while(rtmp) {
bcopy2(&(rtmp->cid),ptmp->start+1);
if (pfs_debug >= 6) {
if(rtmp->peer.sin_family == AF_INET)
fprintf(stderr,"\nSending abort message (cid=%d) to %s(%d)...",
ntohs(rtmp->cid),inet_ntoa(rtmp->peer_addr),PEER_PORT(rtmp));
else fprintf(stderr,"\nSending abort message...");
(void) fflush(stderr);
}
ns = sendto(ardp_port,(char *)(ptmp->start), ptmp->length, 0,
&(rtmp->peer), S_AD_SZ);
if(ns != ptmp->length) {
if (pfs_debug) {
fprintf(stderr,"\nsent only %d/%d: ",ns, ptmp->length);
perror("");
}
ardp_ptfree(ptmp);
return(ARDP_NOT_SENT);
}
if (pfs_debug >= 6) fprintf(stderr,"Sent.\n");
rtmp->status = ARDP_STATUS_ABORTED;
EXTRACT_ITEM(rtmp,ardp_activeQ);
--ardp_activeQ_len;
if(req) rtmp = NOREQ;
else rtmp = rtmp->next;
}
ardp_ptfree(ptmp);
return(ARDP_SUCCESS);
}
/*
* ardp_trap_int - signal handler to abort request on ^C
*/
SIGNAL_RET_TYPE ardp_trap_int()
{
ardp_abort(NOREQ);
exit(1);
}
/*
* ardp_abort_on_int - set up signal handler to abort request on ^C
*/
int
ardp_abort_on_int()
{
signal(SIGINT,ardp_trap_int);
return(ARDP_SUCCESS);
}

View File

@@ -0,0 +1,752 @@
/*
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*
* Written by bcn 1991 as check_for_messages in rdgram.c (Prospero)
* Modified by bcn 1/93 modularized and incorporated into new ardp library
* Modified by swa 12/93 made handle arbitrary length ardp_runQ
* Modified by swa 3/95 for bunyip; trapping errno 9 in bad rcvfrom.
*/
/* This version of lib/ardp/ardp_accept.c will work both in Prospero
Prealpha.17May94 and in the current (as of 3/21/95) working sources at ISI.
*/
#include <usc-license.h>
#include <netdb.h>
#include <stdio.h>
#include <sys/param.h>
/* Need types.h for u_short */
#include <sys/types.h>
#include <sys/socket.h>
#ifdef AIX
#include <sys/select.h>
#endif
#ifdef SOLARIS
#include <sys/signal.h>
#endif
#include <errno.h>
#include <ardp.h>
#include <pserver.h>
#include <plog.h>
#include <pprot.h>
#include <pmachine.h>
#include <pfs_threads.h> /* Mutex stuff */
#define LOG_PACKET(REQ,QP) \
if((REQ)->priority || (pQlen > 4)) \
if(pQNlen && (REQ)->priority) \
plog(L_QUEUE_INFO, REQ, "Queued: %d of %d (%d) - Priority %d", \
QP, pQlen, pQNlen, (REQ)->priority, 0); \
else if(pQNlen) \
plog(L_QUEUE_INFO, REQ, "Queued: %d of %d (%d)", \
QP, pQlen, pQNlen, 0); \
else if((REQ)->priority) \
plog(L_QUEUE_INFO, REQ, "Queued: %d of %d - Priority %d", \
QP, pQlen, (REQ)->priority, 0); \
else if(QP != pQlen) \
plog(L_QUEUE_INFO, REQ, "Queued: %d of %d", QP, pQlen, 0); \
else plog(L_QUEUE_INFO, REQ, "Queued: %d", pQlen, 0);
EXTERN_MUTEXED_DEF_INITIALIZER(RREQ,ardp_pendingQ,NOREQ); /*Pending requests*/
int pQlen = 0; /* Length of pending queue */
int pQNlen = 0; /* Number of niced requests */
static RREQ ardp_partialQ = NOREQ; /* Incomplete requests */
int ptQlen = 0; /* Length of incomplete queue */
int ptQmaxlen = 20; /* Max length of incomplete queue */
EXTERN_MUTEXED_DEF_INITIALIZER(RREQ,ardp_runQ,NOREQ); /* Requests currently in
progress */
EXTERN_MUTEXED_DEF_INITIALIZER(RREQ,ardp_doneQ,NOREQ); /* Processed requests
*/
int dQlen = 0; /* Length of reply queue */
/* Mutexed with ardp_doneQ */
int dQmaxlen = 20; /* Max length of reply queue */
static struct timeval zerotime = {0, 0}; /* Used by select */
#define max(x,y) (x > y ? x : y)
extern int (*ardp_pri_func)(); /* Function to compare priorities */
extern int ardp_pri_override; /* If 1, overide value in request */
/* C library error facility */
extern int ardp_srvport;
extern int ardp_prvport;
#ifdef ARCHIE
#ifdef __STDC__
extern int arch_get_etime(RREQ);
#else
extern int arch_get_etime();
#endif
#endif
static void ardp_update_cfields(RREQ existing, RREQ newvalues);
static void ardp_header_ack_rwait(PTEXT tpkt, RREQ nreq, int is_ack_needed,
int is_rwait_needed);
int
ardp_accept_and_wait(int timeout, int usec)
{
struct sockaddr_in from;
int fromlen;
int n = 0;
PTEXT pkt;
unsigned char flags1,flags2;
unsigned short pid; /* protocol ID for higher-level protocol */
int qpos; /* Position of new req in queue */
int dpos; /* Position of dupe in queue */
RREQ creq; /* Current request */
RREQ treq; /* Temporary request pointer */
RREQ nreq; /* New request pointer */
RREQ areq = NOREQ; /* Request needing ack */
RREQ match_in_runQ = NOREQ; /* if match found in runq for
completed request. */
int hdr_len;
char *ctlptr;
short stmp;
int tmp;
int check_for_ack = 1;
fd_set readfds; /* Used for select */
long now; /* Time - used for retries */
long rr_time = 0; /* Time last retrans from done queue */
struct timeval time_out;
time_out.tv_sec = timeout;
time_out.tv_usec = usec;
#ifdef PFS_THREADS
/* Changed from original interface. This will try the lock and return
an error if unsuccessful. Otherwise it will get the lock */
if (p_th_mutex_trylock(p_th_mutexARDP_ACCEPT))
return ARDP_SUCCESS; /* Being retrieved */
#endif
check_for_more:
/* This is initialized afresh before each select(). Some operating
systems, such as LINUX, modify the time_out parameter to SELECT().
--swa, 6/19/94 */
time_out.tv_sec = timeout;
time_out.tv_usec = usec;
now = time(NULL);
/* Check both the prived and unprived ports if necessary */
FD_ZERO(&readfds);
FD_SET(ardp_srvport, &readfds);
if(ardp_prvport != -1) FD_SET(ardp_prvport, &readfds);
tmp = select(max(ardp_srvport,ardp_prvport) + 1,
&readfds,(fd_set *)0,(fd_set *)0,&time_out);
if(tmp == 0) {
if(areq) ardp_acknowledge(areq); areq = NOREQ;
p_th_mutex_unlock(p_th_mutexARDP_ACCEPT);
return ARDP_SUCCESS;
}
if(tmp < 0) {
p_th_mutex_unlock(p_th_mutexARDP_ACCEPT);
return ARDP_SELECT_FAILED;
}
creq = ardp_rqalloc();
pkt = ardp_ptalloc();
/* There is a message waiting, add it to the queue */
fromlen = sizeof(from);
if((ardp_prvport >= 0) && FD_ISSET(ardp_prvport,&readfds))
n = recvfrom(ardp_prvport, pkt->dat, ARDP_PTXT_LEN_R, 0,
(struct sockaddr *) &from, &fromlen);
else {
assert(FD_ISSET(ardp_srvport, &readfds));
n = recvfrom(ardp_srvport, pkt->dat, ARDP_PTXT_LEN_R, 0,
(struct sockaddr *) &from, &fromlen);
}
if (n <= 0) {
plog(L_NET_ERR,NOREQ,"Bad recvfrom n = %d errno = %d %s",
n, errno, unixerrstr(), 0);
/* I added this in response to a problem experienced by Bunyip.
--swa, 3/21/95 */
if (errno == 9) {
if ((ardp_prvport >= 0) && FD_ISSET(ardp_prvport, &readfds))
plog(L_NET_ERR, NOREQ, "The bad descriptor was descriptor #%d,
represented internally by the variable ardp_prvport", ardp_prvport);
else if (FD_ISSET(ardp_srvport, &readfds))
plog(L_NET_ERR, NOREQ, "The bad descriptor was descriptor #%d,
represented internally by the variable ardp_srvport", ardp_srvport);
else
internal_error("Something is wrong with your system's version
of select(). No descriptors are readable; unclear how we got here.");
plog(L_NET_ERR, NOREQ,
"This should never happen. Attempting to restart server with SIGUSR1.");
kill(getpid(), SIGUSR1); /* sending restart signal to Prospero
server or to whatever we hand*/
}
ardp_rqfree(creq); ardp_ptfree(pkt);
p_th_mutex_unlock(p_th_mutexARDP_ACCEPT);
return ARDP_BAD_RECV;
}
bcopy(&from,&(creq->peer),sizeof(creq->peer));
creq->cid = 0; creq->peer_ardp_version = 0;
creq->rcvd_time.tv_sec = now;
creq->prcvd_thru = 0;
if ( ! verify_acl_list(&from) ) {
ardp_breply(creq, ARDP_R_COMPLETE, acl_message(),0);
ardp_ptfree(pkt);
goto check_for_more;
}
pkt->start = pkt->dat;
pkt->length = n;
*(pkt->start + pkt->length) = '\0';
pkt->mbz = 0; /* force zeros to catch runaway strings */
pkt->seq = 1;
if((hdr_len = (unsigned char) *(pkt->start)) < 32) {
ctlptr = pkt->start + 1;
pkt->seq = 0;
if(hdr_len >= 3) { /* Connection ID */
bcopy2(ctlptr,&stmp);
if(stmp) creq->cid = ntohs(stmp);
ctlptr += 2;
}
if(hdr_len >= 5) { /* Packet number */
bcopy2(ctlptr,&stmp);
pkt->seq = ntohs(stmp);
}
else { /* No packet number specified, so this is the only one */
pkt->seq = 1;
creq->rcvd_tot = 1;
}
ctlptr += 2;
if(hdr_len >= 7) { /* Total number of packets */
bcopy2(ctlptr,&stmp); /* 0 means don't know */
if(stmp) creq->rcvd_tot = ntohs(stmp);
}
ctlptr += 2;
if(hdr_len >= 9) { /* Receievd through */
bcopy2(ctlptr,&stmp); /* 0 means don't know */
if(stmp) {
creq->prcvd_thru = ntohs(stmp);
}
}
ctlptr += 2;
if(hdr_len >= 11) { /* Backoff */
/* Not supported by server */
}
ctlptr += 2;
flags1 = flags2 = 0;
if(hdr_len >= 12) flags1 = *ctlptr++; /* Flags */
if(hdr_len >= 13) flags2 = *ctlptr++; /* Flags */
if(flags2 == 1) { /* Cancel request */
EXTERN_MUTEXED_LOCK(ardp_pendingQ);
treq = ardp_pendingQ;
while(treq) {
if((treq->cid == creq->cid) &&
(treq->peer_port == creq->peer_port) &&
(treq->peer_addr.s_addr == creq->peer_addr.s_addr)){
plog(L_QUEUE_INFO,treq,
"Request canceled by client - dequeued",0);
pQlen--;if(treq->priority > 0) pQNlen--;
EXTRACT_ITEM(treq,ardp_pendingQ);
ardp_rqfree(treq);
ardp_rqfree(creq); ardp_ptfree(pkt);
EXTERN_MUTEXED_UNLOCK(ardp_pendingQ);
goto check_for_more;
}
treq = treq->next;
}
plog(L_QUEUE_INFO,creq,
"Request canceled by client - not on queue",0);
ardp_rqfree(creq); ardp_ptfree(pkt);
EXTERN_MUTEXED_UNLOCK(ardp_pendingQ);
goto check_for_more;
}
/* If the client specifies option flags and doesn't specify control
info to match them, we probably should log this; right now we just
silently ignore it. */
if (ctlptr < pkt->start + hdr_len) /* if still control info */ {
/* Priority specified. */
if(flags1 & 0x2) {
bcopy2(ctlptr,&stmp);
creq->priority = ntohs(stmp);
ctlptr += 2;
}
}
if (ctlptr < pkt->start + hdr_len) /* if still control info */ {
/* Higher-level protocol ID follows. */
/* N.B.: used to be a bug here where this was 0x1; this is in
variance with the ARDP spec and I've corrected the
implementation to conform to the spec. */
if(flags1 & 0x4) {
bcopy2(ctlptr,&stmp);
pid = ntohs(stmp);
ctlptr += 2;
}
}
if (ctlptr < pkt->start + hdr_len) /* if still control info */ {
/* Window size follows (2 octets of information). */
if(flags1 & 0x8) {
bcopy2(ctlptr,&stmp);
creq->pwindow_sz = ntohs(stmp);
ctlptr += 2;
if (creq->pwindow_sz == 0) {
creq->pwindow_sz = ARDP_DEFAULT_WINDOW_SZ;
plog(L_NET_INFO, creq,
"Client explicity reset window size to server \
default (%d)",
ARDP_DEFAULT_WINDOW_SZ);
} else {
if (creq->pwindow_sz > ARDP_MAX_WINDOW_SZ) {
plog(L_NET_INFO, creq, "Client set window size \
to %d; server will limit it to %d", creq->pwindow_sz, ARDP_MAX_WINDOW_SZ);
creq->pwindow_sz = ARDP_MAX_WINDOW_SZ;
} else {
plog(L_NET_INFO, creq,
"Client set window size to %d", creq->pwindow_sz);
}
}
}
}
if((creq->priority < 0) && (creq->priority != -42)) {
plog(L_NET_RDPERR, creq, "Priority %d requested - ignored", creq->priority, 0);
creq->priority = 0;
}
if(pkt->seq == 1) creq->rcvd_thru = max(creq->rcvd_thru, 1);
pkt->length -= hdr_len;
pkt->start += hdr_len;
pkt->text = pkt->start;
}
else {
/* When we are no longer getting any of these old format */
/* requests, we know that everyone is using the new */
/* reliable datagram protocol, and that they also */
/* have the singleton response bug fixed. We can then */
/* get rid of the special casing for singleton responses */
/* Lower the priority to encourage people to upgrade */
creq->priority = 1;
creq->peer_ardp_version = -1;
#ifdef LOGOLDFORMAT
plog(L_DIR_PWARN,creq,"Old RDP format",0);
#endif LOGOLDFORMAT
pkt->seq = 1;
creq->rcvd_tot = 1;
creq->rcvd_thru = 1;
}
/* Check to see if it is already on done, partial, or pending */
/* Done queue */
EXTERN_MUTEXED_LOCK(ardp_doneQ);
treq = ardp_doneQ;
CHECK_HEAD(treq);
while(treq) {
if((treq->cid != 0) && (treq->cid == creq->cid) &&
(bcmp((char *) &(treq->peer),
(char *) &from,sizeof(from))==0)){
/* Request is already on doneQ */
if(creq->prcvd_thru > treq->prcvd_thru) {
treq->prcvd_thru = creq->prcvd_thru;
rr_time = 0; /* made progress, don't supress retransmission */
}
nreq = treq;
/* Retransmit reply if not completely received */
/* and if we didn't retransmit it this second */
if((nreq->prcvd_thru != nreq->trns_tot) &&
((rr_time != now) || (nreq != ardp_doneQ))) {
PTEXT tpkt; /* Temporary pkt pointer */
plog(L_QUEUE_INFO,nreq,"Retransmitting reply (%d of %d ack)",
nreq->prcvd_thru, nreq->trns_tot, 0);
/* Transmit all outstanding packets */
for (tpkt = nreq->trns; tpkt; tpkt = tpkt->next) {
if((tpkt->seq <= (nreq->prcvd_thru + nreq->pwindow_sz)) &&
((tpkt->seq == 0) || (tpkt->seq > nreq->prcvd_thru))) {
/* (A) Request an ack at the end of a window
(B) Request an ack in the last packet if the
service has rescinded a wait request, but we
aren't sure that the client knows this.
*/
ardp_header_ack_rwait(tpkt, nreq,
/* do set ACK BIT: */
(/*A*/ tpkt->seq ==
(nreq->prcvd_thru
+ nreq->pwindow_sz))
|| /*B*/
((tpkt->seq == nreq->trns_tot)
/* last pkt */
&& (nreq->svc_rwait_seq >
nreq->prcvd_thru)),
/* Might an RWAIT be needed? */
(nreq->svc_rwait_seq >
nreq->prcvd_thru));
ardp_snd_pkt(tpkt,nreq);
}
}
rr_time = now; /* Remember time of retransmission */
}
/* Move matched request to front of queue */
/* nreq is definitely in ardp_doneQ right now. */
/* This replaces much icky special-case code that used to be here
-- swa, Feb 9, 1994 */
EXTRACT_ITEM(nreq, ardp_doneQ);
PREPEND_ITEM(nreq, ardp_doneQ);
ardp_rqfree(creq); ardp_ptfree(pkt);
EXTERN_MUTEXED_UNLOCK(ardp_doneQ);
goto check_for_more;
}
/* While we're checking the done queue also see if any */
/* replies require follow up requests for acknowledgments */
/* This is currently used when the server has requested that the client
wait for a long time, and then has rescinded that wait request
(because the message is done). Such a rescinding of the wait
request should be received by the client, and the server is
expecting an ACK. */
/* You can add additional tests here if there are other circumstances
under which you want the server to expect the client to send an
acknowledgement. */
if(check_for_ack && (treq->svc_rwait_seq > treq->prcvd_thru) &&
(treq->retries_rem > 0) && (now >= treq->wait_till.tv_sec)) {
#define ARDP_LOG_SPONTANEOUS_RETRANSMISSIONS
#ifdef ARDP_LOG_SPONTANEOUS_RETRANSMISSIONS
plog(L_QUEUE_INFO,treq,"Requested ack not received - pinging client (%d of %d/%d ack)",
treq->prcvd_thru, treq->svc_rwait_seq, treq->trns_tot, 0);
#endif /* ARDP_LOG_SPONTANEOUS_RETRANSMISSIONS */
/* Resend the final packet only - to wake the client */
if(treq->trns) ardp_snd_pkt(treq->trns->previous,treq);
treq->timeout_adj.tv_sec = ARDP_BACKOFF(treq->timeout_adj.tv_sec);
treq->wait_till.tv_sec = now + treq->timeout_adj.tv_sec;
treq->retries_rem--;
}
CHECK_NEXT(treq);
treq = treq->next;
} /*while*/
EXTERN_MUTEXED_UNLOCK(ardp_doneQ);
check_for_ack = 0; /* Only check once per call to ardp_accept */
/* If unsequenced control packet free it and check for more */
if(pkt->seq == 0) {
ardp_rqfree(creq); ardp_ptfree(pkt);
goto check_for_more;
}
/* Check if incomplete and match up with other incomplete requests */
if(creq->rcvd_tot != 1) { /* Look for rest of request */
treq = ardp_partialQ;
while(treq) {
if((treq->cid != 0) && (treq->cid == creq->cid) &&
(bcmp((char *) &(treq->peer),
(char *) &from,sizeof(from))==0)) {
/* We found the rest of the request */
/* coallesce and log and check_for more */
PTEXT tpkt; /* Temporary pkt pointer */
ardp_update_cfields(treq,creq);
if(creq->rcvd_tot) treq->rcvd_tot = creq->rcvd_tot;
tpkt = treq->rcvd;
while(tpkt) {
if(tpkt->seq == treq->rcvd_thru+1) treq->rcvd_thru++;
if(tpkt->seq == pkt->seq) {
/* Duplicate - discard */
plog(L_NET_INFO,creq,"Multi-packet duplicate received (pkt %d of %d)",
pkt->seq, creq->rcvd_tot, 0);
if(areq != treq) {
if(areq) {
ardp_acknowledge(areq);
}
areq = treq;
}
ardp_rqfree(creq); ardp_ptfree(pkt);
goto check_for_more;
}
if(tpkt->seq > pkt->seq) {
/* Insert new packet in rcvd */
pkt->next = tpkt;
pkt->previous = tpkt->previous;
if(treq->rcvd == tpkt) treq->rcvd = pkt;
else tpkt->previous->next = pkt;
tpkt->previous = pkt;
if(pkt->seq == treq->rcvd_thru+1) treq->rcvd_thru++;
while(tpkt && (tpkt->seq == treq->rcvd_thru+1)) {
treq->rcvd_thru++;
tpkt = tpkt->next;
}
pkt = NOPKT;
break;
}
tpkt = tpkt->next;
}
if(pkt) { /* Append at end of rcvd */
APPEND_ITEM(pkt,treq->rcvd);
if(pkt->seq == treq->rcvd_thru+1) treq->rcvd_thru++;
pkt = NOPKT;
}
if(treq->rcvd_tot && (treq->rcvd_thru == treq->rcvd_tot)) {
if(areq == treq) areq = NOREQ;
creq = treq; EXTRACT_ITEM(creq, ardp_partialQ); --ptQlen;
plog(L_NET_INFO,creq,"Multi-packet request complete",0);
goto req_complete;
}
else {
if(areq != treq) {
if(areq) {
ardp_acknowledge(areq);
}
areq = treq;
}
plog(L_NET_INFO, creq,
"Multi-packet request continued (rcvd %d of %d)",
creq->rcvd_thru, creq->rcvd_tot, 0);
goto check_for_more;
}
}
treq = treq->next;
}
/* This is the first packet we received in the request */
/* log it and queue it and check for more */
plog(L_NET_INFO,creq,"Multi-packet request received (pkt %d of %d)",
pkt->seq, creq->rcvd_tot, 0);
APPEND_ITEM(pkt,creq->rcvd);
APPEND_ITEM(creq,ardp_partialQ); /* Add at end of incomp queue */
if(++ptQlen > ptQmaxlen) {
treq = ardp_partialQ; /* Remove from head of queue */
EXTRACT_ITEM(ardp_partialQ,ardp_partialQ); ptQlen--;
plog(L_NET_ERR, treq,
"Too many incomplete requests - dropped (rthru %d of %d)",
treq->rcvd_thru, treq->rcvd_tot, 0);
ardp_rqfree(treq);
}
goto check_for_more;
}
plog(L_NET_INFO, creq, "Received packet", 0);
req_complete:
qpos = 0; dpos = 1;
/* Insert this message at end of pending but make sure the */
/* request is not already in pending */
nreq = creq; creq = NOREQ;
EXTERN_MUTEXED_LOCK(ardp_pendingQ);
treq = ardp_pendingQ;
if(pkt) {
nreq->rcvd_tot = 1;
APPEND_ITEM(pkt,nreq->rcvd);
}
EXTERN_MUTEXED_LOCK(ardp_runQ);
for (match_in_runQ = ardp_runQ; match_in_runQ;
match_in_runQ = match_in_runQ->next) {
if((match_in_runQ->cid == nreq->cid) && (match_in_runQ->cid != 0) &&
(bcmp((char *) &(match_in_runQ->peer),
(char *) &(nreq->peer),sizeof(nreq->peer))==0)) {
/* Request is running right now */
ardp_update_cfields(match_in_runQ,nreq);
plog(L_QUEUE_INFO,match_in_runQ,"Duplicate discarded (presently executing)",0);
/*!! This looks strange - freeing but not removing from ardp_runQ*/
ardp_rqfree(nreq);
nreq = match_in_runQ;
break; /* leave match_in_runQ set to nreq */
}
}
EXTERN_MUTEXED_UNLOCK(ardp_runQ);
if (match_in_runQ) {
/* do nothing; handled above. */
} else if(ardp_pendingQ) {
int keep_looking = 1; /* Keep looking for dup. Initially say to
keep on looking. */
while(treq) {
if((treq->cid != 0) && (treq->cid == nreq->cid) &&
(bcmp((char *) &(treq->peer),
(char *) &(nreq->peer),sizeof(treq->peer))==0)){
/* Request is already on queue */
ardp_update_cfields(treq,nreq);
plog(L_QUEUE_INFO,treq,"Duplicate discarded (%d of %d)",dpos,pQlen,0);
ardp_rqfree(nreq);
nreq = treq;
keep_looking = 0; /* We found the duplicate */
break;
}
if((ardp_pri_override && ardp_pri_func && (ardp_pri_func(nreq,treq) < 0)) ||
(!ardp_pri_override && ((nreq->priority < treq->priority) ||
((treq->priority == nreq->priority) && ardp_pri_func &&
(ardp_pri_func(nreq,treq) < 0))))) {
if(ardp_pendingQ == treq) {
nreq->previous = ardp_pendingQ->previous;
nreq->next = ardp_pendingQ;
ardp_pendingQ->previous = nreq;
ardp_pendingQ = nreq;
}
else {
nreq->next = treq;
nreq->previous = treq->previous;
nreq->previous->next = nreq;
treq->previous = nreq;
}
pQlen++;
if(nreq->priority > 0) pQNlen++;
LOG_PACKET(nreq, dpos);
qpos = dpos;
keep_looking = 1; /* There may still be a duplicate */
break;
}
if(!treq->next) {
treq->next = nreq;
nreq->previous = treq;
ardp_pendingQ->previous = nreq;
pQlen++;
if(nreq->priority > 0) pQNlen++;
LOG_PACKET(nreq,dpos+1);
qpos = dpos+1;
keep_looking = 0; /* Nothing more to check */
break;
}
treq = treq->next;
dpos++;
}
/* Save queue position to send to client if appropriate */
qpos = dpos;
/* If not added at end of queue, check behind packet for dup */
if(keep_looking) {
while(treq) {
if((treq->cid == nreq->cid) && (treq->cid != 0) &&
(bcmp((char *) &(treq->peer),
(char *) &(nreq->peer),
sizeof(treq->peer))==0)){
/* Found a dup */
plog(L_QUEUE_INFO,treq,"Duplicate replaced (removed at %d)", dpos, 0);
pQlen--;if(treq->priority > 0) pQNlen--;
EXTRACT_ITEM(treq,ardp_pendingQ);
ardp_rqfree(treq);
break;
}
treq = treq->next;
dpos++;
}
} /* if keep_looking */
}
else {
nreq->next = NULL;
ardp_pendingQ = nreq;
ardp_pendingQ->previous = nreq;
pQlen++;if(nreq->priority > 0) pQNlen++;
LOG_PACKET(nreq, dpos);
qpos = dpos;
}
EXTERN_MUTEXED_UNLOCK(ardp_pendingQ);
/* Fill in queue position and system time */
nreq->inf_queue_pos = qpos;
/* nreq->inf_sys_time = **compute-system-time-here** */
#ifdef ARCHIE
nreq -> inf_sys_time = arch_get_etime(nreq);
#endif
/* Here we can optionally send a message telling the */
/* client to back off. How long should depend on the */
/* queue length and the mean service time */
/* 15 min for now - the archie server is overloaded */
#ifdef ARCHIE
/* This is an old version of the Prospero clients that only archie servers
will need to be able to talk to, so don't bother doing this test
for anything but an archie server. */
if((nreq->peer_ardp_version >= 0) && (sindex(nreq->rcvd->start,"VERSION 1")))
nreq->peer_ardp_version = -2;
/* Archie servers should request a longer wait. Other heavily used
databases may want to have this command defined too. */
ardp_rwait(nreq,900,nreq->inf_queue_pos,nreq->inf_sys_time);
#endif
goto check_for_more;
}
static
void
ardp_update_cfields(RREQ existing,RREQ newvalues)
{
if(newvalues->prcvd_thru > existing->prcvd_thru)
existing->prcvd_thru = newvalues->prcvd_thru;
}
/* Rewrite the header of TPKT to conform to the status in nreq. The only
fields
we need to set are possibly the ACK bit in octet 11 and possibly the rwait
field in octets 9 & 10. We always send the received-through field for the
sake of simplicity of implementation. */
static void ardp_header_ack_rwait(PTEXT tpkt, RREQ nreq, int is_ack_needed,
int is_rwait_needed)
{
int new_hlength; /* new header length. */
int old_hlength; /* old header length */
unsigned short us_tmp; /* tmp for values. */
old_hlength = tpkt->text - tpkt->start;
/* If rwait needed, leave room for it. */
new_hlength = 9; /* Include room for received-through count */
if (is_rwait_needed)
new_hlength = 11;
if (is_ack_needed) new_hlength = 12;
/* Allocate space for new header. */
tpkt->start = tpkt->text - new_hlength;
tpkt->length += new_hlength - old_hlength;
/* Set the header length and version # (zeroth octet) */
/* Version # is zero in this version of the ARDP library; last 6 bytes
of octet are header length. */
*(tpkt->start) = (char) new_hlength;
/* Set octets 1 through 8 of header */
/* Connection ID (octets 1 & 2) */
bcopy2(&(nreq->cid),tpkt->start+1);
/* Sequence number (octets 3 & 4) */
us_tmp = htons(tpkt->seq);
bcopy2(&us_tmp,tpkt->start+3);
/* Total packet count (octets 5 & 6) */
us_tmp = htons(nreq->trns_tot);
bcopy2(&us_tmp,tpkt->start+5);
/* Received through (octets 7 & 8) */
us_tmp = htons(nreq->rcvd_thru);
bcopy2(&us_tmp,tpkt->start+7);
/* Now set any options. */
/* expected time 'till response */
if (new_hlength > 9) {
us_tmp = htons(nreq->svc_rwait);
bcopy2(&us_tmp, tpkt->start+9);
}
if (new_hlength > 11) {
tpkt->start[11] =
is_ack_needed ? 0x80 /* ACK BIT */ : 0x00 /* Don't ack */;
}
}
int
ardp_accept() {
return ardp_accept_and_wait(0,0);
}

View File

@@ -0,0 +1,163 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-copyr.h>.
*
* Written by bcn 2/93 to add text to a request
*/
#include <usc-copyr.h>
#include <string.h>
#include <stdio.h>
#include <ardp.h>
#include <sys/types.h> /* so pmachine.h won't redefine it. */
#include <pmachine.h> /* for bcopy() */
#define max(x,y) (x > y ? x : y)
#define min(x,y) (x < y ? x : y)
/*
* ardp_add2req - add text to request structure
*
* ardp_add2req takes a request structure, flags, a buffer containing text
* to be added to the output queue of the request, and the length of the
* buffer.
*
* If the specified length of the buffer is 0, ardp_add2req calculates
* it using strlen (if the lenght is zero, the assumption is that the
* buffer is null terminated).
* If the buffer is a NULL pointer and the specified length is 0, then
* it treated as a true zero-length buffer.
*
* If the flag ARDP_A2R_NOSPLITB is set, the request will not be split
* across packets. If ARDP_A2R_NOSPLITL, the lines may not be split
* across packets, and text added to a request without a trailing new
* line will be deferred until a newline is added or ardp_add2req is called
* without ARDP_A2R_NOSPLITL set. If ARDP_A2R_COMPLETE is specified, it
* indicates this is the final text to be added to the request structure,
* and no text will remain buffered. If there is still deferred text,
* a newline will be added. If the flag ARDP_A2R_TAGLENGTH is specified,
* the data written to the request will be tagged with a four octet length
* field in network byte order.
*
* NOTE: If you use this function to add text to a request, then you
* should use only this function. If this function is called on
* a request previously constructed by hand, unexpected failures
* may result.
*
* BUGS: ARDP_A2R_NOSPLITL is not currently supported unless
* ARDP_A2R_NOSPLITB is also set.
* ARDP_A2R_TAGLENGTH is not presently supported.
* An ardp_flush_partial_line() is needed to handle some manifestations
* of the ARDP_TOOLONG error. Alternatively, we might specify an
* additional flag to ardp_add2req() to specify the behavior on an
* ARDP_TOOLONG error.
*/
int
ardp_add2req(RREQ req, /* Request to get the text */
int flags, /* Options to add2req */
char *buf, /* New text for request */
int buflen) /* Length of the new text */
{
int remaining; /* Space remaining in pkt */
int written; /* # Octets written */
char *newline; /* last nl in string */
int deflen; /* Length of deferred text */
int extra; /* Extra space needed */
long taglen; /* Length in net byte ord */
PTEXT pkt = NOPKT; /* Current packet */
PTEXT ppkt; /* Previous packet */
/* Note: New text gets written after pkt->ioptr. If */
/* there is text waiting for a newline, then ->ioptr */
/* may be beyond ->start+->length, which will be the */
/* text up to the final newline seen so far */
/* XXX For now if NOSPLITL, must also specify NOSPLITB */
if((flags & ARDP_A2R_NOSPLITL) && !(flags & ARDP_A2R_NOSPLITB))
return(ARDP_FAILURE);
if(buf && !buflen) buflen = strlen(buf);
if(!buf) buf = "";
keep_writing:
/* Find ot allocate last packet in ->outpkt */
if(req->outpkt) pkt = req->outpkt->previous;
if(!pkt) {
if((pkt = ardp_ptalloc()) == NOPKT) return(ARDP_FAILURE);
APPEND_ITEM(pkt,req->outpkt);
}
deflen = pkt->ioptr - (pkt->start + pkt->length);
extra = deflen;
if(flags & ARDP_A2R_NOSPLITL) extra += 1;
if(flags & ARDP_A2R_TAGLENGTH) extra += 4;
if((flags & ARDP_A2R_NOSPLITB) && (buflen + extra > ARDP_PTXT_LEN))
return(ARDP_TOOLONG);
remaining = ARDP_PTXT_LEN - (pkt->ioptr - pkt->start);
if(((flags & ARDP_A2R_NOSPLITB) && (remaining < buflen + 1)) ||
((flags & ARDP_A2R_TAGLENGTH) && (remaining < 4)) ||
(remaining == 0)) {
ppkt = pkt;
if((pkt = ardp_ptalloc()) == NOPKT) return(ARDP_FAILURE);
if(ppkt->start + ppkt->length != ppkt->ioptr) {
/* Must move deferred text to new packet */
bcopy(ppkt->start+ppkt->length, pkt->start, deflen);
ppkt->ioptr = ppkt->start + ppkt->length;
*(ppkt->ioptr) = '\0';
pkt->ioptr += deflen;
}
APPEND_ITEM(pkt,req->outpkt);
remaining = ARDP_PTXT_LEN;
}
if(flags & ARDP_A2R_TAGLENGTH) {
taglen = htonl(buflen);
bcopy4(&buflen,pkt->ioptr);
pkt->ioptr += 4;
remaining -= 4;
}
written = min(remaining,buflen);
bcopy(buf,pkt->ioptr,written);
pkt->ioptr += written;
if(flags & ARDP_A2R_NOSPLITL) {
*(pkt->ioptr) = '\0'; /* To catch runaway strrchar */
/* Find last newline */
newline = strrchr(pkt->start + pkt->length,'\n');
if(newline) pkt->length = newline + 1 - pkt->start;
}
else pkt->length = pkt->ioptr - pkt->start;
/* Always need to stick on trailing NULL for sake of ardp_respond(),
which expects it. */
*pkt->ioptr = '\0';
/* In this case, ARDP_A@R_NOSPLITB was not specified, split it */
if(written != buflen) {
buf += written;
buflen -= written;
goto keep_writing;
}
if(flags & ARDP_A2R_COMPLETE) {
deflen = pkt->ioptr - (pkt->start + pkt->length);
/* If deferred, write a newline */
if(deflen) {
*(pkt->ioptr++) = '\n';
pkt->length = pkt->ioptr - pkt->start;
/* Always need to stick on trailing NULL for sake of
ardp_respond(), which expects it. */
*pkt->ioptr = '\0';
}
}
return ARDP_SUCCESS;
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*
* Written by bcn 2/93 to send reply to request
* Hacked by swa 11/94 to send length-coded reply to request.
*/
#include <usc-license.h>
#include <stdio.h>
#include <ardp.h>
/*
* ardp_breply - send a reply to a request that might contain binary data
*
* ardp_breply reply takes request to which a reply is to be sent
* a flags field, and a message to be sent to the client in response
* to the request, and a length count for the message. ardp_breply then adds
* the response to the output queue for the request.
*
* A length count of 0 indicates that the buffer is null-terminated.
* (implementation note: by passing the 0 down to ardp_add2req, we
* allow there to be only one pass through the buffer instead of 2.)
*
* If space remains in the packet, the response is buffered pending
* subsequent replies, unless the ARDP_REPL_COMPLETE has been specified,
* in which case all data is sent. If the size of the buffered response
* approaches the maximum packet size, the buffered data is sent, and
* and a new packet is started to hold any remaining data from the current
* message.
*
* The lower level function (ardp_respond) assigns packet numbers and
* tags outgoing packets if necessary or a multi packet response.
*/
int
ardp_breply(RREQ req, /* Request to which this is a response */
int flags, /* Whether this is the final message */
char *message, /* The data to be sent. */
int len) /* message length; 0 means null-terminated */
{
int tmp;
tmp = ardp_add2req(req,flags,message,len);
if (tmp) return tmp;
if(flags&ARDP_R_COMPLETE) return(ardp_respond(req,ARDP_R_COMPLETE));
/* Check to see if any packets are done */
#if 1
if(req->outpkt && req->outpkt->next) {
#else
/* This always yields the same results as the previous line but appears
clunkier to me. */
if(req->outpkt && (req->outpkt->previous != req->outpkt)) {
#endif
PTEXT tpkt; /* Temp to hold active packet */
/* Hold out final packet */
tpkt = req->outpkt->previous;
EXTRACT_ITEM(tpkt,req->outpkt);
tmp = ardp_respond(req,ARDP_R_INCOMPLETE);
APPEND_ITEM(tpkt,req->outpkt);
if (tmp) return tmp;
}
return(ARDP_SUCCESS);
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*
* Written by swa 11/93 to handle error reporting consistently in libardp
*/
#include <usc-license.h>
#include <ardp.h>
#include <perrno.h> /* For perrno */
/* See lib/ardp/usc_lic_str.c */
extern char *usc_license_string;
/* This is used in Prospero in lib/pfs/perrmesg.c. Change it there too if you
change it here. */
char *ardp___please_do_not_optimize_me_out_of_existence;
/* perrno is declared in ardp_perrno.c in case some older applications
have explicitly declared their own perrno variable (a practice we now
discourage). */
/* This function definition is shadowed in lib/pfs/perrmesg.c. Change it there
too if you change it here. */
void
p_clear_errors(void)
{
ardp___please_do_not_optimize_me_out_of_existence = usc_license_string;
perrno = 0;
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*
* Written by bcn 1991 as get_next_request in rdgram.c (Prospero)
* Modified by bcn 1/93 modularized and incorporated into new ardp library
*/
#include <usc-license.h>
#include <stdio.h>
#include <sys/time.h>
#ifdef AIX
#include <sys/select.h>
#endif
#include <ardp.h>
#include <pmachine.h>
extern RREQ ardp_pendingQ;
EXTERN_MUTEXED_DECL(RREQ,ardp_runQ);
extern int pQNlen;
extern int pQlen;
extern int ardp_srvport;
extern int ardp_prvport;
#define max(x,y) (x > y ? x : y)
/*
* ardp_get_nxt - return next request for server
*
* ardp_get_nxt returns the next request to be processed by the server.
* If no requests are pending, ardp_get_nxt waits until a request
* arrives, then returns it.
*/
/* Called outside multithraded stuff; doesn't need to be mutexed. */
RREQ
ardp_get_nxt(void)
{
RREQ nextreq;
fd_set readfds;
int tmp;
tryagain:
if (nextreq = ardp_get_nxt_nonblocking())
return nextreq;
/* if queue is empty, then wait till somethings comes */
/* in, then go back to start */
FD_ZERO(&readfds);
if(ardp_srvport != -1) FD_SET(ardp_srvport, &readfds);
if(ardp_prvport != -1) FD_SET(ardp_prvport, &readfds);
tmp = select(max(ardp_srvport,ardp_prvport) + 1, &readfds,
(fd_set *)0, (fd_set *)0, NULL);
goto tryagain;
}
/*
* Nonblocking version of the above.
* Returns NULL if no pending items.
*/
RREQ
ardp_get_nxt_nonblocking(void)
{
ardp_accept();
/* return next message in queue */
if (ardp_pendingQ) {
/* Atomic test; save ourselves the trouble of going through the kernel
if nothing in queue */
EXTERN_MUTEXED_LOCK(ardp_pendingQ);
if(ardp_pendingQ) {
RREQ nextreq = ardp_pendingQ;
EXTRACT_ITEM(nextreq, ardp_pendingQ);
pQlen--;if(nextreq->priority > 0) pQNlen--;
EXTERN_MUTEXED_UNLOCK(ardp_pendingQ);
nextreq->svc_start_time.tv_sec = time(NULL);
EXTERN_MUTEXED_LOCK(ardp_runQ);
APPEND_ITEM(nextreq,ardp_runQ);
EXTERN_MUTEXED_UNLOCK(ardp_runQ);
return(nextreq);
}
EXTERN_MUTEXED_UNLOCK(ardp_pendingQ);
}
return NOREQ;
}

View File

@@ -0,0 +1,124 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-copyr.h>.
*
* Written by bcn 1/93 For use in adrp_send
*/
#include <usc-copyr.h>
#include <stdio.h>
#include <ardp.h>
#include <pmachine.h> /* for bcopy() */
extern int ardp_priority; /* Override for 0 priority */
extern int pfs_debug;
/*
* ardp_headers - Add headers to packets to be sent to server
*
* ardp_headers takes pointer to a request structure and adds headers to
* all the packets in the trns list. The fields for the headers are
* taken from other fields in the request structure. If the priority is
* zero, it is taken from the global vairable ardp_priority.
*
* If ardp_headers is called more than once, subsequent calls will
* update the headers to conform to changes in the request fields.
*/
int
ardp_headers(RREQ req)
{
PTEXT ptmp; /* Temporary packet pointer */
for(ptmp = req->trns; ptmp; ptmp = ptmp->next) {
int old_hlength; /* Old header length */
int new_hlength; /* New header length, whatever it may
be. */
unsigned short ftmp; /* Temporary for values of fields */
/* Boolean: do we stamp this packet with the window size? */
/* We will add an explicity window-size stamp to the first sent, if
an explicit window size was set. This packet is the one stamped
with sequence number 1. Thus we know that the window size message
won't be lost. */
int stamp_window_size = (req->flags & ARDP_FLAG_SEND_MY_WINDOW_SIZE)
&& (ptmp->seq == 1);
int stamp_priority = (req->priority || ardp_priority)
&& (ptmp->seq == 1);
old_hlength = ptmp->text - ptmp->start;
/* XXX Should do further tests to make sure all packets present */
if(ptmp->seq == 0) {
if (pfs_debug >= 1)
fprintf(stderr, "ardp: sequence number not set in packet\n");
fflush(stderr);
return(ARDP_BAD_REQ);
}
/* If priority stamp or explicit client window size, need octets 11 and
12 to be present. */
if (stamp_priority || stamp_window_size) {
new_hlength = 13; /* room for octets through 12 */
if(req->priority || ardp_priority)
new_hlength += 2; /* 2 octets for priority argument. */
if (stamp_window_size)
new_hlength += 2; /* 2 octets for window size */
} else {
new_hlength = 9; /* room for octets through 8 (received-through)
*/
}
/* New header length now set. */
/* Allocate space for the new header */
ptmp->start = ptmp->text - new_hlength;
ptmp->length += new_hlength - old_hlength;
/* Set the header length and version # (zeroth octet) */
/* Version # is zero in this version of the ARDP library; last 6 bytes
of octet are header length. */
*(ptmp->start) = (char) new_hlength;
/* Set octets 1 through 8 of header */
/* Connection ID (octets 1 & 2) */
bcopy2(&(req->cid),ptmp->start+1);
/* Sequence number (octets 3 & 4) */
ftmp = htons(ptmp->seq);
bcopy2(&ftmp,ptmp->start+3);
/* Total packet count (octets 5 & 6) */
ftmp = htons(req->trns_tot);
bcopy2(&ftmp,ptmp->start+5);
/* Received through (octets 7 & 8) */
ftmp = htons(req->rcvd_thru);
bcopy2(&ftmp,ptmp->start+7);
/* Now set any options. */
if (new_hlength > 9) {
char * optiondata; /* where options go. */
/* zero out octets 9 and 10 (expected time 'till response). It is
not defined for the client to specify this to the server,so
it is always zero. */
bzero2(ptmp->start + 9);
/* set octet 11 (flags) initially clear */
ptmp->start[11] = 0;
/* Here Octet 12 (option) is zero (no special options). */
ptmp->start[12] = 0;
optiondata = ptmp->start + 13; /* additional octets start here */
/* Priority */
if(stamp_priority) {
*(ptmp->start+11) |= 0x02; /* priority flag */
if(req->priority) ftmp = htons(req->priority);
else ftmp = htons(ardp_priority);
bcopy2(&ftmp, optiondata);
optiondata += 2;
}
if(stamp_window_size) {
*(ptmp->start+11) |= 0x08; /* Set window size flag */
ftmp = htons(req->window_sz);
bcopy2(&ftmp, optiondata);
optiondata += 2;
}
assert(optiondata == ptmp->start + new_hlength);
}
}
return(ARDP_SUCCESS);
}

View File

@@ -0,0 +1,17 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*
* Written by swa 12/93 to handle error reporting consistently in libardp
*/
#include <usc-license.h>
#include <ardp.h>
/* Data definition. This may be reset by any client. */
int (*internal_error_handler)(const char file[], int line, const char mesg[]) = 0;

View File

@@ -0,0 +1,85 @@
/*
* Copyright (c) 1993-1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
#include <pfs_threads.h>
#include <ardp.h>
#ifdef PFS_THREADS
p_th_mutex p_th_mutexARDP_ACCEPT; /* declaration */
p_th_mutex p_th_mutexPTEXT; /* declared in ardp_mutexes.c */
p_th_mutex p_th_mutexARDP_RQALLOC; /* declared in ardp_mutexes.c */
p_th_mutex p_th_mutexGETHOSTBYNAME; /* declared in pfs_mutexes.c */
p_th_mutex p_th_mutexARDP_SELFNUM; /* declared in pfs_mutexes.c */
p_th_mutex p_th_mutexDNSCACHE; /* declared in pfs_mutexes.c */
p_th_mutex p_th_mutexALLDNSCACHE; /* declared in pfs_mutexes.c */
p_th_mutex p_th_mutexFILES; /* declared on p__self_num.c */
p_th_mutex p_th_mutexFILELOCK; /* declared in flock.c */
#endif
void
ardp_init_mutexes(void)
{
#ifdef PFS_THREADS
EXTERN_MUTEXED_INIT_MUTEX(ardp_doneQ);
EXTERN_MUTEXED_INIT_MUTEX(ardp_runQ);
p_th_mutex_init(p_th_mutexGETHOSTBYNAME);
p_th_mutex_init(p_th_mutexARDP_ACCEPT);
p_th_mutex_init(p_th_mutexPTEXT);
p_th_mutex_init(p_th_mutexARDP_RQALLOC);
p_th_mutex_init(p_th_mutexARDP_SELFNUM);
p_th_mutex_init(p_th_mutexDNSCACHE);
p_th_mutex_init(p_th_mutexALLDNSCACHE);
p_th_mutex_init(p_th_mutexFILES);
p_th_mutex_init(p_th_mutexFILELOCK);
#endif
}
#ifndef NDEBUG
void
ardp_diagnose_mutexes(void)
{
#ifdef PFS_THREADS
DIAGMUTEX(ardp_doneQ,"ardp_doneQ");
DIAGMUTEX(ardp_runQ,"ardp_runQ");
DIAGMUTEX(GETHOSTBYNAME,"GETHOSTBYNAME");
DIAGMUTEX(ARDP_ACCEPT,"ARDP_ACCEPT");
DIAGMUTEX(PTEXT,"PTEXT");
DIAGMUTEX(ARDP_RQALLOC,"ARDP_RQALLOC");
DIAGMUTEX(ARDP_SELFNUM,"ARDP_SELFNUM");
DIAGMUTEX(DNSCACHE,"DNSCACHE");
DIAGMUTEX(ALLDNSCACHE,"ALLDNSCACHE");
DIAGMUTEX(FILES,"FILES");
DIAGMUTEX(FILELOCK,"FILELOCK");
#endif
}
#endif /*NDEBUG*/

View File

@@ -0,0 +1,19 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*
* Written by swa 11/93 to handle error reporting consistently in libardp
*/
#include <usc-license.h>
#include <ardp.h>
#include <pfs_threads.h>
#ifdef NEVERDEFINED
int perrno = 0; /* Declare it. */
#endif
EXTERN_INT_DEF(perrno);

View File

@@ -0,0 +1,420 @@
/*
* Copyright (c) 1991, 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*
* Written by bcn 1989-92 as part of dirsend.c in the Prospero distribution
* Modified by bcn 1/93 moved to ardp library - added asynchrony
*/
#include <usc-license.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#ifdef AIX
#include <sys/select.h>
#endif
#include <ardp.h>
#include <perrno.h>
#include <pmachine.h> /* for bcopy() */
extern RREQ ardp_activeQ; /* Info about active requests */
extern RREQ ardp_completeQ; /* Info about completed reqs */
extern int ardp_port; /* Opened UDP port */
extern int pfs_debug; /* Debug level */
int ardp_activeQ_len; /* Length of activeQ */
static struct timeval zerotime = {0, 0}; /* Used by select */
#define max(x,y) (x > y ? x : y)
static ardp__pr_ferror(int errcode);
/*
* ardp_process_active - process active requests
*
* ardp_process_active takes no arguments. It checks to see if any responses
* are pending on the UDP port, and if so processes them, adding them
* to the request structures on ardp_activeQ. If no requests are pending
* ardp_process_active processes and requests requiring retries then
* returns.
*
*/
int
ardp_process_active()
{
fd_set readfds; /* Used for select */
struct sockaddr_in from; /* Reply received from */
int from_sz; /* Size of address structure */
int hdr_len; /* Header Length */
char *ctlptr; /* Pointer to control field */
unsigned short cid = 0; /* Connection ID from rcvd pkt */
unsigned char rdflag11; /* First byte of flags (bit vect)*/
unsigned char rdflag12; /* Second byte of flags (int) */
unsigned char tchar; /* For decoding extra fields */
unsigned short stmp; /* Temp short for conversions */
unsigned long ltmp; /* Temp long for converions */
int tmp; /* Temporaty return value */
int nr; /* Number octest received */
long now; /* The current time */
RREQ req = NOREQ; /* To store request info */
PTEXT pkt = NOPKT; /* Packet being processed */
PTEXT ptmp = NOPKT; /* Packet being processed */
assert(P_IS_THIS_THREAD_MASTER()); /* something_received not MT-Safe */
check_for_pending:
/* Set list of file descriptors to be checked by select */
FD_ZERO(&readfds);
FD_SET(ardp_port, &readfds);
/* select - either recv is ready, or not */
/* see if timeout or error or wrong descriptor */
tmp = select(ardp_port + 1, &readfds, (fd_set *)0, (fd_set *)0, &zerotime);
/* If tmp is zero, then nothing to process, check for timeouts */
if(tmp == 0) {
now = time(NULL);
req = ardp_activeQ;
while(req) {
if (req->status == ARDP_STATUS_ACKPEND) {
ardp_xmit(req, -1 /* just ACK; send no data packets */);
req->status = ARDP_STATUS_ACTIVE;
}
if((req->wait_till.tv_sec) && (now >= req->wait_till.tv_sec)) {
if(req->retries_rem-- > 0) {
req->timeout_adj.tv_sec = ARDP_BACKOFF(req->timeout_adj.tv_sec);
if (pfs_debug >= 8) {
fprintf(stderr,"Connection %d timed out - Setting timeout to %d seconds.\n",
ntohs(req->cid), (int) req->timeout_adj.tv_sec);
}
req->wait_till.tv_sec = now + req->timeout_adj.tv_sec;
ardp_xmit(req, req->pwindow_sz);
} else {
if(pfs_debug >= 8) {
fprintf(stderr,"Connection %d timed out - Retry count exceeded.\n",
ntohs(req->cid) );
(void) fflush(stderr);
}
req->status = ARDP_TIMEOUT;
EXTRACT_ITEM(req,ardp_activeQ);
--ardp_activeQ_len;
APPEND_ITEM(req,ardp_completeQ);
}
}
req = req->next;
}
return(ARDP_SUCCESS);
}
/* If negative, then return an error */
if((tmp < 0) || !FD_ISSET(ardp_port, &readfds)) {
if (pfs_debug)
fprintf(stderr, "select failed : returned %d port=%d\n",
tmp, ardp_port);
return(ardp__pr_ferror(ARDP_SELECT_FAILED));
}
/* Process incoming packets */
pkt = ardp_ptalloc();
pkt->start = pkt->dat;
from_sz = sizeof(from);
if ((nr = recvfrom(ardp_port, pkt->start, sizeof(pkt->dat),
0, &from, &from_sz)) < 0) {
if (pfs_debug) perror("recvfrom");
ardp_ptlfree(pkt);
return(ardp__pr_ferror(ARDP_BAD_RECV));
}
pkt->length = nr;
*(pkt->start + pkt->length) = '\0';
if (pfs_debug >= 6)
fprintf(stderr,"Received packet from %s\n", inet_ntoa(from.sin_addr));
/* If the first byte is greater than 31 we have an old version */
/* response - return error */
if((hdr_len = (unsigned char) *(pkt->start)) > 31) {
ardp_ptfree(pkt);
if(ardp_activeQ->next == NOREQ)
return(ardp__pr_ferror(ARDP_BAD_VERSION));
else goto check_for_pending;
}
/* For the current format, the first two bits are a version number */
/* and the next six are the header length (including the first byte). */
ctlptr = pkt->start + 1;
if(hdr_len >= 3) { /* Connection ID */
bcopy2(ctlptr,&stmp);
if(stmp) cid = stmp;
ctlptr += 2;
}
/* Match up response with request */
req = ardp_activeQ;
while(req) {
if(cid == req->cid) break;
req = req->next;
}
if(!req) { /* The request isn't on the active queue */
if (pfs_debug>=6)
fprintf(stderr,"Packet received for inactive request (cid %d)\n",
ntohs(cid));
ardp_ptfree(pkt);
/* The following can be removed when old servers are gone */
if((cid == 0) && (ardp_activeQ->next == NOREQ))
return(ardp__pr_ferror(ARDP_BAD_VERSION));
goto check_for_pending;
}
if(hdr_len >= 5) { /* Packet number */
bcopy2(ctlptr,&stmp);
pkt->seq = ntohs(stmp);
ctlptr += 2;
}
else { /* No packet number specified, so this is the only one */
pkt->seq = 1;
req->rcvd_tot = 1;
}
if(hdr_len >= 7) { /* Total number of packets */
bcopy2(ctlptr,&stmp); /* 0 means don't know */
if(stmp) req->rcvd_tot = ntohs(stmp);
ctlptr += 2;
}
if(hdr_len >= 9) { /* Receievd through */
bcopy2(ctlptr,&stmp); /* 1 means received request */
req->prcvd_thru = max(ntohs(stmp),req->prcvd_thru);
ctlptr += 2;
}
if(hdr_len >= 11) { /* Service requested wait */
bcopy2(ctlptr,&stmp);
if(stmp || (req->svc_rwait != ntohs(stmp))) {
now = time(NULL);
/* New or non-zero requested wait value */
req->svc_rwait = ntohs(stmp);
if(pfs_debug >= 8)
fprintf(stderr,"Service asked us to wait %d seconds\n",
req->svc_rwait);
/* Adjust out timeout */
req->timeout_adj.tv_sec = max(req->timeout.tv_sec,req->svc_rwait);
req->wait_till.tv_sec = now + req->timeout_adj.tv_sec;
/* Reset the retry count */
req->retries_rem = req->retries;
}
ctlptr += 2;
}
if(hdr_len >= 12) { /* Flags (1st byte) */
bcopy1(ctlptr,&rdflag11);
if(rdflag11 & 0x80) {
if(pfs_debug >= 8)
fprintf(stderr,"Ack requested\n");
req->status = ARDP_STATUS_ACKPEND;
}
if(rdflag11 & 0x40) {
if(pfs_debug >= 8)
fprintf(stderr,"Sequenced control packet\n");
pkt->length = -1;
}
ctlptr += 1;
}
if(hdr_len >= 13) { /* Flags (2nd byte) */
/* Reserved for future use */
bcopy1(ctlptr,&rdflag12);
ctlptr += 1;
if(rdflag12 == 2) {
/* Attempt to set back prcvd_thru */
bcopy2(pkt->start+7,&stmp);
req->prcvd_thru = ntohs(stmp);
}
if(rdflag12 == 1) {
/* ARDP Connection Refused */
if(pfs_debug >= 8)
fprintf(stderr,"***ARDP connection refused by server***\n");
req->status = ARDP_REFUSED;
EXTRACT_ITEM(req,ardp_activeQ);
--ardp_activeQ_len;
APPEND_ITEM(req,ardp_completeQ);
goto check_for_pending;
}
if(rdflag12 == 4) {
/* Server Redirect */
bcopy4(ctlptr,&(req->peer_addr));
ctlptr += 4;
bcopy2(ctlptr,&(req->peer_port));
ctlptr += 2;
if(pfs_debug >= 8)
fprintf(stderr,"***ARDP redirect to %s(%d)***\n",
inet_ntoa(req->peer_addr),PEER_PORT(req));
ardp_xmit(req, req->pwindow_sz);
}
if(rdflag12 == 254) {
tchar = *ctlptr;
ctlptr++;
if(tchar & 0x1) { /* Queue position */
bcopy2(ctlptr,&stmp);
req->inf_queue_pos = ntohs(stmp);
if(pfs_debug >= 8)
fprintf(stderr,"Current queue position on server is %d\n",
req->inf_queue_pos);
ctlptr += 2;
}
if(tchar & 0x2) { /* Expected system time */
bcopy4(ctlptr,&ltmp);
req->inf_sys_time = ntohl(ltmp);
if(pfs_debug >= 8)
fprintf(stderr,"Expected system time is %d seconds\n",
req->inf_sys_time);
ctlptr += 4;
}
}
}
/* If ->seq 0, then an unsequenced control packet */
if(pkt->seq == 0) {
ardp_ptfree(pkt);
goto check_for_pending;
}
if(pkt->length >= 0) pkt->length -= hdr_len;
pkt->start += hdr_len;
pkt->text = pkt->start;
pkt->ioptr = pkt->start;
if(pfs_debug >= 8) fprintf(stderr,"Packet %d of %d (cid=%d)\n", pkt->seq,
req->rcvd_tot, ntohs(req->cid));
if (req->rcvd == NOPKT) {
/* Add it as the head of empty doubly linked list */
req->rcvd = pkt;
pkt->previous = pkt;
if(pkt->seq == 1) {
req->comp_thru = pkt;
req->rcvd_thru = 1;
/* If only one packet, then return it. We will assume */
/* that it is not a sequenced control packet */
if(req->rcvd_tot == 1) goto req_complete;
}
goto ins_done;
}
if(req->comp_thru && (pkt->seq <= req->rcvd_thru))
ardp_ptfree(pkt); /* Duplicate */
else if(pkt->seq < req->rcvd->seq) { /* First (sequentially) */
pkt->next = req->rcvd;
pkt->previous = req->rcvd->previous;
req->rcvd->previous = pkt;
req->rcvd = pkt;
if(req->rcvd->seq == 1) {
req->comp_thru = req->rcvd;
req->rcvd_thru = 1;
}
}
else { /* Insert later in the packet list unless duplicate */
ptmp = (req->comp_thru ? req->comp_thru : req->rcvd);
while (pkt->seq > ptmp->seq) {
if(ptmp->next == NULL) {
/* Insert at end */
ptmp->next = pkt;
pkt->previous = ptmp;
pkt->next = NULL;
req->rcvd->previous = pkt;
goto ins_done;
}
ptmp = ptmp->next;
}
if(ptmp->seq == pkt->seq) /* Duplicate */
ardp_ptfree(pkt);
else { /* insert before ptmp (we know were not first) */
ptmp->previous->next = pkt;
pkt->previous = ptmp->previous;
pkt->next = ptmp;
ptmp->previous = pkt;
}
}
ins_done:
/* Find out how much is complete and remove sequenced control packets */
while(req->comp_thru && req->comp_thru->next &&
(req->comp_thru->next->seq == (req->comp_thru->seq + 1))) {
/* We have added one more in sequence */
if(pfs_debug >= 8)
fprintf(stderr,"Packets now received through %d\n",
req->comp_thru->next->seq);
if(req->comp_thru->length == -1) {
/* Old comp_thru was a sequenced control packet */
ptmp = req->comp_thru;
req->comp_thru = req->comp_thru->next;
req->rcvd_thru = req->comp_thru->seq;
EXTRACT_ITEM(ptmp,req->rcvd);
ardp_ptfree(ptmp);
}
else {
/* Old comp_thru was a data packet */
req->comp_thru = req->comp_thru->next;
req->rcvd_thru = req->comp_thru->seq;
}
/* Update outgoing packets */
ardp_headers(req);
/* We've made progress, so reset timeout and retry count */
req->timeout_adj.tv_sec = max(req->timeout.tv_sec,req->svc_rwait);
req->retries_rem = req->retries;
}
/* See if there are any gaps - possibly toggle GAP status */
if(!req->comp_thru || req->comp_thru->next) {
if (req->status == ARDP_STATUS_ACTIVE) req->status = ARDP_STATUS_GAPS;
}
else if (req->status == ARDP_STATUS_GAPS) req->status = ARDP_STATUS_ACTIVE;
/* If incomplete, wait for more */
if (!(req->comp_thru) || (req->comp_thru->seq != req->rcvd_tot))
goto check_for_pending;
req_complete:
if (pfs_debug >= 7) {
fprintf(stderr,"The complete response has been received.\n");
(void) fflush(stderr);
}
if(req->status == ARDP_STATUS_ACKPEND) {
if (pfs_debug >= 7) {
if (req->peer.sin_family == AF_INET)
fprintf(stderr,"Acknowledging final packet to %s(%d)\n",
inet_ntoa(req->peer_addr), PEER_PORT(req));
else fprintf(stderr,"Acknowledging final packet\n");
(void) fflush(stderr);
}
ardp_xmit(req, req->pwindow_sz);
}
req->status = ARDP_STATUS_COMPLETE;
req->inpkt = req->rcvd;
EXTRACT_ITEM(req,ardp_activeQ);
--ardp_activeQ_len;
APPEND_ITEM(req,ardp_completeQ);
return(ARDP_SUCCESS);
}
static int
ardp__pr_ferror(int errcode)
{
RREQ creq;
while(ardp_activeQ) {
creq = ardp_activeQ;
ardp_activeQ->status = errcode;
EXTRACT_ITEM(creq,ardp_activeQ);
--ardp_activeQ_len;
APPEND_ITEM(creq,ardp_completeQ);
}
perrno = errcode;
return(errcode);
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 1989, 1990, 1991 by the University of Washington
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>.
*
* Written by bcn 1989-91 as part of the Prospero distribution
* Modified by bcn 1/93 changed to conform to ardp.h
* Modified by swa 12/93 threads added.
*/
#include <uw-copyright.h>
#include <usc-copyr.h>
#include <ardp.h>
#include <stdlib.h> /* For malloc or free */
#include <pfs_threads.h>
#include <mitra_macros.h>
/* "free" conflicted with free() - Mitra */
static PTEXT lfree = NOPKT; /* locked with p_th_mutexPTEXT */
int ptext_count = 0;
int ptext_max = 0;
/*
* ardp_ptalloc - allocate and initialize ptext structure
*
* ardp_ptalloc returns a pointer to an initialized structure of type
* PTEXT. If it is unable to allocate such a structure, it
* returns NULL (NOPKT).
*/
PTEXT
ardp_ptalloc()
{
PTEXT pt;
TH_STRUC_ALLOC(ptext,PTEXT,pt);
/* Initialize and fill in default values. */
pt->seq = 0;
pt->length = 0;
/* The offset is to leave room for additional headers */
pt->start = pt->dat + ARDP_PTXT_HDR;
pt->text = pt->start;
pt->ioptr = pt->start;
pt->mbz = 0;
return(pt);
}
/*
* ardp_ptfree - free a PTEXT structure
*
* ardp_ptfree takes a pointer to a PTEXT structure and adds it to
* the free list for later reuse.
*/
void ardp_ptfree(pt)
PTEXT pt;
{
TH_STRUC_FREE(ptext,PTEXT,pt);
}
/*
* ardp_ptlfree - free a PTEXT structure
*
* ardp_ptlfree takes a pointer to a PTEXT structure frees it and any linked
* PTEXT structures. It is used to free an entrie list of PTEXT
* structures.
*/
void ardp_ptlfree(pt)
PTEXT pt;
{
TH_STRUC_LFREE(PTEXT,pt,ardp_ptfree);
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*
* Written by bcn 2/93 to send reply to request
* Gutted by swa 11/93 functionality moved to ardp_breply().
*/
#include <usc-license.h>
#include <stdio.h>
#include <ardp.h>
/*
* ardp_reply - send a null-terminated string as a reply to a request
*
* ardp_reply reply takes request to which a reply is to be sent
* a flags field, and a message to be sent to the client in response
* to the request. ardp_reply then calls ardp_reply() to do the work.
*
* If space remains in the packet, the response is buffered pending
* subsequent replies, unless the ARDP_REPL_COMPLETE has been specified,
* in which case all data is sent. If the size of the buffered response
* approaches the maximum packet size, the buffered data is sent, and
* and a new packet is started to hold any remaining data from the current
* message. (This is implemented by ardp_breply()).
*/
int
ardp_reply(RREQ req, /* Request to which this is a response */
int flags, /* Whether this is the final message */
char *message) /* The data to be sent */
{
return ardp_breply(req, flags, message, 0);
}

View File

@@ -0,0 +1,471 @@
/*
* Copyright (c) 1991 by the University of Washington
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>.
*
* Written by bcn 1991 as transmit in rdgram.c (Prospero)
* Modified by bcn 1/93 modularized and incorporated into new ardp library
*/
#include <uw-copyright.h>
#include <usc-copyr.h>
#include <stdio.h>
#include <ardp.h>
#include <pmachine.h> /* for bcopy() */
#include <plog.h>
EXTERN_MUTEXED_DECL(RREQ,ardp_doneQ);
EXTERN_MUTEXED_DECL(RREQ,ardp_runQ);
extern int ardp_srvport;
extern int ardp_prvport;
extern int dQlen; /* mutexed with ardp_doneQ */
extern int dQmaxlen;
int ardp_clear_doneQ_loginfo = 0; /* Clear log info from the doneQ.
Set by the -n option to
dirsrv. */
/*
* ardp_respond - respond to request
*
* ardp_respond takes a request block whose ->outpkt element is a pointer
* to a list of packets that have not yet been returned. It moves the
* packets to the transmission queue of the request (->trns) and assigns a
* sequence number to each packet. If options is ARDP_R_COMPLETE, it
* also sets the ->trns_tot field of the request indicating the total
* number of packets in the response. if the ARDP_R_NOSEND option is
* not specified, the current packet is also sent to the client.
*
* ardp_respond() expects the text of the packet to have a trailing null
* at the end of it, which is transmitted for safety's sake.
* (noted: swa, 8/5/93). This explains some bugs...
*/
int
ardp_respond(req, options)
RREQ req;
int options;
{
char buf[ARDP_PTXT_DSZ];
int sent;
int retval = ARDP_SUCCESS; /* Return value */
unsigned short cid = htons(req->cid);
unsigned short nseq = 0;
unsigned short ntotal = 0;
unsigned short rcvdthru = 0;
unsigned short bkoff = 0;
PTEXT tpkt; /* Temporary pkt pointer */
*buf = '\0';
if(req->peer_ardp_version < 0) cid = 0;
if(req->status == ARDP_STATUS_FREE)
internal_error("Attempt to respond to free RREQ\n");
if(!req->outpkt) return(ARDP_BAD_REQ);
more_to_process:
if(!req->trns) req->outpkt->seq = 1;
else req->outpkt->seq = req->trns->previous->seq + 1;
if((options & ARDP_R_COMPLETE) && (req->outpkt->next == NOPKT)) {
/* It's the last packet to send. */
req->trns_tot = req->outpkt->seq; /* set the total # of packets; now
known. */
/* Test this condition later to see if the server (us) needs to request
that the client ACK. The server will request an ACK if we had
previously told the client to back off and now are rescinding that.
*/
}
nseq = htons((u_short) req->outpkt->seq);
ntotal = htons((u_short) req->trns_tot);
if((req->peer_ardp_version < 0)&&(req->peer_ardp_version != -2)) {
if(req->trns_tot) sprintf(buf, "MULTI-PACKET %d OF %d",
req->outpkt->seq, req->trns_tot);
else sprintf(buf,"MULTI-PACKET %d\n",req->outpkt->seq);
}
/* Note that in the following, we don't have to make sure */
/* there is room for the header in the packet because we */
/* are the only one that moves back the start, and ptalloc */
/* allocates space for us in all packets it creates */
/* If a single message and no connection ID to return, */
/* and no pending server requested wait pending then */
/* we can leave the control fields out */
if((req->trns_tot == 1) && (req->svc_rwait == 0)) {
/* Once V4 clients gone, the next if condition can be removed */
if((req->peer_ardp_version > -1)||(req->peer_ardp_version == -2)) {
if(req->cid == 0) {
req->outpkt->start -= 1;
req->outpkt->length += 1;
*req->outpkt->start = (char) 1;
}
else {
req->outpkt->start -= 3;
req->outpkt->length += 3;
*req->outpkt->start = (char) 3;
bcopy2(&cid,req->outpkt->start+1); /* Conn ID */
}
}
}
/* Fill in the control fields */
else {
/* For old versions, assume that svc_rwait of > 5 is too long. */
/* For new versions, if we set the svc_rwait before to any non-default
value, now set it to 0. (client's default). */
/* if we might have to set octet 11 flags (in this case, the ACK flag),
then we need to send an 11-byte request.
This is the case either:
(a) if we need to clear a service requested wait or
(b) if we are sending the last packet of a window, so that the
client should ACK (or request a retry) before the next one goes.
*/
if (/* Case (A) -- clear wait */
((req->peer_ardp_version < 0 && req->svc_rwait > 5)
|| (req->peer_ardp_version == 0 && req->svc_rwait)
|| (req->svc_rwait_seq > req->prcvd_thru))
|| /* Case (B) -- sending last packet of a window */
(req->outpkt->seq == req->prcvd_thru + req->pwindow_sz)) {
req->outpkt->start -= 12;
req->outpkt->length += 12;
*req->outpkt->start = (char) 12;
rcvdthru = htons((u_short) req->rcvd_thru);
bcopy2(&rcvdthru,req->outpkt->start+7); /* Recvd Through */
/* XXX Note that when all clients V5, new wait will be 0 */
/* Assume we should cancel the wait and remember when reset */
if((req->peer_ardp_version < 0 && req->svc_rwait > 5)
|| (req->peer_ardp_version == 0 && req->svc_rwait)) {
if(req->peer_ardp_version < 0)
req->svc_rwait = 5;
else
req->svc_rwait = 0;
req->svc_rwait_seq = req->outpkt->seq; /* This was the sequence
number it was reset
on. */
/* We'll ask for an acknowledgement when we send the last
packet of the response. */
}
bkoff = htons((u_short) req->svc_rwait);
bcopy2(&bkoff,req->outpkt->start+9); /* New ttwait */
/* Send an ACK IF: */
if ((/* (A1) It's the last packet */
(req->trns_tot && req->outpkt->seq == req->trns_tot)
&& /* (A2) If we reduced a previously requested wait, and haven't
yet had that reduction acknowledged, then ask for an
acknowledgement. */
(req->svc_rwait_seq > req->prcvd_thru))
|| /* OR: Case (B) -- sending last packet of a window */
(req->outpkt->seq == req->prcvd_thru + req->pwindow_sz)) {
req->retries_rem = 4;
req->wait_till.tv_sec = time(NULL) + req->timeout_adj.tv_sec;
*(req->outpkt->start+11) = 0x80; /* Request ack */
} else {
*(req->outpkt->start+11) = 0x00; /* Don't request ack */
}
}
else {
req->outpkt->start -= 7;
req->outpkt->length += 7;
*req->outpkt->start = (char) 7;
}
bcopy2(&cid,req->outpkt->start+1); /* Conn ID */
bcopy2(&nseq,req->outpkt->start+3); /* Pkt no */
bcopy2(&ntotal,req->outpkt->start+5); /* Total */
}
#if 0
/* commented out by swa@isi.edu, since nulls in packets are now significant
to the ARDP library. Therefore, one should NOT be appended to each
packet in the data area. */
/* Make room for the trailing null */
req->outpkt->length += 1;
#endif
/* Only send if packet not yet received. */
/* Do honor the window of req->pwindow_sz packets. */
if((!(options & ARDP_R_NOSEND)) &&
(req->outpkt->seq <= (req->prcvd_thru + req->pwindow_sz)) &&
(req->outpkt->seq > req->prcvd_thru) /* This packet not yet received */
) {
retval = ardp_snd_pkt(req->outpkt,req);
}
/* Add packet to req->trns */
tpkt = req->outpkt;
EXTRACT_ITEM(tpkt,req->outpkt);
APPEND_ITEM(tpkt,req->trns);
if(req->outpkt) goto more_to_process;
/* If complete then add request structure to done */
/* queue in case we have to retry. */
if(options & ARDP_R_COMPLETE) {
RREQ match_in_runQ; /* Variable for indexing ardp_runQ */
/* Request has been processed, here you can accumulate */
/* statistics on system time or service time */
plog(L_QUEUE_COMP, req, "Requested service completed");
arch_set_etime(req); /* bajan */
EXTERN_MUTEXED_LOCK(ardp_runQ);
for (match_in_runQ = ardp_runQ; match_in_runQ; match_in_runQ = match_in_runQ->next) {
if(match_in_runQ == req) {
EXTRACT_ITEM(req, ardp_runQ);
break;
}
}
/* At this point, 'req' is the completed request structure. It is
definitely not on the ardp_runQ, and if it was, it's been removed.
*/
EXTERN_MUTEXED_UNLOCK(ardp_runQ);
if((req->cid == 0) || (dQmaxlen <= 0)) {
/* If request has no CID (can't be matched on a retry) or
if done-Q max length is <= 0 (i.e., don't keep a doneQ), then
just throw away the request now that it's done. --swa */
#if 0 /* ask BCN about this. Should never be
necessary, since req->outpkt is always going
to be NULL or we wouldn't be here. */
req->outpkt = NULL;
#endif
ardp_rqfree(req);
}
else {
/* This item should be put on the doneQ; don't just throw it away.
*/
/* Note that this code will not handle a reduction in the size of
dQmaxlen; if anywhere you reset it to a smaller value, that code
will have to truncate the queue. */
EXTERN_MUTEXED_LOCK(ardp_doneQ);
if(dQlen <= dQmaxlen) {
/* Add to start */
#ifndef NDEBUG /* this helps debugging and slightly cuts down
on memory usage of the doneq. */
if (ardp_clear_doneQ_loginfo)
ardp_rq_partialfree(req);
#endif
PREPEND_ITEM(req, ardp_doneQ);
dQlen++;
} else {
/* The last item in the queue is ardp_doneQ->previous. */
/* Use a variable to denote it, so that the EXTRACT_ITEM macro
doesn't encounter problems (since it internally modifies the
referent of the name ardp_doneQ->previous). */
register RREQ doneQ_lastitem = ardp_doneQ->previous;
/* Add new request to start */
#ifndef NDEBUG /* this helps debugging and slightly cuts down
on memory usage of the doneq. */
if (ardp_clear_doneQ_loginfo)
ardp_rq_partialfree(req);
#endif
PREPEND_ITEM(req, ardp_doneQ);
/* Now, prepare to remove the last item in the queue */
/* If the request to remove was not acknowledged by the
clients, log the fact */
if(doneQ_lastitem->svc_rwait_seq >
doneQ_lastitem->prcvd_thru) {
plog(L_QUEUE_INFO,doneQ_lastitem,
"Requested ack never received (%d of %d/%d ack)",
doneQ_lastitem->prcvd_thru,
doneQ_lastitem->svc_rwait_seq,
doneQ_lastitem->trns_tot);
}
/* Now do the removal and free it. */
EXTRACT_ITEM(doneQ_lastitem, ardp_doneQ);
ardp_rqfree(doneQ_lastitem);
}
EXTERN_MUTEXED_UNLOCK(ardp_doneQ);
}
}
return(retval);
}
/*
* ardp_rwait - sends a message to a client requesting
* that it wait for service. This message indicates that
* there may be a delay before the request can be processed.
* The recipient should not attempt any retries until the
* time specified in this message has elapsed. Depending on the
* protocol version in use by the client, the additional
* queue position and system time arguments may be returned.
*/
int
ardp_rwait(RREQ req, /* Request to which this is a reply */
int timetowait, /* How long client should wait */
short qpos, /* Queue position */
/* Note stime is a System call in solaris, changed to systemtime */
int systemtime) /* System time */
{
PTEXT r = ardp_ptalloc();
short cid = htons(req->cid);
short nseq = 0;
short zero = 0;
short backoff;
short stmp;
int ltmp;
int tmp;
if(req->peer_ardp_version < 0) cid = 0;
/* Remember that we sent a server requested wait and assume */
/* it took effect, though request will be unsequenced */
/* This seems bogus to me. Rather, more appropriate would be to send an
unsequenced control packet if the requested wait is being extended and
a sequenced packet if the wait is being shortened, since the shortening
of the wait is an event which requires an acknowledgement. */
/* Note, however, that this shortening is a way the current function is not
used. */
req->svc_rwait_seq = req->prcvd_thru; /* Mark the latest requested wait as
definitely having been received.
This is not necessary, actually --
leaving this set to zero is ok. */
req->svc_rwait = timetowait;
*r->start = (char) 11;
r->length = 11;
backoff = htons((u_short) timetowait);
bcopy2(&cid,r->start+1); /* Connection ID */
bcopy2(&nseq,r->start+3); /* Packet number */
bcopy2(&zero,r->start+5); /* Total packets */
bcopy2(&zero,r->start+7); /* Received through */
bcopy2(&backoff,r->start+9); /* Backoff */
if((req->peer_ardp_version >= 0) && (qpos || systemtime)) {
r->length = 14;
bzero3(r->start+11);
*(r->start+12) = (unsigned char) 254;
if(qpos) *(r->start+13) |= (unsigned char) 1;
if(systemtime) *(r->start+13) |= (unsigned char) 2;
if(qpos) {
stmp = htons(qpos);
bcopy2(&stmp,r->start+r->length);
r->length += 2;
}
if(systemtime) {
ltmp = htonl(systemtime);
bcopy4(&ltmp,r->start+r->length);
r->length += 4;
}
*r->start = (char) r->length;
}
tmp = ardp_snd_pkt(r,req);
ardp_ptfree(r);
return(tmp);
}
/*
* ardp_refuse - sends a message to the recipient indicating
* that its connection attempt has been refused.
*/
int
ardp_refuse(RREQ req)
{
PTEXT r;
short cid = htons(req->cid);
short zero = 0;
int tmp;
/* If old version won't understand refused */
if(req->peer_ardp_version < 0) return(ARDP_FAILURE);
r = ardp_ptalloc();
*r->start = (char) 13;
r->length = 13;
bcopy2(&cid,r->start+1); /* Connection ID */
bcopy2(&zero,r->start+3); /* Packet number */
bcopy2(&zero,r->start+5); /* Total packets */
bcopy2(&zero,r->start+7); /* Received through */
bcopy2(&zero,r->start+9); /* Backoff */
bzero2(r->start+11); /* Flags */
*(r->start + 12) = (unsigned char) 1; /* Refused */
tmp = ardp_snd_pkt(r,req);
ardp_ptfree(r);
return(tmp);
}
/*
* ardp_redirect - sends a message to the recipient indicating that
* all unacknowledged packets should be sent to a new target destination.
* The target specifies the host address and the UDP port in network
* byte order. For now, redirections should only occur before any
* request packets have been acknowledged, or response packets sent.
*/
int
ardp_redirect(RREQ req, /* Request to be redirected */
struct sockaddr_in *target) /* Address of new server */
{
PTEXT r;
short cid = htons(req->cid);
int tmp;
/* Old versions don't support redirection */
if(req->peer_ardp_version < 0) return(ARDP_FAILURE);
r = ardp_ptalloc();
*r->start = (char) 19;
r->length = 19;
bcopy2(&cid,r->start+1); /* Connection ID */
bzero(r->start+3,9); /* Pktno, total, rcvd, swait, flags1 */
*(r->start + 12) = '\004'; /* Redirect option */
bcopy4(&(target->sin_addr),r->start+13);
bcopy2(&(target->sin_port),r->start+17);
tmp = ardp_snd_pkt(r,req);
ardp_ptfree(r);
return(tmp);
}
/*
* ardp_ack - sends an acknowledgment message to the client indicating
* that all packets through req->rcvd_thru have been recived. It is
* only called on receipt of a multi-packet server request.
*/
int
ardp_acknowledge(RREQ req) /* Request to which this is a reply */
{
PTEXT r = ardp_ptalloc();
short cid = htons(req->cid);
short rcvd = htons(req->rcvd_thru);
short zero = 0;
int tmp;
*r->start = (char) 9;
r->length = 9;
bcopy2(&cid,r->start+1); /* Connection ID */
bcopy2(&zero,r->start+3); /* Packet number */
bcopy2(&zero,r->start+5); /* Total packets */
bcopy2(&rcvd,r->start+7); /* Received through */
tmp = ardp_snd_pkt(r,req);
ardp_ptfree(r);
return(tmp);
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-copyr.h>.
*
* Written by bcn 1/93 to check and/or wait for completion of request
*/
#include <usc-copyr.h>
#include <stdio.h>
#ifdef AIX
#include <sys/select.h>
#endif
#include <ardp.h>
#include <perrno.h>
#include <pmachine.h>
extern RREQ ardp_activeQ; /* Info about active requests */
extern RREQ ardp_completeQ;/* Info about completed reqs */
extern int ardp_port; /* Opened UDP port */
extern int pfs_debug; /* Debug level */
/*
* ardp_retrieve - check and/or wait for completion of request
*
* ardp_retrieve takes a request and a time to wait. It will check to
* see if the request is complete and if so, returns ARDP_SUCCESS.
* If not complete, ardp_retrieve will wait up till the time to wait
* before returning. If still incomplete it will return ARDP_PENDING.
* A time to wait of -1 indicates that one should not return until
* complete, or until a timeout occurs. On any failure (other than
* still pending), an error code is returned.
*
* BUGS: Right now, only accepts ttwait values of 0 and -1. If
* positive, it is currently treated as -1.
*/
int
ardp_retrieve(req,ttwait)
RREQ req; /* Request to wait for */
int ttwait; /* Time to wait in microseconds */
{
fd_set readfds; /* Used for select */
struct timeval *selwait; /* Time to wait for select */
int tmp; /* Hold value returned by select */
/* XXX For now only support ttwait values of 0 and -1 */
if(ttwait > 0) return(ARDP_FAILURE);
p_clear_errors();
if(req->status == ARDP_STATUS_FREE) {
fprintf(stderr,"Attempt to retrieve free RREQ\n");
abort();
return(ARDP_BAD_REQ);
}
if(req->status == ARDP_STATUS_NOSTART) {
perrno = ARDP_BAD_REQ;
return(perrno);
}
check_for_more:
ardp_process_active();
if((req->status == ARDP_STATUS_COMPLETE) || (req->status > 0)) {
EXTRACT_ITEM(req,ardp_completeQ);
if(pfs_debug >= 9) {
PTEXT ptmp; /* debug-step through req->rcvd */
if(req->status > 0) fprintf(stderr,"Request failed (error %d)!",
req->status);
else fprintf(stderr,"Packets received...");
ptmp = req->rcvd;
while(ptmp) {
fprintf(stderr,"Packet %d:\n",ptmp->seq);
ardp_showbuf(ptmp->start, ptmp->length, stderr);
putc('\n', stderr);
ptmp = ptmp->next;
}
(void) fflush(stderr);
}
if(req->status == ARDP_STATUS_COMPLETE) return(ARDP_SUCCESS);
else {
perrno = req->status; /* Specific error */
return(perrno);
}
}
if(ttwait == 0) return(ARDP_PENDING);
/* Here we should figure out how long to wait, a minimum of */
/* ttwait, or the first retry timer for any pending request */
/* For the time being, we use the retry timer of the */
/* current request. */
if (pfs_debug >= 6) fprintf(stderr,"Waiting for reply...");
FD_ZERO(&readfds);
FD_SET(ardp_port, &readfds);
selwait = &(req->timeout_adj);
/* select - either recv is ready, or timeout */
/* see if timeout or error or wrong descriptor */
tmp = select(ardp_port + 1, &readfds, (fd_set *)0, (fd_set *)0, selwait);
/* Packet received, or timeout - both handled by ardp_process_active */
if(tmp >= 0) goto check_for_more;
if (pfs_debug) fprintf(stderr, "select failed: returned %d\n", tmp);
perrno = ARDP_SELECT_FAILED;
return(perrno);
}

View File

@@ -0,0 +1,240 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*
* Written by bcn 1991 as part of the Prospero distribution
* Modified by bcn 1/93 extended rreq structure
* Modified by swa 11/93 multithreaded
*/
#include <usc-license.h>
#include <stdio.h>
#include <ardp.h>
#include <stdlib.h> /* malloc or free */
#include <pmachine.h> /* for bzero() */
#include <pfs.h> /* for pafree and stfree */
/* When debugging the ARDP window flow control stuff, use these definitions. */
/* Defaults are set here. */
#if 0
#define ARDP_MY_WINDOW_SZ 2 /* Our window size;currently only implemented on
the client. Here, the client asks for a
window size of 2, for testing. */
#undef ARDP_DEFAULT_WINDOW_SZ /* Peer window size the server will use for its
default flow-control strategy. */ */
#define ARDP_DEFAULT_WINDOW_SZ 1 /* for testing. */
#endif
static ardp_default_timeout = ARDP_DEFAULT_TIMEOUT;
static ardp_default_retry = ARDP_DEFAULT_RETRY;
int ardp_priority = 0; /* Default priority */
static RREQ lfree = NOREQ;
int rreq_count = 0;
int rreq_max = 0;
#ifndef NDEBUG
static int rreq_member_of_list(RREQ rr, RREQ list);
#endif
extern RREQ ardp_pendingQ, ardp_runQ, ardp_doneQ;
/*
* rralloc - allocate and initialize an rreq structure
*
* ardp_rqalloc returns a pointer to an initialized structure of type
* RREQ. If it is unable to allocate such a structure, it
* returns NOREQ (NULL).
*/
RREQ
ardp_rqalloc()
{
RREQ rq;
p_th_mutex_lock(p_th_mutexARDP_RQALLOC);
if(lfree) {
rq = lfree;
lfree = lfree->next;
}
else {
rq = (RREQ) malloc(sizeof(RREQ_ST));
if (!rq) return(NOREQ);
rreq_max++;
}
rreq_count++;
p_th_mutex_unlock(p_th_mutexARDP_RQALLOC);
rq->status = ARDP_STATUS_NOSTART;
#ifdef ARDP_MY_WINDOW_SZ
rq->flags = ARDP_FLAG_SEND_MY_WINDOW_SIZE; /* used by clients. */
#else
rq->flags = 0;
#endif
rq->cid = 0;
rq->priority = ardp_priority;
rq->pf_priority = 0;
rq->peer_ardp_version = 0;
rq->inpkt = NOPKT;
rq->rcvd_tot = 0;
rq->rcvd = NOPKT;
rq->rcvd_thru = 0;
#ifdef ARDP_MY_WINDOW_SZ /* This sets the window size we'll ask for */
rq->window_sz = ARDP_MY_WINDOW_SZ;
#else
rq->window_sz = 0;
#endif
rq->pwindow_sz = ARDP_DEFAULT_WINDOW_SZ; /* sets the window size we assume
our peer will accept in the
absence of an explicit
request. */
rq->comp_thru = NOPKT;
rq->outpkt = NOPKT;
rq->trns_tot = 0;
rq->trns = NOPKT;
rq->prcvd_thru = 0;
bzero(&(rq->peer),sizeof(rq->peer));
rq->rcvd_time.tv_sec = 0;
rq->rcvd_time.tv_usec = 0;
rq->svc_start_time.tv_sec = 0;
rq->svc_start_time.tv_usec = 0;
rq->svc_comp_time.tv_sec = 0;
rq->svc_comp_time.tv_usec = 0;
rq->timeout.tv_sec = ardp_default_timeout;
rq->timeout.tv_usec = 0;
rq->timeout_adj.tv_sec = ardp_default_timeout;
rq->timeout_adj.tv_usec = 0;
rq->wait_till.tv_sec = 0;
rq->wait_till.tv_usec = 0;
rq->retries = ardp_default_retry;
rq->retries_rem = ardp_default_retry;
rq->svc_rwait = 0;
rq->svc_rwait_seq = 0;
rq->inf_queue_pos = 0;
rq->inf_sys_time = 0;
#ifdef PROSPERO
rq->auth_info = NULL;
#endif /* PROSPERO */
rq->client_name = NULL;
rq->peer_sw_id = NULL;
rq->cfunction = NULL;
rq->cfunction_args = NULL;
rq->previous = NOREQ;
rq->next = NOREQ;
return(rq);
}
/*
* ardp_rqfree - free a RREQ structure
*
* ardp_rqfree takes a pointer to a RREQ structure and adds it to
* the free list for later reuse.
*/
void ardp_rqfree(rq)
RREQ rq;
{
#ifndef NDEBUG
/* This is different from the way we do consistency checking in the PFS
library, because here the status field is just sitting to be used. */
assert(rq->status != ARDP_STATUS_FREE);
rq->status = ARDP_STATUS_FREE;
CHECK_OFFLIST(rq); /* MITRA macro; probably does the same as those
listed below. Might never be defined. */
assert(!rreq_member_of_list(rq, ardp_pendingQ));
assert(!rreq_member_of_list(rq, ardp_runQ));
assert(!rreq_member_of_list(rq, ardp_doneQ));
#endif
/* Don't free inpkt or comp_thru, already on rcvd */
if(rq->rcvd) ardp_ptlfree(rq->rcvd);
/* But outpkt has not been added to trns */
if(rq->outpkt) ardp_ptlfree(rq->outpkt);
if(rq->trns) ardp_ptlfree(rq->trns);
#ifdef PROSPERO
if (rq->auth_info) pafree(rq->auth_info);
#endif /* PROSPERO */
if (rq->client_name) stfree(rq->client_name);
if (rq->peer_sw_id) stfree(rq->peer_sw_id);
p_th_mutex_lock(p_th_mutexARDP_RQALLOC);
rq->next = lfree;
rq->previous = NOREQ;
lfree = rq;
rreq_count--;
p_th_mutex_unlock(p_th_mutexARDP_RQALLOC);
}
#ifndef NDEBUG
/* Free just the fields that are needed only while processing the request
but not the fields that will be used for a request that is on the ardp_doneQ
so that the results can be retransmitted. This is only needed when
debugging the server. It is used in ardp_respond() and is #ifdef'd NDEBUG.
*/
void
ardp_rq_partialfree(RREQ rq)
{
#ifdef PROSPERO
if (rq->auth_info) { pafree(rq->auth_info); rq->auth_info = NULL; }
#endif /* PROSPERO */
if (rq->client_name) { stfree(rq->client_name); rq->client_name = NULL; }
if (rq->peer_sw_id) { stfree(rq->peer_sw_id); rq->peer_sw_id = NULL; }
}
#endif
/*
* ardp_rqlfree - free many RREQ structures
*
* ardp_rqlfree takes a pointer to a RREQ structure frees it and any linked
* RREQ structures. It is used to free an entrie list of RREQ
* structures.
*/
void
ardp_rqlfree(rq)
RREQ rq;
{
RREQ nxt;
while(rq != NOREQ) {
nxt = rq->next;
ardp_rqfree(rq);
rq = nxt;
}
}
/*
* ardp_set_retry - change default values for timeout
*
* ardp_set_retry takes a value for timout in seconds and a count
* of the number of retries to allow. It sets static variables in this
* file used by pralloc to set the default values in request structures
* it allocates.
*/
int
ardp_set_retry(int to, int rt)
{
/* XXX This is a critical section, but it is safe as long as we are not on
a multiprocessor and don't block. So no mutexes. */
ardp_default_timeout = to;
ardp_default_retry = rt;
/*** XXX End Critical section */
return(ARDP_SUCCESS);
}
#ifndef NDEBUG
/* Return 1 if the RREQ rr is a member of the list LIST. */
static int
rreq_member_of_list(RREQ rr, RREQ list)
{
for ( ; list; list = list->next) {
if (rr == list) return 1;
}
return 0; /* false */
}
#endif

View File

@@ -0,0 +1,305 @@
/*
* Copyright (c) 1991-1993 by the University of Southern California
*
* Written by bcn 1989-92 as dirsend.c in the Prospero distribution
* Modified by bcn 1/93 separate library and add support for asynchrony
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
#include <stdio.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <ardp.h>
#include <perrno.h>
#include <pmachine.h>
#define OLD_GETHOSTBYNAME /* do it the old way, since we're on the client
*/
#ifdef PROSPERO
#include <pcompat.h>
#else /* not PROSPERO */
#define DISABLE_PFS_START()
#define DISABLE_PFS_END()
#endif /* not PROSPERO */
RREQ ardp_activeQ = NOREQ; /* Info about active requests */
RREQ ardp_completeQ = NOREQ;/* Completed requests */
static unsigned short ardp_def_port_no = 0; /* Default UDP port to use */
int ardp_port = -1; /* Opened UDP port */
extern int pfs_debug; /* Debug level */
static ardp_init();
static short ardp_next_cid();
/*
* ardp_send - send a request and possibly wait for response
*
* ardp_send takes a pointer to a structure of type RREQ, an optional
* hostname, an optional pointer to the desination address, and the time to
* wait before returning in microseconds.
*
* If a destination address was specified, the address is inserted
* into the RREQ structure. If not, but a hostname was specified, the
* hostname is resolved, and its address inserted into the RREQ
* structure. The hostname may be followed by a port number in
* parentheses in which case the port field is filled in. If not
* specified, the Prospero directory server port is used as the default.
* If the host address is a non-null pointer to an empty address, then
* the address is also filled in.
*
* ardp_send then sends the packets specified by the request structure
* to the address in the request structure. If the time to wait is
* -1, it waits until the complete response has been received and
* returns PSUCCESS or PFAILURE depending on the outcome. Any
* returned packets are left in the RREQ strucure. If the time to
* wait is 0, ardp_send returns immediately. The prereq strucure will
* be filled in as the response is received if calls are made to
* ardp_check_messages (which may be called by an interrupt, or
* explicitly at appropriate points in the application. If the time
* to wait is positive, then ardp_send waits the specified lenght of
* time before returning.
*
* If ardp_send returns before the complete response has been
* received, it returns ARDP_PENDING (-1). This means that only
* the status field in the RREQ structure may be used until the status
* field indicates ARDP_STATUS_COMPLETE. In no event shall it be legal
* for the application to modify fields in the RREQ structure while a
* request is pending. If the request completes during the call to
* ardp_send, it returns ARDP_SUCCESS (0). On error, a positive
* return or status value indicates the error that occured.
*
* In attempting to obtain the response, the ARDP library will wait
* for a response and retry an appropriate number of times as defined
* by timeout and retries (both static variables). It will collect
* however many packets form the reply, and return them in the
* request structue.
*
* ARGS: req Request structure holding packets to send
* and to receive the response
* hname Hostname including optional port in parentheses
* dest Pointer to destination address
* ttwait Time to wait in microseconds
*
* MODIFIES: dest If pointer to empty address
* req Fills in ->recv and frees ->trns
*
* NOTE: In preparing packets for transmission, the packets
* are modified. Once the full response has been received,
* the packets that were sent are freed.
*/
int
ardp_send(RREQ req, /* Request structure to use (in, out) */
char *dname, /* Hostname (and port) of destination */
struct sockaddr_in *dest, /* Pointer to destination address */
int ttwait) /* Time to wait in microseconds */
{
char hostnoport[400];/* Hostname without port */
char *openparen; /* Start of port in dname */
int req_udp_port; /* UDP port from hostname */
#ifdef OLD_GETHOSTBYNAME /* unused */
struct hostent *host; /* Host info from gethostbyname */
#endif
PTEXT ptmp; /* Temporary packet pointer */
int DpfStmp; /* Used when disabling prospero */
int tmp; /* To temporarily hold return values */
p_clear_errors();
if((ardp_port < 0) && (tmp = ardp_init())) return(tmp);
if(req->status == ARDP_STATUS_FREE) {
fprintf(stderr,"Attempt to send free RREQ\n");
abort();
return(perrno = ARDP_BAD_REQ);
}
while(req->outpkt) {
req->outpkt->seq = ++(req->trns_tot);
ptmp = req->outpkt;
EXTRACT_ITEM(ptmp,req->outpkt);
APPEND_ITEM(ptmp,req->trns);
}
if(pfs_debug >= 9) {
fprintf(stderr, "In ardp_send - sending to %s\n", dname);
ptmp = req->trns;
while(ptmp) {
fprintf(stderr,"Packet %d:\n",ptmp->seq);
ardp_showbuf(ptmp->text, ptmp->length, stderr);
putc('\n', stderr);
ptmp = ptmp->next;
}
}
/* Assign connection ID */
req->cid = ardp_next_cid();
/* Resolve the host name, address, and port arguments */
/* If we were given the host address, then use it. Otherwise */
/* lookup the hostname. If we were passed a host address of */
/* 0, we must lookup the host name, then replace the old value */
if(!dest || (dest->sin_addr.s_addr == 0)) {
/* I we have a null host name, return an error */
if((dname == NULL) || (*dname == '\0')) {
if (pfs_debug >= 1)
fprintf(stderr, "ardp_send: Null hostname specified\n");
return(perrno = ARDP_BAD_HOSTNAME);
}
/* If a port is included, save it away */
if(openparen = strchr(dname,'(')) {
sscanf(openparen+1,"%d",&req_udp_port);
if(req_udp_port) req->peer_port = htons(req_udp_port);
strncpy(hostnoport,dname,399);
if((openparen - dname) < 400) {
*(hostnoport + (openparen - dname)) = '\0';
dname = hostnoport;
}
}
#ifdef OLD_GETHOSTBYNAME
DISABLE_PFS_START();
assert(P_IS_THIS_THREAD_MASTER());
if((host = gethostbyname(dname)) == NULL) {
DISABLE_PFS_END();
/* Check if a numeric address */
req->peer.sin_family = AF_INET;
req->peer_addr.s_addr = inet_addr(dname);
if(req->peer_addr.s_addr == -1) {
if (pfs_debug >= 1)
fprintf(stderr, "ardp: Can't resolve host %s\n", dname);
return(perrno = ARDP_BAD_HOSTNAME);
}
}
else {
DISABLE_PFS_END();
req->peer.sin_family = host->h_addrtype;
bcopy(host->h_addr, (char *)&(req->peer_addr),
host->h_length);
}
#else
/* New way of doing things */
if (ardp_hostname2addr(dname, &req->peer_addr))
return perrno = ARDP_BAD_HOSTNAME;
#endif
}
else bcopy(dest, &(req->peer), S_AD_SZ);
/* If no port set, use default port */
if(req->peer_port == 0) req->peer_port = ardp_def_port_no;
/* If dest was set, but zero, fill it in */
if(dest && (dest->sin_addr.s_addr == 0))
bcopy(&(req->peer), dest, S_AD_SZ);
if(tmp = ardp_headers(req)) return(tmp);
req->status = ARDP_STATUS_ACTIVE;
APPEND_ITEM(req,ardp_activeQ);
req->wait_till.tv_sec = time(NULL) + req->timeout_adj.tv_sec;
ardp_xmit(req, req->pwindow_sz);
return(ardp_retrieve(req,ttwait));
}
/*
* ardp_init - Open socket and bind port for network operations
*
* ardp_init attempts to determine the default destination port.
* It then opens a socket for network operations and attempts
* to bind it to an available privleged port. It tries to bind to a
* privileged port so that its peer can tell it is communicating with
* a "trusted" program. If it can not bind a priveleged port, then
* it also returns successfully since the system will automatically
* assign a non-priveleged port later, in which case the peer will
* assume that it is communicating with a non-trusted program. It
* is expected that in the normal case, we will fail to bind the
* port since most applications calling this routine should NOT
* be setuid.
*/
static int
ardp_init()
{
struct servent *sp; /* Entry from services file */
struct sockaddr_in us; /* Our address */
int DpfStmp;/* Used when disabling prospero */
int tmp; /* For stepping through ports */
/* Determine default udp port to use */
DISABLE_PFS_START();
assert(P_IS_THIS_THREAD_MASTER()); /*SOLARIS: getservbyname MT-Unsafe */
if ((sp = getservbyname(ARDP_DEFAULT_PEER,"udp")) == 0) {
if (pfs_debug >= 10)
fprintf(stderr, "ardp: udp/%s unknown service - using %d\n",
ARDP_DEFAULT_PEER, ARDP_DEFAULT_PORT);
ardp_def_port_no = htons((u_short) ARDP_DEFAULT_PORT);
}
else ardp_def_port_no = sp->s_port;
DISABLE_PFS_END();
if (pfs_debug >= 10)
fprintf(stderr,"default udp port is %d\n", ntohs(ardp_def_port_no));
/* Open the local socket from which packets will be sent */
errno=0;
if((ardp_port = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
if (pfs_debug >= 1)
fprintf(stderr,"ardp: Can't open socket - %s\n",
unixerrstr());
return(perrno = ARDP_UDP_CANT);
}
#ifndef ARDP_NONPRIVED
/* Try to bind it to a privileged port - loop through candidate */
/* ports trying to bind. If failed, that's OK, we will let the */
/* system assign a non-privileged port later */
bzero((char *)&us, sizeof(us));
us.sin_family = AF_INET;
for(tmp = ARDP_FIRST_PRIVP; tmp < ARDP_FIRST_PRIVP+ARDP_NUM_PRIVP;tmp++) {
us.sin_port = htons((u_short) tmp);
if(bind(ardp_port, (struct sockaddr *)&us, sizeof(us)) == 0)
return(ARDP_SUCCESS);
if(errno != EADDRINUSE) return(ARDP_SUCCESS);
}
#endif /* ARDP_NONPRIVED */
return(ARDP_SUCCESS);
}
/*
* ardp_next_cid - return next connection ID in network byte order
*
* ardp_next_cid returns the next connection ID to be used
* after first converting it to network byte order.
*/
static short ardp_next_cid()
{
static unsigned short next_conn_id = 0; /* Next conn id to use */
static int last_pid = 0; /* Reset after forks */
int pid = getpid();
/* If we did a fork, reinitialize */
if(last_pid != pid) {
if(ardp_port >= 0) close(ardp_port);
ardp_port = -1;
next_conn_id = 0;
ardp_init();
}
/* Find first connection ID */
assert(P_IS_THIS_THREAD_MASTER()); /* rand and srand are unsafe */
if(next_conn_id == 0) {
srand(pid+time(0));
next_conn_id = rand();
last_pid = pid;
}
if(++next_conn_id == 0) ++next_conn_id;
return(htons(next_conn_id));
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 1993 by the University of Southern Calfornia
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
#include <stdio.h>
#include <ctype.h>
static void showc(char c, FILE *outf);
/* Return non-zero if string ends in a newline. */
/* Like fputs, but for bstrings. */
void
ardp_showbuf(const char *bst, int len, FILE *out)
{
while (len-- > 0) {
showc(*bst++, out);
}
}
#include <ctype.h>
extern int pfs_debug;
static void
showc(char c, FILE *outf)
{
if (c == '\\') {
putc('\\', outf);
putc('\\', outf);
} else if (isprint(c)) {
putc(c, outf);
} else if ((c == '\n')) {
if (pfs_debug >= 11) {
putc('\\', outf);
putc('n', outf);
} else {
putc('\n', outf);
}
} else if ((c == '\t')) {
if (pfs_debug >= 11) {
putc('\\', outf);
putc('t', outf);
} else {
putc('\t', outf);
}
} else if ((c == '\r')) {
if (pfs_debug >= 11) {
putc('\\', outf);
putc('r', outf);
} else {
putc('\r', outf);
}
} else {
fprintf(outf, "\\%#03o", c);
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-copyr.h>.
*
* Written by bcn 1/93 to send a single packet to a peer
*/
#include <usc-copyr.h>
#include <stdio.h>
#include <ardp.h>
#include <plog.h>
#include <errno.h>
#include <perrno.h>
extern int ardp_srvport;
extern int ardp_prvport;
/*
* ardp_snd_pkt - transmits a single packet to address in req
*
* ardp_snd_pkt takes a pointer to a packet of type PTEXT to be
* sent to a peer identified by req->peer. It then send the packet to
* the peer. If the packet was sent successfully, ARDP_SUCCESS is
* returned. Successful transmission of the packet does not provide
* any assurance of receipt by the peer. If the attempt to send
* the packet fails, ARDP_NOT_SENT is returned.
*/
int
ardp_snd_pkt(pkt,req)
PTEXT pkt;
RREQ req;
{
int sent;
sent = sendto(((ardp_prvport != -1) ? ardp_prvport : ardp_srvport),
pkt->start, pkt->length, 0, &(req->peer), S_AD_SZ);
if(sent == pkt->length) return(ARDP_SUCCESS);
plog(L_NET_ERR, req, "Attempt to send message failed (errno %d %s)",
errno, unixerrstr(), 0);
return(ARDP_NOT_SENT);
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (c) 1991 by the University of Washington
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>.
*
* Written by bcn 1991 as part of rdgram.c in Prospero distribution
* Modified by bcn 1/93 modularized and incorporated into new ardp library
*/
#include <uw-copyright.h>
#include <usc-copyr.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <ardp.h>
#include <plog.h>
int (*ardp_pri_func)() = NULL; /* Function to compare priorities */
int ardp_pri_override = 0; /* If 1, then oveeride value in request */
int ardp_srvport = -1;
int ardp_prvport = -1;
/*
* ardp_set_queueing_plicy - set function for queueing policy
*
* ardp_set_queuing_policy allows one to provide a function that will set
* priorities for requests. When passed two req structures, r1 and r2, the
* function should return a negative number if r1 should be executed first
* (i.e. r1 has a lower numerical priority) and positive if r2 should be
* executed first. If the function returns 0, it means the two have the
* same priority and should be executed FCFS. If override is non-zero, then
* the priority function is to be applied to all requests. If non-zero,
* it is only applied to those with identical a priori priorities (as
* specified in the datagram itself.
*/
int
ardp_set_queuing_policy(pf,override)
int (*pf)(); /* Function to compare priorities */
int override; /* If 1, then oveeride value in request */
{
ardp_pri_func = pf;
ardp_pri_override = override;
return(ARDP_SUCCESS);
}
int
ardp_set_prvport(port)
int port;
{
ardp_prvport = port;
return(ARDP_SUCCESS);
}
int
ardp_bind_port(portname)
char *portname;
{
struct sockaddr_in s_in = {AF_INET};
struct servent *sp;
int on = 1;
int port_no = 0;
assert(P_IS_THIS_THREAD_MASTER()); /*getpwuid MT-Unsafe*/
if(*portname == '#') {
sscanf(portname+1,"%d",&port_no);
if(port_no == 0) {
fprintf(stderr, "ardp_bind_port: port number must follow #\n");
exit(1);
}
s_in.sin_port = htons((ushort) port_no);
}
else if((sp = getservbyname(portname, "udp")) != NULL) {
s_in.sin_port = sp->s_port;
}
else if(strcmp(portname,ARDP_DEFAULT_PEER) == 0) {
fprintf(stderr, "ardp_bind_port: udp/%s unknown service - using %d\n",
ARDP_DEFAULT_PEER, ARDP_DEFAULT_PORT);
s_in.sin_port = htons((ushort) ARDP_DEFAULT_PORT);
}
else {
fprintf(stderr, "ardp_bind_port: udp/%s unknown service\n",portname);
exit(1);
}
if ((ardp_srvport = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
plog(L_STATUS,NOREQ,"Startup - Can't open socket",0);
fprintf(stderr, "ardp_bind_port: Can't open socket\n");
exit(1);
}
if (setsockopt(ardp_srvport, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
fprintf(stderr, "dirsrv: setsockopt (SO_REUSEADDR)\n");
if (bind(ardp_srvport, (struct sockaddr *) &s_in, S_AD_SZ) < 0) {
plog(L_STATUS,NOREQ,"Startup - Can't bind socket",0);
fprintf(stderr, "dirsrv: Can not bind socket\n");
exit(1);
}
return(ntohs(s_in.sin_port));
}

View File

@@ -0,0 +1,103 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*
* Written by bcn 1/93 to send a list of packets to a destination
*/
#include <usc-license.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <ardp.h>
#include <pmachine.h> /* for bcopy() and select() */
extern int pfs_debug; /* Debug level */
extern int ardp_port; /* Opened UDP port */
/*
* ardp_xmit - transmits packets in req->trns
*
* ardp_xmit takes a pointer to a request structure of type RREQ and a
* window size. It then sends the packet on the request structure
* transmit queue to the peer address in the request structure starting after
* the indicated peer rcvd_thru value, and up to the number of packets
* specified by the window size. It returns ARDP_SUCCESS on success and
* returns an error code on failure.
*
* This is called on both the client and server side, called respectively by
* ardp_send() and ardp_pr_actv().
*/
int
ardp_xmit(RREQ req, /* Request structure with packets to send */
int window) /* Max packets to send at once. Note that
right now this is always identical to
req->pwindow_sz.
0 means infinite window size
-1 means just send an ACK; don't send any
data packets. */
{
PTEXT ptmp; /* Packet pointer for stepping through trns */
unsigned short stmp; /* Temp short for conversions */
int ns; /* Number of bytes actually sent */
static PTEXT ack = NOPKT; /* Only an ack to be sent */
if(window < 0 || req->prcvd_thru >= req->trns_tot) {
/* All our packets got through, send acks only */
if(ack == NOPKT) {
ack = ardp_ptalloc();
/* Add header */
ack->start -= 9;
ack->length += 9;
*(ack->start) = (char) 9;
/* An unsequenced control packet */
bzero4(ack->start+3);
}
/* Received Through */
stmp = htons(req->rcvd_thru);
bcopy2(&stmp,ack->start+7);
/* Connection ID */
bcopy2(&(req->cid),ack->start+1);
ptmp = ack;
}
else ptmp = req->trns;
/* Note that we don't want to get rid of packts before the */
/* peer received through since the peer might later tell */
/* us it forgot them and ask us to send them again */
/* XXX whether this is allowable should be an application */
/* specific configration option. */
while(ptmp) {
if((window > 0) && (ptmp->seq > req->prcvd_thru + window)) break;
if((ptmp->seq == 0) || (ptmp->seq > req->prcvd_thru)) {
if (pfs_debug >= 6) {
if (req->peer.sin_family == AF_INET)
fprintf(stderr,
"Sending message%s (cid=%d) (seq=%d) to %s(%d)...",
(ptmp == ack) ? " (ACK only)" : "",
ntohs(req->cid), ntohs(ptmp->seq),
inet_ntoa(req->peer_addr), PEER_PORT(req));
else fprintf(stderr,"Sending message...");
(void) fflush(stderr);
}
ns = sendto(ardp_port,(char *)(ptmp->start), ptmp->length, 0,
&(req->peer), S_AD_SZ);
if(ns != ptmp->length) {
if (pfs_debug >= 1) {
fprintf(stderr,"\nsent only %d/%d: ",ns, ptmp->length);
perror("");
}
return(ARDP_NOT_SENT);
}
if (pfs_debug >= 6) fprintf(stderr,"Sent.\n");
}
ptmp = ptmp->next;
}
return(ARDP_SUCCESS);
}

View File

View File

@@ -0,0 +1,72 @@
/* Copyright (c) 1993, by Pandora Systems */
/* Author: Mitra <mitra@path.net> */
/* Allocation code copied and adapted from:
prospero/alpha.5.2a+/lib/pfs/flalloc */
#include "dnscache_alloc.h"
#include <pfs.h>
#include <pfs_threads.h>
#include <mitra_macros.h>
static DNSCACHE lfree = NULL; /* Free dnscaches */
/* These are global variables which will be read by dirsrv.c
Too bad C doesn't have better methods for structuring such global data. */
int dnscache_count = 0;
int dnscache_max = 0;
/************* Standard routines to alloc, free and copy *************/
/*
* dnscache_alloc - allocate and initialize DNSCACHE structure
*
* returns a pointer to an initialized structure of type
* DNSCACHE. If it is unable to allocate such a structure, it
* signals out_of_memory();
*/
DNSCACHE
dnscache_alloc()
{
DNSCACHE acache;
TH_STRUC_ALLOC(dnscache,DNSCACHE,acache);
acache->name = NULL;
acache->usecount = 0;
bzero(&acache->sockad,sizeof(acache->sockad));
return(acache);
}
/*
* dnscache_free - free a DNSCACHE structure
*
* dnscache_free takes a pointer to a DNSCACHE structure and adds it to
* the free list for later reuse.
*/
void
dnscache_free(DNSCACHE acache)
{
stfree(acache->name) ; acache->name = NULL;
TH_STRUC_FREE(dnscache,DNSCACHE,acache);
}
/*
* dnscache_lfree - free a linked list of DNSCACHE structures.
*
* dnscache_lfree takes a pointer to a dnscache structure frees it and
* any linked
* DNSCACHE structures. It is used to free an entire list of WAISMSGBUFF
* structures.
*/
void
dnscache_lfree(acache)
DNSCACHE acache;
{
TH_STRUC_LFREE(DNSCACHE,acache,dnscache_free);
}
void
dnscache_freespares()
{
TH_FREESPARES(dnscache,DNSCACHE);
}

View File

@@ -0,0 +1,33 @@
#ifndef dnscache_alloc_h
#define dnscache_alloc_h
#include <pfs.h>
#include <pfs_threads.h>
#include <netinet/in.h>
struct dnscache {
#ifdef ALLOCATOR_CONSISTENCY_CHECK
int consistency;
#endif
char *name;
struct sockaddr_in sockad;
int usecount; /* For determining size of cache */
struct dnscache *next;
struct dnscache *previous;
};
typedef struct dnscache *DNSCACHE;
typedef struct dnscache DNSCACHE_ST;
extern DNSCACHE dnscache_alloc();
extern void dnscache_free(DNSCACHE acache);
extern void dnscache_lfree(DNSCACHE acache);
extern void dnscache_freespares();
extern int dnscache_count, dnscache_max;
/*extern DNSCACHE dnscache_copy(DNSCACHE f, int r);*/
#ifdef PFS_THREADS
extern p_th_mutex p_th_mutexDNSCACHE;
extern p_th_mutex p_th_mutexALLDNSCACHE;
#endif
#endif /*dnscache_alloc_h*/

221
prospero/lib/ardp/flocks.c Normal file
View File

@@ -0,0 +1,221 @@
/* Copyright (c) 1993, by Pandora Systems */
/* Author: Mitra <mitra@path.net> */
/* Allocation code copied and adapted from:
lib/pfs/flalloc.c in the Prospero Alpha.5.2a release. */
#include <pfs.h>
#include <plog.h>
#include "flocks.h"
#include "mitra_macros.h"
#ifdef PFS_THREADS
extern p_th_mutex p_th_mutexFILES;
#endif
/* FileLocks are currently unused by dirsrv.c, and not linked into the ardp
library. So dirsrv will not report on them in replies to a STATUS message.
*/
static FILELOCK lfree = NULL; /* Free filelocks */
/* These are global variables which will be read by dirsrv.c
Too bad C doesn't have better methods for structuring such global data. */
int filelock_count = 0;
int filelock_max = 0;
int filelock_open = 0;
int filelock_open_max = 0;
int filelock_sepwaits = 0;
int filelock_secwaits = 0;
FILELOCK filelock_locked = NULL;
/************* Standard routines to alloc, free and copy *************/
/*
* filelock_alloc - allocate and initialize FILELOCK structure
*
* returns a pointer to an initialized structure of type
* FILELOCK. If it is unable to allocate such a structure, it
* signals out_of_memory();
*/
FILELOCK
filelock_alloc()
{
FILELOCK fl;
TH_STRUC_ALLOC(filelock,FILELOCK,fl);
fl->name = NULL;
fl->readers = 0;
return(fl);
}
/*
* filelock_free - free a FILELOCK structure
*
* filelock_free takes a pointer to a FILELOCK structure and adds it to
* the free list for later reuse.
*/
void
filelock_free(FILELOCK fl)
{
stfree(fl->name); fl->name = NULL;
fl->readers = 0;
TH_STRUC_FREE(filelock, FILELOCK, fl);
}
/*
* filelock_lfree - free a linked list of FILELOCK structures.
*
* filelock_lfree takes a pointer to a filelock structure frees it and
* any linked
* FILELOCK structures. It is used to free an entire list of FILELOCK
* structures.
*/
void
filelock_lfree(fl)
FILELOCK fl;
{
TH_STRUC_LFREE(FILELOCK,fl,filelock_free);
}
static void
filelock_unreaders(FILELOCK flock)
{
/* Assumes p_th_mutexFILES is locked already */
assert(flock->readers > 0);
if (!(--flock->readers)) {
EXTRACT_ITEM(flock,filelock_locked);
filelock_free(flock);
}
}
static void
filelock_unwriters(FILELOCK flock)
{
/* Assumes p_th_mutexFILES is locked already */
assert(flock->readers == -1);
EXTRACT_ITEM(flock, filelock_locked);
filelock_free(flock);
}
void
filelock_freespares()
/* This is used for filelocks to free up space in the child */
{
TH_FREESPARES(filelock,FILELOCK);
}
void
filelock_release(const char *filename, int readonly)
{
FILELOCK flock;
p_th_mutex_lock(p_th_mutexFILES);
flock = filelock_locked;
FIND_FNCTN_LIST(flock, name, filename, stequal);
assert(flock); /* it better be locked */
if (readonly) {
filelock_unreaders(flock); /* May destroy flock */
} else {
filelock_unwriters(flock); /* May destroy flock */
}
filelock_open--;
p_th_mutex_unlock(p_th_mutexFILES);
}
int
locked_fclose_A(FILE *afile, const char *filename, int readonly)
{
int retval;
/* Assumes already obtained filelock for filename */
retval = fclose(afile);
/* At least on solaris, this can return an error for no apparent reason */
#if 0
assert(!retval);
#endif
filelock_release(filename, readonly);
return(retval);
}
void
filelock_obtain(const char *filename, int readonly)
{
FILELOCK(flock);
int haswaited = 0;
for (;;) {
p_th_mutex_lock(p_th_mutexFILES);
flock = filelock_locked;
FIND_FNCTN_LIST(flock, name, filename,stequal);
if (!flock) { /* didnt find a matching lock */
flock = filelock_alloc();
flock->name = stcopy(filename);
flock->readers = 0;
APPEND_ITEM(flock,filelock_locked);
}
/* Found, or created a matching lock */
if (readonly) {
if (flock->readers >= 0) {
flock->readers++;
break;
}
/* Drops thru here, if we want it readonly, but someone else writing*/
} else {
if (flock->readers == 0) {
flock->readers = -1; /* Special code for writer */
break;
}
/* Drops thru here, if we want to write, but someone else
is reading/writing */
}
/* At this point we cant lock it, so unlock mutex, wait, and try again*/
p_th_mutex_unlock(p_th_mutexFILES);
plog(L_QUEUE_INFO,NOREQ, "Waiting for filelock for %s", filename, 0);
if (!haswaited) filelock_sepwaits++;
filelock_secwaits++;
sleep(1); /* Maybe too long */
} /*for*/
if (++filelock_open > filelock_open_max) {
filelock_open_max = filelock_open;
}
/* break is always done with mutex locked */
p_th_mutex_unlock(p_th_mutexFILES);
}
FILE *
locked_fopen(const char *filename, const char *mode)
{
FILELOCK flock;
FILE *retval;
int readonly = stequal(mode,"r");
filelock_obtain(filename,readonly); /* Will wait till available */
if (!(retval = fopen(filename,mode))) {
filelock_release(filename, readonly);
}
return retval;
}
/* Suuitable sequence for creating a file via a temporary
filelock_obtain(filename,FALSE);
if (!(afile = locked_fopen(tmpfilename, "w")) )
filelock_release(filename,FALSE);
written stuff to the file - retval set if fails
return(locked_fclose_and_rename(afile, tmpfilename, filenam,retvale));
*/
int
locked_fclose_and_rename(
FILE *afile, /* Open "w" temporary file */
const char *tmpfilename, /* Name of temp file */
const char *filename, /* Name desired */
int retval) /* FALSE if ok to rename, TRUE cleanup*/
{
if (fflush(afile) || ferror(afile)) { retval = PFAILURE; }
if (locked_fclose_A(afile, tmpfilename, FALSE)) { retval = PFAILURE; }
if (!retval) { /* Dont attempt to rename if failed */
if (rename(tmpfilename, filename)) { retval = PFAILURE; }
}
unlink(tmpfilename);
filelock_release(filename,FALSE);
return(retval);
}

View File

@@ -0,0 +1,28 @@
#ifndef rmg_filelock_h
#define rmg_filelock_h
#include <pfs.h>
struct filelock {
#ifdef ALLOCATOR_CONSISTENCY_CHECK
int consistency;
#endif
char *name;
int readers; /* -1 for writing */
/* Note we dont keep the fileno here since each locker opens seperately*/
struct filelock *next;
struct filelock *previous;
};
typedef struct filelock *FILELOCK;
typedef struct filelock FILELOCK_ST;
extern FILELOCK filelock_alloc();
extern void filelock_free(FILELOCK chan);
extern void filelock_lfree(FILELOCK chan);
extern void filelock_freespares();
extern FILELOCK filelock_copy(FILELOCK f, int r);
#ifdef PFS_THREADS
extern p_th_mutex p_th_mutexFILELOCK;
#endif
#endif /*rmg_filelock_h*/

View File

@@ -0,0 +1,204 @@
/*
* Copyright (c) 1991-1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
#include <ardp.h>
#include <perrno.h>
#include <sys/types.h> /* for gethostbyname() */
#include <sys/socket.h> /* for gethostbyname */
#include <netdb.h> /* for gethostbyname. */
#include <netinet/in.h> /* for struct sockaddr_in */
#include <pmachine.h> /* for bzero */
#include <string_with_strcasecmp.h> /* for strcasecmp */
#ifdef PROSPERO
#include <pserver.h> /* For DNSCACHE_MAX */
#ifdef DNSCACHE_MAX
#include "dnscache_alloc.h"
#endif
#include <pcompat.h>
#else /* not PROSPERO */
#define DISABLE_PFS_START()
#define DISABLE_PFS_END()
#endif /* not PROSPERO */
extern int stcaseequal(const char *s1,const char *s2);
/*
* This function serves as a thread-safe version of gethostbyname(),
* which is not a re-entrant function since it uses static data.
*
* It normally accepts a hostname and initializes the socket address
* appropriately, then returns PSUCCESS. Also accepts numeric addresses.
* Does not currently handle the port #, although that would be a useful future
* extension.
*
* It returns ARDP_BAD_HOSTNAME if the hostname could not be resolved.
* gethostbyname should not be called anywhere else in multi-threaded versions
* of the Prospero code; to this end, an error define occurs for it in
* pfs_threads.h
*
* Oh no there isn't a definition in pfs_threads.h - Mitra
*
* Note that gethostbyname() is not multi-threaded internally, and
* does block, so we might block on name resolution as a bottleneck.
* Probably want a multithreaded name resolver library. Release such a thing
* as freeware?
*
* It also converts numeric addresses appropriately.
*/
/* If change this - uncomment/comment initialization in server/dirsrv.c */
#ifdef DNSCACHE_MAX
#include "dnscache_alloc.h"
#include <mitra_macros.h> /* FIND_FNCTN_LIST */
#include <string.h> /* For strcmp */
DNSCACHE alldnscaches = NULL;
int alldnscache_count = 0;
void
sockaddr_copy(struct sockaddr_in *src, struct sockaddr_in *destn)
{
/* Nothing in a sockaddr_in is a pointer */
memcpy(destn, src, sizeof(struct sockaddr_in));
}
#endif /*DNSCACHE_MAX*/
/* Caching has been added, to this - take care that it does what you
want, I'm certainly open to changes if this isnt what we need.
Currently it is called by something at a higher layer, with a
hostname of the name to cache, and a hostaddr of NULL.
Currently this is used to cache all the hostnames hard coded
into include/* on the assumption that these are unlikely to move around
while a server is running. Later, we may want to delete a cached
entry periodically, or if it fails.
The first thing in alldnscaches is always a copy of the last thing
found, to allow really quick returns on repeat requests.
Note - great care is taken here to
a) avoid deadlock between GETHOSTBYNAME and DNSCACHE mutexes
b) avoid requirement for GETHOSTBYNAME mutex, if found in cache
This allows multiple cached results to be returned while a
single thread calls gethostbyname
*/
void
ardp_hostname2addr_initcache()
{
}
static void
dnscache_clean()
{
DNSCACHE dc, nextdc;
if (alldnscache_count > DNSCACHE_MAX) {
if (! p_th_mutex_trylock(p_th_mutexALLDNSCACHE)) {
/* Since this is only optimisation, skip if its locked already */
for (dc = alldnscaches; dc ; dc = nextdc) {
nextdc = dc->next;
if (!(--dc->usecount)) {
EXTRACT_ITEM(dc,alldnscaches);
dnscache_free(dc);
alldnscache_count--;
}
}
p_th_mutex_unlock(p_th_mutexALLDNSCACHE);
}
}
}
int
ardp_hostname2addr(const char *hostname, struct sockaddr_in *hostaddr)
{
struct hostent *hp; /* Remote host we're connecting to. */
int retval; /* Value to return */
#define RETURN(rv) { retval = (rv); goto cleanup; }
#ifdef PROSPERO
int DpfStmp; /* for DISABLE_PFS_START() */
#endif
#ifdef DNSCACHE_MAX
DNSCACHE acache = NULL;
acache = alldnscaches;
p_th_mutex_lock(p_th_mutexALLDNSCACHE);
/* Cant use TH_FIND_FNCTN_LIST because must retain lock */
FIND_FNCTN_LIST(acache, name, hostname, stcaseequal);
if(acache) {
acache->usecount++;
if (hostaddr) {
/* Note is is pointless, but not harmfull to call again
for same hostaddr - may just want to rerun*/
sockaddr_copy(&(acache->sockad),hostaddr);
}
p_th_mutex_unlock(p_th_mutexALLDNSCACHE); /* Also released below*/
return(ARDP_SUCCESS); /* Dont free acache */
}
p_th_mutex_unlock(p_th_mutexALLDNSCACHE); /* Note also released above*/
acache = dnscache_alloc(); /*locks DNSCACHE temporarily*/
acache->name = stcopy(hostname);
if (!hostaddr) { hostaddr = &(acache->sockad); }
#endif /*DNSCACHE_MAX*/
DISABLE_PFS_START(); /* Turn off compatibility library if on */
p_th_mutex_lock(p_th_mutexGETHOSTBYNAME);
hp = gethostbyname((char *) hostname); /* cast to char * in case bad prototype.
*/
DISABLE_PFS_END(); /* Restore compat. lib. */
if (hp == NULL) {
p_th_mutex_unlock(p_th_mutexGETHOSTBYNAME);
/* Try to see if it might be a numeric address. */
/* Check if a numeric address */
hostaddr->sin_family = AF_INET;
hostaddr->sin_addr.s_addr = inet_addr(hostname);
if(hostaddr->sin_addr.s_addr == -1) {
p_clear_errors(); /* clear p_err_string if set. */
RETURN(perrno = ARDP_BAD_HOSTNAME);
}
RETURN(ARDP_SUCCESS);
}
bzero((char *) hostaddr, sizeof *hostaddr);
memcpy((char *)&hostaddr->sin_addr, hp->h_addr, hp->h_length);
hostaddr->sin_family = hp->h_addrtype;
/* Don't unlock the mutex until we're no longer reading from hp. */
p_th_mutex_unlock(p_th_mutexGETHOSTBYNAME); /* Note can be unlocked above*/
/* Copy last result into cache */
#ifdef DNSCACHE_MAX
if (alldnscaches == NULL)
ardp_hostname2addr_initcache();
sockaddr_copy(hostaddr,&(acache->sockad));
/* Boost initially, to bias towards keeping recent*/
acache->usecount = 5;
p_th_mutex_lock(p_th_mutexALLDNSCACHE);
APPEND_ITEM(acache,alldnscaches);
alldnscache_count++;
p_th_mutex_unlock(p_th_mutexALLDNSCACHE);
dnscache_clean(); /* Only does anything if cache too big */
#endif /*DNSCACHE_MAX*/
return(ARDP_SUCCESS); /* Dont free acache */
cleanup:
#ifdef DNSCACHE_MAX
if (acache) dnscache_free(acache);
#endif
return(retval);
}
/* Prototype needs to go into here, not just in pfs.h. */
int
stcaseequal(const char *s1,const char *s2)
{
if (s1 == s2) /* test for case when both NULL*/
return TRUE;
if (!s1 || !s2) /* test for one NULL */
return FALSE;
return (strcasecmp(s1, s2) == 0);
}

View File

@@ -0,0 +1,141 @@
/*
* Copyright (c) 1991-1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
#include <pfs_threads.h>
#include <ardp.h> /* for internal error stuff. */
/* This is the only section of code which calls the pthread_ routines directly.
Everything else is through the interface in pfs_threads.h. */
#ifdef PFS_THREADS
/* Don't compile this if !PFS_THREADS, because it overrides macro definitions
*/
static struct {
p_th_t thread;
int inuse;
} thread_map[P_MAX_NUM_THREADS];
#ifdef PFS_THREADS_SOLARIS
thread_key_t thread_map_key;
#endif
int
p__th_self_num(void)
{
#if defined(PFS_THREADS_FLORIDA) || !defined(NDEBUG)
p_th_t self = p_th_self();
#endif
#ifdef PFS_THREADS_FLORIDA
int i;
for (i = 0; i < P_MAX_NUM_THREADS; ++i) {
if (thread_map[i].inuse
&& p_th_equal(thread_map[i].thread, self))
return i;
}
#endif
#ifdef PFS_THREADS_SOLARIS
long val;
if (!thread_map_key) return 0; /* Assume not threading */
if (!thr_getspecific(thread_map_key,(void *)&val)) {
assert(p_th_equal(thread_map[val].thread, self));
assert(val < P_MAX_NUM_THREADS); /* i.e. 0 .. MAX-1 */
return val;
}
#endif /*PFS_THREADS_SOLARIS*/
internal_error("p__th_self_num() called for a thread that didn't have its \
number set with p__th_allocate_self_num() or p__th_set_self_master()");
return -1 ; /* Keep Gcc happy */
}
void
p__th_set_self_master(void)
{
assert(!thread_map[0].inuse);
thread_map[0].inuse = 1;
thread_map[0].thread = p_th_self();
#ifdef PFS_THREADS_SOLARIS
assert(!thread_map_key);
thr_keycreate(&thread_map_key, NULL);
thr_setspecific(thread_map_key, 0);
#endif
}
/*
* This allocates a number to this thread.
* It also does consistency checking to make sure the function is called
* only on a thread that doesn't have a number already allocated.
*/
void
p_th_allocate_self_num(void)
{
int allocated = 0;
p_th_t self = p_th_self();
int i;
CHECK_MEM();
assert(thread_map_key); /* Better be initialized*/
/* I think this needs mutexing */
p_th_mutex_lock(p_th_mutexARDP_SELFNUM);
for (i = 0; i < P_MAX_NUM_THREADS; ++i) {
if (!thread_map[i].inuse) {
if (!allocated) {
thread_map[i].thread = self;
thread_map[i].inuse = 1;
++allocated;
CHECK_MEM();
#ifdef PFS_THREADS_SOLARIS
thr_setspecific(thread_map_key,(void *)i);
#endif
}
} else {
if(p_th_equal(thread_map[i].thread, self)) {
internal_error("Shouldn't allocate a number to a thread twice.");
}
}
}
p_th_mutex_unlock(p_th_mutexARDP_SELFNUM);
}
void
p_th_deallocate_self_num(void)
{
int i = p__th_self_num();
thread_map[i].inuse = 0;
}
extern p_th_mutex p_th_mutexFILES;
#ifndef NDEBUG
char mutex_locked_msg[] = "Mutex %s locked\n";
#endif
#ifdef PFS_THREADS_SOLARIS
/* Return true if fails to lock - i.e was already locked */
int
p_th_mutex_islocked(mutex_t *mp)
{
int retval;
if (retval = mutex_trylock(mp)) {
return retval;
} else {
return mutex_unlock(mp);
}
}
#endif /* PFS_THREADS_SOLARIS */
#endif /*PFS_THREADS*/

View File

@@ -0,0 +1,324 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#if !defined(AIX) && !defined(SOLARIS)
#include <vfork.h>
#endif
#include <malloc.h>
#include <search.h>
#include <memory.h>
#include <string.h>
#include <limits.h>
#include <sys/stat.h>
#include "typedef.h"
#include "db_files.h"
#include "host_db.h"
#include "header.h"
#include "error.h"
#include "archie_strings.h"
#include "files.h"
#include "master.h"
#include "protos.h"
#include "db_ops.h"
/* This performs a simple ACL based on ip addresses */
typedef struct {
int ip[4]; /* Composes the ip address a.b.c.d */
} ip_t;
#define DIRSRV_ACL_FILE "dirsrv.acl"
#define DIRSRV_ACL_MESSAGE_FILE "dirsrv.acl.mesg"
#define DIRSRV_ACL_MESSAGE_DEFAULT "Access to this server is restricted"
static ip_t *acl_list = NULL;
static int acl_list_num = 0;
static int acl_list_max = 0;
static int acl_not_present = 0;
static char acl_err_mesg[100];
#define IP_STAR 257
extern int errno;
static int qcompare_ip(a,b)
ip_t *a, *b;
{
if ( a->ip[0] != b->ip[0] )
return a->ip[0]- b->ip[0];
if ( a->ip[1] != b->ip[1] )
return a->ip[1]- b->ip[1];
if ( a->ip[2] != b->ip[2] )
return a->ip[2]- b->ip[2];
return a->ip[3]- b->ip[3];
}
static int compare_ip(a,b) /* Assuming that can contain * */
ip_t *a, *b;
{
if ( b->ip[0] == IP_STAR )
return 0;
if ( a->ip[0] != b->ip[0] )
return a->ip[0]- b->ip[0];
if ( b->ip[1] == IP_STAR )
return 0;
if ( a->ip[1] != b->ip[1] )
return a->ip[1]- b->ip[1];
if ( b->ip[2] == IP_STAR )
return 0;
if ( a->ip[2] != b->ip[2] )
return a->ip[2]- b->ip[2];
if ( b->ip[3] == IP_STAR )
return 0;
return a->ip[3]- b->ip[3];
}
static int file_proc(ft,name,present)
file_info_t *ft;
char *name;
int *present;
{
struct stat st;
*present = 1;
if ( ft == NULL ) {
error(A_ERR,"file_proc", "Unable to create ft file pointer");
return 0;
}
sprintf(ft->filename,"%s/%s/%s",get_archie_home(),DEFAULT_ETC_DIR,name);
if ( stat(ft->filename,&st) == -1 ) {
if ( errno == ENOENT ) {
*present = 0;
return 0;
}
error(A_ERR,"file_proc","Error finding ft: %s, errno = %d",ft->filename,errno);
return 0;
}
if ( open_file(ft, O_RDONLY) == ERROR ) {
error(A_ERR,"file_proc", "Error opening acl file: %s",ft->filename);
return 0;
}
return 1;
}
static void read_acl_message()
{
char buff[100];
int i;
file_info_t *acl_mesg = create_finfo();
strcpy(acl_err_mesg, DIRSRV_ACL_MESSAGE_DEFAULT);
if ( file_proc(acl_mesg,DIRSRV_ACL_MESSAGE_FILE,&i) ) {
if ( fgets(buff,99,acl_mesg->fp_or_dbm.fp) != NULL ) {
*(strrchr(buff,'\n')) = '\0';
strcpy(acl_err_mesg,buff);
}
close_file(acl_mesg);
destroy_finfo(acl_mesg);
}
}
int read_acl_file()
{
char buff[100];
int i,j;
char **av;
file_info_t *acl_file = create_finfo();
if (! file_proc(acl_file,DIRSRV_ACL_FILE,&j) ) {
if ( j == 0 ) {
acl_not_present = 1;
destroy_finfo(acl_file);
return 1;
}
destroy_finfo(acl_file);
return 0;
}
/* Count the number of items */
fseek(acl_file->fp_or_dbm.fp, 0L ,0);
i = 0;
while (fgets(buff,99,acl_file->fp_or_dbm.fp) != NULL ) {
i++;
}
if ( i == 0 ) {
error(A_INFO,"read_acl_file","ACL file is empty");
acl_not_present = 1;
destroy_finfo(acl_file);
return 1;
}
if ( acl_list_max == 0 ) { /* New */
acl_list_max = i+10;
acl_list = (ip_t*)malloc(sizeof(ip_t)*acl_list_max);
if ( acl_list == NULL ) {
error(A_ERR,"read_acl_file","Unable to allocate memory");
destroy_finfo(acl_file);
return 0;
}
}
else {
ip_t *tmp;
if ( acl_list_max <= i ) {
acl_list_max = i+10;
tmp = (ip_t*)realloc(acl_list, sizeof(ip_t)*acl_list_max);
if ( tmp == NULL ) {
error(A_ERR,"read_acl_file", "Unable to expand allocated memory");
}
acl_list = tmp;
}
}
acl_list_num = 0;
fseek(acl_file->fp_or_dbm.fp, 0L ,0);
while (fgets(buff,99,acl_file->fp_or_dbm.fp) != NULL ) {
av = str_sep(buff,'.');
if ( av == NULL ) {
error(A_ERR,"read_acl_file", "Unable to decompose string: %s",buff);
}
for ( i = 0; i < 4; i++ ) {
if ( av[i] == NULL|| av[i][0] == '*' ) {
break;
}
acl_list[acl_list_num].ip[i] = atoi(av[i]);
}
for ( ; i < 4; i++ ) {
acl_list[acl_list_num].ip[i] = IP_STAR;
}
acl_list_num++;
}
close_file(acl_file);
qsort(acl_list,acl_list_num, sizeof(ip_t),qcompare_ip);
read_acl_message();
destroy_finfo(acl_file);
return 1;
}
int verify_acl_list(from)
struct sockaddr_in *from;
{
ip_t ip;
int i;
char **av;
char *ip_addr;
if ( acl_not_present )
return 1;
if ( acl_list == NULL ) {
if (!read_acl_file() )
return 0;
if ( acl_not_present )
return 1;
}
ip_addr = inet_ntoa(from->sin_addr);
printf("%s\n",ip_addr);
/* decompose address */
av = str_sep(ip_addr,'.');
if ( av == NULL ) {
error(A_ERR,"verify_acl_list","Unable to decompsoe ip address: %s. Accepting",ip_addr);
return 1;
}
ip.ip[0] = atoi(av[0]);
ip.ip[1] = atoi(av[1]);
ip.ip[2] = atoi(av[2]);
ip.ip[3] = atoi(av[3]);
if ( ip.ip[0] == 127 && ip.ip[1] == 0 && ip.ip[2] == 0 && ip.ip[3] == 1 ) {
free_opts(av);
return 1;
}
for ( i = 0; i < acl_list_num; i++ ) {
int ret;
ret = compare_ip(&ip, &acl_list[i]);
if ( ret == 0 ){
free_opts(av);
return 1;
}
if ( ret < 0 ) {
free_opts(av);
return 0;
}
}
free_opts(av);
return 0;
}
char *acl_message()
{
return acl_err_mesg;
}
#if 0
char *prog;
int main(argc,argv)
int argc;
char **argv;
{
char buff[100];
struct sockaddr_in from;
prog = argv[0];
while ( fgets(buff,99,stdin) != NULL ) {
*(strrchr(buff,'\n')) = '\0';
printf("Checking %s, ",buff);
from.sin_addr.s_addr = inet_addr(buff);
if ( verify_acl_list(&from) )
printf("Ok\n");
else
printf("No:%s\n",acl_message());
}
return 0;
}
#endif

View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 1991-1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
#include <pmachine.h>
#if defined(HAVESTRERROR)
#include <errno.h>
#include <string.h> /* For stringerr*/
#else
#include <errno.h> /* For sys_nerr and sys_errlist*/
#ifndef SOLARIS
/* definitely needed under SunOS; probably under almost everything right
now. Solaris's <errno.h> declares these; others don't. */
extern int sys_nerr;
extern char *sys_errlist[];
#endif /* ndef SOLARIS */
#undef HAVESTRERROR
#endif
const char *
unixerrstr(void)
{
#ifdef HAVESTRERROR
/* sys_errlist is not in SOLARIS, replace with strerror()
which may not be thread safe in some applications
there doesnt appear to be a posix compliant equivalent */
return strerror(errno);
#else
/* Would be nice to have the message include the error #. */
return errno < sys_nerr ? sys_errlist[errno] : "Unprintable Error";
#endif
}

View File

@@ -0,0 +1,15 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
/* This string is modified in ardp_xmit.c. That forces the C compiler to
include it in the Prospero binaries. If you know a less kludgy way to
force a fancy optimizing C compiler to include it in the binaries, please
let us know.
*/
char *usc_license_string = "PROSPERO(TM) Copyright (c) 1991-1993 University of Southern California\nPROSPERO is a trademark of the University of Southern California\n";

1
prospero/lib/filters/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
Makefile

View File

@@ -0,0 +1,7 @@
FILES
Makefile.nofil
apply_fil.c
flist2string.c
helpers.c
nl_apply_fil.c
reorder_dir.c

View File

@@ -0,0 +1,35 @@
# lib/filters/Makefile
# This is the makefile for the version of the Prospero Directory Service
# where client-side filters are not loadable.
# This is the default distributed version.
SOURCEBASE=../..
include $(SOURCEBASE)/Makefile.config
CFILES = \
nl_apply_fil.c
OBJECTS = \
nl_apply_fil.o
all: ${FIL_LIB}
${FIL_LIB}: ${OBJECTS}
rm -f ${FIL_LIB}
ar rv ${FIL_LIB} ${OBJECTS}
$(RANLIB) ${FIL_LIB}
install:
# cp ${FIL_LIB} ${P_BINARIES}/${FIL_LIB}
# $(RANLIB) ${P_BINARIES}/${FIL_LIB}
# Dependencies
nl_apply_fil.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h

View File

@@ -0,0 +1,138 @@
/*
* Copyright (c) 1989, 1990, 1991 by the University of Washington
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>.
*/
#include <uw-copyright.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/file.h>
#include <sys/param.h>
#include <errno.h>
#include <pfs.h>
#include <pcompat.h>
#include <perrno.h>
#include <pmachine.h>
typedef char *(*STR_function)();
/*!! No way is this thread safe!!! */
STR_function filter;
STR_function select_filter();
/* Variables that may be accessed by the filter */
char *FlT_htype = P_MACHINE_TYPE; /* Current Host Type */
char *FlT_ostype = P_OS_TYPE; /* Current Host Type */
/*
* apply_filters - Apply filters to a directroy
*
* APPLY_FILTERS takes a pointer to a directory, a list of
* filters to be to be applied to the directory.
* It also takes a pointer to the link to the directory
* which is made available to the filter. The last
* argument specifies whether a single filter is to
* be applied, or all filters in a list.
*
* The filters are then applied one by one
* to the directory, and the result returned. Filters may
* be defined by the user. The arguments may be modified,
* and the returned directory will be the same directory as
* passed as an argument.
*
* ARGS: dir - The directory to be filtered (will be modified)
* filters - A list of the filters to be applied
* dl - Directory link
* oa - 0 = One, 1 = All
*
* MODIFIES: apply_filters might modify any of its arguments.
* 'dir' is always modified to contain the result of
* applying the filters. The return value is a pointer
* to dir.
*
* apply_filters might also modify any of the following global
* variables:
*
* FILTERS: Have access to read or modify the arguments, the
* global variables listed above, and the following
* local variables:
*
*
* RETURNS: A pointer to the resulting directory.
* 0 on failure with the error code in perrno.
*
*
* BUGS: Doesn't trap failures in filters
*/
#define MAX_FILTER_ARGS 20 /* good round number for starters. We should
dynamically allocate the array instead, of
course. */
VDIR
apply_filters(dir,filters,dl,oa)
VDIR dir;
FILTER filters;
VLINK dl;
int oa;
{
VLINK curfil;
VDIR result = dir;
char npath[MAXPATHLEN];
char *argarray[MAX_FILTER_ARGS];
char *miscarray[2];
int argcount = 0;
int retval;
/* "" means don't load a symbol table */
DISABLE_PFS(initialize_loader(""));
curfil = filters;
while(curfil) {
TOKEN argi; /* argument index */
assert(curfil->execution_location == FIL_CLIENT);
assert(curfil->type == FIL_DIRECTORY || curfil->type == FIL_HIERARCHY);
argarray[0] = NULL;
/* Additional arguments to the filter */
miscarray[0] = (char *) dl;
miscarray[1] = (char *) filters;
for (argi = curfil->args, argcount = 0; argi; argi = argi->next) {
argarray[argcount++] = stcopy(argi->token);
assert(argcount <= MAX_FILTER_ARGS);
}
retval = mapname(curfil,npath,MAP_READONLY);
if(retval) {
perrno = retval;
return(0);
}
DISABLE_PFS(load_filter(npath));
/* I'm amazed this works - we have a struc filter in pfs.h,
and a variable filter hereh*/
filter = select_filter("filter");
result = (VDIR) filter(result,miscarray,argcount,argarray);
if(oa) curfil = curfil->next;
else curfil = NULL;
}
if(result != dir) vdir_copy(result,dir);
reorder_dir(dir);
return(dir);
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 1989, 1990 by the University of Washington
*
* For copying and distribution information, please see the file
* <uw-copyright.h>.
*/
#include <uw-copyright.h>
#include <stdio.h>
#include <string.h>
#include <pfs.h>
#include <perrno.h>
#ifdef NEVERDEFINED_NOTUSED
char *
flist2string(flist)
VLINK flist;
{
static char fstring[1000];
char *p = fstring;
*p = '\0';
while(flist) {
sprintf(p,"{%c,%s,%s,%s,%s,%s}",flist->linktype,flist->hosttype,
flist->host,flist->hsonametype,flist->hsoname,flist->args);
p += strlen(p);
flist = flist->next;
}
return(fstring);
}
#endif /*NEVERDEFINED*/
#ifdef NEVERDEFINEDBUGGYASANYTHING
VLINK
fstring2list(st)
char *st;
{
VLINK flist = NULL;
VLINK fl = NULL;
VLINK nf;
char *sp = st;
while(*sp) { /* This is bizarre sp never changes!! */
nf = vlalloc();
if(fl) fl->next = nf;
else flist = nf;
fl = nf;
sscanf(sp,"{%c,%s,%s,%s,%s, %[^}]",&(fl->linktype),fl->hosttype,
fl->host,fl->hsonametype,fl->hsoname,fl->args);
flist = flist->next;
}
return(flist); /* Also bizarre - always null!! */
}
#endif /*NEVERDEFINED*/

View File

@@ -0,0 +1,134 @@
/*
* Copyright (c) 1989, 1990 by the University of Washington
*
* For copying and distribution information, please see the file
* <uw-copyright.h>.
*/
#include <uw-copyright.h>
/*----------------------------------------------------------------------*/
/* */
/* helpers.c */
/* */
/* Routines to help Prospero interface with the EI. */
/* */
/*----------------------------------------------------------------------*/
#include "ei/arbBA/ei.h"
#include "ei/arbBA/symtab.h"
#include "ei/arbBA/node.h"
#include "ei/arbBA/arb.h"
#include "ei/arbBA/map.h"
#include <pfs.h>
#include <stdio.h>
#include <string.h>
/*typedef char *(*STR_function)();*/
STR_function filter;
/*
* load_filter - a crude but adequate procedure for loading in a filter.
* When called several times in succession, cascades the filters
* in nested `focuses'. This assures that the currently loaded file
* is the one first looked at, and then it searches upward. A better
* model might build a very bushy tree instead, which would prevent a
* bad reference being accidentally resolved by a filter loaded earlier.
*/
load_filter(filter_file_name)
char *filter_file_name;
{
struct node *app_node;
struct node *ext_node;
int fnl; /* Filter name length */
fnl = strlen(filter_file_name);
if(strcmp(filter_file_name+fnl-2,".o")==0) {
*(filter_file_name+fnl-2) = '\0';
}
app_node = EIRegister(CURRENT,filter_file_name);
ext_node = ext(app_node);
change_focus(ext_node);
}
STR_function select_filter(filter_name)
char *filter_name;
{
return (STR_function) C_select(CURRENT,filter_name);
}
initialize_loader(fullpath)
char *fullpath;
{
ei_initialize(1,&fullpath);
}
struct sym_ent {
char *symbol;
long addr;
};
/* The following is the list of variables and procedures that */
/* are to be accessible from within filters. */
/* */
/* The values of these variables should be constant, though */
/* an errant filter might change them. */
extern int atlfree();
extern char *index();
extern PATTRIB pget_at();
extern int printf();
extern VLINK rd_vlink();
extern char *stcopy();
extern char *stcopyr();
extern char *strncpy();
extern VLINK vlalloc();
extern VLINK vlcopy();
extern int vllfree();
extern VLINK vl_delete();
extern int vl_insert();
extern int wcmatch();
extern char *FlT_htype;
extern char *FlT_ostype;
static struct sym_ent
filter_externals[] = {{"_atlfree",(long)atlfree},
{"_index",(long)index},
{"_pget_at",(long)pget_at},
{"_printf",(long)printf},
{"_rd_vlink",(long)rd_vlink},
{"_sprintf",(long)sprintf},
{"_stcopy",(long)stcopy},
{"_stcopyr",(long)stcopyr},
{"_vlalloc",(long)vlalloc},
{"_vlcopy",(long)vlcopy},
{"_vllfree",(long)vllfree},
{"_vl_delete",(long)vl_delete},
{"_vl_insert",(long)vl_insert},
{"_wcmatch",(long)wcmatch},
{"_FlT_hosttype",(long)&FlT_htype},
{"_FlT_ostype",(long)&FlT_ostype},
{"",0}};
/*
* symbol_find - take a name passed from the C dynamic linker and look it
* up in this table for prospero filters. Returns its address, or -1 on
* failure.
*/
long symbol_find(name)
char *name;
{
struct sym_ent *sym;
for (sym = filter_externals ; sym->addr != 0; sym++) {
if (strcmp(name,sym->symbol) == 0)
return(sym->addr);
}
return -1; /* failure */
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 1989, 1990 by the University of Washington
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>
*/
#include <uw-copyright.h>
#include <usc-copyr.h>
#include <pfs.h>
/*
* apply_filters - Apply filters to a directory NULL VERSION
*
* This was the null version of apply filters. It is used
* in those implementations that do not support filters.
*
* Added a predefined filter, from server/list.c
*/
VDIR
dummy_filter(VDIR dir, TOKEN args)
{
printf("Do dummy filter");
return dir;
}
VDIR (*user_filter1)() = dummy_filter;
VDIR (*user_filter2)() = dummy_filter;
VDIR (*user_filter3)() = dummy_filter;
VDIR (*user_filter4)() = dummy_filter;
VDIR (*user_filter5)() = dummy_filter;
#define MAX_FILTER_ARGS 30 /* See note elsewhere about this*/
VDIR
apply_filters(dir,filters, dl, oa)
VDIR dir;
FILTER filters;
VLINK dl;
int oa;
{
FILTER curfil;
VDIR result = dir;
curfil = filters;
while(curfil) {
#ifdef NEVER_DEFINED
if (strequal(curfil->name, "XYZ") {
char *argarray[MAX_FILTER_ARGS];
int argcount = 0;
TOKEN argi; /* argument index */
for (argi = curfil->args, argcount = 0; argi; argi = argi->next) {
argarray[argcount++] = stcopy(argi->token);
assert(argcount <= MAX_FILTER_ARGS);
}
return(xyz_filter(dir,argcount,argarray);
}
#endif
if (strequal(curfil->name, "USER1"))
result = (user_filter1(result,curfil->args)) ;
if (strequal(curfil->name, "USER2"))
result = (user_filter2(result,curfil->args)) ;
if (strequal(curfil->name, "USER3"))
result = (user_filter3(result,curfil->args)) ;
if (strequal(curfil->name, "USER4"))
result = (user_filter4(result,curfil->args)) ;
if (strequal(curfil->name, "USER5"))
result = (user_filter5(result,curfil->args)) ;
if (oa)
curfil = curfil->next;
else
curfil = NULL;
}
if (result != dir) {
vdir_copy(result,dir);
};
return(dir);
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 1989, 1990, 1991 by the University of Washington
*
* For copying and distribution information, please see the file
* <uw-copyright.h>.
*/
#include <uw-copyright.h>
#include <stdio.h>
#include <pfs.h>
reorder_dir(dir)
VDIR dir;
{
VLINK cl;
VLINK tl;
cl = dir->links;
while(cl) {
if((cl->linktype == 'U') || (cl->linktype == '-'))
{
if(cl->previous == NULL) dir->links = cl->next;
else cl->previous->next = cl->next;
if(cl->next) cl->next->previous = cl->previous;
}
tl = cl;
cl = cl->next;
if(tl->linktype == 'U') ul_insert(tl,dir,NULL);
}
cl = dir->ulinks;
while(cl) {
if(cl->linktype != 'U')
{
if(cl->previous == NULL) dir->ulinks = cl->next;
else cl->previous->next = cl->next;
if(cl->next) cl->next->previous = cl->previous;
}
tl = cl;
cl = cl->next;
if((tl->linktype != 'U') && (tl->linktype != '-'))
vl_insert(tl,dir,VLI_ALLOW_CONF);
}
}

1
prospero/lib/pcompat/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
Makefile

View File

@@ -0,0 +1,17 @@
FILES
Makefile
closedir.c
creat.c
execve.c
getvdirent.c
open.c
opendir.c
pcompat_init.c
pfs_access.c
pfs_default.c
pfs_quiet.c
readdir.c
scandir.c
seekdir.c
stat.c
telldir.c

129
prospero/lib/pcompat/Makefile.in Executable file
View File

@@ -0,0 +1,129 @@
SOURCEBASE = ../..
include $(SOURCEBASE)/Makefile.config
# There used to be a lib/pcompat/Makefile.pcompat and a separate
# lib/pcompat/Makefile.nopcompat.
# This is no longer the case.
CFILES = \
closedir.c \
creat.c \
execve.c \
getvdirent.c \
open.c \
opendir.c \
pcompat_init.c \
pfs_access.c \
pfs_default.c \
pfs_quiet.c \
readdir.c \
scandir.c \
seekdir.c \
stat.c \
telldir.c
OBJECTS = \
closedir.o \
creat.o \
execve.o \
getvdirent.o \
open.o \
opendir.o \
pcompat_init.o \
pfs_access.o \
pfs_default.o \
pfs_quiet.o \
readdir.o \
scandir.o \
seekdir.o \
stat.o \
telldir.o
all: ${CMP_LIB}
${CMP_LIB}: ${OBJECTS}
rm -f ${CMP_LIB}
ar rv ${CMP_LIB} ${OBJECTS}
ranlib ${CMP_LIB}
install:
# $(INSTALL) -o $(OWNER) -g $(GROUP) ${CMP_LIB} ${P_BINARIES}/${CMP_LIB}
# ranlib ${P_BINARIES}/${CMP_LIB}
# Dependencies
closedir.o : \
../../include/pmachine.h
creat.o : \
../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h ../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pcompat.h
execve.o : \
../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pcompat.h
getvdirent.o : \
../../include/pmachine.h \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/implicit_fixes.h \
../../include/pcompat.h ../../include/perrno.h
open.o : \
../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h ../../include/pfs_threads.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pcompat.h \
../../include/perrno.h
opendir.o : \
../../include/pmachine.h
pcompat_init.o : ../../include/pcompat.h \
../../include/pfs_threads.h \
../../include/pfs_utils.h ../../include/pmachine.h \
../../include/pfs.h ../../include/ardp.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/implicit_fixes.h
pfs_access.o : \
../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h ../../include/pfs_threads.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/psite.h ../../include/pcompat.h \
../../include/perrno.h
pfs_default.o : ../../include/pcompat.h \
../../include/pfs_threads.h \
../../include/pfs_utils.h ../../include/pmachine.h
pfs_quiet.o : ../../include/pcompat.h \
../../include/pfs_threads.h \
../../include/pfs_utils.h ../../include/pmachine.h
readdir.o : \
../../include/pmachine.h
scandir.o : \
../../include/pmachine.h \
../../include/pfs_threads.h \
../../include/pfs_utils.h
seekdir.o : \
../../include/pmachine.h
stat.o : \
../../include/pfs.h ../../include/pfs_utils.h \
../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pcompat.h \
../../include/perrno.h
telldir.o : \
../../include/pmachine.h

View File

@@ -0,0 +1,74 @@
/*
* Derived from Berkeley source code. Those parts are
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)closedir.c 5.8 (Berkeley) 6/1/90";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <errno.h>
#include <pmachine.h>
#ifdef USE_SYS_DIR_H
#include <sys/dir.h>
#else
#include <dirent.h>
#endif
/*
* close a directory.
*/
#ifdef CLOSEDIR_RET_TYPE_VOID
void
#else
int
#endif
closedir(dirp)
register DIR *dirp;
{
int fd;
fd = dirp->dd_fd;
dirp->dd_fd = -1;
dirp->dd_loc = 0;
(void)free((void *)dirp->dd_buf);
(void)free((void *)dirp);
if(fd < 0) {
if(p__delvdirentries(fd)) {
errno = EBADF;
#ifdef CLOSEDIR_RET_TYPE_VOID
return;
#else
return(-1);
#endif
}
#ifdef CLOSEDIR_RET_TYPE_VOID
return;
#else
return(0);
#endif
}
#ifdef CLOSEDIR_RET_TYPE_VOID
else return;
#else
else return(close(fd));
#endif
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 1989, 1990, 1991 by the University of Washington
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>.
*/
#include <uw-copyright.h>
#include <usc-copyr.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/file.h>
#include <sys/param.h>
#ifdef SOLARIS
#include <sys/syscall.h>
#else
#include <syscall.h>
#endif
#include <errno.h>
#include <pfs.h>
#include <pcompat.h>
#include <pmachine.h>
/* syscall is not MT-safe (at least under Solaris)
#ifndef PFS_THREADS
creat(const char *name,
#ifdef OPEN_MODE_ARG_IS_INT
int mode
#else
mode_t mode
#endif
)
{
char npath[MAXPATHLEN];
int tmp;
tmp = pfs_access(name, npath, sizeof npath, PFA_CRMAP);
if(tmp) return(-1);
return(syscall(SYS_creat,npath,mode));
}
#endif /*PFS_THREADS*/

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 1992, 1994 by the University of Southern California
*
* For copying and distribution information, please see the files
* <usc-license.h>
*/
#include <usc-license.h>
#include <sys/param.h>
#ifdef SOLARIS
#include <sys/syscall.h>
#else
#include <syscall.h>
#endif
#include <errno.h>
#include <pfs.h>
#include <pcompat.h>
/* syscall is not MT-safe (at least under Solaris) */
#ifndef PFS_THREADS
int
execve(const char *name, char * const*argv, char * const *envp)
{
char npath[MAXPATHLEN];
int tmp;
tmp = pfs_access(name, npath, sizeof npath, PFA_MAP);
/* Should figure out what correct error return should be */
if(tmp) return(-1);
return(syscall(SYS_execve,npath,argv,envp));
}
#endif /*PFS_THREADS*/

View File

@@ -0,0 +1,186 @@
/*
* Copyright (c) 1991-1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
#include <sys/param.h>
#define DIRSIZ_MACRO /* needed for HPUX; does no harm otherwise. */
#include <stdio.h>
#include <stdlib.h> /* For malloc or free */
#include <pmachine.h>
/* Needed if not already included. */
#ifdef USE_SYS_DIR_H /* Support for SYS_DIR_H may be finally dead.
I hope. */
#include <sys/dir.h>
#else
#include <dirent.h>
#endif
#include <pfs.h>
#include <pcompat.h>
#include <perrno.h>
/* Maximum open virtual directories */
#define MAX_VDDESC 16
static struct dirent *dirbuf[MAX_VDDESC + 1] = {NULL};
static int dirpos[MAX_VDDESC + 1] = {0};
static int dirbsz[MAX_VDDESC + 1] = {0};
int
p__getvdirentries(int fd, char *buf, int nbytes, int *basep)
{
int bytes = 0;
struct dirent *dp;
char *bp;
if(fd > -1) return(0);
if(fd < - MAX_VDDESC) return(0);
dp = (struct dirent *) ((char *)dirbuf[-fd] + dirpos[-fd]);
while(dp->d_reclen && (dp->d_reclen <= nbytes)) {
bcopy(dp,buf,dp->d_reclen);
nbytes = nbytes - (unsigned short) dp->d_reclen;
buf = buf + (unsigned short) dp->d_reclen;
bytes = bytes + (unsigned short) dp->d_reclen;
bp = (char *) dp;bp += dp->d_reclen;dp = (struct dirent *) bp;
}
*basep = dirpos[-fd];
dirpos[-fd] = dirpos[-fd] + bytes;
return(bytes);
}
int
p__readvdirentries(char *dirname)
{
VDIR_ST dir_st;
VDIR dir= &dir_st;
VLINK l;
long dsize = 0;
int dirnum = 0;
struct dirent *dp;
int tmp;
vdir_init(dir);
check_pfs_default();
/* If disabled, do no mapping */
if(pfs_enable == PMAP_DISABLE) return(PSUCCESS);
/* This is a kludge. We should not be modifying the */
/* path arg, but... */
if(pfs_enable == PMAP_ATSIGN) {
if(*dirname == '@') {
strcpy(dirname,dirname+1);
return(PSUCCESS);
}
}
if(pfs_enable == PMAP_COLON) {
if(*dirname == ':') dirname++;
else return(PSUCCESS);
}
p__compat_initialize();
tmp = rd_vdir(dirname,0,dir,RVD_LREMEXP);
if(tmp) return(tmp);
l = dir->links;
while(l) {
/* The next statement should track the DIRSIZ macro */
dsize = dsize + (sizeof(struct dirent) - (MAXNAMLEN+1)) +
((strlen(l->name)+1 +3) & ~3);
l = l->next;
}
/* This is just in case */
dsize = dsize + 256;
dirnum = 0;
while(dirnum++ <= MAX_VDDESC) {
if(!dirbuf[dirnum]) break;
}
if(dirnum > MAX_VDDESC) RETURNPFAILURE;
dp = (struct dirent *) malloc(dsize);
dirbuf[dirnum] = dp;
dirpos[dirnum] = 0;
dirbsz[dirnum] = dsize;
l = dir->links;
while(l) {
dp->d_ino = (unsigned long) 999;
#if !defined (SOLARIS)
dp->d_namlen = (unsigned short) strlen(l->name);
#endif
dp->d_reclen = (unsigned short) DIRSIZ(dp);
strcpy(dp->d_name,l->name);
dp = (struct dirent *) ((char *) dp + dp->d_reclen);
l = l->next;
}
dp->d_ino = (unsigned long) 0;
dp->d_reclen = (unsigned short) 0;
#if !defined (SOLARIS)
dp->d_namlen = (unsigned short) 0;
#endif
*(dp->d_name) = '\0';
vllfree(dir->links);
vllfree(dir->ulinks);
return(-dirnum);
}
int
p__delvdirentries(int desc)
{
if(desc > -1) RETURNPFAILURE;
if(desc < - MAX_VDDESC) RETURNPFAILURE;
if(dirbuf[- desc]) {
free(dirbuf[- desc]);
dirbuf[- desc] = NULL;
return(PSUCCESS);
}
RETURNPFAILURE;
}
int
p__seekvdir(int desc, int pos)
{
if(desc > -1) RETURNPFAILURE;
if(desc < - MAX_VDDESC) RETURNPFAILURE;
if(!dirbuf[- desc]) RETURNPFAILURE;
dirpos[-desc] = pos;
return(PSUCCESS);
}
int
p__getvdbsize(int desc, int pos)
{
if(desc > -1) RETURNPFAILURE;
if(desc < - MAX_VDDESC) RETURNPFAILURE;
if(!dirbuf[- desc]) RETURNPFAILURE;
return(dirbsz[-desc]);
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 1992,1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
/* Originally written by Cliff Neuman, 1989
Modified by Steven Augart, 1992, 1994
*/
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/file.h>
#include <sys/param.h>
#ifdef SOLARIS
#include <sys/syscall.h>
#else
#include <syscall.h>
#endif
#include <errno.h>
#include <pfs.h>
#include <pcompat.h>
#include <perrno.h>
#include <pmachine.h>
extern int pfs_quiet;
/* HPUX prototype: extern int open(const char *, int, ...);
SunOS prototype: int open() */
int
#ifndef PROTOTYPE_FOR_OPEN_HAS_EMPTY_ARGLIST
open(const char *path, int flags, ...)
{
va_list ap;
#ifdef OPEN_MODE_ARG_IS_INT
int mode;
#else
mode_t mode;
#endif
#else
open(path, flags, mode)
char *path;
int flags;
#ifdef OPEN_MODE_ARG_IS_INT
int mode;
#else
mode_t mode;
#endif
{
#endif
char npath[MAXPATHLEN];
int pfaflags;
int tmp;
int open_return;
#ifndef PROTOTYPE_FOR_OPEN_HAS_EMPTY_ARGLIST
va_start(ap, flags);
#ifdef OPEN_MODE_ARG_IS_INT
mode = va_arg(ap, int);
#else
mode = va_arg(ap, mode_t);
#endif
#endif
if(flags & O_CREAT) pfaflags = PFA_CRMAP;
else pfaflags = PFA_MAP;
if((flags & (O_ACCMODE)) == O_RDONLY) pfaflags |= PFA_RO;
tmp = pfs_access(path,npath, sizeof npath, pfaflags);
if(tmp && (tmp != PMC_DELETE_ON_CLOSE)) {
if(!pfs_quiet) printf("open failed: %s\n",p_err_text[tmp]);
errno = ENOENT;
return(-1);
}
open_return = syscall(SYS_open,npath,flags,mode);
if(tmp == PMC_DELETE_ON_CLOSE) unlink(npath);
return(open_return);
}

View File

@@ -0,0 +1,105 @@
/*
* Derived from Berkeley source code. Those parts are
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)opendir.c 5.10 (Berkeley) 6/1/90";
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
#include <fcntl.h>
#include <errno.h>
#include <pmachine.h>
#ifdef USE_SYS_DIR_H
#include <sys/dir.h>
#else
#include <dirent.h>
#endif
#if defined(AIX) && defined(__GNUC__) /* lucb */
#define dd_bsize dd_size
#endif
#ifndef DIRBLKSIZ
#define DIRBLKSIZ 512
#endif
#include <stdlib.h> /* For malloc */
long _rewinddir;
/*
* open a directory.
*/
DIR *
opendir(const char *name)
{
register DIR *dirp;
register int fd;
fd = p__readvdirentries(name);
if(fd > 0) {
errno = ENOENT;
return(NULL);
}
if(fd == 0) {
if ((fd = open(name, 0, 0)) == -1)
return NULL;
if (fcntl(fd, F_SETFD, 1) == -1) {
close (fd);
return(NULL);
}
}
if((dirp = (DIR *)malloc(sizeof(DIR))) == NULL) return(NULL);
/*
* If CLSIZE is an exact multiple of DIRBLKSIZ, use a CLSIZE
* buffer that it cluster boundary aligned.
* Hopefully this can be a big win someday by allowing page trades
* to user space to be done by getdirentries()
*/
#ifdef CLSIZE
if ((CLSIZE % DIRBLKSIZ) == 0) {
dirp->dd_buf = malloc(CLSIZE);
dirp->dd_bsize = CLSIZE;
} else {
#endif
dirp->dd_buf = malloc(DIRBLKSIZ);
dirp->dd_bsize = DIRBLKSIZ;
#ifdef CLSIZE
}
#endif
if (dirp->dd_buf == NULL) {
close (fd);
return NULL;
}
dirp->dd_fd = fd;
dirp->dd_loc = 0;
#ifdef SUNOS /* lucb */
dirp->dd_bbase = 0;
#endif
/*
* Set up seek point for rewinddir.
*/
_rewinddir = telldir(dirp);
return dirp;
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright (c) 1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
#include <pcompat.h> /* prototype for p__compat_initialize() */
#include <pfs.h> /* prototype for p_initialize() */
/* Author: Steven Seger Augart, Mar. 30, 1994 */
/* This file contains automatic initialization routines for the PCOMPAT
library. No Prospero functions should be called before p_initialize() has
been called. This makes the pcompat library self-initializing. */
/* This function can be safely called more than once. */
static int initialized = 0;
void
p__compat_initialize(void)
{
if (!initialized) {
++initialized;
p_initialize("uclP", 0, (struct p_initialize_st *) NULL);
}
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright (c) 1989, 1990, 1991 by the University of Washington
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>.
*/
#include <uw-copyright.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/param.h>
#include <errno.h>
#include <pfs.h>
#include <psite.h>
#include <pcompat.h>
#include <pmachine.h>
#include <perrno.h>
/*
* see pcompat.h for the meanings of the flage
*/
int
pfs_access(const char *path, char *npath, int npathlen, int flags)
{
char cpath[MAXPATHLEN];
char *prefix;
char *suffix;
VLINK vl;
int tmp;
suffix = "";
check_pfs_default();
errno = 0;
/* If disabled, do no mapping */
if(pfs_enable == PMAP_DISABLE) {
strcpy(npath,path);
return(PSUCCESS);
}
if(pfs_enable == PMAP_COLON) {
if(*path == ':') path++;
else if(index(path,':'));
else {strcpy(npath,path); return(PSUCCESS);}
}
if((pfs_enable == PMAP_ATSIGN_NF) || (pfs_enable == PMAP_ATSIGN)) {
if(*path == '@') {
path++;
strcpy(npath,path);
return(PSUCCESS);
}
}
p__compat_initialize();
/* I should probably choose better values for errno */
vl = rd_vlink(path);
if((perrno || !vl) && ((flags == PFA_CRMAP)||(flags == PFA_CREATE))) {
strcpy(cpath,path);
prefix = cpath;
suffix = strrchr(cpath,'/');
if(suffix) {
if(suffix == prefix) prefix = "/";
*(suffix++) = '\0';
vl = rd_vlink(prefix);
if(vl) {
sprintf(cpath,"%s/%s",vl->hsoname,suffix);
vl->hsoname = stcopyr(cpath,vl->hsoname);
}
}
}
/* If not found, but PMAP_ATSIGN_NF, then check if a real file */
if(((perrno == PFS_DIR_NOT_FOUND) || (perrno == RVD_DIR_NOT_THERE) ||
(!perrno && !vl)) &&
(pfs_enable == PMAP_ATSIGN_NF) &&
(*path == '/') && ((strncmp(path,"/tmp",4) == 0) ||
((flags != PFA_CRMAP) && (flags != PFA_CREATE)))) {
strcpy(npath,path);
return(PSUCCESS);
}
if(perrno) {errno = ENOENT;return(perrno);}
if(!vl) {errno = ENOENT;return(PFS_FILE_NOT_FOUND);}
#ifdef PCOMPAT_SUPPORT_FTP
/* P_AM_FTP requires prompting for a password, which is not something
transparent to the user. That's why without the special
PCOMPAT_SUPPORT_FTP definition, mapname isn't called with the
MAP_PROMPT_OK option. */
tmp = mapname(vl,npath, npathlen,
MAP_PROMPT_OK | ((flags & PFA_RO) ?
MAP_READONLY : MAP_READWRITE));
#else
tmp = mapname(vl,npath, npathlen, ((flags & PFA_RO) ?
MAP_READONLY : MAP_READWRITE));
#endif
vllfree(vl);
if(tmp && (tmp != PMC_DELETE_ON_CLOSE)) errno = ENOENT;
return(tmp);
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*/
#include <usc-license.h>
#include <pcompat.h>
int pfs_default = -1;
char *getenv();
extern int pfs_debug;
void
p__get_pfs_default(void)
{
char *pfs_default_string;
char *pfs_debug_string;
/* if pfs_disable_flag is set to disable, skip as there */
/* is probably a reason for it */
if(pfs_enable == PMAP_DISABLE) return;
/* Check PFS_DEFAULT and if set, set pfs_disable_flag */
if(pfs_default == -1) {
pfs_default_string = getenv("PFS_DEFAULT");
if(pfs_default_string == 0) pfs_default = -2;
else if(sscanf(pfs_default_string,"%d",&pfs_default) != 1)
pfs_default = -2;
else pfs_enable = pfs_default;
}
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright (c) 1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
#include <pcompat.h>
/* Written: Cliff Neuman, 1989, 1991. */
/* Updated documentation and declarations: swa@ISI.EDU, 1994. */
/*
* pfs_quiet - Printing of error messages on prospero failure
*
* This file initializes pfs_quiet to 0. It is included
* the pcompat library library in case it is left out
* by an application. A value of 0 means that open and
* other redefined system calls will print an error
* message on the standard error stream before returning
* if an error was detected by Prospero.
*
*/
int pfs_quiet = 0;

View File

@@ -0,0 +1,77 @@
/*
* Derived from Berkeley source code. Those parts are
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)readdir.c 5.7 (Berkeley) 6/1/90";
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
#include <pmachine.h>
#ifdef USE_SYS_DIR_H
#include <sys/dir.h>
#else
#include <dirent.h>
#endif
/*
* get next entry in a directory.
*/
struct dirent *
readdir(dirp)
register DIR *dirp;
{
register struct dirent *dp;
for (;;) {
if (dirp->dd_loc == 0) {
if(dirp->dd_fd >= 0)
#if defined(SUNOS)
dirp->dd_size = getdents(dirp->dd_fd,
dirp->dd_buf, dirp->dd_bsize);
#else
dirp->dd_size = getdirentries(dirp->dd_fd,
dirp->dd_buf, dirp->dd_bsize, &dirp->dd_bbase);
#endif
else
dirp->dd_size = p__getvdirentries(dirp->dd_fd,
dirp->dd_buf, dirp->dd_bsize, &dirp->dd_bbase);
if (dirp->dd_size <= 0)
return NULL;
}
if (dirp->dd_loc >= dirp->dd_size) {
dirp->dd_loc = 0;
continue;
}
dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc);
if ((int)dp & 03) /* bogus pointer check */
return NULL;
#if defined(SUNOS)
dirp->dd_bbase = dp->d_off;
#endif
if (dp->d_reclen <= 0 ||
dp->d_reclen > dirp->dd_bsize + 1 - dirp->dd_loc)
return NULL;
dirp->dd_loc += dp->d_reclen;
if (dp->d_ino == 0)
continue;
return (dp);
}
}

View File

@@ -0,0 +1,142 @@
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted provided
* that: (1) source distributions retain this entire copyright notice and
* comment, and (2) distributions including binaries display the following
* acknowledgement: ``This product includes software developed by the
* University of California, Berkeley and its contributors'' in the
* documentation or other materials provided with the distribution and in
* all advertising materials mentioning features or use of this software.
* 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)scandir.c 5.9 (Berkeley) 6/24/90";
#endif /* LIBC_SCCS and not lint */
/*
* Scan the directory dirname calling select to make a list of selected
* directory entries then sort using qsort and compare routine dcomp.
* Returns the number of entries and a pointer to a list of pointers to
* struct dirent (through namelist). Returns -1 if there were any errors.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h> /* For malloc and free */
#include <pmachine.h>
#ifdef USE_SYS_DIR_H
#include <sys/dir.h>
#else
#include <dirent.h>
#endif
#include <pfs_threads.h> /* For PFS_THREADS */
/*
* The DIRSIZ macro gives the minimum record length which will hold
* the directory entry. This requires the amount of space in struct dirent
* without the d_name field, plus enough space for the name with a terminating
* null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
*/
#undef DIRSIZ
#define DIRSIZ(dp) \
((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
int
scandir(const char *dirname, struct dirent ***namelist,
int (*select)(const struct dirent *),
int (*dcomp)(const struct dirent **, const struct dirent **))
{
register struct dirent *d, *p, **names;
register int nitems;
struct stat stb;
long arraysz;
DIR *dirp;
/* The next variable shuts up GCC thinking that dcomp is of a different
type from int (*)() */
int (*dcomp_qsort_losing_prototype)() = (int (*)()) dcomp;
#ifdef PFS_THREADS
struct {
struct dirent a;
char b[_POSIX_PATH_MAX];
} readdir_result_st;
struct dirent *readdir_result = (struct dirent *) &readdir_result_st;
#endif
if ((dirp = opendir(dirname)) == NULL) {
return(-1);
}
if (fstat(dirp->dd_fd, &stb) < 0) {
closedir(dirp);
return(-1);
}
/*
* estimate the array size by taking the size of the directory file
* and dividing it by a multiple of the minimum size entry.
*/
arraysz = (stb.st_size / 24);
names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
if (names == NULL)
return(-1);
nitems = 0;
assert(P_IS_THIS_THREAD_MASTER()); /*SOLARIS: readdir is MT-Unsafe */
#ifdef PFS_THREADS
while ((d = readdir_r(dirp,readdir_result)) != NULL) {
#else
while ((d = readdir(dirp)) != NULL) {
#endif
if (select != NULL && !(*select)(d))
continue; /* just selected names */
/*
* Make a minimum size copy of the data
*/
p = (struct dirent *)malloc(DIRSIZ(d));
if (p == NULL)
return(-1);
p->d_ino = d->d_ino;
p->d_reclen = d->d_reclen;
p->d_namlen = d->d_namlen;
bcopy(d->d_name, p->d_name, p->d_namlen + 1);
/*
* Check to make sure the array has space left and
* realloc the maximum size.
*/
if (++nitems >= arraysz) {
if (fstat(dirp->dd_fd, &stb) < 0)
return(-1); /* just might have grown */
arraysz = stb.st_size / 12;
names = (struct dirent **)realloc((char *)names,
arraysz * sizeof(struct dirent *));
if (names == NULL)
return(-1);
}
names[nitems-1] = p;
}
closedir(dirp);
if (nitems && dcomp != NULL)
qsort(names, nitems, sizeof(struct dirent *),
dcomp_qsort_losing_prototype);
*namelist = names;
return(nitems);
}
/*
* Alphabetic order comparison routine for those who want it.
*/
int
alphasort(const struct dirent **d1, const struct dirent **d2)
{
return strcmp((*d1)->d_name, (*d2)->d_name);
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)seekdir.c 5.7 (Berkeley) 6/1/90";
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
#include <pmachine.h>
#ifdef USE_SYS_DIR_H
#include <sys/dir.h>
#else
#include <dirent.h>
#endif
/*
* Seek to an entry in a directory.
* p__seekdir is in telldir.c so that it can share opaque data structures.
*/
void
seekdir(DIR *dirp, long loc)
{
p__seekdir(dirp, loc);
}

136
prospero/lib/pcompat/stat.c Normal file
View File

@@ -0,0 +1,136 @@
/*
* Copyright (c) 1993, 1994 by the University of Southern California
*
* For copying and distribution information, please see the files
* <usc-license.h>
*/
#include <usc-license.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef SOLARIS
#include <sys/syscall.h>
#else
#include <syscall.h>
#endif
#include <errno.h>
#include <pfs.h>
#include <pcompat.h>
#include <pmachine.h> /* for bzero */
#include <perrno.h> /* for testing against errors returned by
prospero subfunctions. */
static int stat_l(const char *path, struct stat *buf, int lflag);
/* syscall is not MT-safe (at least under Solaris) */
#ifndef PFS_THREADS
/* Call stat_l indicating normal stat */
int
stat(const char *path, struct stat *buf)
{
return(stat_l(path,buf,0));
}
/* Call stat_l indicating lstat */
int
lstat(const char *path, struct stat *buf)
{
return(stat_l(path,buf,1));
}
static int
stat_l(const char *path, struct stat *buf, int lflag)
{
VDIR_ST dir_st;
VDIR dir= &dir_st;
PATTRIB ap,nextap;
int tmp;
vdir_init(dir);
check_pfs_default();
/* If disabled, make system call */
if(pfs_enable == PMAP_DISABLE) {
return(syscall((lflag ? SYS_lstat : SYS_stat), path, buf));
}
if(pfs_enable == PMAP_COLON) {
if(*path == ':') path++;
else if(index(path,':'));
else return(syscall((lflag ? SYS_lstat : SYS_stat), path, buf));
}
if((pfs_enable == PMAP_ATSIGN_NF) || (pfs_enable == PMAP_ATSIGN)) {
if(*path == '@') {
path++;
return(syscall((lflag ? SYS_lstat : SYS_stat), path, buf));
}
}
bzero(buf,sizeof(struct stat));
buf->st_uid = (uid_t) -1;
buf->st_gid = (gid_t) -1;
p__compat_initialize();
/* I should probably choose better values for errno */
tmp = rd_vdir(path,0,dir,RVD_DFILE_ONLY|RVD_ATTRIB);
if((dir->links == NULL) || (tmp && (tmp != DIRSRV_NOT_DIRECTORY))) {
if(((tmp == PFS_DIR_NOT_FOUND)||(tmp == RVD_DIR_NOT_THERE)|| !tmp)&&
(pfs_enable == PMAP_ATSIGN_NF) && (*path == '/')) {
return(syscall((lflag ? SYS_lstat : SYS_stat), path, buf));
}
errno = ENOENT;
return(-1);
}
if(tmp == 0) buf->st_mode |= (S_IFDIR | 0555);
else buf->st_mode |= 0444;
if(strncmp(dir->links->target,"EXTERNAL",8) == 0) ap = NULL;
else ap = pget_at(dir->links,"#ALL");
/* If can't get real attributes, try those stored with link */
if((ap == NULL) && dir->links->lattrib) {
ap = dir->links->lattrib;
dir->links->lattrib = NULL;
}
while(ap) {
switch (*(ap->aname)) {
case 'L':
if((strcmp(ap->aname,"LAST-MODIFIED") == 0) &&
ap->avtype == ATR_SEQUENCE ) {
buf->st_mtime = asntotime(ap->value.sequence->token);
}
break;
case 'S':
if((strcmp(ap->aname,"SIZE") == 0) &&
ap->avtype == ATR_SEQUENCE) {
int size;
qsscanf(ap->value.sequence->token,"%d",&size);
buf->st_size = size;
/* The following is a good guess at number of blocks */
buf->st_blocks = (size+511) / 512;
}
break;
default:
break;
}
nextap = ap->next;
atfree(ap);
ap = nextap;
}
vllfree(dir->links);
vllfree(dir->ulinks);
return(0);
}
#endif /*PFS_THREADS*/

View File

@@ -0,0 +1,129 @@
/*
* Derived from Berkeley source code. Those parts are
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)telldir.c 5.8 (Berkeley) 6/1/90";
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
#include <pmachine.h>
#include <stdlib.h> /* For malloc and free */
#ifdef USE_SYS_DIR_H
#include <sys/dir.h>
#else
#include <dirent.h>
#endif
#if defined(AIX) && defined(__GNUC__) /* lucb */
#define dd_bsize dd_size
#endif
/*
* The option SINGLEUSE may be defined to say that a telldir
* cookie may be used only once before it is freed. This option
* is used to avoid having memory usage grow without bound.
*/
#define SINGLEUSE
/*
* One of these structures is malloced to describe the current directory
* position each time telldir is called. It records the current magic
* cookie returned by getdirentries and the offset within the buffer
* associated with that return value.
*/
struct ddloc {
struct ddloc *loc_next;/* next structure in list */
long loc_index; /* key associated with structure */
long loc_seek; /* magic cookie returned by getdirentries */
long loc_loc; /* offset of entry in buffer */
};
#define NDIRHASH 32 /* Num of hash lists, must be a power of 2 */
#define LOCHASH(i) ((i)&(NDIRHASH-1))
static long dd_loccnt; /* Index of entry for sequential readdir's */
static struct ddloc *dd_hash[NDIRHASH]; /* Hash list heads for ddlocs */
/*
* return a pointer into a directory
*/
long
telldir(dirp)
DIR *dirp;
{
register int index;
register struct ddloc *lp;
if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL)
return (-1);
index = dd_loccnt++;
lp->loc_index = index;
lp->loc_seek = dirp->dd_bbase;
lp->loc_loc = dirp->dd_loc;
lp->loc_next = dd_hash[LOCHASH(index)];
dd_hash[LOCHASH(index)] = lp;
return (index);
}
/*
* seek to an entry in a directory.
* Only values returned by "telldir" should be passed to seekdir.
*/
void
p__seekdir(register DIR *dirp, long loc)
{
register struct ddloc *lp;
register struct ddloc **prevlp;
struct dirent *dp;
extern long lseek();
prevlp = &dd_hash[LOCHASH(loc)];
lp = *prevlp;
while (lp != NULL) {
if (lp->loc_index == loc)
break;
prevlp = &lp->loc_next;
lp = lp->loc_next;
}
if (lp == NULL)
return;
if (lp->loc_loc == dirp->dd_loc && lp->loc_seek == dirp->dd_bbase)
goto found;
if(dirp->dd_fd < 0)
p__seekvdir(dirp->dd_fd,lp->loc_seek);
else
(void) lseek(dirp->dd_fd, lp->loc_seek, 0);
dirp->dd_bbase = lp->loc_seek;
dirp->dd_loc = 0;
while (dirp->dd_loc < lp->loc_loc) {
assert(P_IS_THIS_THREAD_MASTER()); /*SOLARIS: readdir MT-Unsafe */
dp = readdir(dirp);
if (dp == NULL)
break;
}
found:
#ifdef SINGLEUSE
*prevlp = lp->loc_next;
free((caddr_t)lp);
#endif
}

1
prospero/lib/pfs/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
Makefile

117
prospero/lib/pfs/FILES Normal file
View File

@@ -0,0 +1,117 @@
FILES
Makefile
acalloc.c
acltypes.c
add_vlink.c
asntotime.c
atalloc.c
atr_build.c
atr_lookup.c
bindecode.c
binencode.c
charset.h
cl_qoprintf.c
copyfile.c
del_vlink.c
elt.c
equal_atrs.c
equal_seq.c
filetoin.c
fl_insert.c
flalloc.c
fputbst.c
get_acl.c
in_acl.c
in_atrs.c
in_filter.c
in_forwarded.c
in_id.c
in_line.c
in_link.c
in_nextline.c
in_readc.c
in_select.c
in_sequence.c
internal_err.c
is_file.c
length.c
mapname.c
mk_vdir.c
mkdirs.c
modify_acl.c
month_sname.c
myhost.c
oballoc.c
obother.c
opentcp.c
out_acl.c
out_atr.c
out_atrs.c
out_filter.c
out_link.c
out_sequence.c
p__qbstokenize.c
p__qbstscanf.c
p__req.c
p_get_dir.c
p_initialize.c
p_uln_index.c
paalloc.c
penviron.c
perrmesg.c
pfalloc.c
pfs_debug.c
pfs_enable.c
pfs_fopen.c
pfs_mutexes.c
pfs_open.c
pget_am.c
pget_at.c
pmap_cache.c
pmap_nfs.c
pset_at.c
pset_linkat.c
qbstp_stcopyr.c
qfprintf.c
qindex.c
qoprintf.c
qrindex.c
qscanf.c
qsp_stcopyr.c
qsprintf.c
qsscanf.c
qtokenize.c
rd_vdir.c
rd_vlink.c
re_comp_exec.c
readheader.c
scan_error.c
sindex.c
slashpath.c
slashpath2.c
socket.c
stat.c
stcopy.c
stequal.c
strccmp.c
strpbrk.c
strspn.c
timetoasn.c
tkalloc.c
tklistcmp.c
tokeniz_mcmp.c
ucase.c
ul_insert.c
unquote.c
update_link.c
vfsetenv.c
vl_add_atrs.c
vl_comp.c
vl_delete.c
vl_insert.c
vlalloc.c
vqfprintf.c
vqscanf.c
vqsprintf.c
wcmatch.c
wholefiltoin.c

933
prospero/lib/pfs/Makefile.in Executable file
View File

@@ -0,0 +1,933 @@
#
# Makefile for Prospero Directory Service PFS library.
SOURCEBASE = ../..
include $(SOURCEBASE)/Makefile.config
CFILES = \
acalloc.c \
acltypes.c \
add_vlink.c \
asntotime.c \
atalloc.c \
atr_build.c \
atr_lookup.c \
bindecode.c \
binencode.c \
cl_qoprintf.c \
copyfile.c \
del_vlink.c \
elt.c \
equal_atrs.c \
equal_seq.c \
filetoin.c \
flalloc.c \
fl_insert.c \
fputbst.c \
get_acl.c \
in_acl.c \
in_atrs.c \
in_filter.c \
in_forwarded.c \
in_id.c \
in_line.c \
in_link.c \
in_nextline.c \
in_readc.c \
in_select.c \
in_sequence.c \
internal_err.c \
is_file.c \
length.c \
mapname.c \
mk_vdir.c \
mkdirs.c \
month_sname.c \
modify_acl.c \
myhost.c \
oballoc.c \
obother.c \
opentcp.c \
out_acl.c \
out_atr.c \
out_atrs.c \
out_filter.c \
out_link.c \
out_sequence.c \
p__qbstokenize.c \
p__qbstscanf.c \
p__req.c \
p_get_dir.c \
p_initialize.c \
p_uln_index.c \
paalloc.c \
penviron.c \
perrmesg.c \
pfalloc.c \
pfs_debug.c \
pfs_enable.c \
pfs_fopen.c \
pfs_mutexes.c \
pfs_open.c \
pget_am.c \
pget_at.c \
pmap_cache.c \
pmap_nfs.c \
pset_at.c \
pset_linkat.c \
qbstp_stcopyr.c \
qfprintf.c \
qindex.c \
qoprintf.c \
qrindex.c \
qscanf.c \
qsp_stcopyr.c \
qsprintf.c \
qsscanf.c \
qtokenize.c \
rd_vdir.c \
rd_vlink.c \
re_comp_exec.c \
readheader.c \
scan_error.c \
sindex.c \
slashpath.c \
slashpath2.c \
socket.c \
stat.c \
stcopy.c \
stequal.c \
strccmp.c \
strpbrk.c \
strspn.c \
timetoasn.c \
tkalloc.c \
tokeniz_mcmp.c \
ucase.c \
ul_insert.c \
unquote.c \
update_link.c \
vfsetenv.c \
vl_add_atrs.c \
vqfprintf.c \
vqscanf.c \
vqsprintf.c \
vl_comp.c \
vl_delete.c \
vl_insert.c \
vlalloc.c \
wcmatch.c \
wholefiltoin.c
OBJECTS = \
acalloc.o \
acltypes.o \
add_vlink.o \
asntotime.o \
atalloc.o \
atr_build.o \
atr_lookup.o \
bindecode.o \
binencode.o \
cl_qoprintf.o \
copyfile.o \
del_vlink.o \
elt.o \
equal_atrs.o \
equal_seq.o \
filetoin.o \
flalloc.o \
fl_insert.o \
fputbst.o \
get_acl.o \
in_acl.o \
in_atrs.o \
in_filter.o \
in_forwarded.o \
in_id.o \
in_line.o \
in_link.o \
in_nextline.o \
in_readc.o \
in_sequence.o \
in_select.o \
internal_err.o \
is_file.o \
length.o \
mapname.o \
mk_vdir.o \
mkdirs.o \
month_sname.o \
modify_acl.o \
myhost.o \
oballoc.o \
obother.o \
opentcp.o \
out_acl.o \
out_atr.o \
out_atrs.o \
out_filter.o \
out_link.o \
out_sequence.o \
p__qbstokenize.o \
p__qbstscanf.o \
p__req.o \
p_get_dir.o \
p_initialize.o \
p_uln_index.o \
paalloc.o \
penviron.o \
perrmesg.o \
pfalloc.o \
pfs_debug.o \
pfs_enable.o \
pfs_fopen.o \
pfs_mutexes.o \
pfs_open.o \
pget_am.o \
pget_at.o \
pmap_cache.o \
pmap_nfs.o \
pset_at.o \
pset_linkat.o \
qbstp_stcopyr.o \
qfprintf.o \
qindex.o \
qoprintf.o \
qrindex.o \
qscanf.o \
qsp_stcopyr.o \
qsprintf.o \
qsscanf.o \
qtokenize.o \
rd_vdir.o \
rd_vlink.o \
re_comp_exec.o \
readheader.o \
scan_error.o \
sindex.o \
slashpath.o \
slashpath2.o \
socket.o \
stat.o \
stcopy.o \
stequal.o \
strccmp.o \
strpbrk.o \
strspn.o \
timetoasn.o \
tkalloc.o \
tokeniz_mcmp.o \
ucase.o \
ul_insert.o \
unquote.o \
update_link.o \
vfsetenv.o \
vl_add_atrs.o \
vqfprintf.o \
vqscanf.o \
vqsprintf.o \
vl_comp.o \
vl_delete.o \
vl_insert.o \
vlalloc.o \
wcmatch.o \
wholefiltoin.o
all: ${PFS_LIB}
SPECIAL_OTHERTARGETS = $(PFS_LIB)
install:
# We currently don't install this library
# cp ${PFS_LIB} ${P_BINARIES}/${PFS_LIB}
# $(RANLIB) ${P_BINARIES}/${PFS_LIB}
${PFS_LIB}: ${OBJECTS}
rm -f ${PFS_LIB}
ar r${AR_FLAGS} ${PFS_LIB} ${OBJECTS}
$(RANLIB) ${PFS_LIB}
## This will cuse there to be too many dependencies for TAGS and ETAGS
## include $(SOURCEBASE)/Makefile.boilerplate
# Dependencies
acalloc.o : ../../include/pmachine.h \
../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h ../../include/pfs_threads.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/implicit_fixes.h
acltypes.o :
add_vlink.o : \
../../include/ardp.h ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/pprot.h \
../../include/pparse.h \
../../include/perrno.h
asntotime.o :
atalloc.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h ../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
atr_build.o : ../../include/pfs.h ../../include/pfs_utils.h \
../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
atr_lookup.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pprot.h ../../include/pparse.h
bindecode.o :
binencode.o :
cl_qoprintf.o : ../../include/ardp.h \
../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/pparse.h
copyfile.o : ../../include/perrno.h \
../../include/pfs_threads.h \
../../include/pfs_utils.h ../../include/pfs.h ../../include/ardp.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
del_vlink.o : \
../../include/ardp.h ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/pprot.h ../../include/pparse.h \
../../include/perrno.h
elt.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
equal_atrs.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
equal_seq.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
filetoin.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pparse.h
flalloc.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
fl_insert.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/perrno.h
fputbst.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h ../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
get_acl.o : \
../../include/ardp.h ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/pparse.h \
../../include/pprot.h ../../include/perrno.h
in_acl.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pparse.h \
../../include/pprot.h ../../include/perrno.h
in_atrs.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pparse.h \
../../include/perrno.h ../../include/pprot.h
in_filter.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pparse.h \
../../include/pprot.h ../../include/perrno.h
in_forwarded.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pparse.h \
../../include/pprot.h ../../include/perrno.h
in_id.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/perrno.h ../../include/pparse.h \
../../include/pprot.h
in_line.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pparse.h \
../../include/perrno.h
in_link.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pparse.h \
../../include/pprot.h ../../include/perrno.h
in_nextline.o : ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/pparse.h
in_readc.o : ../../include/ardp.h \
../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/pparse.h
in_select.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/perrno.h ../../include/pparse.h \
../../include/pprot.h
in_sequence.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pparse.h
internal_err.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/perrno.h
is_file.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/implicit_fixes.h \
../../include/pmachine.h
length.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
mapname.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/psite.h ../../include/pcompat.h \
../../include/perrno.h
mk_vdir.o : \
../../include/ardp.h ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/pprot.h ../../include/perrno.h ../../include/pparse.h
mkdirs.o : \
../../include/pmachine.h \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/implicit_fixes.h \
../../include/perrno.h
month_sname.o :
modify_acl.o : \
../../include/ardp.h ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/pprot.h ../../include/perrno.h ../../include/pparse.h
myhost.o : ../../include/pcompat.h ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/pmachine.h \
../../include/pfs.h ../../include/ardp.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/implicit_fixes.h
oballoc.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h ../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
obother.o : ../../include/pfs.h ../../include/pfs_utils.h \
../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
opentcp.o : \
../../include/pfs_threads.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/perrno.h ../../include/sockettime.h
out_acl.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pparse.h
out_atr.o : ../../include/pfs.h ../../include/pfs_utils.h \
../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pparse.h \
../../include/pprot.h
out_atrs.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pparse.h
out_filter.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pparse.h
out_link.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pparse.h
out_sequence.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pparse.h \
../../include/pprot.h
p__qbstokenize.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
p__qbstscanf.o : \
../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pparse.h
p__req.o : \
../../include/ardp.h ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/psite.h ../../include/pprot.h ../../include/perrno.h \
../../include/pcompat.h
p_get_dir.o : \
../../include/pprot.h \
../../include/ardp.h ../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/perrno.h ../../include/pparse.h
p_initialize.o : ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/pfs.h ../../include/ardp.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/perrno.h ../../include/pcompat.h
p_uln_index.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
paalloc.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/implicit_fixes.h \
../../include/pmachine.h
penviron.o : \
../../include/pcompat.h ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/pmachine.h \
../../include/pfs.h ../../include/ardp.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/psite.h ../../include/perrno.h
perrmesg.o : ../../include/perrno.h ../../include/pfs_threads.h \
../../include/pfs_utils.h
pfalloc.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h ../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
pfs_debug.o :
pfs_enable.o : ../../include/pcompat.h \
../../include/pfs_threads.h \
../../include/pfs_utils.h ../../include/pmachine.h
pfs_fopen.o : \
../../include/pfs.h ../../include/pfs_utils.h \
../../include/ardp.h ../../include/pfs_threads.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pcompat.h \
../../include/perrno.h
pfs_mutexes.o : ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/pfs.h ../../include/ardp.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
pfs_open.o : \
../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h ../../include/pfs_threads.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pcompat.h \
../../include/perrno.h
pget_am.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/perrno.h
pget_at.o : \
../../include/ardp.h ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/pprot.h ../../include/perrno.h ../../include/pparse.h
pmap_cache.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h ../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pcompat.h \
../../include/psite.h ../../include/perrno.h ../../include/mitra_macros.h
pmap_nfs.o : ../../include/psite.h
pset_at.o : \
../../include/ardp.h ../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/pparse.h \
../../include/pprot.h ../../include/perrno.h
pset_linkat.o : \
../../include/ardp.h ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/pparse.h \
../../include/perrno.h
qbstp_stcopyr.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
qfprintf.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pprot.h
qindex.o : ../../include/pfs.h ../../include/pfs_utils.h \
../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/perrno.h
qoprintf.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pparse.h
qrindex.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
qscanf.o : ../../include/pparse.h \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
qsp_stcopyr.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
qsprintf.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
qsscanf.o : \
../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pparse.h
qtokenize.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pprot.h
rd_vdir.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h ../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/perrno.h
rd_vlink.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/perrno.h
re_comp_exec.o : ../../include/pfs_threads.h \
../../include/pfs_utils.h
readheader.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/implicit_fixes.h \
../../include/pmachine.h
scan_error.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h ../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/perrno.h
sindex.o : \
../../include/pmachine.h \
../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h ../../include/pfs_threads.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/implicit_fixes.h
slashpath.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
slashpath2.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
socket.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/perrno.h ../../include/posix_signal.h \
../../include/sockettime.h
stat.o : \
../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
stcopy.o : \
../../include/ardp.h ../../include/pfs_threads.h ../../include/pfs_utils.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h \
../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h
stequal.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
strccmp.o :
strpbrk.o :
strspn.o :
timetoasn.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
tkalloc.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h ../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/mitra_macros.h
tokeniz_mcmp.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pprot.h
ucase.o :
ul_insert.o : \
../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h ../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/perrno.h
unquote.o : \
../../include/pfs_threads.h ../../include/pfs_utils.h
update_link.o : \
../../include/ardp.h ../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h ../../include/../lib/ardp/flocks.h ../../include/pfs.h \
../../include/pmachine.h \
../../include/implicit_fixes.h \
../../include/pprot.h ../../include/perrno.h
vfsetenv.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/psite.h ../../include/perrno.h
vl_add_atrs.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pparse.h \
../../include/perrno.h
vqfprintf.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pprot.h ../../include/perrno.h
vqscanf.o : \
../../include/pfs_threads.h \
../../include/pfs_utils.h ../../include/pfs.h ../../include/ardp.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pparse.h \
charset.h
vqsprintf.o : ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/pfs_utils.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/pfs.h ../../include/pmachine.h \
../../include/implicit_fixes.h \
charset.h
vl_comp.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h
vl_delete.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/perrno.h
vl_insert.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h ../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/perrno.h
vlalloc.o : \
../../include/pfs.h ../../include/pfs_utils.h ../../include/ardp.h ../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/mitra_macros.h
wcmatch.o : \
../../include/pmachine.h
wholefiltoin.o : ../../include/pfs.h \
../../include/pfs_utils.h ../../include/ardp.h \
../../include/pfs_threads.h \
../../include/list_macros.h \
../../include/../lib/ardp/flocks.h ../../include/implicit_fixes.h \
../../include/pmachine.h \
../../include/pparse.h \
../../include/perrno.h

149
prospero/lib/pfs/acalloc.c Normal file
View File

@@ -0,0 +1,149 @@
/*
* Copyright (c) 1992, 1993, 1994 by the University of Southern California
* For copying and distribution information, please see the file
* <usc-license.h>
*/
/* Munged by swa to handle multiple principals. */
#include <pmachine.h>
#ifdef SOLARIS /* don't know why this was included. */
#include <sys/select.h>
#endif
#include <usc-license.h>
#include <stdio.h>
#include <stdlib.h> /* For malloc */
#include <pfs.h>
static ACL aclflist = NULL;
int acl_count = 0;
int acl_max = 0;
/*
* acalloc - allocate and initialize access control list structure
*
* ACALLOC returns a pointer to an initialized structure of type
* ACL. If it is unable to allocate such a structure, it
* returns NULL.
*/
ACL
acalloc()
{
ACL acl_ent;
p_th_mutex_lock(p_th_mutexACALLOC);
if(aclflist) {
acl_ent = aclflist;
aclflist = aclflist->next;
}
else {
acl_ent = (ACL) malloc(sizeof(ACL_ST));
if (!acl_ent) out_of_memory();
acl_max++;
}
acl_count++;
p_th_mutex_unlock(p_th_mutexACALLOC);
/* Initialize and fill in default values */
#ifdef ALLOCATOR_CONSISTENCY_CHECK
acl_ent->consistency = INUSE_PATTERN;
#endif
acl_ent->acetype = 0;
acl_ent->atype = NULL;
acl_ent->rights = NULL;
acl_ent->principals = NULL;
acl_ent->restrictions = NULL;
acl_ent->app.ptr = NULL; /* On every architecture I ever heard of,
acl_ent->app.flg is now 0 too */
acl_ent->previous = NULL;
acl_ent->next = NULL;
return(acl_ent);
}
static void (*acappfreefunc)(ACL) = NULL;
/*
* Specify which special freeing function (if any) to be used to free the
* app.ptr member of the ACL structure, if set.
*/
void
acappfree(void (* appfreefunc)(ACL))
{
acappfreefunc = appfreefunc;
}
/*
* acfree - free an ACL structure
*
* ACFREE takes a pointer to an ACL structure and adds it to
* the free list for later reuse.
*/
void
acfree(acl_ent)
ACL acl_ent;
{
#ifdef ALLOCATOR_CONSISTENCY_CHECK
assert(acl_ent->consistency == INUSE_PATTERN);
acl_ent->consistency = FREE_PATTERN;
#endif
acl_ent->acetype = 0;
if(acl_ent->atype) stfree(acl_ent->atype);
if(acl_ent->rights) stfree(acl_ent->rights);
if(acl_ent->principals) {
tklfree(acl_ent->principals);
acl_ent->principals = NULL;
}
/* If acl_ent->restrictions, error since not yet implemented */
assert(!acl_ent->restrictions);
if(acappfreefunc && acl_ent->app.ptr) {
(*acappfreefunc)(acl_ent->app.ptr); acl_ent->app.ptr = NULL;
}
p_th_mutex_lock(p_th_mutexACALLOC);
acl_ent->next = aclflist;
if(aclflist) aclflist->previous = acl_ent;
acl_ent->previous = NULL;
aclflist = acl_ent;
acl_count--;
p_th_mutex_unlock(p_th_mutexACALLOC);
}
/*
* aclfree - free an ACL structure
*
* ACLFREE takes a pointer to an ACL structure frees it and any linked
* ACL structures. It is used to free an entrie list of ACL
* structures.
*/
void
aclfree(acl_ent)
ACL acl_ent;
{
ACL nxt;
while(acl_ent != NULL) {
nxt = acl_ent->next;
acfree(acl_ent);
acl_ent = nxt;
}
}
ACL
aclcopy(ACL acl)
{
ACL retval = NULL;
for ( ;acl ; acl = acl->next) {
ACL new = acalloc();
new->acetype = acl->acetype;
if(acl->atype) new->atype = stcopyr(acl->atype,new->atype);
if(acl->rights) new->rights = stcopyr(acl->rights,new->rights);
if(acl->principals) new->principals = tkcopy(acl->principals);
/* If struct restrict ever used, will need to copy that too. */
assert(!acl->restrictions);
APPEND_ITEM(new, retval);
}
return(retval);
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 1991 by the University of Washington
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>.
*/
#include <uw-copyright.h>
#include <usc-copyr.h>
#define NULL 0
char *acltypes[] = {
/* 0 */ "UNINITIALIZED ACL -- You should never see this message.",
/* 1 */ "NONE",
/* 2 */ "DEFAULT",
/* 3 */ "SYSTEM",
/* 4 */ "OWNER",
/* 5 */ "DIRECTORY",
/* 6 */ "CONTAINER",
/* 7 */ "ANY",
/* 8 */ "AUTHENT",
/* 9 */ "LGROUP",
/* 10 */ "GROUP",
/* 11 */ "ASRTHOST",
/* 12 */ "TRSTHOST",
/* 13 */ "IETF-AAC",
/* 14 */ "SUBSCRIPTION",
/* 15 */ "DEFCONT ACL -- You should never see this message.",
/* 16 */ NULL};

View File

@@ -0,0 +1,163 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the files
* <usc-license.h>
*/
#include <usc-copyr.h>
#include <stdio.h> /* declare fprintf() */
#include <string.h> /* SOLARIS doesnt have strings.h */
#include <ardp.h>
#include <pfs.h>
#include <pprot.h>
#include <pparse.h>
#include <perrno.h>
extern int pfs_debug;
/*
*/
int
add_vlink(
const char *direct, /* Virtual name for the directory */
const char *lname, /* Name of the new link */
VLINK l, /* Link to be inserted */
int flags) /* Options for link to add */
{
VLINK dlink; /* Link to remote directory. This points to
memory in the DIR structure; it is
freed when we call vdir_freelinks(dir). */
VDIR_ST dir_st;
VDIR dir = &dir_st;
RREQ req; /* Text of request to dir server. Free before
return. */
int fwdcnt = MAX_FWD_DEPTH;
OUTPUT_ST out_st;
OUTPUT out = &out_st;
INPUT_ST in_st;
INPUT in = &in_st;
PATTRIB ca; /* current attribute */
int tmp;
vdir_init(dir);
/* If magic number has been modified, set it back to 0 */
if(l->f_magic_no < 0) l->f_magic_no = 0;
/* We must first find the directory into which the link */
/* will be inserted */
tmp = rd_vdir(direct,0,dir,RVD_ATTRIB|RVD_DFILE_ONLY);
if (tmp || (dir->links == NULL)) {
vdir_freelinks(dir);
return(DIRSRV_NOT_DIRECTORY);
}
dlink = dir->links;
startover:
req = p__start_req(dlink->host);
requesttoout(req, out);
p__add_req(req,
"DIRECTORY ASCII %'s\nCREATE-LINK '' %c %'s %'s %s %'s %s %'s %d",
dlink->hsoname, ((flags & AVL_INVISIBLE) ? 'I' :
((flags& AVL_UNION) ? 'U' : 'L')),
l->target, lname, l->hosttype,l->host,
l->hsonametype, l->hsoname,l->version);
if (l->dest_exp) {
char *cp = NULL;
p__add_req(req, " DEST-EXP %s",
cp = p_timetoasn_stcopyr(l->dest_exp, cp));
stfree(cp);
}
p__add_req(req, "\n");
if (l->f_magic_no) p__add_req(req, "ID REMOTE %d\n", l->f_magic_no);
for (ca = l->lattrib; ca; ca = ca->next) {
/* Convert attributes of OBJECT precedence to CACHED precedence. */
/* Don't leave the link modified that we passed to this function. */
if (ca->precedence == ATR_PREC_OBJECT) {
ca->precedence = ATR_PREC_CACHED;
out_atr(out, ca, 0);
ca->precedence = ATR_PREC_OBJECT;
} else {
out_atr(out, ca, 0);
}
}
tmp = ardp_send(req,dlink->host,0,ARDP_WAIT_TILL_TO);
if(pfs_debug && tmp) {
fprintf(stderr,"Dirsend failed: %d\n",tmp);
}
if(req->rcvd == NOPKT) {
ardp_rqfree(req);
vdir_freelinks(dir);
return(perrno);
}
/* Here we must parse reponse - While looking at each packet */
rreqtoin(req, in);
while(!in_eof(in)) {
char *line;
char *next_word;
if (tmp = in_line(in, &line, &next_word)) {
ardp_rqfree(req);
vdir_freelinks(dir);
return(tmp);
}
switch (*line) {
case 'F': /* FAILURE or FORWARDED */
/* FORWARDED */
if(strncmp(line,"FORWARDED",9) == 0) {
if(fwdcnt-- <= 0) {
ardp_rqfree(req);
vdir_freelinks(dir);
perrno = PFS_MAX_FWD_DEPTH;
return(perrno);
}
/* parse and start over */
tmp = qsscanf(line,"FORWARDED %*s %'&s %*s %'&s %*d %*d",
&dlink->host, &dlink->hsoname);
if(tmp < 2) {
ardp_rqfree(req);
perrno = DIRSRV_BAD_FORMAT;
break;
}
ardp_rqfree(req);
goto startover;
}
/* If FAILURE or anything else scan error */
goto scanerr;
case 'S': /* SUCCESS */
if(strncmp(line,"SUCCESS",7) == 0) {
ardp_rqfree(req);
vdir_freelinks(dir);
return(PSUCCESS);
}
goto scanerr;
scanerr:
default:
if(*line && (tmp = scan_error(line, req))) {
ardp_rqfree(req);
vdir_freelinks(dir);
return(tmp);
}
break;
}
}
perrno = DIRSRV_BAD_FORMAT;
ardp_rqfree(req);
vdir_freelinks(dir);
return(perrno);
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 1991 by the University of Washington
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>
*/
#include <uw-copyright.h>
#include <time.h>
static month_start[12] = {0, 31, 59, 90, 120, 151,
181, 212, 243, 273, 304, 334};
time_t
asntotime(timestring)
char *timestring;
{
int tmp;
struct tm ts;
long seconds;
int numleap;
tmp = sscanf(timestring,"%4d%2d%2d%2d%2d%2d", &(ts.tm_year),
&(ts.tm_mon), &(ts.tm_mday), &(ts.tm_hour), &(ts.tm_min),
&(ts.tm_sec));
if(tmp != 6) return(0);
ts.tm_mon = ts.tm_mon - 1;
ts.tm_year = ts.tm_year - 1900;
/* The following may not be portable */
seconds = (ts.tm_year - 70) * 365 * 24 * 60 * 60;
seconds = seconds + (month_start[ts.tm_mon] * 24 * 60 * 60);
seconds = seconds + (ts.tm_mday * 24 * 60 * 60);
seconds = seconds + (ts.tm_hour * 60 * 60);
seconds = seconds + (ts.tm_min * 60);
seconds = seconds + ts.tm_sec;
/* Account for leap years (good until 2100) */
numleap = ts.tm_year - 72;
numleap = numleap / 4;
if((ts.tm_mon > 1) && ((ts.tm_year % 4) == 0)) numleap++;
seconds = seconds + (numleap * 24 * 60 * 60);
return(seconds);
}

207
prospero/lib/pfs/atalloc.c Normal file
View File

@@ -0,0 +1,207 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*/
#include <usc-license.h>
#include <stdio.h>
#include <pfs.h>
static PATTRIB lfree = NULL;
int pattrib_count = 0;
int pattrib_max = 0;
/*
* atalloc - allocate and initialize vlink structure
*
* ATALLOC returns a pointer to an initialized structure of type
* PATTRIB. If it is unable to allocate such a structure, it
* returns NULL.
*/
PATTRIB
atalloc(void)
{
PATTRIB at;
p_th_mutex_lock(p_th_mutexATALLOC);
if(lfree) {
at = lfree;
lfree = lfree->next;
} else {
at = (PATTRIB) malloc(sizeof(PATTRIB_ST));
if (!at) out_of_memory();
pattrib_max++;
}
pattrib_count++;
p_th_mutex_unlock(p_th_mutexATALLOC);
#ifdef ALLOCATOR_CONSISTENCY_CHECK
at->consistency = INUSE_PATTERN;
#endif
/* Initialize and fill in default values */
at->precedence = ATR_PREC_OBJECT;
at->nature = ATR_NATURE_UNKNOWN;
at->avtype = ATR_UNKNOWN;
at->aname = NULL;
at->value.sequence = NULL;
at->app.ptr = NULL; /* On every architecture I ever heard of,
at->app.flg is now 0 too */
at->previous = NULL;
at->next = NULL;
return(at);
}
static void (*atappfreefunc)(PATTRIB) = NULL;
/*
* Specify which special freeing function (if any) to be used to free the
* app.ptr member of the PATTRIB structure, if set.
*/
void
atappfree(void (* appfreefunc)(PATTRIB))
{
atappfreefunc = appfreefunc;
}
/*
* atfree - free a PATTRIB structure
*
* ATFREE takes a pointer to a PATTRRIB structure and adds it to
* the free list for later reuse.
*/
void
atfree(PATTRIB at)
{
#ifdef ALLOCATOR_CONSISTENCY_CHECK
assert(at->consistency == INUSE_PATTERN);
at->consistency = FREE_PATTERN;
#endif
if(at->aname) stfree(at->aname);
switch(at->avtype) {
case ATR_UNKNOWN:
break;
case ATR_SEQUENCE:
if (at->value.sequence)
tklfree(at->value.sequence);
break;
case ATR_FILTER:
if(at->value.filter)
flfree(at->value.filter);
break;
case ATR_LINK:
if (at->value.link)
vlfree(at->value.link);
break;
default:
internal_error("Illegal avtype");
}
if(atappfreefunc && at->app.ptr) {
(*atappfreefunc)(at->app.ptr); at->app.ptr = NULL;
}
p_th_mutex_lock(p_th_mutexATALLOC);
at->next = lfree;
at->previous = NULL;
lfree = at;
pattrib_count--;
p_th_mutex_unlock(p_th_mutexATALLOC);
}
/*
* atlfree - free a PATTRIB structure
*
* ATLFREE takes a pointer to a PATTRIB structure frees it and any linked
* PATTRIB structures. It is used to free an entrie list of PATTRIB
* structures.
*/
void
atlfree(PATTRIB at)
{
PATTRIB nxt;
while(at != NULL) {
nxt = at->next;
atfree(at);
at = nxt;
}
}
PATTRIB
atcopy(PATTRIB at)
{
PATTRIB newat;
if (!at) return(at); /* Copying NULL gets NULL */
/* Of course, many callers wont do anything sensible if returned NULL!*/
newat = atalloc();
#ifdef ALLOCATOR_CONSISTENCY_CHECK
assert(at->consistency == INUSE_PATTERN);
#endif
newat->precedence = at->precedence;
newat->nature = at->nature;
newat->avtype = at->avtype;
newat->aname = stcopyr(at->aname, newat->aname);
#ifdef NEVERDEFINED
/* WARNING - this typicaly copies a pointer to a token, leaving two pattrib
pointing into the same token, free-ing one will leave the other
with an invalid (and core-dump-able) pointer - Mitra*/
newat->value = at->value;
#else
switch(at->avtype) {
case ATR_UNKNOWN:
break;
case ATR_SEQUENCE:
if (at->value.sequence)
newat->value.sequence = tkcopy(at->value.sequence);
break;
case ATR_FILTER:
if(at->value.filter)
newat->value.filter = flcopy(at->value.filter,TRUE);
break;
case ATR_LINK:
if (at->value.link)
newat->value.link = vlcopy(at->value.link,TRUE);
break;
default:
internal_error("Illegal avtype");
}
#endif
/* leave previous and next unset. */
return newat;
}
PATTRIB
atlcopy(PATTRIB atl)
{
PATTRIB retval = NULL;
for ( ; atl; atl = atl->next) {
PATTRIB newat = atcopy(atl); /*Note atcopy fixed to copy data */
APPEND_ITEM(newat, retval);
}
return retval;
}
#ifndef NDEBUG
int
at_nlinks(PATTRIB atl)
{
int i;
for (i=0; atl; atl=atl->next) {
if (atl->avtype == ATR_LINK)
i++;
}
return i;
}
#endif /*NDEBUG*/

View File

@@ -0,0 +1,45 @@
/* Build an attribute
Author - Mitra
(Steve - feel free to incorporate as you wish)
*/
#include <pfs.h>
/* Build a PATTRIB, with its list of tokens */
/* Note convention that calling routing passes last arg as (char *)0 */
/* Also note , that passing (char *)1 will force the next argument to
be pointed to, rather than copied (which is what tkappend does) */
/* Return it - this fills in defaults, caller can override */
PATTRIB
vatbuild(char *name, va_list ap)
{
char *s;
PATTRIB at = atalloc();
at->aname = stcopy(name);
/* If any of these arent reasonable defaults move up to callers */
at->avtype = ATR_SEQUENCE;
if (strequal(name, "ACCESS-METHOD"))
at->nature = ATR_NATURE_FIELD;
else if strequal(name,"CONTENTS")
at->nature = ATR_NATURE_INTRINSIC;
else
at->nature = ATR_NATURE_APPLICATION;
at->precedence = ATR_PREC_OBJECT;
while(s = va_arg(ap, char *)) {
if (s == (char *) 1) {
at->value.sequence =
tkappend(NULL,at->value.sequence);
s = va_arg(ap, char *);
at->value.sequence->previous->token = s;
} else
at->value.sequence =
tkappend(s, at->value.sequence);
}
return(at);
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file <usc-copyr.h>
*/
/* This file will probably go away after we define REALLY_NEW_FIELD
*/
#include <usc-copyr.h>
/* Written by swa@ISI.EDU, Sept. 21--24, 1992 */
#include <pfs.h>
#include <pprot.h>
#include <pparse.h>
static struct atr_type_by_field_name {
char *name;
char type;
} atr_type_by_field_name[] = {
/* Not all fields are defined here yet. */
"ACCESS-METHOD", ATR_SEQUENCE,
"BASE-TYPE", ATR_SEQUENCE,
"CLOSURE", ATR_LINK,
"DEST-EXP", ATR_SEQUENCE,
"FILTER", ATR_FILTER,
"HOST", ATR_SEQUENCE,
"HOST-TYPE", ATR_SEQUENCE,
"HSONAME", ATR_SEQUENCE,
"HSONAME-TYPE", ATR_SEQUENCE,
"ID", ATR_SEQUENCE,
"LINK-TYPE", ATR_SEQUENCE,
"NAME-COMPONENT", ATR_SEQUENCE,
"OWNER", ATR_SEQUENCE,
"TARGET", ATR_SEQUENCE,
"TTL", ATR_SEQUENCE,
"VERSION", ATR_SEQUENCE,
NULL, ATR_UNKNOWN
};
static struct atr_type_by_type_name {
char *name;
char type;
} atr_type_by_type_name[] = {
"FILTER", ATR_FILTER,
"LINK", ATR_LINK,
"SEQUENCE", ATR_SEQUENCE,
"ASCII", ATR_SEQUENCE, /* XXX Backwards compatability; will go away
soon. */
NULL, ATR_UNKNOWN
};
/* used by atr_in. */
int
lookup_avtype_by_field_name(const char aname[])
{
struct atr_type_by_field_name *p;
for (p = atr_type_by_field_name; p->name; ++p)
if (strequal(p->name, aname))
return p->type;
return ATR_UNKNOWN;
}
/* If you add elements to this table, you will also need to change pfs.h */
int
lookup_avtype_by_avtypename(const char t_avtype[])
{
struct atr_type_by_type_name *p;
for (p = atr_type_by_type_name; p->name; ++p)
if (strequal(p->name, t_avtype))
return p->type;
return ATR_UNKNOWN;
}
char *
lookup_avtypename_by_avtype(int avtype)
{
struct atr_type_by_type_name *p;
for (p = atr_type_by_type_name; p->name; ++p)
if (p->type == avtype)
return p->name;
return "UNKNOWN-TYPE-NAME-PLEASE-COMPLAIN-TO-THE-MAINTAINER";
}
/* If you add elements to this table, you will also need to change pfs.h */
static struct aban {
char *name;
char precedence;
} precedence_by_precedencename[] = {
"OBJECT", ATR_PREC_OBJECT,
"LINK", ATR_PREC_LINK,
"CACHED", ATR_PREC_CACHED,
"REPLACEMENT", ATR_PREC_REPLACE,
"ADDITIONAL", ATR_PREC_ADD,
NULL, ATR_PREC_UNKNOWN
};
int
lookup_precedence_by_precedencename(const char t_precedence[])
{
struct aban *p;
for (p = precedence_by_precedencename; p->name; ++p)
if (strequal(p->name, t_precedence))
return p->precedence;
return ATR_UNKNOWN;
}
char *
lookup_precedencename_by_precedence(int precedence)
{
struct aban *p;
for (p = precedence_by_precedencename; p->name; ++p)
if (p->precedence == precedence)
return p->name;
return "UNKNOWN-APPLIES-TO-VALUE-PLEASE-COMPLAIN-TO-THE-MAINTAINER";
}

View File

@@ -0,0 +1,81 @@
/* bindecode.c
Author: Steven Augart <swa@isi.edu>
Written: 8/17/92
I am really interested in comments on this code, suggestions for making it
faster, and criticism of my style. Please send polite suggestions for
improvement to swa@isi.edu.
*/
/* Copyright (c) 1992 by the University of Southern California. */
/* For copying and distribution information, see the file <usc-copyr.h> */
#include <usc-copyr.h>
/*
bindecode() takes a char* (INBUF) that represents a null-terminated string
containing a NUL-less representation of binary data, produced by
binencode(). bindecode() converts the contents of INBUF to a pure binary
representation, and saves it in OUTBUF. OUTBUFSIZE is the size of OUTBUF.
bindecode() returns the # of characters it wrote to OUTBUF, or the # of
characters it would have written if there had been enough room. Note that no
terminating NUL is added to the string.
bindecode() will write partial strings to buffers which are not long enough.
This seems to be reasonable behavior to me.
To check for error returns, all is OK if bindecode's return value is less
than OUTBUFSIZE. Otherwise, you need to either allocate a bigger outbuf, or
give up. (This is consistent with the return values for qsprintf() and
binencode().)
*/
#ifdef __STDC__
#include <stddef.h>
int
bindecode(char *inbuf, char *outbuf, size_t outbufsize)
#else
int
bindecode(inbuf, outbuf, outbufsize)
char *inbuf, *outbuf;
int outbufsize;
#endif
{
int outcount = 0; /* how many characters did we output? */
#define rawput(c) do { \
++outcount; \
if (outbufsize > 0) { \
--outbufsize; \
*outbuf++ = (c); \
} \
} while (0)
for (; *inbuf; ++inbuf) {
if (*inbuf == '\\') {
++inbuf;
if (*inbuf == '0')
rawput('\0');
else if (*inbuf == '\\')
rawput('\\');
else if (*inbuf == 's')
rawput(' ');
else if (*inbuf == 't')
rawput('\t');
else if (*inbuf == 'v')
rawput('\v');
else if (*inbuf == 'f')
rawput('\f');
else if (*inbuf == 'r')
rawput('\r');
else if (*inbuf == 'n')
rawput('\n');
else
return -1; /* format error */
} else {
rawput(*inbuf);
}
}
return outcount;
}

View File

@@ -0,0 +1,91 @@
/* binencode.c
Author: Steven Augart <swa@isi.edu>
Written: 8/17/92
I am really interested in comments on this code, suggestions for making it
faster, and criticism of my style. Please send polite suggestions for
improvement to swa@isi.edu.
*/
/* Copyright (c) 1992 by the University of Southern California. */
/* For copying and distribution information, see the file <usc-copyr.h> */
#include <usc-copyr.h>
/*
binencode() takes a char* (INBUF) and a size count (INBUFSIZE) as its first
two arguments. INBUF is assumed to be an array of INBUFSIZE chars containing
binary data. binencode() converts the contents of INBUF to a
printing-character representation, and saves it in OUTBUF. OUTBUFSIZE is the
size of OUTBUF.
binencode() returns the # of characters it wrote to the string, or the # of
characters it would have written if there had been enough room. Its return
value INCLUDES the NUL ('\0'). Binencode() takes the SIZE of the buffer it
writes to as an argument. This allows us to guard against buffer overflow.
binencode() will write partial strings to buffers which are not long enough.
This seems to be reasonable behavior to me.
To check for error returns, all is OK if binencode's return value is less than
OUTBUFSIZE. Otherwise, you need to either allocate a bigger outbuf, or give
up. (This is consistent with the return values for qsprintf() and
bindecode().)
This string can be converted back with bindecode().
This string does NOT need to be quoted using qsprintf and qsscanf; it
escapes the NUL, backslash, newline, and horizontal whitespace.
*/
#ifdef __STDC__
#include <stddef.h>
int
binencode(char *inbuf, size_t inbufsize, char *outbuf, size_t outbufsize)
#else
int
binencode(inbuf, inbufsize, outbuf, outbufsize)
char *inbuf, *outbuf;
int inbufsize, outbufsize;
#endif
{
int outcount = 0; /* how many characters did we output? */
#define rawput(c) do { \
++outcount; \
if (outbufsize > 0) { \
--outbufsize; \
*outbuf++ = (c); \
} \
} while (0)
for (; inbufsize > 0; ++inbuf, --inbufsize) {
if (*inbuf == '\0') {
rawput('\\');
rawput('0');
} else if (*inbuf == '\\') {
rawput('\\');
rawput('\\');
} else if (*inbuf == ' ') {
rawput('\\');
rawput('s');
} else if (*inbuf == '\t') {
rawput('\\');
rawput('t');
} else if (*inbuf == '\v') {
rawput('\\');
rawput('v');
} else if (*inbuf == '\r') {
rawput('\\');
rawput('r');
} else if (*inbuf == '\f') {
rawput('\\');
rawput('f');
} else if (*inbuf == '\n') {
rawput('\\');
rawput('n');
} else {
rawput(*inbuf);
}
}
rawput('\0');
return outcount;
}

View File

@@ -0,0 +1,28 @@
/* charset.h */
/* Written by Steven Augart <swa@isi.edu> July, 1992 */
/* This implements a simple character set recognizer. */
/* It is used by qsprintf.c and qsscanf.c */
/* must include limits.h to use this. */
#include <limits.h>
/* These macros define an abstraction for a set of characters where one can add
members, remove them, and test for membership. There are several ways in
which this might be made more efficient, but I'm tired. */
#include <string.h> /* This should include a definition of
memset(), but the one on our system doesn't
have it, so I have to define memset below.
*/
extern void *memset(void *, int, size_t);
typedef char charset[UCHAR_MAX + 1]; /* what we'll work on */
#define new_full_charset(cs) do { memset((cs), 1, sizeof (cs)); \
/* cs['\0'] = 0; */} while (0)
#define new_empty_charset(cs) memset((cs), 0, sizeof (cs))
#define add_char(cs, c) do { \
assert(c != EOF); \
((cs)[(unsigned char) (c)] = 1); \
} while (0)
#define remove_char(cs, c) ((cs)[(unsigned char) (c)] = 0)
#define in_charset(cs,c) (((c) != EOF) && (cs)[(unsigned char) (c)])

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the file <usc-copyr.h>
*/
#include <usc-copyr.h>
#include <ardp.h>
#include <pfs.h>
#include <pparse.h>
int
cl_qoprintf(OUTPUT out, const char fmt[], ...)
{
va_list ap;
va_start(ap, fmt);
assert(! out->req && out->request);
return vp__add_req(out->request, fmt, ap);
}
int
requesttoout(RREQ req, OUTPUT out)
{
out->request = req;
out->req = NULL;
out->f = NULL;
return PSUCCESS;
}

View File

@@ -0,0 +1,79 @@
#include <errno.h>
#include <perrno.h>
#include <pfs.h>
#include <stdio.h> /* FILE, fopen etc */
int
copyFile(char *source,char *destn)
{
/* This code is adapted from user/vget:copy_file, but errors are now
not put on standard out, and it doesnt use "goto" */
char buf[1024];
int numread,numwritten;
FILE *in, *out;
if ((in = fopen(source, "r")) == NULL) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Couldn't open the file %s for reading. Copy failed.\n",
source);
RETURNPFAILURE;
}
if ((out = fopen(destn, "w")) == NULL) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Couldn't open the file %s for writing. Copy failed.\n",
destn);
fclose(in);
RETURNPFAILURE;
}
while ((numread = fread(buf, 1, sizeof buf, in)) >0 ) {
numwritten = fwrite(buf, 1, numread, out);
if (numwritten != numread) {
p_err_string = qsprintf_stcopyr(p_err_string,
"tried to write %d items to %s; only wrote %d. Copying aborted.\n",
numread, destn, numwritten);
fclose(in);
fclose(out);
RETURNPFAILURE;
}
}
if (ferror(in)) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Error while reading from %s; copying to %s aborted\n",
source, destn);
fclose(in);
fclose(out);
RETURNPFAILURE;
} else {
/* done! */
fclose(in);
fclose(out);
return PSUCCESS;
}
}
#include <errno.h>
int
renameOrCopyAndDelete(char *source, char *destn)
{
int retval;
if (!(rename(source,destn)))
return 0;
switch (errno) {
case EXDEV:
if (retval = copyFile(source,destn))
return retval; /* Couldnt copy , p_err_string set*/
if(retval = unlink(source)) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Couldnt unlink %s: %s",source, unixerrstr());
}
return(retval); /* success or failure */
default: {
p_err_string = qsprintf_stcopyr(p_err_string,
"Couldnt rename %s to %s: %s",
source,destn, unixerrstr());
return -1; /* Failed to rename for another reason*/
}
}
}

View File

@@ -0,0 +1,143 @@
/*
* Copyright (c) 1989, 1990 by the University of Washington
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>.
*
* Written by bcn 1989 modified 1989-1992
* Modified by swa 1992 to use startreq
* Modified by bcn 1/93 to use ardp library
*/
#include <uw-copyright.h>
#include <usc-copyr.h>
#include <stdio.h>
#include <string.h>
#include <ardp.h>
#include <pfs.h>
#include <pprot.h>
#include <pparse.h>
#include <perrno.h>
#include <pmachine.h>
extern int pfs_debug;
int
del_vlink(vpath,flags)
const char *vpath; /* Name of link to be deleted */
int flags; /* Options for directory */
{
char *dirhst; /* Host of current directory */
char *remdir; /* Dir on remote host */
char *cname = ""; /* Component name */
char *pname = ""; /* Parent name */
char pathcpy[MAX_VPATH];
int fwdcnt = MAX_FWD_DEPTH;
char fwdhst[MAX_DIR_LINESIZE];
char fwdfnm[MAX_DIR_LINESIZE];
RREQ req; /* Text of request to dir server */
VDIR_ST dir_st;
VDIR dir = &dir_st;
INPUT_ST in_st;
INPUT in = &in_st;
int tmp;
vdir_init(dir);
strcpy(pathcpy,vpath);
cname = p_uln_rindex(pathcpy,'/');
if(!cname) cname = pathcpy;
else {
*cname++ = '\0';
pname = pathcpy;
if(cname == (pname + 1)) pname = "/";
}
/* We must first find the directory from which the link */
/* will be deleted */
tmp = rd_vdir(pname,0,dir,RVD_DFILE_ONLY);
if (tmp || (dir->links == NULL)) return(DIRSRV_NOT_DIRECTORY);
dirhst = dir->links->host;
remdir = dir->links->hsoname;
startover:
req = p__start_req(dirhst);
p__add_req(req, "DIRECTORY ASCII %'s\nDELETE-LINK '' %'s\n",
remdir, cname);
tmp = ardp_send(req,dirhst,0,ARDP_WAIT_TILL_TO);
if(pfs_debug && tmp) {
fprintf(stderr,"ARDP_send failed: %d\n",tmp);
}
if(req->rcvd == NOPKT) return(perrno);
/* Here we must parse reponse - While looking at each packet */
rreqtoin(req, in);
while(!in_eof(in)) {
char *line;
char *next_word;
if (tmp = in_line(in, &line, &next_word)) {
ardp_rqfree(req);
return(tmp);
}
switch (*line) {
case 'F': /* FAILURE or FORWARDED */
/* FORWARDED */
if(strncmp(line,"FORWARDED",9) == 0) {
if(fwdcnt-- <= 0) {
ardp_rqfree(req);
perrno = PFS_MAX_FWD_DEPTH;
return(perrno);
}
/* parse and start over */
tmp = sscanf(line,"FORWARDED %*s %s %*s %s %*d %*d",
fwdhst,fwdfnm);
dirhst = stcopy(fwdhst);
remdir = stcopy(fwdfnm);
if(tmp < 2) {
ardp_rqfree(req);
perrno = DIRSRV_BAD_FORMAT;
break;
}
ardp_rqfree(req);
goto startover;
}
/* If FAILURE or anything else scan error */
goto scanerr;
case 'S': /* SUCCESS */
if(strncmp(line,"SUCCESS",7) == 0) {
ardp_rqfree(req);
return(PSUCCESS);
}
goto scanerr;
scanerr:
default:
if(*line && (tmp = scan_error(line, req))) {
ardp_rqfree(req);
return(tmp);
}
break;
}
}
perrno = DIRSRV_BAD_FORMAT;
ardp_rqfree(req);
return(perrno);
}

28
prospero/lib/pfs/elt.c Normal file
View File

@@ -0,0 +1,28 @@
/*
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the file <usc-copyr.h>
*/
/* Author: Steven Augart, swa@isi.edu */
#include <usc-copyr.h>
#include <stdio.h>
#include <pfs.h>
extern int pfs_debug;
/* Return the NTH element of a sequence S. Indexing starts at zero. Works
just like the Common LISP ELT function. */
char *
elt(TOKEN s, int nth)
{
if (nth < 0) {
if (pfs_debug)
fprintf(stderr, "elt() called with illegal negative index %d\n",
nth);
return NULL;
}
for (; s && nth > 0; s = s->next, --nth)
;
return s ? s->token : NULL;
}

View File

@@ -0,0 +1,55 @@
/* Copyright (c) 1992, 1993 by the University of Southern California.
* For copying and distribution information, please see the file
* <usc-copyr.h>.
*/
#include <usc-copyr.h>
#include <pfs.h>
/* This function is used by edit_link_info() and edit_object_info() in the
server to determine whether two attributes are the same. It will eventually
also be used for merging attributes in VLS and other clients.
*/
int
equal_attributes(PATTRIB a1, PATTRIB a2)
{
if (a1->precedence != a2->precedence
|| a1->nature != a2->nature
|| a1->avtype != a2->avtype
|| !strequal(a1->aname, a2->aname))
return FALSE;
switch(a1->avtype) {
case ATR_SEQUENCE:
return equal_sequences(a1->value.sequence,
a2->value.sequence);
case ATR_FILTER:
return equal_filters(a1->value.filter, a2->value.filter);
case ATR_LINK:
return vl_equal(a1->value.link, a2->value.link);
default:
internal_error("Invalid attribute type!");
/*NOTREACHED */
}
/* NOTREACHED */
assert(0);
return(-1); /*Keep gcc happy*/
}
int
equal_filters(FILTER f1, FILTER f2)
{
if (f1->name && f2->name) { /* Both PREDEFINED */
if (!strequal(f1->name, f2->name))
return FALSE;
} else if (f1->link && f2->link) { /* both LOADABLE */
if (!vl_equal(f1->link, f2->link))
return FALSE;
} else { /* One PREDEFINED, other LOADABLE */
return FALSE;
}
return (f1->type == f2->type
&& f1->execution_location == f2->execution_location
&& f1->pre_or_post == f2->pre_or_post
&& equal_sequences(f1->args, f2->args));
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the file <usc-copyr.h>
*/
#include <usc-copyr.h>
/* Written by swa@ISI.EDU, Sept. 24, 1992 */
/* This is used by equal_attributes(), and probably not by much else. */
/* Compare two token lists. Return nonzero value if they match; zero if
they don't. */
#include <pfs.h>
int
equal_sequences(t1, t2)
TOKEN t1, t2;
{
for (;;t1 = t1->next, t2 = t2->next) {
if (t1 == t2) /* Handles the case where both are NULL */
return TRUE;
if (!t1 || !t2) /* handles the case where one is null and the
other is not. */
return FALSE;
if (!strequal(t1->token, t2->token))
return FALSE;
}
/* NOTREACHED */
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file <usc-copyr.h>
*/
#include <usc-copyr.h>
#include <pfs.h>
#include <pparse.h>
#ifndef FILE
#include <stdio.h>
#endif
void
filetoin(FILE *f, INPUT in)
{
in->sourcetype = IO_FILE;
in->rreq = NULL;
in->inpkt = NULL;
in->ptext_ioptr = NULL;
in->s = NULL;
in->file = f;
in->offset = ftell(f);
in->flags = JUST_INITIALIZED | SERVER_DATA_FILE;
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 1989, 1990 by the University of Washington
*
* For copying and distribution information, please see the file
* <uw-copyright.h>.
*/
#include <uw-copyright.h>
#include <stdio.h>
#include <pfs.h>
#include <perrno.h>
/*
* fl_insert - Add a filter to a link
*
* FL_INSERT takes a filter, and a link that is to receive
* the filter. The filter is then appended to the linked list
* of filters associated with the link.
*
* ARGS: fil - Filter to be inserted, lin - Link to get filter
*
* RETURNS: PSUCCESS - always
*/
int
fl_insert(fil,lin)
#if 0
VLINK fil; /* Filter to be inserted */
#endif
FILTER fil;
VLINK lin; /* Link to receive filter */
{
APPEND_ITEM(fil, lin->filters);
#if 0
VLINK current; /* To step through list */
/* If this is the first filter in the link */
if(lin->filters == NULL) {
lin->filters = fil;
fil->previous = NULL;
fil->next = NULL;
return(PSUCCESS);
}
/* Otherwise, find the last filter */
current = lin->filters;
while(current->next) current = current->next;
/* insert the new filter */
current->next = fil;
fil->next = NULL;
fil->previous = current;
#endif
return(PSUCCESS);
}

182
prospero/lib/pfs/flalloc.c Normal file
View File

@@ -0,0 +1,182 @@
/*
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*/
#include <usc-copyr.h>
#include <stdio.h>
#include <stdlib.h> /* For malloc and free */
#include <pfs.h>
static FILTER lfree = NULL;
/* These are global variables which will be read by dirsrv.c
Too bad C doesn't have better methods for structuring such global data. */
int filter_count = 0;
int filter_max = 0;
/*
* flalloc - allocate and initialize FILTER structure
*
* FLALLOC returns a pointer to an initialized structure of type
* FILTER. If it is unable to allocate such a structure, it
* signals out_of_memory();
*/
FILTER
flalloc()
{
FILTER fil;
p_th_mutex_lock(p_th_mutexFLALLOC);
if(lfree) {
fil = lfree;
lfree = lfree->next;
}
else {
fil = (FILTER) malloc(sizeof(FILTER_ST));
if (!fil) out_of_memory();
filter_max++;
}
filter_count++;
p_th_mutex_unlock(p_th_mutexFLALLOC);
/* Initialize and fill in default values */
#ifdef ALLOCATOR_CONSISTENCY_CHECK
fil->consistency = INUSE_PATTERN;
#endif
fil->name = NULL;
fil->link = NULL;
fil->type = 0; /* Illegal value */
fil->execution_location = 0; /* Neither -- illegal value. */
fil->pre_or_post = 0; /* Neither -- illegal value */
fil->args = NULL;
fil->errmesg = NULL; /* error message from filter application, if
any. */
fil->app.ptr = NULL; /* On every architecture I ever heard of,
fil->app.flg is now 0 too */
fil->previous = NULL;
fil->next = NULL;
return(fil);
}
static void (*flappfreefunc)(FILTER) = NULL;
/*
* Specify which special freeing function (if any) to be used to free the
* app.ptr member of the FILTER structure, if set.
*/
void
flappfree(void (* appfreefunc)(FILTER))
{
flappfreefunc = appfreefunc;
}
/*
* flfree - free a FILTER structure
*
* FLFREE takes a pointer to a FILTER structure and adds it to
* the free list for later reuse.
*/
void
flfree(FILTER fil)
{
#ifdef ALLOCATOR_CONSISTENCY_CHECK
assert(fil->consistency == INUSE_PATTERN);
fil->consistency = FREE_PATTERN;
#endif
if(fil->name) stfree(fil->name);
if(fil->link) vlfree(fil->link);
if(fil->args) tklfree(fil->args);
if (fil->errmesg) stfree(fil->errmesg);
if(flappfreefunc && fil->app.ptr) {
(*flappfreefunc)(fil->app.ptr); fil->app.ptr = NULL;
}
p_th_mutex_lock(p_th_mutexFLALLOC);
fil->next = lfree;
fil->previous = NULL;
lfree = fil;
filter_count--;
p_th_mutex_unlock(p_th_mutexFLALLOC);
}
/*
* fllfree - free a linked list of FILTER structures.
*
* FLLFREE takes a pointer to a FILTER structure frees it and any linked
* FILTER structures. It is used to free an entrie list of FILTER
* structures.
*/
void
fllfree(fil)
FILTER fil;
{
FILTER nxt;
while((fil != NULL) /* && !fil->dontfree */) {
nxt = fil->next;
flfree(fil);
fil = nxt;
}
}
/*
* flcopy - allocates a new filter structure and
* initializes it with a copy of another
* filter, v.
*
* If r is non-zero, successive filters will be
* iteratively copied.
*
* fl-previous will always be null on the first link, and
* will be appropriately filled in for iteratively copied links.
*
* FLCOPY returns a pointer to the new structure of type
* FILTER. If it is unable to allocate such a structure, it
* returns NULL.
*
* FLCOPY will recursively copy the link associated with a filter and
* its associated attributes.
*/
FILTER
flcopy(FILTER f, int r)
{
FILTER nf;
FILTER snf; /* Start of the chain of new links */
FILTER tf; /* Temporary link pointer */
if (!f) return NULL; /* If called with NULL return it */
nf = flalloc();
snf = nf;
copyeach:
/* Copy f into nf */
#ifdef ALLOCATOR_CONSISTENCY_CHECK
assert(f->consistency == INUSE_PATTERN);
#endif
if(f->name) nf->name = stcopyr(f->name,nf->name);
if(f->link) nf->link = vlcopy(f->link, 1);
nf->type = f->type;
nf->execution_location = f->execution_location;
nf->pre_or_post = f->pre_or_post;
nf->args = tkcopy(f->args);
f->errmesg = stcopy(f->errmesg);
if(r && f->next) {
f = f->next;
tf = nf;
nf = flalloc();
nf->previous = tf;
tf->next = nf;
goto copyeach;
}
return(snf);
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright (c) 1993 by the University of Southern Calfornia
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
#include <stdio.h>
#include <pfs.h> /* for prototypes */
/* Return non-zero if string ends in a newline. */
/* Like fputs, but for bstrings. */
int
p__fputbst(const char *bst, FILE *out)
{
int len = p_bstlen(bst);
int need_newline = 0;
while (len-- > 0) {
need_newline = (*bst != '\n'); /* Does the bstring end in a newline? */
putc(*bst++, out);
}
return need_newline;
}

192
prospero/lib/pfs/get_acl.c Normal file
View File

@@ -0,0 +1,192 @@
/*
* Copyright (c) 1991 by the University of Washington
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>.
*/
#include <uw-copyright.h>
#include <usc-copyr.h>
#include <stdio.h>
#include <string.h>
#include <ardp.h>
#include <pfs.h>
#include <pparse.h>
#include <pprot.h>
#include <perrno.h>
extern int pfs_debug;
/* lname is specified if we want the ACL for a link within a directory.
It is left out when requesting the ACL for the directory itself. */
/* XXX To be done: add an ID field. */
#define LIST_ACL_SEND_OLDSTYLE_OBJECT_AND_CONTAINER /* until Alpha.5.2 servers
are gone. */
#define SEND_DIRECTORY_NOT_OBJECT /* Until Alpha.5.2 and before servers all
gone. */
ACL
get_acl(VLINK dlink,
const char *lname,
/* Note that 'directory' and 'object' flags will soon be the same. */
int flags /* 0 = directory, 1 = link, 2 = object, 3 = included/named,
4 = container 5 = named*/)
{
RREQ req; /* Text of request to dir server */
ACL retval = NULL; /* ACLs being returned */
ACL ap; /* Temporary acl pointer */
char *options = ""; /* List of options */
int fwdcnt = MAX_FWD_DEPTH;
char fwdhst[MAX_DIR_LINESIZE];
char fwdfnm[MAX_DIR_LINESIZE];
INPUT_ST in_st;
INPUT in = &in_st;
char *next_line;
int tmp;
if(flags == 0) {
options = "DIRECTORY";
/* no link name should be specified with the directory option. */
if (lname && *lname) return NULL;
}
/* If for a link, or an included ACL */
else if ((flags == 1) || (flags == 3) || (flags == 5)) {
/* link name must be specified with this option */
if (!lname || !*lname)
return NULL;
if (flags == 1) options = "LINK";
else if (flags == 3) options = "INCLUDE";
else if (flags == 5) options = "NAMED";
}
else if (flags == 2) {
options = "OBJECT";
if (lname && *lname) return NULL;
}
else if (flags == 4) {
options = "CONTAINER";
if (lname && *lname) return NULL;
}
if(lname == NULL) lname = "";
if(strcmp(dlink->target,"NULL") == 0) return(NULL);
if(strcmp(dlink->target,"EXTERNAL") == 0) return(NULL);
startover:
req = p__start_req(dlink->host);
if ((flags == 0) || (flags == 1)) {
#ifdef SEND_DIRECTORY_NOT_OBJECT
p__add_req(req, "DIRECTORY %'s %'s\n", dlink->hsonametype,
dlink->hsoname);
#else
p__add_req(req, "OBJECT %'s %'s\n", dlink->hsonametype,
dlink->hsoname);
#endif
}
#ifdef LIST_ACL_SEND_OLDSTYLE_OBJECT_AND_CONTAINER
if ((flags == 0) || (flags == 1) || (flags == 3) || (flags == 5)) {
p__add_req(req, "LIST-ACL %s", options);
if(*lname) p__add_req(req, " %'s", lname);
p__add_req(req, "\n");
}
if ((flags == 2) || (flags == 4)) {
p__add_req(req, "LIST-ACL %s %s\n", options, dlink->hsoname);
}
#else
if (flags == 2 || flags == 4) {
p__add_req(req, "OBJECT %'s %'s\n", dlink->hsonametype,
dlink->hsoname);
p__add_req(req, "LIST-ACL %'s\n", options);
}
if ((flags == 0) || (flags == 1) || (flags == 3) || (flags == 5)) {
p__add_req(req, "LIST-ACL %s", options);
if(*lname) p__add_req(req, " %'s", lname);
p__add_req(req, "\n");
}
#endif
perrno = 0;
tmp = ardp_send(req,dlink->host,0,ARDP_WAIT_TILL_TO);
if(pfs_debug && tmp) {
fprintf(stderr,"get_acl(): Dirsend failed: %d\n",tmp);
perrno = tmp;
}
/* If we don't get a response, then return error */
if(req->rcvd == NULL) return(NULL);
rreqtoin(req, in);
/* Here we must parse reponse */
/* While looking at each packet */
while (in_nextline(in)) {
char *line, *next_word;
if(tmp = in_line(in, &line, &next_word)) {
aclfree(retval);
perrno = tmp;
return NULL;
}
switch (*line) {
/* Temporary variables to info */
/* There is already a variable "tmp" in this function*/
int tmp1;
case 'A': /* ACL */
if(!strnequal(line,"ACL",3)) goto scanerr;
if (retval) {/* if already saw ACL lines */
perrno = DIRSRV_BAD_FORMAT;
aclfree(retval);
return NULL;
}
if(in_ge1_acl(in, line, next_word, &retval)) {
aclfree(retval);
return NULL;
}
break;
case 'F':/* FORWARDED */
if(strncmp(line,"FORWARDED",9) == 0) {
if(fwdcnt-- <= 0) {
ardp_rqfree(req);
perrno = PFS_MAX_FWD_DEPTH;
return(NULL);
}
/* parse and start over */
tmp1 = qsscanf(line,"FORWARDED %'&s %'&s %'&s %'&s %ld %ld",
&dlink->hosttype, &dlink->host,
&dlink->hsonametype, &dlink->hsoname,
&dlink->version, &dlink->f_magic_no);
if(tmp1 < 2) {
perrno = DIRSRV_BAD_FORMAT;
break;
}
ardp_rqfree(req);
goto startover;
}
/* If FAILURE or other, then scan error */
goto scanerr;
scanerr:
default:
if(tmp1 = scan_error(line, req)) {
ardp_rqfree(req);
return(NULL);
}
break;
} /* switch() */
} /* while (in_nextline(in)) */
ardp_rqfree(req);
return(retval);
}

129
prospero/lib/pfs/in_acl.c Normal file
View File

@@ -0,0 +1,129 @@
/*
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the file <usc-copyr.h>
*/
#include <usc-copyr.h>
#include <pfs.h>
#include <pparse.h>
#include <pprot.h>
#include <perrno.h>
static int
in_acl_data(INPUT in, char *command, char *next_word, ACL value);
int in_ge1_acl(INPUT in, char *command, char *next_word, ACL *aclp)
{
ACL nacl = acalloc();
int retval;
if (!nacl) out_of_memory();
if(retval = in_acl_data(in, command, next_word, nacl)) {
acfree(nacl);
return perrno = retval;
}
if(retval = in_acl(in, &nacl->next)) {
acfree(nacl);
return perrno = retval;
}
/* now need to correct the doubly-linked list. */
if (nacl->next) {
nacl->previous = nacl->next->previous;
nacl->next->previous = nacl;
}
*aclp = nacl;
return PSUCCESS;
}
/* This function is called with in_nextline() referring to the first line that
might contain ACL data. It sets perrno and p_err_string if bad data is
found, and ALSO returns an error code. */
/* Reads in a string of ACL lines. */
int
in_acl(INPUT in, ACL *aclp)
{
ACL list = NULL; /* head of a linked list of new acls. */
char *command, *next_word;
while(in_nextline(in) && strnequal(in_nextline(in), "ACL", 3)) {
ACL nacl = acalloc();
int retval; /* return code from function calls. */
if (!nacl) {
aclfree(list);
out_of_memory();
}
APPEND_ITEM(nacl, list);
if(retval = in_line(in, &command, &next_word)) {
aclfree(list);
return perrno = retval;
}
if(retval = in_acl_data(in, command, next_word, nacl)) {
aclfree(list);
return perrno = retval;
}
/* We just safely read in the rest of the line. */
/* Read in additional lines to skip over any RESTRICTION lines. */
while (in_nextline(in)
&& strnequal(in_nextline(in), "RESTRICTION ", 12)) {
extern int p__server;
if(retval = in_line(in, &command, &next_word)) {
aclfree(list);
return perrno = retval;
}
if (p__server) {
aclfree(list);
p_err_string = qsprintf_stcopyr(p_err_string,
"UNIMPLEMENTED This server cannot handle RESTRICTIONS \
yet: %s", command);
return perrno = retval;
} else {
pwarn = PWARNING;
p_warn_string = qsprintf_stcopyr(p_warn_string,
"The server sent an ACL with a RESTRICTION, but we \
don't know what it means: %s", command);
/* just go on; it's only a warning. */
}
}
}
*aclp = list; /* safe & done. */
return PSUCCESS;
}
static int
in_acl_data(INPUT in, char *command, char *next_word, ACL value)
{
AUTOSTAT_CHARPP(t_acetypep);
AUTOSTAT_CHARPP(t_atypep);
AUTOSTAT_CHARPP(t_rightsp);
char *p_principals;
extern char *acltypes[];
p_principals = NULL;
if(qsscanf(next_word, "%'&s %'&s %'&s %r",
&*t_acetypep, &*t_atypep, &*t_rightsp, &p_principals) < 3) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Malformed ACL line: %'s", command);
return PARSE_ERROR;
}
for(value->acetype = 0;acltypes[value->acetype];
(value->acetype)++) {
if(strequal(acltypes[value->acetype],*t_acetypep))
break;
}
if(acltypes[value->acetype] == NULL) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Unknown ACL type: %'s", command);
return PARSE_ERROR;
}
/* We stcopy() twice; this is not necessary. */
value->atype = stcopyr((**t_atypep ? *t_atypep : NULL), value->atype);
value->rights = stcopyr((**t_rightsp ? *t_rightsp : NULL), value->rights);
value->principals = (p_principals ? qtokenize(p_principals) : NULL);
return PSUCCESS;
}

242
prospero/lib/pfs/in_atrs.c Normal file
View File

@@ -0,0 +1,242 @@
/*
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file <usc-copyr.h>
*/
#include <usc-copyr.h>
#include <pfs.h>
#include <pparse.h>
#include <perrno.h>
#include <pprot.h>
int p__server = 0; /* set to 1 by dirsrv.c. */
static int
in_attribute_value(INPUT in, char *command, char *next_word, int nesting,
char avtype, union avalue *value);
int in_ge1_atrs(INPUT in, char *command, char *next_word, PATTRIB *valuep)
{
PATTRIB at = atalloc();
int retval;
CHECK_MEM();
*valuep = NULL;
CHECK_PTRinBUFF(command,next_word);
if (!at) out_of_memory();
if (retval = in_atr_data(in, command, next_word, 0, at)) {
atfree(at);
return retval;
}
APPEND_ITEM(at, *valuep);
if (retval = in_atrs(in, 0, &at->next)) {
atfree(at);
return retval;
}
/* now need to correct the doubly-linked list. */
if (at->next) {
at->previous = at->next->previous;
at->next->previous = at;
}
return PSUCCESS;
}
/* Read in a series of protocol-style ATTRIBUTE lines. */
/* starts with in_nextline() set to the first possible ATTRIBUTE line, and
returns with in_nextline() set to the next line of available text. */
/* the caller is responsible for calling palfree() on whatever in_atrs()
delivers up. */
int
in_atrs(INPUT in, int nesting, PATTRIB *valuep)
{
char t_nesting[100];
char *command, *next_word;
PATTRIB list = NULL; /* Head of a linked list of new attributes. */
int retval;
while(in_nextline(in)
&& qsscanf(in_nextline(in), "ATTRIBUTE%!!(>)", t_nesting, sizeof
t_nesting) == 1) {
PATTRIB at;
if(strlen(t_nesting) < nesting)
break; /* we're done with reading the subats */
at = atalloc();
if (!at) {
atlfree(list);
out_of_memory();
}
APPEND_ITEM(at, list);
if (strlen(t_nesting) > nesting) {
/* OOPS! Unexpectedly deep nesting. */
atlfree(list);
p_err_string = qsprintf_stcopyr(p_err_string,
"ATTRIBUTE line sent with Nesting too deep; got %d, \
expected %d: %s", strlen(t_nesting), nesting, command);
return perrno = PARSE_ERROR;
}
assert(strlen(t_nesting) == nesting);
if(retval = in_line(in, &command, &next_word)) {
atlfree(list);
return perrno = retval;
}
CHECK_PTRinBUFF(command,next_word);
if(retval = in_atr_data(in, command, next_word, nesting, at)) {
atlfree(list);
return perrno = retval;
}
}
/* done! */
*valuep = list;
return PSUCCESS;
}
/* We may need to recursively read the subattributes of a link, which means we
may need to read multiple lines here. */
int
in_atr_data(INPUT in, char *command, char *next_word, int nesting, PATTRIB at)
{
char t_nature[sizeof "APPLICATION"];
AUTOSTAT_CHARPP(t_anamep);
AUTOSTAT_CHARPP(t_avtypep);
char t_precedence[40];
int retval;
int tmp; /* from qsscanf() */
char *maybe_eol; /* Need a pointer to end of line. */
/* Used as a temporary in two separate places in the
code. */
CHECK_PTRinBUFF(command,next_word);
tmp = qsscanf(next_word, "%!!s %!!s %'&s%r %r",
t_precedence, sizeof t_precedence,
t_nature, sizeof t_nature, t_anamep, &maybe_eol, &next_word);
if (tmp < 4) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Malformed attribute line: %s", command);
return perrno = PARSE_ERROR;
} else if (tmp == 4) {
/* no tokens for data given. This still might be legal -- e.g., a
zero-length sequence. */
next_word = maybe_eol;
#if 0
/* This following item won't work because in_attribute_value expects
NEXT_WORD to be a pointer into the same string indicated by COMMAND.
This was causing a crash whenever we had a zero-item SEQUENCE.
--swa */
next_word = "";
#endif
} /* else all is ok. */
at->precedence = lookup_precedence_by_precedencename(t_precedence);
#ifndef REALLY_NEW_FIELD
if(strequal(t_nature, "FIELD")) {
char *cp; /* temp. ptr. */
at->nature = ATR_NATURE_FIELD;
/* If the oldstyle field name field doesn't contain a valid old field
name, try to parse it as a new style message. */
if((at->avtype = lookup_avtype_by_field_name(*t_anamep))
== ATR_UNKNOWN)
goto new_field;
/* If there's a t_avtype that matches the appropriate type for this
field AND we have additional data following it then it's probably a
new-style field. */
tmp = qsscanf(next_word, "%&'s %r", t_avtypep, &cp);
if (tmp == 2 && at->avtype == lookup_avtype_by_avtypename(*t_avtypep))
goto new_field;
/* Treat it as an old-style field. */
} else /* Note the indentation below looks odd,
but it's the most correct way I can think of
to do it. --swa */
#endif
if (strnequal(t_nature, "APPLICATION", 11) ||
#ifdef REALLY_NEW_FIELD
strnequal(t_nature, "FIELD", 5) ||
#endif
strnequal(t_nature, "INTRINSIC", 9)) {
at->nature = (t_nature[0] == 'A' ? ATR_NATURE_APPLICATION
#ifdef REALLY_NEW_FIELD
: t_nature[0] == 'F' ? ATR_NATURE_FIELD
#endif
: ATR_NATURE_INTRINSIC);
new_field:
/* An independent use of maybe_eol as a temporary. */
tmp = qsscanf(next_word, "%&'s%r %r",
t_avtypep, &maybe_eol, &next_word);
if (tmp < 2) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Malformed ATTRIBUTE line: %s", command);
return perrno = PARSE_ERROR;
} else if (tmp == 2)
next_word = maybe_eol; /* no more data -- zero length sequence,
etc. */
#if 0
/* This following item won't work because in_attribute_value expects
NEXT_WORD to be a pointer into the same string indicated by COMMAND.
This was causing a crash whenever we had a zero-item SEQUENCE.
--swa */
next_word = "";
#endif
if ((at->avtype = lookup_avtype_by_avtypename(*t_avtypep))
== ATR_UNKNOWN) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Unknown Attribute Value type: %s",
*t_avtypep);
return perrno = PARSE_ERROR;
}
CHECK_MEM();
} else { /* Unknown t_nature */
p_err_string = qsprintf_stcopyr(p_err_string,
"Only APPLICATION, INTRINSIC, and FIELD attribute value \
types exist -- Malformed ATTRIBUTE line: %s", command);
return perrno = PARSE_ERROR;
CHECK_MEM();
}
at->aname = stcopy(*t_anamep);
if (next_word) {
/* Lack of next_word is not an error, just dont fill out the value */
if(retval = in_attribute_value(in, command, next_word, nesting,
at->avtype, &at->value)) {
/* Error message will have been sent by in_attribute_value */
return perrno = retval;
}
}
/* The entry AT now has all of its members filled in. On to the next!
*/
return PSUCCESS;
}
/* Based upon the value of the attribute, as passed in AVTYPE, parse the
input line and store the results in VALUE. This may cause recursive calls
to in_attributes(). Return PSUCCESS or PFAILURE.
Command should be the head of a BSTRING and NEXT_WORD should be a pointer
into the bstring. */
static
int
in_attribute_value(INPUT in, char *command, char *next_word, int nesting,
char avtype, union avalue *value)
{
CHECK_PTRinBUFF(command,next_word);
CHECK_MEM();
switch(avtype) {
case ATR_FILTER:
return in_filter(in, command, next_word, nesting + 1,
&value->filter);
case ATR_LINK:
return in_link(in, command, next_word, nesting + 1,
&value->link, (TOKEN *) NULL);
case ATR_SEQUENCE:
return in_sequence(in, command, next_word, &value->sequence);
default:
internal_error("Invalid attribute value type!");
/*NOTREACHED */
}
/* NOTREACHED */
return -1; /* Keep gcc happy */
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the file <usc-copyr.h>
*/
#include <usc-copyr.h>
#include <pfs.h>
#include <pparse.h>
#include <pprot.h>
#include <perrno.h>
/* reads in a single FILTER line. */
int
in_filter(INPUT in, char *command, char *next_word, int nesting,
FILTER *valuep)
{
char t_filtype[MAX_DIR_LINESIZE];
char t_execloc[MAX_DIR_LINESIZE];
char t_pre_or_post[MAX_DIR_LINESIZE];
char t_predef_or_link[MAX_DIR_LINESIZE];
char t_name[MAX_DIR_LINESIZE];
char *p_args;
int tmp; /* return val. from qsscanf(). */
FILTER fil; /* The result. */
tmp = qsscanf(next_word, "%!!s %!!s %!!s %!!s %r",
t_filtype, sizeof t_filtype,
t_execloc, sizeof t_execloc,
t_pre_or_post, sizeof t_pre_or_post,
t_predef_or_link, sizeof t_predef_or_link, &next_word);
/* Set them. */
if (tmp < 5) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Filter description format error: %'s", command);
return perrno = PARSE_ERROR;
}
fil = flalloc();
if (!fil)
out_of_memory();
if(strequal(t_filtype, "DIRECTORY"))
fil->type = FIL_DIRECTORY;
else if (strequal(t_filtype, "HIERARCHY"))
fil->type = FIL_HIERARCHY;
else if (strequal(t_filtype, "OBJECT"))
fil->type = FIL_OBJECT;
else if (strequal(t_filtype, "UPDATE"))
fil->type = FIL_UPDATE;
else {
flfree(fil);
p_err_string = qsprintf_stcopyr(p_err_string,
"Unknown filter type: %'s", command);
return perrno = PARSE_ERROR;
}
if (strequal(t_execloc, "CLIENT"))
fil->execution_location = FIL_CLIENT;
else if (strequal(t_execloc, "SERVER"))
fil->execution_location = FIL_SERVER;
else {
flfree(fil);
p_err_string = qsprintf_stcopyr(p_err_string,
"Unknown filter execution location: %'s", command);
return perrno = PARSE_ERROR;
}
if (strequal(t_pre_or_post, "PRE"))
fil->pre_or_post = FIL_PRE;
else if (strequal(t_pre_or_post, "POST"))
fil->pre_or_post = FIL_POST;
else {
flfree(fil);
p_err_string = qsprintf_stcopyr(p_err_string,
"Unknown filter pre-or-post specification: %'s",
command);
return perrno = PARSE_ERROR;
}
if(strequal(t_predef_or_link, "PREDEFINED")) {
tmp = qsscanf(next_word, "%'s ARGS %r", t_name, &p_args);
if (tmp < 1) {
flfree(fil);
p_err_string = qsprintf_stcopyr(p_err_string,
"Malformed filter spec: %'s", command);
return perrno = PARSE_ERROR;
}
fil->name = stcopyr(t_name, fil->name);
if (tmp == 2)
fil->args = qtokenize(p_args);
} else if (strequal(t_predef_or_link, "LINK")) {
int retval; /* return from subfunction. */
if(retval = in_link(in, command, next_word, nesting, &(fil->link),
&(fil->args))) {
flfree(fil);
return retval;
}
} else {
flfree(fil);
p_err_string = qsprintf_stcopyr(p_err_string,
"Malformed filter spec, neither LINK nor PREDEFINED : %'s",
command);
return perrno = PARSE_ERROR;
}
*valuep = fil;
return PSUCCESS;
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file <usc-copyr.h>
*/
#include <usc-copyr.h>
#include <pfs.h>
#include <pparse.h>
#include <pprot.h>
#include <perrno.h>
/* Assumes next_word points to the word following a FORWARDED response. */
int
in_forwarded_data(INPUT in, char *command, char *next_word, VLINK dlink)
{
int tmp;
int moretext; /* flag we use to check if there's more text on
the line to examine. */
int retval = PSUCCESS; /* return value from functions */
tmp = qsscanf(next_word,"%~%'&s %'&s %'&s %'&s %ld %r",
&dlink->hosttype, &dlink->host,
&dlink->hsonametype, &dlink->hsoname,
&dlink->version, &next_word);
/* Log and return a better message */
if(tmp < 5) {
p_err_string = qsprintf_stcopyr(p_err_string, "Too few arguments: %'s",
command, 0);
return perrno = PARSE_ERROR;
}
moretext = (tmp == 6);
/* search for DEST_EXP, if set. */
if (moretext) {
AUTOSTAT_CHARPP(t_destexpp);
tmp = qsscanf(next_word, "DEST-EXP %'&s %r", t_destexpp, &next_word);
if (tmp >= 1)
dlink->dest_exp = asntotime(*t_destexpp);
moretext = (tmp == 2);
}
if (moretext) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Unknown tokens at end of FORWARDED specification: %'s",
command);
return perrno = PARSE_ERROR;
}
/* Look for any and all following ID lines and merge them with the link. */
retval = in_id(in, &dlink->f_magic_no);
if (retval) return perrno = retval;
return PSUCCESS;
}

57
prospero/lib/pfs/in_id.c Normal file
View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the file <usc-copyr.h>
*/
#include <usc-copyr.h>
#include <pfs.h>
#include <perrno.h>
#include <pparse.h>
#include <pprot.h>
/* The interface to this function will change. The long * must become a
pointer to some more generic ID storage type. But for now, this is correct.
We simply ignore ID types that we don't understand. I believe this is
correct.
*/
int
in_id(INPUT in, long *magic_nop)
{
char *command, *next_word;
long atol();
while (in_nextline(in) && strnequal(in_nextline(in), "ID", 2)) {
char t_id_type[MAX_DIR_LINESIZE];
int retval; /* retval from subfunctions. */
int tmp; /* # of tokens matched by qsscanf() */
TOKEN seq = NULL;
if(retval = in_line(in, &command, &next_word)) {
return retval;
}
tmp = qsscanf(next_word, "%!!s %r", t_id_type, sizeof t_id_type,
&next_word);
if (tmp < 1) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Malformed ID line received: %s", command);
return PARSE_ERROR;
}
if (strequal(t_id_type, "REMOTE")) {
if(retval = in_sequence(in, command, next_word, &seq))
return retval;
if (!seq || seq->next) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Malformed REMOTE ID type received; must be a single \
integer: %s", command);
return PARSE_ERROR;
}
/* XXX should use qsscanf() for the overflow checking. */
*magic_nop = atol(seq->token);
}
/* Just ignore other ID types. */
tklfree(seq);
}
return PSUCCESS;
}

130
prospero/lib/pfs/in_line.c Normal file
View File

@@ -0,0 +1,130 @@
/*
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*/
#include <usc-license.h>
#include <ctype.h>
#include <pfs.h>
#include <pparse.h>
#include <perrno.h>
/* in_line reads quoted Prospero lines from a number of sources, up to the next
unquoted newline. Upon return, *thislinep points to the start of a
NUL-terminated string which contains a Prospero protocol command line.
*next_wordp points to the first word in that string after command.
in_line passes through the error codes returned by its subsidiary functions.
The only error they return is PARSE_ERROR. If pfs_debug is set, then
explanatory detail describing the malformed line will be reported on
stderr.
*thislinep and *next_wordp point to a buffer private to in_line(). This
buffer may be rewritten after each new line is read.
*/
int
in_line(INPUT in, char **thislinep, char **next_wordp)
{
int tmp; /* temp return value. */
INPUT_ST eol_st; /* temp. variable for end of line. */
INPUT eol = &eol_st; /* temp. variable for end of line. */
int linebuflen; /* length to copy into linebuf */
int i; /* temporary index */
/* A local static variable. Points to the line in progress. */
AUTOSTAT_CHARPP(linebufp);
char *cp; /* temp. index */
if (!in_nextline(in)) internal_error("in_line() called with no data");
/* Ok, set EOL to the end of this input line. */
tmp = qscanf(in, "%~%r%'*(^\n\r)%r", in, eol);
if (tmp < 2) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Read Prospero message with an unterminated quote");
return PARSE_ERROR;
}
/* Make sure that linebuf points to a string with enough room to hold the
current line. */
if (in->sourcetype == IO_STRING) {
linebuflen = eol->s - in->s; /* string type doesn't use offset member.
*/
} else {
linebuflen = eol->offset - in->offset; /* size that strlen() would
return */
}
if (!*linebufp)
assert(*linebufp = stalloc(linebuflen + 1));
else if (p__bstsize(*linebufp) < linebuflen + 1) {
stfree(*linebufp);
assert(*linebufp = stalloc(linebuflen + 1));
}
/* Now copy the bytes from the input stream to the linebuf. This preserves
quoting, which is very important. */
for(cp = *linebufp, i = 0; i < linebuflen; ++cp, ++i, in_incc(in))
*cp = in_readc(in);
*cp = '\0';
assert((in->sourcetype != IO_STRING) ? in->offset == eol->offset : 1);
/* I need to trim off trailing spaces here. Or else there might be
trouble. Hmm. */
while (cp > *linebufp && isspace(*--cp)) {
*cp = '\0', --linebuflen;
}
p_bst_set_buffer_length_nullterm(*linebufp, linebuflen);
/* push on the read pointer for in to the start of the next line. */
tmp = qscanf(in, "%R", in);
if (tmp < 1) {
#if 0 /* gripe about unterminated lines */
p_err_string = qsprintf_stcopyr(p_err_string,
"Read Prospero message with a line that was not LF \
terminated.");
return PARSE_ERROR;
#else
while (!in_eof(in)) /* Gobble up anything else that remains.
I don't expect there to be anything. */
in_incc(in);
#endif
}
/* linebuf now points to a complete line of still quoted text. */
*thislinep = *linebufp;
if(p__qbstscanf(*thislinep, *thislinep, "%*'s%~%r", next_wordp) < 1
|| *thislinep == *next_wordp) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Read Prospero message with an empty line.");
return PARSE_ERROR;
}
return PSUCCESS;
}
void
rreqtoin(RREQ rreq, INPUT in)
{
in->sourcetype = IO_RREQ;
in->offset = 0; /* on byte 0. */
if(in->rreq = rreq) { /* might be NULL. */
in->inpkt = rreq->rcvd;
in->ptext_ioptr = rreq->rcvd->text;
/* Do a loop because there might be a crazy client that sends some
packets in a sequence with empty length fields. Skip any of them we
encounter; go to the next packet with some content. */
while (in->ptext_ioptr >= in->inpkt->text + in->inpkt->length) {
in->inpkt = in->inpkt->next;
if (in->inpkt == NULL)
break;
in->ptext_ioptr = in->inpkt->text;
}
} else {
in->inpkt = NULL;
in->ptext_ioptr = NULL;
}
#ifndef NDEBUG
in->file = NULL;
in->s = NULL;
#endif
in->flags = JUST_INITIALIZED; /* is this needed? */
}

127
prospero/lib/pfs/in_link.c Normal file
View File

@@ -0,0 +1,127 @@
/*
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the file <usc-copyr.h>
*/
#include <usc-copyr.h>
#include <pfs.h>
#include <pparse.h>
#include <pprot.h>
#include <perrno.h>
/* Returns PSUCCESS or PFAILURE.
Stashes its results in *valuep, and in *argsp, if argsp is non-NULL.
Starts reading from next_word.
*/
#define RETURN(rv) { retval = rv ; goto cleanup ; }
/* This wasnt freeing clink in all cases */
int
in_link(INPUT in, char *command, char *next_word,
int nesting, VLINK *valuep,
TOKEN *argsp /* Only used by in_filter. */)
{
VLINK clink;
int tmp;
char t_linktype;
char t_type[MAX_DIR_LINESIZE];
char t_name[MAX_DIR_LINESIZE];
char t_htype[MAX_DIR_LINESIZE];
char t_host[MAX_DIR_LINESIZE];
char t_ntype[MAX_DIR_LINESIZE];
char t_fname[MAX_DIR_LINESIZE];
char t_destexp[20];
char *p_args;
PATTRIB at;
int moretext; /* flag we use to check if there's more text on
the line to examine. */
int retval = PSUCCESS; /* return value from functions */
CHECK_MEM();
clink = vlalloc(); /* free-d or returned in valuep */
tmp = qsscanf(next_word, "%c %s %'s %s %'s %s %'s %d %r",
&t_linktype,t_type,t_name,t_htype,t_host,
t_ntype,t_fname,
&(clink->version), &next_word);
/* Log and return a better message */
if(tmp < 8) {
p_err_string = qsprintf_stcopyr(p_err_string, "Too few arguments: %'s",
command, 0);
RETURN(perrno = PARSE_ERROR);
}
assert(tmp <= 9);
moretext = (tmp == 9);
if (t_linktype == 'U' || t_linktype == 'L' || t_linktype == 'I'
|| in->flags == SERVER_DATA_FILE
&& (t_linktype == 'n' || t_linktype == 'N'))
clink->linktype = t_linktype;
else {
p_err_string = qsprintf_stcopyr(p_err_string,
"Illegal link type %c specified: %'s", t_linktype, command);
RETURN(perrno = PARSE_ERROR);
}
clink->target = stcopyr(t_type, clink->target);
clink->name = stcopyr(t_name, clink->name);
clink->hosttype = stcopyr(t_htype,clink->hosttype);
clink->host = stcopyr(t_host,clink->host);
clink->hsonametype = stcopyr(t_ntype,clink->hsonametype);
clink->hsoname = stcopyr(t_fname,clink->hsoname);
/* search for DEST_EXP, if set. */
if (moretext) {
tmp = qsscanf(next_word, "DEST-EXP %!!s %r", t_destexp,
sizeof t_destexp, &next_word);
if (tmp >= 1)
clink->dest_exp = asntotime(t_destexp);
moretext = (tmp == 2);
}
if (argsp) { /* if args requested */
/* if given */
if (moretext) {
tmp = qsscanf(next_word, "ARGS %r", &p_args);
if (tmp == 1) {
*argsp = qtokenize(p_args);
moretext = 0;
} else {
p_err_string = qsprintf_stcopyr(p_err_string,
"Unknown tokens at end of LINK specification: %'s",
command);
RETURN(perrno = PARSE_ERROR);
}
} else {
/* no more text, but args requested. */
*argsp = NULL;
}
}
/* check for leftover text. */
if (moretext) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Unknown tokens at end of LINK specification: %'s",
command);
RETURN( perrno = PARSE_ERROR);
}
/* Look for any and all following ID lines and merge them with the link. */
retval = in_id(in, &clink->f_magic_no);
/* look for ATTRIBUTE lines specifying link attributes. */
/* errors reported in p_err_string by these subfunctions. */
/* These subfunctions will free up memory they don't need. */
if (!retval) retval = in_atrs(in, nesting, &at);
if (!retval) retval = vl_add_atrs(at, clink);
if (retval) {
if(argsp) tklfree(*argsp);
/* in_atrs and add_attributes free their allocated memory if they fail;
we don't have to. */
RETURN(retval;) /* in_atrs && add_attributes set perrno, too.
*/
}
*valuep = clink;
return PSUCCESS;
cleanup:
vlfree(clink);
return(retval);
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*/
#include <usc-license.h>
#include <ardp.h>
#include <pfs.h>
#include <pparse.h>
#include <ctype.h> /* For isascii */
/* isascii() is not provided in POSIX, so we just do it here. */
#ifndef isascii
#define isascii(c) ((unsigned)(c)<=0177)
#endif
/* XXX Assumes that the longest possible word we could read in is
ARDP_PTXT_LEN_R. This is actually a bogus assumption; one can trigger the
assertion by sending a packet with a first word longer than that.
We don't cache the value returned from in_nextline() so it's safe to use
static data. Keywords (1st word in a line) are never quoted; this is safe
then.
*/
/* This function returns a pointer to internal data which will be overwritten
on the next call to in_nextline().
This function is used for lookahead in the parsing, and could be replaced
with other routines to do that.
*/
char *
in_nextline(INPUT oldin)
{
INPUT_ST in_st;
INPUT in = &in_st;
AUTOSTAT_CHARPP(bufp);
char *cp; /* Pointer into the buffer*/
int c;
if (!*bufp) *bufp = stalloc(ARDP_PTXT_LEN_R);
cp = *bufp;
input_copy(oldin, in);
if((c = in_readc(in)) == EOF) /* test for EOF */
return NULL;
while ((c != EOF) && isascii(c) && !isspace(c)) {
*(cp++) = c;
in_incc(in);
c = in_readc(in);
assert(cp - *bufp < p__bstsize(*bufp));
}
*cp = '\0';
return *bufp;
}

141
prospero/lib/pfs/in_readc.c Normal file
View File

@@ -0,0 +1,141 @@
/*
* Copyright(c) 1993 by the University of Southern California
* For copying information, see the file <usc-license.h>
*/
#include <usc-license.h>
#include <ardp.h>
#include <pfs.h>
#include <pparse.h>
extern int pfs_debug;
int (*stdio_fseek)();
/* Returns the distinguished value EOF if end of input detected.
*/
int
in_readc(INPUT in)
{
int c;
switch(in->sourcetype) {
case IO_FILE:
if((*stdio_fseek)(in->file, in->offset, 0) == -1) {
/* improper seek */
if (pfs_debug)
fprintf(stderr, "in in_readc() an improper fseek was detected.");
return '\0';
}
if((c = getc(in->file)) == EOF) {
clearerr(in->file); /* don't want this to stick around. */
}
return c;
case IO_STRING:
return *(in->s)
? (unsigned char) *(in->s) : EOF;
case IO_RREQ:
return (in->inpkt)
? (unsigned char) *in->ptext_ioptr : EOF;
case IO_BSTRING:
return (in->offset < in->bstring_length)
? (unsigned char) *(in->s) : EOF;
default:
internal_error("invalid in->iotype");
}
return(-1); /* Unreached - keeps gcc happy */
}
/* this is not too efficient. Fix it one day (yeah, right.). */
int
in_readcahead(INPUT in, int howfar)
{
INPUT_ST incpy_st;
INPUT incpy = &incpy_st;
assert(howfar >= 0);
input_copy(in, incpy);
while (howfar-- > 0)
in_incc(incpy);
return in_readc(incpy);
}
/* This function may legally be called on a stream which has already reached
EOF. In that case, it's a no-op. */
void
in_incc(INPUT in)
{
/* this takes advantage of the null termination trick. */
int c;
switch(in->sourcetype) {
case IO_FILE:
++in->offset;
break;
case IO_STRING:
if (in->s) ++(in->s); /* don't increment past end of the string. */
break;
case IO_RREQ:
if (in->inpkt) {
++in->ptext_ioptr;
++in->offset;
/* Do a loop because there might be a crazy client that
sends some packets in a sequence with empty length fields.
Skip any of them we encounter; go to the next packet with some
content. */
while (in->ptext_ioptr >= in->inpkt->start + in->inpkt->length) {
in->inpkt = in->inpkt->next;
if (in->inpkt == NULL)
break;
in->ptext_ioptr = in->inpkt->text;
}
}
break;
case IO_BSTRING:
if (in->offset < in->bstring_length) {
++in->offset;
++in->s;
}
break;
default:
internal_error("invalid in->iotype");
}
}
/*
* It is not at all clear what role this plays, given that in_readc() does
* this test for us. But it remains.
*/
int
in_eof(INPUT in)
{
switch(in->sourcetype) {
case IO_FILE:
if((*stdio_fseek)(in->file, in->offset, 0) == -1) {
/* improper seek */
if (pfs_debug)
fprintf(stderr, "in in_readc() an improper fseek was detected.");
return EOF;
}
if(getc(in->file) == EOF) {
clearerr(in->file); /* don't want this to stick around. */
return EOF;
}
return 0;
case IO_STRING:
if (*(in->s)) return 0;
else return EOF;
case IO_RREQ:
if (in->inpkt) return 0;
else return EOF;
case IO_BSTRING:
if (in->offset < in->bstring_length) return 0;
else return EOF;
}
assert(FALSE); /*Never gets here */
return -1;
}

View File

@@ -0,0 +1,51 @@
/* author: swa@isi.edu */
/*
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the file <usc-copyr.h>
*/
#include <usc-copyr.h>
#include <pfs.h>
#include <perrno.h>
#include <pparse.h>
#include <pprot.h>
/* The interface to this function will change. The long * must become a
pointer to a list of attributes (PATTRIB *). But for now, this is correct,
since dsrfinfo() and the name searching code don't pay attention to such
information. */
/* We simply ignore ID types that we don't understand. I believe this is
correct. */
int
in_select(INPUT in, long *magic_nop)
{
char *command, *next_word;
long atol();
while (in_nextline(in) && strnequal(in_nextline(in), "SELECT", 6)) {
char t_id_type[MAX_DIR_LINESIZE];
int retval; /* retval from subfunctions. */
PATTRIB at = atalloc();
if(retval = in_line(in, &command, &next_word)) {
atfree(at);
return retval;
}
assert(next_word >= command);
if (retval = in_atr_data(in, command, next_word, 0, at)) {
atfree(at);
return retval;
}
if (at->avtype == ATR_SEQUENCE && at->nature == ATR_NATURE_FIELD
&& strequal(at->aname, "ID") && length(at->value.sequence) == 2
&& strequal(at->value.sequence->token, "REMOTE")) {
/* XXX should use qsscanf() for the overflow checking. */
*magic_nop = atol(at->value.sequence->next->token);
}
/* Just ignore other attribute and ID types. */
atfree(at);
}
return PSUCCESS;
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright (c) 1992, 1993, 1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*/
#include <usc-license.h>
#include <pfs.h>
#include <pparse.h>
/* Command should be the head of a BSTRING and NEXT_WORD should be a pointer
into the BSTRING. */
/* Convert portion of command starting at *next_word to list of TOKENs */
int
in_sequence(INPUT in, char *command, char *next_word, TOKEN *valuep)
{
CHECK_PTRinBUFF(command,next_word);
*valuep = p__qbstokenize(command, next_word);
return PSUCCESS;
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 1992,1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
#include <pfs.h> /* includes internal error definitions. */
#include <stdio.h>
#include <perrno.h>
/* This is set by p__fout_of_memory(). It is looked at by the server restart
code in server/dirsrv.c and server/restart_srv.c. */
int p__is_out_of_memory = 0;
/* A function version of internal_error(). Used by macros. */
void
p__finternal_error(const char file[], int line, const char msg[])
{
#if 0
write(2, "Internal error in file ",
sizeof "Internal error in file " -1);
write(2, file, strlen(file));
write(2, ": ", 2);
write(2, msg, strlen(msg));
write(2, "\n", 1);
#endif
fprintf(stderr, "Internal error at %s:%d: %s\n",
file, line, msg);
if (internal_error_handler)
(*internal_error_handler)(file, line, msg);
else
abort();
}
void
p__fout_of_memory(const char file[], int line)
{
p__is_out_of_memory++;
p__finternal_error(file, line, "Out of Memory");
}

Some files were not shown because too many files have changed in this diff Show More