Intial commit
This commit is contained in:
1
prospero/lib/psrv/.gitignore
vendored
Normal file
1
prospero/lib/psrv/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Makefile
|
||||
29
prospero/lib/psrv/FILES
Normal file
29
prospero/lib/psrv/FILES
Normal file
@@ -0,0 +1,29 @@
|
||||
FILES
|
||||
Makefile
|
||||
ad2l_atr.c
|
||||
archie2
|
||||
archie3
|
||||
at_delete.c
|
||||
change_acl.c
|
||||
check_acl.c
|
||||
check_nfs.c
|
||||
chk_krb_auth.c
|
||||
chk_localpth.c
|
||||
dsdir.c
|
||||
dsrfinfo.c
|
||||
dsrobject.c
|
||||
dsrobject_v6.c
|
||||
dswfinfo.c
|
||||
dswobject.c
|
||||
error_reply.c
|
||||
gopher_gw
|
||||
magic.c
|
||||
named_acl.c
|
||||
optparse.c
|
||||
plog.c
|
||||
ppasswd.c
|
||||
psrv_mutexes.c
|
||||
replyf.c
|
||||
retrieve_fp.c
|
||||
srv_qoprintf.c
|
||||
wais_gw
|
||||
243
prospero/lib/psrv/Makefile.in
Executable file
243
prospero/lib/psrv/Makefile.in
Executable file
@@ -0,0 +1,243 @@
|
||||
# Makefile for LIB/PSRV
|
||||
|
||||
SOURCEBASE = ../..
|
||||
include $(SOURCEBASE)/Makefile.config
|
||||
|
||||
SUBDIRS =
|
||||
|
||||
CFILES = \
|
||||
ad2l_atr.c \
|
||||
at_delete.c \
|
||||
change_acl.c \
|
||||
check_acl.c \
|
||||
check_nfs.c \
|
||||
chk_krb_auth.c \
|
||||
chk_localpth.c \
|
||||
dsdir.c \
|
||||
dsrfinfo.c \
|
||||
dsrobject.c \
|
||||
dswfinfo.c \
|
||||
dswobject.c \
|
||||
error_reply.c \
|
||||
magic.c \
|
||||
named_acl.c \
|
||||
optparse.c \
|
||||
plog.c \
|
||||
ppasswd.c \
|
||||
psrv_mutexes.c \
|
||||
replyf.c \
|
||||
retrieve_fp.c \
|
||||
srv_qoprintf.c
|
||||
|
||||
OBJECTS = \
|
||||
ad2l_atr.o \
|
||||
at_delete.o \
|
||||
change_acl.o \
|
||||
check_acl.o \
|
||||
check_nfs.o \
|
||||
chk_krb_auth.o \
|
||||
chk_localpth.o \
|
||||
dsdir.o \
|
||||
dsrfinfo.o \
|
||||
dsrobject.o \
|
||||
dswfinfo.o \
|
||||
dswobject.o \
|
||||
error_reply.o \
|
||||
magic.o \
|
||||
named_acl.o \
|
||||
optparse.o \
|
||||
plog.o \
|
||||
ppasswd.o \
|
||||
psrv_mutexes.o \
|
||||
replyf.o \
|
||||
retrieve_fp.o \
|
||||
srv_qoprintf.o
|
||||
|
||||
|
||||
all: ${SRV_LIB} all_subdirs
|
||||
|
||||
install:
|
||||
|
||||
# cp ${SRV_LIB} ${P_BINARIES}/${SRV_LIB}
|
||||
# ${RANLIB} ${P_BINARIES}/${SRV_LIB}
|
||||
|
||||
|
||||
${SRV_LIB}: ${OBJECTS}
|
||||
rm -f ${SRV_LIB}
|
||||
ar r${AR_FLAGS} ${SRV_LIB} ${OBJECTS}
|
||||
${RANLIB} ${SRV_LIB}
|
||||
|
||||
# Dependencies
|
||||
ad2l_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/perrno.h
|
||||
at_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/psrv.h ../../include/pparse.h \
|
||||
../../include/perrno.h
|
||||
change_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/psite.h ../../include/pprot.h ../../include/plog.h \
|
||||
../../include/psrv.h \
|
||||
../../include/pparse.h ../../include/perrno.h
|
||||
check_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/pserver.h \
|
||||
../../include/pprot.h ../../include/plog.h \
|
||||
../../include/psrv.h ../../include/pparse.h
|
||||
check_nfs.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
|
||||
chk_krb_auth.o : ../../include/psite.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/psrv.h ../../include/pparse.h \
|
||||
../../include/pserver.h
|
||||
chk_localpth.o : \
|
||||
../../include/pmachine.h \
|
||||
../../include/pserver.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/plog.h
|
||||
dsdir.o : \
|
||||
../../include/pmachine.h \
|
||||
../../include/pserver.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/implicit_fixes.h \
|
||||
../../include/plog.h \
|
||||
../../include/pprot.h ../../include/perrno.h ../../include/pparse.h \
|
||||
../../include/psrv.h ../../include/posix_signal.h ../../include/mitra_macros.h
|
||||
dsrfinfo.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/pprot.h ../../include/perrno.h ../../include/pparse.h ../../include/psrv.h
|
||||
dsrobject.o : \
|
||||
../../include/pmachine.h \
|
||||
../../include/pserver.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 ../../include/psrv.h ../../include/pparse.h \
|
||||
../../include/plog.h
|
||||
dswfinfo.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/psrv.h ../../include/perrno.h ../../include/plog.h
|
||||
dswobject.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 ../../include/psrv.h ../../include/pparse.h \
|
||||
../../include/plog.h
|
||||
error_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 \
|
||||
../../include/psrv.h ../../include/pparse.h \
|
||||
../../include/plog.h ../../include/pprot.h ../../include/perrno.h
|
||||
magic.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
|
||||
named_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/perrno.h ../../include/psrv.h ../../include/pparse.h \
|
||||
../../include/plog.h
|
||||
optparse.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/psrv.h ../../include/perrno.h
|
||||
plog.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
|
||||
ppasswd.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/pserver.h ../../include/ppasswd.h \
|
||||
../../include/perrno.h
|
||||
psrv_mutexes.o : ../../include/pserver.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/psrv.h ../../include/pparse.h
|
||||
replyf.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/pprot.h ../../include/psrv.h ../../include/pparse.h
|
||||
retrieve_fp.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/psrv.h ../../include/pparse.h \
|
||||
../../include/perrno.h
|
||||
srv_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 \
|
||||
../../include/psrv.h
|
||||
101
prospero/lib/psrv/ad2l_atr.c
Normal file
101
prospero/lib/psrv/ad2l_atr.c
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-copyr.h>.
|
||||
*
|
||||
* Written by bcn, 17 January 1993
|
||||
*/
|
||||
|
||||
#include <usc-copyr.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <pfs.h>
|
||||
#include <perrno.h>
|
||||
|
||||
/*
|
||||
* ad2l_seq1_atr - add single element sequence attribute to link
|
||||
*
|
||||
* The routines ad2l_seq1_atr is intended to provide a high level
|
||||
* interface for adding a common form of attribute to a link,
|
||||
* adding a sequence attribute. If compiled under ANSI C, it
|
||||
* allows the addition of sequence attributes. If under non
|
||||
* ANSI C, it allows the addition of a sequence attribute with
|
||||
* a single element value.
|
||||
*
|
||||
* This functions is intended for use by information service providers
|
||||
* converting information from their database to link information to be
|
||||
* returned by a Prospero server.
|
||||
*/
|
||||
int
|
||||
ad2l_seq_atr(VLINK l, /* Link to receive attribute */
|
||||
char precedence, /* To what the attribute applies */
|
||||
char nature, /* Nature of the attribute */
|
||||
char *aname, /* The name of the attribute */
|
||||
...) /* Elements of the value */
|
||||
{
|
||||
va_list ap;
|
||||
char *seq_elem; /* Element of sequence */
|
||||
|
||||
PATTRIB at = atalloc();
|
||||
|
||||
if(!at) RETURNPFAILURE;
|
||||
|
||||
at->precedence = precedence;
|
||||
at->nature = nature;
|
||||
at->aname = stcopy(aname);
|
||||
at->avtype = ATR_SEQUENCE;
|
||||
va_start(ap, aname);
|
||||
while(seq_elem = va_arg(ap, char *)) {
|
||||
at->value.sequence = tkappend(seq_elem, at->value.sequence);
|
||||
}
|
||||
va_end(ap);
|
||||
APPEND_ITEM(at, l->lattrib);
|
||||
return(PSUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ad2l_am_atr - add access method attribute to link
|
||||
*
|
||||
* The routine ad2l_am_atr is intended to provide a high level
|
||||
* interface for adding the common form of the access method attribute to
|
||||
* a link, adding an access method attribute with the first four generic
|
||||
* arguments null (the value will be taken from the link itself).
|
||||
*
|
||||
* This function is intended for use by information service providers
|
||||
* converting information from their database to link information to be
|
||||
* returned by a Prospero server.
|
||||
*/
|
||||
void
|
||||
ad2l_am_atr(VLINK l, /* Link to receive attribute */
|
||||
char *am, /* The access method */
|
||||
...) /* Specific elements of the value */
|
||||
{
|
||||
PATTRIB at = atalloc();
|
||||
va_list ap;
|
||||
char *arg; /* Arguments to access method */
|
||||
|
||||
va_start(ap, am);
|
||||
arg = va_arg(ap, char *);
|
||||
va_end(ap);
|
||||
|
||||
at->precedence = ATR_PREC_CACHED;
|
||||
at->nature = ATR_NATURE_FIELD;
|
||||
at->aname = stcopy("ACCESS-METHOD");
|
||||
at->avtype = ATR_SEQUENCE;
|
||||
at->value.sequence = tkappend(am, at->value.sequence);
|
||||
|
||||
if(arg) {
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend(arg, at->value.sequence);
|
||||
}
|
||||
|
||||
while(arg = va_arg(ap, char *)) {
|
||||
at->value.sequence = tkappend(arg,at->value.sequence);
|
||||
}
|
||||
APPEND_ITEM(at, l->lattrib);
|
||||
}
|
||||
1
prospero/lib/psrv/archie2/.gitignore
vendored
Normal file
1
prospero/lib/psrv/archie2/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Makefile
|
||||
10
prospero/lib/psrv/archie2/FILES
Normal file
10
prospero/lib/psrv/archie2/FILES
Normal file
@@ -0,0 +1,10 @@
|
||||
FILES
|
||||
Makefile
|
||||
README
|
||||
arch_dsdb.c
|
||||
arch_prioritize.c
|
||||
atopdate.c
|
||||
atoplink.c
|
||||
prarch.h
|
||||
prarch_host.c
|
||||
prarch_match.c
|
||||
95
prospero/lib/psrv/archie2/Makefile.backup
Executable file
95
prospero/lib/psrv/archie2/Makefile.backup
Executable file
@@ -0,0 +1,95 @@
|
||||
A_INC = -Iarchie_src
|
||||
|
||||
INCS += ${A_INC}
|
||||
|
||||
# libraries should be relative to this dir, not SRC
|
||||
DBS_LIB = libpsarchie.a
|
||||
|
||||
CFLAGS += -O2 -DMMAP -DSTRFIND -DCLEANUP
|
||||
|
||||
CFILES = \
|
||||
arch_dsdb.c \
|
||||
arch_prioritize.c \
|
||||
prarch_match.c \
|
||||
prarch_host.c \
|
||||
atopdate.c \
|
||||
atoplink.c
|
||||
|
||||
OBJECTS = \
|
||||
arch_dsdb.o \
|
||||
arch_prioritize.o \
|
||||
prarch_match.o \
|
||||
prarch_host.o \
|
||||
atopdate.o \
|
||||
atoplink.o
|
||||
|
||||
ARC_LIB = \
|
||||
oper.o \
|
||||
database.o \
|
||||
misc.o \
|
||||
error.o \
|
||||
net.o
|
||||
|
||||
ARC_LIBSRC = \
|
||||
oper.c \
|
||||
database.c \
|
||||
misc.c \
|
||||
error.c \
|
||||
net.c
|
||||
|
||||
|
||||
CODE = ${CFILES} Makefile
|
||||
|
||||
all: ${DBS_LIB}
|
||||
|
||||
install:
|
||||
cp ${DBS_LIB} ${INSTDIR}/${SRV_LIB}
|
||||
ranlib ${INSTDIR}/${DBS_LIB}
|
||||
|
||||
cleandb:
|
||||
\rm -f db/* /usr/tmp/archie.lock
|
||||
\cp /dev/null db/file-list
|
||||
\cp /dev/null db/strings-list
|
||||
|
||||
${ARC_LIB}: Makefile
|
||||
${CC} ${F_CC} ${F_CPP} $*.c
|
||||
|
||||
${ARC_LIBSRC}:
|
||||
ln -s archie_src/$@
|
||||
|
||||
${DBS_LIB}: ${OBJECTS} ${ARC_LIB}
|
||||
rm -f ${DBS_LIB}
|
||||
ar rv ${DBS_LIB} ${OBJECTS} ${ARC_LIB}
|
||||
ranlib ${DBS_LIB}
|
||||
|
||||
# These Dependencies cannot be automatedly generated by the SWA Prospero
|
||||
# scripts, unless you're running on a machine with the ARCHIE sources on it.
|
||||
# Therefore, we treat them specially.
|
||||
# These dependencies should be updated the next time someone reading this is
|
||||
# in a position to do so.
|
||||
# Actually, to set the dependencies, create a dummy archie_src directory
|
||||
# with archie_defs.h, database.h, structs.h, defines.h, error.h
|
||||
# This will work unless any archie include files in turn include other
|
||||
# include files, which we of course don't know.
|
||||
atoplink.o: prarch.h
|
||||
atoplink.o: archie_src/database.h
|
||||
atoplink.o: archie_src/defines.h
|
||||
atoplink.o: ../../../include/pfs.h
|
||||
atoplink.o: ../../../include/psite.h
|
||||
atoplink.o: archie_src/structs.h
|
||||
prarch_host.o: prarch.h
|
||||
prarch_host.o: archie_src/archie_defs.h
|
||||
prarch_host.o: archie_src/database.h
|
||||
prarch_host.o: archie_src/defines.h
|
||||
prarch_host.o: ../../../include/perrno.h
|
||||
prarch_host.o: ../../../include/pfs.h
|
||||
prarch_host.o: archie_src/structs.h
|
||||
|
||||
# Dependencies
|
||||
arch_prioritize.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
|
||||
45
prospero/lib/psrv/archie2/README
Normal file
45
prospero/lib/psrv/archie2/README
Normal file
@@ -0,0 +1,45 @@
|
||||
This directory contains code needed to integrate the archie 2 release
|
||||
with a Prospero server.
|
||||
|
||||
You should start from the most recent prospero release. You can
|
||||
obtain information about the release from info-prospero@isi.edu. The
|
||||
release should be available on prospero.isi.edu in the file
|
||||
/pub/prospero/prospero.tar.Z.
|
||||
|
||||
Here are specific instructions on how to tie Prospero in to Archie:
|
||||
Retrieve the release, and untar it. Installation instructions are
|
||||
included, but they are not tailored to Archie. The changes to the
|
||||
installations instruction for using it with Archie follow:
|
||||
|
||||
1) There is probably no need to set up separate user and group IDs
|
||||
for Prospero, just use those for Archie.
|
||||
|
||||
2) In pserver.h, define PSRV_ARCHIE.
|
||||
|
||||
3) In server/Makefile uncomment the appropriate DB_LIBS line
|
||||
for your configuration (archie2 or archie3)
|
||||
|
||||
4) In the directory lib/psrv/archie2 or lib/psrv/archie3, create
|
||||
a symbolic link archie_src in the directory the archie sources. Note,
|
||||
you must obtain archie sources from the archie group. For archie3,
|
||||
these sources must have been obtained after 2/22/93. For archie2,
|
||||
there has been a change to oper.c in the archie sources that should
|
||||
have been obtained since 2/22/93. Note also that for archie2, the
|
||||
archie sources must be set up to use the full path of the database
|
||||
directory, or you will also have to create a db symbolic link from the
|
||||
directory within which the Prospero server will run.
|
||||
|
||||
5) Run make in lib/psrv/archie2 or lib/psrv/archie3 depending
|
||||
on your configuration. If using archie3, make a link from
|
||||
libparchie.a to the file libparchie.a in the archie3
|
||||
distribution. If you want, you can add lib/psrv/archie2
|
||||
or lib/psrv/archie3 to the list of subdirectories in the
|
||||
top level Prospero makefile (SUBDIR).
|
||||
|
||||
6) Make the other necessary customizations (as per the installation
|
||||
instructions for prospero) by editing include/pserver.h,
|
||||
include/pmachine.h, and the top level make file.
|
||||
|
||||
7) As per the installation instructions, do a make, make install,
|
||||
then run pstart (you will probably want to add pstart to your
|
||||
system startup files).
|
||||
376
prospero/lib/psrv/archie2/arch_dsdb.c
Normal file
376
prospero/lib/psrv/archie2/arch_dsdb.c
Normal file
@@ -0,0 +1,376 @@
|
||||
/*
|
||||
* 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 ABSOLUTE_MAX_HITS 2500
|
||||
#define ABSOLUTE_MAX_GIF 100
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/dir.h>
|
||||
#include <stdio.h>
|
||||
#include <sgtty.h>
|
||||
#include <string_with_strcasecmp.h>
|
||||
|
||||
/* Archie defines */
|
||||
#include <defines.h>
|
||||
#include <structs.h>
|
||||
#include <error.h>
|
||||
#include <database.h>
|
||||
|
||||
#include "prarch.h"
|
||||
|
||||
#include <pserver.h>
|
||||
#include <pfs.h>
|
||||
#include <ardp.h>
|
||||
#include <psrv.h>
|
||||
#include <plog.h>
|
||||
#include <pprot.h>
|
||||
#include <perrno.h>
|
||||
#include <pmachine.h>
|
||||
|
||||
int archie_supported_version = 2;
|
||||
|
||||
extern char hostname[];
|
||||
extern char hostwport[];
|
||||
char archie_prefix[] = "ARCHIE";
|
||||
static int num_slashes(char *s);
|
||||
static int tkllength(TOKEN tkl);
|
||||
/*
|
||||
* dsdb - Make a database query as if it were a directory lookup
|
||||
*
|
||||
*/
|
||||
arch_dsdb(RREQ req, /* Request pointer */
|
||||
char *name, /* Name of the directory */
|
||||
char **componentsp, /* Next component of name */
|
||||
TOKEN *rcompp, /* Additional components */
|
||||
VDIR dir, /* Directory to be filled in */
|
||||
int options, /* Options to list command */
|
||||
const char *rattrib, /* Requested attributes */
|
||||
FILTER filters) /* Filters to be applied */
|
||||
{
|
||||
/* Note that componentspp and rcompp are pointers to */
|
||||
/* pointers. This is necessary because */
|
||||
/* this routine must be able to update these values */
|
||||
/* if more than one component of the name is */
|
||||
/* resolved. */
|
||||
char *components = NULL;
|
||||
int num_unresolvedcomps = 0;
|
||||
VLINK cur_link = NULL;
|
||||
char newdirname[MAXPATHLEN];
|
||||
static int dbopen = 0;
|
||||
char fullquery[MAXPATHLEN];
|
||||
char *dbpart;
|
||||
char dbquery[MAXPATHLEN];
|
||||
char dbargs[MAXPATHLEN];
|
||||
char dbarg1[MAXPATHLEN];
|
||||
char dbarg2[MAXPATHLEN];
|
||||
char dbarg3[MAXPATHLEN];
|
||||
char dirlinkname[MAXPATHLEN];
|
||||
char sep;
|
||||
char *firstsep;
|
||||
int tmp;
|
||||
VLINK dirlink = NULL;
|
||||
TOKEN tkl_tmp;
|
||||
|
||||
/* Make sure NAME, COMPONENTSP, and RCOMPP arguments are correct. */
|
||||
|
||||
/* Name components with slashes in them are malformed inputs to the
|
||||
ARCHIE database. */
|
||||
if(componentsp && (components = *componentsp)) {
|
||||
if(index(components, '/'))
|
||||
RETURNPFAILURE;
|
||||
for (tkl_tmp = *rcompp; tkl_tmp; tkl_tmp = tkl_tmp->next)
|
||||
if (index(tkl_tmp->token, '/'))
|
||||
RETURNPFAILURE;
|
||||
} else {
|
||||
if (*rcompp) RETURNPFAILURE; /* ridiculous to specify additional comps
|
||||
and no initial comps.*/
|
||||
}
|
||||
|
||||
/* Directory already initialized, but note that this */
|
||||
/* is not a real directory */
|
||||
dir->version = -1;
|
||||
dir->inc_native = 3; /* Not really a directory */
|
||||
|
||||
/* Note that if we are resolving multiple components */
|
||||
/* (rcomp!=NULL) the directory will already be empty */
|
||||
/* since had anything been in it dirsrv would have */
|
||||
/* already cleared it and moved on to the next comp */
|
||||
|
||||
/* Do only once */
|
||||
if(!dbopen++) {
|
||||
set_default_dir(DEFAULT_DBDIR);
|
||||
if((tmp = open_db_files(DB_RDONLY)) != A_OK) {
|
||||
dbopen = 0;
|
||||
plog(L_DB_ERROR,NOREQ,"Can't open archie database",0);
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* For now, if only verifying, indicate success */
|
||||
/* We don't want to do a DB search. Eventually */
|
||||
/* we might actually check that the directory */
|
||||
/* is valid. */
|
||||
if(options&DSDB_VERIFY) return(PSUCCESS);
|
||||
|
||||
/* Construct the full query from the pieces passed to us */
|
||||
tmp = -1 + qsprintf(fullquery,sizeof fullquery, "%s%s%s",name,
|
||||
((components && *components) ? "/" : ""),
|
||||
((components && *components) ? components : ""));
|
||||
for (tkl_tmp = *rcompp; tkl_tmp; tkl_tmp = tkl_tmp->next)
|
||||
tmp += -1 + qsprintf(fullquery + tmp, sizeof fullquery - tmp,
|
||||
"/%s", (*rcompp)->token);
|
||||
if (tmp + 1 > sizeof fullquery) return DSRDIR_NOT_A_DIRECTORY;
|
||||
|
||||
/* The format for the queries is */
|
||||
/* DATABASE_PREFIX/COMMAND(PARAMETERS)/ARGS */
|
||||
|
||||
/* Strip off the database prefix */
|
||||
dbpart = fullquery + strlen(archie_prefix);
|
||||
|
||||
/* And we want to skip the next slash */
|
||||
dbpart++;
|
||||
|
||||
/* Find the query (up to the next /), determine if the */
|
||||
/* / exists and then read the args */
|
||||
tmp = sscanf(dbpart,"%[^/]%c%s",dbquery,&sep,dbargs);
|
||||
|
||||
/* If no separator, for now return nothing */
|
||||
/* Eventually, we might return a list of the query */
|
||||
/* types supported */
|
||||
if(tmp < 2) return(PSUCCESS);
|
||||
|
||||
/* Check query type */
|
||||
if(strncmp(dbquery,"MATCH",5)==0) {
|
||||
char stype = 'R'; /* search type */
|
||||
int maxthit = 100; /* max entries to return */
|
||||
int maxmatch = 100; /* max strings to match */
|
||||
int maxhitpm = 100; /* max hits per match */
|
||||
int offset = 0; /* entries to skip */
|
||||
search_sel method; /* Search method */
|
||||
int onlystr = 0; /* Just return strings */
|
||||
|
||||
/* In the MATCH querytype, the directory part of the query (the
|
||||
argument named NAME) may have no more than 3 components.
|
||||
There are 3 possible formats:
|
||||
1) DATABASE_PREFIX (one component)
|
||||
2) (1)/MATCH(...)
|
||||
3) (2)/query-term (3 total components)
|
||||
*/
|
||||
if (num_slashes(name) > 2) return DSRDIR_NOT_A_DIRECTORY;
|
||||
/* if no strings to match, return nothing */
|
||||
if(tmp < 3) return(PSUCCESS);
|
||||
|
||||
/* Get arguments */
|
||||
tmp = sscanf(dbquery,"MATCH(%d,%d,%d,%d,%c",&maxthit,
|
||||
&maxmatch,&maxhitpm,&offset,&stype);
|
||||
|
||||
if(tmp < 3) {
|
||||
sscanf(dbquery,"MATCH(%d,%d,%c",&maxthit,&offset,&stype);
|
||||
maxmatch = maxthit;
|
||||
maxhitpm = maxthit;
|
||||
}
|
||||
/* Note: in maxhits, 0 means use default, -1 means use max */
|
||||
|
||||
/* Don't let the user request more than ABSOLUTE_MAX_HITS */
|
||||
if((maxthit > ABSOLUTE_MAX_HITS) || (maxthit < 1)) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Legal values for max hits are between 1 and %d ",
|
||||
ABSOLUTE_MAX_HITS);
|
||||
return(DIRSRV_NOT_AUTHORIZED);
|
||||
}
|
||||
if(maxthit == 0) maxthit = ABSOLUTE_MAX_HITS;
|
||||
|
||||
switch(stype) {
|
||||
case '=':
|
||||
onlystr = 0;
|
||||
method = S_EXACT ;
|
||||
break;
|
||||
case 'C':
|
||||
onlystr = 0;
|
||||
method = S_SUB_CASE_STR ;
|
||||
break;
|
||||
case 'c':
|
||||
onlystr = 0;
|
||||
method = S_E_SUB_CASE_STR ;
|
||||
break;
|
||||
case 'K':
|
||||
onlystr = 1;
|
||||
method = S_SUB_CASE_STR ;
|
||||
break;
|
||||
case 'k':
|
||||
onlystr = 1;
|
||||
method = S_E_SUB_CASE_STR ;
|
||||
break;
|
||||
case 'R':
|
||||
onlystr = 0;
|
||||
method = S_FULL_REGEX ;
|
||||
break;
|
||||
case 'r':
|
||||
onlystr = 0;
|
||||
method = S_E_FULL_REGEX ;
|
||||
break;
|
||||
case 'X':
|
||||
onlystr = 1;
|
||||
method = S_FULL_REGEX ;
|
||||
break;
|
||||
case 'x':
|
||||
onlystr = 1;
|
||||
method = S_E_FULL_REGEX ;
|
||||
break;
|
||||
case 'z':
|
||||
onlystr = 1;
|
||||
method = S_E_SUB_NCASE_STR ;
|
||||
break;
|
||||
case 'Z':
|
||||
onlystr = 1;
|
||||
method = S_SUB_NCASE_STR ;
|
||||
break;
|
||||
case 's':
|
||||
onlystr = 0;
|
||||
method = S_E_SUB_NCASE_STR ;
|
||||
break;
|
||||
case 'S':
|
||||
default:
|
||||
onlystr = 0;
|
||||
method = S_SUB_NCASE_STR ;
|
||||
break;
|
||||
}
|
||||
|
||||
*dbarg1 = *dbarg2 = *dbarg3 = '\0';
|
||||
|
||||
tmp = sscanf(dbargs,"%[^/]%c%[^/]%c%s",dbarg1,&sep,dbarg2,
|
||||
&sep,dbarg3);
|
||||
|
||||
if(tmp < 2) {
|
||||
/* This specifies a directory, but not a link within it */
|
||||
/* create a pseudo directory and return a pointer */
|
||||
/* In other words, listing a MATCH directory by itself yields
|
||||
an empty directory. */
|
||||
if(*dbarg1 && (strcmp(dbarg1,"*")!= 0)) {
|
||||
dirlink = vlalloc();
|
||||
dirlink->target = stcopyr("DIRECTORY",dirlink->target);
|
||||
dirlink->name = stcopyr(dbarg1,dirlink->name);
|
||||
dirlink->host = stcopyr(hostwport,dirlink->host);
|
||||
sprintf(dirlinkname,"%s/%s/%s",archie_prefix,dbquery,dbarg1);
|
||||
dirlink->hsoname = stcopyr(dirlinkname,dirlink->hsoname);
|
||||
vl_insert(dirlink,dir,VLI_ALLOW_CONF);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(tmp > 4) {
|
||||
/* There are remaining components */
|
||||
num_unresolvedcomps = num_slashes(dbarg3);
|
||||
}
|
||||
#ifdef ABSOLUTE_MAX_GIF
|
||||
/* If looking for GIF files (arrgh) don't allow them */
|
||||
/* to set an unreasonable number of hits, this is */
|
||||
/* promted by someone who set max hits to 10,000 */
|
||||
if((maxthit+offset > ABSOLUTE_MAX_GIF)&&(((strlen(dbarg1) >= 4)&&
|
||||
(strcasecmp(dbarg1+strlen(dbarg1)-4,".gif") == 0)) ||
|
||||
(strcasecmp(dbarg1,"gif") == 0))) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Max hits for GIF searches is %d - See archie/doc/giflist.Z on \
|
||||
archie.mcgill.ca for full gif list",ABSOLUTE_MAX_GIF);
|
||||
return(DIRSRV_NOT_AUTHORIZED);
|
||||
}
|
||||
#endif ABSOLUTE_MAX_GIF
|
||||
|
||||
tmp = prarch_match(dbarg1,maxthit,maxmatch,maxhitpm,
|
||||
offset,method,dir,FALSE,onlystr);
|
||||
if(tmp) RETURNPFAILURE;
|
||||
}
|
||||
}
|
||||
else if (strncmp(dbquery,"HOST",4)==0) {
|
||||
/* First component of args is the site name */
|
||||
/* remaining components are the directory name */
|
||||
|
||||
*dbarg1 = *dbarg2 = '\0';
|
||||
|
||||
tmp = sscanf(dbargs,"%[^/]%c%s",dbarg1,&sep,dbarg2);
|
||||
|
||||
/* If first component is null, return an empty directory */
|
||||
if(tmp < 1) return(PSUCCESS);
|
||||
|
||||
/* if first component exists, but is last component, */
|
||||
/* then it is the name of the subdirectory for the */
|
||||
/* host, create a pseudo directory and return a */
|
||||
/* pointer, If first component is a wildcard, and no */
|
||||
/* additional components, then return matching list */
|
||||
/* of sites. */
|
||||
if(tmp == 1) {
|
||||
tmp = prarch_host(dbarg1,NULL,dir,A2PL_ARDIR);
|
||||
if(tmp == PRARCH_TOO_MANY) return(DIRSRV_TOO_MANY);
|
||||
if(tmp) return(tmp);
|
||||
}
|
||||
/* More than one component, Look up the requested directory */
|
||||
/* Note that the since the full query is passed to us, it */
|
||||
/* includes the component name, thus the directory name is */
|
||||
/* what you get when you strip off the last component of the */
|
||||
/* name */
|
||||
else {
|
||||
char *lastsep = rindex(dbarg2,'/');
|
||||
if(lastsep) *lastsep++ = '\0';
|
||||
else *dbarg2 = '\0';
|
||||
tmp = prarch_host(dbarg1,dbarg2,dir,A2PL_ARDIR);
|
||||
if(tmp == PRARCH_DONT_HAVE_SITE)
|
||||
return(DSRDIR_NOT_A_DIRECTORY);
|
||||
if(tmp) RETURNPFAILURE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Query type not supported */
|
||||
return(DSRDIR_NOT_A_DIRECTORY);
|
||||
}
|
||||
|
||||
/* We are done, but we need to figure out if we resolved multiple
|
||||
components and reset *componentsp and *rcompp appropriately. */
|
||||
|
||||
if (num_unresolvedcomps) {
|
||||
int skip = tkllength(*rcompp) - num_unresolvedcomps;
|
||||
if (skip < 0) return DSRDIR_NOT_A_DIRECTORY; /* shouldn't happen. */
|
||||
while(skip-- > 0) {
|
||||
assert(*rcompp);
|
||||
*componentsp = (*rcompp)->token;
|
||||
*rcompp = (*rcompp)->next;
|
||||
}
|
||||
} else {
|
||||
while (*rcompp) {
|
||||
*componentsp = (*rcompp)->token;
|
||||
*rcompp = (*rcompp)->next;
|
||||
}
|
||||
}
|
||||
return(PSUCCESS);
|
||||
}
|
||||
|
||||
static int
|
||||
tkllength(TOKEN tkl)
|
||||
{
|
||||
int retval = 0;
|
||||
for (;tkl; tkl = tkl->next)
|
||||
++retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int
|
||||
num_slashes(char *s)
|
||||
{
|
||||
int retval = 0;
|
||||
for (; *s; ++s) {
|
||||
if (*s == '/')
|
||||
++retval;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
77
prospero/lib/psrv/archie2/arch_prioritize.c
Normal file
77
prospero/lib/psrv/archie2/arch_prioritize.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
#include <ardp.h>
|
||||
#include <pfs.h>
|
||||
#include <perrno.h>
|
||||
|
||||
static assign_priority();
|
||||
|
||||
arch_prioritize_request(r1,r2)
|
||||
RREQ r1,r2;
|
||||
{
|
||||
if(!r1->pf_priority)
|
||||
r1->pf_priority = assign_priority(r1);
|
||||
if(!r2->pf_priority)
|
||||
r2->pf_priority = assign_priority(r2);
|
||||
|
||||
if(r1->pf_priority == r2->pf_priority) return(0);
|
||||
else if (r1->pf_priority < r2->pf_priority) return(-1);
|
||||
else return(1);
|
||||
}
|
||||
|
||||
|
||||
static assign_priority(r1)
|
||||
RREQ r1;
|
||||
{
|
||||
char *arg_ptr;
|
||||
int maxhit = 0;
|
||||
int maxmatch = 0;
|
||||
int maxhitpm = 0;
|
||||
int offset;
|
||||
char stype;
|
||||
int tmp;
|
||||
int retval;
|
||||
|
||||
/* Result is probably cached, use it or lose it */
|
||||
if(r1->prcvd_thru > 0) return(2);
|
||||
|
||||
arg_ptr = sindex(r1->rcvd->start,"ARCHIE");
|
||||
if(!arg_ptr) return(1);
|
||||
|
||||
arg_ptr = sindex(arg_ptr,"MATCH");
|
||||
if(!arg_ptr) return(3);
|
||||
|
||||
tmp = sscanf(arg_ptr,"MATCH(%d,%d,%d,%d,%c",&maxhit,&maxmatch,
|
||||
&maxhitpm,&offset,&stype);
|
||||
if(tmp != 5) tmp = sscanf(arg_ptr,"MATCH(%d,%d,%c",&maxhit,
|
||||
&offset,&stype);
|
||||
if(tmp < 3) return(4);
|
||||
|
||||
if(stype == '=') retval = 0;
|
||||
else if ((stype == 'r') || (stype == 'x')) retval = 700;
|
||||
else if ((stype == 'R') || (stype == 'X')) retval = 800;
|
||||
else retval = 100;
|
||||
|
||||
/* If old format request, then add penalty */
|
||||
if(tmp != 5) retval += 100;
|
||||
|
||||
tmp = maxhit;
|
||||
if(offset > 0) tmp += offset;
|
||||
|
||||
if(tmp > 10000) retval += 10000;
|
||||
else if (tmp > 100) retval+= tmp;
|
||||
else retval+= 100;
|
||||
|
||||
if(sindex(arg_ptr,"gif") || sindex(arg_ptr,"GIF")) retval += 20000;
|
||||
|
||||
return(retval);
|
||||
}
|
||||
31
prospero/lib/psrv/archie2/atopdate.c
Normal file
31
prospero/lib/psrv/archie2/atopdate.c
Normal file
@@ -0,0 +1,31 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <defines.h>
|
||||
#include <structs.h>
|
||||
#include <database.h>
|
||||
|
||||
extern datestruct unpack_date();
|
||||
|
||||
char *atopdate(entry_db)
|
||||
db_date entry_db;
|
||||
{
|
||||
|
||||
static char result[20] ;
|
||||
datestruct entry;
|
||||
|
||||
entry = unpack_date(entry_db);
|
||||
|
||||
if(entry.hour == MAX_HOUR) {
|
||||
entry.hour = 0;
|
||||
entry.min = 0;
|
||||
}
|
||||
|
||||
(void) sprintf(result,"%04d%02d%02d%02d%02d00Z",entry.year,entry.month+1,
|
||||
entry.day,entry.hour,entry.min);
|
||||
|
||||
return(result);
|
||||
|
||||
}
|
||||
147
prospero/lib/psrv/archie2/atoplink.c
Normal file
147
prospero/lib/psrv/archie2/atoplink.c
Normal file
@@ -0,0 +1,147 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <database.h>
|
||||
#include <sys/mman.h>
|
||||
#include <defines.h>
|
||||
#include <structs.h>
|
||||
#include <pfs.h>
|
||||
#include <psite.h>
|
||||
#include "prarch.h"
|
||||
|
||||
extern FILE *strings_table;
|
||||
extern char *strings_begin;
|
||||
|
||||
extern char hostname[];
|
||||
extern char hostwport[];
|
||||
extern char archie_prefix[];
|
||||
|
||||
char *perms_itoa();
|
||||
char *print_date();
|
||||
char *atopdate();
|
||||
char *strstr();
|
||||
|
||||
VLINK atoplink(site_out *sop, /* Site output pointer */
|
||||
int flags) /* Flags: see above */
|
||||
{
|
||||
VLINK vl = vlalloc(); /* New link */
|
||||
PATTRIB at; /* Attributes */
|
||||
PATTRIB last_at; /* Last attribute */
|
||||
char fullpath[MAX_STRING_LEN];
|
||||
char namebuf[MAX_STRING_LEN];
|
||||
char *endname = NULL;
|
||||
char modestring[20];
|
||||
char str_ent[256];
|
||||
char atval[256];
|
||||
char *nameptr; /* Last component of file name */
|
||||
char *ptr;
|
||||
site_rec *srp = &(sop->site_ent); /* Site record pointer */
|
||||
long strings_pos;
|
||||
|
||||
/* For now, all directory pointers are to pseudo-directories */
|
||||
flags |= A2PL_ARDIR;
|
||||
|
||||
if((flags & A2PL_ROOT) || (srp->dir_or_f == 'T')) {
|
||||
/* It's a directory - we should check to see if the site is */
|
||||
/* running prospero, and if so return a pointer to the actual */
|
||||
/* directory. If it isn't then we return a real pointer to */
|
||||
/* a pseudo-directory maintained by this archie server. */
|
||||
vl->target = stcopyr("DIRECTORY",vl->target);
|
||||
}
|
||||
else {
|
||||
/* It's a file - we should check to see if the site is */
|
||||
/* running prospero, and if so return a pointer to the real */
|
||||
/* file. If it isn't, then we generate an external link */
|
||||
vl->target = stcopyr("EXTERNAL",vl->target);
|
||||
ad2l_am_atr(vl,"AFTP","BINARY",NULL);
|
||||
flags &= (~A2PL_ARDIR);
|
||||
}
|
||||
|
||||
if(flags & A2PL_ARDIR) vl->host = stcopyr(hostwport,vl->host);
|
||||
else vl->host = stcopyr(sop->site_name,vl->host);
|
||||
|
||||
/* Get the the last component of name */
|
||||
|
||||
if(flags & A2PL_ROOT) vl->name = stcopyr(sop->site_name,vl->name);
|
||||
else {
|
||||
strncpy(namebuf,strings_begin + srp->in_or_addr.strings_ind +
|
||||
sizeof(strings_header),sizeof(namebuf));
|
||||
namebuf[sizeof(namebuf)-1] = '\0';
|
||||
if(endname = strstr(namebuf," -> ")) *endname = '\0';
|
||||
nameptr = namebuf;
|
||||
vl->name = stcopyr(nameptr,vl->name);
|
||||
}
|
||||
|
||||
if(flags & A2PL_ARDIR) {
|
||||
if(flags & A2PL_ROOT)
|
||||
sprintf(fullpath,"%s/HOST/%s",archie_prefix, sop->site_name);
|
||||
else
|
||||
sprintf(fullpath,"%s/HOST/%s%s%s%s",archie_prefix,
|
||||
sop->site_name, sop->site_path,
|
||||
((*(sop->site_path + strlen(sop->site_path) - 1) == '/') ?
|
||||
"" : "/"), (nameptr ? nameptr : ""));
|
||||
}
|
||||
else {
|
||||
if(flags & A2PL_ROOT)
|
||||
sprintf(fullpath,"/");
|
||||
else
|
||||
sprintf(fullpath,"%s%s%s",sop->site_path,
|
||||
((*(sop->site_path + strlen(sop->site_path) - 1) == '/') ?
|
||||
"" : "/"), (nameptr ? nameptr : ""));
|
||||
}
|
||||
|
||||
vl->hsoname = stcopyr(fullpath,vl->hsoname);
|
||||
|
||||
if(!(flags & A2PL_ROOT)) {
|
||||
/* Here we can add cached attribute values from the archie */
|
||||
/* database such as size, protection, and last modified time */
|
||||
sprintf(atval,"%d bytes",srp->size);
|
||||
ad2l_seq_atr(vl,ATR_PREC_CACHED,ATR_NATURE_INTRINSIC,
|
||||
"SIZE",atval,NULL);
|
||||
|
||||
/* Directory modes in unix string format */
|
||||
if(ptr = perms_itoa(srp->perms)) {
|
||||
if(endname) sprintf(modestring,"%c%s",'l',ptr);
|
||||
else sprintf(modestring,"%c%s",((srp->dir_or_f=='T')?'d':'-'),ptr);
|
||||
ad2l_seq_atr(vl,ATR_PREC_CACHED,ATR_NATURE_INTRINSIC,
|
||||
"UNIX-MODES", modestring, NULL);
|
||||
}
|
||||
|
||||
/* Modified date - in prospero format */
|
||||
if(ptr = atopdate(srp->mod_time)) {
|
||||
ad2l_seq_atr(vl,ATR_PREC_CACHED,ATR_NATURE_INTRINSIC,
|
||||
"LAST-MODIFIED", ptr, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if((flags & A2PL_ROOT) || (flags & A2PL_H_LAST_MOD)) {
|
||||
/* Modified date - in prospero format */
|
||||
if(ptr = atopdate(sop->site_mod_time))
|
||||
ad2l_seq_atr(vl,ATR_PREC_CACHED,ATR_NATURE_APPLICATION,
|
||||
"AR_H_LAST_MOD", ptr, NULL);
|
||||
}
|
||||
|
||||
if((flags & A2PL_ROOT || (flags & A2PL_H_IP_ADDR))) {
|
||||
/* Host IP Address */
|
||||
if(sop->site_ipaddr.s_addr)
|
||||
ad2l_seq_atr(vl,ATR_PREC_CACHED,ATR_NATURE_APPLICATION,
|
||||
"AR_H_IP_ADDR", inet_ntoa(sop->site_ipaddr),
|
||||
NULL);
|
||||
}
|
||||
return(vl);
|
||||
}
|
||||
|
||||
VLINK atoqlink(char *str,int maxhit,int maxmatch,int maxhitpm)
|
||||
{
|
||||
VLINK vl = vlalloc();
|
||||
char fullpath[MAX_STRING_LEN];
|
||||
|
||||
sprintf(fullpath,"%s/MATCH(%d,%d,%d,0,=)/%s", archie_prefix,
|
||||
maxhit, maxmatch, maxhitpm, str);
|
||||
|
||||
vl->name = stcopyr(str,vl->host);
|
||||
vl->target = stcopyr("DIRECTORY",vl->target);
|
||||
vl->hsoname = stcopyr(fullpath,vl->hsoname);
|
||||
vl->host = stcopyr(hostwport,vl->host);
|
||||
return(vl);
|
||||
}
|
||||
42
prospero/lib/psrv/archie2/prarch.h
Normal file
42
prospero/lib/psrv/archie2/prarch.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* Error codes returned by prarch routines */
|
||||
#define PRARCH_SUCCESS 0 /* Successful completion */
|
||||
#define PRARCH_BAD_ARG 1 /* Bad argument */
|
||||
#define PRARCH_OUT_OF_MEMORY 2 /* Can't allocate enough space */
|
||||
#define PRARCH_BAD_REGEX 3 /* Bad regular expression */
|
||||
#define PRARCH_DONT_HAVE_SITE 4 /* Can't find site file */
|
||||
#define PRARCH_CANT_OPEN_FILE 5 /* Can't open DB file */
|
||||
#define PRARCH_DB_ERROR 6 /* Database Error */
|
||||
#define PRARCH_CLEANUP 7 /* Cleanup failed */
|
||||
#define PRARCH_TOO_MANY 8 /* Too many matches */
|
||||
|
||||
|
||||
/* For constructing link attributes */
|
||||
#define A2PL_H_IP_ADDR 0x001
|
||||
#define A2PL_HOSTIP 0x001
|
||||
#define A2PL_H_OS_TYPE 0x002
|
||||
#define A2PL_H_TIMEZ 0x004
|
||||
#define A2PL_LK_LAST_MOD 0x020
|
||||
#define A2PL_LINK_COUNT 0x040
|
||||
#define A2PL_LINK_SZ 0x080
|
||||
#define A2PL_NATIVE_MODES 0x100
|
||||
#define A2PL_H_LAST_MOD 0x200
|
||||
#define A2PL_SITEDATE 0x200
|
||||
#define A2PL_UNIX_MODES 0x800
|
||||
|
||||
#define A2PL_ROOT 0x10000
|
||||
#define A2PL_ARDIR 0x40000
|
||||
|
||||
/* Structure definitions */
|
||||
struct site_out_t{
|
||||
struct in_addr site_ipaddr;
|
||||
db_date site_mod_time;
|
||||
char site_name[MAX_HOST_LEN];
|
||||
char site_update[SMALL_STR_LEN];
|
||||
char site_path[MAX_FILE_NAME];
|
||||
site_rec site_ent;
|
||||
};
|
||||
|
||||
typedef struct site_out_t site_out;
|
||||
|
||||
char *get_host_file_name();
|
||||
struct vlink *atoplink();
|
||||
293
prospero/lib/psrv/archie2/prarch_host.c
Normal file
293
prospero/lib/psrv/archie2/prarch_host.c
Normal file
@@ -0,0 +1,293 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
/* Archie definitions */
|
||||
#include <ndbm.h>
|
||||
#include <defines.h>
|
||||
#include <archie_defs.h>
|
||||
#include <structs.h>
|
||||
#include <database.h>
|
||||
#include <error.h>
|
||||
|
||||
#include "prarch.h"
|
||||
|
||||
#include <pfs.h>
|
||||
#include <perrno.h>
|
||||
#include <plog.h>
|
||||
#include <pmachine.h> /* For bzero */
|
||||
#define TOO_MANY_HOSTS 200
|
||||
|
||||
/*
|
||||
* prarch_host - Search host for contents of directory
|
||||
*
|
||||
* ARGS: site_name - name of host for which search is to be made
|
||||
* dirname - name of directory to return (NULL if root )
|
||||
* vd - pointer to directory to be filled in
|
||||
* archiedir - flag - directory links should be to archie
|
||||
*/
|
||||
int prarch_host(char *site_name, /* Name of host to be searched */
|
||||
char *dirname, /* Name of directory to be listed */
|
||||
VDIR vd, /* Directory to be filled in */
|
||||
int flags) /* Flags: Which attributes to use */
|
||||
{
|
||||
site_out so;
|
||||
char *host_name;
|
||||
char result[MAX_STRING_LEN];
|
||||
char date_str[SMALL_STR_LEN];
|
||||
char hostip_str[SMALL_STR_LEN];
|
||||
site_rec curr_site_rec;
|
||||
site_rec rootrec;
|
||||
int recno;
|
||||
int last_parent = -1;
|
||||
site_rec *site_ptr;
|
||||
int correct_dir = 0; /* Scanning the requested directory */
|
||||
int loopcount = 0; /* To decide when to call ardp_accept */
|
||||
VLINK clink; /* Current link */
|
||||
FILE *fp;
|
||||
|
||||
caddr_t site_begin;
|
||||
site_rec *site_end;
|
||||
struct stat statbuf;
|
||||
|
||||
if(!dirname) { /* Find host directory */
|
||||
char hosttemp[200];
|
||||
char *p = hosttemp;
|
||||
char *htemp = site_name;
|
||||
char tmp1[MAX_STRING_LEN];
|
||||
char tmp2[MAX_STRING_LEN];
|
||||
char dirlinkname[MAXPATHLEN];
|
||||
char **test;
|
||||
int i;
|
||||
|
||||
/* If a single wildcard, then return nothing */
|
||||
if(strcmp(site_name,"*") == 0) return(PRARCH_SUCCESS);
|
||||
|
||||
/* If regular expressions or wildcards */
|
||||
if((index(site_name,'(') || index(site_name,'?') ||
|
||||
index(site_name,'*'))) {
|
||||
|
||||
if((*htemp == '(') && (*(htemp + strlen(htemp)-1) == ')')) {
|
||||
strncpy(hosttemp,htemp+1,sizeof(hosttemp));
|
||||
hosttemp[sizeof(hosttemp)-1] = '\0';
|
||||
hosttemp[strlen(hosttemp)-1] = '\0';
|
||||
}
|
||||
else if(htemp) {
|
||||
*p++ = '^';
|
||||
while(*htemp) {
|
||||
if(*htemp == '*') {*(p++)='.'; *(p++) = *(htemp++);}
|
||||
else if(*htemp == '?') {*(p++)='.';htemp++;}
|
||||
else if(*htemp == '.') {*(p++)='\\';*(p++)='.';htemp++;}
|
||||
else if(*htemp == '[') {*(p++)='\\';*(p++)='[';htemp++;}
|
||||
else if(*htemp == '$') {*(p++)='\\';*(p++)='$';htemp++;}
|
||||
else if(*htemp == '^') {*(p++)='\\';*(p++)='^';htemp++;}
|
||||
else if(*htemp == '\\') {*(p++)='\\';*(p++)='\\';htemp++;}
|
||||
else *(p++) = *(htemp++);
|
||||
}
|
||||
*p++ = '$';
|
||||
*p++ = '\0';
|
||||
}
|
||||
|
||||
test = (char **) find_sites(hosttemp,&i,tmp1);
|
||||
if((int) test == BAD_REGEX) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"archie find_sites(): bad regular expression");
|
||||
return(PRARCH_BAD_REGEX);
|
||||
}
|
||||
if((int) test == DB_HBYADDR_ERROR) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"archie find_sites() hostbyaddr error");
|
||||
return(PRARCH_DB_ERROR);
|
||||
}
|
||||
if((int) test == BAD_MALLOC) {
|
||||
p_err_string = qsprintf_stcopyyr(p_err_string,
|
||||
"archie find_sites() out of memory");
|
||||
return(PRARCH_OUT_OF_MEMORY);
|
||||
}
|
||||
if(i > TOO_MANY_HOSTS) {
|
||||
free(test[i]);
|
||||
return(PRARCH_TOO_MANY);
|
||||
}
|
||||
else while( i-- ) {
|
||||
get_site_file(test[i],tmp2);
|
||||
if((fp = fopen(db_file(tmp2),"r")) != (FILE *) NULL) {
|
||||
|
||||
if(fstat(fileno(fp),&statbuf) == -1) {
|
||||
plog(L_DB_ERROR,NOREQ,"can't stat site file %s",db_file(tmp2));
|
||||
fclose(fp);
|
||||
continue;
|
||||
}
|
||||
|
||||
site_begin = mmap(0,statbuf.st_size,PROT_READ,MAP_SHARED,
|
||||
fileno(fp),0);
|
||||
|
||||
if((site_begin == (caddr_t)-1) || (site_begin == (caddr_t)NULL)){
|
||||
plog(L_DB_ERROR,NOREQ,"can't map site file %s",db_file(tmp2));
|
||||
fclose(fp);
|
||||
continue;
|
||||
}
|
||||
|
||||
bzero(&so,sizeof(so));
|
||||
if(print_sinfo(site_begin,so.site_name,hostip_str,date_str) != 0) {
|
||||
plog(L_DB_ERROR,NOREQ,"can't obtain site info from %s",
|
||||
db_file(tmp2));
|
||||
munmap(site_begin,statbuf.st_size);
|
||||
fclose(fp);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The root is the first record in the site after site info */
|
||||
rootrec = *(((site_rec *) site_begin));
|
||||
|
||||
bcopy(&rootrec,&(so.site_ent),sizeof(rootrec));
|
||||
bcopy(&(rootrec.in_or_addr.ipaddress),&(so.site_ipaddr),
|
||||
sizeof(so.site_ipaddr));
|
||||
bcopy(&(rootrec.mod_time),&(so.site_mod_time),
|
||||
sizeof(so.site_mod_time));
|
||||
clink = atoplink(&so,flags|A2PL_ARDIR|A2PL_ROOT);
|
||||
if(clink) vl_insert(clink,vd,VLI_NOSORT);
|
||||
|
||||
if(munmap(site_begin,statbuf.st_size) == -1) {
|
||||
plog(L_DB_ERROR,NOREQ,"archie munmap() failed on %s",db_file(tmp2));
|
||||
return(PRARCH_CLEANUP);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
free(test[i]);
|
||||
}
|
||||
else plog(L_DB_ERROR,NOREQ,"fopen failed for %s",db_file(tmp2));
|
||||
}
|
||||
return(PRARCH_SUCCESS);
|
||||
}
|
||||
/* No regular expression or wildcards */
|
||||
else {
|
||||
if(( host_name = get_host_file_name( site_name )) == (char *)NULL )
|
||||
return(PRARCH_SUCCESS); /* No match */
|
||||
|
||||
if((fp = fopen(host_name,"r")) != (FILE *) NULL) {
|
||||
|
||||
if(fstat(fileno(fp),&statbuf) == -1) {
|
||||
plog(L_DB_ERROR,NOREQ,"can't stat site file %s",db_file(tmp2));
|
||||
fclose(fp);
|
||||
return(PRARCH_CANT_OPEN_FILE);
|
||||
}
|
||||
|
||||
site_begin = mmap(0,statbuf.st_size,PROT_READ,MAP_SHARED,
|
||||
fileno(fp),0);
|
||||
|
||||
if((site_begin == (caddr_t)-1) || (site_begin == (caddr_t)NULL)){
|
||||
plog(L_DB_ERROR,NOREQ,"can't map site file %s",db_file(tmp2));
|
||||
fclose(fp);
|
||||
return(PRARCH_CANT_OPEN_FILE);
|
||||
}
|
||||
|
||||
bzero(&so,sizeof(so));
|
||||
if(print_sinfo(site_begin,so.site_name,hostip_str,date_str) != 0) {
|
||||
plog(L_DB_ERROR,NOREQ,"can't obtain site info from %s",
|
||||
db_file(tmp2));
|
||||
munmap(site_begin,statbuf.st_size);
|
||||
fclose(fp);
|
||||
return(PRARCH_DB_ERROR);
|
||||
}
|
||||
|
||||
/* The root is the first record in the site after site info */
|
||||
rootrec = *(((site_rec *) site_begin));
|
||||
bcopy(&rootrec,&(so.site_ent),sizeof(rootrec));
|
||||
bcopy(&(rootrec.in_or_addr.ipaddress),&(so.site_ipaddr),
|
||||
sizeof(so.site_ipaddr));
|
||||
bcopy(&(rootrec.mod_time),&(so.site_mod_time),
|
||||
sizeof(so.site_mod_time));
|
||||
clink = atoplink(&so,flags|A2PL_ARDIR|A2PL_ROOT);
|
||||
if(clink) {
|
||||
clink->name = stcopyr(site_name,clink->name);
|
||||
vl_insert(clink,vd,VLI_NOSORT);
|
||||
}
|
||||
|
||||
if(munmap(site_begin,statbuf.st_size) == -1) {
|
||||
plog(L_DB_ERROR,NOREQ,"archie munmap() failed on %s",db_file(tmp2));
|
||||
return(PRARCH_CLEANUP);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return(PRARCH_SUCCESS);
|
||||
}
|
||||
else return(PRARCH_CANT_OPEN_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
bzero(&so,sizeof(so));
|
||||
|
||||
if(( host_name = get_host_file_name( site_name )) == (char *)NULL )
|
||||
return(PRARCH_DONT_HAVE_SITE);
|
||||
|
||||
if((fp = fopen(host_name, "r")) == NULL)
|
||||
return(PRARCH_CANT_OPEN_FILE);
|
||||
|
||||
if(fstat(fileno(fp),&statbuf) == -1) {
|
||||
fclose(fp);
|
||||
return(PRARCH_CANT_OPEN_FILE);
|
||||
}
|
||||
|
||||
site_begin = mmap(0,statbuf.st_size,PROT_READ,MAP_SHARED,
|
||||
fileno(fp),0);
|
||||
|
||||
if((site_begin == (caddr_t) -1) || (site_begin == (caddr_t) NULL)) {
|
||||
fclose(fp);
|
||||
return(PRARCH_CANT_OPEN_FILE);
|
||||
}
|
||||
|
||||
if(print_sinfo(site_begin,so.site_name,hostip_str,date_str) != 0) {
|
||||
munmap(site_begin,statbuf.st_size);
|
||||
fclose(fp);
|
||||
return(PRARCH_DB_ERROR);
|
||||
}
|
||||
|
||||
site_end = (site_rec *)site_begin + statbuf.st_size / sizeof(site_rec);
|
||||
|
||||
rootrec = *(((site_rec *) site_begin));
|
||||
|
||||
bcopy(&(rootrec.in_or_addr.ipaddress),&(so.site_ipaddr),
|
||||
sizeof(so.site_ipaddr));
|
||||
bcopy(&(rootrec.mod_time),&(so.site_mod_time),
|
||||
sizeof(so.site_mod_time));
|
||||
|
||||
for(recno = 1;(site_ptr = (site_rec *)site_begin + recno) < site_end;
|
||||
recno++){
|
||||
|
||||
if((loopcount++ & 0x3ff) == 0) ardp_accept();
|
||||
|
||||
curr_site_rec = *site_ptr;
|
||||
|
||||
if(last_parent != curr_site_rec.parent_ind){
|
||||
|
||||
if(find_ancestors(site_begin, recno, result) != 0) {
|
||||
munmap(site_begin,statbuf.st_size);
|
||||
fclose(fp);
|
||||
return(PRARCH_DB_ERROR);
|
||||
}
|
||||
|
||||
last_parent = curr_site_rec.parent_ind;
|
||||
|
||||
/* Don't want to check the leading / */
|
||||
if(strcmp(dirname,result+1) == 0) {
|
||||
correct_dir++;
|
||||
strcpy(so.site_path,result);
|
||||
}
|
||||
else if(correct_dir) break;
|
||||
}
|
||||
bcopy(&curr_site_rec,&(so.site_ent),sizeof(curr_site_rec));
|
||||
if(correct_dir) {
|
||||
if((loopcount & 0x7f) == 0) ardp_accept();
|
||||
clink = atoplink(&so,flags);
|
||||
if(clink) vl_insert(clink,vd,VLI_NOSORT);
|
||||
}
|
||||
}
|
||||
|
||||
munmap(site_begin,statbuf.st_size);
|
||||
fclose(fp);
|
||||
return(PRARCH_SUCCESS);
|
||||
}
|
||||
637
prospero/lib/psrv/archie2/prarch_match.c
Normal file
637
prospero/lib/psrv/archie2/prarch_match.c
Normal file
@@ -0,0 +1,637 @@
|
||||
/*XXX Note to make this thread safe, need to mutex re_comp and re_exec */
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h> /* For malloc and free */
|
||||
|
||||
#define _toupper(c) ((c)-'a'+'A')
|
||||
|
||||
#ifdef MMAP
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
/* Archie definitions */
|
||||
#include <ndbm.h>
|
||||
#include <defines.h>
|
||||
#include <structs.h>
|
||||
#include <database.h>
|
||||
#include <error.h>
|
||||
|
||||
#include "prarch.h"
|
||||
|
||||
#include <ardp.h>
|
||||
#include <pfs.h>
|
||||
#include <perrno.h>
|
||||
#include <plog.h>
|
||||
|
||||
VLINK atoplink();
|
||||
VLINK atoqlink();
|
||||
|
||||
char *re_comp();
|
||||
char *make_lcase();
|
||||
int get_match_list();
|
||||
|
||||
extern char *strings_begin;
|
||||
extern long strings_table_size;
|
||||
extern DBM *fast_strings;
|
||||
|
||||
/* So we can adjust our cache policy based on queue length */
|
||||
extern int pQlen;
|
||||
|
||||
static char lowertable[256] = {
|
||||
'\000','\001','\002','\003','\004','\005','\006','\007',
|
||||
'\010','\011','\012','\013','\014','\015','\016','\017',
|
||||
'\020','\021','\022','\023','\024','\025','\026','\027',
|
||||
'\030','\031','\032','\033','\034','\035','\036','\037',
|
||||
' ','!','"','#','$','%','&','\'',
|
||||
'(',')','*','+',',','-','.','/',
|
||||
'0','1','2','3','4','5','6','7',
|
||||
'8','9',':',';','<','=','>','?',
|
||||
'@','a','b','c','d','e','f','g',
|
||||
'h','i','j','k','l','m','n','o',
|
||||
'p','q','r','s','t','u','v','w',
|
||||
'x','y','z','[','\\',']','^','_',
|
||||
'`','a','b','c','d','e','f','g',
|
||||
'h','i','j','k','l','m','n','o',
|
||||
'p','q','r','s','t','u','v','w',
|
||||
'x','y','z','{','|','}','~','\177',
|
||||
'\200','\201','\202','\203','\204','\205','\206','\207',
|
||||
'\210','\211','\212','\213','\214','\215','\216','\217',
|
||||
'\220','\221','\222','\223','\224','\225','\226','\227',
|
||||
'\230','\231','\232','\233','\234','\235','\236','\237',
|
||||
'\240','\241','\242','\243','\244','\245','\246','\247',
|
||||
'\250','\251','\252','\253','\254','\255','\256','\257',
|
||||
'\260','\261','\262','\263','\264','\265','\266','\267',
|
||||
'\270','\271','\272','\273','\274','\275','\276','\277',
|
||||
'\300','\301','\302','\303','\304','\305','\306','\307',
|
||||
'\310','\311','\312','\313','\314','\315','\316','\317',
|
||||
'\320','\321','\322','\323','\324','\325','\326','\327',
|
||||
'\330','\331','\332','\333','\334','\335','\336','\337',
|
||||
'\340','\341','\342','\343','\344','\345','\346','\347',
|
||||
'\350','\351','\352','\353','\354','\355','\356','\357',
|
||||
'\360','\361','\362','\363','\364','\365','\366','\367',
|
||||
'\370','\371','\372','\373','\374','\375','\376','\377'};
|
||||
|
||||
#define MATCH_CACHE_SIZE 15
|
||||
|
||||
struct match_cache {
|
||||
char *arg; /* Matched regular expression */
|
||||
int max_hits; /* Maximum matchess <0 = found all */
|
||||
int offset; /* Offset */
|
||||
search_sel search_type; /* Search method (the one used) */
|
||||
search_sel req_type; /* Requested method */
|
||||
VLINK matches; /* Matches */
|
||||
VLINK more; /* Additional matches */
|
||||
int flags; /* Flags: for link attributes */
|
||||
struct match_cache *next; /* Next entry in cache */
|
||||
};
|
||||
|
||||
static struct match_cache *mcache = NULL;
|
||||
|
||||
static int cachecount = 0;
|
||||
|
||||
/*
|
||||
* prarch_match - Search archie database for specified file
|
||||
*
|
||||
* PRARCH_MATCH searches the archie database and returns
|
||||
* a list of files matching the provided regular expression
|
||||
*
|
||||
* ARGS: program_name - regular expression for files to match
|
||||
* max_hits - maximum number of entries to return (max hits)
|
||||
* offset - start the search after this many hits
|
||||
* search_type - search method
|
||||
* vd - pointer to directory to be filled in
|
||||
* archiedir - flag - directory links should be to archie
|
||||
* onlystrings - flag - only return strings, not matches
|
||||
*
|
||||
* Search method is one of: S_FULL_REGEX
|
||||
* S_EXACT
|
||||
* S_SUB_NCASE_STR
|
||||
* S_SUB_CASE_STR
|
||||
*/
|
||||
int prarch_match(char *program_name, /* Regular expression to be matched */
|
||||
int max_hits, /* Maximum number of entries to rtrn */
|
||||
int max_match, /* Maximum number of unique strings */
|
||||
int max_hitspm, /* Maximum hits per match */
|
||||
int offset, /* Skip # matches before starting */
|
||||
search_sel search_type, /* Search method */
|
||||
VDIR vd, /* Directory to be filled in */
|
||||
int flags, /* Flag for link attributes */
|
||||
int onlystrings) /* Only return matching strings */
|
||||
{
|
||||
/*
|
||||
* Search the database for the string specified by 'program_name'. Use the
|
||||
* fast dbm strings database if 'is_exact' is set, otherwise search through
|
||||
* the strings table. Stop searching after all matches have been found, or
|
||||
* 'max_hits' matches have been found, whichever comes first.
|
||||
*/
|
||||
char s_string[MAX_STRING_LEN];
|
||||
char *strings_ptr;
|
||||
char *strings_curr_off;
|
||||
strings_header str_head;
|
||||
datum search_key, key_value;
|
||||
search_sel new_search_type = S_EXACT; /* Alternate search method */
|
||||
search_sel or_search_type = search_type; /* Original search method */
|
||||
int nocase = 0;
|
||||
int hits_exceeded = FALSE; /* should be boolean? */
|
||||
char *strings_end;
|
||||
int match_number;
|
||||
int patlen;
|
||||
site_out **site_outptr;
|
||||
site_out site_outrec;
|
||||
int i;
|
||||
VLINK cur_link;
|
||||
int loopcount = 0;
|
||||
int retval;
|
||||
int match_rem = max_match;
|
||||
|
||||
if(!program_name || !(*program_name)) return(PRARCH_BAD_ARG);
|
||||
|
||||
if((0 < max_hits) && (max_hits < match_rem)) match_rem = max_hits;
|
||||
if((0 < max_hits) && (max_hits < max_hitspm)) max_hitspm = max_hits;
|
||||
|
||||
strcpy(s_string, program_name);
|
||||
|
||||
/* See if we can use a less expensive search method */
|
||||
if((search_type == S_FULL_REGEX) || (search_type == S_E_FULL_REGEX)) {
|
||||
/* Regex search assumes wildcards on both ends, so remove from string */
|
||||
if(strncmp(program_name,".*",2) == 0)
|
||||
strcpy(s_string, program_name+2);
|
||||
if((i = strlen(s_string)) >= 2) {
|
||||
if(strcmp(s_string+i-2,".*") == 0)
|
||||
*(s_string+i-2) = '\0';
|
||||
}
|
||||
|
||||
/* If no special characters, then fall back to substring search */
|
||||
if((search_type == S_FULL_REGEX) &&
|
||||
(strpbrk(s_string,"\\^$.,[]<>*+?|(){}/") == NULL))
|
||||
or_search_type = search_type = S_SUB_CASE_STR;
|
||||
else if((search_type == S_E_FULL_REGEX) &&
|
||||
(strpbrk(s_string,"\\^$.,[]<>*+?|(){}/") == NULL))
|
||||
or_search_type = search_type = S_E_SUB_CASE_STR;
|
||||
}
|
||||
|
||||
/* The caching code assumes we are handed an empty directory */
|
||||
/* if not, return an error for now. Eventually we will get */
|
||||
/* rid of that assumption */
|
||||
if(vd->links) {
|
||||
plog(L_DIR_ERR, NOREQ, "Prarch_match handed non empty dir",0);
|
||||
return(PRARCH_BAD_ARG);
|
||||
}
|
||||
|
||||
if(!onlystrings && (check_cache(s_string,max_hits,offset,search_type,
|
||||
flags,&(vd->links)) == TRUE)) {
|
||||
plog(L_DB_INFO, NOREQ, "Responding with cached data",0);
|
||||
return(PSUCCESS);
|
||||
}
|
||||
|
||||
site_outptr = (site_out **) malloc((unsigned)(sizeof(site_out) *
|
||||
(max_hits + offset)));
|
||||
if(!site_outptr) return(PRARCH_OUT_OF_MEMORY);
|
||||
|
||||
startsearch:
|
||||
|
||||
strings_ptr = strings_begin;
|
||||
strings_end = strings_begin + (int) strings_table_size;
|
||||
|
||||
match_number = 0;
|
||||
|
||||
switch(search_type){
|
||||
|
||||
case S_E_SUB_CASE_STR:
|
||||
new_search_type = S_SUB_CASE_STR;
|
||||
goto exact_match;
|
||||
case S_E_SUB_NCASE_STR:
|
||||
new_search_type = S_SUB_NCASE_STR;
|
||||
goto exact_match;
|
||||
case S_E_FULL_REGEX:
|
||||
new_search_type = S_FULL_REGEX;
|
||||
exact_match:
|
||||
case S_EXACT:
|
||||
|
||||
search_key.dptr = s_string;
|
||||
search_key.dsize = strlen(s_string) + 1;
|
||||
|
||||
ardp_accept();
|
||||
key_value = dbm_fetch(fast_strings, search_key) ;
|
||||
|
||||
if(key_value.dptr != (char *)NULL){ /* string in table */
|
||||
|
||||
int string_pos;
|
||||
|
||||
bcopy(key_value.dptr,(char *)&string_pos, key_value.dsize);
|
||||
|
||||
strings_ptr += string_pos;
|
||||
|
||||
bcopy(strings_ptr,(char *)&str_head,sizeof(strings_header));
|
||||
|
||||
ardp_accept();
|
||||
|
||||
if(onlystrings) {
|
||||
cur_link = atoqlink(strings_ptr,max_hits,max_match,max_hitspm);
|
||||
if(cur_link) vl_insert(cur_link,vd,VLI_NOSORT);
|
||||
if(--match_rem <= 0) {
|
||||
hits_exceeded = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(str_head.filet_index != -1) {
|
||||
retval = get_match_list((int) str_head.filet_index, max_hitspm,
|
||||
&match_number, site_outptr, FALSE);
|
||||
|
||||
if((retval != A_OK) && (retval != HITS_EXCEEDED)) {
|
||||
plog(L_DB_ERROR, NOREQ,"get_match_list failed (%d)",retval,0);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if( match_number >= max_hits + offset ){
|
||||
hits_exceeded = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (search_type != S_EXACT) { /* Not found - but try other method */
|
||||
search_type = new_search_type;
|
||||
goto startsearch;
|
||||
}
|
||||
break;
|
||||
|
||||
case S_FULL_REGEX:
|
||||
|
||||
if(re_comp(s_string) != (char *)NULL){
|
||||
return (PRARCH_BAD_REGEX);
|
||||
}
|
||||
|
||||
str_head.str_len = -1;
|
||||
|
||||
ardp_accept();
|
||||
|
||||
while((strings_curr_off = strings_ptr + str_head.str_len + 1) < strings_end){
|
||||
|
||||
if((loopcount++ & 0x7ff) == 0) ardp_accept();
|
||||
|
||||
strings_ptr = strings_curr_off;
|
||||
|
||||
bcopy(strings_ptr,(char *)&str_head,sizeof(strings_header));
|
||||
|
||||
strings_ptr += sizeof(strings_header);
|
||||
|
||||
if(re_exec( strings_ptr ) == 1 ){ /* TRUE */
|
||||
strings_curr_off = strings_ptr;
|
||||
|
||||
ardp_accept();
|
||||
|
||||
if(onlystrings) {
|
||||
if(strstr(strings_ptr," -> ") == NULL) { /* No broken strings */
|
||||
cur_link = atoqlink(strings_ptr,max_hits,max_match,max_hitspm);
|
||||
if(cur_link) vl_insert(cur_link,vd,VLI_NOSORT);
|
||||
if(--match_rem <= 0) {
|
||||
hits_exceeded = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(str_head.filet_index != -1){
|
||||
retval = get_match_list((int) str_head.filet_index, max_hitspm,
|
||||
&match_number, site_outptr, FALSE);
|
||||
|
||||
if((retval != A_OK) && (retval != HITS_EXCEEDED)) {
|
||||
plog(L_DB_ERROR, NOREQ,"get_match_list failed (%d)",retval,0);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if( match_number >= max_hits + offset ){
|
||||
hits_exceeded = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
#define TABLESIZE 256
|
||||
|
||||
case S_SUB_NCASE_STR:
|
||||
nocase++;
|
||||
case S_SUB_CASE_STR: {
|
||||
char pattern[MAX_STRING_LEN];
|
||||
int skiptab[TABLESIZE];
|
||||
register int pc, tc;
|
||||
register int local_loopcount = 0xfff;
|
||||
char *bp1;
|
||||
int skip;
|
||||
int plen;
|
||||
int plen_1;
|
||||
int tlen;
|
||||
unsigned char tchar;
|
||||
|
||||
plen = strlen(s_string);
|
||||
plen_1 = plen -1;
|
||||
|
||||
/* Old code (replaced by inline code taken from initskip) */
|
||||
/* patlen = strlen(s_string ) ; */
|
||||
/* initskip(s_string, patlen, search_type == S_SUB_NCASE_STR) ; */
|
||||
|
||||
if(nocase) {
|
||||
for(pc = 0; s_string[pc]; pc++)
|
||||
pattern[pc] = lowertable[s_string[pc]];
|
||||
pattern[pc] = '\0';
|
||||
}
|
||||
else strcpy(pattern,s_string);
|
||||
|
||||
for( i = 0 ; i < TABLESIZE ; i++ )
|
||||
skiptab[ i ] = plen;
|
||||
|
||||
/* Note that we want both ucase and lcase in this table if nocase */
|
||||
for( i = 0, tchar = *pattern; i < plen ; i++, tchar = *(pattern + i)) {
|
||||
skiptab[tchar] = plen - 1 - i;
|
||||
if(nocase && islower(tchar))
|
||||
skiptab[_toupper(tchar)] = plen - 1 - i;
|
||||
}
|
||||
|
||||
/* Begin heavily optimized and non portable code */
|
||||
|
||||
/* Note that we are depending on str_head being 8 bytes */
|
||||
tlen = -9; /* str_head.str_len */
|
||||
|
||||
strings_curr_off = strings_ptr;
|
||||
|
||||
while((strings_curr_off += tlen + 9) < strings_end) {
|
||||
if(--local_loopcount == 0) {
|
||||
ardp_accept();
|
||||
local_loopcount = 0xfff;
|
||||
}
|
||||
|
||||
strings_ptr = strings_curr_off;
|
||||
|
||||
/* This is a kludge, non-portable, but it eliminates a pr call */
|
||||
/* Note that the size is 8 on suns. Is there a better way? */
|
||||
/* bcopy(strings_ptr,(char *)&str_head,sizeof(strings_header)); */
|
||||
bp1 = (char *) &str_head;
|
||||
/* The copying of the file index is done only on a match */
|
||||
bp1[4] = strings_ptr[4]; bp1[5] = strings_ptr[5];
|
||||
/* bp1[6] = strings_ptr[6]; bp1[7] = strings_ptr[7]; */
|
||||
|
||||
tlen = (unsigned short) str_head.str_len;
|
||||
|
||||
/* To catch database corruption, this is a sanity check */
|
||||
if((tlen < 0) || (tlen > MAX_STRING_LEN)) {
|
||||
plog(L_DB_ERROR, NOREQ,"Database corrupt: string length out of bounds",0);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Old code (replaced by inline code taken from strfind) */
|
||||
/* if(strfind(strings_ptr,str_head.str_len)) */
|
||||
|
||||
if( tlen <= plen_1 ) continue;
|
||||
pc = tc = plen_1;
|
||||
|
||||
strings_ptr += 8;
|
||||
|
||||
/* Moved the nocase test outside the inner loop for performace */
|
||||
/* Clauses are identical except for the first if */
|
||||
if(nocase) do {
|
||||
tchar = strings_ptr[tc];
|
||||
|
||||
/* improve efficiency of this test */
|
||||
if(lowertable[tchar] == pattern[pc]) {--pc; --tc;}
|
||||
else {
|
||||
skip = skiptab[tchar] ;
|
||||
tc += (skip < plen_1 - pc) ? plen : skip ;
|
||||
pc = plen_1 ;
|
||||
}
|
||||
} while( pc >= 0 && tc < tlen ) ;
|
||||
else /* (!nocase) */ do {
|
||||
tchar = strings_ptr[tc];
|
||||
|
||||
/* improve efficiency of this test */
|
||||
if(tchar == pattern[pc]) {--pc; --tc;}
|
||||
else {
|
||||
skip = skiptab[tchar] ;
|
||||
tc += (skip < plen_1 - pc) ? plen : skip ;
|
||||
pc = plen_1 ;
|
||||
}
|
||||
} while( pc >= 0 && tc < tlen ) ;
|
||||
|
||||
if(pc >= 0) continue;
|
||||
|
||||
/* We have a match */
|
||||
|
||||
/* Finish copying str_head - strings_curr_off */
|
||||
/* is old strings_ptr. */
|
||||
bp1[0] = strings_curr_off[0]; bp1[1] = strings_curr_off[1];
|
||||
bp1[2] = strings_curr_off[2]; bp1[3] = strings_curr_off[3];
|
||||
|
||||
/* End heavily optimized and non portable code */
|
||||
|
||||
ardp_accept();
|
||||
|
||||
if(onlystrings) {
|
||||
if(strstr(strings_ptr," -> ") == NULL) { /* No broken strings */
|
||||
cur_link = atoqlink(strings_ptr,max_hits,max_match,max_hitspm);
|
||||
if(cur_link) vl_insert(cur_link,vd,VLI_NOSORT);
|
||||
if(--match_rem <= 0) {
|
||||
hits_exceeded = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(str_head.filet_index != -1){
|
||||
retval = get_match_list((int) str_head.filet_index, max_hitspm,
|
||||
&match_number, site_outptr, FALSE);
|
||||
|
||||
if((retval != A_OK) && (retval != HITS_EXCEEDED)) {
|
||||
plog(L_DB_ERROR,NOREQ,"get_match_list failed (%d)",retval,0);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if( match_number >= max_hits + offset ) {
|
||||
hits_exceeded = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return(PRARCH_BAD_ARG);
|
||||
|
||||
cleanup:
|
||||
for(i = 0;i < match_number; i++) free((char *)site_outptr[i]);
|
||||
free((char *)site_outptr);
|
||||
return(PRARCH_DB_ERROR);
|
||||
}
|
||||
|
||||
for(i = 0;i < match_number; i++){
|
||||
if((i & 0x7f) == 0) ardp_accept();
|
||||
site_outrec = *site_outptr[i];
|
||||
if(i >= offset) {
|
||||
cur_link = atoplink(site_outrec,flags);
|
||||
if(cur_link) vl_insert(cur_link,vd,VLI_NOSORT);
|
||||
}
|
||||
free((char *)site_outptr[i]);
|
||||
}
|
||||
free((char *)site_outptr);
|
||||
|
||||
if(hits_exceeded) {
|
||||
/* Insert a continuation entry */
|
||||
}
|
||||
|
||||
if((search_type == S_EXACT) && (pQlen > (MATCH_CACHE_SIZE - 5)))
|
||||
return(PRARCH_SUCCESS);
|
||||
|
||||
if(!onlystrings)
|
||||
add_to_cache(vd->links,s_string, (hits_exceeded ? max_hits : -max_hits),
|
||||
offset,search_type,or_search_type,flags);
|
||||
|
||||
return(PRARCH_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/* Check for cached results */
|
||||
check_cache(arg,max_hits,offset,qtype,flags,linkpp)
|
||||
char *arg;
|
||||
int max_hits;
|
||||
int offset;
|
||||
search_sel qtype;
|
||||
int flags;
|
||||
VLINK *linkpp;
|
||||
{
|
||||
struct match_cache *cachep = mcache;
|
||||
struct match_cache *pcachep = NULL;
|
||||
VLINK tmp_link, cur_link;
|
||||
VLINK rest = NULL;
|
||||
VLINK next = NULL;
|
||||
int count = max_hits;
|
||||
|
||||
while(cachep) {
|
||||
if(((qtype == cachep->search_type)||(qtype == cachep->req_type))&&
|
||||
(cachep->offset == offset) &&
|
||||
/* All results are in cache - or enough to satisfy request */
|
||||
((cachep->max_hits < 0) || (max_hits <= cachep->max_hits)) &&
|
||||
(strcmp(cachep->arg,arg) == 0) &&
|
||||
(cachep->flags == flags)) {
|
||||
/* We have a match. Move to front of list */
|
||||
if(pcachep) {
|
||||
pcachep->next = cachep->next;
|
||||
cachep->next = mcache;
|
||||
mcache = cachep;
|
||||
}
|
||||
|
||||
/* We now have to clear the expanded bits or the links */
|
||||
/* returned in previous queries will not be returned */
|
||||
/* We also need to truncate the list of there are more */
|
||||
/* matches than requested */
|
||||
cur_link = cachep->matches;
|
||||
|
||||
/* IMPORTANT: This code assumes the list is one */
|
||||
/* dimensional, which is the case because we called */
|
||||
/* vl_insert with the VLI_NOSORT option */
|
||||
while(cur_link) {
|
||||
cur_link->expanded = FALSE;
|
||||
if((--count == 0) && cur_link->next) {
|
||||
/* truncate list */
|
||||
if(cachep->more) {
|
||||
cur_link->next->previous = cachep->more->previous;
|
||||
cachep->more->previous = cachep->matches->previous;
|
||||
cachep->matches->previous->next = cachep->more;
|
||||
}
|
||||
else {
|
||||
cachep->more = cur_link->next;
|
||||
cachep->more->previous = cachep->matches->previous;
|
||||
}
|
||||
cur_link->next = NULL;
|
||||
cachep->matches->previous = cur_link;
|
||||
}
|
||||
else if ((cur_link->next == NULL) && (count != 0) &&
|
||||
cachep->more) {
|
||||
/* Merge lists */
|
||||
cachep->matches->previous = cachep->more->previous;
|
||||
cur_link->next = cachep->more;
|
||||
cachep->more->previous = cur_link;
|
||||
cachep->more = NULL;
|
||||
}
|
||||
cur_link = cur_link->next;
|
||||
}
|
||||
*linkpp = cachep->matches;
|
||||
return(TRUE);
|
||||
}
|
||||
pcachep = cachep;
|
||||
cachep = cachep->next;
|
||||
}
|
||||
*linkpp = NULL;
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
|
||||
/* Cache the response for later use */
|
||||
add_to_cache(vl,arg,max_hits,offset,search_type,req_type,flags)
|
||||
VLINK vl;
|
||||
char *arg;
|
||||
int max_hits;
|
||||
int offset;
|
||||
search_sel search_type;
|
||||
search_sel req_type;
|
||||
int flags;
|
||||
{
|
||||
struct match_cache *newresults = NULL;
|
||||
struct match_cache *pcachep = NULL;
|
||||
|
||||
if(cachecount < MATCH_CACHE_SIZE) { /* Create a new entry */
|
||||
newresults = (struct match_cache *) malloc(sizeof(struct match_cache));
|
||||
cachecount++;
|
||||
newresults->next = mcache;
|
||||
mcache = newresults;
|
||||
newresults->arg = stcopy(arg);
|
||||
newresults->max_hits = max_hits;
|
||||
newresults->offset = offset;
|
||||
newresults->search_type = search_type;
|
||||
newresults->req_type = req_type;
|
||||
newresults->flags = flags;
|
||||
newresults->matches = NULL;
|
||||
newresults->more = NULL;
|
||||
}
|
||||
else { /* Use last entry - Assumes list has at least two entries */
|
||||
pcachep = mcache;
|
||||
while(pcachep->next) pcachep = pcachep->next;
|
||||
newresults = pcachep;
|
||||
|
||||
/* move to front of list */
|
||||
newresults->next = mcache;
|
||||
mcache = newresults;
|
||||
|
||||
/* Fix the last entry so we don't have a cycle */
|
||||
while(pcachep->next != newresults) pcachep = pcachep->next;
|
||||
pcachep->next = NULL;
|
||||
|
||||
/* Free the old results */
|
||||
if(newresults->matches) {
|
||||
newresults->matches->dontfree = FALSE;
|
||||
vllfree(newresults->matches);
|
||||
newresults->matches = NULL;
|
||||
}
|
||||
if(newresults->more) {
|
||||
newresults->more->dontfree = FALSE;
|
||||
vllfree(newresults->more);
|
||||
newresults->more = NULL;
|
||||
}
|
||||
|
||||
newresults->arg = stcopyr(arg,newresults->arg);
|
||||
newresults->max_hits = max_hits;
|
||||
newresults->offset = offset;
|
||||
newresults->search_type = search_type;
|
||||
newresults->req_type = req_type;
|
||||
newresults->flags = flags;
|
||||
}
|
||||
|
||||
/* Since we are caching the data. If there are any links, */
|
||||
/* note that they should not be freed when sent back */
|
||||
if(vl) vl->dontfree = TRUE;
|
||||
|
||||
newresults->matches = vl;
|
||||
}
|
||||
|
||||
|
||||
48
prospero/lib/psrv/at_delete.c
Normal file
48
prospero/lib/psrv/at_delete.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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> /* def of PATTRIB */
|
||||
#include <psrv.h> /* prototype for delete_matching_at() */
|
||||
#include <list_macros.h> /* EXTRACT_ITEM macro */
|
||||
#include <perrno.h>
|
||||
|
||||
/* Looks for an attribute equal to the key according to the equal function.
|
||||
Deletes & frees it.
|
||||
Returns: PSUCCESS or PFAILURE
|
||||
This is currently only used in ed_link_info.c and ed_obj_info.c
|
||||
*/
|
||||
int
|
||||
delete_matching_at(PATTRIB key, PATTRIB *headp, int (*equal)(PATTRIB, PATTRIB))
|
||||
{
|
||||
/* ick - this was "index" which is defined as a macro */
|
||||
PATTRIB ind;
|
||||
/* Find the match. */
|
||||
for (ind = *headp; ind; ind = ind->next) {
|
||||
if ((*equal)(key, ind)) {
|
||||
EXTRACT_ITEM(ind, (*headp));
|
||||
atfree(ind);
|
||||
return PSUCCESS;
|
||||
}
|
||||
}
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
|
||||
int
|
||||
delete_matching_fl(FILTER key, FILTER *headp)
|
||||
{
|
||||
FILTER ind;
|
||||
/* Find the match. */
|
||||
for (ind = *headp; ind; ind = ind->next) {
|
||||
if (equal_filters(key, ind)) {
|
||||
EXTRACT_ITEM(ind, (*headp));
|
||||
flfree(ind);
|
||||
return PSUCCESS;
|
||||
}
|
||||
}
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
468
prospero/lib/psrv/change_acl.c
Normal file
468
prospero/lib/psrv/change_acl.c
Normal file
@@ -0,0 +1,468 @@
|
||||
/*
|
||||
* Copyright (c) 1991 by the University of Washington
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <uw-copyright.h>.
|
||||
*/
|
||||
|
||||
#include <uw-copyright.h>
|
||||
|
||||
#include <string.h> /* No strings.h in SOLARIS */
|
||||
|
||||
#include <ardp.h>
|
||||
#include <pfs.h>
|
||||
#include <psite.h>
|
||||
#include <pprot.h>
|
||||
#include <plog.h>
|
||||
#include <pmachine.h>
|
||||
#include <psrv.h>
|
||||
#include <perrno.h>
|
||||
|
||||
static ACL find_aclent();
|
||||
char *addrights();
|
||||
char *subtractrights();
|
||||
extern ACL nulldir_acl;
|
||||
extern ACL nullobj_acl;
|
||||
extern ACL nullcont_acl;
|
||||
extern ACL nulllink_acl;
|
||||
|
||||
ACL aclcopy();
|
||||
|
||||
/*
|
||||
* change_acl - change access control list
|
||||
*
|
||||
* CHANGE_ACL change an access control list (*aclp)
|
||||
* by adding, deleting, or modifying the entry
|
||||
* specified by ae.
|
||||
*
|
||||
* ARGS: aclp - pointer to ACL pointer
|
||||
* ae - a pointer to a single ACL entry to be added or deleted
|
||||
* id - client identification
|
||||
* flags - information on the operation to be performed
|
||||
* diracl - the directory acl (to check if user has access)
|
||||
*
|
||||
* NOTE: This code which automatically adds administer (unless noself
|
||||
* is specified) can be used to upgrade < or [ privs to A. Dirsrv
|
||||
* include a check which sets noself when admister access is
|
||||
* allows by virtual of a [ or <.
|
||||
*/
|
||||
int
|
||||
change_acl(aclp,ae,req,flags,diracl)
|
||||
ACL *aclp; /* Pointer to ACL pointer */
|
||||
ACL ae; /* ACL entry to change */
|
||||
RREQ req; /* Client identification */
|
||||
int flags; /* Operation and flags */
|
||||
ACL diracl;/* Directory ACL */
|
||||
{
|
||||
ACL a = *aclp;
|
||||
ACL ws;
|
||||
ACL wacl;
|
||||
int operation;
|
||||
int nosystem;
|
||||
int noself;
|
||||
int dflag;
|
||||
int oflag;
|
||||
int adminflag;
|
||||
int acltype;
|
||||
int sca_code;
|
||||
PAUTH painfo = NULL;
|
||||
|
||||
operation = flags & EACL_OP;
|
||||
nosystem = flags & EACL_NOSYSTEM;
|
||||
noself = flags & EACL_NOSELF;
|
||||
dflag = !((flags&EACL_OTYPE)^EACL_DIRECTORY);
|
||||
oflag = !((flags&EACL_OTYPE)^EACL_OBJECT);
|
||||
acltype = (flags&EACL_OTYPE);
|
||||
|
||||
if(acltype == EACL_LINK) sca_code = SCA_LINK;
|
||||
else if(acltype == EACL_DIRECTORY) sca_code = SCA_DIRECTORY;
|
||||
else if(acltype == EACL_OBJECT) sca_code = SCA_OBJECT;
|
||||
else sca_code = SCA_MISC;
|
||||
|
||||
switch(operation) {
|
||||
|
||||
case EACL_DEFAULT:
|
||||
aclfree(a);
|
||||
acfree(ae);
|
||||
a = NULL;
|
||||
|
||||
/* If adminflag is clear it means that the user would not be */
|
||||
/* able to administer the new directory or link, and that */
|
||||
/* such a situation is undesirable */
|
||||
if(noself) adminflag = 1; /* Ok to clear admin rights for user */
|
||||
else if(acltype == EACL_LINK)
|
||||
adminflag = srv_check_acl(a,diracl,req,"a",sca_code,NULL,NULL);
|
||||
else adminflag = srv_check_acl(a,a,req,"A",sca_code,NULL,NULL);
|
||||
|
||||
if(acltype == EACL_LINK) a = aclcopy(nulllink_acl);
|
||||
else if(acltype == EACL_DIRECTORY) a = aclcopy(nulldir_acl);
|
||||
else if(acltype == EACL_OBJECT) a = aclcopy(nullobj_acl);
|
||||
|
||||
if(adminflag == 0) srv_add_client_to_acl("Aa",req,&(a),acltype);
|
||||
|
||||
*aclp = a;
|
||||
return(PSUCCESS);
|
||||
|
||||
case EACL_SET:
|
||||
aclfree(a);
|
||||
a = ae;
|
||||
|
||||
/* Unless the nosystem flag has been specified, add an */
|
||||
/* entry for the SYSTEM ACL */
|
||||
if(!nosystem) {
|
||||
wacl = acalloc();
|
||||
wacl->acetype = ACL_SYSTEM;
|
||||
a->next = wacl;
|
||||
wacl->previous = a;
|
||||
}
|
||||
|
||||
/* If adminflag is clear it means that the user would not be */
|
||||
/* able to administer the new directory or link, and that */
|
||||
/* such a situation is undesirable */
|
||||
if(noself) adminflag = 1; /* Ok to clear admin rights for user */
|
||||
else if(acltype == EACL_LINK)
|
||||
adminflag = srv_check_acl(a,diracl,req,"a",sca_code,NULL,NULL);
|
||||
else adminflag = srv_check_acl(a,a,req,"A",sca_code,NULL,NULL);
|
||||
|
||||
if(adminflag == 0) srv_add_client_to_acl("Aa",req,&(a),acltype);
|
||||
|
||||
*aclp = a;
|
||||
return(PSUCCESS);
|
||||
|
||||
eacl_insert:
|
||||
case EACL_INSERT:
|
||||
/* Must make sure all required fields are specified */
|
||||
/* Rights must be included for all but NONE, DEFAULT, */
|
||||
/* SYSTEM, and DIRECTORY, CONTAINER, and IETF_AAC */
|
||||
if(!((ae->rights && *(ae->rights))||(ae->acetype==ACL_NONE) ||
|
||||
(ae->acetype==ACL_DEFAULT)||(ae->acetype==ACL_SYSTEM) ||
|
||||
(ae->acetype==ACL_DIRECTORY)||(ae->acetype==ACL_CONTAINER)||
|
||||
(ae->acetype==ACL_IETF_AAC))) {
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
|
||||
/* No need to make sure the user can still access since */
|
||||
/* we are only adding rights. This ignores the case of */
|
||||
/* negative rights, but for now we assume that if the */
|
||||
/* user is specifying negative rights that they are */
|
||||
/* intended */
|
||||
|
||||
/* If NULL, first add entries for default values. We need */
|
||||
/* to leave them even if the user said not to add them */
|
||||
/* Since they were "already there". */
|
||||
if(!a) {
|
||||
if(acltype == EACL_LINK) a = aclcopy(nulllink_acl);
|
||||
else if(acltype == EACL_DIRECTORY) a = aclcopy(nulldir_acl);
|
||||
else if(acltype == EACL_OBJECT) a = aclcopy(nullobj_acl);
|
||||
}
|
||||
|
||||
/* Check to see if entry already exists */
|
||||
wacl = find_aclent(a,ae,1);
|
||||
if(wacl) {
|
||||
/* Already there */
|
||||
aclfree(ae);
|
||||
*aclp = a;
|
||||
return(PSUCCESS);
|
||||
}
|
||||
|
||||
/* New ACL antries are added a head of list. This means */
|
||||
/* that any negative rights specified will override any */
|
||||
/* rights that were already present. Additionaly, any */
|
||||
/* positive rights specified will override any negative */
|
||||
/* rights that already existed. */
|
||||
wacl = ae;
|
||||
while(wacl->next) wacl = wacl->next;
|
||||
wacl->next = a;
|
||||
a->previous = wacl;
|
||||
a = wacl;
|
||||
*aclp = a;
|
||||
return(PSUCCESS);
|
||||
|
||||
eacl_delete:
|
||||
case EACL_DELETE:
|
||||
/* If NULL, first add entries for default values. We need */
|
||||
/* to leave them even if the user said not to add them */
|
||||
/* Since they were "already there". */
|
||||
if(!a) {
|
||||
if(acltype == EACL_LINK) a = aclcopy(nulllink_acl);
|
||||
else if(acltype == EACL_DIRECTORY) a = aclcopy(nulldir_acl);
|
||||
else if(acltype == EACL_OBJECT) a = aclcopy(nullobj_acl);
|
||||
}
|
||||
|
||||
wacl = find_aclent(a,ae,1);
|
||||
if(!wacl) RETURNPFAILURE;
|
||||
if(a == wacl) {
|
||||
a = a->next;
|
||||
a->previous = NULL;
|
||||
acfree(wacl);
|
||||
}
|
||||
else {
|
||||
wacl->previous->next = wacl->next;
|
||||
if(wacl->next) wacl->next->previous = wacl->previous;
|
||||
acfree(wacl);
|
||||
}
|
||||
|
||||
if(noself) adminflag = 1; /* Ok to clear admin rights for user */
|
||||
else if(acltype == EACL_LINK)
|
||||
adminflag = srv_check_acl(a,diracl,req,"a",sca_code,NULL,NULL);
|
||||
else adminflag = srv_check_acl(a,a,req,"A",sca_code,NULL,NULL);
|
||||
|
||||
if(adminflag == 0) srv_add_client_to_acl("Aa",req,&(a),acltype);
|
||||
|
||||
/* If empty, must create a placeholder so that it */
|
||||
/* doesn't revert to nulldir */
|
||||
if(!a) {
|
||||
a = acalloc();
|
||||
a->acetype = ACL_NONE;
|
||||
}
|
||||
|
||||
acfree(ae);
|
||||
*aclp = a;
|
||||
return(PSUCCESS);
|
||||
|
||||
case EACL_ADD:
|
||||
/* If no rights specified must be insert */
|
||||
if(!(ae->rights)) goto eacl_insert;
|
||||
|
||||
/* Havn't figured out how to ADD ><][)(, so go to INSERT */
|
||||
if(index("><][)(",*(ae->rights))) goto eacl_insert;
|
||||
|
||||
/* If NULL, first add entries for default values. We need */
|
||||
/* to leave them even if the user said not to add them */
|
||||
/* Since they were "already there". */
|
||||
if(!a) {
|
||||
if(acltype == EACL_LINK) a = aclcopy(nulllink_acl);
|
||||
else if(acltype == EACL_DIRECTORY) a = aclcopy(nulldir_acl);
|
||||
else if(acltype == EACL_OBJECT) a = aclcopy(nullobj_acl);
|
||||
}
|
||||
|
||||
wacl = find_aclent(a,ae,0);
|
||||
|
||||
/* If no other entries, then go to insert */
|
||||
if(!wacl) goto eacl_insert;
|
||||
|
||||
/* Now we must add characters to wacl->rights for */
|
||||
/* any new characters in ae->rights */
|
||||
wacl->rights = stcopyr(addrights(wacl->rights,ae->rights),wacl->rights);
|
||||
acfree(ae);
|
||||
return(PSUCCESS);
|
||||
|
||||
case EACL_SUBTRACT:
|
||||
/* If no rights specified must delete */
|
||||
if(!(ae->rights)) goto eacl_delete;
|
||||
|
||||
/* Havn't figured out how to DELETE ><][)(, so go to DELETE */
|
||||
if(index("><][)(",*(ae->rights))) goto eacl_delete;
|
||||
|
||||
wacl = find_aclent(a,ae,0);
|
||||
|
||||
/* If no other entries, return error */
|
||||
if(!wacl) {
|
||||
acfree(ae);
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
|
||||
/* Now we must subtract characters from wacl->rights */
|
||||
/* for the characters in ae->rights */
|
||||
wacl->rights = subtractrights(wacl->rights,ae->rights);
|
||||
|
||||
/* If rights are now null, must delete the entry */
|
||||
if(!wacl->rights || !*(wacl->rights)) {
|
||||
if(wacl->previous) {
|
||||
wacl->previous->next = wacl->next;
|
||||
if(wacl->next) wacl->next->previous = wacl->previous;
|
||||
acfree(wacl);
|
||||
}
|
||||
else { /* It is at start of list */
|
||||
a = wacl->next;
|
||||
a->previous = NULL;
|
||||
acfree(wacl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure that user can fix his mistakes */
|
||||
if(noself) adminflag = 1; /* Ok to clear admin rights for user */
|
||||
else if(acltype == EACL_LINK)
|
||||
adminflag = srv_check_acl(a,diracl,req,"a",sca_code,NULL,NULL);
|
||||
else adminflag = srv_check_acl(a,a,req,"A",sca_code,NULL,NULL);
|
||||
|
||||
if(adminflag == 0) srv_add_client_to_acl("Aa",req,&(a),acltype);
|
||||
|
||||
/* If empty, must create a placeholder so that it */
|
||||
/* doesn't revert to nulldir */
|
||||
if(!a) {
|
||||
a = acalloc();
|
||||
a->acetype = ACL_NONE;
|
||||
}
|
||||
|
||||
acfree(ae);
|
||||
*aclp = a;
|
||||
return(PSUCCESS);
|
||||
}
|
||||
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function adds rights to the ACL for all principals identified
|
||||
* in the clients auth_info structure
|
||||
*/
|
||||
void
|
||||
srv_add_client_to_acl(char *rights, /* Rights to be added */
|
||||
RREQ req, /* Client identification */
|
||||
ACL *inoutacl,
|
||||
int flags) /* Directory ACL */
|
||||
{
|
||||
ACL nacl = NULL; /* new ACL entry */
|
||||
PAUTH painfo = req->auth_info;
|
||||
int times_thru = 0;
|
||||
while(painfo) {
|
||||
/* Defer the weakest method unless it's the only method */
|
||||
if((painfo->ainfo_type == PFSA_UNAUTHENTICATED) && !check_prvport(req))
|
||||
{painfo = painfo->next; continue;}
|
||||
nacl = acalloc();
|
||||
nacl->rights = stcopyr(rights,nacl->rights);
|
||||
|
||||
if(painfo->ainfo_type == PFSA_UNAUTHENTICATED) {
|
||||
TOKEN p = req->auth_info->principals;
|
||||
nacl->acetype = ACL_TRSTHOST;
|
||||
nacl->rights = stcopyr(rights,nacl->rights);
|
||||
|
||||
for ( ; p ; p = p->next) {
|
||||
nacl->principals = tkappend(NULL,nacl->principals);
|
||||
nacl->principals->previous->token =
|
||||
qsprintf_stcopyr(NULL,"%s@%s",p->token,
|
||||
inet_ntoa(req->peer_addr));
|
||||
}
|
||||
}
|
||||
else if(painfo->ainfo_type == PFSA_KERBEROS) {
|
||||
nacl->acetype = ACL_AUTHENT;
|
||||
nacl->atype = stcopy("KERBEROS");
|
||||
}
|
||||
else if(painfo->ainfo_type == PFSA_P_PASSWORD) {
|
||||
nacl->acetype = ACL_AUTHENT;
|
||||
nacl->atype = stcopy("P_PASSWORD");
|
||||
}
|
||||
|
||||
if(!(nacl->principals)) nacl->principals = tkcopy(painfo->principals);
|
||||
change_acl(inoutacl,nacl,req,EACL_ADD|flags,*inoutacl);
|
||||
|
||||
painfo = painfo->next;
|
||||
}
|
||||
/* OK, so ASRTHOST is the only method, I guess we'll use it */
|
||||
if(!nacl && req->auth_info &&
|
||||
(req->auth_info->ainfo_type == PFSA_UNAUTHENTICATED)) {
|
||||
TOKEN p = req->auth_info->principals;
|
||||
nacl = acalloc();
|
||||
nacl->acetype = ACL_ASRTHOST;
|
||||
nacl->rights = stcopyr(rights,nacl->rights);
|
||||
|
||||
for ( ; p ; p = p->next) {
|
||||
nacl->principals = tkappend(NULL,nacl->principals);
|
||||
nacl->principals->previous->token =
|
||||
qsprintf_stcopyr(NULL,"%s@%s",p->token,
|
||||
inet_ntoa(req->peer_addr));
|
||||
}
|
||||
change_acl(inoutacl,nacl,req,EACL_ADD|flags,*inoutacl);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find an ACL entry matching entry e in list a
|
||||
*
|
||||
* r is a flag which if set means the rights must match.
|
||||
* if clear, then the rights can be different.
|
||||
*/
|
||||
static ACL find_aclent(a,e,r)
|
||||
ACL a;
|
||||
ACL e;
|
||||
int r;
|
||||
{
|
||||
ACL w;
|
||||
|
||||
w = a;
|
||||
while(w) {
|
||||
if((w->acetype == e->acetype) &&
|
||||
((!(w->atype) && !(e->atype)) ||
|
||||
(w->atype && e->atype && (strcmp(w->atype,e->atype)==0))) &&
|
||||
((!(w->principals) && !(e->principals)) ||
|
||||
(w->principals && e->principals
|
||||
&& equal_sequences(w->principals,e->principals))) &&
|
||||
((!r && (!(w->rights) || !(index("><)(][",*(w->rights))))) ||
|
||||
(!(w->rights) && !(e->rights)) ||
|
||||
(w->rights && e->rights && (strcmp(w->rights,e->rights)==0))))
|
||||
return(w);
|
||||
w = w->next;
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Add rights returns a string containing those rights
|
||||
* that are in r or a. For known rights, addrights
|
||||
* will try to place them in canonical order.
|
||||
*
|
||||
* WARNING: Subtractrights frees r. It is expected that
|
||||
* the string pointed to by r will be replaced
|
||||
* by the string handed back.
|
||||
*/
|
||||
char *addrights(char *r, char *a)
|
||||
{
|
||||
/* Don't need to mutex; constant. */
|
||||
const char canonical[] = "-><)(][STUABVYLlRQGgrWMmwuDKzdEeIiPp";
|
||||
char *cp; /* index variable */
|
||||
const char *ccp; /* index variable */
|
||||
char *newrights;
|
||||
char *nr; /* newrights */
|
||||
|
||||
if(!r) return(stcopy(a));
|
||||
|
||||
nr = newrights = stalloc(strlen(r)+strlen(a)+1);
|
||||
|
||||
/* First check each known right */
|
||||
for(ccp = canonical;*ccp;ccp++) {
|
||||
if(index(r,*ccp)) *(nr++) = *ccp;
|
||||
else if(index(a,*ccp)) *(nr++) = *ccp;
|
||||
}
|
||||
/* Now scan r and include anything that is not canonical */
|
||||
for(cp = r;*cp;cp++) {
|
||||
if(index(canonical,*cp)==0) *(nr++) = *cp;
|
||||
}
|
||||
/* Now scan a and include anything that is not canonical */
|
||||
/* and isn't in r */
|
||||
for(cp = a;*cp;cp++) {
|
||||
if((index(canonical,*cp)==0)&&
|
||||
(index(r,*cp)==0)) *(nr++) = *cp;
|
||||
}
|
||||
*(nr++) = '\0';
|
||||
stfree(r);
|
||||
return(newrights);
|
||||
}
|
||||
|
||||
/*
|
||||
* Subtract rights returns a string containing those rights
|
||||
* in r that are not in s.
|
||||
*
|
||||
* WARNING: Subtractrights frees r. It is expected that
|
||||
* the string pointed to by r will be replaced
|
||||
* by the string handed back.
|
||||
*/
|
||||
char *subtractrights(r,s)
|
||||
char *r;
|
||||
char *s;
|
||||
{
|
||||
char *newrights = stalloc(strlen(r)+1);
|
||||
char *or; /* oldrights */
|
||||
char *nr; /* newrights */
|
||||
|
||||
for(or = r,nr = newrights;*or;or++) {
|
||||
if(strchr(s,*or)==NULL) *(nr++) = *or;
|
||||
}
|
||||
*(nr++) = '\0';
|
||||
|
||||
stfree(r);
|
||||
return(newrights);
|
||||
}
|
||||
879
prospero/lib/psrv/check_acl.c
Normal file
879
prospero/lib/psrv/check_acl.c
Normal file
@@ -0,0 +1,879 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/types.h> /* for decl. of inet_ntoa() */
|
||||
#include <sys/socket.h> /* for decl. of inet_ntoa() */
|
||||
#include <netinet/in.h> /* for decl. of inet_ntoa() */
|
||||
#include <arpa/inet.h> /* for decl. of inet_ntoa() */
|
||||
|
||||
|
||||
#include <ardp.h>
|
||||
#include <pfs.h>
|
||||
#include <pserver.h>
|
||||
#include <pprot.h>
|
||||
#include <plog.h>
|
||||
#include <pmachine.h>
|
||||
#include <psrv.h>
|
||||
|
||||
#ifndef IPPORT_RESERVED
|
||||
#define IPPORT_RESERVED 1024
|
||||
#endif
|
||||
|
||||
|
||||
/* used to initialize ACLs */
|
||||
struct aclinit {
|
||||
int acetype;
|
||||
char *atype;
|
||||
char *rights;
|
||||
char *prin_1; /* principals list */
|
||||
char *prin_2; /* principals list */
|
||||
char *prin_3; /* principals list */
|
||||
char *prin_4; /* principals list */
|
||||
char *prin_5; /* principals list */
|
||||
char *prin_6; /* principals list */
|
||||
char *prin_7; /* principals list */
|
||||
char *prin_8; /* principals list */
|
||||
char *prin_9; /* principals list */
|
||||
char *prin_10; /* principals list */
|
||||
char *prin_11; /* principals list */
|
||||
char *prin_12; /* principals list */
|
||||
char *prin_13; /* principals list */
|
||||
char *prin_14; /* principals list */
|
||||
char *prin_15; /* principals list */
|
||||
char *prin_16; /* principals list */
|
||||
char *prin_17; /* principals list */
|
||||
char *prin_18; /* principals list */
|
||||
char *prin_19; /* principals list */
|
||||
char *prin_20; /* principals list */
|
||||
char *prin_21; /* principals list */
|
||||
char *prin_22; /* principals list */
|
||||
char *prin_23; /* principals list */
|
||||
char *prin_24; /* principals list */
|
||||
char *prin_25; /* principals list */
|
||||
char *prin_26; /* principals list */
|
||||
};
|
||||
|
||||
static ACL_ST default_iacl = {ACL_DEFAULT, NULL};
|
||||
static ACL_ST system_iacl = {ACL_SYSTEM, NULL};
|
||||
static ACL_ST container_iacl = {ACL_CONTAINER, NULL};
|
||||
static ACL_ST directory_iacl = {ACL_DIRECTORY, NULL};
|
||||
|
||||
static struct aclinit default_aclinit[] = DEFAULT_ACL;
|
||||
static struct aclinit system_aclinit[] = SYSTEM_ACL;
|
||||
static struct aclinit override_aclinit[] = OVERRIDE_ACL;
|
||||
static struct aclinit maint_aclinit[] = MAINT_ACL;
|
||||
|
||||
/* Only modified in p_srv_check_acl_initialize_defaults(), which is called
|
||||
before we go multi-threaded. */
|
||||
ACL default_acl = NULL;
|
||||
ACL system_acl = NULL;
|
||||
ACL override_acl = NULL;
|
||||
ACL nulldir_acl = NULL;
|
||||
ACL nullobj_acl = NULL;
|
||||
ACL nullcont_acl = NULL;
|
||||
ACL nulllink_acl = NULL;
|
||||
ACL maint_acl = NULL;
|
||||
|
||||
static checkl_acl_r();
|
||||
static check_permissions();
|
||||
static check_asserted_principal();
|
||||
ACL get_container_acl();
|
||||
static ACL aclinit2acl(struct aclinit init[], int nelems);
|
||||
static int checkl_acl_r(ACL acl, ACL dacl, RREQ req, char *op, int depth, int ld,char *objid,char *itemid);
|
||||
|
||||
/* Called before things start to run in psrv. */
|
||||
void
|
||||
p_srv_check_acl_initialize_defaults(void)
|
||||
{
|
||||
default_acl = aclinit2acl(default_aclinit,
|
||||
sizeof default_aclinit
|
||||
/ sizeof default_aclinit[0]);
|
||||
system_acl = aclinit2acl(system_aclinit,
|
||||
sizeof system_aclinit
|
||||
/ sizeof system_aclinit[0]);
|
||||
override_acl = aclinit2acl(override_aclinit,
|
||||
sizeof override_aclinit
|
||||
/ sizeof override_aclinit[0]);
|
||||
maint_acl = aclinit2acl(maint_aclinit,
|
||||
sizeof maint_aclinit
|
||||
/ sizeof maint_aclinit[0]);
|
||||
|
||||
default_iacl.next = &system_iacl;
|
||||
system_iacl.previous = &default_iacl;
|
||||
nulldir_acl = &default_iacl;
|
||||
nulllink_acl = &directory_iacl;
|
||||
nullobj_acl = &container_iacl;
|
||||
nullcont_acl = nulldir_acl;
|
||||
|
||||
}
|
||||
|
||||
static ACL aclentryinit2aclentry(struct aclinit *init);
|
||||
|
||||
/* constructs a real list of ACL entries out of an array of aclinit
|
||||
structures. */
|
||||
static ACL
|
||||
aclinit2acl(struct aclinit init[], int nelems)
|
||||
{
|
||||
|
||||
ACL rethead = NULL; /* head of list of AC entries being returned */
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nelems; ++i) {
|
||||
ACL tmp = aclentryinit2aclentry(&init[i]);
|
||||
APPEND_ITEM(tmp, rethead);
|
||||
}
|
||||
return rethead;
|
||||
}
|
||||
|
||||
|
||||
static ACL
|
||||
aclentryinit2aclentry(struct aclinit *init)
|
||||
{
|
||||
ACL retval;
|
||||
retval = acalloc();
|
||||
if (!retval) out_of_memory();
|
||||
retval->acetype = init->acetype;
|
||||
retval->atype = init->atype;
|
||||
retval->rights = init->rights;
|
||||
retval->principals = NULL;
|
||||
if (init->prin_1)
|
||||
retval->principals = tkappend(init->prin_1, retval->principals);
|
||||
if (init->prin_2)
|
||||
retval->principals = tkappend(init->prin_2, retval->principals);
|
||||
if (init->prin_3)
|
||||
retval->principals = tkappend(init->prin_3, retval->principals);
|
||||
if (init->prin_4)
|
||||
retval->principals = tkappend(init->prin_4, retval->principals);
|
||||
if (init->prin_5)
|
||||
retval->principals = tkappend(init->prin_5, retval->principals);
|
||||
if (init->prin_6)
|
||||
retval->principals = tkappend(init->prin_6, retval->principals);
|
||||
if (init->prin_7)
|
||||
retval->principals = tkappend(init->prin_8, retval->principals);
|
||||
if (init->prin_9)
|
||||
retval->principals = tkappend(init->prin_9, retval->principals);
|
||||
if (init->prin_10)
|
||||
retval->principals = tkappend(init->prin_10, retval->principals);
|
||||
if (init->prin_11)
|
||||
retval->principals = tkappend(init->prin_11, retval->principals);
|
||||
if (init->prin_12)
|
||||
retval->principals = tkappend(init->prin_12, retval->principals);
|
||||
if (init->prin_13)
|
||||
retval->principals = tkappend(init->prin_13, retval->principals);
|
||||
if (init->prin_14)
|
||||
retval->principals = tkappend(init->prin_14, retval->principals);
|
||||
if (init->prin_15)
|
||||
retval->principals = tkappend(init->prin_15, retval->principals);
|
||||
if (init->prin_16)
|
||||
retval->principals = tkappend(init->prin_16, retval->principals);
|
||||
if (init->prin_17)
|
||||
retval->principals = tkappend(init->prin_17, retval->principals);
|
||||
if (init->prin_18)
|
||||
retval->principals = tkappend(init->prin_18, retval->principals);
|
||||
if (init->prin_19)
|
||||
retval->principals = tkappend(init->prin_19, retval->principals);
|
||||
if (init->prin_20)
|
||||
retval->principals = tkappend(init->prin_20, retval->principals);
|
||||
if (init->prin_21)
|
||||
retval->principals = tkappend(init->prin_21, retval->principals);
|
||||
if (init->prin_22)
|
||||
retval->principals = tkappend(init->prin_22, retval->principals);
|
||||
if (init->prin_23)
|
||||
retval->principals = tkappend(init->prin_23, retval->principals);
|
||||
if (init->prin_24)
|
||||
retval->principals = tkappend(init->prin_24, retval->principals);
|
||||
if (init->prin_25)
|
||||
retval->principals = tkappend(init->prin_25, retval->principals);
|
||||
if (init->prin_26)
|
||||
retval->principals = tkappend(init->prin_26, retval->principals);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* srv_check_acl - check access control list
|
||||
*
|
||||
* SRV_CHECK_ACL checks an access control list to see if a particular
|
||||
* user is authorized to perform a particular operation. It returns
|
||||
* a positive number if the operation is authorized, and zero if
|
||||
* not authorized. SRV_CHECK_ACL actually checks up to three access
|
||||
* control lists. First, the access control list associated with
|
||||
* a link is checked (if specified). If the operation would not
|
||||
* be authorized, the secondary ACL may be checked if present, and
|
||||
* depending on the type of ACL check specified in the flags field,
|
||||
* to see if it applies to or overrides the individual entry. If sill
|
||||
* not authorized, an override ACL is checked to see if the operation
|
||||
* is performed.
|
||||
*
|
||||
* NOTE on negative rights: Negative rights apply within
|
||||
* a particular access control list only. Thus, a negative
|
||||
* entry in the link ACL can override other entries in the
|
||||
* link ACL, but it will not prevent access if the user
|
||||
* is authorized to perform the operation by the directory
|
||||
* or override ACL's.
|
||||
*/
|
||||
int
|
||||
srv_check_acl(ACL pacl, /* Primary ACL */
|
||||
ACL sacl, /* Secondary ACL */
|
||||
RREQ req, /* Request; used for client identification */
|
||||
char *op, /* Operation */
|
||||
int flags, /* Type of ACL check */
|
||||
char *objid, /* hsoname of object to which ACL applies */
|
||||
char *itemid) /* Name of item to be manipulated */
|
||||
{
|
||||
int answer = 0;
|
||||
|
||||
/* Now called from dirsrv */
|
||||
#if 0
|
||||
if(!initialized) initialize_defaults();
|
||||
#endif
|
||||
|
||||
if(flags == SCA_LINK) {
|
||||
if(!pacl) pacl = nulllink_acl;
|
||||
if(!sacl) sacl = nulldir_acl;
|
||||
answer = checkl_acl_r(pacl,sacl,req,op,ACL_NESTING,
|
||||
SCA_LINK,objid,itemid);
|
||||
if(!answer) answer = checkl_acl_r(sacl,sacl,req,op,ACL_NESTING,
|
||||
SCA_DIRECTORY,objid,itemid);
|
||||
}
|
||||
else if(flags == SCA_LINKDIR) {
|
||||
if(!pacl) pacl = nulllink_acl;
|
||||
if(!sacl) sacl = nulldir_acl;
|
||||
answer = checkl_acl_r(pacl,sacl,req,op,ACL_NESTING,
|
||||
SCA_LINK,objid,itemid);
|
||||
if(!answer) answer = checkl_acl_r(sacl,sacl,req,op,ACL_NESTING,
|
||||
SCA_DIRECTORY,objid,itemid);
|
||||
}
|
||||
else if(flags == SCA_DIRECTORY) {
|
||||
if(!pacl) pacl = nulldir_acl;
|
||||
answer = checkl_acl_r(pacl,pacl,req,op,ACL_NESTING,
|
||||
SCA_DIRECTORY,objid,itemid);
|
||||
}
|
||||
else if (flags == SCA_OBJECT) {
|
||||
ACL cacl = NULL;
|
||||
if(!pacl) pacl = nullobj_acl;
|
||||
if(!sacl) {
|
||||
if(objid && (cacl = get_container_acl(objid))) {
|
||||
answer = checkl_acl_r(pacl,cacl,req,op,ACL_NESTING,
|
||||
SCA_OBJECT,objid,itemid);
|
||||
aclfree(cacl);
|
||||
}
|
||||
else answer = checkl_acl_r(pacl,nullcont_acl,req,op,ACL_NESTING,
|
||||
SCA_OBJECT,objid,itemid);
|
||||
}
|
||||
else answer = checkl_acl_r(pacl,sacl,req,op,ACL_NESTING,SCA_OBJECT,
|
||||
objid,itemid);
|
||||
}
|
||||
else if (flags == SCA_MISC) {
|
||||
if(!pacl) pacl = maint_acl;
|
||||
answer = checkl_acl_r(pacl,NULL,req,op,ACL_NESTING,
|
||||
SCA_MISC,objid,itemid);
|
||||
}
|
||||
|
||||
if(answer) return(answer);
|
||||
|
||||
/* Check to see if absolute override applies */
|
||||
return(checkl_acl_r(override_acl,NULL,req,op,ACL_NESTING,
|
||||
SCA_MISC, objid,itemid));
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
checkl_acl_r(acl,sacl,req,op,depth,ld,objid,itemid)
|
||||
ACL acl; /* Access control list */
|
||||
ACL sacl; /* Secondary access control list */
|
||||
char *op; /* Operation */
|
||||
RREQ req; /* Client identification */
|
||||
int depth; /* Maximum nesting */
|
||||
int ld; /* 0 = link, 1 = dir, 2 = both, 4=misc */
|
||||
char *objid; /* Object associated with ACL */
|
||||
char *itemid; /* Name of item to manipulate */
|
||||
{
|
||||
int retval = 0; /* Would this entry authorize op */
|
||||
int answer = 1; /* How to answer if match */
|
||||
|
||||
if(depth == 0) return(NOT_AUTHORIZED);
|
||||
|
||||
while(acl) {
|
||||
retval = check_permissions(op,acl->rights,ld);
|
||||
if(retval||((acl->rights==NULL)&&((acl->acetype == ACL_DEFAULT)
|
||||
||(acl->acetype == ACL_SYSTEM)
|
||||
||(acl->acetype == ACL_DIRECTORY)
|
||||
||(acl->acetype == ACL_CONTAINER)
|
||||
||(acl->acetype == ACL_IETF_AAC)))) {
|
||||
if(retval == NEG_AUTHORIZED) answer = NOT_AUTHORIZED;
|
||||
else answer = AUTHORIZED;
|
||||
|
||||
switch(acl->acetype) {
|
||||
|
||||
case ACL_NONE:
|
||||
break;
|
||||
case ACL_DEFAULT:
|
||||
retval = checkl_acl_r(default_acl,sacl,req,op,depth-1,ld,objid,itemid);
|
||||
if(retval) return(answer);
|
||||
break;
|
||||
case ACL_SYSTEM:
|
||||
retval = checkl_acl_r(system_acl,sacl,req,op,depth-1,ld,objid,itemid);
|
||||
if(retval) return(answer);
|
||||
break;
|
||||
case ACL_OWNER:
|
||||
/* Check if user is the owner of the dirtectory */
|
||||
#if 0
|
||||
/* We need to find the owner of the file/directory */
|
||||
/* for which this ACL applies and check whether it */
|
||||
/* is the current principal. For now, we don't */
|
||||
/* know the name of the file or directory. When */
|
||||
/* the interface is changed so we do know it, we */
|
||||
/* will check against the current host address and */
|
||||
/* the TRSTHOST authentication type. Alternatively */
|
||||
/* we will use an OBJECT-OWNER attribute from the */
|
||||
/* object attribute list which will be in the form */
|
||||
/* of an ACL entry, but without a rights field */
|
||||
#endif
|
||||
break;
|
||||
case ACL_DIRECTORY:
|
||||
if(ld == SCA_LINK) {
|
||||
retval = checkl_acl_r(sacl,sacl,req,op,depth-1,
|
||||
SCA_LINKDIR,objid,itemid);
|
||||
if(retval) return(answer);
|
||||
}
|
||||
break;
|
||||
case ACL_CONTAINER:
|
||||
if(ld == SCA_OBJECT) {
|
||||
retval = checkl_acl_r(sacl,sacl,req,op,depth-1,
|
||||
SCA_CONTAINER,objid,itemid);
|
||||
if(retval) return(answer);
|
||||
}
|
||||
break;
|
||||
case ACL_ANY:
|
||||
return(answer);
|
||||
case ACL_AUTHENT:
|
||||
if (acl->atype && strequal(acl->atype, "KERBEROS")) {
|
||||
PAUTH pap; /* Iteration variable for PAUTH. */
|
||||
TOKEN prin; /* principals */
|
||||
/* Loop through all of the Kerberos authenticated
|
||||
principals. (This is upward-compatible with future
|
||||
versions of Kerberos that will allow one to be
|
||||
registered as multiple principals simultaneously.)
|
||||
*/
|
||||
for (pap = req->auth_info; pap; pap = pap->next) {
|
||||
if (pap->ainfo_type == PFSA_KERBEROS) {
|
||||
for (prin = pap->principals; prin;
|
||||
prin = prin->next) {
|
||||
if (member(prin->token, acl->principals))
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (acl->atype && strequal(acl->atype, "P_PASSWORD")) {
|
||||
PAUTH pap; /* Iteration variable for PAUTH. */
|
||||
TOKEN prin; /* principals */
|
||||
/* Loop through all of the principals. */
|
||||
for (pap = req->auth_info; pap; pap = pap->next) {
|
||||
if (pap->ainfo_type == PFSA_P_PASSWORD) {
|
||||
for (prin = pap->principals; prin;
|
||||
prin = prin->next) {
|
||||
if (member(prin->token, acl->principals))
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case ACL_LGROUP: /* Not yet implemented */
|
||||
break;
|
||||
case ACL_GROUP: /* Not yet implemented */
|
||||
break;
|
||||
case ACL_TRSTHOST: /* Check host and userid */
|
||||
if (!check_prvport(req))
|
||||
break;
|
||||
/* DELIBERATE FALLTHROUGH */
|
||||
case ACL_ASRTHOST: /* Check host and asserted userid */
|
||||
{
|
||||
PAUTH pap;
|
||||
TOKEN prin; /* principals */
|
||||
/* Loop through all of the asserted principals. */
|
||||
for (pap = req->auth_info; pap; pap = pap->next) {
|
||||
if (pap->ainfo_type == PFSA_UNAUTHENTICATED) {
|
||||
for (prin = pap->principals; prin;
|
||||
prin = prin->next) {
|
||||
if (check_asserted_principal(prin->token,
|
||||
acl->principals,
|
||||
req->peer_addr))
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ACL_IETF_AAC:
|
||||
/* This ACL entry type is not yet implemented */
|
||||
break;
|
||||
default: /* Not implemented */
|
||||
break;
|
||||
}
|
||||
}
|
||||
acl = acl->next;
|
||||
}
|
||||
return(NOT_AUTHORIZED);
|
||||
}
|
||||
|
||||
/*
|
||||
* check_permissions - Check if operation is authorized
|
||||
*
|
||||
* CHECK_PERMISIONS takes a string with letters representing
|
||||
* the permissions required for the current opration, and
|
||||
* a string listing operating authorized by the current ACL
|
||||
* entry. It returns a 1 if the operation would be
|
||||
* authorized by the current entry, a 0 if not, and a -1
|
||||
* if the ACL entry would have authorized the operation,
|
||||
* but began with a "-" indicating negative authorization.
|
||||
*
|
||||
* ARGS: op - String with operations to be performed
|
||||
* p - Permissions from ACL entry
|
||||
* ld - Whther ACL entry is for directory or link (or both)
|
||||
*
|
||||
* RETURNS: 1 if authorized
|
||||
* 0 if not authorized
|
||||
* -1 if negative authorization
|
||||
*
|
||||
* Protections
|
||||
*
|
||||
* The more common entry appears first if multiple rights allow an
|
||||
* operation. The operation identifier appears second.
|
||||
*
|
||||
* Object File Directory Link* Meaning
|
||||
* AB AB AB Aa Administer ACL
|
||||
* VYAB VYAB VYAB VvAa View ACL
|
||||
* - - L Ll List link
|
||||
* Rg RG RQ RrQ Read link, get attribute or file
|
||||
* Wu Ww WM WmM Modify attribute, data, links
|
||||
* EiWu EeWw EIWM - Insert attributes links, append (extend)
|
||||
* DzWu - DKWM DdKWMm Delete link or attribute
|
||||
*
|
||||
* The following will eventually be replaced by restricted forms of
|
||||
* Administer (A or B).
|
||||
*
|
||||
* > > > ] Add rights
|
||||
* < < < [ Remove rights
|
||||
* ) ) ) - Add rights
|
||||
* ( ( ( - Remove rights
|
||||
*
|
||||
* The following only appear on the server maintenance ACL
|
||||
*
|
||||
* S Restart server
|
||||
* T Terminate server
|
||||
* U Update system information
|
||||
* P Administer passwords
|
||||
* p Add new password entry
|
||||
*
|
||||
* A - sign in an ACL means that the specified rights are explicitly
|
||||
* denied. In the table, it means not applicable.
|
||||
*
|
||||
* * A capital letter on a link ACL means that this right exists in the
|
||||
* direcory ACL for the directory containing the link.
|
||||
*
|
||||
* ** When restrictions are supported, they can be used to restrict the
|
||||
* specific attributes to which a right applies, or to restrict the
|
||||
* interpretation of an ACL entry to only the Object, File, or Directory,
|
||||
* or link.
|
||||
*
|
||||
* When a small letter is associated with a directory, it is the default
|
||||
* used for those links in the directory which do not otherwise specify
|
||||
* protections. The large letter for a directory indicates that the
|
||||
* right applies to ALL entries in the directory, regardless of the ACLs
|
||||
* associated with the individual link.
|
||||
*
|
||||
* These rights apply to the directory and individual links. The ability
|
||||
* to read a link does not grant any rights to read the file that the
|
||||
* link points to. Instead, it grants the right to read the binding
|
||||
* of the link. The protection mechanisms for the objects themselves
|
||||
* depend on the underlying access mechanism.
|
||||
*
|
||||
* The Administer right is required to change the ACL. "A" allows one
|
||||
* to change the ACLs for the directory as a whole, as well as those
|
||||
* for individual links. It does not, however, grant any rights to
|
||||
* the object pointed to by those links (e.g. it doesn't allow one
|
||||
* to change the permissions on subdirectories.
|
||||
*
|
||||
* List allows one to list an entry in a wildcarded search. Read allows
|
||||
* one to learn the binding of a link. If one can read a link, but
|
||||
* not list it, then it can only be seen when the user specifies the
|
||||
* exact name of the link in a query.
|
||||
*
|
||||
* Modify allows one to change the binding of a link. It does not
|
||||
* allow one to create a new link or delete an existing one. Insert
|
||||
* or delete access are necessary for that.
|
||||
*
|
||||
* View allows one to view the contents of the ACL. Administer implies view.
|
||||
* Add rights and remove rights, ><][)(, allow one to add or remove the
|
||||
* other rights that are specified as part of the same ACL entry. It is
|
||||
* a limited form of administer. The other rights included in the
|
||||
* same ACL entry do not apply, but only restrict which rights may be
|
||||
* added or removed. The add or remove indicators must appear in the
|
||||
* first one or two positions in the rights field, and can not themselves
|
||||
* be added or removed unless they also appear later in the rights field.
|
||||
*
|
||||
* If the permission string begins with a "-" and if the specified operation
|
||||
* would otherwise be authorized, check_permissions returns -1 indicating
|
||||
* that an applicable negative right has been found, and that the operation
|
||||
* should be denied even if subsequent ACL entries authorizing it are found.
|
||||
* If an ACL entry preceding this one has already authorized the operation,
|
||||
* the operation will be performed.
|
||||
*
|
||||
* BUGS: For now, only the first character in ><][])( means add or
|
||||
* delete the following rights, and all rights included in the
|
||||
* entry including the first ><][)( may be added or deleted.
|
||||
* Eventually, we will check the first two positions to see
|
||||
* if adding and deleting is allowed, and the matching
|
||||
* characters in those positions will be removed before
|
||||
* checking subsequent characters.
|
||||
*/
|
||||
int
|
||||
static check_permissions(op,p,ld)
|
||||
char *op; /* Operation */
|
||||
char *p; /* Permissions */
|
||||
int ld; /* 0 =link, 1 =directory, 2=both, 4=misc */
|
||||
{
|
||||
char *tp = p;
|
||||
int polarity = 1; /* -1 = neg authorization */
|
||||
|
||||
if(!p || !(*p)) return(NOT_AUTHORIZED);
|
||||
|
||||
if(*p == '-') polarity = -1;
|
||||
|
||||
/* Reject if ACL entry for insert or delete rights, but not operation */
|
||||
if(index("><][)(",*p) && !index("><][",*op))
|
||||
return(NOT_AUTHORIZED);
|
||||
/* Insert or delete rights must be first in ACL permissions */
|
||||
while(*(++tp)) if(index("><][)(",*tp)) return(NOT_AUTHORIZED);
|
||||
|
||||
while(*op) {
|
||||
switch(*(op++)) {
|
||||
|
||||
case 'a':
|
||||
if((ld != 1) && index(p,'a')) continue;
|
||||
if((ld != 0) && index(p,'A')) continue;
|
||||
else return(NOT_AUTHORIZED);
|
||||
case 'A':
|
||||
case 'B':
|
||||
if((ld != 0) && index(p,'A')) continue;
|
||||
if((ld != 0) && index(p,'B')) continue;
|
||||
else return(NOT_AUTHORIZED);
|
||||
|
||||
case 'v':
|
||||
if((ld != 1) && index(p,'v')) continue;
|
||||
if((ld != 0) && index(p,'V')) continue;
|
||||
if((ld != 1) && index(p,'a')) continue;
|
||||
if((ld != 0) && index(p,'A')) continue;
|
||||
else return(NOT_AUTHORIZED);
|
||||
case 'V':
|
||||
case 'Y':
|
||||
if((ld != 0) && index(p,'V')) continue;
|
||||
if((ld != 0) && index(p,'Y')) continue;
|
||||
if((ld != 0) && index(p,'A')) continue;
|
||||
if((ld != 0) && index(p,'B')) continue;
|
||||
else return(NOT_AUTHORIZED);
|
||||
|
||||
case 'l':
|
||||
if((ld != 1) && index(p,'l')) continue;
|
||||
case 'L': /* and fall through */
|
||||
if((ld != 0) && index(p,'L')) continue;
|
||||
else return(NOT_AUTHORIZED);
|
||||
|
||||
case 'r':
|
||||
if((ld != 1) && index(p,'r')) continue;
|
||||
case 'R': /* and fall through */
|
||||
case 'Q': /* and fall through */
|
||||
if((ld != 0) && index(p,'R')) continue;
|
||||
if((ld != 0) && index(p,'Q')) continue;
|
||||
else return(NOT_AUTHORIZED);
|
||||
|
||||
case 'G':
|
||||
if((ld != 0) && index(p,'G')) continue;
|
||||
if((ld != 0) && index(p,'R')) continue;
|
||||
else return(NOT_AUTHORIZED);
|
||||
|
||||
case 'g':
|
||||
if((ld != 0) && index(p,'g')) continue;
|
||||
if((ld != 0) && index(p,'R')) continue;
|
||||
else return(NOT_AUTHORIZED);
|
||||
|
||||
case 'm':
|
||||
if((ld != 1) && index(p,'m')) continue;
|
||||
case 'M': /* and fall through */
|
||||
if((ld != 0) && index(p,'M')) continue;
|
||||
if((ld != 0) && index(p,'W')) continue;
|
||||
else return(NOT_AUTHORIZED);
|
||||
|
||||
case 'w': /* and fall through */
|
||||
if((ld != 0) && index(p,'w')) continue;
|
||||
if((ld != 0) && index(p,'W')) continue;
|
||||
else return(NOT_AUTHORIZED);
|
||||
|
||||
case 'u': /* and fall through */
|
||||
if((ld != 0) && index(p,'u')) continue;
|
||||
if((ld != 0) && index(p,'W')) continue;
|
||||
else return(NOT_AUTHORIZED);
|
||||
|
||||
case 'I':
|
||||
if((ld != 0) && index(p,'I')) continue;
|
||||
if((ld != 0) && index(p,'E')) continue;
|
||||
if((ld != 0) && index(p,'W')) continue;
|
||||
if((ld != 0) && index(p,'M')) continue;
|
||||
else return(NOT_AUTHORIZED);
|
||||
|
||||
case 'e':
|
||||
if((ld != 0) && index(p,'e')) continue;
|
||||
if((ld != 0) && index(p,'E')) continue;
|
||||
if((ld != 0) && index(p,'W')) continue;
|
||||
if((ld != 0) && index(p,'w')) continue;
|
||||
else return(NOT_AUTHORIZED);
|
||||
|
||||
case 'i':
|
||||
if((ld != 0) && index(p,'i')) continue;
|
||||
if((ld != 0) && index(p,'E')) continue;
|
||||
if((ld != 0) && index(p,'W')) continue;
|
||||
if((ld != 0) && index(p,'u')) continue;
|
||||
else return(NOT_AUTHORIZED);
|
||||
|
||||
case 'd':
|
||||
if((ld != 1) && index(p,'d')) continue;
|
||||
if((ld != 1) && index(p,'m')) continue;
|
||||
case 'D': /* and fall through */
|
||||
if((ld != 0) && index(p,'D')) continue;
|
||||
if((ld != 0) && index(p,'K')) continue;
|
||||
if((ld != 0) && index(p,'W')) continue;
|
||||
if((ld != 0) && index(p,'M')) continue;
|
||||
else return(NOT_AUTHORIZED);
|
||||
|
||||
case 'z': /* and fall through */
|
||||
if((ld != 0) && index(p,'D')) continue;
|
||||
if((ld != 0) && index(p,'z')) continue;
|
||||
if((ld != 0) && index(p,'W')) continue;
|
||||
if((ld != 0) && index(p,'u')) continue;
|
||||
else return(NOT_AUTHORIZED);
|
||||
|
||||
case ']':
|
||||
if((ld != 1) && index(p,']')) continue;
|
||||
if((ld != 0) && index(p,'>')) continue;
|
||||
else return(NOT_AUTHORIZED);
|
||||
case '>':
|
||||
if((ld != 0) && index(p,'>')) continue;
|
||||
if((ld != 0) && index(p,')')) continue;
|
||||
else return(NOT_AUTHORIZED);
|
||||
|
||||
case '[':
|
||||
if((ld != 1) && index(p,'[')) continue;
|
||||
if((ld != 0) && index(p,'<')) continue;
|
||||
else return(NOT_AUTHORIZED);
|
||||
case '<':
|
||||
if((ld != 0) && index(p,'<')) continue;
|
||||
if((ld != 0) && index(p,'(')) continue;
|
||||
else return(NOT_AUTHORIZED);
|
||||
|
||||
/* Maintenance operations. */
|
||||
case 'S':
|
||||
if (index(p, 'S')) continue;
|
||||
else return NOT_AUTHORIZED;
|
||||
case 'T':
|
||||
if (index(p, 'T')) continue;
|
||||
else return NOT_AUTHORIZED;
|
||||
case 'U':
|
||||
if (index(p, 'U')) continue;
|
||||
else return NOT_AUTHORIZED;
|
||||
case 'P':
|
||||
if (index(p, 'P')) continue;
|
||||
else return NOT_AUTHORIZED;
|
||||
case 'p':
|
||||
if (index(p, 'p')) continue;
|
||||
if (index(p, 'P')) continue;
|
||||
else return NOT_AUTHORIZED;
|
||||
default:
|
||||
return(NOT_AUTHORIZED);
|
||||
}
|
||||
}
|
||||
return(polarity);
|
||||
}
|
||||
|
||||
#ifdef NOTDEF
|
||||
/* Unused. Make this thread-safe before commenting it out. */
|
||||
static char *inet_ntoa(a)
|
||||
struct in_addr a;
|
||||
{
|
||||
static char astring[20];
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
sprintf(astring,"%d.%d.%d.%d",(a.s_addr >> 24) & 0xff,
|
||||
(a.s_addr >> 16) & 0xff,(a.s_addr >> 8) & 0xff,
|
||||
a.s_addr & 0xff);
|
||||
#else
|
||||
sprintf(astring,"%d.%d.%d.%d", a.s_addr & 0xff,
|
||||
(a.s_addr >> 8) & 0xff,(a.s_addr >> 16) & 0xff,
|
||||
(a.s_addr >> 24) & 0xff);
|
||||
#endif
|
||||
|
||||
return(astring);
|
||||
}
|
||||
#endif NOTDEF
|
||||
|
||||
/* Only used locally in a context where it returns static data overwritten by
|
||||
each call. */
|
||||
static char *
|
||||
inet_def_local(char *s)
|
||||
{
|
||||
AUTOSTAT_CHARPP(adstringp);
|
||||
static long myaddr = 0; /* look below to see how this is mutexed */
|
||||
char intstring[10];
|
||||
static long o[4]; /* look below to see how this is mutexed */
|
||||
char *ads;
|
||||
long *octet;
|
||||
|
||||
if (!*adstringp) *adstringp = stalloc(50); /* effectively, an array of size
|
||||
50. */
|
||||
if (!myaddr) {
|
||||
p_th_mutex_lock(p_th_mutexPSRV_CHECK_ACL_INET_DEF_LOCAL);
|
||||
/* Now that we have a mutex, check adstring again, since it might
|
||||
have changed since we tested it. This tests whether another
|
||||
initialization successfully completed since we called this. */
|
||||
if (!myaddr) {
|
||||
long local_myaddr = myaddress();
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
o[0] = (local_myaddr >> 24) & 0xff;
|
||||
o[1] = (local_myaddr >> 16) & 0xff;
|
||||
o[2] = (local_myaddr >> 8) & 0xff;
|
||||
o[3] = local_myaddr & 0xff;
|
||||
#else
|
||||
o[0] = local_myaddr & 0xff;
|
||||
o[1] = (local_myaddr >> 8) & 0xff;
|
||||
o[2] = (local_myaddr >> 16) & 0xff;
|
||||
o[3] = (local_myaddr >> 24) & 0xff;
|
||||
#endif
|
||||
myaddr = local_myaddr; /* change done; commit. */
|
||||
}
|
||||
p_th_mutex_unlock(p_th_mutexPSRV_CHECK_ACL_INET_DEF_LOCAL);
|
||||
}
|
||||
|
||||
octet = o;
|
||||
|
||||
ads = *adstringp;
|
||||
while(*s && ((ads - *adstringp) < 40) ) {
|
||||
switch(*s) {
|
||||
case '.':
|
||||
octet++;
|
||||
*ads++ = *s;
|
||||
break;
|
||||
case '%':
|
||||
qsprintf(intstring,sizeof intstring, "%d",*octet);
|
||||
bcopy(intstring,ads,strlen(intstring));
|
||||
ads += strlen(intstring);
|
||||
break;
|
||||
default:
|
||||
*ads++ = *s;
|
||||
break;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
*ads++ = '\0';
|
||||
|
||||
return(*adstringp);
|
||||
|
||||
}
|
||||
|
||||
/* Are we logged into a privileged port? 1 if yes, zero if no. */
|
||||
int
|
||||
check_prvport(req)
|
||||
RREQ req;
|
||||
{
|
||||
return PEER_PORT(req) <= IPPORT_RESERVED;
|
||||
}
|
||||
|
||||
/*
|
||||
* check_asserted_principal - check for membership in list of principals
|
||||
* and check optional host ID. The principals have the format used by ASRTHOST
|
||||
* and TRSTHOST.
|
||||
*/
|
||||
static int
|
||||
check_asserted_principal(username,principals, hostaddr)
|
||||
char username[];
|
||||
struct in_addr hostaddr;
|
||||
TOKEN principals;
|
||||
{
|
||||
for(; principals; principals = principals->next) {
|
||||
char *host;
|
||||
|
||||
/* principal specified in the ACL entry. We copy it because we can't
|
||||
modify the principals structure, since the principals structure
|
||||
might contain strings that are in readonly memory. */
|
||||
AUTOSTAT_CHARPP(aclprinp);
|
||||
*aclprinp = stcopyr(principals->token, *aclprinp);
|
||||
|
||||
host = strchr(*aclprinp,'@');
|
||||
if(host == NULL) {
|
||||
if(wcmatch(username,*aclprinp)) return(TRUE);
|
||||
else continue;
|
||||
}
|
||||
*(host++) = '\0';
|
||||
|
||||
if(!wcmatch(username,*aclprinp)) continue;
|
||||
|
||||
if(index("%123456789.",*host)) { /* Host address */
|
||||
if(wcmatch(inet_ntoa(hostaddr),inet_def_local(host)))
|
||||
return(TRUE);
|
||||
continue;
|
||||
}
|
||||
else if(*host == '0') { /* Host address with leading 0 */
|
||||
if(wcmatch(inet_ntoa(hostaddr),inet_def_local(host+1)))
|
||||
return(TRUE);
|
||||
continue;
|
||||
}
|
||||
else { /* Host name - not implemented */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
ACL get_container_acl(char *path)
|
||||
{
|
||||
PFILE container;
|
||||
ACL cont_acl = NULL;
|
||||
ACL tacl = NULL;
|
||||
ACL tacl2 = NULL;
|
||||
char cpath[MAXPATHLEN];
|
||||
char *slash;
|
||||
|
||||
strcpy(cpath,path);
|
||||
slash = strrchr(cpath,'/');
|
||||
|
||||
if(slash) {
|
||||
*slash = '\0';
|
||||
container = pfalloc();
|
||||
dsrfinfo(cpath,0,container);
|
||||
cont_acl = container->oacl; container->oacl = NULL;
|
||||
pffree(container);
|
||||
tacl = cont_acl;
|
||||
while(tacl) {
|
||||
if(tacl->acetype == ACL_CONTAINER) {
|
||||
tacl2 = tacl;
|
||||
tacl = tacl->next;
|
||||
EXTRACT_ITEM(tacl2,cont_acl);
|
||||
acfree(tacl2);
|
||||
}
|
||||
else tacl = tacl->next;
|
||||
}
|
||||
return(cont_acl);
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
85
prospero/lib/psrv/check_nfs.c
Normal file
85
prospero/lib/psrv/check_nfs.c
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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 <sys/param.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <pfs.h>
|
||||
#include <pmachine.h>
|
||||
|
||||
extern char *hostname;
|
||||
|
||||
/*
|
||||
* check_nfs - Check whether file is available by NFS
|
||||
*
|
||||
* CHECK_NFS takes the name of a file and a network address.
|
||||
* It returns the name of the filesystem (prefix of the file)
|
||||
* which may be exported by NFS to the client. The prefix is
|
||||
* followed by a space and the suffix. This is the form of the
|
||||
* paramters to be returned for access by NFS.
|
||||
*
|
||||
* ARGS: path - Name of file to be retrieved
|
||||
* client - IP address of the client
|
||||
*
|
||||
* RETURNS: A newly allocated sequence containing NFS access method for that
|
||||
* file, or NULL if the file is not available to the client by NFS.
|
||||
*
|
||||
* NOTES: The returned memory must be freed by the caller.
|
||||
*
|
||||
* BUGS: The procedure should check the NFS exports file. Right now
|
||||
* it only guesses at the prefix and check to make sure the
|
||||
* request is from the local subnet. It also incorrectly assumes that
|
||||
* the file must be exported by the local host. Ugh.
|
||||
*/
|
||||
#ifdef PFS_THREADS
|
||||
extern p_th_mutex p_th_mutexPSRV_CHECK_NFS_MYADDR;
|
||||
#endif
|
||||
|
||||
TOKEN
|
||||
check_nfs(char *path, long client)
|
||||
{
|
||||
TOKEN nfs_am = NULL;
|
||||
static long myaddr = 0; /* MUTEXED below */
|
||||
char prefix[MAXPATHLEN];
|
||||
char *suffix;
|
||||
char *slash;
|
||||
|
||||
/* First time called, find out hostname and remember it */
|
||||
if(!myaddr) {
|
||||
#ifdef PFS_THREADS
|
||||
p_th_mutex_lock(p_th_mutexPSRV_CHECK_NFS_MYADDR);
|
||||
if (!myaddr) { /* check again */
|
||||
#endif
|
||||
myaddr = myaddress();
|
||||
#ifdef PFS_THREADS
|
||||
}
|
||||
p_th_mutex_unlock(p_th_mutexPSRV_CHECK_NFS_MYADDR);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
if((myaddr ^ client) & 0xffffff00) return(NULL);
|
||||
#else
|
||||
if((myaddr ^ client) & 0x00ffffff) return(NULL);
|
||||
#endif
|
||||
|
||||
strcpy(prefix,path);
|
||||
slash = strchr(prefix+1,'/');
|
||||
if(slash) {*slash = '\0'; suffix = slash + 1;}
|
||||
else return(NULL);
|
||||
nfs_am = tkappend("NFS", nfs_am);
|
||||
nfs_am = tkappend("INTERNET-D", nfs_am);
|
||||
nfs_am = tkappend(hostname, nfs_am);
|
||||
nfs_am = tkappend("ASCII", nfs_am);
|
||||
nfs_am = tkappend(suffix, nfs_am);
|
||||
nfs_am = tkappend(prefix, nfs_am);
|
||||
return nfs_am;
|
||||
}
|
||||
112
prospero/lib/psrv/chk_krb_auth.c
Normal file
112
prospero/lib/psrv/chk_krb_auth.c
Normal file
@@ -0,0 +1,112 @@
|
||||
/* Checks Kerberos authentication, and returns authenticated client name.
|
||||
Returns non-zero on error. */
|
||||
|
||||
/* Copyright (c) 1992 by the University of Southern California.
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-copyr.h>.
|
||||
*/
|
||||
/* Author: Prasad Upasani (prasad@isi.edu)
|
||||
* Modifications by swa@isi.edu.
|
||||
*/
|
||||
|
||||
|
||||
#include <psite.h> /* must precede pfs.h for PSRV_KERBEROS
|
||||
compilation option. */
|
||||
#include <pfs.h>
|
||||
#include <psrv.h> /* prototypes this function */
|
||||
#include <pserver.h>
|
||||
#ifdef PSRV_KERBEROS /* Only compile this file if we are using
|
||||
Kerberos, since it refers to files in the
|
||||
Kerberos libraries. */
|
||||
/* This is currently actually used only by the server. It is in libpsrv. */
|
||||
#include <stdio.h>
|
||||
#include <krb5/krb5.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
|
||||
/* Returns 0 (PSUCCESS) on success; any other value on failure (should make
|
||||
this be PFAILURE, just for consistency. */
|
||||
int
|
||||
check_krb_auth(char *auth, struct sockaddr_in client,
|
||||
char **ret_client_namep /* Stores the name to be returned.
|
||||
Either NULL or memory previously
|
||||
allocated with stalloc() or
|
||||
stcopy(). */)
|
||||
{
|
||||
krb5_data inbuf;
|
||||
krb5_principal server;
|
||||
krb5_address *sender_addr;
|
||||
char service_name[255], hostname[255];
|
||||
int retval;
|
||||
krb5_address client_addr;
|
||||
krb5_tkt_authent *authdat;
|
||||
char *client_name;
|
||||
char *srvtab = NULL; /* NULL means to use the default Kerberos srvtab */
|
||||
#ifdef KERBEROS_SRVTAB
|
||||
int srvtabsiz;
|
||||
#endif
|
||||
|
||||
/* Create a server principal structure. */
|
||||
if (retval = gethostname(hostname, sizeof(hostname)))
|
||||
RETURNPFAILURE;
|
||||
|
||||
strcpy(service_name, KERBEROS_SERVICE);
|
||||
strcat(service_name, "/");
|
||||
strcat(service_name, hostname);
|
||||
|
||||
if (krb5_parse_name(service_name, &server))
|
||||
RETURNPFAILURE;
|
||||
|
||||
/* Put auth data into a krb5_data structure. */
|
||||
inbuf.data = stalloc(AUTHENTICATOR_SZ); /* starting value */
|
||||
again:
|
||||
if (inbuf.data == NULL) out_of_memory();
|
||||
retval = bindecode(auth, inbuf.data, p__bstsize(inbuf.data));
|
||||
if (retval > p__bstsize(inbuf.data)) {
|
||||
stfree(inbuf.data);
|
||||
inbuf.data = stalloc(retval);
|
||||
goto again;
|
||||
}
|
||||
/* Successfully decoded. */
|
||||
inbuf.length = retval;
|
||||
|
||||
/* Put client address in a krb5_address structure. */
|
||||
client_addr.addrtype = client.sin_family;
|
||||
client_addr.length = sizeof(client.sin_addr);
|
||||
client_addr.contents = (krb5_octet *) &client.sin_addr;
|
||||
|
||||
#ifdef KERBEROS_SRVTAB
|
||||
srvtab =
|
||||
stalloc(srvtabsiz = sizeof("FILE:") + sizeof(KERBEROS_SRVTAB) + 1);
|
||||
assert(qsprintf(srvtab, srvtabsiz, "FILE:%s", KERBEROS_SRVTAB) <= srvtabsiz);
|
||||
#endif
|
||||
|
||||
/* Check authentication. */
|
||||
retval = krb5_rd_req(&inbuf,
|
||||
server,
|
||||
&client_addr,
|
||||
srvtab,
|
||||
0, 0, 0,
|
||||
&authdat);
|
||||
|
||||
stfree(inbuf.data);
|
||||
#ifdef KERBEROS_SRVTAB
|
||||
stfree(srvtab);
|
||||
#endif
|
||||
|
||||
if (retval) RETURNPFAILURE; /* Authentication failed. */
|
||||
|
||||
/* Get client name. */
|
||||
/* client_name points to memory allocated with malloc() by
|
||||
krb5_unparse_name(). The caller is supposed to free it. */
|
||||
if (retval = krb5_unparse_name(authdat->authenticator->client,
|
||||
&client_name))
|
||||
RETURNPFAILURE;
|
||||
|
||||
*ret_client_namep = stcopyr(client_name, *ret_client_namep);
|
||||
free(client_name);
|
||||
return PSUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#endif /* PSRV_KERBEROS */
|
||||
306
prospero/lib/psrv/chk_localpth.c
Normal file
306
prospero/lib/psrv/chk_localpth.c
Normal file
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* 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 <sys/types.h> /* Needed by SCO; doesn't hurt others. */
|
||||
#include <sys/param.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <pmachine.h>
|
||||
|
||||
|
||||
#include <pserver.h>
|
||||
|
||||
#ifdef SHARED_PREFIXES /* if no SHARED_PREFIXES definition, this is
|
||||
useless. */
|
||||
#include <pfs.h>
|
||||
#include <plog.h> /* log errors in initializing. */
|
||||
|
||||
/* isascii() is not provided in POSIX, so we just do it here. */
|
||||
#ifndef isascii
|
||||
#define isascii(c) ((unsigned)(c)<=0177)
|
||||
#endif
|
||||
|
||||
extern char *hostname;
|
||||
|
||||
/*
|
||||
* check_localpath - Check whether file is available via the LOCAL access
|
||||
* method.
|
||||
*
|
||||
* CHECK_LOCALPATH takes the name of a file and a network
|
||||
* address. If possible, it returns a string which is the name for the
|
||||
* file in the client's filesystem.
|
||||
*
|
||||
* ARGS: path - Name of file to be retrieved
|
||||
* client - IP address of the client
|
||||
*
|
||||
* RETURNS: A character pointer to a static buffer containing the new name
|
||||
* of the file in the client's namespace, or NULL if the file is not
|
||||
* available to the client by the LOCAL access method.
|
||||
*
|
||||
* NOTES: The returned buffer will be reused on the next call.
|
||||
*/
|
||||
|
||||
static struct shared_prefixes {
|
||||
char **locals; /* array of char *; null terminated */
|
||||
char *remote; /* string, or NULL indicating not exported. */
|
||||
/* A network byte order list of ip addresses of clients for which this
|
||||
entry is meaningful. */
|
||||
long *includes; /* 0L terminated; octet w/255 means wildcard */
|
||||
/* A network byte order list of ip addresses of clients for which this
|
||||
entry is NOT meaningful. Overrides includes. Default (if no match in
|
||||
either includes or exceptions) is not to include. */
|
||||
long *exceptions; /* 0L terminated; octet w/255 means wildcard */
|
||||
} *shared_prefixes = NULL;
|
||||
|
||||
extern void p_init_shared_prefixes(void);
|
||||
|
||||
char *
|
||||
check_localpath(char *path, long client)
|
||||
{
|
||||
struct shared_prefixes *spp;
|
||||
AUTOSTAT_CHARPP(rempathp); /* remapped path that we return */
|
||||
char **locp; /* pointer to locals */
|
||||
long *ipaddrp; /* pointer to IP addresses */
|
||||
|
||||
|
||||
#ifndef PFS_THREADS
|
||||
if (!shared_prefixes) p_init_shared_prefixes();
|
||||
#else
|
||||
assert(shared_prefixes); /* must have been called from dirsrv */
|
||||
#endif
|
||||
|
||||
/* Try to match local path */
|
||||
for (spp = shared_prefixes; spp->locals; ++spp)
|
||||
for (locp = spp->locals; *locp; ++locp)
|
||||
if (strnequal(*locp, path, p__bstsize(*locp) - 1))
|
||||
goto prefixmatch; /* prefix match */
|
||||
|
||||
prefixmatch:
|
||||
if (!spp->locals) return NULL; /* no match */
|
||||
/* Now make sure one of the includes addresses matches. */
|
||||
for (ipaddrp = spp->includes; *ipaddrp; ++ipaddrp) {
|
||||
if ((((*ipaddrp & 0xff000000) == 0xff000000)
|
||||
|| ((*ipaddrp & 0xff000000) == (client & 0xff000000)))
|
||||
&& (((*ipaddrp & 0x00ff0000) == 0x00ff0000)
|
||||
|| ((*ipaddrp & 0x00ff0000) == (client & 0x00ff0000)))
|
||||
&& (((*ipaddrp & 0x0000ff00) == 0x0000ff00)
|
||||
|| ((*ipaddrp & 0x0000ff00) == (client & 0x0000ff00)))
|
||||
&& (((*ipaddrp & 0x000000ff) == 0x000000ff)
|
||||
|| ((*ipaddrp & 0x000000ff) == (client & 0x000000ff))))
|
||||
break;
|
||||
}
|
||||
if (*ipaddrp == 0L) /* no matches */
|
||||
return NULL;
|
||||
/* Now make sure none of the exceptions addresses matches. */
|
||||
for (ipaddrp = spp->exceptions; *ipaddrp; ++ipaddrp) {
|
||||
if ((((*ipaddrp & 0xff000000) == 0xff000000)
|
||||
|| ((*ipaddrp & 0xff000000) == (client & 0xff000000)))
|
||||
&& (((*ipaddrp & 0x00ff0000) == 0x00ff0000)
|
||||
|| ((*ipaddrp & 0x00ff0000) == (client & 0x00ff0000)))
|
||||
&& (((*ipaddrp & 0x0000ff00) == 0x0000ff00)
|
||||
|| ((*ipaddrp & 0x0000ff00) == (client & 0x0000ff00)))
|
||||
&& (((*ipaddrp & 0x000000ff) == 0x000000ff)
|
||||
|| ((*ipaddrp & 0x000000ff) == (client & 0x000000ff))))
|
||||
return NULL; /* found a match */
|
||||
}
|
||||
/* We have a match. Map it! */
|
||||
*rempathp = qsprintf_stcopyr(*rempathp, "%s%s", spp->remote,
|
||||
path + strlen(*locp));
|
||||
return *rempathp;
|
||||
}
|
||||
|
||||
static long wcinet_aton(char *ascaddr);
|
||||
|
||||
/* Now called from dirsrv() upon initialization, so that we don't have to
|
||||
initialize it automatically in multithreaded case. */
|
||||
void
|
||||
p_init_shared_prefixes(void)
|
||||
{
|
||||
char **cp;
|
||||
int numnulls = 0;
|
||||
int numentries; /* # of entries in the shared_prefixes array */
|
||||
int centry; /* index of entry being initialized */
|
||||
static char *init_sd[] = SHARED_PREFIXES;
|
||||
int i; /* I is just a reused index variable; value is also used right
|
||||
after a loop closes, in an assertion check. */
|
||||
|
||||
|
||||
/* Count the # of entries */
|
||||
for (i = 0; i < sizeof init_sd / sizeof init_sd[0]; ++i)
|
||||
if (init_sd[i] == NULL) ++numnulls;
|
||||
/* More efficient version of: if ((numnulls % 4) != 0) */
|
||||
if (numnulls & 0x3) {
|
||||
plog(L_DATA_FRM_ERR, NOREQ,
|
||||
"Incorrectly formatted SHARED_PREFIXES entry in \
|
||||
the pserver.h configuration file; got %d excess NULLs (out of %d total). The number \
|
||||
of NULLs will always be an even multiple of 4 in a correctly formatted \
|
||||
SHARED_PREFIXES configuration file.", numnulls & 0x3, numnulls);
|
||||
plog(L_DATA_FRM_ERR, NOREQ,
|
||||
"Please correct this. In the mean time, this server will \
|
||||
muddle on as best it can.");
|
||||
}
|
||||
numentries = (numnulls >> 2);
|
||||
/* Allocate one extra as a sentinel marking end of the array. */
|
||||
shared_prefixes =
|
||||
(struct shared_prefixes *)
|
||||
stalloc(sizeof *shared_prefixes * (numentries + 1));
|
||||
shared_prefixes[numentries].locals = NULL;
|
||||
/* finish initializing */
|
||||
for (centry = 0, cp = init_sd; centry < numentries; ++centry) {
|
||||
int subarraynelem;
|
||||
/* continue to use I above as an index. */
|
||||
|
||||
/* count # of entries for locals */
|
||||
for (subarraynelem = 0; cp[subarraynelem]; ++subarraynelem)
|
||||
;
|
||||
shared_prefixes[centry].locals =
|
||||
(char **) stalloc((1 + subarraynelem) * sizeof (char *));
|
||||
i = 0;
|
||||
for(;*cp; ++cp)
|
||||
shared_prefixes[centry].locals[i++] = stcopy(*cp);
|
||||
shared_prefixes[centry].locals[i] = NULL;
|
||||
assert(i == subarraynelem); /* sanity check */
|
||||
++cp; /* onto remote entry */
|
||||
if (*cp) {
|
||||
shared_prefixes[centry].remote = stcopy(*cp);
|
||||
if (*++cp) {
|
||||
plog(L_DATA_FRM_ERR, NOREQ,
|
||||
"Incorrectly formatted SHARED_PREFIXES entry in \
|
||||
pserver.h configuration file: only one remote prefix should be specified per \
|
||||
entry. This occurred while scanning the %dth entry.", centry);
|
||||
plog(L_DATA_FRM_ERR, NOREQ,
|
||||
"Please correct this. In the mean time, this \
|
||||
server will muddle on as best it can.");
|
||||
while (*++cp) /* skip irrelevant entries. */
|
||||
;
|
||||
}
|
||||
}
|
||||
else
|
||||
shared_prefixes[centry].remote = NULL;
|
||||
++cp; /* onto include internet addrs. */
|
||||
|
||||
/* count # of entries for includes */
|
||||
for (subarraynelem = 0; cp[subarraynelem]; ++subarraynelem)
|
||||
;
|
||||
shared_prefixes[centry].includes =
|
||||
(long *) stalloc((1 + subarraynelem) * sizeof (long));
|
||||
for(i = 0; *cp; ++cp, ++i)
|
||||
shared_prefixes[centry].includes[i] = wcinet_aton(*cp);
|
||||
shared_prefixes[centry].includes[i] = 0L;
|
||||
assert(i == subarraynelem); /* sanity check */
|
||||
++cp; /* onto exceptions entry */
|
||||
/* count # of entries for exceptions */
|
||||
for (subarraynelem = 0; cp[subarraynelem]; ++subarraynelem)
|
||||
;
|
||||
shared_prefixes[centry].exceptions =
|
||||
(long *) stalloc((1 + subarraynelem) * sizeof (long));
|
||||
for(i = 0; *cp; ++cp, ++i)
|
||||
shared_prefixes[centry].exceptions[i] = wcinet_aton(*cp);
|
||||
shared_prefixes[centry].exceptions[i] = 0L;
|
||||
assert(i == subarraynelem); /* sanity check */
|
||||
++cp; /* onto next entry, if there is one. */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* If there are any problems with the format, return 127.0.0.1, which will
|
||||
never be useful, since the local AM code will already snag it. Yaay! */
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define LOOPBACK_ADDR 0x7f000001
|
||||
/* octets are numbered 'a' for leftmost in ascii form, 'b', 'c', and 'd' for
|
||||
rightmost. */
|
||||
#define octetat(octetnum, value) ((value & 0xff) << ((3 - octetnum) * 8))
|
||||
#else
|
||||
#define LOOPBACK_ADDR 0x0100007f
|
||||
#define octetat(octetnum, value) ((value & 0xff) << (octetnum * 8))
|
||||
#endif
|
||||
|
||||
|
||||
/* This icky function takes an internet address with exactly 4 octets in it,
|
||||
* separated by 3 dots. The octets may be exactly one of:
|
||||
* a) decimal numbers between 0 and 255
|
||||
* b) * -- indicates wildcard
|
||||
* c) % -- indicates address of current host.
|
||||
*/
|
||||
static long
|
||||
wcinet_aton(char *asc_addr)
|
||||
{
|
||||
char workaddr[30]; /* working copy of ascii address. */
|
||||
long retval = 0L;
|
||||
char *thisp, *nextp;
|
||||
int octetval;
|
||||
|
||||
if (strlen(asc_addr) >= sizeof workaddr)
|
||||
goto malformed;
|
||||
strcpy(workaddr, asc_addr); /* leave asc_addr for error reporting */
|
||||
|
||||
|
||||
thisp = nextp = workaddr;
|
||||
nextp = strchr(nextp, '.');
|
||||
if (!nextp) goto malformed;
|
||||
*nextp = '\0';
|
||||
++nextp;
|
||||
if ((octetval = parse_octet(0, thisp)) < 0)
|
||||
goto malformed;
|
||||
retval |= octetat(0, octetval);
|
||||
thisp = nextp;
|
||||
nextp = strchr(nextp, '.');
|
||||
if (!nextp) goto malformed;
|
||||
*nextp = '\0';
|
||||
++nextp;
|
||||
if ((octetval = parse_octet(1, thisp)) < 0)
|
||||
goto malformed;
|
||||
retval |= octetat(1, octetval);
|
||||
thisp = nextp;
|
||||
nextp = strchr(nextp, '.');
|
||||
if (!nextp) goto malformed;
|
||||
*nextp = '\0';
|
||||
++nextp;
|
||||
if ((octetval = parse_octet(2, thisp)) < 0)
|
||||
goto malformed;
|
||||
retval |= octetat(2, octetval);
|
||||
thisp = nextp;
|
||||
if ((octetval = parse_octet(3, thisp)) < 0)
|
||||
goto malformed;
|
||||
retval |= octetat(3, octetval);
|
||||
return retval;
|
||||
|
||||
malformed:
|
||||
plog(L_DATA_FRM_ERR, NOREQ, "Malformed internet address in \
|
||||
SHARED_PREFIXES initializer: %s\n", asc_addr);
|
||||
return INADDR_LOOPBACK; /* in <netinet/in.h> */
|
||||
}
|
||||
|
||||
|
||||
/* 0 to 255, or neg. value for failure/malformed input. */
|
||||
int
|
||||
parse_octet(int octetnum, char *asc_octet)
|
||||
{
|
||||
static long myaddr = 0L; /* safe; updated atomically (in one instr.) */
|
||||
int retval;
|
||||
if (!myaddr) myaddr = myaddress(); /* myaddress() is now safe.
|
||||
Atomic; can't overwrite*/
|
||||
if (strequal(asc_octet, "*")) return 255;
|
||||
if (strequal(asc_octet, "%")) {
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
return (myaddr & (0xff000000 >> (octetnum * 8)))
|
||||
>> ((3 - octetnum) * 8);
|
||||
#else
|
||||
return (myaddr & (0xff << (octetnum * 8))) >> (octetnum * 8);
|
||||
#endif
|
||||
}
|
||||
retval = atoi(asc_octet);
|
||||
for (;*asc_octet; ++asc_octet)
|
||||
if (!isascii(*asc_octet) || !isdigit(*asc_octet))
|
||||
return -1;
|
||||
return retval;
|
||||
}
|
||||
#endif /* SHARED_PREFIXES */
|
||||
845
prospero/lib/psrv/dsdir.c
Normal file
845
prospero/lib/psrv/dsdir.c
Normal file
@@ -0,0 +1,845 @@
|
||||
/*
|
||||
* 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>
|
||||
#include <sys/stat.h> /* sys/types.h included already */
|
||||
/* sys/dir.h on SCO_UNIX doesnt define DIR */
|
||||
#include <pmachine.h>
|
||||
#if defined(SCOUNIX) || defined(SOLARIS) || !defined(USE_SYS_DIR_H)
|
||||
#if defined(PFS_THREADS_SOLARIS) && !defined(_REENTRANT)
|
||||
#define _REENTRANT /* needed to get prototype for readdir_r() */
|
||||
#endif /* defined(PFS_THREADS_SOLARIS) && !defined(_REENTRANT) */
|
||||
#include <dirent.h>
|
||||
#else
|
||||
#include <sys/dir.h>
|
||||
#endif
|
||||
|
||||
#if defined(SOLARIS) /* seems true on pand05.prod.aol.net */
|
||||
#define SOLARIS_GCC_BROKEN_LIMITS_H
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sgtty.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <pserver.h>
|
||||
#include <ardp.h>
|
||||
#include <pfs.h>
|
||||
#include <plog.h>
|
||||
#include <pprot.h>
|
||||
#include <perrno.h>
|
||||
#include <pmachine.h>
|
||||
#include <pparse.h>
|
||||
#include <psrv.h> /* For dsrfinfo etc */
|
||||
#include <posix_signal.h> /* Needed on SOLARIS for sigset_t etc */
|
||||
#include <mitra_macros.h> /* For L2 */
|
||||
|
||||
#define DIR_VNO 5 /* version # of the directory format. */
|
||||
|
||||
extern char root[];
|
||||
extern char shadow[];
|
||||
extern char dirshadow[];
|
||||
extern char dircont[];
|
||||
#define TMP_DIRNAME_SUFFIX ".TMP"
|
||||
extern char pfsdat[];
|
||||
extern char aftpdir[];
|
||||
|
||||
extern char hostname[];
|
||||
extern char hostwport[];
|
||||
|
||||
extern char *acltypes[];
|
||||
|
||||
|
||||
static int indsrdir_v5(INPUT in, char vfs_dirname[], VDIR dir, VLINK ul);
|
||||
static int reload_native_cache(char native_dirname[], VDIR dir);
|
||||
static int check_vfs_dir_forwarding(VDIR dir, char name[], long magic);
|
||||
static size_t canonicalize_prefix(char *native_name, char canon_buf[],
|
||||
size_t canon_bufsiz);
|
||||
size_t nativize_prefix(char *hsoname, char native_buf[], size_t native_bufsiz);
|
||||
|
||||
/*
|
||||
Policy for caching native links:
|
||||
1) If a native directory is converted to NONATIVE (The only case in which
|
||||
this happens in the current code is if a native link was
|
||||
deleted in it), then it's now entirely virtual, and all native links are
|
||||
saved.
|
||||
2) If the compilation option PSRV_CACHE_NATIVE is set, then
|
||||
all native links and their attributes are cached. The cache is reloaded
|
||||
whenever the native MTIME has changed. The CACHED attributes on a link will
|
||||
also be reloaded whenever an UPDATE protocol message is sent (that mechanism
|
||||
is not handled in dsdir). If no special compilation option is defined,
|
||||
NATIVE-ONLY directories are guaranteed to be not cached unless at least one
|
||||
link attribute is set on a link in that directory.
|
||||
3) In any case, a entry will be written out for a directory if any attribute
|
||||
is set (via EDIT-LINK-INFO) on an entry in that directory. NATIVE links with
|
||||
LINK attributes on them WILL be written out, but other NATIVE links in the
|
||||
directory may or may not be.
|
||||
4) For the current implementation, all directories that are not NATIVE-ONLY
|
||||
are always written out and NATIVE-ONLY directories with links with non-OBJECT
|
||||
and non-CACHED attributes are always written out.
|
||||
*/
|
||||
/* Thoughts on this:
|
||||
This will break if we start caching partial attribute reads. Therefore, the
|
||||
solution for THAT is to have a new attribute value type called UNSET. This
|
||||
will always be CACHED and means that the corresponding OBJECT attribute is
|
||||
UNSET and therefore need not be verified. This can become a part of the
|
||||
protocol.
|
||||
|
||||
We'll also still have the problem of partially-cached reads not containing
|
||||
all values. E.g.: checking of INTRINSIC+ should probably be disabled, no?
|
||||
So, CONTENTS is special. So perhaps a special tag on the cached data saying
|
||||
whether it contains all INTRINSIC attributes. Also, a test whether a
|
||||
particular attribute is INTRINSIC+ or just INTRINSIC.
|
||||
|
||||
A quicker solution is not to cache partial attribute reads.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* New policy: the PFSDAT directory must be NONATIVE. This is enforced.
|
||||
* Fixes some old bugs.
|
||||
*/
|
||||
|
||||
/*
|
||||
* dsrdir - Read the contents of a directory from disk
|
||||
*
|
||||
* DSRDIR is used by the directory server to read the contents of
|
||||
* a directory off disk. It takes the host specific part of the system
|
||||
* level name of the directory as an argument, and a directory structure
|
||||
* which it fills in.
|
||||
* If the directory is forwarded, it returns DSRFINFO_FORWARDED.
|
||||
* On error, it returns an error code and logs the circumstances to plog().
|
||||
* It may also return a warning code.
|
||||
*
|
||||
* dsrdir() is frequently called to expand union links. Therefore,
|
||||
* it must be careful about caching. */
|
||||
int
|
||||
dsrdir(hsoname,magic,dir,ul,flags)
|
||||
char *hsoname; /* hsoname */
|
||||
int magic; /* magic # specified in DIRECTORY command */
|
||||
VDIR dir; /* dir to fill in */
|
||||
VLINK ul; /* Pointer to the vlink currently being expanded */
|
||||
/* used for location to insert new union links */
|
||||
int flags; /* DSRD_ATTRIBUTES = get attributes for files */
|
||||
/* Or DSRD_VERIFY_DIR -- see psrv.h */
|
||||
{
|
||||
FILE *vfs_dir;
|
||||
char vfs_dirname[MAXPATHLEN]; /* name of .directory#contents file */
|
||||
char native_dirname[MAXPATHLEN]; /* name of physical directory
|
||||
corresponding to 'hsoname'. Only
|
||||
differs from 'hsoname' if "AFTP" or
|
||||
other special prefix in use. */
|
||||
int tmp;
|
||||
int vfs_dir_problem = 0; /* 1 if failure while reading VFS dir. */
|
||||
time_t native_dir_mtime; /* mtime of native dir. */
|
||||
int return_value = DSRDIR_NOT_A_DIRECTORY;
|
||||
int pfsdatlen = strlen(pfsdat);
|
||||
|
||||
|
||||
nativize_prefix(hsoname, native_dirname, sizeof native_dirname);
|
||||
strcpy(vfs_dirname,shadow);
|
||||
strcat(vfs_dirname,native_dirname);
|
||||
strcat(vfs_dirname,"/");
|
||||
|
||||
strcat(vfs_dirname,dircont);
|
||||
|
||||
/* vfs_dirname is now the name of a file which, if it exists, means we are
|
||||
guaranteed that the virtual directory exists. */
|
||||
|
||||
/* native_dirname is the name of a local UNIX directory which, if it
|
||||
exists, will be read to produce a virtual directory. */
|
||||
|
||||
/* Special case code for common case of verifying */
|
||||
if (flags & DSRD_VERIFY_DIR) {
|
||||
if (is_file(vfs_dirname) || is_dir(native_dirname))
|
||||
return PSUCCESS; /* VERIFIED the directory exists */
|
||||
else
|
||||
return PFAILURE;
|
||||
}
|
||||
dir->version = -1;
|
||||
dir->magic_no = 0;
|
||||
dir->inc_native = VDIN_INCLREAL; /* Include native if can't read */
|
||||
dir->f_info = NULL;
|
||||
dir->dacl = NULL;
|
||||
|
||||
/* XXX This should no longer be necessary. */
|
||||
if(ul == NULL) { /* Don't clear links if expanding */
|
||||
dir->links = NULL;
|
||||
dir->ulinks = NULL;
|
||||
}
|
||||
|
||||
/* Check whether cacheing will be ok. */
|
||||
/* Special code in dump_links to handle ULINK_PLACEHOLDER */
|
||||
if (!dir->links &&
|
||||
(!dir->ulinks ||
|
||||
!dir->ulinks->next && dir->ulinks->expanded == ULINK_PLACEHOLDER))
|
||||
dir->flags |= VDIR_FIRST_READ;
|
||||
else
|
||||
dir->flags &= ~VDIR_FIRST_READ;
|
||||
|
||||
|
||||
/* NOTE: A temporary inefficient directory format is */
|
||||
/* in use. It will be changed. */
|
||||
|
||||
/* Read the contents of the VFS directory */
|
||||
if((vfs_dir = locked_fopen(vfs_dirname,"r")) != NULL) {
|
||||
INPUT_ST in_st;
|
||||
INPUT in = &in_st;
|
||||
if(tmp = wholefiletoin(vfs_dir, in)) {
|
||||
locked_fclose_A(vfs_dir, vfs_dirname, TRUE);
|
||||
plog(L_DIR_ERR,NOREQ,"%s",p_err_string);
|
||||
return tmp;
|
||||
}
|
||||
if (ferror(vfs_dir)) vfs_dir_problem++;
|
||||
if (locked_fclose_A(vfs_dir, vfs_dirname, TRUE)) vfs_dir_problem++;
|
||||
VLDEBUGBEGIN;
|
||||
return_value = indsrdir_v5(in, vfs_dirname, dir, ul);
|
||||
VLDEBUGDIR(dir);
|
||||
VLDEBUGEND;
|
||||
/* What it means when indsrdir_v5 returns an error is not fully
|
||||
clearly defined. */
|
||||
if (return_value) vfs_dir_problem++;
|
||||
} else /* Note that this directory is entirely native */
|
||||
(dir->inc_native = VDIN_ONLYREAL);
|
||||
|
||||
/* (Re)load the contents of the native directory into the current cached
|
||||
listing if cache is out of date or not present. */
|
||||
/* This comment is from MITRA and I disavow it. --swa, 5/17/94 */
|
||||
/* mitra: I havent corrected this behaviour for VDIN_PSEUDO yet
|
||||
behaviour if their is a real directory is unpredictable */
|
||||
if(dir->inc_native != VDIN_NONATIVE &&
|
||||
(native_dir_mtime = mtime(native_dirname)) > dir->native_mtime) {
|
||||
/* Report an error if we couldn't read the native directory. */
|
||||
return_value = reload_native_cache(native_dirname, dir);
|
||||
if (!return_value && !vfs_dir_problem
|
||||
&& (dir->flags & VDIR_FIRST_READ)) {
|
||||
/* XXX Need to set a don't-ever-write flag if there are problems so
|
||||
that we know we can't support updates to this directory. */
|
||||
/* if we successfully reloaded the cache */
|
||||
/* update mod time. Use a value of mtime guaranteed to be before
|
||||
reload_native_cache() started reading. */
|
||||
dir->native_mtime = native_dir_mtime;
|
||||
#ifndef PSRV_CACHE_NATIVE /* don't bother writing out changes if not
|
||||
cacheing. */
|
||||
if (dir->inc_native != VDIN_ONLYREAL)
|
||||
#endif
|
||||
/* Write out the changes. Failure to write out the updated
|
||||
cache is not an error, but does yield a warning. */
|
||||
if (tmp = dswdir(hsoname, dir)) {
|
||||
p_warn_string = qsprintf_stcopyr(p_warn_string,
|
||||
"Failed to update native cache for directory %'s:\
|
||||
Prospero error %d", hsoname, tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Handle directory forwarding. */
|
||||
if((return_value != PSUCCESS) || (dir->magic_no != magic))
|
||||
if (check_vfs_dir_forwarding(dir, hsoname, magic)
|
||||
== DSRFINFO_FORWARDED)
|
||||
return DSRFINFO_FORWARDED;
|
||||
/* Directories in the pfsdat area must be NONATIVE */
|
||||
if (strnequal(hsoname, pfsdat, pfsdatlen)
|
||||
&& (hsoname[pfsdatlen] == '/' || hsoname[pfsdatlen] == '\0'))
|
||||
dir->inc_native = VDIN_NONATIVE;
|
||||
return(return_value);
|
||||
}
|
||||
|
||||
|
||||
/* Returns PSUCCESS if no forwarding, DSRFINFO_FORWARDING if forwarding
|
||||
occurred. This is only called if the directory's magic number has a
|
||||
mismatch. */
|
||||
static int
|
||||
check_vfs_dir_forwarding(VDIR dir, char hsoname[], long magic)
|
||||
{
|
||||
PFILE dfi = pfalloc();
|
||||
int tmp = dsrfinfo(hsoname,magic,dfi);
|
||||
if(tmp == DSRFINFO_FORWARDED) {
|
||||
dir->f_info = dfi;
|
||||
return(DSRFINFO_FORWARDED);
|
||||
}
|
||||
/* This bit of code may not be necessary. Anyway, this stuff is
|
||||
getting replaced soon. --swa@isi.edu */
|
||||
else if((dir->magic_no < 0) && dfi->forward) {
|
||||
dir->f_info = dfi;
|
||||
return(DSRFINFO_FORWARDED);
|
||||
}
|
||||
pffree(dfi);
|
||||
return PSUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Returns PFAILURE if it attempts to read a malformed directory;
|
||||
PSUCCESS if all went well. */
|
||||
static
|
||||
int
|
||||
indsrdir_v5(INPUT in, char vfs_dirname[], VDIR dir, VLINK ul)
|
||||
{
|
||||
char *command, *next_word;
|
||||
char include_native[30];
|
||||
char *cp; /* dummy pointer */
|
||||
VLINK cur_link = NULL; /* set this when we see a link. */
|
||||
int seen_version = 0; /* seen directory format version #? */
|
||||
|
||||
while(in_nextline(in)) {
|
||||
char t_timestring[30];
|
||||
|
||||
if(in_line(in, &command, &next_word)) {
|
||||
plog(L_DATA_FRM_ERR, NOREQ, "Couldn't read line from %s: %s",
|
||||
vfs_dirname, p_err_string);
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
|
||||
if (qsscanf(command, "VERSION %d %r", &(dir->version), &cp) == 1) {
|
||||
if (dir->version != DIR_VNO) {
|
||||
plog(L_DATA_FRM_ERR, NOREQ,
|
||||
"Bad directory info format: %s: Encountered VERSION %d; \
|
||||
dirsrv can only interpret version %d", vfs_dirname, dir->version, DIR_VNO);
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
seen_version++;
|
||||
continue;
|
||||
}
|
||||
if (!seen_version) {
|
||||
plog(L_DATA_FRM_ERR, NOREQ,
|
||||
"Bad directory info format: %s: VERSION line not found; must \
|
||||
appear at the start of the file.", vfs_dirname);
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
if (qsscanf(command, "MAGIC-NUMBER %d %r", &(dir->magic_no), &cp) == 1)
|
||||
continue;
|
||||
if (qsscanf(command, "INCLUDE-NATIVE %!!s %r",
|
||||
include_native, sizeof include_native, &cp) == 1) {
|
||||
if(strequal(include_native, "INCLNATIVE"))
|
||||
dir->inc_native = VDIN_INCLNATIVE;
|
||||
else if (strequal(include_native, "INCLREAL"))
|
||||
dir->inc_native = VDIN_INCLREAL;
|
||||
else if (strequal(include_native, "NONATIVE"))
|
||||
dir->inc_native = VDIN_NONATIVE;
|
||||
else if (strequal(include_native, "PSEUDO"))
|
||||
dir->inc_native = VDIN_PSEUDO;
|
||||
else {
|
||||
plog(L_DATA_FRM_ERR, NOREQ,
|
||||
"Bad directory info format %s: %s", vfs_dirname, command);
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (qsscanf(command, "NATIVE-MTIME %!!s %r",
|
||||
t_timestring, sizeof t_timestring, &cp) == 1) {
|
||||
dir->native_mtime = asntotime(t_timestring);
|
||||
continue;
|
||||
}
|
||||
if (qsscanf(command, "ACL %r", &cp) == 1) {
|
||||
if (cur_link) {
|
||||
if(in_ge1_acl(in, command, next_word, &cur_link->acl)) {
|
||||
plog(L_DATA_FRM_ERR, NOREQ,
|
||||
"Bad directory info format %s: %s",
|
||||
vfs_dirname, p_err_string);
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
} else {
|
||||
if(in_ge1_acl(in, command, next_word, &dir->dacl)) {
|
||||
plog(L_DATA_FRM_ERR, NOREQ,
|
||||
"Bad directory info format %s: %s",
|
||||
vfs_dirname, p_err_string);
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* in_link() will automatically call in_atrs. */
|
||||
if (qsscanf(command, "LINK %r", &next_word) == 1) {
|
||||
if(in_link(in, command, next_word, 0, &cur_link,
|
||||
(TOKEN *) NULL)) {
|
||||
plog(L_DATA_FRM_ERR, NOREQ,
|
||||
"Bad directory info format %s: %s",
|
||||
vfs_dirname, p_err_string);
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
/* if union link without UL variable set, then vl_insert will
|
||||
insert it at the end of the list of union links. */
|
||||
|
||||
/* This call to ul_insert() makes sure that, *if*
|
||||
list() is in the process of expanding union links, any new
|
||||
union links are inserted in the right position (i.e., right
|
||||
after the link we're currently expanding). This makes sure
|
||||
that nested union links are expanded in the proper order,
|
||||
whereas calling vl_insert() would instead mean that the
|
||||
new union link CUR_LINK was stuck at the end of the
|
||||
directory's list of union links; this would be wrong.
|
||||
Also, ul_insert() checks for conflicts if given an insertion
|
||||
positon. */
|
||||
if(ul && cur_link->linktype == 'U') {
|
||||
int tmp = ul_insert(cur_link,dir,ul);
|
||||
if(!tmp) ul = cur_link; /* A subsequent identical link in this
|
||||
directory won't supersede this one.
|
||||
*/
|
||||
} else {
|
||||
/* vl_insert(cur_link, dir, VLI_ALLOW_CONF); */
|
||||
/* this is an experiment in efficiency. */
|
||||
vl_insert(cur_link, dir, VLI_NOSORT);
|
||||
}
|
||||
/* By this point cur_link should be inserted so dont free */
|
||||
/* If it's a native link, then set the flags appropriately. */
|
||||
if (cur_link->linktype == 'n') {
|
||||
cur_link->linktype = 'I';
|
||||
cur_link->flags |= VLINK_NATIVE;
|
||||
} else if (cur_link->linktype == 'N') {
|
||||
cur_link->linktype = 'L';
|
||||
cur_link->flags |= VLINK_NATIVE;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* Gee, nothing seems to match. Guess it must be an error. */
|
||||
plog(L_DATA_FRM_ERR, NOREQ, "Bad directory info format %s: %s",
|
||||
vfs_dirname, command);
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
return PSUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* dswdir - Write directory contents to disk
|
||||
*
|
||||
* On success, returns PSUCCESS. On error, returns an error code but does
|
||||
* not set p_err_string.
|
||||
*
|
||||
* The contents of the
|
||||
* Any OBJECT attributes to be written will be automatically downgraded to
|
||||
* CACHED.
|
||||
* Any INTRINSIC namespace attributes will not be written.
|
||||
*/
|
||||
int
|
||||
dswdir(char *name,VDIR dir)
|
||||
{
|
||||
char vfs_dirname[MAXPATHLEN];
|
||||
char tmp_vfs_dirname[MAXPATHLEN];
|
||||
FILE *vfs_dir;
|
||||
int retval;
|
||||
|
||||
|
||||
/* if a VFS directory, then create it if necessary */
|
||||
if(strnequal(pfsdat,name,strlen(pfsdat)))
|
||||
if(mkdirs(name)) RETURNPFAILURE;
|
||||
|
||||
/* Determine name of shadow */
|
||||
strcpy(vfs_dirname,shadow);
|
||||
#if 1
|
||||
nativize_prefix(name, vfs_dirname + strlen(shadow),
|
||||
sizeof vfs_dirname - strlen(shadow));
|
||||
#else
|
||||
if((*name != '/') && *aftpdir && (strncmp(name,"AFTP",4) == 0)) {
|
||||
/* Special file name */
|
||||
strcat(vfs_dirname,aftpdir);
|
||||
strcat(vfs_dirname,name+4);
|
||||
}
|
||||
else strcat(vfs_dirname,name);
|
||||
#endif
|
||||
|
||||
/* Create the shadow directory if necessary */
|
||||
if(mkdirs(vfs_dirname)) RETURNPFAILURE;
|
||||
|
||||
/* Determine name of directory contents */
|
||||
strcat(vfs_dirname,"/");
|
||||
strcat(vfs_dirname,dircont);
|
||||
|
||||
|
||||
/* NOTE: A temporary inefficient directory format is */
|
||||
/* in use. For this reason, the code supporting it */
|
||||
/* is also interim code, and does not do any checking */
|
||||
/* to make sure that the directory actually follows */
|
||||
/* the format. This, a munged directory will result */
|
||||
/* in unpredictable results. */
|
||||
|
||||
/* A name to write a temporary directory to. We write to a temporary
|
||||
file and then rename it after it's been successfully written. We do
|
||||
this so that we're guaranteed that if the disk fills up we don't lose
|
||||
any data. */
|
||||
if(qsprintf(tmp_vfs_dirname, sizeof tmp_vfs_dirname, "%s%s",
|
||||
vfs_dirname, TMP_DIRNAME_SUFFIX) > sizeof tmp_vfs_dirname)
|
||||
RETURNPFAILURE;
|
||||
|
||||
|
||||
/* Write the contents of the VFS directory */
|
||||
filelock_obtain(vfs_dirname,FALSE); /* Make sure can write original */
|
||||
if((vfs_dir = locked_fopen(tmp_vfs_dirname,"w")) == NULL) {
|
||||
filelock_release(vfs_dirname,FALSE);
|
||||
return(PFAILURE);
|
||||
}
|
||||
fdswdir_v5(vfs_dir, dir);
|
||||
retval = locked_fclose_and_rename(vfs_dir, tmp_vfs_dirname,
|
||||
vfs_dirname,FALSE);
|
||||
return(retval);
|
||||
|
||||
}
|
||||
|
||||
static void dump_links(OUTPUT out, VLINK cur_link);
|
||||
|
||||
/* Actually returns no useful return value. We check for failures using
|
||||
ferror(). */
|
||||
int fdswdir_v5(FILE *vfs_dir, VDIR dir)
|
||||
{
|
||||
OUTPUT_ST out_st;
|
||||
OUTPUT out = &out_st;
|
||||
VLINK vl;
|
||||
|
||||
filetoout(vfs_dir, out);
|
||||
qoprintf(out, "VERSION %d\n", DIR_VNO);
|
||||
if (dir->magic_no)
|
||||
qoprintf(out, "MAGIC-NUMBER %d\n", dir->magic_no);
|
||||
qoprintf(out, "INCLUDE-NATIVE ");
|
||||
if(dir->inc_native == VDIN_INCLREAL || dir->inc_native == VDIN_ONLYREAL) {
|
||||
qoprintf(out,"INCLREAL\n");
|
||||
} else if(dir->inc_native == VDIN_INCLNATIVE) {
|
||||
qoprintf(out,"INCLNATIVE\n");
|
||||
} else if (dir->inc_native == VDIN_NONATIVE) {
|
||||
qoprintf(out,"NONATIVE\n");
|
||||
/* If directory is not native, shouldn't be any links which are NATIVE
|
||||
*/
|
||||
for (vl = dir->links; vl; vl = vl->next) {
|
||||
vl->flags &= ~VLINK_NATIVE;
|
||||
}
|
||||
} else if (dir->inc_native == VDIN_PSEUDO) {
|
||||
qoprintf(out,"PSEUDO\n");
|
||||
} else
|
||||
internal_error("unknown value of dir->inc_native");
|
||||
if (dir->native_mtime && dir->inc_native != VDIN_NONATIVE) {
|
||||
char *cp = NULL;
|
||||
qoprintf(out, "NATIVE-MTIME %s\n",
|
||||
cp = p_timetoasn_stcopyr(dir->native_mtime, cp));
|
||||
stfree(cp);
|
||||
}
|
||||
/* print out the directory ACL. */
|
||||
out_acl(out, dir->dacl);
|
||||
dump_links(out, dir->links);
|
||||
dump_links(out, dir->ulinks);
|
||||
return PSUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dump_links(OUTPUT out, VLINK cur_link)
|
||||
{
|
||||
for (; cur_link; cur_link = cur_link->next) {
|
||||
PATTRIB ca;
|
||||
FILTER cur_fil;
|
||||
|
||||
/* Special case for ULINK_PLACEHOLDER. */
|
||||
if (cur_link->expanded == ULINK_PLACEHOLDER) continue;
|
||||
/* don't output native links to directory unless we just converted
|
||||
it to NONATIVE, or unless caching is enabled for the native
|
||||
directory, or unless they have attributes beyond the OBJECT ones. */
|
||||
if (cur_link->flags & VLINK_NATIVE) {
|
||||
cur_link->linktype = cur_link->linktype == 'I' ? 'n' : 'N';
|
||||
}
|
||||
qoprintf(out, "LINK ");
|
||||
out_link(out, cur_link, 0, (TOKEN) NULL);
|
||||
for (ca = cur_link->lattrib; ca; ca = ca->next) {
|
||||
if (ca->nature != ATR_NATURE_INTRINSIC) {
|
||||
if (ca->precedence == ATR_PREC_OBJECT)
|
||||
ca->precedence = ATR_PREC_CACHED;
|
||||
out_atr(out, ca, 0);
|
||||
}
|
||||
}
|
||||
for (cur_fil = cur_link->filters; cur_fil; cur_fil = cur_fil->next) {
|
||||
qoprintf(out, "ATTRIBUTE LINK FIELD FILTER FILTER ");
|
||||
out_filter(out, cur_fil, 0);
|
||||
}
|
||||
out_acl(out, cur_link->acl);
|
||||
if (cur_link->flags & VLINK_NATIVE) {
|
||||
cur_link->linktype = cur_link->linktype == 'N' ? 'L' : 'I';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static VLINK read_native_dir(char native_dirname[], int inc_native_flag,
|
||||
int read_attributes, int read_basetype);
|
||||
static void merge_native(VLINK links, VDIR dir);
|
||||
|
||||
/* PSUCCESS if all went well; anything else if problems. */
|
||||
static int
|
||||
reload_native_cache(char native_dirname[], VDIR dir)
|
||||
{
|
||||
VLINK links = read_native_dir(native_dirname, dir->inc_native, 1, 1);
|
||||
if (!links & perrno) return perrno;
|
||||
merge_native(links, dir); /* can't fail */
|
||||
return PSUCCESS; /* done! */
|
||||
}
|
||||
|
||||
|
||||
static void replace_cached(PATTRIB *nativeatlp, PATTRIB *vdiratlp);
|
||||
|
||||
/* Merge the native directory listing with the links read in from disk (if
|
||||
ANY!). Free the unused LINKS. */
|
||||
static void
|
||||
merge_native(VLINK links, VDIR dir)
|
||||
{
|
||||
register VLINK curl, nxtl; /* do a for loop with CURrent and NeXT link
|
||||
references since we may delete the current
|
||||
link. */
|
||||
/* Optimize a common case. This will be the case for every directory that
|
||||
is pure VDIN_ONLYREAL */
|
||||
if (!dir->links) {
|
||||
dir->links = links;
|
||||
return;
|
||||
}
|
||||
/* Each native link we confirm in DIR is tagged as CONFIRMED. */
|
||||
for (curl = links, nxtl = curl ? curl->next : NULL;
|
||||
curl;
|
||||
curl = nxtl, nxtl = curl ? curl->next : NULL) {
|
||||
VLINK vl;
|
||||
/* Search in the existing directory for a VLINK that matches CURL */
|
||||
for (vl = dir->links; vl; vl = vl->next) {
|
||||
if (!(vl->flags & VLINK_CONFIRMED) /* only do ones from this
|
||||
directory */
|
||||
&& (vl->flags & VLINK_NATIVE) && vl_equal(curl, vl)) {
|
||||
/* match found. Update any CACHED attributes on the link in
|
||||
the directory from those in the native link. Note that
|
||||
vl_equal() ignores the L/I LINKTYPE distinction. */
|
||||
vl->flags |= VLINK_CONFIRMED;
|
||||
replace_cached(&curl->lattrib, &vl->lattrib);
|
||||
EXTRACT_ITEM(curl, links);
|
||||
vlfree(curl);
|
||||
goto next_native; /* on to the next native link. */
|
||||
}
|
||||
}
|
||||
/* No match found for CURL. Plop it on the list. */
|
||||
EXTRACT_ITEM(curl, links); /* so we don't munge pointers in the list
|
||||
links. (This was a PERNICIOUS bug). */
|
||||
APPEND_ITEM(curl, dir->links);
|
||||
curl->flags |= VLINK_CONFIRMED | VLINK_NATIVE;
|
||||
next_native:
|
||||
}
|
||||
/* Remove any NATIVE links that are not CONFIRMED */
|
||||
/* We do not again use VLINK_CONFIRMED. Don't bother turning it off on the
|
||||
links, since that would just be more expensive. */
|
||||
for (curl = dir->links, nxtl = L2(curl,next);
|
||||
curl;
|
||||
curl = nxtl, nxtl = L2(curl,next)) {
|
||||
if ((curl->flags & VLINK_NATIVE) && !(curl->flags & VLINK_CONFIRMED)) {
|
||||
EXTRACT_ITEM(curl, dir->links);
|
||||
vlfree(curl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Replace all the CACHED and OBJECT attributes on VLATL with all OBJECT
|
||||
attributes from the list on NATIVEATLP. Make sure that *nativeatlp does not
|
||||
point to memory that we don't want to be freed. */
|
||||
static void
|
||||
replace_cached(PATTRIB *nativeatlp, PATTRIB *vlatlp)
|
||||
{
|
||||
PATTRIB ca, ca_temp;
|
||||
/* Flush all CACHED attributes on VLATL */
|
||||
for (ca = *vlatlp; ca; ca = ca_temp) {
|
||||
ca_temp = ca->next;
|
||||
if (ca->precedence == ATR_PREC_CACHED
|
||||
|| ca->precedence == ATR_PREC_OBJECT) {
|
||||
EXTRACT_ITEM(ca, *vlatlp);
|
||||
atfree(ca);
|
||||
}
|
||||
}
|
||||
/* Put the OBJECT attributes on the VLATL. They will be sent out as
|
||||
OBJECT attributes. Code in dswdir() converts them to CACHED attributes
|
||||
upon write. */
|
||||
/* Future efficiency speedup: Replace this loop with the CONCATENATE_LISTS
|
||||
macro. */
|
||||
CONCATENATE_LISTS(*vlatlp, *nativeatlp);
|
||||
/* *nativeatlp will automatically be set to NULL by the CONCATENATE_LISTS
|
||||
macro. */
|
||||
}
|
||||
|
||||
#include <limits.h> /* for _POSIX_PATH_MAX for readdir_result. */
|
||||
|
||||
#ifndef SOLARIS_GCC_BROKEN_LIMITS_H
|
||||
#include <limits.h> /* for _POSIX_PATH_MAX for readdir_result. */
|
||||
#else
|
||||
#ifndef _POSIX_PATH_MAX
|
||||
#undef _LIMITS_H
|
||||
#include "/usr/include/limits.h"
|
||||
/* XXX why on earth is this not defining _POSIX_PATH_MAX? At any rate,
|
||||
pick a really large number that will certainly work well enough for now. */
|
||||
#ifndef _POSIX_PATH_MAX
|
||||
#define _POSIX_PATH_MAX 2048
|
||||
#endif
|
||||
#endif /* not _POSIX_PATH_MAX */
|
||||
#endif /* SOLARIS_GCC_BROKEN_LIMITS_H */
|
||||
|
||||
/* Return a linked list of files with the VLINK_NATIVE flag set on them. */
|
||||
/* The flags are both always set for now. They will be useful later if various
|
||||
degrees of #FAST are specified. */
|
||||
/* Error reporting: return NULL and set perrno. */
|
||||
static VLINK
|
||||
read_native_dir(char native_dirname[],
|
||||
int inc_native_flag,
|
||||
int read_attributes, /* implies read_basetype. */
|
||||
int read_basetype) /* make sure basetype is correct in
|
||||
listing */
|
||||
{
|
||||
DIR *dirp;
|
||||
struct dirent *dp;
|
||||
#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
|
||||
char *slash;
|
||||
char vl_hsoname[MAXPATHLEN];
|
||||
VLINK retval = NULL; /* list of links to return. */
|
||||
VLINK cur_link;
|
||||
int tmp;
|
||||
|
||||
if(is_dir(native_dirname) != 1) {
|
||||
perrno = DSRDIR_NOT_A_DIRECTORY;
|
||||
return NULL;
|
||||
}
|
||||
if((dirp = opendir(native_dirname)) == NULL) {
|
||||
perrno = PFAILURE;
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,"%s",unixerrstr());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef PFS_THREADS
|
||||
for (dp = readdir_r(dirp, readdir_result); dp != NULL;
|
||||
dp = readdir_r(dirp, readdir_result)) {
|
||||
#else /* PFS_THREADS */
|
||||
for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
|
||||
#endif /* PFS_THREADS */
|
||||
canonicalize_prefix(native_dirname, vl_hsoname, sizeof vl_hsoname);
|
||||
|
||||
/* We must special case unix concept of . and .. */
|
||||
/* if we want to eliminate useless parts of path */
|
||||
/* If the filename is "..", then */
|
||||
if(strequal(dp->d_name,"..")) {
|
||||
#ifdef NODOTDOT
|
||||
continue;
|
||||
#else
|
||||
if(inc_native_flag == VDIN_INCLREAL ||
|
||||
inc_native_flag == VDIN_ONLYREAL) continue;
|
||||
slash = rindex(vl_hsoname,'/');
|
||||
if(slash) *slash = '\0';
|
||||
else strcpy(vl_hsoname,"/");
|
||||
if(!(*vl_hsoname)) strcpy(vl_hsoname,"/");
|
||||
#endif
|
||||
}
|
||||
/* Else if ".", do nothing. If not "." add to */
|
||||
/* vl_hsoname */
|
||||
else if(!strequal(dp->d_name,".")) {
|
||||
if(*(vl_hsoname + strlen(vl_hsoname) - 1)!='/')
|
||||
strcat(vl_hsoname,"/");
|
||||
strcat(vl_hsoname,dp->d_name);
|
||||
}
|
||||
/* If ".", must still decide if we include it */
|
||||
else if(inc_native_flag == VDIN_INCLREAL ||
|
||||
inc_native_flag == VDIN_ONLYREAL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cur_link = vlalloc();
|
||||
|
||||
cur_link->name = stcopy(dp->d_name);
|
||||
cur_link->hsoname = stcopy(vl_hsoname);
|
||||
cur_link->host = stcopy(hostwport);
|
||||
cur_link->flags = VLINK_NATIVE;
|
||||
#define INVISIBLE_DOT_FILES
|
||||
#ifdef INVISIBLE_DOT_FILES
|
||||
/* Native . files are initially invisible. We do special things to
|
||||
make sure that linktype is not important in comparing two links
|
||||
during a cache reload, since this could be reset after the link
|
||||
is loaded. */
|
||||
if (*cur_link->name == '.')
|
||||
cur_link->linktype = 'I';
|
||||
else
|
||||
cur_link->linktype = 'L';
|
||||
#else
|
||||
cur_link->linktype = 'L';
|
||||
#endif
|
||||
if (read_attributes) {
|
||||
PFILE fi = pfalloc();
|
||||
tmp = dsrfinfo(cur_link->hsoname, cur_link->f_magic_no,fi);
|
||||
if(tmp == -1)
|
||||
cur_link->target = stcopyr("DIRECTORY",cur_link->target);
|
||||
/* 5/16/94: is this the attribute deletion bug? */
|
||||
if(tmp <= 0) {
|
||||
cur_link->lattrib = fi->attributes;
|
||||
fi->attributes = NULL;
|
||||
}
|
||||
pffree(fi);
|
||||
} else if (read_basetype) {
|
||||
char native_filename_buf[MAXPATHLEN];
|
||||
char *native_filename;
|
||||
/* This code saves us the hassle of a trip through nativize_prefix
|
||||
if it is not necessary. */
|
||||
if (cur_link->hsoname[0] != '/') {
|
||||
nativize_prefix(cur_link->hsoname, native_filename,
|
||||
sizeof native_filename);
|
||||
native_filename = native_filename_buf;
|
||||
} else {
|
||||
native_filename = cur_link->hsoname;
|
||||
}
|
||||
if(tmp = is_dir(native_filename)) {
|
||||
if (tmp == 1) {
|
||||
cur_link->target =
|
||||
stcopyr("DIRECTORY",cur_link->target);
|
||||
} else if (tmp == -1) {
|
||||
/* Maybe we should report an error to plog?? */
|
||||
vlfree(cur_link);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
APPEND_ITEM(cur_link, retval);
|
||||
}
|
||||
closedir(dirp);
|
||||
perrno = PSUCCESS;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/* Turns a name of the form /usr/ftp/... (or whatever) into AFTP/... (or
|
||||
whatever). Returns the # of characters it needed to write out the new
|
||||
canonical version of the name. This is the canonical form of the HSONAME.
|
||||
*/
|
||||
static size_t
|
||||
canonicalize_prefix(char *native_name, char canon_buf[], size_t canon_bufsiz)
|
||||
{
|
||||
int aftpdirsiz = strlen(aftpdir);
|
||||
if (*aftpdir && strnequal(native_name, aftpdir, aftpdirsiz)
|
||||
&& (native_name[aftpdirsiz] == '/' ||
|
||||
native_name[aftpdirsiz] == '\0')) {
|
||||
return qsprintf(canon_buf, canon_bufsiz, "AFTP%s",
|
||||
native_name + aftpdirsiz);
|
||||
}
|
||||
return qsprintf(canon_buf, canon_bufsiz, "%s", native_name);
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
nativize_prefix(char *hsoname, char native_buf[], size_t native_bufsiz)
|
||||
{
|
||||
int aftpdirsiz = strlen(aftpdir);
|
||||
if (*aftpdir && strnequal(hsoname, "AFTP", 4)
|
||||
&& (hsoname[4] == '/' || hsoname[4] == '\0')) {
|
||||
return qsprintf(native_buf, native_bufsiz, "%s%s",
|
||||
aftpdir, hsoname + 4);
|
||||
}
|
||||
#ifdef DIRECTORYCACHING
|
||||
/* MITRAISM -- this is used exclusively for the DIRECTORYCACHING stuff.
|
||||
/* This should handle all other prefixes, without breaking any
|
||||
other code, which wont call this if it has a prefix */
|
||||
if (*hsoname != '/')
|
||||
return qsprintf(native_buf, native_bufsiz, "/%s", hsoname);
|
||||
#endif
|
||||
return qsprintf(native_buf, native_bufsiz, "%s", hsoname);
|
||||
}
|
||||
481
prospero/lib/psrv/dsrfinfo.c
Normal file
481
prospero/lib/psrv/dsrfinfo.c
Normal file
@@ -0,0 +1,481 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1990, 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 <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef USE_SYS_DIR_H
|
||||
#include <sys/dir.h>
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <sgtty.h>
|
||||
#include <string.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#define FILE_VNO 5 /* version # of the file format. */
|
||||
|
||||
#include <ardp.h>
|
||||
#include <pfs.h>
|
||||
#include <plog.h>
|
||||
#include <pprot.h>
|
||||
#include <perrno.h>
|
||||
#include <pmachine.h>
|
||||
#include <pparse.h>
|
||||
#include <psrv.h> /* For nativize_prefix etc */
|
||||
|
||||
extern char shadow[];
|
||||
extern char dirshadow[];
|
||||
extern char dircont[];
|
||||
extern char aftpdir[];
|
||||
|
||||
PATTRIB atalloc();
|
||||
VLINK check_fwd();
|
||||
|
||||
/* Temporary hack. This will go away when the interface to dsrfinfo() and
|
||||
dsrobject() changes. Note that the attributes returned depend upon the
|
||||
client address; this will have to be resolved when we try caching this kind
|
||||
of directory service information. */
|
||||
PERFILE_STATIC_LONG_DEF(client_addr); /* set client address. Initially
|
||||
0. */
|
||||
#define client_addr p_th_arclient_addr[p__th_self_num()]
|
||||
|
||||
void
|
||||
set_client_addr(long client_addr_arg)
|
||||
{
|
||||
client_addr = client_addr_arg;
|
||||
}
|
||||
|
||||
/*
|
||||
* dsrfinfo - Read file info from disk
|
||||
*
|
||||
* DSRFINFO is used by the directory server to read file information from
|
||||
* disk. It takes the host specific part of the system level name of the
|
||||
* file about which information is to be read, and a pointer to the file
|
||||
* structure which it fills in. It returns 0 or -1 on success, 0 if a file
|
||||
* and -1 if a directory. On errors with some corrupt lines in the shadow
|
||||
* file, it logs the bad data format to the Prospero logfile, and attempts to
|
||||
* continue. On other errors, it returns PFAILURE. If unable to find the
|
||||
* object, it returns DSRFINFO_NOT_A_FILE. If it finds useful forwarding
|
||||
* information, it will return DSRFINFO_FORWARDED.
|
||||
*/
|
||||
|
||||
int
|
||||
dsrfinfo(char *nm,long magic,PFILE fi)
|
||||
{
|
||||
struct requested_attributes req_obj_ats_st;
|
||||
|
||||
ZERO(&req_obj_ats_st);
|
||||
req_obj_ats_st.all = 1;
|
||||
return dsrfinfo_with_attribs(nm, magic, fi, &req_obj_ats_st);
|
||||
}
|
||||
|
||||
/*
|
||||
* For now, we have turned off the magic # matching features. Forwarding is
|
||||
* no longer magic number based, pending a determination on the role of magic
|
||||
* numbers in object creation. See /nfs/pfs/notes/forwarding.
|
||||
*/
|
||||
int
|
||||
dsrfinfo_with_attribs(char *nm,long magic,PFILE fi,
|
||||
struct requested_attributes *req_obj_ats)
|
||||
{
|
||||
FILE *pfs_fi = NULL;
|
||||
char *pfs_fi_name = NULL;
|
||||
char name[MAXPATHLEN];
|
||||
char shadow_fname[MAXPATHLEN];
|
||||
char dirshadow_fname[MAXPATHLEN];
|
||||
|
||||
VLINK cur_fp; /* current forwarding poiner */
|
||||
int tmp;
|
||||
char *ls; /* Last slash */
|
||||
|
||||
struct passwd *ownpw;
|
||||
struct group *owngr;
|
||||
struct tm *mt;
|
||||
char mtime_str[20];
|
||||
char mode_str[15];
|
||||
|
||||
PATTRIB at;
|
||||
PATTRIB ap; /* Temp attribute pointer */
|
||||
|
||||
struct stat file_stat_dat;
|
||||
struct stat *file_stat = &file_stat_dat;
|
||||
|
||||
/* This may be reset to -1 once we determine it's a directory. If we go up
|
||||
the directory tree looking for forwarding information, it will be reset
|
||||
to DSRFINFO_FORWARDED. */
|
||||
int retval = PSUCCESS;
|
||||
INPUT_ST in_st;
|
||||
INPUT in = &in_st;
|
||||
|
||||
/* Expand special file names */
|
||||
if((*nm != '/') && *aftpdir && (strncmp(nm,"AFTP",4) == 0)) {
|
||||
strcpy(name,aftpdir);
|
||||
strcat(name,nm+4);
|
||||
}
|
||||
else strcpy(name,nm);
|
||||
|
||||
/* Need to canonicalize the file or directory name (strip out any
|
||||
symbolic links. */
|
||||
/* XXX Find the real name of the file and use it */
|
||||
/* rnl = readlink(filename,rname,MAXPATHLEN); */
|
||||
/* if(rnl >= 0) *(rname+rnl) = '\0'; */
|
||||
|
||||
fi->version = -1; /* sentinel value in case not found. */
|
||||
fi->f_magic_no = 0;
|
||||
/* No need to initialize rest of fi, its already initialized */
|
||||
startover:
|
||||
|
||||
/* Determine name of shadow file */
|
||||
strcpy(shadow_fname,shadow);
|
||||
nativize_prefix(name, shadow_fname + strlen(shadow),
|
||||
sizeof shadow_fname - strlen(shadow));
|
||||
qsprintf(dirshadow_fname,sizeof dirshadow_fname,"%s/%s",shadow_fname,dirshadow);
|
||||
|
||||
/* NOTE: A temporary inefficient shadow file format is*/
|
||||
/* in use. For this reason, the code supporting it */
|
||||
/* is also interim code, and does not do any checking */
|
||||
/* to make sure that the file actually follows */
|
||||
/* the format. Thus, a munged file will result */
|
||||
/* in unpredictable results. */
|
||||
|
||||
/* Read the contents of the shadow file */
|
||||
/* First find out if it is a directory */
|
||||
if(stat(shadow_fname,file_stat) == 0) {
|
||||
if(file_stat->st_mode & S_IFDIR)
|
||||
pfs_fi = locked_fopen(pfs_fi_name = dirshadow_fname,"r");
|
||||
else pfs_fi = locked_fopen(pfs_fi_name = shadow_fname,"r");
|
||||
}
|
||||
|
||||
if(pfs_fi != NULL) {
|
||||
#define RETURN(rv) { retval = (rv); goto cleanup ; }
|
||||
char *line, *next_word;
|
||||
tmp = wholefiletoin(pfs_fi, in);
|
||||
locked_fclose_A(pfs_fi, pfs_fi_name, TRUE);
|
||||
if(tmp) {
|
||||
plog(L_DIR_ERR,NOREQ,"%s",p_err_string);
|
||||
return tmp;
|
||||
}
|
||||
while(in_nextline(in)) {
|
||||
if (in_line(in, &line, &next_word)) {
|
||||
/* If we cannot parse it, do not use it. */
|
||||
plog(L_DATA_FRM_ERR,NOREQ,
|
||||
"Unreadable file info format in %s.", shadow_fname);
|
||||
RETURN(PFAILURE);
|
||||
}
|
||||
|
||||
CHECK_PTRinBUFF(line,next_word);
|
||||
switch(*line) {
|
||||
case 'V': /* Version Number */
|
||||
tmp = sscanf(line,"VERSION %d",&(fi->version));
|
||||
if(tmp != 1) {
|
||||
plog(L_DATA_FRM_ERR,NOREQ,"Bad file info format %s: %s",
|
||||
shadow_fname,line,0);
|
||||
}
|
||||
if (fi->version != FILE_VNO) {
|
||||
plog(L_DATA_FRM_ERR, NOREQ, "Bad file info format %s: \
|
||||
unknown version %d, expected %d", shadow_fname, fi->version, FILE_VNO);
|
||||
RETURN(PFAILURE);
|
||||
}
|
||||
break;
|
||||
case 'M': /* Magic Number */
|
||||
tmp = sscanf(line,"MAGIC-NUMBER %ld",&(fi->f_magic_no));
|
||||
if(tmp != 1) {
|
||||
fi->f_magic_no = 0;
|
||||
plog(L_DATA_FRM_ERR,NOREQ,"Bad file info format %s: %s",
|
||||
shadow_fname,line);
|
||||
}
|
||||
break;
|
||||
case 'E': /* Expiration Date */
|
||||
break;
|
||||
case 'T': /* Time to live */
|
||||
break;
|
||||
case 'L': /* Time of last reference */
|
||||
break;
|
||||
case 'F': /* Forwarding Pointer */
|
||||
/* A forwarding pointer has its NAME member set to the old
|
||||
hosname of the object (now being forwarded). the NAME
|
||||
member may terminate in a *, indicating a wildcarded match.
|
||||
The HOST is the new host of the object and the HSONAME is
|
||||
its new HSONAME. A trailing * in the HSONAME is replaced
|
||||
by whatever matched the trailing * in the NAME member
|
||||
of the object being forwarded. Yes, this means that it is
|
||||
difficult to forward an object whose real HSONAME ends in
|
||||
'*'. We do not currently create such objects, although we
|
||||
might. */
|
||||
if (strnequal(line, "FORWARD", 7)
|
||||
&& in_link(in, line, next_word, 0, &cur_fp,
|
||||
(TOKEN *) NULL) == PSUCCESS) {
|
||||
APPEND_ITEM(cur_fp, fi->forward);
|
||||
} else {
|
||||
plog(L_DATA_FRM_ERR,NOREQ,"Bad file info format %s: %s",
|
||||
shadow_fname,line);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'B': /* Back Link */
|
||||
break;
|
||||
case 'A': /* Attribute or ACL*/
|
||||
if (strnequal(line, "ACL", 3)) {
|
||||
if(in_ge1_acl(in, line, next_word, &fi->oacl)) {
|
||||
plog(L_DATA_FRM_ERR,NOREQ,"Bad file info format %s: %s",
|
||||
shadow_fname,line);
|
||||
RETURN(PFAILURE);
|
||||
}
|
||||
}
|
||||
else if (!strnequal(line, "ATTRIBUTE", 9)
|
||||
|| in_ge1_atrs(in, line, next_word, &fi->attributes))
|
||||
plog(L_DATA_FRM_ERR,NOREQ,"Bad file info format %s: %s",
|
||||
shadow_fname,line);
|
||||
break;
|
||||
/*default will skip on to next line - prob reasonable*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef SERVER_DO_NOT_SUPPORT_FORWARDING
|
||||
#if 0 /* This code is inconsistent; was murdered from
|
||||
older working code */
|
||||
/* Explicitly setting the magic # of an object to a negative number
|
||||
indicates that 'this object is not really here; it's just
|
||||
a placeholder for forwarding pointers'. */
|
||||
/* Comparing the magic #s is a fast operation; faster than scanning
|
||||
though a list of forwarding pointers. Therefore, if the magic #s
|
||||
match, all is well. */
|
||||
/* Check_above sets the return value to DSRFINFO_FORWARDED to indicate
|
||||
that we're searching up the UNIX directory hierarchy for a matching
|
||||
FORWARD message */
|
||||
/* Determine if the file has been forwarded, and if so return, */
|
||||
/* indicating that fact */
|
||||
/* A file is assumed to have been forwarded if (a) an explicit magic #
|
||||
was requested and it doesn't match the current magic # and matching
|
||||
forwarding data was found here for it
|
||||
if (((fi->f_magic_no && magic && (fi->f_magic_no != magic)) ||
|
||||
(fi->f_magic_no < 0))
|
||||
&& check_fwd(fi->forward,nm,magic))
|
||||
return(DSRFINFO_FORWARDED);
|
||||
/* Otherwise, this isn't the object that we thought it was (or it
|
||||
has 'I am not really here' set on it, but no forwarding
|
||||
informatin found. */
|
||||
else
|
||||
return DSRFINFO_NOT_A_FILE;
|
||||
#else
|
||||
|
||||
/* Test: is this object marked indicating that it's the ghost of a
|
||||
forwarded object? */
|
||||
if (fi->f_magic_no < 0) retval = DSRFINFO_FORWARDED;
|
||||
if (retval == DSRFINFO_FORWARDED) {
|
||||
if (check_fwd(fi->forward, nm, magic)) /* if not locally forwarded.
|
||||
*/
|
||||
return DSRFINFO_FORWARDED;
|
||||
else
|
||||
return DSRFINFO_NOT_A_FILE;
|
||||
}
|
||||
#endif
|
||||
#endif /* SERVER_DO_NOT_SUPPORT_FORWARDING */
|
||||
|
||||
}
|
||||
|
||||
/* Fill in attributes from the real file, if it exists and if we are not
|
||||
just running up the hierarchy for forwarding information, and if we
|
||||
actually want any of these attributes. */
|
||||
|
||||
if((retval == PSUCCESS) && was_attribute_requested("CONTENTS", req_obj_ats))
|
||||
return(retval);
|
||||
|
||||
if ((retval == PSUCCESS)
|
||||
&& ( was_attribute_requested("SIZE", req_obj_ats)
|
||||
|| was_attribute_requested("NATIVE-OWNER", req_obj_ats)
|
||||
|| was_attribute_requested("NATIVE-GROUP", req_obj_ats)
|
||||
|| was_attribute_requested("LAST-MODIFIED", req_obj_ats)
|
||||
|| was_attribute_requested("UNIX-MODES", req_obj_ats))
|
||||
&& (stat(name,file_stat) == 0)) {
|
||||
if (was_attribute_requested("SIZE", req_obj_ats)) {
|
||||
/* off_t st_size; /* total size of file */
|
||||
at = atalloc();
|
||||
at->aname = stcopy("SIZE");
|
||||
at->avtype = ATR_SEQUENCE;
|
||||
at->nature = ATR_NATURE_INTRINSIC;
|
||||
at->value.sequence = tkalloc(NULL);
|
||||
at->value.sequence->token =
|
||||
qsprintf_stcopyr((char *) NULL, "%d bytes", file_stat->st_size);
|
||||
APPEND_ITEM(at, fi->attributes);
|
||||
}
|
||||
|
||||
#ifndef PFS_THREADS
|
||||
if (was_attribute_requested("NATIVE-OWNER", req_obj_ats)) {
|
||||
/* short st_uid; /* user-id of owner */
|
||||
ownpw = getpwuid(file_stat->st_uid); /* not MT safe */
|
||||
if(ownpw) {
|
||||
at = atalloc();
|
||||
at->aname = stcopy("NATIVE-OWNER");
|
||||
at->avtype = ATR_SEQUENCE;
|
||||
at->nature = ATR_NATURE_INTRINSIC;
|
||||
at->value.sequence = tkalloc(ownpw->pw_name);
|
||||
APPEND_ITEM(at, fi->attributes);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef PFS_THREADS
|
||||
if (was_attribute_requested("NATIVE-GROUP", req_obj_ats)) {
|
||||
/* short st_gid; /* group-id of owner */
|
||||
owngr = getgrgid(file_stat->st_gid); /* not MT safe */
|
||||
if(owngr) {
|
||||
at = atalloc();
|
||||
at->aname = stcopy("NATIVE-GROUP");
|
||||
at->avtype = ATR_SEQUENCE;
|
||||
at->nature = ATR_NATURE_INTRINSIC;
|
||||
at->value.sequence = tkalloc(owngr->gr_name);
|
||||
APPEND_ITEM(at, fi->attributes);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (was_attribute_requested("LAST-MODIFIED", req_obj_ats)) {
|
||||
/* time_t st_atime; /* file last access time */
|
||||
|
||||
/* time_t st_mtime; /* file last modify time */
|
||||
if(file_stat->st_mtime) {
|
||||
at = atalloc();
|
||||
at->aname = stcopy("LAST-MODIFIED");
|
||||
at->avtype = ATR_SEQUENCE;
|
||||
at->nature = ATR_NATURE_INTRINSIC;
|
||||
at->value.sequence = tkalloc(NULL);
|
||||
at->value.sequence->token =
|
||||
p_timetoasn_stcopyr(file_stat->st_mtime,
|
||||
at->value.sequence->token);
|
||||
APPEND_ITEM(at, fi->attributes);
|
||||
}
|
||||
}
|
||||
|
||||
if (was_attribute_requested("UNIX-MODES", req_obj_ats)) {
|
||||
/* u_short st_mode; /* protection */
|
||||
at = atalloc();
|
||||
at->aname = stcopy("UNIX-MODES");
|
||||
at->avtype = ATR_SEQUENCE;
|
||||
at->nature = ATR_NATURE_INTRINSIC;
|
||||
|
||||
strcpy(mode_str,"----------");
|
||||
if((file_stat->st_mode & S_IFLNK) == S_IFLNK) mode_str[0] = 'l';
|
||||
if(file_stat->st_mode & S_IREAD) mode_str[1] = 'r';
|
||||
if(file_stat->st_mode & S_IWRITE) mode_str[2] = 'w';
|
||||
if(file_stat->st_mode & S_IEXEC) mode_str[3] = 'x';
|
||||
if(file_stat->st_mode & S_ISUID) mode_str[3] = 's';
|
||||
if(file_stat->st_mode & (S_IREAD>>3)) mode_str[4] = 'r';
|
||||
if(file_stat->st_mode & (S_IWRITE>>3)) mode_str[5] = 'w';
|
||||
if(file_stat->st_mode & (S_IEXEC>>3)) mode_str[6] = 'x';
|
||||
if(file_stat->st_mode & S_ISGID) mode_str[6] = 's';
|
||||
if(file_stat->st_mode & (S_IREAD>>6)) mode_str[7] = 'r';
|
||||
if(file_stat->st_mode & (S_IWRITE>>6)) mode_str[8] = 'w';
|
||||
if(file_stat->st_mode & (S_IEXEC>>6)) mode_str[9] = 'x';
|
||||
if(file_stat->st_mode & S_IFDIR) {
|
||||
mode_str[0] = 'd';
|
||||
if(retval == PSUCCESS) retval = -1;
|
||||
}
|
||||
at->value.sequence = tkalloc(mode_str);
|
||||
APPEND_ITEM(at, fi->attributes);
|
||||
}
|
||||
}
|
||||
/* If no native file AND no PFS file info, then look for forwarding */
|
||||
else if(fi->version < 0) goto check_above;
|
||||
|
||||
/* Stick on the INTRINSIC ACCESS-METHOD attributes. */
|
||||
if (retval == 0 /* if it's a file */
|
||||
&& was_attribute_requested("ACCESS-METHOD", req_obj_ats)) {
|
||||
PATTRIB at1 = NULL;
|
||||
PATTRIB nextat;
|
||||
get_access_method(name, client_addr, &at1);
|
||||
for ( ; at1; at1 = nextat) {
|
||||
nextat = at1->next;
|
||||
EXTRACT_HEAD_ITEM(at1);
|
||||
APPEND_ITEM(at1, fi->attributes);
|
||||
}
|
||||
}
|
||||
return(retval);
|
||||
|
||||
/* Check above looks for forwarding pointers in directories */
|
||||
/* above the named file. It is reached when we have been passed
|
||||
an hsoname for a nonexistent object.
|
||||
We might be passed an hsoname for a nonexistent object either
|
||||
(a) if the object has been forwarded or (b) the object has not
|
||||
yet been created. So we look for forwarding information or
|
||||
for a real superior object. Once we make a hit (or hit the root of the
|
||||
tree), we return either DSRFINFO_FORWARDED or DSRFINFO_NOT_A_FILE.
|
||||
*/
|
||||
/* Look up, in case the object has moved, but a forwarding address does not
|
||||
exist in the corresponding file info, but might exist further up. */
|
||||
|
||||
check_above:
|
||||
|
||||
retval = DSRFINFO_NOT_A_FILE; /* If the forwarded test succeeds, will
|
||||
return DSRFINFO_FORWARDED instead. */
|
||||
|
||||
ls = strrchr(name,'/');
|
||||
/* If we have used up all components, return failure */
|
||||
if((ls == 0) || (ls == name)) return(DSRFINFO_NOT_A_FILE);
|
||||
|
||||
*ls = '\0';
|
||||
|
||||
goto startover;
|
||||
|
||||
cleanup: /* used for abnormal exit */
|
||||
/* input file is closed in code above. */
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* check_fwd takes a list of forwarding pointers, checks to see */
|
||||
/* if any apply to the object with the specified magic number */
|
||||
/* and returns the appropiate link, or none if not forwarded */
|
||||
/* If the match is a widarded match, the returned link will be */
|
||||
/* modified so that the matched wildcard is replaced by the */
|
||||
/* text that matched it */
|
||||
/* */
|
||||
/* BUGS only a trailing * wildcard is allowed */
|
||||
VLINK
|
||||
check_fwd(fl,name,magic)
|
||||
VLINK fl;
|
||||
char *name;
|
||||
int magic;
|
||||
{
|
||||
char *sp; /* Star pointer */
|
||||
|
||||
while(fl) {
|
||||
if(((magic == 0) || (fl->f_magic_no == 0) ||
|
||||
(fl->f_magic_no == magic)) && (wcmatch(name,fl->name))) {
|
||||
|
||||
sp = strchr(fl->hsoname,'*');
|
||||
if(sp) *sp = '\0';
|
||||
|
||||
sp = strchr(fl->name,'*');
|
||||
if(sp) {
|
||||
int n;
|
||||
|
||||
sp = name + (sp - fl->name);
|
||||
fl->name = stcopyr(name,fl->name);
|
||||
fl->hsoname = qsprintf_stcopyr(fl->hsoname,
|
||||
"%s%s",fl->hsoname,sp);
|
||||
}
|
||||
|
||||
return(fl);
|
||||
}
|
||||
fl = fl->next;
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
555
prospero/lib/psrv/dsrobject.c
Normal file
555
prospero/lib/psrv/dsrobject.c
Normal file
@@ -0,0 +1,555 @@
|
||||
/*
|
||||
* 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 <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pmachine.h>
|
||||
#ifndef SOLARIS /* if not posix, need MAXPATHLEN still */
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include <pserver.h> /* For DIRECTORYCACHING and for PLOG
|
||||
overrides. */
|
||||
#include <pfs.h>
|
||||
#include <perrno.h>
|
||||
#include <psrv.h>
|
||||
#include <plog.h>
|
||||
|
||||
#ifdef DSROBJECT_SPEEDUP_IS_EXPERIMENTAL
|
||||
int dsrobject_speedup = 1; /* speed up DSROBJECT. This can be set to 0 to
|
||||
use the old code. These changes made by SWA
|
||||
during the week of 5/9/94 */
|
||||
#endif
|
||||
|
||||
|
||||
static PATTRIB newamat(void);
|
||||
|
||||
#ifdef DIRECTORYCACHING
|
||||
|
||||
/* One day */
|
||||
#define SECONDSPERDAY (60*60*24)
|
||||
#define MAXDIRCACHEAGE (1*SECONDSPERDAY)
|
||||
int cache_attempt = 0; int cache_can = 0; int cache_yes = 0;
|
||||
/* Used to see how many times dsrobject() failed in a retrieval request. */
|
||||
int dsrobject_fail = 0;
|
||||
|
||||
int
|
||||
vdir_outofdate(VDIR dir, char *hsoname)
|
||||
{
|
||||
char native_dirname[MAXPATHLEN];
|
||||
char vfs_dirname[MAXPATHLEN];
|
||||
|
||||
nativize_prefix(hsoname, native_dirname, sizeof native_dirname);
|
||||
strcpy(vfs_dirname,shadow);
|
||||
strcat(vfs_dirname,native_dirname);
|
||||
strcat(vfs_dirname,"/");
|
||||
strcat(vfs_dirname,dircont);
|
||||
|
||||
return (stat_age(vfs_dirname) > MAXDIRCACHEAGE);
|
||||
}
|
||||
#endif /*DIRECTORYCACHING */
|
||||
/* Union links are expanded at a higher level.
|
||||
* The only message dsrobject() sends to the client is an ardp_rwait().
|
||||
* dsrobject() logs NOT-AUTHORIZED failures via plog, but doesn't send messages
|
||||
to the client; the caller does that.
|
||||
* Checks to make sure hsoname is within the space we're allowed to discuss.
|
||||
* Does check to make sure you have r, G, or g rights on a database before it
|
||||
lets you scan that database for information.
|
||||
*/
|
||||
|
||||
/* flags honored::
|
||||
DRO_VERIFY_DIR
|
||||
|
||||
*/
|
||||
/*
|
||||
Returns:
|
||||
DSRFINFO_FORWARDED
|
||||
DIRSRV_NOT_AUTHORIZED
|
||||
DIRSRV_NOT_FOUND
|
||||
PFAILURE
|
||||
PSUCCESS
|
||||
*/
|
||||
/* If called with the DRO_VERIFY flag, will set the P_OBJECT_FILE and
|
||||
P_OBJECT_DIRECTORY flags in the ob structure, but will not *necessarily* put
|
||||
any other information into the ob structure. Caller is still responsible
|
||||
for freeing any links pointed to by the ob structure. */
|
||||
|
||||
/* If called with the DRO_VERIFY_DIR flag, will return PSUCCESS only if object
|
||||
is a directory. Will not necessarily put any other information into the OB
|
||||
structure. Caller is still responsible for freeing any links pointed to by
|
||||
the ob structure. */
|
||||
|
||||
/* dsrobject(), if it returns anything other than DSRFINFO_FORWARDED or
|
||||
PSUCCESS, may leave the ob structure with arbitrary data in it. The caller
|
||||
should not expect the ob structure to remain untouched. */
|
||||
|
||||
/* At the moment, the only option we look at in dsrobject_list_options is the
|
||||
requested_attributes one, and that only to test for the CONTENTS
|
||||
attribute. */
|
||||
|
||||
/* The database ACL itself may be obtained by using an HSONAME that is just the
|
||||
root prefix of the database. */
|
||||
|
||||
int requested_contents(struct dsrobject_list_options *listopts);
|
||||
PATTRIB read_contents(char hsoname[]);
|
||||
|
||||
int
|
||||
dsrobject(RREQ req, char hsoname_type[], char hsoname[], long version,
|
||||
long magic_no,
|
||||
int flags, struct dsrobject_list_options *listopts, P_OBJECT ob)
|
||||
{
|
||||
VDIR_ST dir_st;
|
||||
register VDIR dir = &dir_st;
|
||||
register PFILE fi = NULL; /* Only set if it needs to be. */
|
||||
int retval; /* Integer return value from subfunctions */
|
||||
int dirretval = PFAILURE; /* Save initial dsrdir result*/
|
||||
#ifdef DIRECTORYCACHING
|
||||
int cancache = TRUE;
|
||||
#endif
|
||||
|
||||
#ifdef DSROBJECT_SPEEDUP_IS_EXPERIMENTAL
|
||||
if (!dsrobject_speedup)
|
||||
flags &= ~DRO_VERIFY; /* if not speedup, turn off DRO_VERIFY flag. */
|
||||
#endif
|
||||
VLDEBUGBEGIN;
|
||||
vdir_init(dir); /* empty directory. */
|
||||
set_client_addr(req->peer_addr.s_addr); /* temporary hack. */
|
||||
|
||||
/* Check whether HSONAME-TYPE and HSONAME are valid. */
|
||||
if (!strequal(hsoname_type, "ASCII")) {
|
||||
plog(L_DIR_ERR, req, "dsrobject(): got invalid hsoname-type: %s",
|
||||
hsoname_type, 0);
|
||||
vdir_freelinks(dir);
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
if (check_handle(hsoname) == FALSE) {
|
||||
plog(L_AUTH_ERR, req, "Got an HSONAME outside the part of the \
|
||||
filesystem that this server is authorized to publish information about: %s",
|
||||
hsoname);
|
||||
/* Free the directory links */
|
||||
vdir_freelinks(dir);
|
||||
return DIRSRV_NOT_AUTHORIZED;
|
||||
}
|
||||
|
||||
if ( *hsoname != '/') {
|
||||
/* Database or special prefix in use */
|
||||
register int i;
|
||||
#ifdef DIRECTORYCACHING /* mitracode */
|
||||
cache_attempt++;
|
||||
/* SWA bug fix: this assumes listopts is always set, which it need not
|
||||
be. */
|
||||
/* mitra: Can not cache if specifying a component (other than"*") */
|
||||
/* swa added: Can not cache if #ALL attributes not set. This prevents
|
||||
us from blowing it badly. */
|
||||
|
||||
if (!listopts
|
||||
|| (listopts->thiscompp && strcmp(*(listopts->thiscompp),"*"))
|
||||
|| !listopts->req_link_ats.all)
|
||||
cancache = FALSE;
|
||||
if (cancache) {
|
||||
cache_can++;
|
||||
VLDEBUGBEGIN;
|
||||
if (!(dirretval
|
||||
= dsrdir(hsoname, magic_no, dir, NULL, DSRD_ATTRIBUTES)))
|
||||
cache_yes++;
|
||||
VLDEBUGDIR(dir);
|
||||
VLDEBUGEND;
|
||||
}
|
||||
|
||||
#endif
|
||||
if (dirretval != PSUCCESS
|
||||
#ifdef DIRECTORYCACHING
|
||||
|| vdir_outofdate(dir,hsoname)
|
||||
#endif
|
||||
|| !(dir->links) ) {
|
||||
for (i = 0; i < db_num_ents; i++) {
|
||||
if (strnequal(hsoname, db_prefixes[i].prefix,
|
||||
strlen(db_prefixes[i].prefix))
|
||||
&& strequal(db_prefixes[i].hsoname_type, hsoname_type)) {
|
||||
ACL dbacl;
|
||||
|
||||
VLDEBUGBEGIN;
|
||||
get_named_acl(db_prefixes[i].named_acl, &dbacl);
|
||||
VLDEBUGEND;
|
||||
if (dbacl
|
||||
&& !srv_check_acl(dbacl, NULL, req, "r",
|
||||
SCA_LINKDIR,db_prefixes[i].prefix,NULL)
|
||||
&& !srv_check_acl(dbacl, NULL, req, "g",
|
||||
SCA_LINKDIR,db_prefixes[i].prefix,NULL)
|
||||
&& !srv_check_acl(dbacl, NULL, req, "G",
|
||||
SCA_LINKDIR,db_prefixes[i].prefix,NULL)) {
|
||||
plog(L_AUTH_ERR, req,
|
||||
"Unauthorized database request: %s %s",
|
||||
hsoname, listopts? *(listopts->thiscompp) : "");
|
||||
vdir_freelinks(dir);
|
||||
return DIRSRV_NOT_AUTHORIZED;
|
||||
}
|
||||
/* This could take a while, tell client not to retry.
|
||||
This should be customized on a per-database basis. */
|
||||
ardp_rwait(req, 180, 0, 0);
|
||||
VLDEBUGBEGIN;
|
||||
retval= db_prefixes[i].read_function(req, hsoname,
|
||||
version, magic_no, flags, listopts, ob);
|
||||
VLDEBUGOB(ob);
|
||||
VLDEBUGEND;
|
||||
#ifdef DIRECTORYCACHING
|
||||
if (retval == PSUCCESS && ob->links) {
|
||||
if (cancache) {
|
||||
VLDEBUGBEGIN;
|
||||
dswobject(hsoname_type,hsoname,ob);
|
||||
VLDEBUGEND;
|
||||
}
|
||||
vdir_freelinks(dir);
|
||||
return(retval);
|
||||
} else if (dirretval == PSUCCESS) {
|
||||
/* Must just have been old*/
|
||||
/*drop through and reread dir and file*/
|
||||
break;
|
||||
} else { /* Neither old nor new version available */
|
||||
/* Or directory is really empty */
|
||||
vdir_freelinks(dir);
|
||||
return(retval);
|
||||
}
|
||||
#else
|
||||
vdir_freelinks(dir);
|
||||
return retval;
|
||||
#endif /*DIRECTORYCACHING*/
|
||||
}
|
||||
} /*for*/
|
||||
} /*PSUCCESS*/
|
||||
/* Here we have a prefix that is not a database, */
|
||||
/* but not a normal filename either */
|
||||
/* If normal file names need not begin with / */
|
||||
/* fall through and try a normal query */
|
||||
}
|
||||
/* Local directories can have associated finfo too. */
|
||||
if (dirretval == PSUCCESS) { /* No need to reread if did already */
|
||||
retval = dirretval;
|
||||
} else {
|
||||
VLDEBUGBEGIN;
|
||||
retval = dsrdir(hsoname, magic_no, dir, NULL,
|
||||
/* Set DSRD_VERIFY_DIR iff DRO_VERIFY_DIR is set. */
|
||||
((flags & DRO_VERIFY_DIR) ? DSRD_VERIFY_DIR : 0)
|
||||
/* Note that dsrdir() curently always returns all
|
||||
object attributes. This costs us some potentially
|
||||
unnecessary MALLOC()s. */
|
||||
| ((listopts && listopts->requested_attrs) ?
|
||||
DSRD_ATTRIBUTES : 0));
|
||||
VLDEBUGDIR(dir);
|
||||
VLDEBUGEND;
|
||||
}
|
||||
if (retval == PSUCCESS) ob->flags |= P_OBJECT_DIRECTORY;
|
||||
if (retval == PSUCCESS || retval == DSRDIR_NOT_A_DIRECTORY ||
|
||||
retval == DIRSRV_NOT_DIRECTORY || retval == DIRSRV_NOT_FOUND) {
|
||||
int dsrfinfo_retval;
|
||||
|
||||
#ifdef SERVER_DO_NOT_SUPPORT_FORWARDING
|
||||
/* Don't bother with the dsrfinfo() unless a specific attribute or set
|
||||
of attributes was requested, or unless a directory was not found. */
|
||||
if (listopts->req_obj_ats.all
|
||||
|| listopts->req_obj_ats.interesting
|
||||
|| listopts->req_obj_ats.specific) {
|
||||
fi = pfalloc();
|
||||
dsrfinfo_retval = dsrfinfo_with_attribs(hsoname, magic_no, fi,
|
||||
&listopts->req_obj_ats);
|
||||
} else {
|
||||
dsrfinfo_retval = PFAILURE;
|
||||
}
|
||||
#else
|
||||
VLDEBUGBEGIN;
|
||||
dsrfinfo_retval = dsrfinfo(hsoname,magic_no,fi);
|
||||
VLDEBUGFI(fi);
|
||||
VLDEBUGEND;
|
||||
if (dsrfinfo_retval == DSRFINFO_FORWARDED) {
|
||||
ob->inc_native = VDIN_MUNGED;
|
||||
ob->forward = fi->forward; fi->forward = NULL;
|
||||
pffree(fi);
|
||||
vdir_freelinks(dir);
|
||||
return dsrfinfo_retval;
|
||||
}
|
||||
#endif
|
||||
if (dsrfinfo_retval < 0) { /* dsrfinfo returns <0 to mean
|
||||
directory */
|
||||
ob->flags |= P_OBJECT_DIRECTORY;
|
||||
retval = PSUCCESS;
|
||||
} else if (dsrfinfo_retval == PSUCCESS) {
|
||||
ob->flags |= P_OBJECT_FILE;
|
||||
if (requested_contents(listopts)) {
|
||||
PATTRIB at = read_contents(hsoname);
|
||||
/* Append it to fi->attributes since ob->attributes will get
|
||||
set from that. */
|
||||
if (at) APPEND_ITEM(at, fi->attributes);
|
||||
}
|
||||
retval = PSUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SERVER_DO_NOT_SUPPORT_FORWARDING
|
||||
if (retval == DSRFINFO_FORWARDED) {
|
||||
/* Only get here if dsrdir() or dsdb() returned DSRFINFO_FORWARDED */
|
||||
ob->inc_native = VDIN_MUNGED;
|
||||
ob->forward = dir->f_info->forward; dir->f_info->forward = NULL;
|
||||
vdir_freelinks(dir);
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
if (retval) {
|
||||
vdir_freelinks(dir);
|
||||
if (fi) pffree(fi);
|
||||
if (retval == DIRSRV_NOT_DIRECTORY || retval == DSRDIR_NOT_A_DIRECTORY
|
||||
|| retval == DSRFINFO_NOT_A_FILE)
|
||||
return DIRSRV_NOT_FOUND;
|
||||
return retval;
|
||||
}
|
||||
/* Now for some manly calisthenics!
|
||||
Merge f_info and directory info. */
|
||||
/* Note this is the model for the VERSION5 version dswobject
|
||||
so, if you change this, probably need to change that - Mitra */
|
||||
/* Only potential conflict here: ACL. Handle it by appending the two
|
||||
ACLs if both are set. (DIRECTORY first; why not). If one is unset,
|
||||
use the default (DEFAULT SYSTEM for DIRECTORY, CONTAINER for OBJECT).
|
||||
If directory and object both have magic numbers set use one from
|
||||
directory.
|
||||
*/
|
||||
if (ob->flags & P_OBJECT_DIRECTORY) {
|
||||
ob->version = dir->version; /* always 0 */
|
||||
ob->inc_native = dir->inc_native;
|
||||
ob->magic_no = dir->magic_no;
|
||||
ob->acl = dir->dacl; dir->dacl = NULL;
|
||||
assert(!dir->f_info); /* should have already been handled */
|
||||
ob->links = dir->links; dir->links = NULL;
|
||||
ob->ulinks = dir->ulinks; dir->ulinks = NULL;
|
||||
ob->native_mtime = dir->native_mtime;
|
||||
} else {
|
||||
ob->inc_native = VDIN_NOTDIR;
|
||||
}
|
||||
/* If FINFO present (will not always need to be present), merge it in. */
|
||||
if (fi) {
|
||||
/* Magic # on directory, if present, supersedes magic # on finfo. */
|
||||
if (!ob->magic_no) ob->magic_no = fi->f_magic_no;
|
||||
/* Append object ACLs. */
|
||||
if (fi->oacl) {
|
||||
CONCATENATE_LISTS(ob->acl, fi->oacl); fi->oacl = NULL;
|
||||
}
|
||||
ob->exp = fi->exp;
|
||||
ob->ttl = fi->ttl;
|
||||
ob->last_ref = fi->last_ref;
|
||||
ob->forward = fi->forward; fi->forward = NULL;
|
||||
ob->backlinks = fi->backlinks; fi->backlinks = NULL;
|
||||
ob->attributes = fi->attributes; fi->attributes = NULL;
|
||||
/* Done merging in attributes from FINFO structure. */
|
||||
}
|
||||
|
||||
/* Clean up and return. */
|
||||
vdir_freelinks(dir);
|
||||
if (fi) pffree(fi); fi = NULL;
|
||||
VLDEBUGOB(ob);
|
||||
VLDEBUGEND;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Return a list of OBJECT INTRINSIC ACCESS-METHOD attributes for the local
|
||||
real file FILENAME. These attributes should be usable by the client coming
|
||||
from the address client_addr. One day this function will no longer be
|
||||
necessary when we have the Prospero access method working.
|
||||
Allocates pattribs and puts them into RETVAL.
|
||||
|
||||
Note that FILENAME has already been expanded from any HSONAME.
|
||||
*/
|
||||
|
||||
/* Called by dsrfinfo at the moment. */
|
||||
void
|
||||
get_access_method(char filename[], long client_addr, PATTRIB *retval)
|
||||
{
|
||||
PATTRIB at; /* temporary working attribute. */
|
||||
TOKEN nfs_am; /* Access method for NFS (if any) */
|
||||
|
||||
*retval = NULL; /* return list starts empty. */
|
||||
|
||||
/* Check for PROSPERO-CONTENTS access method */
|
||||
/* Always true for any local file. */
|
||||
at = newamat();
|
||||
at->value.sequence = tkappend("PROSPERO-CONTENTS", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
APPEND_ITEM(at, *retval);
|
||||
|
||||
|
||||
/* Check for LOCAL access method. */
|
||||
if (myaddress() == client_addr ||
|
||||
/* Check for loopback net. */
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
(client_addr & 0xff000000) == (127 << 24)
|
||||
#else
|
||||
(client_addr & 0x000000ff) == 127
|
||||
#endif
|
||||
) {
|
||||
/* This may not return information for multi-homed hosts.
|
||||
But it will never return incorrect information. */
|
||||
at = newamat();
|
||||
at->value.sequence = tkappend("LOCAL", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
APPEND_ITEM(at, *retval);
|
||||
} else {
|
||||
#ifdef SHARED_PREFIXES
|
||||
char *cp; /* this memory doesn't need to be freed. */
|
||||
if (cp = check_localpath(filename, client_addr)){
|
||||
at = newamat();
|
||||
at->value.sequence = tkappend("LOCAL", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend(cp, at->value.sequence);
|
||||
APPEND_ITEM(at, *retval);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check for NFS access method. */
|
||||
#ifdef NFS_EXPORT
|
||||
if(nfs_am = check_nfs(filename,client_addr)) {
|
||||
at = newamat();
|
||||
at->value.sequence = nfs_am;
|
||||
APPEND_ITEM(at, *retval);
|
||||
}
|
||||
#endif NFS_EXPORT
|
||||
|
||||
/* Check for AFS access method. Note that the hostname is irrelevant. */
|
||||
if(*afsdir && strnequal(filename, afsdir, strlen(afsdir))) {
|
||||
char *suffix = filename + strlen(afsdir);
|
||||
at = newamat();
|
||||
at->value.sequence = tkappend("AFS", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend("ASCII", at->value.sequence);
|
||||
at->value.sequence = tkappend(suffix, at->value.sequence);
|
||||
APPEND_ITEM(at, *retval);
|
||||
|
||||
#ifdef AFS_AFTP_GATEWAY /* provide additional access method for sites
|
||||
that don't run AFS. */
|
||||
at = newamat();
|
||||
at->value.sequence = tkappend("AFTP", at->value.sequence);
|
||||
at->value.sequence = tkappend("INTERNET-D", at->value.sequence);
|
||||
at->value.sequence = tkappend(hostname, at->value.sequence);
|
||||
at->value.sequence = tkappend("ASCII", at->value.sequence);
|
||||
at->value.sequence =
|
||||
tkappend(qsprintf_stcopyr((char *) NULL,
|
||||
"%s%s", AFS_AFTP_GATEWAY, suffix),
|
||||
at->value.sequence);
|
||||
at->value.sequence = tkappend("BINARY", at->value.sequence);
|
||||
APPEND_ITEM(at, *retval);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check for AFTP access method. */
|
||||
if(*aftpdir && strnequal(filename,aftpdir, strlen(aftpdir))) {
|
||||
char *suffix = filename + strlen(aftpdir);
|
||||
|
||||
at = newamat();
|
||||
at->value.sequence = tkappend("AFTP", at->value.sequence);
|
||||
at->value.sequence = tkappend("INTERNET-D", at->value.sequence);
|
||||
at->value.sequence = tkappend(hostname, at->value.sequence);
|
||||
at->value.sequence = tkappend("ASCII", at->value.sequence);
|
||||
at->value.sequence = tkappend(suffix, at->value.sequence);
|
||||
at->value.sequence = tkappend("BINARY", at->value.sequence);
|
||||
APPEND_ITEM(at, *retval);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Allocate a new ACCESS-METHOD attribute. */
|
||||
static
|
||||
PATTRIB
|
||||
newamat(void)
|
||||
{
|
||||
PATTRIB retval = atalloc();
|
||||
retval->aname = stcopyr("ACCESS-METHOD", retval->aname);
|
||||
retval->precedence = ATR_PREC_OBJECT;
|
||||
retval->nature = ATR_NATURE_INTRINSIC;
|
||||
retval->avtype = ATR_SEQUENCE;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/* Was the CONTENTS attribute requested on the object itself? CONTENTS is an
|
||||
INTRINSIC- attribute. Return non-zero (C language "true") if true, zero (C
|
||||
language "false") if false. */
|
||||
int
|
||||
requested_contents(struct dsrobject_list_options *listopts)
|
||||
{
|
||||
return listopts
|
||||
&& was_attribute_requested("CONTENTS", &listopts->req_obj_ats);
|
||||
}
|
||||
|
||||
|
||||
/* Return the CONTENTS attribute. */
|
||||
PATTRIB
|
||||
read_contents(char hsoname[])
|
||||
{
|
||||
char *filename;
|
||||
PATTRIB retval;
|
||||
int fd; /* file descriptor to read from. */
|
||||
struct stat file_stat_st;
|
||||
struct stat * file_stat = &file_stat_st;
|
||||
TOKEN tk; /* working token */
|
||||
|
||||
/* Code modified from dsrfinfo() */
|
||||
/* Expand special file names */
|
||||
if((*hsoname != '/') && *aftpdir && strnequal(hsoname,"AFTP",4))
|
||||
filename = qsprintf_stcopyr("%s%s", aftpdir, hsoname + 4);
|
||||
else
|
||||
filename = stcopy(hsoname);
|
||||
|
||||
fd = open(filename, 0); /* open for reading */
|
||||
if (fd < 0) {
|
||||
stfree(filename);
|
||||
return NULL;
|
||||
}
|
||||
if (stat(filename,file_stat) != 0) {
|
||||
close(fd);
|
||||
stfree(filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
retval = atalloc();
|
||||
retval->aname = stcopyr("CONTENTS", retval->aname);
|
||||
retval->precedence = ATR_PREC_OBJECT;
|
||||
retval->nature = ATR_NATURE_INTRINSIC;
|
||||
retval->avtype = ATR_SEQUENCE;
|
||||
/* Build a two-element sequence, DATA and a byte stream of the data. */
|
||||
retval->value.sequence = tkappend("DATA", retval->value.sequence);
|
||||
|
||||
tk = tkalloc(NULL);
|
||||
/* allocate one extra space for the trailing null. */
|
||||
tk->token = stalloc(file_stat->st_size + 1);
|
||||
/* tk->token is the buffer we fill in. It remains a valid reference even
|
||||
after the APPEND_ITEM. We call APPEND_ITEM() first so that it's easy
|
||||
to abort in case of an error (one less freeing operation to call). */
|
||||
APPEND_ITEM(tk, retval->value.sequence);
|
||||
|
||||
/* Read whole contents and close the file. If either fails, don't set the
|
||||
CONTENTS attribute. */
|
||||
/* This might fail IF the file size changes between the stat() and the
|
||||
read. Oh well. */
|
||||
if(read(fd, tk->token, file_stat->st_size) != file_stat->st_size
|
||||
|| close(fd)) {
|
||||
atfree(retval);
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
p_bst_set_buffer_length_nullterm(tk->token, file_stat->st_size);
|
||||
/* Automatically null terminates it for us too. */
|
||||
return retval;
|
||||
}
|
||||
292
prospero/lib/psrv/dsrobject_v6.c
Normal file
292
prospero/lib/psrv/dsrobject_v6.c
Normal file
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright (c) 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 <perrno.h>
|
||||
#include <psrv.h>
|
||||
#include <plog.h>
|
||||
|
||||
static PATTRIB newamat(void);
|
||||
|
||||
/* Union links are expanded at a higher level.
|
||||
* The only message dsrobject() sends to the client is an ardp_rwait().
|
||||
* dsrobject() logs NOT-AUTHORIZED failures via plog, but doesn't send messages
|
||||
to the client; the caller does that.
|
||||
* Checks to make sure hsoname is within the space we're allowed to discuss.
|
||||
* Does check to make sure you have r, G, or g rights on a database before it
|
||||
lets you scan that database for information.
|
||||
*/
|
||||
|
||||
/* flags:
|
||||
DRO_VERIFY
|
||||
*/
|
||||
/*
|
||||
Returns:
|
||||
DSRFINFO_FORWARDED
|
||||
DIRSRV_NOT_AUTHORIZED
|
||||
PFAILURE
|
||||
PSUCCESS
|
||||
*/
|
||||
/* If called with the DRO_VERIFY flag, will set the P_OBJECT_FILE and
|
||||
P_OBJECT_DIRECTORY flags in the ob structure, but will not *necessarily* put
|
||||
any other information into the ob structure. Caller is still responsible
|
||||
for freeing any links pointed to by the ob structure. */
|
||||
/* dsrobject(), if it returns anything other than DSRFINFO_FORWARDED or
|
||||
PSUCCESS, may leave the ob structure with arbitrary data in it.
|
||||
The caller should not expect the ob structure to remain
|
||||
*/
|
||||
|
||||
/* The database ACL itself may be obtained by using an HSONAME that is just the
|
||||
root prefix of the database. */
|
||||
int
|
||||
dsrobject(RREQ req, char hsoname_type[], char hsoname[], long version,
|
||||
long magic_no,
|
||||
int flags, struct dsrobject_list_options *listopts, P_OBJECT ob)
|
||||
{
|
||||
VDIR_ST dir_st;
|
||||
register VDIR dir = &dir_st;
|
||||
register PFILE fi = NULL; /* Only set if it needs to be. */
|
||||
int retval; /* Integer return value from subfunctions */
|
||||
|
||||
vdir_init(dir); /* empty directory. */
|
||||
set_client_addr(req->peer_addr.s_addr); /* temporary hack. */
|
||||
|
||||
/* Check whether HSONAME-TYPE and HSONAME are valid. */
|
||||
if (!strequal(hsoname_type, "ASCII")) {
|
||||
plog(L_DIR_ERR, req, "dsrobject(): got invalid hsoname-type: %s",
|
||||
hsoname_type, 0);
|
||||
vdir_freelinks(dir);
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
if (check_handle(hsoname) == FALSE) {
|
||||
plog(L_AUTH_ERR, req, "Got an HSONAME outside the part of the \
|
||||
filesystem that this server is authorized to publish information about: %s",
|
||||
hsoname);
|
||||
/* Free the directory links */
|
||||
vdir_freelinks(dir);
|
||||
return DIRSRV_NOT_AUTHORIZED;
|
||||
}
|
||||
|
||||
if (*hsoname != '/') { /* Database or special prefix in use */
|
||||
register int i;
|
||||
for (i = 0; i < db_num_ents; i++) {
|
||||
if (strnequal(hsoname, db_prefixes[i].db_prefix,
|
||||
strlen(db_prefixes[i].db_prefix))) {
|
||||
if (db_prefixes[i].db_acl
|
||||
&& !srv_check_acl(db_prefixes[i].db_acl, NULL, req, "r",
|
||||
SCA_LINKDIR,db_prefixes[i].db_prefix,NULL)
|
||||
&& !srv_check_acl(db_prefixes[i].db_acl, NULL, req, "g",
|
||||
SCA_LINKDIR,db_prefixes[i].db_prefix,NULL)
|
||||
&& !srv_check_acl(db_prefixes[i].db_acl, NULL, req, "G",
|
||||
SCA_LINKDIR,db_prefixes[i].db_prefix,NULL)) {
|
||||
plog(L_AUTH_ERR, req,
|
||||
"Unauthorized database request: %s %s",
|
||||
hsoname, listopts? *(listopts->thiscompp) : "");
|
||||
vdir_freelinks(dir);
|
||||
return DIRSRV_NOT_AUTHORIZED;
|
||||
}
|
||||
/* This could take a while, tell client not to retry */
|
||||
ardp_rwait(req, 180, 0, 0);
|
||||
retval = db_prefixes[i].db_function(req, hsoname,
|
||||
listopts? listopts->thiscompp : NULL,
|
||||
listopts? listopts->remcompp : NULL, dir,
|
||||
(flags & DRO_VERIFY) ? DSDB_VERIFY : 0,
|
||||
"#INTERESTING" /* requested attributes */,
|
||||
listopts ? listopts->filters : NULL);
|
||||
goto dbquery_done;
|
||||
}
|
||||
}
|
||||
/* Here we have a prefix that is not a database, */
|
||||
/* but not a normal filename either */
|
||||
/* If normal file names need not begin with / */
|
||||
/* fall through and try a normal query */
|
||||
}
|
||||
/* Local directories can have associated finfo too. */
|
||||
retval = dsrdir(hsoname, magic_no, dir, NULL, DSRD_ATTRIBUTES);
|
||||
if (retval == PSUCCESS) ob->flags |= P_OBJECT_DIRECTORY;
|
||||
if (retval == PSUCCESS || retval == DIRSRV_NOT_DIRECTORY) {
|
||||
fi = pfalloc();
|
||||
retval = dsrfinfo(hsoname,magic_no,fi);
|
||||
if (retval == DSRFINFO_FORWARDED) {
|
||||
ob->inc_native = VDIN_MUNGED;
|
||||
ob->forward = fi->forward; fi->forward = NULL;
|
||||
pffree(fi);
|
||||
vdir_freelinks(dir);
|
||||
return retval;
|
||||
}
|
||||
if (retval < 0) { /* dsrfinfo returns <0 to mean directory */
|
||||
ob->flags |= P_OBJECT_DIRECTORY;
|
||||
retval = PSUCCESS;
|
||||
} else if (retval == PSUCCESS) {
|
||||
ob->flags |= P_OBJECT_FILE;
|
||||
}
|
||||
}
|
||||
dbquery_done:
|
||||
if (retval == DSRFINFO_FORWARDED) {
|
||||
/* Only get here if dsrdir() or dsdb() returned DSRFINFO_FORWARDED */
|
||||
ob->inc_native = VDIN_MUNGED;
|
||||
ob->forward = dir->f_info->forward; dir->f_info->forward = NULL;
|
||||
vdir_freelinks(dir);
|
||||
return retval;
|
||||
}
|
||||
if (retval) {
|
||||
vdir_freelinks(dir);
|
||||
if (fi) pffree(fi);
|
||||
return retval;
|
||||
}
|
||||
/* Now for some manly calisthenics!
|
||||
Merge f_info and directory info. */
|
||||
/* Only potential conflict here: ACL. Handle it by appending the two
|
||||
ACLs if both are set. (DIRECTORY first; why not). If one is unset,
|
||||
use the default (DEFAULT SYSTEM for DIRECTORY, CONTAINER for OBJECT).
|
||||
If directory and object both have magic numbers set use one from
|
||||
directory.
|
||||
*/
|
||||
if (ob->flags & P_OBJECT_DIRECTORY) {
|
||||
ob->version = dir->version; /* always 0 */
|
||||
ob->inc_native = dir->inc_native;
|
||||
ob->magic_no = dir->magic_no;
|
||||
ob->acl = dir->dacl; dir->dacl = NULL;
|
||||
assert(!dir->f_info); /* should have already been handled */
|
||||
ob->links = dir->links; dir->links = NULL;
|
||||
ob->ulinks = dir->ulinks; dir->ulinks = NULL;
|
||||
ob->native_mtime = dir->native_mtime;
|
||||
} else {
|
||||
ob->inc_native = VDIN_NOTDIR;
|
||||
}
|
||||
if (ob->flags & P_OBJECT_FILE) {
|
||||
if (fi->f_magic_no) ob->magic_no = fi->f_magic_no;
|
||||
if (fi->oacl) {
|
||||
CONCATENATE_LISTS(ob->acl, fi->oacl); fi->oacl = NULL;
|
||||
}
|
||||
ob->exp = fi->exp;
|
||||
ob->ttl = fi->ttl;
|
||||
ob->last_ref = fi->last_ref;
|
||||
ob->forward = fi->forward; fi->forward = NULL;
|
||||
ob->backlinks = fi->backlinks; fi->backlinks = NULL;
|
||||
ob->attributes = fi->attributes; fi->attributes = NULL;
|
||||
}
|
||||
vdir_freelinks(dir);
|
||||
if (fi) pffree(fi); fi = NULL;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Return a list of OBJECT INTRINSIC ACCESS-METHOD attributes for the local
|
||||
real file FILENAME. These attributes should be usable by the client coming
|
||||
from the address client_addr. One day this function will no longer be
|
||||
necessary when we have the Prospero access method working.
|
||||
Allocates pattribs and puts them into RETVAL.
|
||||
|
||||
Note that FILENAME has already been expanded from any HSONAME.
|
||||
*/
|
||||
|
||||
void
|
||||
get_access_method(char filename[], long client_addr, PATTRIB *retval)
|
||||
{
|
||||
PATTRIB at; /* temporary working attribute. */
|
||||
TOKEN nfs_am; /* Access method for NFS (if any) */
|
||||
|
||||
*retval = NULL; /* return list starts empty. */
|
||||
|
||||
/* Check for LOCAL access method. */
|
||||
if (myaddress() == client_addr ||
|
||||
/* Check for loopback net. */
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
(client_addr & 0xff000000) == (127 << 24)
|
||||
#else
|
||||
(client_addr & 0x000000ff) == 127
|
||||
#endif
|
||||
) {
|
||||
/* This may not return information for multi-homed hosts.
|
||||
But it will never return incorrect information. */
|
||||
at = newamat();
|
||||
at->value.sequence = tkappend("LOCAL", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
APPEND_ITEM(at, *retval);
|
||||
} else {
|
||||
#ifdef SHARED_PREFIXES
|
||||
char *cp; /* this memory doesn't need to be freed. */
|
||||
if (cp = check_localpath(filename, client_addr)){
|
||||
at = newamat();
|
||||
at->value.sequence = tkappend("LOCAL", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend(cp, at->value.sequence);
|
||||
APPEND_ITEM(at, *retval);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check for NFS access method. */
|
||||
#ifdef NFS_EXPORT
|
||||
if(nfs_am = check_nfs(filename,client_addr)) {
|
||||
at = newamat();
|
||||
at->value.sequence = nfs_am;
|
||||
APPEND_ITEM(at, *retval);
|
||||
}
|
||||
#endif NFS_EXPORT
|
||||
|
||||
/* Check for AFS access method. Note that the hostname is irrelevant. */
|
||||
if(*afsdir && strnequal(filename, afsdir, strlen(afsdir))) {
|
||||
char *suffix = filename + strlen(afsdir);
|
||||
at = newamat();
|
||||
at->value.sequence = tkappend("AFS", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend("", at->value.sequence);
|
||||
at->value.sequence = tkappend("ASCII", at->value.sequence);
|
||||
at->value.sequence = tkappend(suffix, at->value.sequence);
|
||||
APPEND_ITEM(at, *retval);
|
||||
|
||||
#ifdef AFS_AFTP_GATEWAY /* provide additional access method for sites
|
||||
that don't run AFS. */
|
||||
at = newamat();
|
||||
at->value.sequence = tkappend("AFTP", at->value.sequence);
|
||||
at->value.sequence = tkappend("INTERNET-D", at->value.sequence);
|
||||
at->value.sequence = tkappend(hostname, at->value.sequence);
|
||||
at->value.sequence = tkappend("ASCII", at->value.sequence);
|
||||
at->value.sequence =
|
||||
tkappend(qsprintf_stcopyr((char *) NULL,
|
||||
"%s%s", AFS_AFTP_GATEWAY, suffix),
|
||||
at->value.sequence);
|
||||
at->value.sequence = tkappend("BINARY", at->value.sequence);
|
||||
APPEND_ITEM(at, *retval);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check for AFTP access method. */
|
||||
if(*aftpdir && strnequal(filename,aftpdir, strlen(aftpdir))) {
|
||||
char *suffix = filename + strlen(aftpdir);
|
||||
|
||||
at = newamat();
|
||||
at->value.sequence = tkappend("AFTP", at->value.sequence);
|
||||
at->value.sequence = tkappend("INTERNET-D", at->value.sequence);
|
||||
at->value.sequence = tkappend(hostname, at->value.sequence);
|
||||
at->value.sequence = tkappend("ASCII", at->value.sequence);
|
||||
at->value.sequence = tkappend(suffix, at->value.sequence);
|
||||
at->value.sequence = tkappend("BINARY", at->value.sequence);
|
||||
APPEND_ITEM(at, *retval);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Allocate a new ACCESS-METHOD attribute. */
|
||||
static
|
||||
PATTRIB
|
||||
newamat(void)
|
||||
{
|
||||
PATTRIB retval = atalloc();
|
||||
retval->aname = stcopyr("ACCESS-METHOD", retval->aname);
|
||||
retval->precedence = ATR_PREC_OBJECT;
|
||||
retval->nature = ATR_NATURE_INTRINSIC;
|
||||
retval->avtype = ATR_SEQUENCE;
|
||||
return retval;
|
||||
}
|
||||
124
prospero/lib/psrv/dswfinfo.c
Normal file
124
prospero/lib/psrv/dswfinfo.c
Normal file
@@ -0,0 +1,124 @@
|
||||
/* 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 <psrv.h>
|
||||
#include <stdio.h>
|
||||
#include <perrno.h>
|
||||
#include <plog.h>
|
||||
#ifndef MAXPATHLEN
|
||||
#include <sys/param.h>
|
||||
#ifndef MAXPATHLEN
|
||||
#define MAXPATHLEN 1024
|
||||
#endif
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
|
||||
extern char *rindex();
|
||||
|
||||
extern char shadow[];
|
||||
extern char dirshadow[];
|
||||
extern char dircont[];
|
||||
extern char pfsdat[];
|
||||
extern char aftpdir[];
|
||||
|
||||
#define FILE_VNO 5 /* version # of the file format. Appears in
|
||||
this file and in dsrfinfo.c */
|
||||
|
||||
/* Forward definitions */
|
||||
static FILE *open_shadow_outfile_A(char nm[], char **shadow_fnamep);
|
||||
static int write_data(FILE * outf, PFILE fi);
|
||||
|
||||
/* Logs errors to plog() and returns an error code. */
|
||||
int
|
||||
dswfinfo(char *nm, PFILE fi)
|
||||
{
|
||||
int retval;
|
||||
FILE *outf;
|
||||
AUTOSTAT_CHARPP(shadow_fnamep);
|
||||
|
||||
assert(fi); /* write_data cant handle null fi*/
|
||||
if (outf = open_shadow_outfile_A(nm,shadow_fnamep)) {
|
||||
retval = write_data(outf, fi);
|
||||
} else {
|
||||
return perrno;
|
||||
}
|
||||
locked_fclose_A(outf, *shadow_fnamep, FALSE);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static FILE *
|
||||
open_shadow_outfile_A(char nm[], char **shadow_fnamep)
|
||||
{
|
||||
char real_fname[MAXPATHLEN]; /* Filename after expansion */
|
||||
char shadow_dirname[MAXPATHLEN]; /* directory we create */
|
||||
char *sp; /* pointer to slash */
|
||||
FILE *outf;
|
||||
|
||||
struct stat file_stat_dat;
|
||||
struct stat *file_stat = &file_stat_dat;
|
||||
|
||||
nativize_prefix(nm, real_fname, sizeof(real_fname));
|
||||
|
||||
/* Create the directory to contain the shadow file, if it doesn't already
|
||||
exist. */
|
||||
/* Is the shadow file a directory? */
|
||||
if ((stat(real_fname, file_stat) == 0) || (*nm != '/')) {
|
||||
if ((file_stat->st_mode & S_IFDIR) || (*nm != '/')) {
|
||||
*shadow_fnamep = qsprintf_stcopyr(*shadow_fnamep,
|
||||
"%s%s/%s", shadow, real_fname, dirshadow);
|
||||
} else {
|
||||
*shadow_fnamep = qsprintf_stcopyr(*shadow_fnamep,
|
||||
"%s%s", shadow, real_fname);
|
||||
}
|
||||
} else {
|
||||
plog(L_DATA_FRM_ERR, NOREQ, "Output data file doesnt already exist: %s",
|
||||
real_fname);
|
||||
perrno = PFAILURE;
|
||||
return NULL;
|
||||
}
|
||||
strcpy(shadow_dirname, *shadow_fnamep);
|
||||
assert(sp = rindex(shadow_dirname, '/')); /* must be true. */
|
||||
*sp = '\0';
|
||||
mkdirs(shadow_dirname);
|
||||
if ((outf = locked_fopen(*shadow_fnamep, "w")) == NULL) {
|
||||
plog(L_DATA_FRM_ERR, NOREQ, "Couldn't open the output data file %s",
|
||||
*shadow_fnamep);
|
||||
perrno = PFAILURE;
|
||||
}
|
||||
return outf;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
write_data(FILE * outf, PFILE fi)
|
||||
{
|
||||
OUTPUT_ST out_st;
|
||||
OUTPUT out = &out_st;
|
||||
PATTRIB at;
|
||||
VLINK cur_fp;
|
||||
|
||||
assert(fi);
|
||||
|
||||
filetoout(outf, out);
|
||||
qoprintf(out, "VERSION %d\n", FILE_VNO);
|
||||
qoprintf(out, "MAGIC-NUMBER %d\n", fi->f_magic_no);
|
||||
/* Any forwarding pointers. */
|
||||
for (cur_fp = fi->forward; cur_fp; cur_fp = cur_fp->next) {
|
||||
qoprintf(out, "FORWARD ");
|
||||
out_link(out, cur_fp, 0, (TOKEN) NULL);
|
||||
}
|
||||
/* print out the object ACL if present */
|
||||
out_acl(out, fi->oacl);
|
||||
for (at = fi->attributes; at; at = at->next) {
|
||||
if (at->nature != ATR_NATURE_INTRINSIC) /* INTRINSIC attributes are
|
||||
written specially */
|
||||
out_atr(out, at, 0);
|
||||
}
|
||||
return PSUCCESS;
|
||||
}
|
||||
311
prospero/lib/psrv/dswobject.c
Normal file
311
prospero/lib/psrv/dswobject.c
Normal file
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-copyr.h>.
|
||||
*/
|
||||
|
||||
#include <usc-copyr.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <pmachine.h>
|
||||
#include <pfs.h>
|
||||
#include <perrno.h>
|
||||
#include <psrv.h>
|
||||
#include <plog.h>
|
||||
|
||||
#if (OBJECT_VNO == 5)
|
||||
/* Note this is modeled on the "manly calisthenics" in dsrobject, if this
|
||||
is wrong, then that probably is and vica versa */
|
||||
void
|
||||
ob2dir(P_OBJECT ob, VDIR dir)
|
||||
{
|
||||
|
||||
assert(dir);
|
||||
|
||||
if (ob->flags & P_OBJECT_DIRECTORY) {
|
||||
dir->version = ob->version; /* always 0 */
|
||||
dir->inc_native = ob->inc_native;
|
||||
dir->magic_no = ob->magic_no;
|
||||
dir->dacl = aclcopy(ob->acl);
|
||||
dir->links = vlcopy(ob->links,TRUE);
|
||||
dir->ulinks = vlcopy(ob->ulinks,TRUE);
|
||||
dir->native_mtime = ob->native_mtime;
|
||||
}
|
||||
if (TRUE) { /* (ob->flags & P_OBJECT_FILE) { */
|
||||
/* I'm not sure this is the best way, but since we have f_info field*/
|
||||
register PFILE fi = dir->f_info;
|
||||
if (!dir->f_info) { fi = pfalloc(); dir->f_info = fi; }
|
||||
if (ob->magic_no) fi->f_magic_no = ob->magic_no;
|
||||
/* acl copied above */
|
||||
fi->exp = ob->exp;
|
||||
fi->ttl = ob->ttl;
|
||||
fi->last_ref = ob->last_ref;
|
||||
fi->forward = vlcopy(ob->forward,TRUE);
|
||||
fi->backlinks = vlcopy(ob->backlinks,TRUE);
|
||||
fi->attributes = atlcopy(ob->attributes);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dswobject(char hsonametype[], char hsoname[], P_OBJECT ob)
|
||||
{
|
||||
VDIR_ST dir_st;
|
||||
register VDIR dir = &dir_st;
|
||||
int tmp;
|
||||
|
||||
vdir_init(dir);
|
||||
ob2dir(ob,dir);
|
||||
if (tmp = dswdir(hsoname, dir)) {
|
||||
p_warn_string = qsprintf_stcopyr(p_warn_string,
|
||||
"Failed to update cache for directory %'s: Prospero error %d",
|
||||
hsoname, tmp);
|
||||
}
|
||||
if (dir->f_info) {
|
||||
if (tmp = dswfinfo(hsoname, dir->f_info)) {
|
||||
p_warn_string = qsprintf_stcopyr(p_warn_string,
|
||||
"Failed to update finfo for %'s: Prospero error %d",
|
||||
hsoname, tmp);
|
||||
}
|
||||
}
|
||||
vdir_freelinks(dir);
|
||||
}
|
||||
#endif /*VERSION5*/
|
||||
|
||||
#if (OBJECT_VNO == 6)
|
||||
/* XXX This code is untested and does not work at the moment.
|
||||
I am currently working on it. -swa@ISI.EDU, April 13, 1994. */
|
||||
static int write_data(FILE * outf, P_OBJECT ob);
|
||||
static FILE *open_shadow_outfile_A(char nm[], char *shadow_fname,
|
||||
char **objshadownamep);
|
||||
static size_t canonicalize_prefix(char *native_name, char canon_buf[], size_t canon_bufsiz);
|
||||
static size_t nativize_prefix(char *hsoname, char native_buf[], size_t native_bufsiz);
|
||||
extern int dswobject(char hsonametype[], char hsoname[], P_OBJECT ob)
|
||||
{
|
||||
static int write_data(FILE * outf, P_OBJECT ob);
|
||||
char *objshadowname;
|
||||
int retval;
|
||||
FILE *outf;
|
||||
char shadow_fname[MAXPATHLEN];
|
||||
|
||||
assert(strequal(hsonametype, "ASCII"));
|
||||
filelock_obtain(objshadowname,FALSE); /* Obtain write lock on rel dir */
|
||||
if (!(outf =
|
||||
open_shadow_outfile_A(hsoname, &shadow_fname, &objshadowname)))
|
||||
{ filelock_release(objshadowname, FALSE);
|
||||
return(perrno);
|
||||
}
|
||||
|
||||
retval = write_data(outf, ob);
|
||||
retval = locked_fclose_and_rename(outf, shadow_fname, objshadowname,retval);
|
||||
return(retval);
|
||||
}
|
||||
|
||||
/* XXX This routine will have to be changed. XXX BAD XXX */
|
||||
static FILE *
|
||||
open_shadow_outfile_A(char nm[], char *shadow_fname, char **objshadowname)
|
||||
{
|
||||
char real_fname[MAXPATHLEN]; /* Filename after expansion */
|
||||
char shadow_dirname[MAXPATHLEN]; /* directory we create. */
|
||||
char *sp; /* pointer to slash */
|
||||
FILE *outf;
|
||||
int retval; /* return value from subfunctions */
|
||||
|
||||
struct stat file_stat_dat;
|
||||
struct stat *file_stat = &file_stat_dat;
|
||||
|
||||
/* If special file name, change to real file name */
|
||||
nativize_prefix(nm, real_fname, sizeof real_fname);
|
||||
/* Create the directory to contain the shadow file, if it doesn't already
|
||||
exist. */
|
||||
/* Is the shadow file a directory? */
|
||||
if ((retval = is_dir(real_fname)) == 0) {
|
||||
if (stat(real_fname, file_stat) == 0) {
|
||||
if(file_stat->st_mode & S_IFDIR) {
|
||||
qsprintf(shadow_fname, sizeof shadow_fname,
|
||||
"%s%s/%s", shadow, real_fname, dirshadow);
|
||||
} else {
|
||||
qsprintf(shadow_fname, sizeof shadow_fname,
|
||||
"%s%s", shadow, real_fname);
|
||||
}
|
||||
}
|
||||
strcpy(shadow_dirname, shadow_fname);
|
||||
assert(sp = rindex(shadow_dirname, '/')); /* must be true. */
|
||||
*sp = '\0';
|
||||
mkdirs(shadow_dirname);
|
||||
if ((outf = locked_fopen(shadow_fname, "w")) == NULL) {
|
||||
plog(L_DATA_FRM_ERR, NOREQ, "Couldn't open the output data file %s",
|
||||
shadow_fname);
|
||||
perrno = PFAILURE;
|
||||
}
|
||||
return outf;
|
||||
}
|
||||
|
||||
|
||||
static void dump_links(OUTPUT out, VLINK cur_link);
|
||||
|
||||
static int
|
||||
write_data(FILE * outf, P_OBJECT ob)
|
||||
{
|
||||
OUTPUT_ST out_st;
|
||||
OUTPUT out = &out_st;
|
||||
PATTRIB at;
|
||||
VLINK cur_fp;
|
||||
|
||||
filetoout(outf, out);
|
||||
qoprintf(out, "VERSION %d\n", OBJECT_VNO);
|
||||
if (ob->version) qoprintf("OBJECT-VERSION %d\n", ob->version);
|
||||
qoprintf(out, "MAGIC-NUMBER %d\n", ob->f_magic_no);
|
||||
assert(ob->inc_native != VDIN_UNINITIALIZED);
|
||||
if (ob->inc_native != VDIN_NOTDIR) {
|
||||
qoprintf(out, "INCLUDE-NATIVE ");
|
||||
if(dir->inc_native == VDIN_INCLREAL || dir->inc_native == VDIN_ONLYREAL)
|
||||
qoprintf(out,"INCLREAL\n");
|
||||
else if(dir->inc_native == VDIN_INCLNATIVE)
|
||||
qoprintf(out,"INCLNATIVE\n");
|
||||
else if (dir->inc_native == VDIN_NONATIVE)
|
||||
qoprintf(out,"NONATIVE\n");
|
||||
else
|
||||
internal_error("unknown value of dir->inc_native");
|
||||
}
|
||||
/* print out the ACL if present */
|
||||
out_acl(out, ob->acl);
|
||||
if (ob->exp) {
|
||||
char *cp = NULL;
|
||||
qoprintf(out, "EXP %s\n", cp = p_timetoasn_stcopyr(ob->exp, cp));
|
||||
stfree(cp);
|
||||
}
|
||||
if (ob->ttl) qoprintf(out, "TTL %ld\n", ob->ttl);
|
||||
if (ob->last_ref) {
|
||||
char *cp = NULL;
|
||||
qoprintf(out, "LAST-REF %s\n",
|
||||
cp = p_timetoasn_stcopyr(ob->last_ref, cp));
|
||||
stfree(cp);
|
||||
}
|
||||
/* Any forwarding pointers. */
|
||||
for (cur_fp = ob->forward; cur_fp; cur_fp = cur_fp->next) {
|
||||
qoprintf(out, "FORWARD ");
|
||||
out_link(out, cur_fp, 0, (TOKEN) NULL);
|
||||
}
|
||||
/* Back links */
|
||||
for (cur_fp = ob->backlinks; cur_fp; cur_fp = cur_fp->next) {
|
||||
qoprintf(out, "BACKLINK ");
|
||||
out_link(out, cur_fp, 0, (TOKEN) NULL);
|
||||
}
|
||||
/* Object attributes */
|
||||
for (at = ob->attributes; at; at = at->next) {
|
||||
if (at->nature != ATR_NATURE_INTRINSIC) /* INTRINSIC attributes are
|
||||
written specially */
|
||||
out_atr(out, at, 0);
|
||||
}
|
||||
#if 0 /* need to see if this is still necessary. */
|
||||
/* If directory was, shouldn't be any links which are NATIVE */
|
||||
for (vl = dir->links; vl; vl = vl->next) {
|
||||
vl->flags &= ~VLINK_NATIVE;
|
||||
}
|
||||
#endif
|
||||
dump_links(out, dir->links);
|
||||
dump_links(out, dir->ulinks);
|
||||
if (ob->native_mtime && ob->inc_native != VDIN_NONATIVE) {
|
||||
char *cp = NULL;
|
||||
qoprintf(out, "NATIVE-MTIME %s\n",
|
||||
cp = p_timetoasn_stcopyr(dir->native_mtime, cp));
|
||||
stfree(cp);
|
||||
}
|
||||
return PSUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dump_links(OUTPUT out, VLINK cur_link)
|
||||
{
|
||||
for (; cur_link; cur_link = cur_link->next) {
|
||||
PATTRIB ca;
|
||||
FILTER cur_fil;
|
||||
|
||||
/* Special case for ULINK_PLACEHOLDER. */
|
||||
if (cur_link->expanded == ULINK_PLACEHOLDER) continue;
|
||||
/* don't output native links to directory unless we just converted
|
||||
it to NONATIVE, or unless caching is enabled for the native
|
||||
directory, or unless they have attributes beyond the OBJECT ones. */
|
||||
if (cur_link->flags & VLINK_NATIVE) {
|
||||
cur_link->linktype = cur_link->linktype == 'I' ? 'n' : 'N';
|
||||
}
|
||||
qoprintf(out, "LINK ");
|
||||
out_link(out, cur_link, 0, (TOKEN) NULL);
|
||||
for (ca = cur_link->lattrib; ca; ca = ca->next) {
|
||||
if (ca->nature != ATR_NATURE_INTRINSIC) {
|
||||
if (ca->precedence == ATR_PREC_OBJECT)
|
||||
ca->precedence = ATR_PREC_CACHED;
|
||||
out_atr(out, ca, 0);
|
||||
}
|
||||
}
|
||||
for (cur_fil = cur_link->filters; cur_fil; cur_fil = cur_fil->next) {
|
||||
qoprintf(out, "ATTRIBUTE LINK FIELD FILTER FILTER ");
|
||||
out_filter(out, cur_fil, 0);
|
||||
}
|
||||
out_acl(out, cur_link->acl);
|
||||
if (cur_link->flags & VLINK_NATIVE) {
|
||||
cur_link->linktype = cur_link->linktype == 'N' ? 'L' : 'I';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Stat and get a modification time. Returns 0 upon failure. */
|
||||
static time_t
|
||||
mtime(char native_dirname[])
|
||||
{
|
||||
struct stat st_buf;
|
||||
|
||||
if(stat(native_dirname, &st_buf) == 0)
|
||||
return st_buf.st_mtime;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Is it a directory? 1 = yes, 0 = no, -1 = failure? */
|
||||
static int
|
||||
is_dir(char native_filename[])
|
||||
{
|
||||
struct stat st_buf;
|
||||
|
||||
if(stat(native_filename, &st_buf) == 0)
|
||||
return S_ISDIR(st_buf.st_mode) ? 1 : 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Turns a name of the form /usr/ftp/... (or whatever) into AFTP/... (or
|
||||
whatever). Returns the # of characters it needed to write out the new
|
||||
canonical version of the name. This is the canonical form of the HSONAME.
|
||||
*/
|
||||
static size_t
|
||||
canonicalize_prefix(char *native_name, char canon_buf[], size_t canon_bufsiz)
|
||||
{
|
||||
int aftpdirsiz = strlen(aftpdir);
|
||||
if (*aftpdir && strnequal(native_name, aftpdir, aftpdirsiz)
|
||||
&& (native_name[aftpdirsiz] == '/' ||
|
||||
native_name[aftpdirsiz] == '\0')) {
|
||||
return qsprintf(canon_buf, canon_bufsiz, "AFTP%s",
|
||||
native_name + aftpdirsiz);
|
||||
}
|
||||
return qsprintf(canon_buf, canon_bufsiz, "%s", native_name);
|
||||
}
|
||||
|
||||
|
||||
static size_t
|
||||
nativize_prefix(char *hsoname, char native_buf[], size_t native_bufsiz)
|
||||
{
|
||||
int aftpdirsiz = strlen(aftpdir);
|
||||
if (*aftpdir && strnequal(hsoname, "AFTP", 4)
|
||||
&& (hsoname[4] == '/' || hsoname[4] == '\0')) {
|
||||
return qsprintf(native_buf, native_bufsiz, "%s%s",
|
||||
aftpdir, hsoname + 4);
|
||||
}
|
||||
return qsprintf(native_buf, native_bufsiz, "%s", hsoname);
|
||||
}
|
||||
#endif /* 0 */
|
||||
39
prospero/lib/psrv/error_reply.c
Normal file
39
prospero/lib/psrv/error_reply.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 1992 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-copyr.h>
|
||||
*/
|
||||
|
||||
#include <ardp.h>
|
||||
#include <psrv.h>
|
||||
#include <plog.h>
|
||||
#include <pprot.h>
|
||||
#include <perrno.h>
|
||||
|
||||
/* This function will execute both a vplog() and an vsendmqf() in order to
|
||||
report on an erroneous condition.
|
||||
It makes error returns easier. It returns PFAILURE, since it should only be
|
||||
used if an error has occurred.
|
||||
It also automatically prefixes the word ERROR to the error reply packets.
|
||||
It appends the appropriate newlines, so you don't have to.
|
||||
*/
|
||||
|
||||
int
|
||||
error_reply(RREQ req, char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *bufp;
|
||||
|
||||
va_start(ap, format);
|
||||
|
||||
|
||||
bufp = vplog(L_DIR_PERR, req, format, ap); /* return formatted string */
|
||||
|
||||
reply(req, "ERROR ");
|
||||
reply(req, bufp);
|
||||
creply(req, "\n");
|
||||
va_end(ap);
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
|
||||
1
prospero/lib/psrv/gopher_gw/.gitignore
vendored
Normal file
1
prospero/lib/psrv/gopher_gw/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Makefile
|
||||
6
prospero/lib/psrv/gopher_gw/FILES
Normal file
6
prospero/lib/psrv/gopher_gw/FILES
Normal file
@@ -0,0 +1,6 @@
|
||||
FILES
|
||||
Makefile
|
||||
glalloc.c
|
||||
goph_gw_dsdb.c
|
||||
goph_gw_mutex.c
|
||||
gopher.h
|
||||
47
prospero/lib/psrv/gopher_gw/Makefile.in
Executable file
47
prospero/lib/psrv/gopher_gw/Makefile.in
Executable file
@@ -0,0 +1,47 @@
|
||||
SOURCEBASE = ../../..
|
||||
include $(SOURCEBASE)/Makefile.config
|
||||
|
||||
CFILES = \
|
||||
glalloc.c \
|
||||
goph_gw_dsdb.c \
|
||||
goph_gw_mutex.c
|
||||
|
||||
OBJECTS = \
|
||||
glalloc.o \
|
||||
goph_gw_dsdb.o \
|
||||
goph_gw_mutex.o
|
||||
|
||||
OTHERTARGETS = ${GOPHER_GW_LIB}
|
||||
|
||||
all: ${GOPHER_GW_LIB}
|
||||
|
||||
${GOPHER_GW_LIB}: ${OBJECTS}
|
||||
rm -f ${GOPHER_GW_LIB}
|
||||
ar r${AR_FLAGS} ${GOPHER_GW_LIB} ${OBJECTS}
|
||||
$(RANLIB) ${GOPHER_GW_LIB}
|
||||
|
||||
# Dependencies
|
||||
glalloc.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/psrv.h ../../../include/pparse.h \
|
||||
gopher.h ../../../include/mitra_macros.h
|
||||
goph_gw_dsdb.o : \
|
||||
../../../include/pmachine.h \
|
||||
../../../include/pserver.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/implicit_fixes.h \
|
||||
../../../include/psrv.h ../../../include/pparse.h \
|
||||
../../../include/perrno.h ../../../include/plog.h gopher.h
|
||||
goph_gw_mutex.o : gopher.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
|
||||
58
prospero/lib/psrv/gopher_gw/glalloc.c
Normal file
58
prospero/lib/psrv/gopher_gw/glalloc.c
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 <pfs.h>
|
||||
#include <psrv.h>
|
||||
#include "gopher.h"
|
||||
#include <mitra_macros.h>
|
||||
|
||||
static GLINK lfree = NULL;
|
||||
int glink_count = 0;
|
||||
int glink_max = 0;
|
||||
|
||||
|
||||
/*
|
||||
glalloc(): Allocate and initialize GLINK structure.
|
||||
Signal out_of_memory() on failure.
|
||||
*/
|
||||
|
||||
GLINK
|
||||
glalloc(void)
|
||||
{
|
||||
GLINK gl;
|
||||
|
||||
TH_STRUC_ALLOC(glink,GLINK,gl);
|
||||
/* Initialize and fill in default values */
|
||||
gl->type = '0';
|
||||
gl->name = NULL;
|
||||
gl->selector = NULL;
|
||||
gl->host = NULL;
|
||||
gl->port = 0;
|
||||
gl->protocol_mesg = NULL;
|
||||
return gl;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
glfree(GLINK gl)
|
||||
{
|
||||
/* Free any bits of memory pointed to by members of the structure. */
|
||||
if (gl->name) stfree(gl->name);
|
||||
if (gl->host) stfree(gl->host);
|
||||
if (gl->selector) stfree(gl->selector);
|
||||
if (gl->protocol_mesg) stfree(gl->protocol_mesg);
|
||||
/* Free the structure itself. */
|
||||
TH_STRUC_FREE(glink,GLINK,gl);
|
||||
}
|
||||
|
||||
void
|
||||
gllfree(GLINK gl)
|
||||
{
|
||||
TH_STRUC_LFREE(GLINK,gl,glfree)
|
||||
}
|
||||
|
||||
867
prospero/lib/psrv/gopher_gw/goph_gw_dsdb.c
Normal file
867
prospero/lib/psrv/gopher_gw/goph_gw_dsdb.c
Normal file
@@ -0,0 +1,867 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
/* Definitions of constants */
|
||||
#define MAX_NUM_GOPHER_LINKS 3000 /* maximum # of directory links to
|
||||
return before giving up. */
|
||||
|
||||
/* Archie server we redirect ftp:hostname@ queries to. */
|
||||
/* Don't define this for now, since it can lead to odd results. */
|
||||
/* #define ARCHIE_SERVER "ARCHIE.SURA.NET" */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h> /* includes SOL_SOCKET */
|
||||
#include <netinet/in.h>
|
||||
#include <sys/uio.h> /* for writev(), struct iovec */
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
#include <pmachine.h>
|
||||
|
||||
#include <pserver.h>
|
||||
#include <ardp.h> /* unixerrstr() prototype. */
|
||||
#include <pfs.h> /* assert, internal_error, prototypes */
|
||||
#include <psrv.h>
|
||||
#include <perrno.h>
|
||||
#include <plog.h>
|
||||
#include "gopher.h"
|
||||
#include <string.h>
|
||||
#ifdef PSRV_WAIS_GW
|
||||
#include <wais-source.h>
|
||||
#include <psite.h> /* For WAIS_SOURCE_DIR */
|
||||
#endif
|
||||
|
||||
/* 5 secs seems a bit short for this */
|
||||
#ifndef G_OPEN_TIMEOUT
|
||||
#define G_OPEN_TIMEOUT 10
|
||||
#endif
|
||||
#ifndef G_READ_TIMEOUT
|
||||
#define G_READ_TIMEOUT 10
|
||||
#endif
|
||||
|
||||
#ifndef GFTP_READ_TIMEOUT
|
||||
#define GFTP_READ_TIMEOUT 20
|
||||
#endif
|
||||
|
||||
#ifndef GSEARCH_READ_TIMEOUT
|
||||
#define GSEARCH_READ_TIMEOUT 30
|
||||
#endif
|
||||
|
||||
extern char hostwport[];
|
||||
extern int quick_open_tcp_stream(char host[], int port, int timeout);
|
||||
extern char *quick_fgets(char *s, int n, FILE *stream, int timeout);
|
||||
|
||||
static GLINK quick_get_menu(char *host, int port, char *selector, int tme);
|
||||
static void glinks_to_dirob(GLINK glist, P_OBJECT ob);
|
||||
static void atput(VLINK vl, char *name,...);
|
||||
static void ftp_check_am(GLINK gl, VLINK r, char *textorbin);
|
||||
static void ftp_check_dir(GLINK gl, VLINK r);
|
||||
static int wais_check_dir(GLINK gl, VLINK r);
|
||||
static void zap_trailing_spaces(char *host);
|
||||
|
||||
|
||||
/* This function is passed an empty object which has been initialized with
|
||||
oballoc(). It returns a possibly populated directory and
|
||||
DIRSRV_NOT_FOUND or PSUCCESS. Note that the directory will need
|
||||
to have links within it freed, even if an error code is returned. */
|
||||
|
||||
/* This sets p_warn_string and pwarn if an unrecognized gopher line is
|
||||
received. That is good. */
|
||||
|
||||
/* This code needs to return attributes in response to a GET-OBJECT-INFO query.
|
||||
*/
|
||||
int
|
||||
gopher_gw_dsdb(RREQ req, /* Request pointer (unused) */
|
||||
char *hsoname, /* Name of the directory */
|
||||
long version,/* Version #; currently ignored */
|
||||
long magic_no, /* Magic #; currently ignored */
|
||||
int flags, /* Currently only recognize DRO_VERIFY */
|
||||
struct dsrobject_list_options *listopts, /* options (use *remcompp
|
||||
and *thiscompp) */
|
||||
P_OBJECT ob)
|
||||
{ /* Object to be filled in */
|
||||
int tmp;
|
||||
char *cp;
|
||||
AUTOSTAT_CHARPP(hostp); /* For threads. */
|
||||
int port;
|
||||
char type;
|
||||
char *selectorcp; /* a character pointer that might point to the
|
||||
first part of the selector or possibly the
|
||||
complete selector. */
|
||||
char *selector; /* the final selector */
|
||||
GLINK glist; /* list of gopher links */
|
||||
int timeout; /* Timeout for lines (not connect) */
|
||||
|
||||
ob->version = 0; /* unversioned */
|
||||
ob->inc_native = VDIN_PSEUDO;
|
||||
ob->flags = P_OBJECT_DIRECTORY;
|
||||
ob->magic_no = 0;
|
||||
ob->acl = NULL;
|
||||
tmp = qsscanf(hsoname, "GOPHER-GW/%&[^(](%d)/%c%r/%r",
|
||||
hostp, &port, &type, &cp, &selectorcp);
|
||||
if (tmp < 4)
|
||||
return DIRSRV_NOT_FOUND;
|
||||
|
||||
if (type == '1') {
|
||||
if (tmp < 5)
|
||||
return DIRSRV_NOT_FOUND;
|
||||
selector = selectorcp;
|
||||
} else if (type == '7') {
|
||||
AUTOSTAT_CHARPP(sp); /* Memory allocated for selector */
|
||||
if (tmp < 4)
|
||||
return DIRSRV_NOT_FOUND;
|
||||
else if (tmp == 4) {
|
||||
selectorcp = "";
|
||||
} /* if tmp = 5, selectorcp already set. */
|
||||
/* Now set the selector. */
|
||||
if (!listopts || !listopts->thiscompp || !*listopts->thiscompp ||
|
||||
strequal(*listopts->thiscompp, "")
|
||||
|| strequal(*listopts->thiscompp, "*"))
|
||||
/* last test against * might be inappropriate */
|
||||
return PSUCCESS; /* Display no contents for the directory */
|
||||
/* Set the selector. */
|
||||
selector = *sp = qsprintf_stcopyr(*sp, "%s%s%s", selectorcp,
|
||||
(*selectorcp) ? "\t" : "", *listopts->thiscompp);
|
||||
/* We just used up thiscompp, so we'd better reset it. */
|
||||
/* Oops - && here was meaningless */
|
||||
/* I changed this so that the else is not done if listopts->remcompp
|
||||
is null, in that case (as in when called by get_object_info)
|
||||
listopts->thiscompp is also null so "*listopts->thiscompp = NULL"
|
||||
generates a segment violation, if this is the case then we didnt
|
||||
use a component anyway, so no need to advance to the next */
|
||||
if (listopts->remcompp) {
|
||||
if (*listopts->remcompp) {
|
||||
*listopts->thiscompp = (*listopts->remcompp)->token;
|
||||
*listopts->remcompp = (*listopts->remcompp)->next;
|
||||
} else {
|
||||
*listopts->thiscompp = NULL;
|
||||
}
|
||||
}
|
||||
/* Now that the selector is set, fall through. */
|
||||
} else { /* unknown type for gatewaying */
|
||||
return DIRSRV_NOT_FOUND;
|
||||
}
|
||||
/* don't bother retrieving the contents if just verifying. */
|
||||
if (flags & DRO_VERIFY)
|
||||
return PSUCCESS;
|
||||
if (type == '7') {
|
||||
timeout = GSEARCH_READ_TIMEOUT;
|
||||
} else {
|
||||
if (strncmp(selector,"ftp:",4)== 0 ) {
|
||||
timeout = GFTP_READ_TIMEOUT;
|
||||
} else {
|
||||
timeout = G_READ_TIMEOUT;
|
||||
}
|
||||
}
|
||||
if ((glist = quick_get_menu(*hostp, port, selector, timeout))
|
||||
== NULL && perrno)
|
||||
return perrno;
|
||||
glinks_to_dirob(glist, ob);
|
||||
gllfree(glist);
|
||||
return PSUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static GLINK quick_next_menu_item(FILE * fp, int timeout);
|
||||
extern int p_open_tcp_stream(const char host[], int port);
|
||||
|
||||
/* Returns NULL & sets perrno on error. */
|
||||
static GLINK
|
||||
quick_get_menu(char *host, int port, char *selector, int timeout)
|
||||
{
|
||||
GLINK retval = NULL;
|
||||
GLINK gl;
|
||||
FILE *fp; /* used for reading only. Tried to use it for
|
||||
reading & writing without success; see
|
||||
comment below. */
|
||||
int fd;
|
||||
int tmp; /* return value from write() and read()*/
|
||||
int nlinks = 0; /* # of links in directory */
|
||||
#ifndef NO_IOVEC
|
||||
struct iovec iov[2];
|
||||
#endif
|
||||
|
||||
fd = quick_open_tcp_stream(host, port, G_OPEN_TIMEOUT);
|
||||
/* Copied from vcache */
|
||||
if (fd < 0) {
|
||||
perrno = DIRSRV_GOPHER; /* work on error reporting */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if ! defined(NO_IOVEC) && ! defined(PFS_THREADS)
|
||||
/* Current implementation of threads does not include writev(). */
|
||||
iov[0].iov_base = selector;
|
||||
iov[0].iov_len = strlen(selector);
|
||||
iov[1].iov_base = "\r\n";
|
||||
iov[1].iov_len = 2;
|
||||
tmp = writev(fd, iov, 2);
|
||||
if (tmp != iov[0].iov_len + iov[1].iov_len) {
|
||||
#else
|
||||
tmp = write(fd, selector, strlen(selector));
|
||||
if (tmp != strlen(selector)) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Couldn't send selector to gopher \
|
||||
connection to %s: Call to write(%d,%s,%d) failed: errno %d: \
|
||||
%s", host, fd, selector, strlen(selector), errno, unixerrstr());
|
||||
redo_close:
|
||||
if(close(fd) == -1 && errno == EINTR) goto redo_close;
|
||||
perrno = DIRSRV_GOPHER;
|
||||
return NULL;
|
||||
}
|
||||
tmp = write(fd, "\r\n", 2);
|
||||
if (tmp != 2) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Couldn't send selector to gopher \
|
||||
connection to %s: Call to write(%d, \"\\r\\n\", 2) failed: errno %d: %s",
|
||||
host, fd, errno, unixerrstr());
|
||||
#endif
|
||||
redo_close2:
|
||||
if(close(fd) == -1 && errno == EINTR) goto redo_close2;
|
||||
perrno = DIRSRV_GOPHER;
|
||||
return NULL;
|
||||
}
|
||||
fp = fdopen(fd, "r"); /* open fp just for reading */
|
||||
/* Comment from Alan Emtage of Bunyip Information Systems which explains
|
||||
why I'm treating the writing end as a raw file descriptor and the
|
||||
reading end through the stdio library:
|
||||
|
||||
From: bajan@bunyip.com (Alan Emtage)
|
||||
Date: Sat, 28 Aug 1993 10:01:32 -0400
|
||||
|
||||
Hi Steve,
|
||||
You have a comment in the gopher GW code to the effect that "this
|
||||
experiment didn't work.... if you know why, tell me". Well I will :-)
|
||||
|
||||
For some reason which I haven't figured out, you can't a _socket_ file
|
||||
descriptor with fdopen in any form of update mode (you were trying to do
|
||||
it with "r+"). However it can be done if you open the fd _twice_. One
|
||||
FILE * for reading one for writing. Then everything works fine. What is
|
||||
going on in the underlying layers I don't know, but I'd bet that the
|
||||
symptoms you got was that you were reading things that you had
|
||||
previously written to the FILE * (and thought had just gone down the
|
||||
pipe to the remote connection).
|
||||
|
||||
Hope this helps.
|
||||
|
||||
-Alan
|
||||
*/
|
||||
perrno = PSUCCESS;
|
||||
while (gl = quick_next_menu_item(fp,timeout)) {
|
||||
if (++nlinks > MAX_NUM_GOPHER_LINKS) {
|
||||
perrno = DIRSRV_TOO_MANY;
|
||||
gllfree(retval);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
APPEND_ITEM(gl, retval);
|
||||
}
|
||||
fclose(fp);
|
||||
redo_close3:
|
||||
if(close(fd) == -1 && errno == EINTR) goto redo_close3;
|
||||
if (perrno != PSUCCESS) {
|
||||
gllfree(retval);
|
||||
return(NULL); /* Return error code from next_menu_item*/
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* This client opens a TCP stream to the host/port & returns a FILE pointer. */
|
||||
/* Returns NULL on failure; sets p_err_string */
|
||||
FILE *
|
||||
fopen_stream(char *host, int port)
|
||||
{
|
||||
int fd = quick_open_tcp_stream(host, port, G_OPEN_TIMEOUT);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
return fdopen(fd, "r+");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Reads the next valid menu item from the stream FP. Returns NULL if
|
||||
no more, or if more than 3 erroneous lines go by. If a line is sent
|
||||
longer than 1024 characters, it is definitely illegal according to the
|
||||
Gopher spec, which requests no more than 255 chars for the selector and 80
|
||||
for the description. */
|
||||
/* Need to work on the error reporting. */
|
||||
static GLINK
|
||||
quick_next_menu_item(FILE * fp, int timeout)
|
||||
{
|
||||
GLINK r;
|
||||
char buf[1024];
|
||||
int buflen; /* # of characters in this buffer. */
|
||||
int nbad = 0;
|
||||
|
||||
|
||||
again:
|
||||
if (nbad > 3)
|
||||
return NULL;
|
||||
|
||||
if (!quick_fgets(buf, sizeof buf, fp, timeout)) {
|
||||
if (errno = ETIMEDOUT) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Timed out after %d secs waiting for response", timeout);
|
||||
perrno = DIRSRV_GOPHER;
|
||||
return NULL;
|
||||
}
|
||||
assert(FALSE);
|
||||
}
|
||||
buflen = strlen(buf);
|
||||
if (sizeof buf - 1 == buflen) { /* line too long; missed CRLF */
|
||||
++nbad;
|
||||
goto again;
|
||||
}
|
||||
r = glalloc();
|
||||
/* The standard specifies a trailing CR, but apparantly
|
||||
e.g. archive.egr.msu.edu(70) this is not guarranteed */
|
||||
assert(buf[buflen -1] == '\n');
|
||||
if (buf[buflen - 1] == '\n')
|
||||
buf[--buflen] = '\0';
|
||||
if (buf[buflen - 1] == '\r')
|
||||
buf[--buflen] = '\0';
|
||||
/* Check for end of menu */
|
||||
if (strequal(buf, ".")) {
|
||||
glfree(r);
|
||||
return NULL; /* the end has been spotted. */
|
||||
}
|
||||
#if 0
|
||||
if (qsscanf(buf, "%c%&[^\t]%*1[\t]%&(^\t)%*1[\t]%&[^\t]%*1[\t]%d",
|
||||
&r->type, &r->name, &r->selector, &r->host, &r->port) < 5) {
|
||||
/* Note that %&( is not yet implemented, so we're doing it this way
|
||||
instead. */
|
||||
#else
|
||||
if ((qsscanf(buf, "%c%&[^\t]%*1[\t]%&[^\t]%*1[\t]%&[^\t]%*1[\t]%d",
|
||||
&r->type, &r->name, &r->selector, &r->host, &r->port) < 5)
|
||||
&& ((r->selector = stcopyr("", r->selector)),
|
||||
(qsscanf(buf, "%c%&[^\t]%*1[\t]%*1[\t]%&[^\t]%*1[\t]%d",
|
||||
&r->type, &r->name, &r->host, &r->port) < 4))) {
|
||||
#endif
|
||||
++nbad;
|
||||
p_warn_string = qsprintf_stcopyr(p_warn_string,
|
||||
"Encountered unrecognized Gopher message: %s", buf);
|
||||
pwarn = PWARNING;
|
||||
glfree(r);
|
||||
goto again;
|
||||
}
|
||||
nbad = 0;
|
||||
/* Some special cases, for error messages that appear to be menus */
|
||||
if(strncmp(r->name,"Server error",12) == 0) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,r->name);
|
||||
perrno = DIRSRV_GOPHER;
|
||||
return NULL;
|
||||
}
|
||||
r->protocol_mesg = stcopy(buf);
|
||||
return r;
|
||||
}
|
||||
|
||||
static VLINK gltovl(GLINK gl);
|
||||
static void add_collation_order(int linknum, VLINK vl);
|
||||
|
||||
/* It is ok to modify the GLINKs, as long as glist is left at the head of a
|
||||
list of stuff to be freed with gllfree() by the caller of this function.
|
||||
|
||||
A lot of the hair in this function is here because we must make sure that
|
||||
Gopher replicas are returned as Prospero replicas. For now, the only way to
|
||||
make sure two objects are treated as replicas is for them to be links with
|
||||
the same positive ID REMOTE value. */
|
||||
static void
|
||||
glinks_to_dirob(GLINK glist, P_OBJECT ob)
|
||||
{
|
||||
int menu_entry_number = 0; /* # of menu entries read */
|
||||
int replica_list = 0; /* nonzero if handling replica list */
|
||||
long current_magic_no = 0L; /* set magic starting hash */
|
||||
VLINK vl = NULL; /* last vlink processed */
|
||||
GLINK gl; /* index */
|
||||
for (gl = glist; gl; gl = gl->next) {
|
||||
/* If we found this link is a replica, put a magic # on the head of the
|
||||
list. */
|
||||
if (!replica_list && gl->type == '+') {
|
||||
if (!vl)
|
||||
continue; /* no previous gopher link for this to be a
|
||||
replica of; perhaps we could not convert the
|
||||
gopher link to a virtual link. */
|
||||
if (!current_magic_no)
|
||||
current_magic_no = generate_magic(vl);
|
||||
while (magic_no_in_list(++current_magic_no, ob->links)) {
|
||||
/* Check for numeric overflow */
|
||||
if (current_magic_no <= 0)
|
||||
current_magic_no = 1;
|
||||
}
|
||||
vl->f_magic_no = ++current_magic_no; /* new magic no */
|
||||
}
|
||||
if (gl->type != '+')
|
||||
replica_list = 0;
|
||||
else {
|
||||
assert(gl->previous);
|
||||
gl->type = gl->previous->type; /* gets type from head of list. */
|
||||
}
|
||||
if ((vl = gltovl(gl)) == NULL) {
|
||||
replica_list = 0; /* break the chain of replicas */
|
||||
continue; /* can't convert it */
|
||||
}
|
||||
if (replica_list) {
|
||||
vl->f_magic_no = current_magic_no;
|
||||
add_collation_order(menu_entry_number, vl);
|
||||
} else {
|
||||
add_collation_order(++menu_entry_number, vl);
|
||||
}
|
||||
APPEND_ITEM(vl, ob->links);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef NEVERDEFINED
|
||||
/* I intend using this to return attributes for GIET-OBJECT-INFO calsl
|
||||
but I need docs on what to return first */
|
||||
/* Converts a hsoname back to a gl */
|
||||
static GLINK
|
||||
hsoname2gl(char *hsoname)
|
||||
{
|
||||
GLINK gl = glalloc();
|
||||
|
||||
tmp = qsscanf(hsoname, "GOPHER-GW/%&[^(](%d)/%c/%r",
|
||||
&gl->host, &gl->port, &gl->type, &gl->selectorcp);
|
||||
switch (&gl->type) {
|
||||
'0': if (tmp < 4) goto hsoname2gl_bad;
|
||||
break;
|
||||
'1': if (tmp < 4) goto hsoname2gl_bad;
|
||||
break;
|
||||
'7': if (tmp < 3) goto hsoname2gl_bad;
|
||||
break;
|
||||
default:
|
||||
return NULL; /* Unsupported type */
|
||||
}
|
||||
/* name,selector,protocol_mesg arent set by this */
|
||||
return gl;
|
||||
|
||||
hsoname2gl_bad:
|
||||
glfree(gl);
|
||||
return gl;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Returns NULL if couldn't convert the gopher link GL to a Prospero link VL.
|
||||
Otherwise returns a new VLINK. */
|
||||
static VLINK
|
||||
gltovl(GLINK gl)
|
||||
{
|
||||
VLINK r = vlalloc();
|
||||
PATTRIB at;
|
||||
/* check if something is an AFTP link. If so, handle it appropriately.*/
|
||||
/* add AFTP Access method */
|
||||
|
||||
r->name = gl->name;
|
||||
gl->name = NULL;
|
||||
atput(r, "GOPHER-MENU-ITEM", gl->protocol_mesg, (char *) 0);
|
||||
|
||||
switch (gl->type) {
|
||||
case '0': /* Text files */
|
||||
case 'c': /* Calendar Text files (not in RFC1436) */
|
||||
case 'e': /* Event Text files (not in RFC1436) */
|
||||
/* This comes first because, in the current client implementation,
|
||||
the server is expected to return access methods in what it believes
|
||||
the preferred order is. We prefer direct AFTP connections to
|
||||
overloading the intermediary Gopher gateways. */
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
ftp_check_am(gl, r, "TEXT");
|
||||
atput(r, "ACCESS-METHOD", "GOPHER", "", "", "", "", "TEXT",
|
||||
(char *) 0);
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
r->hsoname = gl->selector;
|
||||
gl->selector = NULL;
|
||||
atput(r, "OBJECT-INTERPRETATION", "DOCUMENT", "TEXT", "ASCII",
|
||||
(char *) 0);
|
||||
break;
|
||||
case '1': /* Directories */
|
||||
r->host = stcopy(hostwport);
|
||||
r->target = stcopyr("DIRECTORY", r->target);
|
||||
r->hsoname = qsprintf_stcopyr(r->hsoname,
|
||||
"GOPHER-GW/%s(%d)/%c/%s", gl->host,
|
||||
gl->port, gl->type, gl->selector);
|
||||
atput(r, "OBJECT-INTERPRETATION", "DIRECTORY", (char *) 0);
|
||||
ftp_check_dir(gl, r);
|
||||
break;
|
||||
case '4': /* Macintosh BinHex (.hqx) text file */
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
ftp_check_am(gl, r, "TEXT");
|
||||
atput(r, "ACCESS-METHOD", "GOPHER", "", "", "", "", "TEXT",
|
||||
(char *) 0);
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
r->hsoname = gl->selector;
|
||||
gl->selector = NULL;
|
||||
atput(r, "OBJECT-INTERPRETATION", "EMBEDDED", "BINHEX", "DATA",
|
||||
(char *) 0);
|
||||
break;
|
||||
case '5': /* PC-Dos binary files. */
|
||||
case '9': /* Generic binary files */
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
ftp_check_am(gl, r, "BINARY");
|
||||
atput(r, "ACCESS-METHOD", "GOPHER", "", "", "", "", "BINARY",
|
||||
(char *) 0);
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
r->hsoname = gl->selector;
|
||||
gl->selector = NULL;
|
||||
atput(r, "OBJECT-INTERPRETATION", "DATA", (char *) 0);
|
||||
break;
|
||||
case '6': /* UNIX UUencoded file. */
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
ftp_check_am(gl, r, "TEXT");
|
||||
atput(r, "ACCESS-METHOD", "GOPHER", "", "", "", "", "TEXT",
|
||||
(char *) 0);
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
r->hsoname = gl->selector;
|
||||
gl->selector = NULL;
|
||||
atput(r, "OBJECT-INTERPRETATION", "EMBEDDED", "UUENCODE", "DATA",
|
||||
(char *) 0);
|
||||
break;
|
||||
case '7': /* Gopher searches */
|
||||
r->target = stcopyr("DIRECTORY", r->target);
|
||||
r->host = stcopy(hostwport);
|
||||
atput(r, "OBJECT-INTERPRETATION", "SEARCH", (char *) 0);
|
||||
#ifdef PSRV_WAIS_GW
|
||||
/* wais_check_dir() rewrites wais searches as appropriate, and
|
||||
reformats the link to be a WAIS one. */
|
||||
if (wais_check_dir(gl, r))
|
||||
break; /* done */
|
||||
#endif
|
||||
/* Write the link as a gopher search link. */
|
||||
r->hsoname =
|
||||
qsprintf_stcopyr(r->hsoname, "GOPHER-GW/%s(%d)/7/%s",
|
||||
gl->host, gl->port, gl->selector);
|
||||
atput(r, "QUERY-METHOD", "gopher-query(search-words)",
|
||||
"${search-words}", "", (char *) 0);
|
||||
atput(r, "QUERY-ARGUMENT", "search-words",
|
||||
"Index word(s) to search for", "mandatory char*", "%s", "",
|
||||
(char *) 0);
|
||||
atput(r, "QUERY-DOCUMENTATION", "gopher-query()", "This is a Gopher \
|
||||
protocol query exported through Prospero. Since it is not a native Prospero \
|
||||
query, we have very little documentation available for you.", (char *) 0);
|
||||
atput(r, "QUERY-DOCUMENTATION", "search-words", "This string says \
|
||||
what you're searching for or what information you're specifying.",
|
||||
"Type any string. Sometimes SPACEs are treated as implied \
|
||||
'and' operators. Sometimes the words 'and', 'or', and 'not' are recognized \
|
||||
as boolean operators.", (char *) 0);
|
||||
break;
|
||||
case '8':{ /* TELNET session */
|
||||
char *m = ""; /* message */
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
if (*(gl->selector))
|
||||
m = qsprintf_stcopyr((char *) NULL,
|
||||
"Use the account name \"%s\" to log in",
|
||||
gl->selector);
|
||||
atput(r, "ACCESS-METHOD", "TELNET", "", "", "", "", m, (char *) 0);
|
||||
zap_trailing_spaces(gl->host);
|
||||
/* Gopher uses a telnet port of 0 to mean the default telnet port. */
|
||||
if (gl->port == 0) {
|
||||
r->host = gl->host;
|
||||
gl->host = NULL;
|
||||
} else {
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
}
|
||||
atput(r, "OBJECT-INTERPRETATION", "PORTAL", (char *) 0);
|
||||
if (*m)
|
||||
stfree(m);
|
||||
break;
|
||||
}
|
||||
case 'I': /* Generic Image. */
|
||||
case ':': /* Gopher+ bitmap image type; not in RFC1436 */
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
ftp_check_am(gl, r, "BINARY");
|
||||
atput(r, "ACCESS-METHOD", "GOPHER", "", "", "", "", "BINARY",
|
||||
(char *) 0);
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
r->hsoname = gl->selector;
|
||||
gl->selector = NULL;
|
||||
atput(r, "OBJECT-INTERPRETATION", "IMAGE", (char *) 0);
|
||||
break;
|
||||
case 'M': /* MIME. Not in RFC1436. */
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
ftp_check_am(gl, r, "TEXT");
|
||||
atput(r, "ACCESS-METHOD", "GOPHER", "", "", "", "", "TEXT", (char *) 0);
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
r->hsoname = gl->selector;
|
||||
gl->selector = NULL;
|
||||
atput(r, "OBJECT-INTERPRETATION", "DOCUMENT", "MIME", (char *) 0);
|
||||
break;
|
||||
|
||||
case 'T':{ /* TN3270 session */
|
||||
char *m = ""; /* message */
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
zap_trailing_spaces(gl->host);
|
||||
/* Gopher uses a telnet port of 0 to mean the default telnet port. */
|
||||
if (gl->port == 0) {
|
||||
r->host = gl->host;
|
||||
gl->host = NULL;
|
||||
} else {
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
}
|
||||
if (*(gl->selector))
|
||||
m = qsprintf_stcopyr((char *) NULL,
|
||||
"Use the account name \"%s\" to log in",
|
||||
gl->selector);
|
||||
atput(r, "ACCESS-METHOD", "TN3270", "", "", "", "", m, (char *) 0);
|
||||
atput(r, "OBJECT-INTERPRETATION", "PORTAL", (char *) 0);
|
||||
if (*m)
|
||||
stfree(m);
|
||||
break;
|
||||
}
|
||||
case 'g': /* Gif */
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
ftp_check_am(gl, r, "BINARY");
|
||||
atput(r, "ACCESS-METHOD", "GOPHER", "", "", "", "", "BINARY",
|
||||
(char *) 0);
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
r->hsoname = gl->selector;
|
||||
gl->selector = NULL;
|
||||
atput(r, "OBJECT-INTERPRETATION", "IMAGE", "GIF", (char *) 0);
|
||||
break;
|
||||
case 's': /* SOUND. Not in RFC1436. */
|
||||
case '<': /* Gopher+ sound type; not in RFC1436 */
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
ftp_check_am(gl, r, "BINARY");
|
||||
atput(r, "ACCESS-METHOD", "GOPHER", "", "", "", "", "BINARY",
|
||||
(char *) 0);
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
r->hsoname = gl->selector;
|
||||
gl->selector = NULL;
|
||||
atput(r, "OBJECT-INTERPRETATION", "SOUND", (char *) 0);
|
||||
break;
|
||||
case 'i': /* the uncommon i type exists in the University
|
||||
of Iowa gopher variant, Panda. */
|
||||
r->name = gl->name;
|
||||
gl->name = NULL;
|
||||
r->target = stcopyr("NULL", r->target);
|
||||
r->hosttype = stcopyr("NULL", r->hosttype);
|
||||
r->host = stcopyr("NULL", r->host);
|
||||
r->hsonametype = stcopyr("NULL", r->hsonametype);
|
||||
r->hsoname = stcopyr("NULL", r->hsoname);
|
||||
r->target = stcopyr("NULL", r->target);
|
||||
atput(r, "OBJECT-INTERPRETATION", "VOID", (char *) 0);
|
||||
break;
|
||||
case ';': /* Gopher+ MOVIE type. It is not at all clear
|
||||
whether this is being used yet.*/
|
||||
r->target = stcopyr("EXTERNAL", r->target);
|
||||
ftp_check_am(gl, r, "BINARY");
|
||||
atput(r, "ACCESS-METHOD", "GOPHER", "", "", "", "", "BINARY",
|
||||
(char *) 0);
|
||||
r->host = qsprintf_stcopyr(r->host, "%s(%d)", gl->host, gl->port);
|
||||
r->hsoname = gl->selector;
|
||||
gl->selector = NULL;
|
||||
atput(r, "OBJECT-INTERPRETATION", "VIDEO", (char *) 0);
|
||||
break;
|
||||
case '.': /* End of directory. */
|
||||
goto ignore;
|
||||
break; /* go on */
|
||||
case '2': /* CSO nameserver; No gateway (yet) */
|
||||
p_warn_string = qsprintf_stcopyr(p_warn_string,
|
||||
"Encountered gopher link to CSO nameserver; we don't support \
|
||||
this type yet: %s", gl->protocol_mesg);
|
||||
pwarn = PWARNING;
|
||||
goto ignore;
|
||||
break;
|
||||
case '3': /* Mitra thinks the error type should be
|
||||
ignored. I am willing to go along with
|
||||
this, given that the standard UNIX Gopher
|
||||
client ignores it. */
|
||||
goto ignore;
|
||||
break;
|
||||
case 'w': /* whois server */
|
||||
p_warn_string = qsprintf_stcopyr(p_warn_string,
|
||||
"Encountered gopher link to WHOIS server; we don't support \
|
||||
this type yet: %s", gl->protocol_mesg);
|
||||
case '-': /* error message type? */
|
||||
default: /* unknown type or type we can't process */
|
||||
p_warn_string = qsprintf_stcopyr(p_warn_string,
|
||||
"Encountered unrecognized Gopher message: %s",
|
||||
gl->protocol_mesg);
|
||||
pwarn = PWARNING;
|
||||
ignore:
|
||||
vlfree(r);
|
||||
r = NULL;
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/* Check if we're an AFTP link. If so, add an AFTP access method. */
|
||||
/* This check should be made before other access methods are added.
|
||||
The server is expected to return access methods in what it believes the
|
||||
preferred order is. We prefer direct AFTP connections to overloading the
|
||||
intermediary Gopher gateways. */
|
||||
/* Gopher AFTP links to files use the HSONAME format:
|
||||
ftp:<aftp-hostname>@/file-path (no trailing slash) */
|
||||
static void
|
||||
ftp_check_am(GLINK gl, VLINK r, char *textorbin)
|
||||
{
|
||||
static char *ftp_hostname = NULL;
|
||||
char *ftp_rest; /* rest of string */
|
||||
if (qsscanf(gl->selector, "ftp:%&[^@]@%r", &ftp_hostname, &ftp_rest) == 2) {
|
||||
int len = strlen(ftp_rest);
|
||||
if (ftp_rest[len - 1] != '/')
|
||||
atput(r, "ACCESS-METHOD", "AFTP", "", ftp_hostname, "", ftp_rest,
|
||||
textorbin, (char *) 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we're an AFTP link. If so, rewrite the HOST and HSONAME to go
|
||||
through the Prospero server at ARCHIE_SERVER (this can be changed). */
|
||||
/* Gopher AFTP links to directories use the HSONAME format:
|
||||
ftp:<aftp-hostname>@/directory.../ */
|
||||
static void
|
||||
ftp_check_dir(GLINK gl, VLINK r)
|
||||
{
|
||||
static char *ftp_hostname = NULL;
|
||||
int len;
|
||||
char *ftp_rest; /* rest of string */
|
||||
if (qsscanf(gl->selector, "ftp:%&[^@]@%r", &ftp_hostname, &ftp_rest) == 2
|
||||
#if 0
|
||||
/* Commented out, doesnt need to be / after @ if gatewaying thru gopher*/
|
||||
&& *ftp_rest == '/'
|
||||
#endif
|
||||
) {
|
||||
len = strlen(ftp_rest);
|
||||
if (ftp_rest[len - 1] == '/') {
|
||||
#if 0 /* commented out because of problem:not all
|
||||
archie servers index all AFTP sites. */
|
||||
#ifdef ARCHIE_SERVER
|
||||
ftp_rest[len - 1] = '\0';
|
||||
r->host = stcopyr(ARCHIE_SERVER, r->host);
|
||||
r->hsoname = qsprintf_stcopyr(r->hsoname, "ARCHIE/HOST/%s%s",
|
||||
ftp_hostname, ftp_rest);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef GOPHER_GW_NEARBY_GOPHER_SERVER
|
||||
r->hsoname = qsprintf_stcopyr(r->hsoname,
|
||||
"GOPHER-GW/%s/1/ftp:%s@%s", GOPHER_GW_NEARBY_GOPHER_SERVER,
|
||||
ftp_hostname, ftp_rest);
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PSRV_WAIS_GW
|
||||
static int
|
||||
wais_check_dir(GLINK gl, VLINK r)
|
||||
{
|
||||
char *w_db = NULL; /* Pointer into gl->selector e.g. zzz */
|
||||
char *w_path = NULL; /* Pointer into gl->selector e.g. xxx/yyy/zzz */
|
||||
AUTOSTAT_CHARPP(w_db_srcp); /* e.g. zzz.src */
|
||||
char *cp = NULL; /* temporary pointer */
|
||||
WAISSOURCE thissource; /* Points to source structure */
|
||||
if (qsscanf(gl->selector, "waissrc:%r", &w_path) != 1) {
|
||||
return FALSE;
|
||||
}
|
||||
if ((w_db = strrchr(w_path, '/')) == NULL) {
|
||||
w_db = w_path;
|
||||
} else {
|
||||
w_db++;
|
||||
}
|
||||
|
||||
if ((cp = strstr(w_db, ".src")) == NULL) {
|
||||
*w_db_srcp = qsprintf_stcopyr(*w_db_srcp, "%s%s", w_db, ".src");
|
||||
} else {
|
||||
*w_db_srcp = stcopyr(w_db, *w_db_srcp); /* *w_db_srcp = zzz.src */
|
||||
}
|
||||
/*!! Open and parse local src file */
|
||||
/* While this may s_alloc the source DONT free it, its on
|
||||
a linked list of sources which persists while the server is up*/
|
||||
if ((thissource = findsource(*w_db_srcp, WAIS_SOURCE_DIR)) == NULL)
|
||||
return FALSE;
|
||||
|
||||
if ((cp = strstr(w_db, ".src")) != NULL) {
|
||||
/* Need to do this AFTER findsource, otherwise can modify gl->selector
|
||||
of non matching source */
|
||||
cp[0] = '\0'; /* w_db = zzz */
|
||||
}
|
||||
r->hsoname = qsprintf_stcopyr(r->hsoname, "WAIS-GW/%s(%s)/QUERY/%s",
|
||||
thissource->server, thissource->service, w_db);
|
||||
if (thissource->subjects)
|
||||
atput(r, "WAIS-SUBJECTS", thissource->subjects, (char *) 0);
|
||||
if (thissource->cost)
|
||||
atput(r, "WAIS-COST-NUM", thissource->cost, (char *) 0);
|
||||
if (thissource->units)
|
||||
atput(r, "WAIS-COST-UNIT", thissource->units, (char *) 0);
|
||||
if (thissource->maintainer)
|
||||
atput(r, "WAIS-COST-MAINTAINER", thissource->maintainer, (char *) 0);
|
||||
atput(r, "QUERY-METHOD", "wais-query(search-words)",
|
||||
"${search-words}", "", (char *) 0);
|
||||
atput(r, "QUERY-ARGUMENT", "search-words",
|
||||
"Index word(s) to search for", "mandatory char*", "%s", "",
|
||||
(char *) 0);
|
||||
if (thissource->description)
|
||||
atput(r, "QUERY-DOCUMENTATION", "wais-query()",
|
||||
thissource->description, (char *) 0);
|
||||
atput(r, "QUERY-DOCUMENTATION", "search-words", "This string says \
|
||||
what you're searching for or what information you're specifying.",
|
||||
"Type any string. Sometimes SPACEs are treated as implied \
|
||||
'and' operators. Sometimes the words 'and', 'or', and 'not' are recognized \
|
||||
as boolean operators.", (char *) 0);
|
||||
return (TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
zap_trailing_spaces(char *host)
|
||||
{
|
||||
int len = strlen(host);
|
||||
while (--len >= 0) {
|
||||
if (host[len] == ' ')
|
||||
host[len] = '\0';
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a collation-order attribute of the form NUMERIC <linknum> to the link
|
||||
VL */
|
||||
static void
|
||||
add_collation_order(int linknum, VLINK vl)
|
||||
{
|
||||
PATTRIB ca = atalloc();
|
||||
char buf[40]; /* long enough to hold the ASCII
|
||||
representation of any int for the
|
||||
foreseeable future. */
|
||||
ca->precedence = ATR_PREC_LINK;
|
||||
ca->nature = ATR_NATURE_APPLICATION;
|
||||
ca->avtype = ATR_SEQUENCE;
|
||||
ca->aname = stcopy("COLLATION-ORDER");
|
||||
ca->value.sequence = tkappend("NUMERIC", ca->value.sequence);
|
||||
assert(qsprintf(buf, sizeof buf, "%d", linknum) <= sizeof buf);
|
||||
ca->value.sequence = tkappend(buf, ca->value.sequence);
|
||||
APPEND_ITEM(ca, vl->lattrib);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
atput(VLINK vl, char *name,...)
|
||||
{
|
||||
va_list ap;
|
||||
char *s;
|
||||
PATTRIB at = atalloc();
|
||||
|
||||
va_start(ap, name);
|
||||
at->aname = stcopy(name);
|
||||
at->avtype = ATR_SEQUENCE;
|
||||
if (strequal(name, "ACCESS-METHOD"))
|
||||
at->nature = ATR_NATURE_FIELD;
|
||||
else
|
||||
at->nature = ATR_NATURE_APPLICATION;
|
||||
if (strequal(vl->target, "EXTERNAL"))
|
||||
at->precedence = ATR_PREC_REPLACE; /* still not clear what to use */
|
||||
else
|
||||
at->precedence = ATR_PREC_OBJECT;
|
||||
while (s = va_arg(ap, char *)) {
|
||||
at->value.sequence =
|
||||
tkappend(s, at->value.sequence);
|
||||
}
|
||||
APPEND_ITEM(at, vl->lattrib);
|
||||
va_end(ap);
|
||||
}
|
||||
39
prospero/lib/psrv/gopher_gw/goph_gw_mutex.c
Normal file
39
prospero/lib/psrv/gopher_gw/goph_gw_mutex.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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 "gopher.h"
|
||||
#include <pfs.h>
|
||||
#include <pfs_threads.h>
|
||||
|
||||
/* This file is used by lib/psrv. So libpgoph_gw.a should follow psrv. */
|
||||
|
||||
|
||||
#ifdef PFS_THREADS
|
||||
p_th_mutex p_th_mutexGLINK; /* declaration */
|
||||
#endif
|
||||
|
||||
void
|
||||
gopher_gw_init_mutexes(void)
|
||||
{
|
||||
#ifdef PFS_THREADS
|
||||
p_th_mutex_init(p_th_mutexGLINK);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void
|
||||
gopher_gw_diagnose_mutexes(void)
|
||||
{
|
||||
printf("{gopher_gw_init_mutexes ");
|
||||
#ifdef PFS_THREADS
|
||||
DIAGMUTEX(GLINK,"GLINK");
|
||||
#endif
|
||||
printf("}");
|
||||
}
|
||||
#endif /*NDEBUG*/
|
||||
|
||||
34
prospero/lib/psrv/gopher_gw/gopher.h
Normal file
34
prospero/lib/psrv/gopher_gw/gopher.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 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_threads.h>
|
||||
|
||||
struct glink {
|
||||
#ifdef ALLOCATOR_CONSISTENCY_CHECK
|
||||
int consistency;
|
||||
#endif
|
||||
char type;
|
||||
char *name;
|
||||
char *selector;
|
||||
char *host;
|
||||
int port;
|
||||
char *protocol_mesg; /* raw item description -- the Gopher
|
||||
protocol message. */
|
||||
struct glink *previous;
|
||||
struct glink *next;
|
||||
};
|
||||
typedef struct glink *GLINK;
|
||||
typedef struct glink GLINK_ST;
|
||||
|
||||
extern GLINK glalloc(void);
|
||||
extern void glfree(GLINK);
|
||||
extern void gllfree(GLINK);
|
||||
#ifdef PFS_THREADS
|
||||
extern p_th_mutex p_th_mutexGLINK; /* declared in goph_gw_mutex.c */
|
||||
#endif
|
||||
39
prospero/lib/psrv/magic.c
Normal file
39
prospero/lib/psrv/magic.c
Normal 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 <pfs.h> /* assert, internal_error, prototypes */
|
||||
|
||||
/* Generate a unique magic number (positive long). This is based upon hashing
|
||||
the vlink VL's HSONAME field. */
|
||||
long
|
||||
generate_magic(VLINK vl)
|
||||
{
|
||||
long retval = 0L;
|
||||
int n = p_bstlen(vl->hsoname);
|
||||
int rvoffset = 0; /* offset for xoring with the return value. */
|
||||
while(n--) {
|
||||
rvoffset += 8;
|
||||
if (rvoffset >= 8 * sizeof retval) rvoffset = 0;
|
||||
retval ^= ((vl->hsoname[n]) << rvoffset);
|
||||
}
|
||||
if (retval < 0) return ~retval;
|
||||
if (retval == 0) return 1;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Is the magic number MAGIC anywhere in use in the list of vlinks LINKS? */
|
||||
int
|
||||
magic_no_in_list(long magic, VLINK links)
|
||||
{
|
||||
for ( ;links ; links = links->next) {
|
||||
if (links->f_magic_no == magic) return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
111
prospero/lib/psrv/named_acl.c
Normal file
111
prospero/lib/psrv/named_acl.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file <usc-copyr.h>
|
||||
*/
|
||||
|
||||
#include <usc-copyr.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <pfs.h>
|
||||
#include <perrno.h>
|
||||
#include <psrv.h>
|
||||
#include <plog.h>
|
||||
|
||||
extern char security[]; /* full pathname of security directory. */
|
||||
|
||||
#define NAMED_ACL_SECURITY_SUBDIR "named" /* subdirectory of security for named
|
||||
ACLs. */
|
||||
/* Get a named ACL with a name from the database, or write it. */
|
||||
|
||||
/* Returns: DIRSRV_NOT_FOUND, PFAILURE, or PSUCCESS */
|
||||
|
||||
static void set_cached_named_acl(char *aclname, ACL wacl);
|
||||
static int get_cached_named_acl(char *aclname, ACL *waclp);
|
||||
|
||||
extern int
|
||||
get_named_acl(char *t_name, ACL *waclp)
|
||||
{
|
||||
AUTOSTAT_CHARPP(filenamep);
|
||||
INPUT_ST in_st;
|
||||
INPUT in = &in_st;
|
||||
int tmp;
|
||||
FILE *fp;
|
||||
|
||||
if(get_cached_named_acl(t_name, waclp) == PSUCCESS)
|
||||
return PSUCCESS;
|
||||
*waclp = NULL; /* start off empty */
|
||||
*filenamep = qsprintf_stcopyr(*filenamep, "%s/%s/%s", security,
|
||||
NAMED_ACL_SECURITY_SUBDIR, t_name);
|
||||
fp = locked_fopen(*filenamep, "r");
|
||||
if (!fp) return DIRSRV_NOT_FOUND;
|
||||
if (wholefiletoin(fp, in)) {
|
||||
plog(L_DIR_ERR,NOREQ,"%s",p_err_string);
|
||||
locked_fclose_A(fp,*filenamep,TRUE);
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
tmp = in_acl(in, waclp);
|
||||
if(tmp)
|
||||
plog(L_DATA_FRM_ERR, NOREQ, "Bad NAMED ACL info format %s: %s",
|
||||
*filenamep, p_err_string);
|
||||
if (locked_fclose_A(fp,*filenamep, TRUE) && !tmp) {
|
||||
plog(L_DATA_FRM_ERR, NOREQ, "Error closing NAMED ACL file %s",
|
||||
*filenamep);
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
if (tmp) RETURNPFAILURE;
|
||||
return PSUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Returns: PFAILURE, or PSUCCESS */
|
||||
extern int
|
||||
set_named_acl(char *t_name, ACL wacl)
|
||||
{
|
||||
AUTOSTAT_CHARPP(filenamep);
|
||||
AUTOSTAT_CHARPP(tmpfilenamep);
|
||||
FILE *fp;
|
||||
OUTPUT_ST out_st;
|
||||
OUTPUT out = &out_st;
|
||||
|
||||
set_cached_named_acl(t_name, wacl);
|
||||
*filenamep = qsprintf_stcopyr(*filenamep, "%s/%s/%s", security,
|
||||
NAMED_ACL_SECURITY_SUBDIR, t_name);
|
||||
*tmpfilenamep = qsprintf_stcopyr(*tmpfilenamep, "%s.TMP", *filenamep);
|
||||
filelock_obtain(*filenamep,FALSE); /* Obtain write lock on rel dir */
|
||||
fp = locked_fopen(*tmpfilenamep, "w");
|
||||
if (!fp) {
|
||||
char *sp;
|
||||
/* couldn't open file for writing. Maybe a subdirectory needs to be
|
||||
created? This could happen if there's a slash in the named acl or
|
||||
if the security directory wasn't created yet. */
|
||||
sp = strrchr(*tmpfilenamep, '/');
|
||||
if (sp) {
|
||||
*sp = '\0';
|
||||
mkdirs(*tmpfilenamep);
|
||||
*sp = '/';
|
||||
fp = locked_fopen(*tmpfilenamep, "w");
|
||||
}
|
||||
if (!fp) {
|
||||
filelock_release(*filenamep,FALSE);
|
||||
return(PFAILURE);
|
||||
}
|
||||
}
|
||||
filetoout(fp, out);
|
||||
out_acl(out, wacl);
|
||||
return(locked_fclose_and_rename(fp, *tmpfilenamep,*filenamep,FALSE));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_cached_named_acl(char *aclname, ACL wacl)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
get_cached_named_acl(char *aclname, ACL *waclp)
|
||||
{
|
||||
RETURNPFAILURE; /* does nothing for now. */
|
||||
}
|
||||
133
prospero/lib/psrv/optparse.c
Normal file
133
prospero/lib/psrv/optparse.c
Normal file
@@ -0,0 +1,133 @@
|
||||
/* optparse.c */
|
||||
/*
|
||||
* Copyright (c) 1992 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file <usc-copyr.h>
|
||||
*/
|
||||
/* Ground out by swa@isi.edu */
|
||||
#include <usc-copyr.h>
|
||||
|
||||
#include <pfs.h>
|
||||
#include <pparse.h>
|
||||
#include <psrv.h>
|
||||
#include <perrno.h>
|
||||
#include <stdlib.h> /* For malloc and free */
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static OPT free = NULL;
|
||||
#endif
|
||||
int opt_count = 0;
|
||||
int opt_max = 0;
|
||||
|
||||
#if 0 /* XXX Options parsing isn't great; but it
|
||||
turns out that we don't need to get fancy
|
||||
yet. What we have will suffice.*/
|
||||
|
||||
/* Initialize option parsing. Feed it an unquoted string containing a
|
||||
|
||||
+ or , -separated list of options. It assumes that it may freely overwrite
|
||||
the string, and make memory references to it. */
|
||||
|
||||
OPT
|
||||
#ifdef __STDC__
|
||||
optparse(char *optionstr)
|
||||
#else
|
||||
optparse(optionstr)
|
||||
char *optionstr;
|
||||
#endif
|
||||
{
|
||||
extern int perrno;
|
||||
perrno = PSUCCESS;
|
||||
OPT retval = NULL;
|
||||
|
||||
while(*optionstr) {
|
||||
OPT nopt = optalloc();
|
||||
char buf[MAX_DIR_LINESIZE];
|
||||
char *bufp;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static struct opt *
|
||||
optalloc(char * name)
|
||||
{
|
||||
OPT retval;
|
||||
|
||||
if (free) {
|
||||
retval = free;
|
||||
free = free->next;
|
||||
} else {
|
||||
retval = malloc(sizeof (OPT_ST));
|
||||
if (!retval) return NULL;
|
||||
++opt_max;
|
||||
}
|
||||
++opt_count;
|
||||
|
||||
retval->name= name;
|
||||
retval->used = 0;
|
||||
retval->args = NULL;
|
||||
retval->argstring = NULL;
|
||||
retval->next = NULL;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static
|
||||
#ifdef __STDC__
|
||||
optfree(OPT opt)
|
||||
#else
|
||||
optfree(opt)
|
||||
OPT opt;
|
||||
#endif
|
||||
{
|
||||
optlfree(opt->args);
|
||||
free(opt);
|
||||
}
|
||||
|
||||
void
|
||||
#ifdef __STDC__
|
||||
optlfree(OPT opts)
|
||||
#else
|
||||
optlfree(opts)
|
||||
OPT opts;
|
||||
#endif
|
||||
{
|
||||
while (opts) {
|
||||
nextop = opts->next;
|
||||
optfree(opts);
|
||||
opts = nextop;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
optquery(opts, optname)
|
||||
OPT opts;
|
||||
char optname[];
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* # of arguments to the option. 0 if none specified. */
|
||||
int
|
||||
optnargs(opts, optname)
|
||||
OPT opts;
|
||||
char optname[];
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* Any options which haven't been queried yet. Check for leftovers!
|
||||
This needs to be freed.
|
||||
*/
|
||||
OPT
|
||||
optremaining()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
350
prospero/lib/psrv/plog.c
Normal file
350
prospero/lib/psrv/plog.c
Normal file
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Copyright (c) 1991-1994 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>.
|
||||
*
|
||||
* Credits: Originally written by Clifford Neuman (University of Washington)
|
||||
* Syslog support added by Jonathan Kamens (MIT Project Athena)
|
||||
* Much code mangling by Steven Augart (USC/ISI)
|
||||
*/
|
||||
|
||||
#include <usc-license.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <ardp.h>
|
||||
#include <pfs.h>
|
||||
#include <pserver.h>
|
||||
#include <plog.h>
|
||||
#include <pmachine.h>
|
||||
/* This definition has to be after pmachine.h so that SCOUNIX gets defined */
|
||||
#if defined(AIX) || defined (SCOUNIX)
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#define logfile P_logfile /* So as not to conflict with WAIS variable --- bajan */
|
||||
|
||||
/* this array contains info on the type of entries to be printed */
|
||||
static int logtype_array[NLOGTYPE+1] = INITIAL_LOG_VECTOR;
|
||||
|
||||
/* info on the filename and open file */
|
||||
static char *log_name = PSRV_LOGFILE;
|
||||
FILE *logfile;
|
||||
static int is_open = 0; /* Mutexed below */
|
||||
#if 0
|
||||
/* not currently used */
|
||||
static int syslog_open = 0;
|
||||
#endif
|
||||
|
||||
static char *pr_inet_ntoa();
|
||||
static FILE *plog_additional_outfile = NULL;
|
||||
|
||||
/*VARARGS4*/
|
||||
|
||||
/*
|
||||
* plog - Add entry to logfile
|
||||
*
|
||||
* PLOG is used to add entries to the logfile. Note that
|
||||
* it is probably not portable since is makes assumptions
|
||||
* about what the compiler will do when it is called with
|
||||
* less than the correct number of arguments which is the
|
||||
* way it is usually called.
|
||||
*
|
||||
* PLOG returns a pointer to the logged entry. If an error
|
||||
* occurs, vlog returns immediately, but does not indicate
|
||||
* that the log operating failed.
|
||||
*
|
||||
* ARGS: type - Type of entry (to decide if we should log it)
|
||||
* req - Pointer to request info including host address,
|
||||
* and useride. (NULL if should not be printed)
|
||||
* format - Format as for qsprintf
|
||||
* remaining arguments -- as for qsprintf
|
||||
* RETURNS: Pointer to a string containing the log entry
|
||||
*
|
||||
* BUGS: The non-ANSI implementation is not portable. It should really use
|
||||
* another mechanism to support a variable number of arguments.
|
||||
* Unfortunately, these mechanisms are not easily available.
|
||||
*
|
||||
* Currently, the log file is opened and closed on each
|
||||
* call.
|
||||
*/
|
||||
|
||||
EXTERN_MUTEX_DECL(PSRV_LOG);
|
||||
|
||||
/* Call this if mutexed, but not open */
|
||||
|
||||
#define LEAVEOPEN 1
|
||||
|
||||
char *
|
||||
vplog(int type, RREQ req, char *format, va_list ap)
|
||||
{
|
||||
time_t now, systime, svctime, wttime;
|
||||
int log_username = 0;
|
||||
int notfirstfield = 0;
|
||||
char *month_sname();
|
||||
char usertxt[MXPLOGENTRY];
|
||||
char fieldtxt[MXPLOGENTRY];
|
||||
|
||||
AUTOSTAT_CHARPP(logtxtp);
|
||||
|
||||
CHECK_MEM();
|
||||
|
||||
*logtxtp = vqsprintf_stcopyr(*logtxtp, format, ap);
|
||||
|
||||
/* If we don't log this type of message, don't write to log */
|
||||
if (!logtype_array[type])
|
||||
return(*logtxtp);
|
||||
|
||||
/* get the time */
|
||||
#ifndef NDEBUG
|
||||
{ int retval =
|
||||
#endif
|
||||
time(&now);
|
||||
#ifndef NDEBUG
|
||||
assert(retval != -1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
svctime = systime = wttime = 0;
|
||||
if(req) {
|
||||
if(req->rcvd_time.tv_sec)
|
||||
wttime = systime = now - req->rcvd_time.tv_sec;
|
||||
|
||||
if(req->svc_start_time.tv_sec) {
|
||||
svctime = now - req->svc_start_time.tv_sec;
|
||||
wttime = req->svc_start_time.tv_sec - req->rcvd_time.tv_sec;
|
||||
}
|
||||
}
|
||||
|
||||
if ((type == L_QUEUE_COMP) && (systime < L_COMP_SYS_THRESHOLD))
|
||||
return(*logtxtp);
|
||||
|
||||
if ((type == L_QUEUE_COMP) && (svctime < L_COMP_SVC_THRESHOLD))
|
||||
return(*logtxtp);
|
||||
|
||||
*usertxt = '\0';
|
||||
|
||||
if(req && req->peer_addr.s_addr &&(logtype_array[L_FIELDS]&L_FIELDS_HADDR))
|
||||
strncat(usertxt, pr_inet_ntoa(req->peer_addr.s_addr),sizeof(usertxt));
|
||||
|
||||
if(type == L_DIR_UPDATE) {
|
||||
if(logtype_array[L_FIELDS] & L_FIELDS_USER_U) log_username++;
|
||||
}
|
||||
else if(type == L_DIR_REQUEST) {
|
||||
if(logtype_array[L_FIELDS] & L_FIELDS_USER_R) log_username++;
|
||||
}
|
||||
else if(logtype_array[L_FIELDS] & L_FIELDS_USER_I) log_username++;
|
||||
|
||||
if(req && req->client_name && *(req->client_name) && log_username) {
|
||||
strncat(usertxt, "(",sizeof(usertxt));
|
||||
strncat(usertxt, req->client_name,sizeof(usertxt));
|
||||
strncat(usertxt, ")",sizeof(usertxt));
|
||||
}
|
||||
|
||||
if(req && req->peer_sw_id && *(req->peer_sw_id) &&
|
||||
(logtype_array[L_FIELDS] & L_FIELDS_SW_ID)) {
|
||||
strncat(usertxt, "[",sizeof(usertxt));
|
||||
strncat(usertxt, req->peer_sw_id,sizeof(usertxt));
|
||||
strncat(usertxt, "]",sizeof(usertxt));
|
||||
}
|
||||
|
||||
if(req && (logtype_array[L_FIELDS] & L_FIELDS_PORT)){
|
||||
qsprintf(fieldtxt, sizeof fieldtxt, "[udp/%d]", PEER_PORT(req));
|
||||
strncat(usertxt, fieldtxt,sizeof(usertxt));
|
||||
}
|
||||
|
||||
if(req && req->cid &&(logtype_array[L_FIELDS] & L_FIELDS_CID)) {
|
||||
qsprintf(fieldtxt, sizeof fieldtxt, "[cid=%d]", ntohs(req->cid));
|
||||
strncat(usertxt, fieldtxt,sizeof(usertxt));
|
||||
}
|
||||
|
||||
if(req && (logtype_array[L_FIELDS] & L_FIELDS_STIME) &&
|
||||
((systime>=L_SYSTIME_THRESHOLD) || (svctime>=L_SVCTIME_THRESHOLD) ||
|
||||
(wttime>=L_WTTIME_THRESHOLD))) {
|
||||
strncat(usertxt, "[",sizeof(usertxt));
|
||||
if(wttime >= L_WTTIME_THRESHOLD) {
|
||||
if(notfirstfield++) strncat(usertxt, ",",sizeof(usertxt));
|
||||
qsprintf(fieldtxt, sizeof fieldtxt, "%d:%02dwt", wttime / 60, wttime % 60);
|
||||
strncat(usertxt, fieldtxt,sizeof(usertxt));
|
||||
}
|
||||
if(svctime >= L_SVCTIME_THRESHOLD) {
|
||||
if(notfirstfield++) strncat(usertxt, ",",sizeof(usertxt));
|
||||
qsprintf(fieldtxt, sizeof fieldtxt,
|
||||
"%d:%02dsvc", svctime / 60, svctime % 60);
|
||||
strncat(usertxt, fieldtxt,sizeof(usertxt));
|
||||
}
|
||||
if(systime >= L_SYSTIME_THRESHOLD) {
|
||||
if(notfirstfield++) strncat(usertxt, ",",sizeof(usertxt));
|
||||
qsprintf(fieldtxt, sizeof fieldtxt, "%d:%02dsys", systime / 60, systime % 60);
|
||||
strncat(usertxt, fieldtxt,sizeof(usertxt));
|
||||
}
|
||||
strncat(usertxt, "]",sizeof(usertxt));
|
||||
}
|
||||
|
||||
#ifdef P_LOGTO_SYSLOG
|
||||
if(!syslog_open++) openlog("prospero",LOG_PID|LOG_ODELAY,LOG_PROSPERO);
|
||||
|
||||
if (logtype_array[type] & ~PLOG_TOFILE_ENABLED) {
|
||||
syslog(logtype_array[type] & ~PLOG_TOFILE_ENABLED,
|
||||
"%s%s%s", usertxt, (*usertxt ? " " : ""), *logtxtp);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If not printing to file return */
|
||||
if (! (logtype_array[type] & PLOG_TOFILE_ENABLED)) return(*logtxtp);
|
||||
|
||||
#ifndef LEAVEOPEN
|
||||
p_th_mutex_lock(p_th_mutexPSRV_LOG);
|
||||
#endif
|
||||
if (!is_open) {
|
||||
#ifdef LEAVEOPEN
|
||||
p_th_mutex_lock(p_th_mutexPSRV_LOG);
|
||||
#endif
|
||||
if (!is_open) { /* Check still open, now we have mutex*/
|
||||
if ((logfile = fopen(log_name,"a")) != NULL) {
|
||||
is_open = 1;
|
||||
}
|
||||
}
|
||||
#ifdef LEAVEOPEN
|
||||
p_th_mutex_unlock(p_th_mutexPSRV_LOG);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (is_open) {
|
||||
|
||||
/* print the log entry */
|
||||
AUTOSTAT_CHARPP(bufp);
|
||||
#ifndef PFS_THREADS
|
||||
struct tm *tm = localtime(&now);
|
||||
#else
|
||||
struct tm tmstruc;
|
||||
struct tm *tm = &tmstruc;
|
||||
localtime_r(&now, tm);
|
||||
#endif
|
||||
*bufp = qsprintf_stcopyr(*bufp, "%2d-%s-%02d %02d:%02d:%02d %s%s%s\n",
|
||||
tm->tm_mday,
|
||||
month_sname(tm->tm_mon + 1),tm->tm_year,
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec,
|
||||
usertxt, (*usertxt ? " - " : ""), *logtxtp);
|
||||
#ifndef NDEBUG
|
||||
{ /* variable scope start */
|
||||
int retval =
|
||||
#endif
|
||||
fputs(*bufp, logfile);
|
||||
#ifndef NDEBUG
|
||||
assert(retval == strlen(*bufp));
|
||||
} /* variable scope end */
|
||||
#endif
|
||||
}
|
||||
/* even if the primary logfile couldn't be opened, go ahead and log to
|
||||
the manual (additional) logfile. */
|
||||
if(plog_additional_outfile) {
|
||||
#if 0
|
||||
/* This is old equivalent code. Leaving it in here just for historical
|
||||
reasons -- no real reason to keep it, unless one is concerned about
|
||||
runnuing out of memory. */
|
||||
fprintf(plog_additional_outfile,
|
||||
"%s%s%s\n", usertxt, (*usertxt ? " - " : ""), *logtxtp));
|
||||
#else
|
||||
AUTOSTAT_CHARPP(bufp);
|
||||
*bufp = qsprintf_stcopyr(*bufp, "%s%s%s\n",
|
||||
usertxt, (*usertxt ? " - " : ""), *logtxtp);
|
||||
#ifndef NDEBUG
|
||||
{ int retval =
|
||||
#endif
|
||||
fputs(*bufp, plog_additional_outfile);
|
||||
#ifndef NDEBUG
|
||||
assert(retval == strlen(*bufp));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
zz(fflush(plog_additional_outfile)); /* must be zero */
|
||||
}
|
||||
|
||||
#ifndef LEAVEOPEN
|
||||
if (is_open) {
|
||||
zz(fclose(logfile));
|
||||
is_open = 0;
|
||||
}
|
||||
p_th_mutex_unlock(p_th_mutexPSRV_LOG);
|
||||
#else
|
||||
zz(fflush(logfile));
|
||||
#endif /*LEAVEOPEN*/
|
||||
return(*logtxtp);
|
||||
|
||||
}
|
||||
|
||||
char *
|
||||
plog(int type, /* Type of log entry */
|
||||
RREQ req, /* Optional info on request */
|
||||
char *format, ...) /* format string */
|
||||
{
|
||||
char *retval;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
retval = vplog(type, req, format, ap);
|
||||
va_end(ap);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* set_logfile - Change the name of the logfile
|
||||
*
|
||||
* SET_LOGFILE changes the name of the file to which
|
||||
* messages are logged. If set_logfile is not called,
|
||||
* the logfile defaults to PFSLOG.
|
||||
*
|
||||
* ARGS: filename - Name of new logfile
|
||||
* Returns: success always
|
||||
*/
|
||||
/* Does not need to be mutexed; set only upon initialization */
|
||||
int
|
||||
set_logfile(char *filename)
|
||||
{
|
||||
assert(P_IS_THIS_THREAD_MASTER());
|
||||
log_name = filename;
|
||||
if(is_open) (void) fclose(logfile);
|
||||
is_open = 0;
|
||||
return(PSUCCESS);
|
||||
}
|
||||
|
||||
static char *
|
||||
pr_inet_ntoa(long a)
|
||||
{
|
||||
AUTOSTAT_CHARPP(astringp);
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
*astringp = qsprintf_stcopyr(*astringp,"%d.%d.%d.%d",(a >> 24) & 0xff,
|
||||
(a >> 16) & 0xff,(a >> 8) & 0xff, a & 0xff);
|
||||
#else
|
||||
*astringp = qsprintf_stcopyr(*astringp,"%d.%d.%d.%d", a & 0xff,
|
||||
(a >> 8) & 0xff,(a >> 16) & 0xff,
|
||||
(a >> 24) & 0xff);
|
||||
#endif
|
||||
return(*astringp);
|
||||
}
|
||||
|
||||
void
|
||||
close_plog(void)
|
||||
{
|
||||
if(is_open) fclose(logfile);
|
||||
is_open = 0;
|
||||
|
||||
#ifdef P_LOGTO_SYSLOG
|
||||
if(syslog_open) closelog();
|
||||
syslog_open = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
plog_manual(FILE *outf)
|
||||
{
|
||||
plog_additional_outfile = outf;
|
||||
}
|
||||
261
prospero/lib/psrv/ppasswd.c
Normal file
261
prospero/lib/psrv/ppasswd.c
Normal file
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* 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> /* for SOLARIS */
|
||||
#ifdef CRYPT_FUNCTION_PROTOTYPE_IN_CRYPT_H /* defined currently only
|
||||
when SOLARIS is active. */
|
||||
#include <crypt.h> /* Solaris: for the crypt() function. */
|
||||
/* Note that the crypt() function is not part of the 1989 ANSI C standard,
|
||||
nor in the 1990 POSIX 1 standard.
|
||||
Therefore, different vendors will treat it differently. */
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <pfs.h>
|
||||
#include <pserver.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef PSRV_P_PASSWORD
|
||||
|
||||
#include <ppasswd.h>
|
||||
#include <perrno.h>
|
||||
|
||||
static int write_ppw_to_file();
|
||||
static char *get_salt(void);
|
||||
|
||||
extern int pfs_debug;
|
||||
|
||||
|
||||
/* Get password file entry for principal. Returns pointer to p_passwd */
|
||||
/* structure if found, else returns NULL. */
|
||||
p_passwd *
|
||||
get_ppw_entry(char *principal)
|
||||
{
|
||||
FILE *passwd_fp;
|
||||
char line[255];
|
||||
char princ_name[255], encrypted_passwd[255];
|
||||
p_passwd *p_pwd = NULL;
|
||||
|
||||
if (!(passwd_fp = locked_fopen(PSRV_PW_FILE, "r")))
|
||||
return NULL;
|
||||
|
||||
while (fgets(line, sizeof(line), passwd_fp)) {
|
||||
sscanf(line, "%s %s\n",
|
||||
princ_name, encrypted_passwd);
|
||||
if (!strcmp(princ_name, principal)) {
|
||||
p_pwd = (p_passwd *) stalloc(sizeof(p_passwd));
|
||||
p_pwd->principal = stcopy(princ_name);
|
||||
p_pwd->encrypted_passwd = stcopy(encrypted_passwd);
|
||||
}
|
||||
}
|
||||
|
||||
(void) locked_fclose_A(passwd_fp,PSRV_PW_FILE, TRUE);
|
||||
return p_pwd;
|
||||
}
|
||||
|
||||
|
||||
/* Write password entry in structure p_pwd to password file, */
|
||||
/* overwriting old entry if one exists for the principal */
|
||||
static int write_ppw_to_file(p_passwd *p_pwd)
|
||||
{
|
||||
FILE *passwd_fp;
|
||||
char in_line[255], out_line[255];
|
||||
char princ_name[255], encrypted_passwd[255];
|
||||
long pos;
|
||||
|
||||
if (!(passwd_fp = locked_fopen(PSRV_PW_FILE, "r+"))) {
|
||||
/* Cannot open password file, so create */
|
||||
if (!(passwd_fp = locked_fopen(PSRV_PW_FILE, "w+"))) {
|
||||
if (pfs_debug)
|
||||
fprintf(stderr, "Cannot create file %s\n",
|
||||
PSRV_PW_FILE);
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
if (chmod(PSRV_PW_FILE, 0600)) {
|
||||
if (pfs_debug)
|
||||
perror("Could not change permissions of passwd file");
|
||||
locked_fclose_A(passwd_fp,PSRV_PW_FILE,FALSE);
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
fprintf(passwd_fp, "# Prospero Server Password File.\n");
|
||||
fprintf(passwd_fp, "%-32s %-32s\n\n",
|
||||
"# <principal>", "<encrypted password>");
|
||||
fseek(passwd_fp, 0L, 1); /* To allow input after output */
|
||||
}
|
||||
|
||||
/* Check if entry exists for principal */
|
||||
while (pos = ftell(passwd_fp), /* Remember position of line */
|
||||
fgets(in_line, sizeof(in_line), passwd_fp)) {
|
||||
if (in_line[0] == '#')
|
||||
continue;
|
||||
sscanf(in_line, "%s %s\n",
|
||||
princ_name, encrypted_passwd);
|
||||
if (!strcmp(princ_name, p_pwd->principal)) {
|
||||
/* Entry found; set file pointer to overwrite */
|
||||
fseek(passwd_fp, pos, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If entry not found, write new entry to end of file, else overwrite */
|
||||
fprintf(passwd_fp, "%-32s %-32s\n",
|
||||
p_pwd->principal, p_pwd->encrypted_passwd);
|
||||
|
||||
(void) locked_fclose_A(passwd_fp,PSRV_PW_FILE,FALSE);
|
||||
return PSUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Set password for principal in password file, overwriting old */
|
||||
/* entry if one exists. */
|
||||
int
|
||||
set_passwd(char *principal, char *passwd)
|
||||
{
|
||||
p_passwd p_pwd;
|
||||
char *salt = get_salt();
|
||||
|
||||
p_pwd.principal = stcopy(principal);
|
||||
p_pwd.encrypted_passwd = (char *) crypt(passwd, salt);
|
||||
if (write_ppw_to_file(&p_pwd))
|
||||
RETURNPFAILURE;
|
||||
stfree(p_pwd.principal);
|
||||
stfree(salt);
|
||||
return PSUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Returns TRUE if password specified for the principal matches */
|
||||
/* password in entry for principal in password file, and FALSE */
|
||||
/* otherwise */
|
||||
int passwd_correct(char * principal, char *passwd)
|
||||
{
|
||||
p_passwd *p_pwd;
|
||||
char *salt, *p;
|
||||
int correct;
|
||||
|
||||
/* Get password file entry */
|
||||
if (!(p_pwd = get_ppw_entry(principal)))
|
||||
return FALSE;
|
||||
|
||||
/* Salt stored as first two characters of encrypted password */
|
||||
salt = p_pwd->encrypted_passwd;
|
||||
|
||||
/* Encrypt supplied password and compare to encrypted password */
|
||||
/* stored in password file */
|
||||
p = (char *) crypt(passwd, salt);
|
||||
correct = strequal(p, p_pwd->encrypted_passwd);
|
||||
|
||||
stfree(p_pwd);
|
||||
return correct;
|
||||
}
|
||||
|
||||
|
||||
/* Constructs and returns a random two-character salt. */
|
||||
/* Salt needed by crypt() is two characters from the set [a-zA-Z0-9./] */
|
||||
static char *get_salt(void)
|
||||
{
|
||||
time_t tim = time(NULL); /* Use current time to achieve */
|
||||
/* randomness between sessions */
|
||||
char *salt;
|
||||
|
||||
salt = stalloc(2);
|
||||
|
||||
salt[0] = 'a' + (tim % 26); /* Letter between 'a' and 'z' */
|
||||
salt[1] = '.' + (tim % 12); /* One of '.', '/', and '0'-'9' */
|
||||
|
||||
return salt;
|
||||
}
|
||||
|
||||
#define RETURN(rv) do { retval = rv; goto cleanup ; }
|
||||
|
||||
/* Deletes principal's password entry from file */
|
||||
int delete_ppw_entry(char *principal)
|
||||
{
|
||||
FILE *passwd_fp = NULL;
|
||||
FILE *tmp_fp = NULL;
|
||||
int retval;
|
||||
char line[255];
|
||||
char princ_name[255], encrypted_passwd[255];
|
||||
char tmp_filename[255];
|
||||
int found = 0;
|
||||
|
||||
assert(P_IS_THIS_THREAD_MASTER());
|
||||
/* XXX !! This is MT-UNSAFE, two writers will totally screw up the
|
||||
pw file, needs mutexing*/
|
||||
|
||||
if (!get_ppw_entry(principal))
|
||||
RETURNPFAILURE;
|
||||
|
||||
if (!(passwd_fp = locked_fopen(PSRV_PW_FILE, "r")))
|
||||
RETURNPFAILURE;
|
||||
qsprintf(tmp_filename, sizeof(tmp_filename), "%s_tmp", PSRV_PW_FILE);
|
||||
if (!(tmp_fp = locked_fopen(tmp_filename, "w"))) {
|
||||
if (pfs_debug) { /* Old code was hosed, only closed if pfs_debug set*/
|
||||
fprintf(stderr, "Could not create temporary file %s\n",
|
||||
tmp_filename);
|
||||
}
|
||||
if (passwd_fp) locked_fclose_A(passwd_fp,PSRV_PW_FILE,TRUE);
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
|
||||
while (fgets(line, sizeof(line), passwd_fp)) {
|
||||
sscanf(line, "%s %s\n",
|
||||
princ_name, encrypted_passwd);
|
||||
if (strcmp(princ_name, principal))
|
||||
fputs(line, tmp_fp);
|
||||
}
|
||||
|
||||
(void) locked_fclose_A(tmp_fp,tmp_filename,FALSE);
|
||||
(void) locked_fclose_A(passwd_fp,PSRV_PW_FILE,TRUE);
|
||||
|
||||
if (rename(tmp_filename, PSRV_PW_FILE)) {
|
||||
unlink(tmp_filename);
|
||||
if (pfs_debug)
|
||||
perror("Could not overwrite password file");
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
|
||||
if (chmod(PSRV_PW_FILE, 0600)) {
|
||||
if (pfs_debug)
|
||||
perror("Could not change permissions of passwd file");
|
||||
RETURNPFAILURE;
|
||||
}
|
||||
|
||||
return PSUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Lists the principals in the Prospero password file */
|
||||
int list_ppw_file(void)
|
||||
{
|
||||
FILE *passwd_fp;
|
||||
char line[255];
|
||||
char princ_name[255], encrypted_passwd[255];
|
||||
int num;
|
||||
|
||||
if (!(passwd_fp = locked_fopen(PSRV_PW_FILE, "r")))
|
||||
RETURNPFAILURE;
|
||||
|
||||
while (fgets(line, sizeof(line), passwd_fp)) {
|
||||
if (line[0] == '#')
|
||||
continue;
|
||||
|
||||
num = sscanf(line, "%s %s\n",
|
||||
princ_name, encrypted_passwd);
|
||||
if (num == 2)
|
||||
printf("%s\n", princ_name);
|
||||
}
|
||||
|
||||
(void) locked_fclose_A(passwd_fp,PSRV_PW_FILE,TRUE);
|
||||
|
||||
return PSUCCESS;
|
||||
}
|
||||
|
||||
#endif /* PSRV_P_PASSWORD */
|
||||
37
prospero/lib/psrv/psrv_mutexes.c
Normal file
37
prospero/lib/psrv/psrv_mutexes.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 <pserver.h>
|
||||
#include <pfs.h>
|
||||
#include <psrv.h>
|
||||
|
||||
|
||||
void
|
||||
psrv_init_mutexes(void)
|
||||
{
|
||||
/* retrieve_fp() is not currently called by the server, so doesn't need
|
||||
mutexing. */
|
||||
p_th_mutex_init(p_th_mutexPSRV_CHECK_ACL_INET_DEF_LOCAL);
|
||||
p_th_mutex_init(p_th_mutexPSRV_CHECK_NFS_MYADDR);
|
||||
p_th_mutex_init(p_th_mutexPSRV_LOG);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void
|
||||
psrv_diagnose_mutexes(void)
|
||||
{
|
||||
printf("{psrv_diagnose_mutexes");
|
||||
DIAGMUTEX(PSRV_CHECK_ACL_INET_DEF_LOCAL,"PSRV_CHECK_ACL_INET_DEF_LOCAL");
|
||||
DIAGMUTEX(PSRV_CHECK_NFS_MYADDR,"PSRV_CHECK_NFS_MYADDR");
|
||||
DIAGMUTEX(PSRV_LOG,"PSRV_LOG");
|
||||
printf("}");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
74
prospero/lib/psrv/replyf.c
Normal file
74
prospero/lib/psrv/replyf.c
Normal file
@@ -0,0 +1,74 @@
|
||||
/* replyf.c */
|
||||
/*
|
||||
* 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 <stdarg.h>
|
||||
|
||||
#include <ardp.h>
|
||||
#include <pfs.h>
|
||||
#include <plog.h>
|
||||
#include <pprot.h>
|
||||
#include <psrv.h> /* includes prototypes of vreplyf(),
|
||||
vcreplyf(), replyf(), and creplyf() */
|
||||
|
||||
|
||||
/*
|
||||
* Note: If you are looking for the definitions of reply and creply
|
||||
* they are defined as macros that call ardp_reply with
|
||||
* the ARDP_R_COMPLETE or ARDP_R_INCOMPLETE flags.
|
||||
* This file defines the formatted versions of these
|
||||
* commands, replyf and creplyf.
|
||||
*/
|
||||
|
||||
int
|
||||
replyf(RREQ req, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int retval;
|
||||
|
||||
va_start(ap, format);
|
||||
retval = vreplyf(req, format, ap);
|
||||
va_end(ap);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
vreplyf(RREQ req, const char *format, va_list ap)
|
||||
{
|
||||
AUTOSTAT_CHARPP(bufp);
|
||||
|
||||
*bufp = vqsprintf_stcopyr(*bufp, format, ap);
|
||||
/* Perform the reply and pass through any error codes */
|
||||
return(ardp_breply(req, ARDP_R_INCOMPLETE, *bufp, p_bstlen(*bufp)));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
creplyf(RREQ req, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int retval;
|
||||
|
||||
va_start(ap, format);
|
||||
retval = vcreplyf(req, format, ap);
|
||||
va_end(ap);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
vcreplyf(RREQ req, const char *format, va_list ap)
|
||||
{
|
||||
AUTOSTAT_CHARPP(bufp);
|
||||
*bufp = vqsprintf_stcopyr(*bufp, format, ap);
|
||||
|
||||
/* Perform the reply and pass through any error codes */
|
||||
return(ardp_breply(req, ARDP_R_COMPLETE, *bufp, p_bstlen(*bufp)));
|
||||
}
|
||||
|
||||
94
prospero/lib/psrv/retrieve_fp.c
Normal file
94
prospero/lib/psrv/retrieve_fp.c
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 <netdb.h>
|
||||
|
||||
#include <pfs.h>
|
||||
#include <psrv.h> /* For dsrfinfo */
|
||||
#include <perrno.h>
|
||||
|
||||
VLINK check_fwd();
|
||||
|
||||
extern char hostname[];
|
||||
|
||||
/* retrieve_fp will retrieve a forwarding pointer and will
|
||||
* replace the changed fields of the link it is passed.
|
||||
* Retrieve will use pget_at to retriev the forwarding
|
||||
* pointer if it is on a remote host. If the same host,
|
||||
* it will retrieve the forwarding pointer directly.
|
||||
* Retrieve fp returs PSUCCESS on success and PFAILURE
|
||||
* on failure.
|
||||
*/
|
||||
#define RETURN(val) { retval = (val) ; goto cleanup; }
|
||||
int
|
||||
retrieve_fp(l)
|
||||
VLINK l;
|
||||
{
|
||||
struct hostent *h_ent;
|
||||
|
||||
static int firsttime = 0;
|
||||
static char thishost[100];
|
||||
char lhost[100];
|
||||
|
||||
PATTRIB fa = NULL; /* Forward attribute */
|
||||
VLINK fp; /* Forwarding Pointer */
|
||||
PFILE fi = pfalloc(); /* Pointer to fi_st */
|
||||
|
||||
int tmp;
|
||||
int retval;
|
||||
|
||||
assert(P_IS_THIS_THREAD_MASTER()); /* not yet converted. Not used currently
|
||||
either. gethostbyname MT-Unsafe */
|
||||
if(firsttime++ == 0) {
|
||||
h_ent = gethostbyname(hostname);
|
||||
strcpy(thishost,h_ent->h_name);
|
||||
}
|
||||
|
||||
/* We should check port numbers too */
|
||||
|
||||
/* Find out if link is on this host */
|
||||
h_ent = gethostbyname(l->host);
|
||||
if(h_ent) strcpy(lhost,h_ent->h_name);
|
||||
else RETURNPFAILURE;
|
||||
if(strcmp(lhost,thishost) == 0) { /* Local */
|
||||
tmp = dsrfinfo(l->hsoname,l->f_magic_no,fi);
|
||||
if((tmp == DSRFINFO_FORWARDED) &&
|
||||
(fp = check_fwd(fi->forward,l->hsoname,l->f_magic_no))) {
|
||||
l->hosttype = stcopyr(fp->hosttype,l->hosttype);
|
||||
l->host = stcopyr(fp->host,l->host);
|
||||
l->hsonametype = stcopyr(fp->hsonametype,l->hsonametype);
|
||||
l->hsoname = stcopyr(fp->hsoname,l->hsoname);
|
||||
l->version = fp->version;
|
||||
l->f_magic_no = fp->f_magic_no;
|
||||
RETURN(PSUCCESS);
|
||||
}
|
||||
RETURN(PFAILURE);
|
||||
}
|
||||
else { /* Remote */
|
||||
/* fa could memory leak if pget_at succeeds, but its not ATR_LINK*/
|
||||
fa = pget_at(l,"FORWARDING-POINTER");
|
||||
if(fa && fa->avtype == ATR_LINK && fa->value.link) {
|
||||
fp = fa->value.link;
|
||||
l->hosttype = stcopyr(fp->hosttype,l->hosttype);
|
||||
l->host = stcopyr(fp->host,l->host);
|
||||
l->hsonametype = stcopyr(fp->hsonametype,l->hsonametype);
|
||||
l->hsoname = stcopyr(fp->hsoname,l->hsoname);
|
||||
l->version = fp->version;
|
||||
l->f_magic_no = fp->f_magic_no;
|
||||
RETURN(PSUCCESS);
|
||||
}
|
||||
else RETURN(PFAILURE);
|
||||
}
|
||||
cleanup:
|
||||
pffree(fi);
|
||||
if (fa) atlfree(fa);
|
||||
return(retval);
|
||||
}
|
||||
|
||||
|
||||
48
prospero/lib/psrv/srv_qoprintf.c
Normal file
48
prospero/lib/psrv/srv_qoprintf.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 <stdio.h> /* for fputs() and EOF */
|
||||
#include <ardp.h>
|
||||
#include <pfs.h>
|
||||
#include <pparse.h>
|
||||
#include <psrv.h>
|
||||
|
||||
/* Returns PFAILURE or PSUCCESS. */
|
||||
int
|
||||
srv_qoprintf(OUTPUT out, const char fmt[], ...)
|
||||
{
|
||||
va_list ap;
|
||||
int retval;
|
||||
|
||||
assert(out->req || out->f);
|
||||
va_start(ap, fmt);
|
||||
|
||||
if (out->f) {
|
||||
retval = vqfprintf(out->f, fmt, ap);
|
||||
} else {
|
||||
retval = vreplyf(out->req, fmt, ap);
|
||||
}
|
||||
va_end(ap);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
reqtoout(RREQ req, OUTPUT out)
|
||||
{
|
||||
out->f = NULL;
|
||||
out->request = NULL;
|
||||
out->req = req;
|
||||
}
|
||||
|
||||
void
|
||||
filetoout(FILE *file, OUTPUT out)
|
||||
{
|
||||
out->req = NULL;
|
||||
out->request = NULL;
|
||||
out->f = file;
|
||||
}
|
||||
8
prospero/lib/psrv/stat_object.c
Normal file
8
prospero/lib/psrv/stat_object.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <pfs.h>
|
||||
#include <psrv.h>
|
||||
|
||||
/* Run STAT on the object OB. */
|
||||
int
|
||||
stat_object(OBJECT ob)
|
||||
{
|
||||
}
|
||||
1
prospero/lib/psrv/wais_gw/.gitignore
vendored
Normal file
1
prospero/lib/psrv/wais_gw/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Makefile
|
||||
49
prospero/lib/psrv/wais_gw/FILES
Normal file
49
prospero/lib/psrv/wais_gw/FILES
Normal file
@@ -0,0 +1,49 @@
|
||||
FILES
|
||||
Makefile
|
||||
buffalloc.c
|
||||
buffalloc.h
|
||||
cdialect.h
|
||||
cutil.c
|
||||
cutil.h
|
||||
docid.h
|
||||
futil.c
|
||||
futil.h
|
||||
ietftype.c
|
||||
ietftype.h
|
||||
ietftype_parse.c
|
||||
ietftype_parse.h
|
||||
ietftypes
|
||||
inface.c
|
||||
inface.h
|
||||
irfileio.c
|
||||
irfileio.h
|
||||
list.c
|
||||
list.h
|
||||
main.c
|
||||
panic.c
|
||||
panic.h
|
||||
sockets.c
|
||||
sockets.h
|
||||
source.c
|
||||
source.h
|
||||
sourcealloc.c
|
||||
sourceparse.c
|
||||
ustubs.c
|
||||
ustubs.h
|
||||
wais_gw_dsdb.c
|
||||
wais_gw_dsdb.h
|
||||
wais_gw_mutex.c
|
||||
waislog.c
|
||||
waislog.h
|
||||
wmessage.c
|
||||
wmessage.h
|
||||
wprot.c
|
||||
wprot.h
|
||||
wutil.c
|
||||
wutil.h
|
||||
zprot.c
|
||||
zprot.h
|
||||
ztype1.c
|
||||
ztype1.h
|
||||
zutil.c
|
||||
zutil.h
|
||||
234
prospero/lib/psrv/wais_gw/Makefile.in
Executable file
234
prospero/lib/psrv/wais_gw/Makefile.in
Executable file
@@ -0,0 +1,234 @@
|
||||
#*****************************************************************************
|
||||
# (c) Copyright 1992,1993 Wide Area Information Servers, Inc *
|
||||
# of California. All rights reserved. *
|
||||
# *
|
||||
# This notice is intended as a precaution against inadvertent publication *
|
||||
# and does not constitute an admission or acknowledgement that publication *
|
||||
# has occurred or constitute a waiver of confidentiality. *
|
||||
# *
|
||||
# Wide Area Information Server software is the proprietary and *
|
||||
# confidential property of Wide Area Information Servers, Inc. *
|
||||
#*****************************************************************************
|
||||
# this file has different configuration ideas from the rest of Prospero.
|
||||
# this is a problem.
|
||||
|
||||
SOURCEBASE=../../..
|
||||
include $(SOURCEBASE)/Makefile.config
|
||||
|
||||
# Note that not all versions of make will support this construct.
|
||||
CFLAGS += $(WCFLAGS)
|
||||
|
||||
# These are needed by the Prospero 'setdependencies' script.
|
||||
|
||||
CFILES = buffalloc.c \
|
||||
ustubs.c \
|
||||
list.c \
|
||||
cutil.c \
|
||||
futil.c \
|
||||
panic.c \
|
||||
waislog.c \
|
||||
irfileio.c \
|
||||
wutil.c \
|
||||
wprot.c \
|
||||
zprot.c \
|
||||
zutil.c \
|
||||
ztype1.c \
|
||||
source.c \
|
||||
sourcealloc.c \
|
||||
sockets.c \
|
||||
inface.c \
|
||||
wmessage.c \
|
||||
ietftype.c \
|
||||
ietftype_parse.c \
|
||||
wais_gw_mutex.c \
|
||||
wais_gw_dsdb.c \
|
||||
sourceparse.c
|
||||
|
||||
|
||||
|
||||
# the z3950 protocol and tcp communications
|
||||
|
||||
UTIL = \
|
||||
buffalloc.o \
|
||||
ustubs.o \
|
||||
list.o \
|
||||
cutil.o \
|
||||
futil.o \
|
||||
panic.o \
|
||||
waislog.o \
|
||||
irfileio.o
|
||||
|
||||
OBJS = \
|
||||
wutil.o \
|
||||
wprot.o \
|
||||
zprot.o \
|
||||
zutil.o \
|
||||
ztype1.o \
|
||||
source.o \
|
||||
sourcealloc.o \
|
||||
sockets.o \
|
||||
inface.o \
|
||||
wmessage.o
|
||||
|
||||
GW = \
|
||||
ietftype.o \
|
||||
ietftype_parse.o \
|
||||
wais_gw_mutex.o \
|
||||
wais_gw_dsdb.o
|
||||
|
||||
OBJECTS = ${UTIL} ${OBJS} ${GW} sourceparse.o
|
||||
|
||||
all: ${WAIS_GW_LIB} sourceparse
|
||||
|
||||
${WAIS_GW_LIB}: ${OBJS} ${UTIL} ${GW}
|
||||
$(RM) -f $@
|
||||
$(AR) $(ARFLAGS) $@ $(OBJS) $(UTIL) $(GW)
|
||||
$(RANLIB) $@
|
||||
|
||||
install: sourceparse ietftypes
|
||||
-for i in sourceparse ietftypes ; do \
|
||||
${INSTALL} -c -m 755 -o ${OWNER} -g ${GROUP} $$i ${P_BINARIES}/$$i${GENERATIONSUFFIX}; \
|
||||
${GENERATION} ${P_BINARIES}/$$i ; \
|
||||
done
|
||||
|
||||
|
||||
sourceparse: sourceparse.o ${WAIS_GW_LIB} $(PFS_LIBS_DEPENDENCIES)
|
||||
${CC} ${CFLAGS} -o $@ sourceparse.o $(WAIS_GW_LIB) $(PFS_LIBS)
|
||||
|
||||
# Not clear why this is necessary. --swa
|
||||
#-u ${COMPILER_PREPENDS_C_SYMBOLS_WITH_UNDERSCORE}gopher_gw_init_mutexes ${SPLIBS}
|
||||
|
||||
|
||||
# Dependencies
|
||||
buffalloc.o : buffalloc.h inface.h \
|
||||
wprot.h cdialect.h zprot.h zutil.h cutil.h \
|
||||
../../../include/pfs_threads.h ../../../include/pfs_utils.h ztype1.h ../../../include/pfs.h \
|
||||
../../../include/ardp.h \
|
||||
../../../include/list_macros.h ../../../include/../lib/ardp/flocks.h \
|
||||
../../../include/implicit_fixes.h \
|
||||
../../../include/pmachine.h \
|
||||
../../../include/mitra_macros.h ../../../include/psrv.h \
|
||||
../../../include/pparse.h
|
||||
ustubs.o : ustubs.h cdialect.h futil.h cutil.h \
|
||||
../../../include/pmachine.h \
|
||||
../../../include/pfs_threads.h ../../../include/pfs_utils.h
|
||||
list.o : list.h cutil.h \
|
||||
cdialect.h
|
||||
cutil.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 cutil.h cdialect.h futil.h
|
||||
futil.o : \
|
||||
futil.h \
|
||||
cdialect.h cutil.h \
|
||||
panic.h ../../../include/pfs_threads.h ../../../include/pfs_utils.h
|
||||
panic.o : \
|
||||
panic.h cdialect.h waislog.h \
|
||||
cutil.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/perrno.h
|
||||
waislog.o :
|
||||
irfileio.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 irfileio.h cdialect.h futil.h cutil.h zprot.h zutil.h
|
||||
wutil.o : futil.h cdialect.h cutil.h \
|
||||
zprot.h \
|
||||
zutil.h ../../../include/pfs_threads.h ../../../include/pfs_utils.h \
|
||||
wprot.h ztype1.h \
|
||||
wutil.h
|
||||
wprot.o : wprot.h cdialect.h zprot.h zutil.h cutil.h \
|
||||
../../../include/pfs_threads.h ../../../include/pfs_utils.h \
|
||||
ztype1.h panic.h
|
||||
zprot.o : zprot.h cdialect.h zutil.h cutil.h \
|
||||
../../../include/pfs_threads.h ../../../include/pfs_utils.h
|
||||
zutil.o : \
|
||||
zutil.h \
|
||||
cdialect.h cutil.h \
|
||||
../../../include/pfs_threads.h ../../../include/pfs_utils.h
|
||||
ztype1.o : ztype1.h cdialect.h zutil.h cutil.h \
|
||||
../../../include/pfs_threads.h ../../../include/pfs_utils.h \
|
||||
panic.h waislog.h
|
||||
source.o : ../../../include/string_with_strcasecmp.h \
|
||||
cutil.h \
|
||||
cdialect.h \
|
||||
futil.h \
|
||||
irfileio.h zprot.h zutil.h ../../../include/pfs_threads.h \
|
||||
../../../include/pfs_utils.h source.h ../../../include/pfs.h ../../../include/ardp.h \
|
||||
../../../include/list_macros.h \
|
||||
../../../include/../lib/ardp/flocks.h ../../../include/implicit_fixes.h \
|
||||
../../../include/pmachine.h \
|
||||
../../../include/mitra_macros.h ../../../include/psrv.h \
|
||||
../../../include/pparse.h
|
||||
sourcealloc.o : buffalloc.h inface.h wprot.h cdialect.h zprot.h \
|
||||
zutil.h cutil.h \
|
||||
../../../include/pfs_threads.h ../../../include/pfs_utils.h \
|
||||
ztype1.h ../../../include/pfs.h ../../../include/ardp.h \
|
||||
../../../include/list_macros.h ../../../include/../lib/ardp/flocks.h \
|
||||
../../../include/implicit_fixes.h \
|
||||
../../../include/pmachine.h \
|
||||
../../../include/mitra_macros.h source.h
|
||||
sockets.o : sockets.h cdialect.h cutil.h \
|
||||
../../../include/posix_signal.h \
|
||||
panic.h waislog.h
|
||||
inface.o : zutil.h cdialect.h cutil.h \
|
||||
../../../include/pfs_threads.h ../../../include/pfs_utils.h \
|
||||
zprot.h wprot.h ztype1.h wmessage.h inface.h sockets.h \
|
||||
waislog.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 buffalloc.h
|
||||
wmessage.o : \
|
||||
wmessage.h cdialect.h cutil.h
|
||||
ietftype.o : ietftype.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 ../../../include/psrv.h \
|
||||
../../../include/pparse.h
|
||||
ietftype_parse.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 \
|
||||
ietftype.h ../../../include/mitra_macros.h
|
||||
wais_gw_mutex.o : ../../../include/pfs_threads.h \
|
||||
../../../include/pfs_utils.h \
|
||||
ietftype_parse.h ietftype.h ../../../include/pfs.h ../../../include/ardp.h \
|
||||
../../../include/list_macros.h \
|
||||
../../../include/../lib/ardp/flocks.h ../../../include/implicit_fixes.h \
|
||||
../../../include/pmachine.h
|
||||
wais_gw_dsdb.o : \
|
||||
../../../include/pmachine.h \
|
||||
../../../include/psite.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/implicit_fixes.h \
|
||||
../../../include/pserver.h ../../../include/psrv.h \
|
||||
../../../include/pparse.h \
|
||||
../../../include/perrno.h ../../../include/plog.h wprot.h cdialect.h zprot.h \
|
||||
zutil.h cutil.h ztype1.h source.h inface.h wais_gw_dsdb.h ietftype.h ietftype_parse.h
|
||||
sourceparse.o : \
|
||||
source.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
|
||||
137
prospero/lib/psrv/wais_gw/buffalloc.c
Normal file
137
prospero/lib/psrv/wais_gw/buffalloc.c
Normal file
@@ -0,0 +1,137 @@
|
||||
/* Copyright (c) 1993, by Pandora Systems */
|
||||
/* Author: Mitra <mitra@path.net> */
|
||||
/* Allocation code copied and adapted from:
|
||||
prospero/alpha.5.2a+/lib/pfs/flalloc */
|
||||
|
||||
/*
|
||||
* Original allocation code Copyright (c) 1991-1993 by the University of
|
||||
* Southern California
|
||||
* Modifications to Pandora code 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 "buffalloc.h"
|
||||
#include <pfs.h>
|
||||
#include <mitra_macros.h>
|
||||
#define Channel_Illegal 0;
|
||||
#include <psrv.h> /* includes global declarations of
|
||||
waismsgbuff_count and waismsgbuff_max to be
|
||||
read by dirsrv.c. */
|
||||
|
||||
static WAISMSGBUFF lfree = NULL; /* Free waismsgbuffs */
|
||||
/* 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 waismsgbuff_count = 0;
|
||||
int waismsgbuff_max = 0;
|
||||
|
||||
|
||||
/************* Standard routines to alloc, free and copy *************/
|
||||
/*
|
||||
* waismsgbuff_alloc - allocate and initialize WAISMSGBUFF structure
|
||||
*
|
||||
* returns a pointer to an initialized structure of type
|
||||
* WAISMSGBUFF. If it is unable to allocate such a structure, it
|
||||
* signals out_of_memory();
|
||||
*/
|
||||
|
||||
WAISMSGBUFF
|
||||
waismsgbuff_alloc()
|
||||
{
|
||||
WAISMSGBUFF msgbuff;
|
||||
|
||||
TH_STRUC_ALLOC(waismsgbuff,WAISMSGBUFF,msgbuff);
|
||||
return(msgbuff);
|
||||
}
|
||||
|
||||
/*
|
||||
* waismsgbuff_free - free a WAISMSGBUFF structure
|
||||
*
|
||||
* waismsgbuff_free takes a pointer to a WAISMSGBUFF structure and adds it to
|
||||
* the free list for later reuse.
|
||||
*/
|
||||
void
|
||||
waismsgbuff_free(WAISMSGBUFF msgbuff)
|
||||
{
|
||||
TH_STRUC_FREE(waismsgbuff,WAISMSGBUFF,msgbuff);
|
||||
}
|
||||
|
||||
/*
|
||||
* waismsgbuff_lfree - free a linked list of WAISMSGBUFF structures.
|
||||
*
|
||||
* waismsgbuff_lfree takes a pointer to a waismsgbuff structure frees it and
|
||||
* any linked
|
||||
* WAISMSGBUFF structures. It is used to free an entire list of WAISMSGBUFF
|
||||
* structures.
|
||||
*/
|
||||
void
|
||||
waismsgbuff_lfree(msgbuff)
|
||||
WAISMSGBUFF msgbuff;
|
||||
{
|
||||
TH_STRUC_LFREE(WAISMSGBUFF,msgbuff,waismsgbuff_free);
|
||||
}
|
||||
|
||||
void
|
||||
waismsgbuff_freespares()
|
||||
{
|
||||
TH_FREESPARES(waismsgbuff,WAISMSGBUFF);
|
||||
}
|
||||
|
||||
#ifdef NEVERDEFINED
|
||||
/*
|
||||
* waismsgbuff_copy - allocates a new waismsgbuff structure and
|
||||
* initializes it with a copy of another
|
||||
* waismsgbuff, v.
|
||||
*
|
||||
* If r is non-zero, successive waismsgbuffs will be
|
||||
* iteratively copied.
|
||||
*
|
||||
* msgbuff-previous will always be null on the first link, and
|
||||
* will be appropriately filled in for iteratively copied links.
|
||||
*
|
||||
* waismsgbuff_copy returns a pointer to the new structure of type
|
||||
* WAISMSGBUFF. If it is unable to allocate such a structure, it
|
||||
* returns NULL.
|
||||
*
|
||||
* waismsgbuff_copy will recursively copy the link associated with
|
||||
* a waismsgbuff and
|
||||
* its associated attributes.
|
||||
*/
|
||||
|
||||
WAISMSGBUFF
|
||||
waismsgbuff_copy(f,r)
|
||||
WAISMSGBUFF f;
|
||||
int r; /* Currently ignored. */
|
||||
{
|
||||
WAISMSGBUFF nf;
|
||||
WAISMSGBUFF snf; /* Start of the chain of new links */
|
||||
WAISMSGBUFF tf; /* Temporary link pointer */
|
||||
|
||||
nf = waismsgbuff_alloc();
|
||||
snf = nf;
|
||||
|
||||
copyeach:
|
||||
|
||||
/* Copy f into nf */
|
||||
#ifdef ALLOCATOR_CONSISTENCY_CHECK
|
||||
assert(f->consistency == INUSE_PATTERN);
|
||||
#endif
|
||||
LOCAL STUFF NOT DEFINED
|
||||
if(r && f->next) {
|
||||
f = f->next;
|
||||
tf = nf;
|
||||
nf = waismsgbuff_alloc();
|
||||
nf->previous = tf;
|
||||
tf->next = nf;
|
||||
goto copyeach;
|
||||
}
|
||||
|
||||
return(snf);
|
||||
}
|
||||
|
||||
#endif
|
||||
27
prospero/lib/psrv/wais_gw/buffalloc.h
Normal file
27
prospero/lib/psrv/wais_gw/buffalloc.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef wais_buffalloc_h
|
||||
#define wais_buffalloc_h
|
||||
|
||||
#include "inface.h" /* For MAX_MESSAGE_LENGTH */
|
||||
#include <pfs.h>
|
||||
#include <pfs_threads.h>
|
||||
|
||||
struct waismsgbuff {
|
||||
#ifdef ALLOCATOR_CONSISTENCY_CHECK
|
||||
int consistency;
|
||||
#endif
|
||||
char buff[(size_t)MAX_MESSAGE_LENGTH * sizeof(char)];
|
||||
struct waismsgbuff *next;
|
||||
struct waismsgbuff *previous;
|
||||
};
|
||||
typedef struct waismsgbuff *WAISMSGBUFF;
|
||||
typedef struct waismsgbuff WAISMSGBUFF_ST;
|
||||
|
||||
extern WAISMSGBUFF waismsgbuff_alloc();
|
||||
extern void waismsgbuff_free(WAISMSGBUFF msgbuff);
|
||||
extern void waismsgbuff_lfree(WAISMSGBUFF msgbuff);
|
||||
extern void waismsgbuff_freespares();
|
||||
/*extern WAISMSGBUFF waismsgbuff_copy(WAISMSGBUFF f, int r);*/
|
||||
|
||||
EXTERN_ALLOC_DECL(WAISMSGBUFF);
|
||||
|
||||
#endif /*wais_buffalloc_h*/
|
||||
117
prospero/lib/psrv/wais_gw/cdialect.h
Normal file
117
prospero/lib/psrv/wais_gw/cdialect.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/* WIDE AREA INFORMATION SERVER SOFTWARE:
|
||||
Developed by Thinking Machines Corporation and put into the public
|
||||
domain with no guarantees or restrictions.
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* there are three kinds of C that we have encountered so far:
|
||||
|
||||
1. ANSI_LIKE - full prototypes and stdargs and ansi includes
|
||||
2. PROTO_ANSI - full prototypes, varargs and misc includes
|
||||
3. K_AND_R - k&r prototypes, varargs and misc includes
|
||||
|
||||
This file is a mess because some compilers do not handle elif. sorry.
|
||||
|
||||
defined symbols for other machines:
|
||||
hp: hpux
|
||||
Next: NeXT
|
||||
*/
|
||||
|
||||
#ifndef C_DIALECT
|
||||
#define C_DIALECT
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#define _AP(args) args
|
||||
|
||||
#ifdef STDC
|
||||
#define ANSI_LIKE
|
||||
#endif /* def STDC */
|
||||
|
||||
#ifdef __STDC__
|
||||
#ifndef M_XENIX /* for some reason XENIX defines __STDC__ */
|
||||
#define ANSI_LIKE
|
||||
#endif /* ndef M_XENIX */
|
||||
#endif /* __STDC__ */
|
||||
|
||||
#ifdef __alpha
|
||||
#define ANSI_LIKE
|
||||
#endif /* def __alpha */
|
||||
|
||||
#ifdef THINK_C
|
||||
#define ANSI_LIKE
|
||||
#endif /* THINK_C */
|
||||
|
||||
#ifdef MPW
|
||||
#define ANSI_LIKE
|
||||
#endif /* MPW */
|
||||
|
||||
#ifdef VAX_C /* vms */
|
||||
#define ANSI_LIKE
|
||||
#endif /* VAX_C */
|
||||
|
||||
#ifdef MSC /* XXX not sure if this is correct */
|
||||
#define ANSI_LIKE
|
||||
#endif /* MSC */
|
||||
|
||||
#ifndef ANSI_LIKE
|
||||
|
||||
#ifdef SABER /* c interpreter/debugger */
|
||||
#define PROTO_ANSI
|
||||
#endif /* SABER */
|
||||
|
||||
#ifdef cstar /* parallel C on the CM */
|
||||
#define PROTO_ANSI
|
||||
#endif /* cstar */
|
||||
|
||||
#ifndef PROTO_ANSI
|
||||
|
||||
#ifdef SUN_C /* XXX not sure if this is correct */
|
||||
#define K_AND_R
|
||||
#endif /* SUN_C */
|
||||
|
||||
#ifdef __GNUC__ /* gcc in traditional mode */
|
||||
#define K_AND_R /* gcc in ansi mode defines __STDC__ */
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#ifdef M_XENIX
|
||||
#define K_AND_R
|
||||
#define NOTCPIP /* doesn't support TCP */
|
||||
#define SYSV /* is based on system V */
|
||||
#endif /* M_XENIX */
|
||||
|
||||
/* otherwise */
|
||||
#define K_AND_R /* default to the stone age */
|
||||
|
||||
#endif /* ndef PROTO_ANSI */
|
||||
#endif /* ndef ANSI_LIKE */
|
||||
|
||||
/* if you are not k_and_r, then load in ustubs always */
|
||||
#ifdef K_AND_R
|
||||
#include "ustubs.h"
|
||||
#endif /* def K_AND_R */
|
||||
|
||||
/* Comment this back in to figure out what the compiler thinks we are */
|
||||
/*
|
||||
#ifdef ANSI_LIKE
|
||||
WeareAnsiLike
|
||||
#endif
|
||||
#ifdef PROTO_ANSI
|
||||
WeareProtoAnsi
|
||||
#endif
|
||||
#ifdef K_AND_R
|
||||
WeareKandR
|
||||
#endif
|
||||
Crash-and-Burn
|
||||
*/
|
||||
/* End of chunk to comment back in */
|
||||
|
||||
#ifdef SCOUNIX
|
||||
#define getdomainname(str,len) sprintf(str,"")
|
||||
#endif /*SCOUNIX*/
|
||||
#endif /* ndef C_DIALECT */
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
|
||||
777
prospero/lib/psrv/wais_gw/cutil.c
Normal file
777
prospero/lib/psrv/wais_gw/cutil.c
Normal file
@@ -0,0 +1,777 @@
|
||||
/*****************************************************************************
|
||||
* (c) Copyright 1992 Wide Area Information Servers, Inc *
|
||||
* of California. All rights reserved. *
|
||||
* *
|
||||
* This notice is intended as a precaution against inadvertent publication *
|
||||
* and does not constitute an admission or acknowledgement that publication *
|
||||
* has occurred or constitute a waiver of confidentiality. *
|
||||
* *
|
||||
* Wide Area Information Server software is the proprietary and *
|
||||
* confidential property of Wide Area Information Servers, Inc. *
|
||||
*****************************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#define cutil_c
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <pfs.h>
|
||||
#include <perrno.h>
|
||||
|
||||
#include "cutil.h"
|
||||
#include "futil.h"
|
||||
|
||||
#ifdef NOTUSEDANDNOTTHREADSAFE
|
||||
long myPID = -1;
|
||||
#endif /*NOTUSEDANDNOTTHREADSAFE*/
|
||||
|
||||
typedef long (longfunc)(long c);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
char*
|
||||
s_strdup(char* s)
|
||||
{
|
||||
unsigned long len;
|
||||
char* copy = NULL;
|
||||
|
||||
if (s == NULL)
|
||||
return(NULL);
|
||||
|
||||
len = strlen(s);
|
||||
copy = (char*)s_malloc((size_t)(sizeof(char)*(len + 1)));
|
||||
strncpy(copy,s,len + 1);
|
||||
return(copy);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#if !defined(IN_RMG) && !defined(PFS_THREADS)
|
||||
char*
|
||||
strtokf(char* s1,longfunc *isDelimiter)
|
||||
{
|
||||
static char* searchStr = NULL;
|
||||
static longfunc *delimiterFunc;
|
||||
long i;
|
||||
char* startTok = NULL;
|
||||
|
||||
if (s1 != NULL)
|
||||
searchStr = s1;
|
||||
|
||||
if (isDelimiter != NULL)
|
||||
delimiterFunc = isDelimiter;
|
||||
|
||||
if (searchStr == NULL || searchStr[0] == '\0')
|
||||
return(NULL);
|
||||
|
||||
if (delimiterFunc == NULL)
|
||||
return(NULL);
|
||||
|
||||
for (i = 0; searchStr[i] != '\0'; i++)
|
||||
{ if ((*delimiterFunc)((long)searchStr[i]) == NOT_DELIMITER)
|
||||
break;
|
||||
}
|
||||
|
||||
if (searchStr[i] == '\0')
|
||||
return(NULL);
|
||||
else
|
||||
startTok = searchStr + i;
|
||||
|
||||
for (; searchStr[i] != '\0'; i++)
|
||||
{ if ((*delimiterFunc)((long)searchStr[i]) == IS_DELIMITER)
|
||||
break;
|
||||
}
|
||||
|
||||
if (searchStr[i] != '\0')
|
||||
{ searchStr[i] = '\0';
|
||||
searchStr = searchStr + i + 1;
|
||||
}
|
||||
else
|
||||
searchStr = searchStr + i;
|
||||
|
||||
return(startTok);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
char*
|
||||
strtokf_isalnum(char* s1)
|
||||
{
|
||||
static char* searchStr = NULL;
|
||||
long i;
|
||||
char* startTok = NULL;
|
||||
|
||||
if (s1 != NULL)
|
||||
searchStr = s1;
|
||||
|
||||
if (searchStr == NULL || searchStr[0] == '\0')
|
||||
return(NULL);
|
||||
|
||||
for (i = 0; searchStr[i] != '\0'; i++)
|
||||
{ if (safeIsAlNum(searchStr[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (searchStr[i] == '\0')
|
||||
return(NULL);
|
||||
else
|
||||
startTok = searchStr + i;
|
||||
|
||||
for (; searchStr[i] != '\0'; i++)
|
||||
{ if (!safeIsAlNum(searchStr[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (searchStr[i] != '\0')
|
||||
{ searchStr[i] = '\0';
|
||||
searchStr = searchStr + i + 1;
|
||||
}
|
||||
else
|
||||
searchStr = searchStr + i;
|
||||
|
||||
return(startTok);
|
||||
}
|
||||
#endif /*NOTUSEDANDNOTTHREADSAFE*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
boolean
|
||||
substrcmp(char* string1,char* string2)
|
||||
/* return true if they match up to the length of the smaller (but not if the
|
||||
smaller is empty)
|
||||
*/
|
||||
{
|
||||
|
||||
register char *a, *b;
|
||||
|
||||
a = string1;
|
||||
b = string2;
|
||||
|
||||
/* see if they are both empty - if so them match */
|
||||
if (*a == '\0' && *b == '\0')
|
||||
return(true);
|
||||
|
||||
/* see if either is empty (but not both) - no match */
|
||||
if (*a == '\0' || *b == '\0')
|
||||
return(false);
|
||||
|
||||
/* otherwise we need to look through each byte */
|
||||
while (*a && *b)
|
||||
{ if (*a++ != *b++)
|
||||
return(false);
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
char
|
||||
char_downcase(unsigned long long_ch)
|
||||
{
|
||||
unsigned char ch = long_ch & 0xFF;
|
||||
|
||||
return(((ch >= 'A') && (ch <= 'Z')) ? (ch + 'a' -'A') : ch);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
char*
|
||||
string_downcase(char *word)
|
||||
{
|
||||
long i = 0;
|
||||
|
||||
if (word == NULL)
|
||||
return(NULL);
|
||||
|
||||
while (word[i] != '\0')
|
||||
{ word[i] = char_downcase((unsigned long)word[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
return(word);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
long
|
||||
cprintf(boolean print, char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
if (print == 1)
|
||||
{ long res;
|
||||
va_start(ap,format);
|
||||
res = vprintf(format,ap);
|
||||
va_end(ap);
|
||||
return(res);
|
||||
}
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
printHexByte(unsigned char h)
|
||||
{
|
||||
if (h < 0x10)
|
||||
printf("0%x",h);
|
||||
else
|
||||
printf("%x",h);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifdef NOTUSEDANDNOTTHREADSAFE
|
||||
char*
|
||||
commafy(long val,char* buf)
|
||||
/*
|
||||
prints the value using format, then adds commas separating every
|
||||
three orders of magnitude on the left side of the decimal point.
|
||||
|
||||
limitations
|
||||
- there needs to be a buffer to write the result into. We provide
|
||||
one for convenience, but of course that's not reentrant, so if you
|
||||
are calling this is multiple times before using the result you'll
|
||||
need to pass in your own buffer
|
||||
- only works on longs
|
||||
- only works on positive nums
|
||||
- no other formatting allowed
|
||||
*/
|
||||
{
|
||||
static char myBuf[100];
|
||||
|
||||
if (buf == NULL)
|
||||
buf = myBuf;
|
||||
|
||||
if (val < 1000) /* 1 thousand */
|
||||
sprintf(buf,"%ld",val);
|
||||
else if (val < 1000000) /* 1 millon */
|
||||
{ long lessThanAGrand = val%1000;
|
||||
long moreThanAGrand = val - lessThanAGrand;
|
||||
sprintf(buf,"%ld,%03ld",moreThanAGrand/1000,lessThanAGrand);
|
||||
}
|
||||
else if (val < 1000000000) /* 1 trillion, 1 gig */
|
||||
{ long lessThanAGrand = val%1000;
|
||||
long lessThanAMil = (val%1000000) - lessThanAGrand;
|
||||
long moreThanAMil = val - lessThanAMil - lessThanAGrand;
|
||||
sprintf(buf,"%ld,%03ld,%03ld",moreThanAMil/1000000,lessThanAMil/1000,
|
||||
val%1000);
|
||||
}
|
||||
|
||||
return(buf);
|
||||
}
|
||||
#endif NOTUSEDANDNOTTHREADSAFE
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifdef NOTUSEDANDNOTTHREADSAFE
|
||||
char*
|
||||
printable_time(void)
|
||||
{
|
||||
static char *string;
|
||||
time_t tptr;
|
||||
time(&tptr);
|
||||
string = ctime(&tptr);
|
||||
if (string)
|
||||
{ if (string[strlen(string)-1] == '\n')
|
||||
string[strlen(string)-1] = '\0';
|
||||
return(string+4);
|
||||
}
|
||||
else
|
||||
return("Time Unknown");
|
||||
}
|
||||
#endif /*NOTUSEDANDNOTTHREADSAFE*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef BSD
|
||||
#define NEED_VPRINTF
|
||||
#endif
|
||||
|
||||
#ifdef NEED_VPRINTF
|
||||
#ifdef OSK
|
||||
#define LONGINT
|
||||
#define INTSPRINTF
|
||||
#endif
|
||||
|
||||
#ifdef NOVOID
|
||||
typedef char *pointer;
|
||||
#else
|
||||
typedef void *pointer;
|
||||
#endif
|
||||
|
||||
#ifdef INTSPRINTF
|
||||
#define Sprintf(string,format,arg) (sprintf((string),(format),(arg)))
|
||||
#else
|
||||
#define Sprintf(string,format,arg) (\
|
||||
sprintf((string),(format),(arg)),\
|
||||
strlen(string)\
|
||||
)
|
||||
#endif
|
||||
|
||||
typedef int *intp;
|
||||
|
||||
int vsprintf(dest, format, args)
|
||||
char *dest;
|
||||
register char *format;
|
||||
va_list args;
|
||||
{
|
||||
register char *dp = dest;
|
||||
register char c;
|
||||
register char *tp;
|
||||
char tempfmt[64];
|
||||
#ifndef LONGINT
|
||||
int longflag;
|
||||
#endif
|
||||
|
||||
tempfmt[0] = '%';
|
||||
while( (c = *format++) != 0) {
|
||||
if(c=='%') {
|
||||
tp = &tempfmt[1];
|
||||
#ifndef LONGINT
|
||||
longflag = 0;
|
||||
#endif
|
||||
continue_format:
|
||||
switch(c = *format++) {
|
||||
case 's':
|
||||
*tp++ = c;
|
||||
*tp = '\0';
|
||||
dp += Sprintf(dp, tempfmt, va_arg(args, char *));
|
||||
break;
|
||||
case 'u':
|
||||
case 'x':
|
||||
case 'o':
|
||||
case 'X':
|
||||
#ifdef UNSIGNEDSPECIAL
|
||||
*tp++ = c;
|
||||
*tp = '\0';
|
||||
#ifndef LONGINT
|
||||
if(longflag)
|
||||
dp += Sprintf(dp, tempfmt, va_arg(args, unsigned long));
|
||||
else
|
||||
#endif
|
||||
dp += Sprintf(dp, tempfmt, va_arg(args, unsigned));
|
||||
break;
|
||||
#endif
|
||||
case 'd':
|
||||
case 'c':
|
||||
case 'i':
|
||||
*tp++ = c;
|
||||
*tp = '\0';
|
||||
#ifndef LONGINT
|
||||
if(longflag)
|
||||
dp += Sprintf(dp, tempfmt, va_arg(args, long));
|
||||
else
|
||||
#endif
|
||||
dp += Sprintf(dp, tempfmt, va_arg(args, int));
|
||||
break;
|
||||
case 'f':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'g':
|
||||
case 'G':
|
||||
*tp++ = c;
|
||||
*tp = '\0';
|
||||
dp += Sprintf(dp, tempfmt, va_arg(args, double));
|
||||
break;
|
||||
case 'p':
|
||||
*tp++ = c;
|
||||
*tp = '\0';
|
||||
dp += Sprintf(dp, tempfmt, va_arg(args, pointer));
|
||||
break;
|
||||
case '-':
|
||||
case '+':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '.':
|
||||
case ' ':
|
||||
case '#':
|
||||
case 'h':
|
||||
*tp++ = c;
|
||||
goto continue_format;
|
||||
case 'l':
|
||||
#ifndef LONGINT
|
||||
longflag = 1;
|
||||
*tp++ = c;
|
||||
#endif
|
||||
goto continue_format;
|
||||
case '*':
|
||||
tp += Sprintf(tp, "%d", va_arg(args, int));
|
||||
goto continue_format;
|
||||
case 'n':
|
||||
*va_arg(args, intp) = dp - dest;
|
||||
break;
|
||||
case '%':
|
||||
default:
|
||||
*dp++ = c;
|
||||
break;
|
||||
}
|
||||
} else *dp++ = c;
|
||||
}
|
||||
*dp = '\0';
|
||||
return dp - dest;
|
||||
}
|
||||
|
||||
|
||||
int vfprintf(dest, format, args)
|
||||
FILE *dest;
|
||||
register char *format;
|
||||
va_list args;
|
||||
{
|
||||
register char c;
|
||||
register char *tp;
|
||||
register int count = 0;
|
||||
char tempfmt[64];
|
||||
#ifndef LONGINT
|
||||
int longflag;
|
||||
#endif
|
||||
|
||||
tempfmt[0] = '%';
|
||||
while(c = *format++) {
|
||||
if(c=='%') {
|
||||
tp = &tempfmt[1];
|
||||
#ifndef LONGINT
|
||||
longflag = 0;
|
||||
#endif
|
||||
continue_format:
|
||||
switch(c = *format++) {
|
||||
case 's':
|
||||
*tp++ = c;
|
||||
*tp = '\0';
|
||||
count += fprintf(dest, tempfmt, va_arg(args, char *));
|
||||
break;
|
||||
case 'u':
|
||||
case 'x':
|
||||
case 'o':
|
||||
case 'X':
|
||||
#ifdef UNSIGNEDSPECIAL
|
||||
*tp++ = c;
|
||||
*tp = '\0';
|
||||
#ifndef LONGINT
|
||||
if(longflag)
|
||||
count += fprintf(dest, tempfmt, va_arg(args, unsigned long));
|
||||
else
|
||||
#endif
|
||||
count += fprintf(dest, tempfmt, va_arg(args, unsigned));
|
||||
break;
|
||||
#endif
|
||||
case 'd':
|
||||
case 'c':
|
||||
case 'i':
|
||||
*tp++ = c;
|
||||
*tp = '\0';
|
||||
#ifndef LONGINT
|
||||
if(longflag)
|
||||
count += fprintf(dest, tempfmt, va_arg(args, long));
|
||||
else
|
||||
#endif
|
||||
count += fprintf(dest, tempfmt, va_arg(args, int));
|
||||
break;
|
||||
case 'f':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'g':
|
||||
case 'G':
|
||||
*tp++ = c;
|
||||
*tp = '\0';
|
||||
count += fprintf(dest, tempfmt, va_arg(args, double));
|
||||
break;
|
||||
case 'p':
|
||||
*tp++ = c;
|
||||
*tp = '\0';
|
||||
count += fprintf(dest, tempfmt, va_arg(args, pointer));
|
||||
break;
|
||||
case '-':
|
||||
case '+':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '.':
|
||||
case ' ':
|
||||
case '#':
|
||||
case 'h':
|
||||
*tp++ = c;
|
||||
goto continue_format;
|
||||
case 'l':
|
||||
#ifndef LONGINT
|
||||
longflag = 1;
|
||||
*tp++ = c;
|
||||
#endif
|
||||
goto continue_format;
|
||||
case '*':
|
||||
tp += Sprintf(tp, "%d", va_arg(args, int));
|
||||
goto continue_format;
|
||||
case 'n':
|
||||
*va_arg(args, intp) = count;
|
||||
break;
|
||||
case '%':
|
||||
default:
|
||||
putc(c, dest);
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
putc(c, dest);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
vprintf(format, args)
|
||||
char *format;
|
||||
va_list args;
|
||||
{
|
||||
return vfprintf(stdout, format, args);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
fs_checkPtr(void* ptr)
|
||||
{
|
||||
if (ptr == NULL)
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"checkPtr found a NULL pointer");
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void*
|
||||
fs_malloc(size_t size)
|
||||
{
|
||||
void* ptr = NULL;
|
||||
|
||||
if (size <= 0) {
|
||||
/* Define error message - even though caller may change it */
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Allocating zero or -ve size %d", size);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#ifdef THINK_C
|
||||
ptr = (void*)NewPtr((long)size);
|
||||
s_checkPtr(ptr);
|
||||
memset(ptr,0,(size_t)size);
|
||||
#else
|
||||
ptr = (void*)calloc((size_t)size,(size_t)1);
|
||||
s_checkPtr(ptr);
|
||||
if (!ptr) out_of_memory();
|
||||
#endif
|
||||
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void*
|
||||
fs_realloc(void* ptr,size_t size)
|
||||
{
|
||||
register void* nptr = NULL;
|
||||
|
||||
if (size <= 0)
|
||||
return(NULL);
|
||||
|
||||
if (ptr == NULL)
|
||||
return(s_malloc(size));
|
||||
|
||||
#ifdef THINK_C
|
||||
nptr = NewPtr(size);
|
||||
s_checkPtr(nptr);
|
||||
BlockMove(ptr,nptr,size);
|
||||
DisposPtr(ptr);
|
||||
#else
|
||||
nptr = (void*)realloc(ptr,size);
|
||||
s_checkPtr(ptr);
|
||||
if (!ptr) out_of_memory();
|
||||
#endif
|
||||
|
||||
return(nptr);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
fs_free(void* ptr)
|
||||
{
|
||||
if (ptr != NULL)
|
||||
{
|
||||
#ifdef THINK_C
|
||||
DisposPtr(ptr);
|
||||
#else
|
||||
free(ptr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
char*
|
||||
fs_strncat(char* dst,char* src,size_t maxToAdd,size_t maxTotal)
|
||||
{
|
||||
size_t dstSize = strlen(dst);
|
||||
size_t srcSize = strlen(src);
|
||||
|
||||
if (dstSize + srcSize < maxTotal)
|
||||
return(strncat(dst,src,maxToAdd));
|
||||
else
|
||||
{ size_t truncateTo = maxTotal - dstSize - 1;
|
||||
char saveChar;
|
||||
char* result = NULL;
|
||||
|
||||
saveChar = src[truncateTo];
|
||||
src[truncateTo] = '\0';
|
||||
result = strncat(dst,src,maxToAdd);
|
||||
src[truncateTo] = saveChar;
|
||||
return(result);
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
char*
|
||||
fs_strncpy(char* s1,char* s2,long n)
|
||||
{
|
||||
s1[n-1] = '\0';
|
||||
return(strncpy(s1, s2, n - 1));
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifdef NOTUSEDANDNOTTHREADSAFE
|
||||
void
|
||||
initMyPID(void)
|
||||
{
|
||||
if (myPID == -1)
|
||||
myPID = getpid();
|
||||
}
|
||||
#endif /*NOTUSEDANDNOTTHREADSAFE*/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
warn(char* message)
|
||||
{
|
||||
#ifdef THINK_C
|
||||
Debugger();
|
||||
#else
|
||||
printf("%s\n<press return to continue>\n",message);
|
||||
getchar();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
char*
|
||||
next_arg(long* argc,char*** argv)
|
||||
{
|
||||
if ((*argc)-- > 0)
|
||||
{ char* arg = *((*argv)++);
|
||||
return(arg);
|
||||
}
|
||||
else
|
||||
{ return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
char*
|
||||
peek_arg(long* argc,char*** argv)
|
||||
{
|
||||
if ((*argc) > 0)
|
||||
return(**argv);
|
||||
else
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifdef NOTUSEDANDNOTTHREADSAFE
|
||||
char*
|
||||
readNextArg(long* argc,char*** argv,boolean* useFile,FILE* file)
|
||||
/*
|
||||
Like next_arg(), but can read arguments from a file (one line per arg).
|
||||
Note you must copy the returned value if you need access to more
|
||||
than one argument at a time.
|
||||
*/
|
||||
{
|
||||
static char buf[300];
|
||||
if (file != NULL && useFile != NULL && *useFile)
|
||||
{ if (fgets(buf,300,file) == NULL) /* nothing more on the file */
|
||||
{ *useFile = false;
|
||||
return(next_arg(argc,argv)); /* start reading regular args again */
|
||||
}
|
||||
else /* return a line from the file */
|
||||
{ buf[strlen(buf) - 1] = '\0'; /* get rid of newline */
|
||||
return(buf);
|
||||
}
|
||||
}
|
||||
else /* just read regular args from the command line */
|
||||
{ return(next_arg(argc,argv));
|
||||
}
|
||||
}
|
||||
#endif /*NOTUSEDANDNOTTHREADSAFE*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef THINK_C
|
||||
|
||||
#if THINK_C == 1
|
||||
#include <EventMgr.h>
|
||||
#endif
|
||||
|
||||
#if THINK_C == 5
|
||||
#include <Events.h>
|
||||
#endif
|
||||
|
||||
#ifdef WAIStation
|
||||
#include "CRetrievalApp.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef NOTUSEDANDNOTTHREADSAFE
|
||||
void
|
||||
beFriendly()
|
||||
{
|
||||
#ifdef never
|
||||
#ifdef THINK_C
|
||||
EventRecord macEvent;
|
||||
|
||||
static RgnHandle mouseRgn = NULL;
|
||||
long sleepTime;
|
||||
|
||||
#ifdef WAIStation
|
||||
gApplication->FrobWaitCursor();
|
||||
#endif
|
||||
|
||||
if (mouseRgn == NULL)
|
||||
mouseRgn = NewRgn();
|
||||
|
||||
sleepTime = 5;
|
||||
|
||||
WaitNextEvent(everyEvent,&macEvent,sleepTime,mouseRgn);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif /*NOTUSEDANDNOTTHREADSAFE*/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
151
prospero/lib/psrv/wais_gw/cutil.h
Normal file
151
prospero/lib/psrv/wais_gw/cutil.h
Normal file
@@ -0,0 +1,151 @@
|
||||
/*****************************************************************************
|
||||
* (c) Copyright 1992 Wide Area Information Servers, Inc *
|
||||
* of California. All rights reserved. *
|
||||
* *
|
||||
* This notice is intended as a precaution against inadvertent publication *
|
||||
* and does not constitute an admission or acknowledgement that publication *
|
||||
* has occurred or constitute a waiver of confidentiality. *
|
||||
* *
|
||||
* Wide Area Information Server software is the proprietary and *
|
||||
* confidential property of Wide Area Information Servers, Inc. *
|
||||
*****************************************************************************/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef cutil_h
|
||||
#define cutil_h
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#ifndef EXIT_SUCCESS
|
||||
/* #include <stdlib.h> */ /* Commented out so compiles on SCO */
|
||||
#endif /* ndef EXIT_SUCCESS */
|
||||
#include "cdialect.h"
|
||||
|
||||
#if defined(THINK_C) || defined(SCOUNIX)
|
||||
#include <time.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#define byte char
|
||||
|
||||
#ifndef cutil_c
|
||||
extern long myPID;
|
||||
#endif /* ndef cutil_c */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Math utilities */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef MAXLONG
|
||||
#define MAXLONG ((long)0x7FFFFFFF)
|
||||
#endif
|
||||
|
||||
#undef MAX
|
||||
#define MAX(x,y) (((x) > (y)) ? (x) : (y))
|
||||
#undef MIN
|
||||
#define MIN(x,y) (((x) < (y)) ? (x) : (y))
|
||||
#undef ABS
|
||||
#define ABS(x) (((x) < 0) ? (-(x)) : (x))
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Define boolean data type */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef boolean
|
||||
#define boolean unsigned long
|
||||
#endif /* ndef boolean */
|
||||
|
||||
#ifndef true
|
||||
#define true ((boolean)1)
|
||||
#endif /* ndef true */
|
||||
|
||||
#ifndef false
|
||||
#define false ((boolean)0)
|
||||
#endif /* ndef false */
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE true
|
||||
#endif /* ndef TRUE */
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE false
|
||||
#endif /* ndef FALSE */
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL (0L)
|
||||
#endif /* ndef NULL */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* String utlities */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#define IS_DELIMITER (1L)
|
||||
#define NOT_DELIMITER !IS_DELIMITER
|
||||
|
||||
#define STREQ(s1,s2) ((*(s1)==*(s2)) && !strcmp(s1,s2))
|
||||
#define STRNCMP(s1,s2,n) \
|
||||
((*(s1)==*(s2)) ? strncmp(s1,s2,n) : (*(s1) - *(s2)))
|
||||
|
||||
#define s_strncat(dst,src,maxToAdd,maxTotal) \
|
||||
fs_strncat((dst),(src),(maxToAdd),(maxTotal))
|
||||
#define s_strncpy(s1,s2,n) fs_strncpy((s1), (s2), (n))
|
||||
|
||||
#define safeIsAlNum(c) ((c > '`' && c < '{') || \
|
||||
(c > '/' && c < ':') || \
|
||||
(c > '@' && c < '['))
|
||||
|
||||
char* s_strdup(char* s);
|
||||
char* strtokf(char* s1,long (*isDelimiter)(long c));
|
||||
char* strtokf_isalnum(char* s1);
|
||||
boolean substrcmp(char *string1, char *string2);
|
||||
char char_downcase(unsigned long ch);
|
||||
char* string_downcase(char* word);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Printing utilities */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#define NL() printf("\n")
|
||||
|
||||
long cprintf(boolean print,char* format,...);
|
||||
void printHexByte(unsigned char h);
|
||||
char* commafy(long val,char* buf);
|
||||
char* printable_time(void);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Heap utilities */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#define s_checkPtr(ptr) fs_checkPtr(ptr)
|
||||
|
||||
#define s_malloc(size) fs_malloc(size)
|
||||
|
||||
#define s_realloc(ptr,size) fs_realloc((ptr),(size))
|
||||
#define s_free(ptr) { fs_free((char*)ptr); ptr = NULL; }
|
||||
|
||||
void fs_checkPtr(void* ptr);
|
||||
void* fs_malloc(size_t size);
|
||||
void* fs_realloc(void* ptr,size_t size);
|
||||
void fs_free(void* ptr);
|
||||
char* fs_strncat(char* dst,char* src,size_t maxToAdd,size_t maxTotal);
|
||||
char* fs_strncpy(char* s1,char* s2, long n);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Miscelaneous Utilities */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void initMyPID(void);
|
||||
void warn(char* message);
|
||||
char* next_arg(long* argc, char*** argv);
|
||||
char* peek_arg(long* argc, char*** argv);
|
||||
char* readNextArg(long* argc,char*** argv,boolean* useFile,FILE* file);
|
||||
void beFriendly(void);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#endif /* ndef cutil_h */
|
||||
|
||||
|
||||
41
prospero/lib/psrv/wais_gw/docid.h
Normal file
41
prospero/lib/psrv/wais_gw/docid.h
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
|
||||
#ifndef docid_h
|
||||
#define docid_h
|
||||
|
||||
#include "cdialect.h"
|
||||
#include "zprot.h"
|
||||
|
||||
#define COPY_WITHOUT_RESTRICTION (0L)
|
||||
#define ALL_RIGHTS_RESERVED (1L)
|
||||
#define DISTRIBUTION_RESTRICTIONS_APPLY (2L)
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
typedef struct DocID
|
||||
{ any* originalServer;
|
||||
any* originalDatabase;
|
||||
any* originalLocalID;
|
||||
any* distributorServer;
|
||||
any* distributorDatabase;
|
||||
any* distributorLocalID;
|
||||
long copyrightDisposition;
|
||||
} DocID;
|
||||
|
||||
DocID* makeDocID(void);
|
||||
DocID* copyDocID(DocID* doc);
|
||||
void freeDocID(DocID* doc);
|
||||
any* GetServer(DocID* doc);
|
||||
DocID* docIDFromAny(any* rawDocID);
|
||||
any* anyFromDocID(DocID* docID);
|
||||
any* GetDatabase(DocID* doc);
|
||||
any* GetLocalID(DocID* doc);
|
||||
long GetCopyrightDisposition(DocID* doc);
|
||||
long ReadDocID(DocID* doc, FILE* file);
|
||||
long WriteDocID(DocID* doc, FILE* file);
|
||||
boolean cmpDocIDs(DocID* d1,DocID* d2);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#endif
|
||||
|
||||
564
prospero/lib/psrv/wais_gw/futil.c
Normal file
564
prospero/lib/psrv/wais_gw/futil.c
Normal file
@@ -0,0 +1,564 @@
|
||||
/*****************************************************************************
|
||||
* (c) Copyright 1992 Wide Area Information Servers, Inc *
|
||||
* of California. All rights reserved. *
|
||||
* *
|
||||
* This notice is intended as a precaution against inadvertent publication *
|
||||
* and does not constitute an admission or acknowledgement that publication *
|
||||
* has occurred or constitute a waiver of confidentiality. *
|
||||
* *
|
||||
* Wide Area Information Server software is the proprietary and *
|
||||
* confidential property of Wide Area Information Servers, Inc. *
|
||||
*****************************************************************************/
|
||||
|
||||
/*-------------------------------------------------------------------------- */
|
||||
/*-------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef THINK_C
|
||||
|
||||
#include <pascal.h>
|
||||
#if THINK_C == 1
|
||||
#include <FileMgr.h>
|
||||
#endif
|
||||
#if THINK_C == 5
|
||||
#include <Files.h>
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#if defined(__svr4__) || defined(SCOUNIX)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include "futil.h"
|
||||
#include "panic.h"
|
||||
#include <pfs_threads.h> /* For locked_fopen etc */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Shared by all threads */
|
||||
static long numFilesCurrentlyOpen = 0;
|
||||
static long maxNumFilesOpenAtOneTime = 0;
|
||||
#if 0
|
||||
FILE*
|
||||
doSafeFOpen(char* filename,char* mode)
|
||||
{
|
||||
FILE* file = NULL;
|
||||
char realMode[100];
|
||||
|
||||
file = locked_fopen(filename,mode);
|
||||
|
||||
if (file != NULL)
|
||||
{ numFilesCurrentlyOpen++;
|
||||
if (numFilesCurrentlyOpen > maxNumFilesOpenAtOneTime)
|
||||
maxNumFilesOpenAtOneTime = numFilesCurrentlyOpen;
|
||||
/*cprintf(dbg,"fopen %ld %s\n",fileno(file),filename);*/
|
||||
}
|
||||
|
||||
return(file);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
long
|
||||
doSafeFClose(FILE* file)
|
||||
{
|
||||
if (file != NULL)
|
||||
{ numFilesCurrentlyOpen--;
|
||||
return(locked_fclose(file));
|
||||
}
|
||||
else
|
||||
return(0L);
|
||||
}
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
long
|
||||
doSafeFSeek(FILE* file,long offset,long fromWhere)
|
||||
{
|
||||
long result;
|
||||
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
|
||||
/*cprintf(dbg,"seek %ld %ld %ld\n",fileno(file),offset,fromWhere);*/
|
||||
|
||||
if (offset == 0 && fromWhere == SEEK_CUR) /* this is a nop */
|
||||
return(0);
|
||||
|
||||
result = fseek(file,offset,fromWhere);
|
||||
|
||||
/* if (result != 0)
|
||||
cprintf(dbg,"seek failed: file %ld offset %ld, fromWhere %d\n",
|
||||
fileno(file),offset,fromWhere);
|
||||
*/
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
long
|
||||
doSafeFTell(FILE* file)
|
||||
{
|
||||
long result;
|
||||
|
||||
if (file == NULL)
|
||||
return(0);
|
||||
|
||||
result = ftell(file);
|
||||
|
||||
if (result == EOF)
|
||||
panic("A seek on an index file failed.\n");
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
long
|
||||
doSafeRename(char* path1,char* path2)
|
||||
{
|
||||
|
||||
#ifdef THINK_C
|
||||
remove(path2);
|
||||
#endif
|
||||
|
||||
return(rename(path1,path2));
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
long
|
||||
writeBytes(long value,long size,FILE* stream)
|
||||
{
|
||||
long i;
|
||||
long answer;
|
||||
|
||||
if ((size < sizeof(long)) && ((value >> (size * 8)) != 0))
|
||||
panic("In a call to writeBytes, the value %ld can not be represented in %ld bytes",value,size);
|
||||
|
||||
for (i = size - 1; i >= 0; i--)
|
||||
answer = putc((value >> (i * 8)) & 0xFF,stream);
|
||||
|
||||
if (ferror(stream) != 0)
|
||||
panic("Write failed");
|
||||
|
||||
return(answer);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifdef NEVERDEFINEDUNUSED
|
||||
long
|
||||
readBytes(long n,FILE* stream)
|
||||
{
|
||||
long answer = 0;
|
||||
unsigned long ch;
|
||||
long i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{ ch = fgetc(stream); /* Note - no timeout */
|
||||
if (ch == EOF)
|
||||
return(EOF);
|
||||
answer = (answer << 8) + (unsigned char)ch;
|
||||
}
|
||||
return(answer);
|
||||
}
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
long
|
||||
readBytesFromMemory(long n,unsigned char* block)
|
||||
{
|
||||
long answer = 0;
|
||||
unsigned char ch;
|
||||
long i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{ ch = *(block++);
|
||||
answer = (answer << 8) + ch;
|
||||
}
|
||||
return(answer);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static char*
|
||||
cleanPath(char* filename)
|
||||
{
|
||||
|
||||
#ifdef THINK_C
|
||||
return(filename);
|
||||
#endif /* def THINK_C */
|
||||
|
||||
char* beginningPtr = strstr(filename,"/../");
|
||||
if (beginningPtr != NULL)
|
||||
{ char *ptr;
|
||||
for (ptr = beginningPtr - 1; ptr >= filename; ptr--)
|
||||
{ if (*ptr == '/')
|
||||
{ strcpy(ptr,beginningPtr + strlen("/../") - 1);
|
||||
cleanPath(filename);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
beginningPtr = strstr(filename,"/./");
|
||||
if (beginningPtr != NULL)
|
||||
{ strcpy(beginningPtr,beginningPtr + strlen("/./") - 1);
|
||||
cleanPath(filename);
|
||||
}
|
||||
|
||||
return(filename);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
char*
|
||||
truename(char* filename,char* fullPath)
|
||||
{
|
||||
|
||||
#ifdef THINK_C
|
||||
|
||||
strcpy(fullPath,filename);
|
||||
return(fullPath);
|
||||
|
||||
#else
|
||||
|
||||
if (filename[0] == '/')
|
||||
{ strcpy(fullPath,filename);
|
||||
cleanPath(fullPath);
|
||||
return(fullPath);
|
||||
}
|
||||
else
|
||||
{ getwd(fullPath);
|
||||
s_strncat(fullPath,"/",MAX_FILENAME_LEN,MAX_FILENAME_LEN);
|
||||
s_strncat(fullPath,filename,MAX_FILENAME_LEN,MAX_FILENAME_LEN);
|
||||
cleanPath(fullPath);
|
||||
return(fullPath);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
char*
|
||||
pathnameName(char* pathname)
|
||||
{
|
||||
|
||||
#ifdef THINK_C
|
||||
char *answer = strrchr(pathname,':');
|
||||
#else
|
||||
char *answer = strrchr(pathname,'/');
|
||||
#endif
|
||||
|
||||
if (answer == NULL)
|
||||
return(pathname);
|
||||
return(answer + 1);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
char*
|
||||
pathnameDirectory(char* pathname,char* destination)
|
||||
{
|
||||
#ifdef THINK_C
|
||||
n char *dirptr = strrchr(pathname,':');
|
||||
#else
|
||||
char *dirptr = strrchr(pathname,'/');
|
||||
#endif
|
||||
|
||||
if (dirptr == NULL)
|
||||
{
|
||||
#ifdef THINK_C
|
||||
strncpy(destination,pathname,MAX_FILENAME_LEN);
|
||||
#else
|
||||
strncpy(destination,"./",MAX_FILENAME_LEN);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{ strncpy(destination,pathname,MAX_FILENAME_LEN);
|
||||
destination[dirptr - pathname + 1] = '\0';
|
||||
}
|
||||
|
||||
return(destination);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifdef NOTUSEDANDNOTTHREADSAFE
|
||||
char*
|
||||
mergePathnames(char* pathname,char* directory)
|
||||
{
|
||||
static char answer[MAX_FILENAME_LEN + 1];
|
||||
|
||||
if ((pathname[0] == '/') || (NULL == directory) || directory[0] == '\0')
|
||||
return(pathname);
|
||||
else
|
||||
{ answer[0] = '\0';
|
||||
strncat(answer,directory,MAX_FILENAME_LEN);
|
||||
|
||||
#ifdef THINK_C
|
||||
if (directory[strlen(directory) - 1] != ':')
|
||||
strncat(answer,":",MAX_FILENAME_LEN);
|
||||
#else
|
||||
if (directory[strlen(directory) - 1] != '/')
|
||||
strncat(answer,"/",MAX_FILENAME_LEN);
|
||||
#endif
|
||||
strncat(answer,pathname,MAX_FILENAME_LEN);
|
||||
}
|
||||
|
||||
return(answer);
|
||||
}
|
||||
#endif /*NOTUSEDANDNOTTHREADSAFE*/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
boolean
|
||||
directoryP(char* f)
|
||||
/* XXX strangely, this fails if f = "". It says that f is a directory */
|
||||
{
|
||||
#ifdef THINK_C
|
||||
return(false);
|
||||
#else
|
||||
struct stat stbuf;
|
||||
if (f == NULL)
|
||||
return(FALSE);
|
||||
else if (stat(f,&stbuf) == -1)
|
||||
return(FALSE);
|
||||
else if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
|
||||
return(true);
|
||||
else
|
||||
return(FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
boolean
|
||||
fileP(char* f)
|
||||
{
|
||||
if (f == NULL)
|
||||
return(false);
|
||||
|
||||
#ifdef THINK_C
|
||||
return(probeFile(f));
|
||||
#else
|
||||
{ struct stat stbuf;
|
||||
if (stat(f,&stbuf) == -1)
|
||||
return(FALSE);
|
||||
else if (!((stbuf.st_mode & S_IFMT) == S_IFDIR))
|
||||
return(true);
|
||||
else
|
||||
return(FALSE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
boolean
|
||||
probeFile(char* filename)
|
||||
{
|
||||
if (filename == NULL)
|
||||
return(false);
|
||||
|
||||
#ifdef THINK_C
|
||||
|
||||
{ FILE* f;
|
||||
f = locked_fopen(filename,"r");
|
||||
if (f == NULL)
|
||||
return(false);
|
||||
else
|
||||
{ locked_fclose_A(f,filename,TRUE);
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
if (access(filename,R_OK) == 0)
|
||||
return(true);
|
||||
else
|
||||
return(false);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
boolean
|
||||
probeFilePossiblyCompressed(char* filename)
|
||||
{
|
||||
if (filename == NULL)
|
||||
return(false);
|
||||
else if (!probeFile(filename))
|
||||
{ char buffer[MAX_FILENAME_LEN * 2];
|
||||
strcpy(buffer,filename);
|
||||
strcat(buffer,".Z");
|
||||
return(probeFile(buffer));
|
||||
}
|
||||
else
|
||||
return(true);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
boolean
|
||||
touchFile(char* filename)
|
||||
{
|
||||
FILE *stream = NULL;
|
||||
if (filename == NULL)
|
||||
return(false);
|
||||
stream = locked_fopen(filename,"a");
|
||||
if (stream == NULL)
|
||||
return(false);
|
||||
else
|
||||
{ locked_fclose_A(stream,filename,FALSE);
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
long
|
||||
fileLength(FILE* stream)
|
||||
{
|
||||
long position;
|
||||
long end = -1;
|
||||
if (stream == NULL)
|
||||
return(-1);
|
||||
position = ftell(stream);
|
||||
safeFSeek(stream,0L,SEEK_END);
|
||||
end = ftell(stream);
|
||||
safeFSeek(stream,position,SEEK_SET);
|
||||
return(end);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
getFileDates(char* filename,time_t* createDate,time_t* modDate)
|
||||
{
|
||||
#ifdef THINK_C
|
||||
*createDate = *modDate = 0;
|
||||
#else
|
||||
struct stat buf;
|
||||
|
||||
if (stat(filename,&buf) != 0)
|
||||
panic("could not stat %s",filename);
|
||||
|
||||
*modDate = buf.st_mtime;
|
||||
*createDate = buf.st_mtime; /* no separate creation date maintained in
|
||||
unix! */
|
||||
#endif
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef NOTUSEDANDNOTTHREADSAFE
|
||||
char*
|
||||
currentUserName(void)
|
||||
{
|
||||
static char answer[200];
|
||||
char hostname[120];
|
||||
|
||||
#ifdef THINK_C
|
||||
|
||||
strcpy(answer,"MAC");
|
||||
|
||||
#else
|
||||
|
||||
#include <pwd.h>
|
||||
|
||||
assert(MASTER_IS_ONLY_UNTHREAD); /*getpwuid MT-Unsafe*/
|
||||
struct passwd *pwent = getpwuid(getuid());
|
||||
strncpy(answer,pwent->pw_name,200);
|
||||
strncat(answer,"@",200);
|
||||
gethostname(hostname,120);
|
||||
strncat(answer,hostname,200);
|
||||
|
||||
#endif
|
||||
|
||||
return(answer);
|
||||
}
|
||||
#endif /*NOTUSEDANDNOTTHREADSAFE*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifdef NOTUSEDANDNOTIMEOUTONREAD
|
||||
boolean
|
||||
readStringFromFile(FILE* stream,char* array,long arrayLength)
|
||||
{
|
||||
long ch;
|
||||
long count = 0;
|
||||
|
||||
array[0] = '\0';
|
||||
while (true)
|
||||
{ ch = fgetc(stream); /* Note no timeout */
|
||||
if(ch == EOF)
|
||||
{ array[count] = '\0';
|
||||
return(false);
|
||||
}
|
||||
else if (count == arrayLength)
|
||||
{ array[count] = '\0';
|
||||
return(false);
|
||||
}
|
||||
else if('\0' == ch)
|
||||
{ array[count] = '\0';
|
||||
return(true);
|
||||
}
|
||||
else
|
||||
array[count++] = ch;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Probably works, but unused */
|
||||
#if 0
|
||||
FILE*
|
||||
openTempFile(char* dir,char* root,char* fullName,char* mode)
|
||||
/* given dir and mode, return a file pointer to the file, fullName is the
|
||||
full name of the file including dir. The leaf of the name begins with
|
||||
root. Only makes sense if mode is a write or append mode
|
||||
*/
|
||||
{
|
||||
FILE* f;
|
||||
|
||||
if (dir == NULL)
|
||||
dir = ".";
|
||||
|
||||
if (root == NULL)
|
||||
root = "temp";
|
||||
|
||||
if (!directoryP(dir))
|
||||
return(NULL);
|
||||
|
||||
assert(P_IS_THIS_THREAD_MASTER()); /* random is MT-Unsafe */
|
||||
for(;;) {
|
||||
sprintf(fullName,"%s/%s%d.%d",dir,root,getpid(),random() % 10000);
|
||||
if ((f = locked_fopen(fullName,"r")) == NULL) {
|
||||
/* no file there to read, we're ok */
|
||||
return locked_fopen(fullName, mode);
|
||||
}
|
||||
else
|
||||
locked_fclose(f,fullName, TRUE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
growFile(FILE* file,long length)
|
||||
{
|
||||
long currentLength;
|
||||
safeFSeek(file,0L,SEEK_END);
|
||||
currentLength = safeFTell(file);
|
||||
safeFSeek(file,length - currentLength,SEEK_END);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
97
prospero/lib/psrv/wais_gw/futil.h
Normal file
97
prospero/lib/psrv/wais_gw/futil.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/*****************************************************************************
|
||||
* (c) Copyright 1992 Wide Area Information Servers, Inc *
|
||||
* of California. All rights reserved. *
|
||||
* *
|
||||
* This notice is intended as a precaution against inadvertent publication *
|
||||
* and does not constitute an admission or acknowledgement that publication *
|
||||
* has occurred or constitute a waiver of confidentiality. *
|
||||
* *
|
||||
* Wide Area Information Server software is the proprietary and *
|
||||
* confidential property of Wide Area Information Servers, Inc. *
|
||||
*****************************************************************************/
|
||||
|
||||
/*-------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef futil_h
|
||||
#define futil_h
|
||||
|
||||
#include "cdialect.h"
|
||||
#include "cutil.h"
|
||||
|
||||
/*-------------------------------------------------------------------------- */
|
||||
|
||||
/* the maximum length of any filename in the system */
|
||||
#define MAX_FILENAME_LEN (255L)
|
||||
|
||||
/* arguments for fseek, which aren't defined on all systems */
|
||||
#ifndef SEEK_SET
|
||||
#define SEEK_SET (0L)
|
||||
#define SEEK_CUR (1L)
|
||||
#define SEEK_END (2L)
|
||||
#endif /* ndef SEEK_SET */
|
||||
|
||||
/* allow NeXT's to check if the file's mode indicates it's a directory */
|
||||
#if (defined(NeXT) && !(defined(S_ISDIR)))
|
||||
#define S_ISDIR(f_mode) ((f_mode) & S_IFDIR)
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------- */
|
||||
|
||||
/* the following functions are "safe" versions of the standard fileio
|
||||
utilities. They should be called through the macros rather than
|
||||
actually calling the functions themselves
|
||||
*/
|
||||
/* Replaced by locked_{fopen,fclose} */
|
||||
#if 0
|
||||
#define safeFOpen(name,mode) doSafeFOpen((name),(mode))
|
||||
#define safeFClose(file) { doSafeFClose((FILE*)(file)); \
|
||||
(file) = NULL;}
|
||||
#endif
|
||||
#define safeFSeek(file,offset,whereFrom) \
|
||||
doSafeFSeek((file),(offset),(whereFrom))
|
||||
#define safeFTell(file) doSafeFTell((file))
|
||||
#define safeRename(path1,path2) doSafeRename((path1),(path2))
|
||||
#if 0
|
||||
FILE* doSafeFOpen(char* fileName,char* mode);
|
||||
long doSafeFClose(FILE* file);
|
||||
#endif
|
||||
long doSafeFSeek(FILE* file,long offset,long wherefrom);
|
||||
long doSafeFTell(FILE* file);
|
||||
|
||||
|
||||
/* these functions read and write arbitrary numbers of bytes in
|
||||
an architecture independent fashion
|
||||
*/
|
||||
long writeBytes(long value,long numBytes,FILE* stream);
|
||||
long readBytes(long numBytes,FILE *stream);
|
||||
long readBytesFromMemory(long numBytes,unsigned char* block);
|
||||
|
||||
|
||||
/* these routines help manage unix style path names */
|
||||
char *truename(char *filename,char *full_path);
|
||||
char *pathnameName(char *pathname);
|
||||
char *pathnameDirectory(char *pathname,char *destination);
|
||||
char *mergePathnames(char *pathname,char *directory);
|
||||
|
||||
|
||||
/* set and get characteristics of a file or directory*/
|
||||
boolean directoryP(char* f);
|
||||
boolean fileP(char* f);
|
||||
boolean probeFile(char *filename);
|
||||
boolean probeFilePossiblyCompressed(char *filename);
|
||||
boolean touchFile(char *filename);
|
||||
long fileLength(FILE* stream);
|
||||
void getFileDates(char* filename,time_t* createDate,time_t* modDate);
|
||||
|
||||
|
||||
/* miscellanious routines */
|
||||
char *currentUserName(void);
|
||||
boolean readStringFromFile(FILE* stream,char* array,long array_length);
|
||||
#if 0
|
||||
FILE* openTempFile(char* dir,char* root,char* fullName,char* mode);
|
||||
#endif
|
||||
void growFile(FILE* file,long len);
|
||||
|
||||
/*-------------------------------------------------------------------------- */
|
||||
|
||||
#endif /* ndef futil_h */
|
||||
101
prospero/lib/psrv/wais_gw/ietftype.c
Normal file
101
prospero/lib/psrv/wais_gw/ietftype.c
Normal file
@@ -0,0 +1,101 @@
|
||||
/* 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 "ietftype.h"
|
||||
#include <pfs.h>
|
||||
#include <mitra_macros.h>
|
||||
#include <psrv.h> /* includes global declarations of
|
||||
ietftype_count and ietftype_max to be read.
|
||||
*/
|
||||
|
||||
static IETFTYPE lfree = NULL; /* Free ietftypes */
|
||||
/* These are global shared variables which will be read by dirsrv.c
|
||||
Too bad C doesn't have better methods for structuring such global data. */
|
||||
int ietftype_count = 0;
|
||||
int ietftype_max = 0;
|
||||
|
||||
|
||||
/* Syntactically same as atput in goph_gw_dsdb.c */
|
||||
PATTRIB ietftype_atput(IETFTYPE it, char *name)
|
||||
{
|
||||
PATTRIB at;
|
||||
|
||||
/* Fails if no arguments -- at = vatbuild(name, ap); */
|
||||
at = atalloc();
|
||||
at->aname = stcopy(name);
|
||||
at->avtype = ATR_SEQUENCE;
|
||||
at->nature = ATR_NATURE_APPLICATION;
|
||||
at->precedence = ATR_PREC_OBJECT;
|
||||
APPEND_ITEM(at, it->prosperotype);
|
||||
return at;
|
||||
}
|
||||
|
||||
/************* Standard routines to alloc, free and copy *************/
|
||||
/*
|
||||
* ietftype_alloc - allocate and initialize IETFTYPE structure
|
||||
*
|
||||
* returns a pointer to an initialized structure of type
|
||||
* IETFTYPE. If it is unable to allocate such a structure, it
|
||||
* signals out_of_memory();
|
||||
*/
|
||||
|
||||
IETFTYPE
|
||||
ietftype_alloc()
|
||||
{
|
||||
IETFTYPE thistype;
|
||||
|
||||
TH_STRUC_ALLOC(ietftype,IETFTYPE,thistype);
|
||||
thistype->standardtype=NULL;
|
||||
thistype->waistype=NULL;
|
||||
thistype->prosperotype=NULL;
|
||||
return(thistype);
|
||||
}
|
||||
|
||||
/*
|
||||
* ietftype_free - free a IETFTYPE structure
|
||||
*
|
||||
* ietftype_free takes a pointer to a IETFTYPE structure and adds it to
|
||||
* the free list for later reuse.
|
||||
*/
|
||||
void
|
||||
ietftype_free(IETFTYPE thistype)
|
||||
{
|
||||
if (thistype->standardtype)
|
||||
{ stfree(thistype->standardtype); thistype->standardtype = NULL;}
|
||||
if (thistype->waistype)
|
||||
{ stfree(thistype->waistype); thistype->waistype = NULL;}
|
||||
if (thistype->prosperotype)
|
||||
{ atfree(thistype->prosperotype); thistype->prosperotype = NULL;}
|
||||
TH_STRUC_FREE(ietftype,IETFTYPE,thistype);
|
||||
}
|
||||
|
||||
/*
|
||||
* ietftype_lfree - free a linked list of IETFTYPE structures.
|
||||
*
|
||||
* ietftype_lfree takes a pointer to a ietftype structure frees it and
|
||||
* any linked
|
||||
* IETFTYPE structures. It is used to free an entire list of IETFTYPE
|
||||
* structures.
|
||||
*/
|
||||
void
|
||||
ietftype_lfree(IETFTYPE thistype)
|
||||
{
|
||||
TH_STRUC_LFREE(IETFTYPE,thistype,ietftype_free);
|
||||
}
|
||||
|
||||
void
|
||||
ietftype_freespares()
|
||||
/* This is used for ietftypes to free up space in the child */
|
||||
{
|
||||
IETFTYPE instance;
|
||||
|
||||
while((instance = lfree) != NULL) {
|
||||
/* Note this is slightly lazy, the thistype list is broken during loop*/
|
||||
lfree = instance->next;
|
||||
free(lfree); /* Matches malloc in STRUC_ALLOC1*/
|
||||
ietftype_max--;
|
||||
}
|
||||
}
|
||||
|
||||
32
prospero/lib/psrv/wais_gw/ietftype.h
Normal file
32
prospero/lib/psrv/wais_gw/ietftype.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef _rmg_ietftype_h
|
||||
#define _rmg_ietftype_h
|
||||
|
||||
#include <pfs.h> /* For ALLOCATOR_CONSISTENCY_CHECK*/
|
||||
#include <pfs_threads.h>
|
||||
|
||||
struct ietftype {
|
||||
#ifdef ALLOCATOR_CONSISTENCY_CHECK
|
||||
int consistency;
|
||||
#endif
|
||||
char *standardtype;
|
||||
char *waistype;
|
||||
PATTRIB prosperotype;
|
||||
struct ietftype *next;
|
||||
struct ietftype *previous;
|
||||
};
|
||||
|
||||
typedef struct ietftype *IETFTYPE;
|
||||
typedef struct ietftype IETFTYPE_ST;
|
||||
|
||||
|
||||
|
||||
extern PATTRIB ietftype_atput(IETFTYPE it, char *name);
|
||||
extern IETFTYPE ietftype_alloc();
|
||||
extern void ietftype_free(IETFTYPE it);
|
||||
extern void ietftype_lfree(IETFTYPE it);
|
||||
extern IETFTYPE ietftype_copy(IETFTYPE f,int r);
|
||||
#ifdef PFS_THREADS
|
||||
extern p_th_mutex p_th_mutexIETFTYPE;
|
||||
#endif
|
||||
|
||||
#endif /*_rmg_ietftype_h*/
|
||||
90
prospero/lib/psrv/wais_gw/ietftype_parse.c
Normal file
90
prospero/lib/psrv/wais_gw/ietftype_parse.c
Normal file
@@ -0,0 +1,90 @@
|
||||
#define IETFTYPEFILE "/usr/local/lib/ietftypes"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <pfs.h>
|
||||
#include "ietftype.h"
|
||||
#include <string.h>
|
||||
#include <pfs_threads.h>
|
||||
#include <mitra_macros.h>
|
||||
|
||||
/* Shared across threads */
|
||||
IETFTYPE IETFTypes = NULL;
|
||||
void ietftype_init();
|
||||
|
||||
/* Return the IETF type corresponding to the waistype - or NULL if not found*/
|
||||
IETFTYPE wais_2_ietftype(char *waistype)
|
||||
{
|
||||
IETFTYPE thistype;
|
||||
|
||||
if (IETFTypes == NULL) {
|
||||
#ifndef PFS_THREADS
|
||||
/* In threaded version, this is done at init time */
|
||||
ietftype_init();
|
||||
if (IETFTypes == NULL)
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
thistype = IETFTypes;
|
||||
TH_FIND_STRING_LIST_CASE(thistype, waistype, waistype, IETFTYPE);
|
||||
/* temp = NULL or ietftype to return */
|
||||
return (thistype);
|
||||
}
|
||||
|
||||
/* Open file of types and initialise data structure */
|
||||
void ietftype_init() {
|
||||
FILE *st;
|
||||
IETFTYPE thistype = NULL;
|
||||
char ourlinebuf[1024];
|
||||
int i;
|
||||
char *tag = NULL;
|
||||
char *value = NULL;
|
||||
char *cp;
|
||||
|
||||
assert(P_IS_THIS_THREAD_MASTER());
|
||||
|
||||
if ((st = fopen(IETFTYPEFILE, "r")) == NULL) /* Not locked_fclose - before mutexes */
|
||||
/* Should set an error string */
|
||||
return;
|
||||
|
||||
while ((cp = fgets(ourlinebuf, sizeof(ourlinebuf), st)) != NULL) {
|
||||
if (ourlinebuf[0] == '\n')
|
||||
continue;
|
||||
if (ourlinebuf[0] == '#') { /* Seperator & comment*/
|
||||
thistype = NULL;
|
||||
continue;
|
||||
}
|
||||
if (thistype == NULL) {
|
||||
thistype = ietftype_alloc();
|
||||
APPEND_ITEM(thistype, IETFTypes);
|
||||
}
|
||||
/*Would be nice if could skip trailing white space in qsscanf*/
|
||||
for ( i = strlen(ourlinebuf) - 1;
|
||||
strchr(" \t\n\r",ourlinebuf[i]);
|
||||
i--)
|
||||
ourlinebuf[i] = '\0';
|
||||
|
||||
if (qsscanf(ourlinebuf, "%&[^:= \t]%*[:= \t]%r",&tag,&value) == 2) {
|
||||
#define tt1(tgstr,field) \
|
||||
if (stcaseequal(tag,tgstr)) { \
|
||||
thistype->field = stcopyr(value,thistype->field); \
|
||||
continue; \
|
||||
}
|
||||
|
||||
tt1("ietf",standardtype);
|
||||
tt1("wais",waistype);
|
||||
if (stcaseequal(tag,"prospero")) {
|
||||
PATTRIB at=ietftype_atput(thistype,"OBJECT-INTERPRETATION");
|
||||
assert(P_IS_THIS_THREAD_MASTER());
|
||||
for(cp=strtok(value,"/");cp != NULL; cp=strtok(NULL,"/"))
|
||||
tkappend(cp,at->value.sequence);
|
||||
}
|
||||
/* Add other fields here as we need them */
|
||||
/* Ignores unrecognized fields */
|
||||
}
|
||||
/* Ignores syntactically incorrect lines */
|
||||
}
|
||||
stfree(tag);
|
||||
fclose(st);
|
||||
}
|
||||
|
||||
6
prospero/lib/psrv/wais_gw/ietftype_parse.h
Normal file
6
prospero/lib/psrv/wais_gw/ietftype_parse.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef IETFTYPE_PARSE_H
|
||||
#define IETFTYPE_PARSE_H
|
||||
#include "ietftype.h"
|
||||
extern IETFTYPE wais_2_ietftype(char *waistype);
|
||||
extern void ietftype_init(void);
|
||||
#endif /*IETFTYPE_PARSE_H*/
|
||||
127
prospero/lib/psrv/wais_gw/ietftypes
Normal file
127
prospero/lib/psrv/wais_gw/ietftypes
Normal file
@@ -0,0 +1,127 @@
|
||||
# This file defines the relationships between different types
|
||||
# new records can be added anywhere,
|
||||
# Order is insignificant, except that this file is searched in order,
|
||||
# so converting x=a to y will return the value for y, from the first record
|
||||
# where x=a
|
||||
#
|
||||
ietf text/plain
|
||||
wais TEXT
|
||||
prospero DOCUMENT/TEXT/ASCII
|
||||
gopher0 0
|
||||
#
|
||||
ietf application/gopher-menu
|
||||
prospero DOCUMENT
|
||||
gopher0 1
|
||||
#
|
||||
gopher0 4
|
||||
prospero EMBEDDED/BINHEX/DATA
|
||||
#
|
||||
# The Generic Binaries should be Gopher type 9
|
||||
gopher0 9
|
||||
prospero DATA
|
||||
#
|
||||
gopher0 5
|
||||
prospero DATA
|
||||
#
|
||||
gopher0 6
|
||||
prospero EMBEDDED/UUENCODE/DATA
|
||||
#
|
||||
gopher0 7
|
||||
prospero SEARCH
|
||||
#
|
||||
gopher0 8
|
||||
prospero PORTAL
|
||||
#
|
||||
gopher0 I
|
||||
prospero IMAGE
|
||||
#
|
||||
gopher0 :
|
||||
prospero IMAGE
|
||||
#
|
||||
gopher0 M
|
||||
ietf multipart/composite?
|
||||
wais MIME
|
||||
prospero DOCUMENT/MIME
|
||||
#
|
||||
gopher0 T
|
||||
prospero PORTAL
|
||||
#
|
||||
gopher0 g
|
||||
prospero IMAGE/GIF
|
||||
wais GIF
|
||||
#
|
||||
gopher0 s
|
||||
prospero SOUND
|
||||
#
|
||||
gopher0 <
|
||||
prospero SOUND
|
||||
#
|
||||
# Uncommon type in Iowa gopher - Panda
|
||||
gopher0 i
|
||||
prospero VOID
|
||||
#
|
||||
gopher0 !
|
||||
prospero VOID
|
||||
#
|
||||
gopher0 ;
|
||||
prospero VIDEO
|
||||
#
|
||||
# CSO
|
||||
gopher0 2
|
||||
#
|
||||
# Error
|
||||
gopher0 3
|
||||
#
|
||||
# Whois
|
||||
gopher0 w
|
||||
#
|
||||
# Possibly an error message type
|
||||
gopher0 -
|
||||
#########################################################################
|
||||
# WAIS types for which incomplete information is available #
|
||||
#########################################################################
|
||||
#
|
||||
#
|
||||
wais EXCEL
|
||||
#
|
||||
wais DVI
|
||||
#
|
||||
wais MS-EXCEL
|
||||
#
|
||||
wais MS-POWERPOINT
|
||||
#
|
||||
wais MS-WORD
|
||||
# Aldus Persuasion
|
||||
wais PERSUASION
|
||||
#
|
||||
wais PICT
|
||||
#
|
||||
wais PS
|
||||
#
|
||||
wais QUICKTIME
|
||||
#
|
||||
wais TEXT-FTP
|
||||
#
|
||||
wais TIFF
|
||||
# Wais question format
|
||||
wais WQST
|
||||
# Wais Source format
|
||||
# this may end up being special cased to generate appropriate pointers
|
||||
wais WSRC
|
||||
ietf text/plain
|
||||
prospero DOCUMENT/TEXT/ASCII
|
||||
gopher0 0
|
||||
#
|
||||
#########################################################################
|
||||
# GOPHER0 #
|
||||
# #
|
||||
# The next bunch are gopher0 types that correspond to other #
|
||||
# types that are already listed above. #
|
||||
#########################################################################
|
||||
gopher0 e
|
||||
ietf text/plain
|
||||
wais TEXT
|
||||
#
|
||||
gopher0 c
|
||||
ietf text/plain
|
||||
wais TEXT
|
||||
896
prospero/lib/psrv/wais_gw/inface.c
Normal file
896
prospero/lib/psrv/wais_gw/inface.c
Normal file
@@ -0,0 +1,896 @@
|
||||
/*****************************************************************************
|
||||
* (c) Copyright 1992 Wide Area Information Servers, Inc *
|
||||
* of California. All rights reserved. *
|
||||
* *
|
||||
* This notice is intended as a precaution against inadvertent publication *
|
||||
* and does not constitute an admission or acknowledgement that publication *
|
||||
* has occurred or constitute a waiver of confidentiality. *
|
||||
* *
|
||||
* Wide Area Information Server software is the proprietary and *
|
||||
* confidential property of Wide Area Information Servers, Inc. *
|
||||
*****************************************************************************/
|
||||
|
||||
#define INPROSPERO
|
||||
|
||||
#include "zutil.h"
|
||||
#include "zprot.h"
|
||||
#include "wprot.h"
|
||||
#include "wmessage.h"
|
||||
#include "inface.h"
|
||||
#include "sockets.h"
|
||||
#include "waislog.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef INPROSPERO
|
||||
#include <pfs.h>
|
||||
#include <perrno.h>
|
||||
#include "buffalloc.h"
|
||||
#endif
|
||||
#include <stdlib.h> /* For malloc and free */
|
||||
|
||||
/* from the Prospero library. Also prototyped in <pfs.h> */
|
||||
extern const char *unixerrstr(void);
|
||||
|
||||
static char Err_Connect[]="WAIS gateway unable to connect to: %s(%s)";
|
||||
|
||||
#define CHARS_PER_PAGE 10000 /* number of chars retrieved in each request */
|
||||
#define RETURN(val) {retval = val; goto cleanup; }
|
||||
|
||||
#define WAIS_verbose FALSE
|
||||
#define TIMEOUT_WAIS_READ 20
|
||||
|
||||
#ifdef COMMENT
|
||||
main()
|
||||
{
|
||||
char* server = "server.wais.com";
|
||||
char* service = "210";
|
||||
char* database = "smithsonian-pictures";
|
||||
char* query = "gorilla";
|
||||
WAISSearchResponse* response;
|
||||
WAISDocumentHeader* header;
|
||||
any* text;
|
||||
|
||||
response = waisQuery(server, service, database, query);
|
||||
printf("%s\n",
|
||||
p_err_string;
|
||||
);
|
||||
if (response != NULL) {
|
||||
header = response->DocHeaders[1];
|
||||
text =
|
||||
waisRetrieve(server, service, database,
|
||||
header->DocumentID,
|
||||
"TEXT", /* JFIF, THNL */
|
||||
header->DocumentLength);
|
||||
printf("%s", text->bytes);
|
||||
printf("%s\n", p_err_string);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void showDiags(diagnosticRecord **d);
|
||||
|
||||
static long interpret_message(char* request_message,
|
||||
long request_length, /* length of the buffer */
|
||||
char* response_message,
|
||||
long response_buffer_length,
|
||||
FILE* connection,
|
||||
boolean verbose);
|
||||
|
||||
static long transport_message(FILE* connection,
|
||||
char* request_message,
|
||||
long request_length,
|
||||
char* response_message,
|
||||
long response_buffer_length);
|
||||
|
||||
static long initConnection(char* inBuffer,
|
||||
char* outBuffer,
|
||||
long bufferSize,
|
||||
FILE* connection,
|
||||
char* userInfo);
|
||||
|
||||
static char* generate_search_apdu(char* buff,
|
||||
long* buff_len,
|
||||
char* seed_words,
|
||||
char* database_name,
|
||||
DocObj** docobjs,
|
||||
long maxDocsRetrieved);
|
||||
|
||||
static char* generate_retrieval_apdu(char* buff,
|
||||
long* buff_len,
|
||||
any* docID,
|
||||
long chunk_type,
|
||||
long start,
|
||||
long end,
|
||||
char* type,
|
||||
char* database_name);
|
||||
|
||||
/* return NULL pointer in event of an error */
|
||||
|
||||
WAISSearchResponse* waisQuery (char* server_name,
|
||||
char* service,
|
||||
char* database,
|
||||
char* keywords)
|
||||
{
|
||||
/*FIX:Mitra:leaks, malloc,p_err_string */
|
||||
char userInfo[500];
|
||||
char hostname[80];
|
||||
char domainname[80];
|
||||
WAISMSGBUFF request_msg = NULL; /* arbitrary message limit */
|
||||
WAISMSGBUFF response_msg = NULL; /* arbitrary message limit */
|
||||
char *request_message = NULL;
|
||||
char *response_message = NULL;
|
||||
long request_buffer_length; /* how of the request is left */
|
||||
SearchResponseAPDU *query_response;
|
||||
WAISSearchResponse *query_response_info;
|
||||
long Max_Docs = 40, message_length = MAX_MESSAGE_LENGTH;
|
||||
FILE *connection = NULL;
|
||||
WAISSearchResponse *retval;
|
||||
|
||||
if (server_name[0] == '\0' && service[0] == '\0')
|
||||
connection = NULL; /* do local searching */
|
||||
else { /* remote search, fill in defaults*/
|
||||
if (server_name[0] == '\0')
|
||||
/*default to local machine*/
|
||||
gethostname(server_name,MAX_SERVER_LENGTH);
|
||||
if (service[0] == '\0')
|
||||
strcpy(service, Z39_50_SERVICE); /* default */
|
||||
if ((connection = connectToServer(server_name,atoi(service))) == NULL){
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
Err_Connect,
|
||||
server_name, service);
|
||||
RETURN(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
request_msg = waismsgbuff_alloc(); request_message = request_msg->buff;
|
||||
response_msg = waismsgbuff_alloc(); response_message = response_msg->buff;
|
||||
|
||||
gethostname(hostname, 80);
|
||||
getdomainname(domainname, 80);
|
||||
|
||||
sprintf(userInfo, "prospero gateway from host: %s.%s", hostname, domainname);
|
||||
|
||||
if((message_length =
|
||||
initConnection(request_message,
|
||||
response_message,
|
||||
message_length,
|
||||
connection,
|
||||
userInfo)) <= 0) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string, Err_Connect,
|
||||
server_name, service);
|
||||
RETURN(NULL);
|
||||
}
|
||||
|
||||
request_buffer_length = message_length; /* how of the request is left */
|
||||
if(NULL ==
|
||||
generate_search_apdu(request_message + HEADER_LENGTH,
|
||||
&request_buffer_length,
|
||||
keywords, database, NULL, Max_Docs)) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Error creating search APDU: request too large");
|
||||
RETURN(NULL);
|
||||
}
|
||||
|
||||
if(0 ==
|
||||
interpret_message(request_message,
|
||||
message_length - request_buffer_length,
|
||||
response_message,
|
||||
message_length,
|
||||
connection,
|
||||
WAIS_verbose /* true verbose */
|
||||
)) { /* perhaps the server shut down on us */
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Unable to deliver message");
|
||||
RETURN(NULL);
|
||||
}
|
||||
|
||||
readSearchResponseAPDU(&query_response, response_message + HEADER_LENGTH);
|
||||
query_response_info =
|
||||
((WAISSearchResponse *)query_response->DatabaseDiagnosticRecords);
|
||||
freeSearchResponseAPDU( query_response);
|
||||
RETURN (query_response_info);
|
||||
|
||||
cleanup:
|
||||
if (connection) fclose(connection);
|
||||
waismsgbuff_free(request_msg);
|
||||
waismsgbuff_free(response_msg);
|
||||
return(retval);
|
||||
|
||||
}
|
||||
|
||||
/* Retrieve next part of DocumentID, assumes open connection to host */
|
||||
int
|
||||
waisRequestNext(FILE *connection,
|
||||
char *request_message, char *response_message,
|
||||
long message_length, any *DocumentID,
|
||||
char *DocumentType, char *database,
|
||||
long count)
|
||||
{
|
||||
long request_buffer_length; /* how of the request is left */
|
||||
|
||||
request_buffer_length = message_length; /* how often the request is left */
|
||||
if(0 ==
|
||||
generate_retrieval_apdu(request_message + HEADER_LENGTH,
|
||||
&request_buffer_length,
|
||||
DocumentID,
|
||||
CT_byte,
|
||||
count * CHARS_PER_PAGE,
|
||||
(count + 1) * CHARS_PER_PAGE,
|
||||
DocumentType,
|
||||
database)) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Error generating retrieval APDU: request too long");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if(0 ==
|
||||
interpret_message(request_message,
|
||||
message_length - request_buffer_length,
|
||||
response_message,
|
||||
message_length,
|
||||
connection,
|
||||
WAIS_verbose /* true verbose */
|
||||
)) { /* perhaps the server shut down, let's see: */
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Error delivering message");
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
any* waisRetrieve(char* server_name,
|
||||
char* service,
|
||||
char* database,
|
||||
any* DocumentID,
|
||||
char* DocumentType,
|
||||
long DocumentLength)
|
||||
{
|
||||
/* docHeader = query_info->DocHeaders[document_number]; */
|
||||
char userInfo[500];
|
||||
char hostname[80];
|
||||
char domainname[80];
|
||||
WAISMSGBUFF request_msg = NULL;
|
||||
WAISMSGBUFF response_msg = NULL;
|
||||
SearchResponseAPDU* retrieval_response = NULL;
|
||||
WAISDocumentText* fragmentText;
|
||||
any* fragment = NULL;
|
||||
any* document_text = NULL;
|
||||
long count = 0, message_length = MAX_MESSAGE_LENGTH;
|
||||
FILE *connection = NULL;
|
||||
any *retval;
|
||||
|
||||
if (server_name[0] == '\0' && service[0] == '\0')
|
||||
connection = NULL; /* do local searching */
|
||||
else /* remote search, fill in defaults*/
|
||||
{ if (server_name[0] == '\0')
|
||||
/*default to local machine*/
|
||||
gethostname(server_name,MAX_SERVER_LENGTH);
|
||||
if (service[0] == '\0')
|
||||
strcpy(service, Z39_50_SERVICE); /* default */
|
||||
if ((connection = connectToServer(server_name,atoi(service))) == NULL)
|
||||
{ p_err_string = qsprintf_stcopyr(p_err_string, Err_Connect,
|
||||
server_name, service);
|
||||
RETURN (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
request_msg = waismsgbuff_alloc();
|
||||
response_msg = waismsgbuff_alloc();
|
||||
|
||||
gethostname(hostname, 80);
|
||||
getdomainname(domainname, 80);
|
||||
|
||||
sprintf(userInfo, "prospero gateway from host: %s.%s", hostname, domainname);
|
||||
|
||||
if((message_length =
|
||||
initConnection(request_msg->buff,
|
||||
response_msg->buff,
|
||||
message_length,
|
||||
connection,
|
||||
userInfo)) <= 0) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string, Err_Connect,
|
||||
server_name, service);
|
||||
RETURN(NULL);
|
||||
}
|
||||
|
||||
if (DocumentType == NULL) DocumentType = s_strdup("TEXT");
|
||||
|
||||
/* we must retrieve the document in parts since it might be very long*/
|
||||
while (TRUE) {
|
||||
|
||||
if (waisRequestNext(connection, request_msg->buff,
|
||||
response_msg->buff,
|
||||
message_length, DocumentID, DocumentType, database, count)) {
|
||||
freeAny(document_text);
|
||||
RETURN(NULL);
|
||||
}
|
||||
readSearchResponseAPDU(&retrieval_response,
|
||||
response_msg->buff + HEADER_LENGTH);
|
||||
|
||||
if(NULL ==
|
||||
((WAISSearchResponse *)
|
||||
retrieval_response->DatabaseDiagnosticRecords)->Text) {
|
||||
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"No text was returned");
|
||||
freeAny(document_text);
|
||||
return(NULL);
|
||||
} else {
|
||||
fragmentText = ((WAISSearchResponse *)
|
||||
retrieval_response->DatabaseDiagnosticRecords)->Text[0];
|
||||
fragment = fragmentText->DocumentText;
|
||||
|
||||
if (count == 0) {
|
||||
document_text = duplicateAny(fragment);
|
||||
} else {
|
||||
/* Increase document_text size to accomodate fragment. */
|
||||
if (!(document_text->bytes =
|
||||
s_realloc(document_text->bytes,
|
||||
(size_t)(document_text->size + fragment->size) * sizeof(char)))) {
|
||||
/* May never get here, since can abort if no memory */
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Unable to allocate space for %d bytes",
|
||||
document_text->size+fragment->size * sizeof(char));
|
||||
freeAny(document_text);
|
||||
RETURN(NULL);
|
||||
}
|
||||
/* Copy the fragment into the document_text. */
|
||||
memcpy(&(document_text->bytes[document_text->size]),
|
||||
fragment->bytes,
|
||||
(size_t) fragment->size * sizeof(char));
|
||||
/* Adjust the size field of document_text. */
|
||||
document_text->size = fragment->size + document_text->size;
|
||||
}
|
||||
}
|
||||
|
||||
/* Under normal behaviour it will loop until it encounters a diagnostic
|
||||
saying read beyond end of document, and then return */
|
||||
if(((WAISSearchResponse *)
|
||||
retrieval_response->DatabaseDiagnosticRecords)->Diagnostics != NULL) {
|
||||
showDiags(((WAISSearchResponse *)
|
||||
retrieval_response->DatabaseDiagnosticRecords)->Diagnostics);
|
||||
p_err_string = qsprintf_stcopyr(p_err_string, "Diagnostic records received");
|
||||
RETURN(document_text);
|
||||
}
|
||||
count++;
|
||||
freeWAISSearchResponse( retrieval_response->DatabaseDiagnosticRecords);
|
||||
freeSearchResponseAPDU( retrieval_response);
|
||||
retrieval_response = NULL;
|
||||
}
|
||||
RETURN(document_text);
|
||||
|
||||
cleanup:
|
||||
freeWAISSearchResponse( retrieval_response->DatabaseDiagnosticRecords);
|
||||
freeSearchResponseAPDU( retrieval_response);
|
||||
if (connection) fclose(connection);
|
||||
waismsgbuff_free(request_msg);
|
||||
waismsgbuff_free(response_msg);
|
||||
return(retval);
|
||||
}
|
||||
|
||||
|
||||
int waisRetrieveFile(
|
||||
char* server_name,
|
||||
char* service,
|
||||
char* database,
|
||||
any* DocumentID,
|
||||
char* DocumentType,
|
||||
long DocumentLength,
|
||||
char* local)
|
||||
{
|
||||
/* docHeader = query_info->DocHeaders[document_number]; */
|
||||
char userInfo[500];
|
||||
char hostname[80];
|
||||
char domainname[80];
|
||||
WAISMSGBUFF request_msg = NULL;
|
||||
WAISMSGBUFF response_msg = NULL;
|
||||
SearchResponseAPDU* retrieval_response = NULL;
|
||||
WAISDocumentText* fragmentText;
|
||||
any* fragment = NULL;
|
||||
any* document_text = NULL;
|
||||
long count = 0, message_length = MAX_MESSAGE_LENGTH;
|
||||
FILE *connection = NULL;
|
||||
int retval;
|
||||
int fd = -1;
|
||||
|
||||
if (server_name[0] == '\0' && service[0] == '\0')
|
||||
connection = NULL; /* do local searching */
|
||||
else /* remote search, fill in defaults*/
|
||||
{ if (server_name[0] == '\0')
|
||||
/*default to local machine*/
|
||||
gethostname(server_name,MAX_SERVER_LENGTH);
|
||||
if (service[0] == '\0')
|
||||
strcpy(service, Z39_50_SERVICE); /* default */
|
||||
if ((connection = connectToServer(server_name,atoi(service))) == NULL)
|
||||
{ p_err_string = qsprintf_stcopyr(p_err_string, Err_Connect,
|
||||
server_name, service);
|
||||
RETURN (-1);
|
||||
}
|
||||
}
|
||||
|
||||
request_msg = waismsgbuff_alloc();
|
||||
response_msg = waismsgbuff_alloc();
|
||||
|
||||
gethostname(hostname, 80);
|
||||
getdomainname(domainname, 80);
|
||||
|
||||
sprintf(userInfo, "prospero gateway from host: %s.%s", hostname, domainname);
|
||||
|
||||
if((message_length =
|
||||
initConnection(request_msg->buff,
|
||||
response_msg->buff,
|
||||
message_length,
|
||||
connection,
|
||||
userInfo)) <= 0) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string, Err_Connect,
|
||||
server_name, service);
|
||||
RETURN(-1);
|
||||
}
|
||||
|
||||
if (DocumentType == NULL) DocumentType = s_strdup("TEXT");
|
||||
|
||||
/* we must retrieve the document in parts since it might be very long*/
|
||||
while (TRUE) {
|
||||
|
||||
if (waisRequestNext(connection, request_msg->buff,
|
||||
response_msg->buff,
|
||||
message_length, DocumentID, DocumentType, database, count)) {
|
||||
freeAny(document_text);
|
||||
RETURN(-1);
|
||||
}
|
||||
readSearchResponseAPDU(&retrieval_response,
|
||||
response_msg->buff + HEADER_LENGTH);
|
||||
|
||||
if(NULL ==
|
||||
((WAISSearchResponse *)
|
||||
retrieval_response->DatabaseDiagnosticRecords)->Text) {
|
||||
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"No text was returned");
|
||||
freeAny(document_text);
|
||||
RETURN(-1);
|
||||
} else {
|
||||
fragmentText = ((WAISSearchResponse *)
|
||||
retrieval_response->DatabaseDiagnosticRecords)->Text[0];
|
||||
fragment = fragmentText->DocumentText;
|
||||
|
||||
if (fd == -1) {
|
||||
if ((fd = open(local,O_WRONLY|O_CREAT|O_TRUNC,
|
||||
S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH))
|
||||
== -1) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Unable to open %s: %s", local, unixerrstr());
|
||||
RETURN(-1);
|
||||
}
|
||||
}
|
||||
if ((write(fd,fragment->bytes,fragment->size * sizeof(char))) == -1) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Unable to write %d characters to %s: %s",
|
||||
fragment->size,local,unixerrstr());
|
||||
RETURN(-1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Under normal behaviour it will loop until it encounters a diagnostic
|
||||
saying read beyond end of document, and then return */
|
||||
if(((WAISSearchResponse *)
|
||||
retrieval_response->DatabaseDiagnosticRecords)->Diagnostics != NULL) {
|
||||
showDiags(((WAISSearchResponse *)
|
||||
retrieval_response->DatabaseDiagnosticRecords)->Diagnostics);
|
||||
p_err_string = qsprintf_stcopyr(p_err_string, "Diagnostic records received");
|
||||
RETURN(0);
|
||||
}
|
||||
count++;
|
||||
freeWAISSearchResponse( retrieval_response->DatabaseDiagnosticRecords);
|
||||
freeSearchResponseAPDU( retrieval_response);
|
||||
retrieval_response = NULL;
|
||||
}
|
||||
RETURN(0);
|
||||
|
||||
cleanup:
|
||||
if (fd != -1) close(fd);
|
||||
/* Dont check error - may fail if other error)*/
|
||||
if (retrieval_response) {
|
||||
freeWAISSearchResponse( retrieval_response->DatabaseDiagnosticRecords);
|
||||
freeSearchResponseAPDU( retrieval_response);
|
||||
}
|
||||
if (connection) fclose(connection);
|
||||
waismsgbuff_free(request_msg);
|
||||
waismsgbuff_free(response_msg);
|
||||
return(retval);
|
||||
}
|
||||
/* returns a pointer into the buffer of the next free byte.
|
||||
if it overflowed, then NULL is returned
|
||||
*/
|
||||
|
||||
char *
|
||||
generate_retrieval_apdu(buff,
|
||||
buff_len,
|
||||
docID,
|
||||
chunk_type,
|
||||
start,
|
||||
end,
|
||||
type,
|
||||
database_name)
|
||||
char *buff;
|
||||
long *buff_len; /* length of the buffer changed to reflect new data written */
|
||||
any *docID;
|
||||
long chunk_type;
|
||||
long start;
|
||||
long end;
|
||||
char *type;
|
||||
char *database_name;
|
||||
{
|
||||
SearchAPDU *search;
|
||||
char *end_ptr;
|
||||
|
||||
char *database_names[2];
|
||||
char *element_names[3];
|
||||
any refID;
|
||||
|
||||
DocObj *DocObjs[2];
|
||||
any *query; /* changed from char* by brewster */
|
||||
|
||||
if(NULL == type)
|
||||
type = s_strdup("TEXT");
|
||||
|
||||
database_names[0] = database_name;
|
||||
database_names[1] = NULL;
|
||||
|
||||
element_names[0] = " ";
|
||||
element_names[1] = ES_DocumentText;
|
||||
element_names[2] = NULL;
|
||||
|
||||
refID.size = 1;
|
||||
refID.bytes = "3";
|
||||
|
||||
switch(chunk_type){
|
||||
case CT_line:
|
||||
DocObjs[0] = makeDocObjUsingLines(docID, type, start, end);
|
||||
break;
|
||||
case CT_byte:
|
||||
DocObjs[0] = makeDocObjUsingBytes(docID, type, start, end);
|
||||
break;
|
||||
}
|
||||
DocObjs[1] = NULL;
|
||||
|
||||
query = makeWAISTextQuery(DocObjs);
|
||||
search = makeSearchAPDU( 10L, 16L, 15L,
|
||||
1L, /* replace indicator */
|
||||
"FOO", /* result set name */
|
||||
database_names, /* database name */
|
||||
QT_TextRetrievalQuery, /* query_type */
|
||||
element_names, /* element name */
|
||||
&refID, /* reference ID */
|
||||
query);
|
||||
end_ptr = writeSearchAPDU(search, buff, buff_len);
|
||||
/* s_free(DocObjs[0]->Type); it's a copy of the input, don't free it! */
|
||||
CSTFreeDocObj(DocObjs[0]);
|
||||
CSTFreeWAISTextQuery(query);
|
||||
freeSearchAPDU(search);
|
||||
return(end_ptr);
|
||||
}
|
||||
|
||||
|
||||
long initConnection(char* inBuffer, /*!! Large malloced buffer */
|
||||
char* outBuffer, /*!! Large malloced bugger */
|
||||
long bufferSize,
|
||||
FILE* connection,
|
||||
char* userInfo)
|
||||
{
|
||||
InitAPDU* init = NULL;
|
||||
InitResponseAPDU* reply = NULL;
|
||||
long result;
|
||||
long retval;
|
||||
|
||||
/* construct an init APDU */
|
||||
init = makeInitAPDU(true,false,false,false,false,bufferSize,bufferSize,
|
||||
userInfo,defaultImplementationID(),
|
||||
defaultImplementationName(),
|
||||
defaultImplementationVersion(),
|
||||
NULL,userInfo);
|
||||
/* write it to the buffer */
|
||||
if ((result =
|
||||
writeInitAPDU(init,inBuffer+HEADER_LENGTH,&bufferSize) - inBuffer
|
||||
) <0)
|
||||
RETURN(-1);
|
||||
|
||||
if (interpret_message(inBuffer,
|
||||
result - HEADER_LENGTH,
|
||||
outBuffer,
|
||||
bufferSize,
|
||||
connection,
|
||||
WAIS_verbose /* true verbose */
|
||||
) == 0)
|
||||
/* error making a connection */
|
||||
RETURN (-1);
|
||||
|
||||
if ((readInitResponseAPDU(&reply,outBuffer + HEADER_LENGTH) == NULL) ||
|
||||
(reply->Result == false))
|
||||
RETURN(-1);
|
||||
|
||||
/* we got a response back */
|
||||
result = reply->MaximumRecordSize;
|
||||
RETURN(result);
|
||||
|
||||
cleanup:
|
||||
if (reply) {
|
||||
freeWAISInitResponse((WAISInitResponse*)reply->UserInformationField);
|
||||
freeInitResponseAPDU(reply);
|
||||
}
|
||||
freeInitAPDU(init);
|
||||
return(retval);
|
||||
}
|
||||
|
||||
|
||||
/* returns a pointer in the buffer of the first free byte.
|
||||
if it overflows, then NULL is returned
|
||||
*/
|
||||
char*
|
||||
generate_search_apdu(char* buff, /* buffer to hold the apdu */
|
||||
long* buff_len, /* buffer length changed for new data */
|
||||
char* seed_words, /* string of the seed words */
|
||||
char* database_name, /* copied */
|
||||
DocObj** docobjs,
|
||||
long maxDocsRetrieved)
|
||||
{
|
||||
/* local variables */
|
||||
|
||||
SearchAPDU *search3;
|
||||
char *end_ptr;
|
||||
/* This is copied, nothing gained if static*/
|
||||
char *database_names[2] = {"", 0};
|
||||
any refID;
|
||||
WAISSearch *query;
|
||||
refID.size = 1;
|
||||
refID.bytes = "3";
|
||||
|
||||
database_names[0] = database_name;
|
||||
query = makeWAISSearch(seed_words, /*pointed at */
|
||||
docobjs, /* DocObjsPtr */
|
||||
0L,
|
||||
1L, /* DateFactor */
|
||||
0L, /* BeginDateRange */
|
||||
0L, /* EndDateRange */
|
||||
maxDocsRetrieved
|
||||
);
|
||||
|
||||
search3 = makeSearchAPDU(30L,
|
||||
5000L, /* should be large */
|
||||
30L,
|
||||
1L, /* replace indicator */
|
||||
"", /* result set name */
|
||||
database_names, /* database name (copied)*/
|
||||
QT_RelevanceFeedbackQuery, /* query_type */
|
||||
0L, /* element name */
|
||||
NULL, /* reference ID */
|
||||
query);
|
||||
|
||||
end_ptr = writeSearchAPDU(search3, buff, buff_len);
|
||||
|
||||
CSTFreeWAISSearch(query);
|
||||
freeSearchAPDU(search3); /* frees copy of database_names */
|
||||
return(end_ptr);
|
||||
}
|
||||
|
||||
|
||||
/* returns the number of bytes written. 0 if an error */
|
||||
long
|
||||
interpret_message(char* request_message,
|
||||
long request_length, /* length of the buffer */
|
||||
char* response_message,
|
||||
long response_buffer_length,
|
||||
FILE* connection,
|
||||
boolean verbose)
|
||||
{
|
||||
long response_length;
|
||||
|
||||
writeWAISPacketHeader(request_message,
|
||||
request_length,
|
||||
(long)'z', /* Z39.50 */
|
||||
"wais ", /* server name */
|
||||
(long)NO_COMPRESSION, /* no compression */
|
||||
(long)NO_ENCODING,(long)HEADER_VERSION);
|
||||
|
||||
if(connection != NULL) {
|
||||
if(0 ==
|
||||
(response_length =
|
||||
transport_message(connection, request_message,
|
||||
request_length,
|
||||
response_message,
|
||||
response_buffer_length)))
|
||||
return(0);
|
||||
}
|
||||
else{
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Local search not supported in this version");
|
||||
return(0);
|
||||
}
|
||||
|
||||
#if !defined(IN_RMG) && !defined(PFS_THREADS)
|
||||
if(verbose){
|
||||
printf ("decoded %ld bytes: \n", response_length);
|
||||
twais_dsply_rsp_apdu(response_message + HEADER_LENGTH,
|
||||
request_length);
|
||||
}
|
||||
#endif
|
||||
|
||||
return(response_length);
|
||||
}
|
||||
|
||||
|
||||
/* this is a safe version of unix 'read' it does all the checking
|
||||
* and looping necessary
|
||||
* to those trying to modify the transport code to use non-UNIX streams:
|
||||
* This is the function to modify!
|
||||
*/
|
||||
long read_from_stream(d,buf,nbytes)
|
||||
long d; /* this is the stream */
|
||||
char *buf;
|
||||
long nbytes;
|
||||
{
|
||||
long didRead;
|
||||
long toRead = nbytes;
|
||||
long totalRead = 0; /* paranoia */
|
||||
|
||||
while (toRead > 0){
|
||||
didRead = quick_read (d, buf, toRead, TIMEOUT_WAIS_READ);
|
||||
if(didRead == -1) /* error*/
|
||||
return(-1);
|
||||
if(didRead == 0) /* eof */
|
||||
return(-2); /* maybe this should return 0? */
|
||||
toRead -= didRead;
|
||||
buf += didRead;
|
||||
totalRead += didRead;
|
||||
}
|
||||
if(totalRead != nbytes) /* we overread for some reason */
|
||||
return(- totalRead); /* bad news */
|
||||
return(totalRead);
|
||||
}
|
||||
|
||||
|
||||
/* returns the length of the response, 0 if an error */
|
||||
|
||||
long
|
||||
transport_message(FILE* connection,
|
||||
char* request_message,
|
||||
long request_length,
|
||||
char* response_message,
|
||||
long response_buffer_length)
|
||||
{
|
||||
WAISMessage header;
|
||||
long response_length;
|
||||
|
||||
|
||||
/* Write out message. Read back header. Figure out response length. */
|
||||
|
||||
if( request_length + HEADER_LENGTH
|
||||
!= fwrite (request_message, 1L, request_length + HEADER_LENGTH, connection))
|
||||
return 0;
|
||||
|
||||
fflush(connection);
|
||||
|
||||
/* read for the first '0' */
|
||||
|
||||
while(1){
|
||||
if(0 > read_from_stream(fileno(connection), response_message, 1))
|
||||
return 0;
|
||||
if('0' == response_message[0])
|
||||
break;
|
||||
}
|
||||
|
||||
if(0 > read_from_stream(fileno(connection),
|
||||
response_message + 1,
|
||||
HEADER_LENGTH - 1))
|
||||
return 0;
|
||||
|
||||
readWAISPacketHeader(response_message, &header);
|
||||
{
|
||||
char length_array[11];
|
||||
strncpy(length_array, header.msg_len, 10);
|
||||
length_array[10] = '\0';
|
||||
response_length = atol(length_array);
|
||||
/*
|
||||
if(verbose){
|
||||
printf("WAIS header: '%s' length_array: '%s'\n",
|
||||
response_message, length_array);
|
||||
}
|
||||
*/
|
||||
if(response_length > response_buffer_length){
|
||||
/* we got a message that is too long, therefore empty the message out,
|
||||
and return 0 */
|
||||
long i;
|
||||
for(i = 0; i < response_length; i++){
|
||||
read_from_stream(fileno(connection),
|
||||
response_message + HEADER_LENGTH,
|
||||
1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
if(0 > read_from_stream(fileno(connection),
|
||||
response_message + HEADER_LENGTH,
|
||||
response_length))
|
||||
return 0;
|
||||
return(response_length);
|
||||
}
|
||||
|
||||
/* modified from Jonny G's version in ui/question.c */
|
||||
void showDiags(d)
|
||||
diagnosticRecord **d;
|
||||
{
|
||||
long i;
|
||||
|
||||
for (i = 0; d[i] != NULL; i++) {
|
||||
if (d[i]->ADDINFO != NULL) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Code: %s, %s", d[i]->DIAG, d[i] ->ADDINFO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert docid into newly stalloc-ed DocumentId */
|
||||
any *
|
||||
un_urlascii(char *docid)
|
||||
{
|
||||
int i=0;
|
||||
int j=0; /* Pointer into string for writing */
|
||||
any *DocumentId;
|
||||
|
||||
DocumentId = (any *)malloc(sizeof(any));
|
||||
if (!DocumentId) out_of_memory();
|
||||
/* Converted string cant be longer than docid */
|
||||
DocumentId->bytes = stalloc(strlen(docid)+1);
|
||||
while (docid[i]) {
|
||||
if (docid[i] != '%') {
|
||||
DocumentId->bytes[j++]=docid[i++];
|
||||
} else {
|
||||
int conv;
|
||||
i++;
|
||||
sscanf(&docid[i],"%2x",&conv);
|
||||
DocumentId->bytes[j++] = (char)conv;
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
DocumentId->size = j;
|
||||
return DocumentId;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
waisRetrieveFileByHsoname(char *local,char *hsoname)
|
||||
{
|
||||
any *DocumentId = NULL;
|
||||
char *host = NULL;
|
||||
char *port = NULL;
|
||||
char *type = NULL;
|
||||
char *database = NULL;
|
||||
char *query = NULL;
|
||||
int tmp;
|
||||
int retval;
|
||||
tmp = qsscanf(hsoname, "WAIS-GW/%&[^(](%&[^)])/%&[^/]/%&[^/]/%&[^/]/%[^\n]",
|
||||
&host, &port, &type, &database, &query);
|
||||
if (tmp != 5) {
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Invalid WAIS hsoname: %s", hsoname);
|
||||
RETURN(-1);
|
||||
}
|
||||
DocumentId = un_urlascii(query);
|
||||
RETURN(waisRetrieveFile(host,port,database,
|
||||
DocumentId,type,0,local));
|
||||
|
||||
cleanup:
|
||||
if (DocumentId) {
|
||||
stfree(DocumentId->bytes);
|
||||
free(DocumentId);
|
||||
}
|
||||
stfree(host);
|
||||
stfree(port);
|
||||
stfree(type);
|
||||
stfree(database);
|
||||
stfree(query);
|
||||
return(retval);
|
||||
}
|
||||
35
prospero/lib/psrv/wais_gw/inface.h
Normal file
35
prospero/lib/psrv/wais_gw/inface.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*****************************************************************************
|
||||
* (c) Copyright 1992 Wide Area Information Servers, Inc *
|
||||
* of California. All rights reserved. *
|
||||
* *
|
||||
* This notice is intended as a precaution against inadvertent publication *
|
||||
* and does not constitute an admission or acknowledgement that publication *
|
||||
* has occurred or constitute a waiver of confidentiality. *
|
||||
* *
|
||||
* Wide Area Information Server software is the proprietary and *
|
||||
* confidential property of Wide Area Information Servers, Inc. *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef interface_h
|
||||
#define interface_h
|
||||
|
||||
#include "wprot.h" /* For WAISSearchResponse */
|
||||
#define Z39_50_SERVICE "210"
|
||||
#define MAX_MESSAGE_LENGTH 100000
|
||||
#define MAX_SERVER_LENGTH 1000
|
||||
|
||||
WAISSearchResponse* waisQuery (char* server_name,
|
||||
char* service,
|
||||
char* database,
|
||||
char* keywords);
|
||||
|
||||
any* waisRetrieve(char* server_name,
|
||||
char* service,
|
||||
char* database,
|
||||
any* DocumentID,
|
||||
char* DocumentType,
|
||||
long DocumentLength);
|
||||
extern any *un_urlascii(char *docid);
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
772
prospero/lib/psrv/wais_gw/irfileio.c
Normal file
772
prospero/lib/psrv/wais_gw/irfileio.c
Normal file
@@ -0,0 +1,772 @@
|
||||
/* WIDE AREA INFORMATION SERVER SOFTWARE:
|
||||
Developed by Thinking Machines Corporation and put into the public
|
||||
domain with no guarantees or restrictions.
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/********************************************************
|
||||
* Writing and reading structures to files. *
|
||||
* *
|
||||
* These use the Lisp printer format with the *
|
||||
* lisp naming conventions. You ask: "Why would *
|
||||
* you want to use that?". Well, we need an *
|
||||
* easily readable data syntax that can handle *
|
||||
* a large number of different data types. *
|
||||
* Further, we need it to be tagged so that *
|
||||
* run time tagged languages can read it and *
|
||||
* it is flexible. We need one that supports *
|
||||
* optional fields so that the format can *
|
||||
* grow backcompatibly. And (the kicker), *
|
||||
* it must be read from many languages since *
|
||||
* user interfaces may be written in anything *
|
||||
* from smalltalk to hypercard. *
|
||||
* *
|
||||
* -brewster 5/10/90 *
|
||||
********************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#include <pfs.h>
|
||||
#include <perrno.h>
|
||||
|
||||
#include "irfileio.h"
|
||||
#include "cutil.h"
|
||||
|
||||
#define INDENT_SPACES (2L)
|
||||
#define MAX_INDENT (40L)
|
||||
#ifdef NOTUSEDANDNOTTHREADSAFE
|
||||
static long indent_level;
|
||||
#endif /*NOTUSEDANDNOTTHREADSAFE
|
||||
|
||||
#define RETURN(val) {retval = val; goto cleanup; }
|
||||
|
||||
/**********************/
|
||||
|
||||
/**********************/
|
||||
|
||||
|
||||
#ifdef NOTUSEDANDNOTTHREADSAFE
|
||||
static void indent(FILE* file);
|
||||
|
||||
static void indent(file)
|
||||
FILE* file;
|
||||
|
||||
{
|
||||
long i;
|
||||
for(i = 0; i <= MIN(MAX_INDENT, MAX(0L, indent_level * INDENT_SPACES)); i++){
|
||||
putc(' ', file);
|
||||
}
|
||||
}
|
||||
|
||||
long WriteStartOfList(file)
|
||||
FILE* file;
|
||||
{
|
||||
indent_level++;
|
||||
return(fprintf(file, " ( "));
|
||||
}
|
||||
|
||||
long WriteEndOfList(file)
|
||||
FILE* file;
|
||||
{
|
||||
indent_level--;
|
||||
return(fprintf(file, " ) "));
|
||||
}
|
||||
|
||||
long WriteStartOfStruct(name,file)
|
||||
char* name;
|
||||
FILE* file;
|
||||
{
|
||||
indent_level++;
|
||||
return(fprintf(file, " (:%s ", name));
|
||||
}
|
||||
|
||||
long WriteEndOfStruct(file)
|
||||
FILE* file;
|
||||
{
|
||||
indent_level--;
|
||||
return(fprintf(file, " ) "));
|
||||
}
|
||||
|
||||
long WriteSymbol(name,file)
|
||||
char* name;
|
||||
FILE* file;
|
||||
{
|
||||
return(fprintf(file, " %s ", name));
|
||||
}
|
||||
|
||||
long WriteNewline(file)
|
||||
FILE* file;
|
||||
{
|
||||
long return_value = fprintf(file, "\n");
|
||||
indent(file);
|
||||
return(return_value);
|
||||
}
|
||||
|
||||
long WriteLong(number,file)
|
||||
long number;
|
||||
FILE* file;
|
||||
{
|
||||
return(fprintf(file, " %ld ", number));
|
||||
}
|
||||
|
||||
long WriteDouble(number,file)
|
||||
double number;
|
||||
FILE* file;
|
||||
{
|
||||
return(fprintf(file, " %f ", number));
|
||||
}
|
||||
|
||||
long WriteString(string,file)
|
||||
char* string;
|
||||
FILE* file;
|
||||
{
|
||||
long i;
|
||||
putc('\"', file);
|
||||
for(i = 0; i < strlen(string); i++){
|
||||
if(string[i] == '\\' || string[i] == '\"')
|
||||
putc('\\', file);
|
||||
putc(string[i], file);
|
||||
}
|
||||
putc('\"', file);
|
||||
return(1);
|
||||
}
|
||||
|
||||
long WriteAny(value,file)
|
||||
any* value;
|
||||
FILE* file;
|
||||
{
|
||||
WriteStartOfStruct("any", file);
|
||||
WriteSymbol(":size", file); WriteLong(value->size, file);
|
||||
WriteSymbol(":bytes", file);
|
||||
Write8BitArray(value->size, value->bytes, file);
|
||||
return(WriteEndOfStruct(file));
|
||||
}
|
||||
|
||||
long Write8BitArray(length,array,file)
|
||||
long length;
|
||||
char* array;
|
||||
FILE* file;
|
||||
{
|
||||
long i;
|
||||
fprintf(file, " #( ");
|
||||
for(i=0; i<length; i++){
|
||||
WriteLong((long)array[i], file);
|
||||
}
|
||||
return(fprintf(file, " ) "));
|
||||
}
|
||||
|
||||
|
||||
long WriteTM(atime,file)
|
||||
struct tm* atime;
|
||||
FILE* file;
|
||||
{
|
||||
WriteStartOfStruct("tm", file);
|
||||
WriteSymbol(":tm-sec", file); WriteLong(atime->tm_sec, file);
|
||||
WriteSymbol(":tm-min", file); WriteLong(atime->tm_min, file);
|
||||
WriteSymbol(":tm-hour", file); WriteLong(atime->tm_hour, file);
|
||||
WriteSymbol(":tm-mday", file); WriteLong(atime->tm_mday, file);
|
||||
WriteSymbol(":tm-mon", file); WriteLong(atime->tm_mon, file);
|
||||
WriteNewline(file);
|
||||
WriteSymbol(":tm-year", file); WriteLong(atime->tm_year, file);
|
||||
WriteSymbol(":tm-wday", file); WriteLong(atime->tm_wday, file);
|
||||
WriteNewline(file);
|
||||
WriteSymbol(":tm-yday", file); WriteLong(atime->tm_yday, file);
|
||||
WriteSymbol(":tm-isdst", file); WriteLong(atime->tm_isdst, file);
|
||||
WriteEndOfStruct(file);
|
||||
return(WriteNewline(file));
|
||||
}
|
||||
|
||||
boolean
|
||||
writeAbsoluteTime(atime,file)
|
||||
struct tm* atime;
|
||||
FILE* file;
|
||||
{
|
||||
WriteStartOfStruct("absolute-time",file);
|
||||
WriteNewline(file);
|
||||
WriteSymbol(":year",file); WriteLong((long)atime->tm_year,file);
|
||||
WriteNewline(file);
|
||||
WriteSymbol(":month",file); WriteLong((long)atime->tm_mon,file);
|
||||
WriteNewline(file);
|
||||
WriteSymbol(":mday",file); WriteLong((long)atime->tm_mday,file);
|
||||
WriteNewline(file);
|
||||
WriteSymbol(":hour",file); WriteLong((long)atime->tm_hour,file);
|
||||
WriteNewline(file);
|
||||
WriteSymbol(":minute",file); WriteLong((long)atime->tm_min,file);
|
||||
WriteNewline(file);
|
||||
WriteSymbol(":second",file); WriteLong((long)atime->tm_sec,file);
|
||||
WriteNewline(file);
|
||||
return(WriteEndOfStruct(file));
|
||||
}
|
||||
#endif /*NOTUSEDANDNOTTHREADSAFE*/
|
||||
|
||||
|
||||
|
||||
/************************/
|
||||
|
||||
/************************/
|
||||
|
||||
|
||||
|
||||
#define BEFORE (1L)
|
||||
#define DURING (2L)
|
||||
#define HASH (3L)
|
||||
#define S (4L)
|
||||
#define QUOTE (5L)
|
||||
|
||||
#if !defined(IN_RMG)
|
||||
boolean ReadStartOfList(file)
|
||||
FILE* file;
|
||||
{
|
||||
long ch;
|
||||
while(TRUE){
|
||||
ch = getc(file);
|
||||
if(ch == '(')
|
||||
return(TRUE);
|
||||
if(!isspace(ch)){
|
||||
|
||||
if(ch == 'N' || ch == 'n'){
|
||||
ch = getc(file);
|
||||
if(ch == 'I' || ch == 'i'){
|
||||
ch = getc(file);
|
||||
if(ch == 'L' || ch == 'l'){
|
||||
ungetc(')', file);
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boolean ReadEndOfList(file)
|
||||
FILE* file;
|
||||
{
|
||||
long ch;
|
||||
while(TRUE){
|
||||
ch = getc(file);
|
||||
if(ch == ')')
|
||||
return(TRUE);
|
||||
if(!isspace(ch))
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
#endif /*!IN_RMG*/
|
||||
|
||||
#define STRING_ESC '\\'
|
||||
|
||||
long
|
||||
SkipObject(file)
|
||||
FILE* file;
|
||||
|
||||
{
|
||||
long ch;
|
||||
|
||||
while (true)
|
||||
{ ch = getc(file);
|
||||
if (ch == EOF)
|
||||
return (EOF);
|
||||
else
|
||||
{ if (isspace(ch))
|
||||
continue;
|
||||
else if (ch == '"')
|
||||
{ long escapeCount = 0;
|
||||
while (true)
|
||||
{ ch = getc(file);
|
||||
if (ch == EOF)
|
||||
return (EOF);
|
||||
else
|
||||
{ if (ch == STRING_ESC)
|
||||
{ escapeCount++;
|
||||
escapeCount = escapeCount % 2;
|
||||
}
|
||||
if (ch == '"' && escapeCount == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if ((isdigit(ch) || ch == '-' || ch == '.') ||
|
||||
(ch == ':'))
|
||||
{ while (!isspace(ch))
|
||||
{ ch = getc(file);
|
||||
if (ch == EOF)
|
||||
return(EOF);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if ((ch == '#') ||
|
||||
(ch == '('))
|
||||
{ long parenCount = 1;
|
||||
if (ch == '#')
|
||||
ch = getc(file);
|
||||
while (parenCount > 0)
|
||||
{ ch = getc(file);
|
||||
if (ch == EOF)
|
||||
return(EOF);
|
||||
else if (ch == '"')
|
||||
{
|
||||
ungetc(ch,file);
|
||||
SkipObject(file);
|
||||
}
|
||||
else if (ch == '(')
|
||||
parenCount++;
|
||||
else if (ch == ')')
|
||||
parenCount--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
long ReadLong(file,answer)
|
||||
FILE* file;
|
||||
long* answer;
|
||||
|
||||
{
|
||||
long ch;
|
||||
long state = BEFORE;
|
||||
boolean isNegative = false;
|
||||
long count = 0;
|
||||
|
||||
*answer = 0;
|
||||
|
||||
while(TRUE){
|
||||
ch = getc(file);
|
||||
if (ch == EOF){
|
||||
break;
|
||||
}
|
||||
else if (isdigit(ch)){
|
||||
if(state == BEFORE){
|
||||
state = DURING;
|
||||
}
|
||||
count++;
|
||||
if(count == 12){
|
||||
|
||||
return(false);
|
||||
}
|
||||
*answer = *answer * 10 + (ch - '0');
|
||||
}
|
||||
else if (ch == '-') {
|
||||
if (isNegative)
|
||||
|
||||
return(false);
|
||||
if (state == BEFORE) {
|
||||
|
||||
isNegative = true;
|
||||
state = DURING;
|
||||
}
|
||||
else {
|
||||
ungetc(ch,file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ch == ')' && (state == DURING)){
|
||||
ungetc(ch, file);
|
||||
return(true);
|
||||
}
|
||||
else if(!isspace(ch)){
|
||||
|
||||
return(false);
|
||||
}
|
||||
|
||||
else if(state == DURING){
|
||||
ungetc(ch, file);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (isNegative)
|
||||
*answer *= -1;
|
||||
return(true);
|
||||
}
|
||||
|
||||
long ReadDouble(file,answer)
|
||||
FILE* file;
|
||||
double* answer;
|
||||
{
|
||||
|
||||
long ch;
|
||||
long state = BEFORE;
|
||||
long count = 0;
|
||||
long decimal_count = 0;
|
||||
|
||||
*answer = 0.0;
|
||||
|
||||
while(TRUE){
|
||||
ch = getc(file);
|
||||
if (ch == EOF){
|
||||
return(true);
|
||||
}
|
||||
else if (ch == '.'){
|
||||
decimal_count ++;
|
||||
}
|
||||
else if (isdigit(ch)){
|
||||
if(state == BEFORE){
|
||||
state = DURING;
|
||||
}
|
||||
count++;
|
||||
if(count == 12){
|
||||
|
||||
return(false);
|
||||
}
|
||||
if (decimal_count == 0){
|
||||
*answer = *answer * 10 + (ch - '0');
|
||||
}
|
||||
else{
|
||||
double fraction = (ch - '0');
|
||||
long internal_count;
|
||||
for(internal_count = 0; internal_count < decimal_count;
|
||||
internal_count++){
|
||||
fraction = fraction / 10.0;
|
||||
}
|
||||
*answer = *answer + fraction;
|
||||
decimal_count++;
|
||||
}
|
||||
}
|
||||
else if(!isspace(ch)){
|
||||
|
||||
return(false);
|
||||
}
|
||||
|
||||
else if(state == DURING){
|
||||
ungetc(ch, file);
|
||||
return(true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static boolean issymbolchar(long ch);
|
||||
|
||||
static
|
||||
boolean issymbolchar(ch)
|
||||
long ch;
|
||||
|
||||
{
|
||||
return(!( isspace(ch) || ch == ')' || ch == '(' || ch == EOF));
|
||||
}
|
||||
|
||||
|
||||
long ReadSymbol(string,file,string_size)
|
||||
char* string;
|
||||
FILE* file;
|
||||
long string_size;
|
||||
{
|
||||
long ch;
|
||||
long state = BEFORE;
|
||||
long position = 0;
|
||||
|
||||
while(TRUE){
|
||||
ch = getc(file);
|
||||
if((state == BEFORE) && (ch == ')'))
|
||||
return(END_OF_STRUCT_OR_LIST);
|
||||
if(issymbolchar((long)ch)){
|
||||
if(state == BEFORE)
|
||||
state = DURING;
|
||||
string[position] = ch;
|
||||
position++;
|
||||
if(position >= string_size){
|
||||
string[string_size - 1] = '\0';
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
else if((state == DURING) || ch == EOF){
|
||||
if(ch != EOF) ungetc(ch, file);
|
||||
string[position] = '\0';
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#if !defined(IN_RMG)
|
||||
long ReadEndOfListOrStruct(file)
|
||||
FILE* file;
|
||||
{
|
||||
long ch;
|
||||
while(TRUE){
|
||||
ch = getc(file);
|
||||
if (EOF == ch)
|
||||
return(FALSE);
|
||||
else if(')' == ch)
|
||||
return(TRUE);
|
||||
else if(!isspace(ch))
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
long ReadString(string,file,string_size)
|
||||
char* string;
|
||||
FILE* file;
|
||||
long string_size;
|
||||
{
|
||||
long ch;
|
||||
long state = BEFORE;
|
||||
long position = 0;
|
||||
string[0] = '\0';
|
||||
|
||||
while(TRUE){
|
||||
ch = getc(file);
|
||||
if((state == BEFORE) && (ch == '\"'))
|
||||
state = DURING;
|
||||
else if (EOF == ch){
|
||||
string[position] = '\0';
|
||||
return(FALSE);
|
||||
}
|
||||
else if ((state == BEFORE) && (ch == ')'))
|
||||
return(END_OF_STRUCT_OR_LIST);
|
||||
else if ((state == DURING) && (ch == '\\'))
|
||||
state = QUOTE;
|
||||
else if ((state == DURING) && (ch == '"')){
|
||||
string[position] = '\0';
|
||||
return(TRUE);
|
||||
}
|
||||
else if ((state == QUOTE) || (state == DURING)){
|
||||
if(state == QUOTE)
|
||||
state = DURING;
|
||||
string[position] = ch;
|
||||
position++;
|
||||
if(position >= string_size){
|
||||
string[string_size - 1] = '\0';
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
long ReadStartOfStruct(name,file)
|
||||
char* name;
|
||||
FILE* file;
|
||||
{
|
||||
int ch;
|
||||
long state = BEFORE;
|
||||
|
||||
name[0] = '\0';
|
||||
|
||||
while(TRUE){
|
||||
ch = getc(file);
|
||||
if((state == BEFORE) && (ch == '#'))
|
||||
state = HASH;
|
||||
if((state == BEFORE) && (ch == '('))
|
||||
state = DURING;
|
||||
else if((state == BEFORE) && (ch == ')'))
|
||||
return(END_OF_STRUCT_OR_LIST);
|
||||
else if((state == BEFORE) && !isspace(ch))
|
||||
return(FALSE);
|
||||
else if(state == HASH){
|
||||
if (ch == 's')
|
||||
state = S;
|
||||
else{
|
||||
fprintf(stderr,"Expected an 's' but got an %c\n", ch);
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
else if(state == S){
|
||||
if (ch == '(')
|
||||
state = DURING;
|
||||
else{
|
||||
fprintf(stderr,"Expected an '(' but got an an %c\n",ch);
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
else if(state == DURING){
|
||||
return(ReadSymbol(name, file, MAX_SYMBOL_SIZE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long CheckStartOfStruct(name,file)
|
||||
char* name;
|
||||
FILE* file;
|
||||
{
|
||||
char temp_string[MAX_SYMBOL_SIZE];
|
||||
long result = ReadStartOfStruct(temp_string, file);
|
||||
if(result == END_OF_STRUCT_OR_LIST)
|
||||
return(END_OF_STRUCT_OR_LIST);
|
||||
else if(result == FALSE)
|
||||
return(FALSE);
|
||||
else if(0 == strcmp(temp_string, name))
|
||||
return(TRUE);
|
||||
else
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
#if !defined(IN_RMG)
|
||||
|
||||
long ReadAny(destination,file)
|
||||
any* destination;
|
||||
FILE* file;
|
||||
{
|
||||
char temp_string[MAX_SYMBOL_SIZE];
|
||||
long retval;
|
||||
|
||||
destination->size = 0;
|
||||
if(FALSE == CheckStartOfStruct("any", file)){
|
||||
fprintf(stderr,"An 'any' structure was not read from the disk");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
while(TRUE){
|
||||
long check_result;
|
||||
check_result = ReadSymbol(temp_string, file, MAX_SYMBOL_SIZE);
|
||||
if(FALSE == check_result)
|
||||
return(FALSE);
|
||||
if(END_OF_STRUCT_OR_LIST == check_result)
|
||||
RETURN(TRUE);
|
||||
|
||||
if(0 == strcmp(temp_string, ":size")) {
|
||||
long size;
|
||||
ReadLong(file,&size);
|
||||
destination->size = (unsigned long)size;
|
||||
}
|
||||
else if(0 == strcmp(temp_string, ":bytes")){
|
||||
long result;
|
||||
|
||||
destination->bytes = (char*)s_malloc(destination->size);
|
||||
if(NULL == destination->bytes){
|
||||
/* May never get here, s_malloc may abort if no space */
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Error on reading file. Malloc couldnt allocate %d bytes",
|
||||
destination->size );
|
||||
RETURN(FALSE);
|
||||
}
|
||||
result = Read8BitArray(destination->bytes, file, destination->size);
|
||||
if(FALSE == result)
|
||||
RETURN(FALSE);
|
||||
}
|
||||
else{
|
||||
p_err_string = qsprintf_stcopyr(p_err_string,
|
||||
"Unknown keyword for ANY %s\n", temp_string);
|
||||
RETURN(FALSE);
|
||||
}
|
||||
} /*while*/
|
||||
cleanup:
|
||||
/* For now, not freeing destination->bytes on error, let caller do it*/
|
||||
return(retval);
|
||||
}
|
||||
|
||||
|
||||
long
|
||||
Read8BitArray(char *destination, FILE *file,long len)
|
||||
{
|
||||
|
||||
int ch; /* don't use a long, because %c conversion
|
||||
isn't defined for longs. */
|
||||
long state = BEFORE;
|
||||
while(TRUE){
|
||||
ch = getc(file);
|
||||
if((state == BEFORE) && ((ch == '#') || (ch == '('))) {
|
||||
if (ch == '(') state = DURING;
|
||||
else state = HASH;
|
||||
}
|
||||
else if((state == BEFORE) && !isspace(ch)){
|
||||
fprintf(stderr,"error in reading array. Expected # and got %c", ch);
|
||||
return(FALSE);
|
||||
}
|
||||
else if(state == HASH){
|
||||
if (ch == '(')
|
||||
state = DURING;
|
||||
else{
|
||||
fprintf(stderr,"Expected an '(' but got an %c\n", ch);
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
else if(state == DURING){
|
||||
long i;
|
||||
ungetc(ch, file);
|
||||
for(i = 0; i < len; i++){
|
||||
long value;
|
||||
if(ReadLong(file,&value) == false){
|
||||
fprintf(stderr,"Error in reading a number from the file.");
|
||||
return(FALSE);
|
||||
}
|
||||
if(value > 255){
|
||||
fprintf(stderr,"Error in reading file. Expected a byte in an ANY, but got %ld", value);
|
||||
return(FALSE);
|
||||
}
|
||||
destination[i] = (char)value;
|
||||
}
|
||||
if(FALSE == ReadEndOfListOrStruct(file)){
|
||||
fprintf(stderr,"array was wrong length");
|
||||
return(FALSE);
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boolean
|
||||
readAbsoluteTime(atime,file)
|
||||
struct tm* atime;
|
||||
FILE* file;
|
||||
{
|
||||
if (CheckStartOfStruct("absolute-time",file) == FALSE)
|
||||
return(false);
|
||||
|
||||
while (true)
|
||||
{ long result;
|
||||
long val;
|
||||
char temp_string[MAX_SYMBOL_SIZE + 1];
|
||||
|
||||
result = ReadSymbol(temp_string,file,MAX_SYMBOL_SIZE);
|
||||
|
||||
if (result == END_OF_STRUCT_OR_LIST)
|
||||
break;
|
||||
else if (result == false)
|
||||
return(false);
|
||||
|
||||
if (strcmp(temp_string,":second") == 0)
|
||||
{ if (ReadLong(file,&val) == false)
|
||||
return(false);
|
||||
atime->tm_sec = val;
|
||||
}
|
||||
|
||||
else if (strcmp(temp_string,":minute") == 0)
|
||||
{ if (ReadLong(file,&val) == false)
|
||||
return(false);
|
||||
atime->tm_min = val;
|
||||
}
|
||||
|
||||
else if (strcmp(temp_string,":hour") == 0)
|
||||
{ if (ReadLong(file,&val) == false)
|
||||
return(false);
|
||||
atime->tm_hour = val;
|
||||
}
|
||||
|
||||
else if (strcmp(temp_string,":mday") == 0)
|
||||
{ if (ReadLong(file,&val) == false)
|
||||
return(false);
|
||||
atime->tm_mday = val;
|
||||
}
|
||||
|
||||
else if (strcmp(temp_string,":month") == 0)
|
||||
{ if (ReadLong(file,&val) == false)
|
||||
return(false);
|
||||
atime->tm_mon = val;
|
||||
}
|
||||
|
||||
else if (strcmp(temp_string,":year") == 0)
|
||||
{ if (ReadLong(file,&val) == false)
|
||||
return(false);
|
||||
atime->tm_year = val;
|
||||
}
|
||||
|
||||
else
|
||||
SkipObject(file);
|
||||
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
#endif
|
||||
46
prospero/lib/psrv/wais_gw/irfileio.h
Normal file
46
prospero/lib/psrv/wais_gw/irfileio.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* WIDE AREA INFORMATION SERVER SOFTWARE:
|
||||
Developed by Thinking Machines Corporation and put into the public
|
||||
domain with no guarantees or restrictions.
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef IRCFILEIO_H
|
||||
#define IRCFILEIO_H
|
||||
|
||||
#include "cdialect.h"
|
||||
#include "futil.h"
|
||||
#include "zprot.h"
|
||||
|
||||
#define MAX_SYMBOL_SIZE (255L)
|
||||
#define END_OF_STRUCT_OR_LIST (6L)
|
||||
|
||||
long SkipObject(FILE* file);
|
||||
long ReadLong(FILE* file,long* num);
|
||||
long ReadDouble(FILE* file,double* num);
|
||||
long ReadSymbol(char* string, FILE* file, long string_size);
|
||||
long ReadString(char* string, FILE* file, long string_size);
|
||||
long CheckStartOfStruct(char* name, FILE* file);
|
||||
long ReadAny(any* destination, FILE* file);
|
||||
long ReadTM(struct tm* /* time */, FILE* file);
|
||||
long Read8BitArray(char* destination, FILE* file, long /* length */);
|
||||
long ReadEndOfListOrStruct(FILE* file);
|
||||
long ReadStartOfStruct(char* name, FILE* file);
|
||||
boolean ReadStartOfList(FILE* file);
|
||||
boolean ReadEndOfList(FILE* file);
|
||||
boolean readAbsoluteTime(struct tm* /* time */,FILE* file);
|
||||
long WriteStartOfStruct(char* name, FILE* file);
|
||||
long WriteEndOfStruct(FILE* file);
|
||||
long WriteSymbol(char* name, FILE* file);
|
||||
long WriteString(char* string, FILE* file);
|
||||
long WriteNewline(FILE* file);
|
||||
long WriteLong(long number, FILE* file);
|
||||
long WriteDouble(double number, FILE* file);
|
||||
long WriteAny(any* value, FILE* file);
|
||||
long Write8BitArray(long /* length */, char* array, FILE* file);
|
||||
long WriteTM(struct tm* /* time */, FILE* file);
|
||||
long WriteStartOfList(FILE* file);
|
||||
long WriteEndOfList(FILE* file);
|
||||
boolean writeAbsoluteTime(struct tm* /* time */,FILE* file);
|
||||
|
||||
#endif
|
||||
217
prospero/lib/psrv/wais_gw/list.c
Normal file
217
prospero/lib/psrv/wais_gw/list.c
Normal file
@@ -0,0 +1,217 @@
|
||||
/*****************************************************************************
|
||||
* (c) Copyright 1992 Wide Area Information Servers, Inc *
|
||||
* of California. All rights reserved. *
|
||||
* *
|
||||
* This notice is intended as a precaution against inadvertent publication *
|
||||
* and does not constitute an admission or acknowledgement that publication *
|
||||
* has occurred or constitute a waiver of confidentiality. *
|
||||
* *
|
||||
* Wide Area Information Server software is the proprietary and *
|
||||
* confidential property of Wide Area Information Servers, Inc. *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "list.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
mapcar(list l,void (*function)())
|
||||
{
|
||||
long i;
|
||||
|
||||
if (null(l))
|
||||
return;
|
||||
|
||||
for (i = 0; i < length(l); i++)
|
||||
{ (*function)(nth(l,i));
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
list
|
||||
collecting(list l,void *item)
|
||||
|
||||
{
|
||||
if (l == NULL)
|
||||
if (!(l = (list)s_malloc(sizeof(listStruct))))
|
||||
return NULL;
|
||||
|
||||
if (l->rlen < length(l) + 1)
|
||||
{ l->rlen = length(l) + 2;
|
||||
l->elems = (void**)s_realloc(l->elems,l->rlen * sizeof(void*));
|
||||
}
|
||||
|
||||
l->elems[length(l)] = item;
|
||||
l->len++;
|
||||
|
||||
return(l);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
freeList(list l)
|
||||
{
|
||||
if (l != NULL)
|
||||
{ s_free(l->elems);
|
||||
s_free(l);
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static long
|
||||
cmpStrings(void* arg1,void* arg2)
|
||||
{
|
||||
return(strcmp(*(char**)arg1,*(char**)arg2));
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
sortList(list l,long (*cmp)())
|
||||
{
|
||||
if (cmp == NULL)
|
||||
cmp = cmpStrings;
|
||||
|
||||
if (length(l) > 1)
|
||||
qsort(l->elems,length(l),sizeof(void*),cmp);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
list
|
||||
insertNth(list l,long n,void* elem)
|
||||
{
|
||||
if (null(l))
|
||||
return(NULL);
|
||||
|
||||
if (n > length(l))
|
||||
return(NULL);
|
||||
|
||||
if (l->rlen < length(l) + 1)
|
||||
{ l->rlen = length(l) + 2;
|
||||
l->elems = (void**)s_realloc(l->elems,l->rlen*sizeof(void*));
|
||||
}
|
||||
|
||||
memmove(l->elems+n+1,l->elems+n,(length(l)-n)*sizeof(void*));
|
||||
l->elems[n] = elem;
|
||||
l->len++;
|
||||
|
||||
return(l);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
list
|
||||
removeNth(list l,long n)
|
||||
{
|
||||
if (null(l))
|
||||
return(NULL);
|
||||
|
||||
if (n >= length(l))
|
||||
return(NULL);
|
||||
|
||||
memmove(l->elems+n,l->elems+n+1,(length(l)-n-1)*sizeof(void*));
|
||||
l->len--;
|
||||
|
||||
if (l->rlen > 4 && l->rlen > length(l) * 2)
|
||||
{ l->rlen = length(l);
|
||||
l->elems = (void**)s_realloc(l->elems,l->rlen * sizeof(void*));
|
||||
}
|
||||
|
||||
return(l);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
boolean
|
||||
lookupInSortedList(list l,void* val,long (*cmpFunc)(void* arg1,void* arg2),
|
||||
long* posInList)
|
||||
|
||||
{
|
||||
long pos;
|
||||
long upperBound = length(l);
|
||||
long lowerBound = 0;
|
||||
long cmp;
|
||||
void* data;
|
||||
|
||||
if (null(l))
|
||||
{ if (posInList != NULL)
|
||||
*posInList = 0;
|
||||
return(false);
|
||||
}
|
||||
|
||||
if (cmpFunc == NULL)
|
||||
cmpFunc = cmpStrings;
|
||||
|
||||
while (upperBound >= lowerBound)
|
||||
{
|
||||
pos = lowerBound + ((upperBound - lowerBound) / 2);
|
||||
|
||||
if (pos == length(l))
|
||||
cmp = -1;
|
||||
else
|
||||
{ data = nth(l,pos);
|
||||
cmp = (*cmpFunc)(&val,&data);
|
||||
}
|
||||
|
||||
if (cmp == 0)
|
||||
{ if (posInList != NULL)
|
||||
*posInList = pos;
|
||||
return(true);
|
||||
}
|
||||
else if (cmp < 0)
|
||||
{ if (pos == lowerBound)
|
||||
{ if (posInList != NULL)
|
||||
*posInList = pos;
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
upperBound = pos;
|
||||
}
|
||||
else
|
||||
{ if (pos >= length(l))
|
||||
{ if (posInList != NULL)
|
||||
*posInList = pos;
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
lowerBound = pos + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (posInList != NULL)
|
||||
*posInList = length(l);
|
||||
return(false);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void*
|
||||
pop(list* l)
|
||||
{
|
||||
void* ans;
|
||||
|
||||
if (l == NULL || *l == NULL)
|
||||
return(NULL);
|
||||
|
||||
ans = first(*l);
|
||||
*l = removeNth(*l,0);
|
||||
return(ans);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
push(list* l,void* elem)
|
||||
{
|
||||
if (l == NULL)
|
||||
return;
|
||||
|
||||
*l = insertNth(*l,0,elem);
|
||||
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
57
prospero/lib/psrv/wais_gw/list.h
Normal file
57
prospero/lib/psrv/wais_gw/list.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*****************************************************************************
|
||||
* (c) Copyright 1992 Wide Area Information Servers, Inc *
|
||||
* of California. All rights reserved. *
|
||||
* *
|
||||
* This notice is intended as a precaution against inadvertent publication *
|
||||
* and does not constitute an admission or acknowledgement that publication *
|
||||
* has occurred or constitute a waiver of confidentiality. *
|
||||
* *
|
||||
* Wide Area Information Server software is the proprietary and *
|
||||
* confidential property of Wide Area Information Servers, Inc. *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef list_h
|
||||
#define list_h
|
||||
|
||||
#include "cutil.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
typedef struct listStruct
|
||||
{ void** elems;
|
||||
long len;
|
||||
long rlen;
|
||||
} listStruct;
|
||||
|
||||
#define list listStruct*
|
||||
|
||||
#define length(l) (long)(((l) == NULL) ? 0L : (l)->len)
|
||||
#define nth(l,n) \
|
||||
(((l) == NULL || length((l)) <= (n)) ? NULL : (l)->elems[(n)])
|
||||
#define car(l) (nth((l),0L))
|
||||
#define cadr(l) (nth((l),2L))
|
||||
#define cdr(l) (removeNth((l),0L))
|
||||
#define first(l) (car(l))
|
||||
#define last(l) (nth((l),length((l))-1L))
|
||||
#define rest(l) (cdr(l))
|
||||
#define setfNth(l,n,elem) \
|
||||
(((l) == NULL || length((l)) <= (n)) ? 0 : ((l)->elems[(n)] = (elem)))
|
||||
#define setfCar(l,elem) (setfNth((l),0L,(elem)))
|
||||
#define null(l) (((l) == NULL || length((l)) == 0L) ? true : false)
|
||||
|
||||
void mapcar(list l,void function (void* argument));
|
||||
list collecting(list l,void *item);
|
||||
void freeList(list l);
|
||||
void sortList(list l,long (*cmp)(void* arg1,void* arg2));
|
||||
list insertNth(list l,long n,void* elem);
|
||||
list removeNth(list l,long n);
|
||||
boolean lookupInSortedList(list l,void* val,
|
||||
long (*cmpFunc)(void* arg1,void* arg2),
|
||||
long* posInList);
|
||||
void* pop(list* l);
|
||||
void push(list* l,void* elem);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#endif
|
||||
|
||||
4
prospero/lib/psrv/wais_gw/main.c
Normal file
4
prospero/lib/psrv/wais_gw/main.c
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
main()
|
||||
{
|
||||
}
|
||||
53
prospero/lib/psrv/wais_gw/panic.c
Normal file
53
prospero/lib/psrv/wais_gw/panic.c
Normal file
@@ -0,0 +1,53 @@
|
||||
/* WIDE AREA INFORMATION SERVER SOFTWARE:
|
||||
Developed by Thinking Machines Corporation and put into the public
|
||||
domain with no guarantees or restrictions.
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "panic.h"
|
||||
#include "waislog.h"
|
||||
#include "cutil.h"
|
||||
|
||||
#include <pfs.h> /* for stcopyr() */
|
||||
#include <perrno.h>
|
||||
|
||||
extern int fault_count;
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
panic(char* formatString,...)
|
||||
/* something bad and unexpected has happened, print out a log message
|
||||
and abort the program in such a way that it can be debugged.
|
||||
*/
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
char msg[2000];
|
||||
|
||||
va_start(ap,formatString);
|
||||
vsprintf(msg,formatString,ap);
|
||||
#if !defined(IN_RMG)
|
||||
#if !defined(PFS_THREADS)
|
||||
waislog(WLOG_HIGH,WLOG_ERROR,msg);
|
||||
#else
|
||||
#error NO WAY TO LOG - DONT COMPILE LIKE THIS
|
||||
#endif
|
||||
#else
|
||||
p_err_string = stcopyr(p_err_string, msg);
|
||||
/* restart_server(fault_count, msg); */
|
||||
#endif
|
||||
va_end(ap);
|
||||
|
||||
#ifdef THINK_C
|
||||
Debugger();
|
||||
#endif
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
15
prospero/lib/psrv/wais_gw/panic.h
Normal file
15
prospero/lib/psrv/wais_gw/panic.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/* WIDE AREA INFORMATION SERVER SOFTWARE:
|
||||
Developed by Thinking Machines Corporation and put into the public
|
||||
domain with no guarantees or restrictions.
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef panic_h
|
||||
#define panic_h
|
||||
|
||||
#include "cdialect.h"
|
||||
|
||||
void panic(char* formatString,...);
|
||||
|
||||
#endif
|
||||
184
prospero/lib/psrv/wais_gw/sockets.c
Normal file
184
prospero/lib/psrv/wais_gw/sockets.c
Normal file
@@ -0,0 +1,184 @@
|
||||
/* WIDE AREA INFORMATION SERVER SOFTWARE:
|
||||
Developed by Thinking Machines Corporation and put into the public
|
||||
domain with no guarantees or restrictions.
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#define sockets_c
|
||||
|
||||
#include "sockets.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <posix_signal.h>
|
||||
|
||||
#include "panic.h"
|
||||
#include "waislog.h"
|
||||
|
||||
/* In theory this is defined in stdio.h, but its hosed on SOLARIS */
|
||||
extern FILE *fdopen(const int fd, const char *opt);
|
||||
|
||||
extern char *sys_errlist[];
|
||||
|
||||
#define QUEUE_SIZE (3L)
|
||||
#define HOSTNAME_BUFFER_SIZE (120L)
|
||||
#define MAX_RETRYS (10L)
|
||||
#define TIMEOUT_CONNECT 5
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#if !defined(IN_RMG) && !defined(PFS_THREADS)
|
||||
static boolean
|
||||
clrSocket(struct sockaddr_in *address,long portnumber,long *sock)
|
||||
{
|
||||
if (errno == EADDRINUSE)
|
||||
{ if (connect(*sock, address, sizeof (struct sockaddr_in)) == 0)
|
||||
{ close(*sock);
|
||||
waislog(WLOG_HIGH,WLOG_ERROR,
|
||||
"cannot bind port %ld (address already in use)",
|
||||
portnumber);
|
||||
waislog(WLOG_HIGH,WLOG_ERROR,
|
||||
"waisserver is already running on this system");
|
||||
panic("Exiting");
|
||||
}
|
||||
else
|
||||
{ int one = 1;
|
||||
|
||||
close(*sock);
|
||||
if ((*sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||
panic("Open socket failed in trying to clear the port.");
|
||||
if (setsockopt(*sock,SOL_SOCKET,SO_REUSEADDR,&one,sizeof(one)) < 0)
|
||||
; /* do nothing? */
|
||||
address->sin_family = AF_INET;
|
||||
address->sin_addr.s_addr = INADDR_ANY;
|
||||
address->sin_port = htons(portnumber);
|
||||
if (bind(*sock, address, sizeof(*address)) == 0)
|
||||
; /* do nothing? */
|
||||
}
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
openServer(long port,long* fd,long size)
|
||||
{
|
||||
struct sockaddr_in address;
|
||||
|
||||
memset(&address, 0, sizeof(address));
|
||||
|
||||
if ((*fd = socket(AF_INET,SOCK_STREAM,0)) < 0)
|
||||
{ panic("can't get file descriptor for socket: %s", sys_errlist[errno]);
|
||||
}
|
||||
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
address.sin_port = htons(port);
|
||||
|
||||
if (bind(*fd,(struct sockaddr*)&address,sizeof(struct sockaddr)) < 0)
|
||||
clrSocket(&address, port, fd);
|
||||
|
||||
if (listen(*fd,QUEUE_SIZE) < 0)
|
||||
panic("can't open server: %s", sys_errlist[errno]);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
fdAcceptClientConnection(long socket,long* fd)
|
||||
{
|
||||
struct sockaddr_in source;
|
||||
int sourcelen;
|
||||
|
||||
#ifdef BSD
|
||||
struct in_addr {
|
||||
union {
|
||||
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
|
||||
u_long S_addr;
|
||||
} S_un;
|
||||
} addr_p;
|
||||
#endif
|
||||
|
||||
sourcelen = sizeof(struct sockaddr_in);
|
||||
|
||||
do {
|
||||
errno = 0;
|
||||
*fd = accept(socket, &source, &sourcelen);
|
||||
} while (*fd < 0 && errno == EINTR);
|
||||
|
||||
if (source.sin_family == AF_INET)
|
||||
{ struct hostent *peer = NULL;
|
||||
|
||||
peer = gethostbyaddr((char*)&source.sin_addr, 4, AF_INET);
|
||||
|
||||
waislog(WLOG_MEDIUM,WLOG_CONNECT,"accepted connection from: %s [%s]",
|
||||
(peer == NULL) ? "" : peer->h_name,
|
||||
#if defined(sparc) && defined(__GNUC__) && !defined(__svr4__)
|
||||
inet_ntoa(&source.sin_addr));
|
||||
#else
|
||||
inet_ntoa(source.sin_addr));
|
||||
#endif /* sparc */
|
||||
}
|
||||
if (*fd < 0)
|
||||
panic("can't accept connection");
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
acceptClientConnection(long socket,FILE** file)
|
||||
{
|
||||
long fd;
|
||||
fdAcceptClientConnection(socket,&fd);
|
||||
if ((*file = fdopen(fd,"r+")) == NULL)
|
||||
panic("can't accept connection");
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
closeClientConnection(FILE* file)
|
||||
{
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
closeServer(long socket)
|
||||
{
|
||||
close(socket);
|
||||
}
|
||||
|
||||
#endif /*!IN_RMG && !PFS_THREADS*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
FILE *
|
||||
connectToServer(char* host_name,long port)
|
||||
{
|
||||
FILE* file;
|
||||
int fd;
|
||||
if ((fd = quick_open_tcp_stream(host_name, port, TIMEOUT_CONNECT)) == -1)
|
||||
return(NULL);
|
||||
|
||||
if ((file = fdopen(fd,"r+")) == NULL)
|
||||
{ perror("Connect to socket did not work, fdopen failure");
|
||||
close(fd);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return(file);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
closeConnectionToServer(FILE* file)
|
||||
{
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
37
prospero/lib/psrv/wais_gw/sockets.h
Normal file
37
prospero/lib/psrv/wais_gw/sockets.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/* WIDE AREA INFORMATION SERVER SOFTWARE:
|
||||
Developed by Thinking Machines Corporation and put into the public
|
||||
domain with no guarantees or restrictions.
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef sockets_h
|
||||
#define sockets_h
|
||||
|
||||
#include "cdialect.h"
|
||||
#include "cutil.h"
|
||||
|
||||
#ifndef THINK_C
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void openServer(long port,long* socket,long size);
|
||||
void acceptClientConnection(long socket,FILE** file);
|
||||
void closeClientConnection(FILE* file);
|
||||
void closeServer(long socket);
|
||||
FILE *connectToServer(char* hostname,long port);
|
||||
void closeConnectionToServer(FILE* file);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
835
prospero/lib/psrv/wais_gw/source.c
Normal file
835
prospero/lib/psrv/wais_gw/source.c
Normal file
@@ -0,0 +1,835 @@
|
||||
/* WIDE AREA INFORMATION SERVER SOFTWARE:
|
||||
Developed by Thinking Machines Corporation and put into the public
|
||||
domain with no guarantees or restrictions.
|
||||
|
||||
This is part of the shell user-interface tools for the WAIS software.
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#define _C_SOURCE
|
||||
|
||||
#include <string_with_strcasecmp.h>
|
||||
#include <stdio.h>
|
||||
#include "cutil.h"
|
||||
#include "futil.h"
|
||||
#include "irfileio.h"
|
||||
#include "source.h"
|
||||
#include <list_macros.h> /* For TH_APPEND_LIST*/
|
||||
#include <mitra_macros.h> /* For TH_FIND_LIST */
|
||||
#include <psrv.h> /* includes global declarations of
|
||||
waissource_count and waissource_max to be
|
||||
read. */
|
||||
|
||||
#define DESC_SIZE 65535
|
||||
|
||||
extern int alphasort();
|
||||
#if !defined(IN_RMG) && !defined(PFS_THREADS)
|
||||
SList Sources;
|
||||
|
||||
/* I'm not sure why this is all commented out, looks like its been
|
||||
superceeded by "SList Sources" */
|
||||
char **Source_items = NULL;
|
||||
#else
|
||||
|
||||
WAISSOURCE WaisSources = NULL;
|
||||
|
||||
#endif /*!IN_RMG && !PFS_THREADS*/
|
||||
|
||||
char *sourcepath = NULL;
|
||||
|
||||
#if !defined(IN_RMG) && !defined(PFS_THREADS)
|
||||
void
|
||||
freeSourceID(sid)
|
||||
SourceID sid;
|
||||
{
|
||||
if (sid != NULL) {
|
||||
if (sid->filename != NULL) s_free(sid->filename);
|
||||
s_free(sid);
|
||||
}
|
||||
}
|
||||
|
||||
SourceID
|
||||
copysourceID(sid)
|
||||
SourceID sid;
|
||||
{
|
||||
SourceID result = NULL;
|
||||
if(sid != NULL) {
|
||||
if((result = (SourceID) s_malloc(sizeof(_SourceID))) != NULL) {
|
||||
result->filename = s_strdup(sid->filename);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
char **
|
||||
buildSourceItemList(sourcelist)
|
||||
SourceList sourcelist;
|
||||
{
|
||||
char **result;
|
||||
int num, i;
|
||||
SourceList source;
|
||||
|
||||
/* find the length of the sidlist in the question */
|
||||
|
||||
for (num = 0, source = sourcelist;
|
||||
source != NULL && source->thisSource != NULL;
|
||||
num++, source = source->nextSource);
|
||||
|
||||
result = (char**)s_malloc((1+num)*sizeof(char*));
|
||||
if(num > 0)
|
||||
for(i =0, source = sourcelist; i<num; i++, source = source->nextSource)
|
||||
result[i] = source->thisSource->filename;
|
||||
result[num] = NULL;
|
||||
return(result);
|
||||
}
|
||||
|
||||
char **
|
||||
buildSItemList(sourcelist)
|
||||
SList sourcelist;
|
||||
{
|
||||
char **result;
|
||||
int num, i;
|
||||
SList source;
|
||||
|
||||
/* find the length of the sidlist in the question */
|
||||
|
||||
for(num = 0, source = sourcelist;
|
||||
source != NULL;
|
||||
num++, source = source->nextSource);
|
||||
|
||||
result = (char**) s_malloc((1+num)*sizeof(char*));
|
||||
if(num > 0)
|
||||
for(i =0, source = sourcelist; i<num; i++, source = source->nextSource)
|
||||
if(source->thisSource != NULL)
|
||||
result[i] = source->thisSource->name;
|
||||
result[num] = NULL;
|
||||
return(result);
|
||||
}
|
||||
|
||||
static short
|
||||
ReadSourceID(file, sid)
|
||||
FILE *file;
|
||||
SourceID sid;
|
||||
{
|
||||
char temp_string[MAX_SYMBOL_SIZE];
|
||||
char filename[MAX_SYMBOL_SIZE];
|
||||
short check_result;
|
||||
|
||||
check_result = CheckStartOfStruct("source-id", file);
|
||||
filename[0] = '\0';
|
||||
if(FALSE == check_result){
|
||||
return(false);
|
||||
}
|
||||
if(END_OF_STRUCT_OR_LIST == check_result)
|
||||
{
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* read the slots: */
|
||||
while(TRUE){
|
||||
|
||||
short check_result = ReadSymbol(temp_string, file, MAX_SYMBOL_SIZE);
|
||||
if(END_OF_STRUCT_OR_LIST == check_result) break;
|
||||
if(FALSE == check_result){
|
||||
return(false);
|
||||
}
|
||||
if(0 == strcmp(temp_string, ":filename")) {
|
||||
if (FALSE == ReadString(filename, file, MAX_SYMBOL_SIZE))
|
||||
return(false);
|
||||
sid->filename = s_strdup(filename);
|
||||
}
|
||||
else
|
||||
SkipObject(file);
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
SourceList ReadListOfSources(file)
|
||||
FILE *file;
|
||||
{
|
||||
short check_result;
|
||||
SourceID sid = NULL;
|
||||
SourceList result, this, last;
|
||||
|
||||
/* initialize */
|
||||
this = last = result = NULL;
|
||||
|
||||
if(ReadStartOfList(file) == FALSE)
|
||||
return(NULL);
|
||||
|
||||
while(TRUE) {
|
||||
sid = (SourceID)s_malloc(sizeof(_SourceID));
|
||||
check_result = ReadSourceID(file, sid);
|
||||
if(check_result == END_OF_STRUCT_OR_LIST) {
|
||||
s_free(sid);
|
||||
return(result);
|
||||
}
|
||||
else if(check_result == FALSE)
|
||||
return(result);
|
||||
|
||||
else if(check_result == TRUE) {
|
||||
if(result == NULL)
|
||||
result = this = (SourceList)s_malloc(sizeof(_SourceList));
|
||||
else
|
||||
this = (SourceList)s_malloc(sizeof(_SourceList));
|
||||
this->thisSource = sid;
|
||||
if(last != NULL)
|
||||
last->nextSource = this;
|
||||
last = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*!defined(IN_RMG) && !defined(PFS_THREADS)*/
|
||||
|
||||
/* from util.c */
|
||||
void find_value(source, key, value, value_size)
|
||||
char *source, *key, *value;
|
||||
int value_size;
|
||||
{
|
||||
char ch;
|
||||
long position = 0; /* position in value */
|
||||
char *pos =(char*)strstr(source, key); /* address into source */
|
||||
|
||||
value[0] = '\0'; /* initialize to nothing */
|
||||
|
||||
if(NULL == pos)
|
||||
return;
|
||||
|
||||
pos = pos + strlen(key);
|
||||
ch = *pos;
|
||||
/* skip leading quotes and spaces */
|
||||
while((ch == '\"') || (ch == ' ')) {
|
||||
pos++; ch = *pos;
|
||||
}
|
||||
for(position = 0; pos < source + strlen(source); pos++){
|
||||
if((ch = *pos) == ' ') {
|
||||
value[position] = '\0';
|
||||
return;
|
||||
}
|
||||
value[position] = ch;
|
||||
position++;
|
||||
if(position >= value_size){
|
||||
value[value_size - 1] = '\0';
|
||||
return;
|
||||
}
|
||||
}
|
||||
value[position] = '\0';
|
||||
}
|
||||
|
||||
static boolean
|
||||
ReadSource(WAISSOURCE source, FILE *file)
|
||||
{
|
||||
char temp_string[MAX_SYMBOL_SIZE];
|
||||
char desc_string[DESC_SIZE];
|
||||
short check_result;
|
||||
long port;
|
||||
|
||||
long version;
|
||||
|
||||
/* make sure it's a Source */
|
||||
|
||||
check_result = CheckStartOfStruct("source", file);
|
||||
if(FALSE == check_result){
|
||||
return(false);
|
||||
}
|
||||
if(END_OF_STRUCT_OR_LIST == check_result)
|
||||
{
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
strcpy(source->server, "");
|
||||
strcpy(source->service, "");
|
||||
|
||||
/* read the slots: */
|
||||
while(TRUE){
|
||||
|
||||
short check_result = ReadSymbol(temp_string, file, MAX_SYMBOL_SIZE);
|
||||
if((END_OF_STRUCT_OR_LIST == check_result) ||
|
||||
(EOF == check_result))
|
||||
break;
|
||||
if(FALSE == check_result){
|
||||
return(false);
|
||||
}
|
||||
if(0 == strcmp(temp_string, ":version")) {
|
||||
if(FALSE == ReadLong(file, &version))
|
||||
return(false);
|
||||
}
|
||||
else if(0 == strcmp(temp_string, ":ip-name")) {
|
||||
if(FALSE == ReadString(temp_string, file, MAX_SYMBOL_SIZE))
|
||||
return(false);
|
||||
strcpy(source->server, temp_string);
|
||||
}
|
||||
else if(0 == strcmp(temp_string, ":ip-address")) {
|
||||
if(FALSE == ReadString(temp_string, file, MAX_SYMBOL_SIZE))
|
||||
return(false);
|
||||
strcpy(source->server, temp_string);
|
||||
}
|
||||
else if(0 == strcmp(temp_string, ":configuration")) {
|
||||
if(FALSE == ReadString(temp_string, file, MAX_SYMBOL_SIZE))
|
||||
return(false);
|
||||
find_value(temp_string, "IPAddress", source->server, STRINGSIZE);
|
||||
find_value(temp_string, "RemotePort", source->service, STRINGSIZE);
|
||||
}
|
||||
else if(0 == strcmp(temp_string, ":tcp-port")) {
|
||||
if(FALSE == ReadLong(file, &port))
|
||||
return(false);
|
||||
sprintf(source->service,"%d", port);
|
||||
}
|
||||
else if(0 == strcmp(temp_string, ":port")) {
|
||||
if(FALSE == ReadLong(file, &port))
|
||||
return(false);
|
||||
sprintf(source->service,"%d", port);
|
||||
}
|
||||
else if(0 == strcmp(temp_string, ":maintainer")) {
|
||||
if(FALSE == ReadString(temp_string, file, MAX_SYMBOL_SIZE))
|
||||
return(false);
|
||||
if(source->maintainer != NULL) s_free(source->maintainer);
|
||||
source->maintainer = s_strdup(temp_string);
|
||||
}
|
||||
else if(0 == strcmp(temp_string, ":database-name")) {
|
||||
if(FALSE == ReadString(temp_string, file, MAX_SYMBOL_SIZE))
|
||||
return(false);
|
||||
strcpy(source->database, temp_string);
|
||||
}
|
||||
else if(0 == strcmp(temp_string, ":cost")) {
|
||||
double cost;
|
||||
if(FALSE == ReadDouble(file, &cost))
|
||||
return(false);
|
||||
sprintf(source->cost, "%.2f", cost);
|
||||
}
|
||||
else if(0 == strcmp(temp_string, ":cost-unit")) {
|
||||
if(FALSE == ReadSymbol(temp_string, file, MAX_SYMBOL_SIZE))
|
||||
return(false);
|
||||
strcpy(source->units, temp_string);
|
||||
}
|
||||
else if(0 == strcmp(temp_string, ":subjects")) {
|
||||
if(FALSE == ReadString(desc_string, file, DESC_SIZE))
|
||||
return(false);
|
||||
if(source->subjects != NULL) s_free(source->subjects);
|
||||
source->subjects = s_strdup(desc_string);
|
||||
}
|
||||
else if(0 == strcmp(temp_string, ":description")) {
|
||||
if(FALSE == ReadString(desc_string, file, DESC_SIZE))
|
||||
return(false);
|
||||
if(source->description != NULL) s_free(source->description);
|
||||
source->description = s_strdup(desc_string);
|
||||
}
|
||||
else if(0 == strcmp(temp_string, ":update-time")) {
|
||||
if(EOF == SkipObject(file)) break;
|
||||
}
|
||||
else
|
||||
if(EOF == SkipObject(file)) break; /* we don't know the key, so we don't know how
|
||||
to interpret the value, skip it */
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
static boolean
|
||||
ReadSourceFile(WAISSOURCE asource, char *filename, char *directory)
|
||||
{
|
||||
FILE *fp;
|
||||
char pathname[MAX_FILENAME_LEN+1];
|
||||
boolean result;
|
||||
|
||||
strncpy(pathname, directory, MAX_FILENAME_LEN);
|
||||
strncat(pathname, filename, MAX_FILENAME_LEN);
|
||||
|
||||
if((fp = locked_fopen(pathname, "r")) == NULL)
|
||||
return FALSE;
|
||||
|
||||
asource->name = s_strdup(filename);
|
||||
asource->directory = s_strdup(directory);
|
||||
|
||||
result = ReadSource(asource, fp);
|
||||
locked_fclose_A(fp,pathname,TRUE);
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
/* Read sourcefile "name" from one of the directories in "sourcepath"
|
||||
and add to Sources (creating that if neccessary). Return source found
|
||||
to make it quicker next time */
|
||||
static WAISSOURCE
|
||||
loadSource(name, sourcepath)
|
||||
char *name;
|
||||
char *sourcepath;
|
||||
{
|
||||
char *i, *p, source_dir[MAX_FILENAME_LEN];
|
||||
WAISSOURCE source = waissource_alloc();
|
||||
|
||||
/*
|
||||
if(sourcepath == NULL || sourcepath[0] == 0) {
|
||||
if((sourcepath = (char*)getenv("WAISSOURCEPATH")) == NULL)
|
||||
return NULL;
|
||||
}
|
||||
*/
|
||||
|
||||
for (p = sourcepath, i = p;
|
||||
i != NULL;
|
||||
p = i+1) {
|
||||
if((i = (char*)strchr(p, ':')) == NULL)
|
||||
strcpy(source_dir, p);
|
||||
else {
|
||||
strncpy(source_dir, p, i-p);
|
||||
source_dir[i-p] = 0;
|
||||
}
|
||||
|
||||
if(ReadSourceFile(source, name, source_dir)) {
|
||||
set_connection(source);
|
||||
TH_APPEND_ITEM(source,WaisSources,WAISSOURCE);
|
||||
return (source);
|
||||
}
|
||||
}
|
||||
s_free(source);
|
||||
source = NULL;
|
||||
return (source);
|
||||
}
|
||||
|
||||
static int
|
||||
match_connection(WAISSOURCE asource, WAISSOURCE bsource)
|
||||
{
|
||||
return (!strcmp(asource->server,bsource->server) &&
|
||||
!strcmp(asource->service,bsource->service));
|
||||
}
|
||||
|
||||
/* Try and copy parameters from another source we've already looked at */
|
||||
static void
|
||||
set_connection(WAISSOURCE source)
|
||||
{
|
||||
WAISSOURCE s = WaisSources;
|
||||
TH_FIND_OBJFNCTN_LIST(s,source,match_connection,WAISSOURCE)
|
||||
if (s) {
|
||||
source->connection = s->connection;
|
||||
source->buffer_length = s->buffer_length;
|
||||
source->initp = s->initp;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(IN_RMG) && !defined(PFS_THREADS)
|
||||
#ifdef NEVERDEFINED
|
||||
boolean newSourcep(name)
|
||||
char *name;
|
||||
{
|
||||
SList s;
|
||||
|
||||
for (s = Sources; s != NULL; s = s->nextSource)
|
||||
if((s->thisSource != NULL) &&
|
||||
!strcmp(name, s->thisSource->name))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
boolean is_source(name, test)
|
||||
char *name;
|
||||
boolean test;
|
||||
{
|
||||
char lastchar;
|
||||
|
||||
lastchar = name[strlen(name)-1];
|
||||
if(test)
|
||||
return ((strlen(name) > 4) &&
|
||||
strstr(name, ".src") &&
|
||||
(!strcmp(".src", strstr(name, ".src"))));
|
||||
else
|
||||
return (lastchar != '~' &&
|
||||
lastchar != '#' &&
|
||||
strcmp(name, ".") &&
|
||||
strcmp(name, ".."));
|
||||
}
|
||||
|
||||
#ifdef USINGSOURCEITEMS
|
||||
static boolean newSource(name)
|
||||
char *name;
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i =0; i < NumSources; i++)
|
||||
if(!strcmp(name, Source_items[i]))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
issfile(dp)
|
||||
struct dirent *dp;
|
||||
{
|
||||
return(is_source(dp->d_name, TRUE) &&
|
||||
newSource(dp->d_name));
|
||||
}
|
||||
|
||||
void SortSourceNames(n)
|
||||
int n;
|
||||
{
|
||||
boolean Changed = TRUE;
|
||||
int i;
|
||||
char *qi;
|
||||
|
||||
while(Changed) {
|
||||
Changed = FALSE;
|
||||
for(i = 0; i < n-1; i++)
|
||||
if(0 < strcasecmp(Source_items[i], Source_items[i+1])) {
|
||||
Changed = TRUE;
|
||||
qi = Source_items[i];
|
||||
Source_items[i] = Source_items[i+1];
|
||||
Source_items[i+1] = qi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GetSourceNames(directory)
|
||||
char *directory;
|
||||
{
|
||||
/* Note result is returned in global Source_items */
|
||||
struct dirent **list;
|
||||
int i, j;
|
||||
assert(P_IS_THIS_THREAD_MASTER());
|
||||
if ((j = scandir(directory, &list, issfile, alphasort)) < 0) {
|
||||
PrintStatus(STATUS_INFO, STATUS_HIGH, "Error on open of source directory: %s.\n", directory);
|
||||
return;
|
||||
}
|
||||
|
||||
if(NumSources > 0)
|
||||
Source_items = (char**) s_realloc(Source_items, (NumSources+j+1) * sizeof(char*));
|
||||
else {
|
||||
if(Source_items != NULL) {
|
||||
for (i = 0; Source_items[i] != NULL; i++) s_free(Source_items[i]);
|
||||
s_free(Source_items);
|
||||
}
|
||||
Source_items = (char**) s_malloc((j+1) * sizeof(char*));
|
||||
}
|
||||
|
||||
for (i = 0; i < j; i++) {
|
||||
Source_items[i+NumSources] = s_strdup(list[i]->d_name);
|
||||
s_free(list[i]);
|
||||
}
|
||||
|
||||
NumSources+=j;
|
||||
SortSourceNames(NumSources);
|
||||
Source_items[NumSources] = NULL;
|
||||
|
||||
s_free(list);
|
||||
}
|
||||
#endif /*USINGSOURCEITEMS*/
|
||||
/* read all the sources from a directory. If test is true, only files ending
|
||||
in .src are valid
|
||||
*/
|
||||
|
||||
/* Not used */
|
||||
#if !defined(IN_RMG)
|
||||
static void
|
||||
ReadSourceDirectory(directory, test)
|
||||
char *directory;
|
||||
boolean test;
|
||||
{
|
||||
char filename[MAX_FILENAME_LEN];
|
||||
FILE *fp;
|
||||
int i, j , newNumSources;
|
||||
SList Last;
|
||||
Source source;
|
||||
struct dirent **list;
|
||||
|
||||
assert(P_IS_THIS_THREAD_MASTER());
|
||||
if ((j = scandir(directory, &list, NULL, NULL)) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(Sources == NULL)
|
||||
Sources = makeSList(NULL, NULL);
|
||||
|
||||
for(Last = Sources; Last->nextSource != NULL; Last = Last->nextSource);
|
||||
|
||||
for (i = 0; i < j; i++) {
|
||||
if (is_source(list[i]->d_name, test)) {
|
||||
if(newSourcep(list[i]->d_name)) {
|
||||
strcpy(filename, directory);
|
||||
strcat(filename, list[i]->d_name);
|
||||
if ((fp = locked_fopen(filename, "r")) != NULL) {
|
||||
source = (Source)s_malloc(sizeof(_Source));
|
||||
memset(source, 0, sizeof(_Source));
|
||||
source->initp = FALSE;
|
||||
source->name = s_strdup(list[i]->d_name);
|
||||
source->directory = s_strdup(directory);
|
||||
ReadSource(source, fp);
|
||||
locked_fclose_A(fp,filename,TRUE);
|
||||
if(Last->thisSource == NULL)
|
||||
Last->thisSource = source;
|
||||
else {
|
||||
Last->nextSource = makeSList(source, NULL);
|
||||
Last = Last->nextSource;
|
||||
}
|
||||
NumSources++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free((char *)list);
|
||||
}
|
||||
#endif
|
||||
|
||||
void WriteSource(directory, source, overwrite)
|
||||
char *directory;
|
||||
Source source;
|
||||
boolean overwrite;
|
||||
{
|
||||
char filename[MAX_FILENAME_LEN];
|
||||
FILE *fp;
|
||||
|
||||
strcpy(filename, directory);
|
||||
strcat(filename, source->name);
|
||||
|
||||
if (overwrite == FALSE)
|
||||
if ((fp = locked_fopen(filename, "r")) != NULL) {
|
||||
PrintStatus(STATUS_INFO, STATUS_HIGH,
|
||||
"File %s exists, click again to overwrite.\n", filename);
|
||||
locked_fclose_A(fp,filename,TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((fp = locked_fopen(filename, "w")) == NULL) {
|
||||
PrintStatus(STATUS_INFO, STATUS_HIGH, "Error opening %s.\n", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(fp, "(:source\n :version 3\n");
|
||||
if(source->server != NULL)
|
||||
if(source->server[0] != 0)
|
||||
if(isdigit(source->server[0]))
|
||||
fprintf(fp, " :ip-address \"%s\"\n", source->server);
|
||||
else
|
||||
fprintf(fp, " :ip-name \"%s\"\n", source->server);
|
||||
|
||||
if(source->service != NULL)
|
||||
if(source->service[0] != 0)
|
||||
fprintf(fp, " :tcp-port %s\n", source->service);
|
||||
|
||||
fprintf(fp, " :database-name \"%s\"\n", source->database);
|
||||
if(source->cost != NULL)
|
||||
if(source->cost[0] != 0)
|
||||
fprintf(fp, " :cost %s \n", source->cost);
|
||||
else
|
||||
fprintf(fp, " :cost 0.00 \n");
|
||||
|
||||
if(source->units != NULL)
|
||||
if(source->units[0] != 0)
|
||||
fprintf(fp, " :cost-unit %s \n", source->units);
|
||||
else
|
||||
fprintf(fp, " :cost-unit :free \n");
|
||||
|
||||
if(source->maintainer != NULL)
|
||||
if(source->maintainer[0] != 0)
|
||||
fprintf(fp, " :maintainer \"%s\"\n",
|
||||
source->maintainer);
|
||||
else
|
||||
fprintf(fp, " :maintainer \"%s\"\n",
|
||||
current_user_name());
|
||||
|
||||
if(source->description != NULL)
|
||||
if(source->description[0] != 0) {
|
||||
fprintf(fp, " :description ");
|
||||
WriteString(source->description, fp);
|
||||
}
|
||||
else
|
||||
fprintf(fp, " :description \"Created with %s by %s on %s.\"\n",
|
||||
command_name, current_user_name(), printable_time());
|
||||
|
||||
fprintf(fp, "\n)");
|
||||
locked_fclose_A(fp,filename,FALSE);
|
||||
}
|
||||
SourceList
|
||||
makeSourceList(source, rest)
|
||||
SourceID source;
|
||||
SourceList rest;
|
||||
{
|
||||
SourceList result;
|
||||
if((result = (SourceList)s_malloc(sizeof(_SourceList))) != NULL) {
|
||||
result->thisSource = source;
|
||||
result->nextSource = rest;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
SList
|
||||
makeSList(source, rest)
|
||||
Source source;
|
||||
SList rest;
|
||||
{
|
||||
SList result;
|
||||
if((result = (SList)s_malloc(sizeof(_SList))) != NULL) {
|
||||
result->thisSource = source;
|
||||
result->nextSource = rest;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
void FreeSource(source)
|
||||
Source source;
|
||||
{
|
||||
if (source != NULL) {
|
||||
if(source->name != NULL)
|
||||
s_free (source->name);
|
||||
if(source->directory != NULL)
|
||||
s_free (source->directory);
|
||||
if(source->description != NULL)
|
||||
s_free (source->description);
|
||||
if(source->maintainer != NULL)
|
||||
s_free (source->maintainer);
|
||||
s_free(source);
|
||||
}
|
||||
}
|
||||
#endif /*!IN_RMG && !PFS_THREADS*/
|
||||
|
||||
/* Find the source name, in either Sources, or it not found try and load it
|
||||
from anywhere in sourcepath */
|
||||
WAISSOURCE
|
||||
findsource(char *name, char *sourcepath)
|
||||
{
|
||||
WAISSOURCE asource = WaisSources;
|
||||
TH_FIND_STRING_LIST(asource,name,name,WAISSOURCE);
|
||||
if (asource)
|
||||
return asource;
|
||||
return (loadSource(name, sourcepath));
|
||||
}
|
||||
|
||||
#if !defined(IN_RMG) && !defined(PFS_THREADS)
|
||||
|
||||
void
|
||||
format_source_cost(str,source)
|
||||
char *str;
|
||||
Source source;
|
||||
{
|
||||
sprintf(str,"Free");
|
||||
if ((source->units != NULL) && (source->cost != NULL)) {
|
||||
|
||||
if(0 == strcmp(source->units, ":dollars-per-query"))
|
||||
sprintf(str,"$%s/query",source->cost);
|
||||
|
||||
if(0 == strcmp(source->units, ":dollars-per-minute"))
|
||||
sprintf(str,"$%s/minute",source->cost);
|
||||
|
||||
if(0 == strcmp(source->units, ":dollars-per-retrieval"))
|
||||
sprintf(str,"$%s/retrieval",source->cost);
|
||||
|
||||
if(0 == strcmp(source->units, ":dollars-per-session"))
|
||||
sprintf(str,"$%s/session",source->cost);
|
||||
|
||||
if(0 == strcmp(source->units, ":other"))
|
||||
sprintf(str,"Special",source->cost);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
freeSourceList(slist)
|
||||
SourceList slist;
|
||||
{
|
||||
SourceList sl;
|
||||
while(slist != NULL) {
|
||||
sl = slist;
|
||||
freeSourceID(sl->thisSource);
|
||||
slist = sl->nextSource;
|
||||
s_free(sl);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#include <sockets.h>
|
||||
*/
|
||||
|
||||
/*#define FORWARDER_SERVER "quake"*/
|
||||
/* send an init message to the source. A side effect is that the
|
||||
negotiation of buffer sizes. The final size is put in
|
||||
source->buffer_length
|
||||
*/
|
||||
#ifdef NEVERDEFINED
|
||||
boolean init_for_source(source, request, length, response)
|
||||
Source source;
|
||||
char *request;
|
||||
long length;
|
||||
char *response;
|
||||
{
|
||||
char userInfo[500];
|
||||
char message[500];
|
||||
char hostname[80];
|
||||
char domain[80];
|
||||
|
||||
gethostname(hostname, 80);
|
||||
getdomainname(domain, 80);
|
||||
#ifdef TELL_USER
|
||||
sprintf(userInfo, "%s %s, from host: %s.%s, user: %s",
|
||||
command_name, VERSION, hostname, domain, getenv("USER"));
|
||||
#else
|
||||
sprintf(userInfo, "%s %s, from host: %s.%s",
|
||||
command_name, VERSION, hostname, domain);
|
||||
#endif
|
||||
|
||||
if(source->initp == FALSE) {
|
||||
if(source->server[0] == 0)
|
||||
source->connection = NULL;
|
||||
else {
|
||||
source->connection = connect_to_server(source->server,
|
||||
atoi(source->service));
|
||||
#ifdef FORWARDER_SERVER
|
||||
|
||||
#ifndef FORWARDER_SERVICE
|
||||
#define FORWARDER_SERVICE "210"
|
||||
#endif
|
||||
|
||||
if(source->connection == NULL) {
|
||||
strncat(source->database, "@", STRINGSIZE);
|
||||
strncat(source->database, source->server, STRINGSIZE);
|
||||
strncat(source->database, ":", STRINGSIZE);
|
||||
strncat(source->database, source->service, STRINGSIZE);
|
||||
strncpy(source->server, FORWARDER_SERVER, STRINGSIZE);
|
||||
strncpy(source->service, FORWARDER_SERVICE, STRINGSIZE);
|
||||
source->connection = connect_to_server(source->server,
|
||||
atoi(source->service));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (source->connection == NULL) {
|
||||
PrintStatus(STATUS_URGENT, STATUS_HIGH, "Bad Connection to server.");
|
||||
source->initp = FALSE;
|
||||
return source->initp;
|
||||
}
|
||||
}
|
||||
source->buffer_length =
|
||||
init_connection(request, response,
|
||||
length,
|
||||
source->connection,
|
||||
userInfo);
|
||||
|
||||
if (source->buffer_length < 0) {
|
||||
PrintStatus(STATUS_URGENT, STATUS_HIGH,
|
||||
"\nError connecting to server: %s service: %s.",
|
||||
source->server, source->service);
|
||||
source->initp = FALSE;
|
||||
}
|
||||
else {
|
||||
SList s;
|
||||
|
||||
source->initp = TRUE;
|
||||
|
||||
for (s = Sources; s != NULL; s = s->nextSource) {
|
||||
if (s->thisSource != source) {
|
||||
if (strcmp(s->thisSource->server, source->server) == 0 &&
|
||||
strcmp(s->thisSource->service, source->service) == 0) {
|
||||
s->thisSource->connection = source->connection;
|
||||
s->thisSource->buffer_length = source->buffer_length;
|
||||
s->thisSource->initp = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return source->initp;
|
||||
}
|
||||
return source->initp;
|
||||
}
|
||||
#endif
|
||||
#endif /*!IN_RMG && PFS_THREADS*/
|
||||
|
||||
104
prospero/lib/psrv/wais_gw/source.h
Normal file
104
prospero/lib/psrv/wais_gw/source.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/* WIDE AREA INFORMATION SERVER SOFTWARE:
|
||||
Developed by Thinking Machines Corporation and put into the public
|
||||
domain with no guarantees or restrictions.
|
||||
|
||||
This is part of the user-interface for the WAIS software.
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _H_SOURCE
|
||||
#define _H_SOURCE
|
||||
|
||||
#define STRINGSIZE 256
|
||||
|
||||
#ifndef boolean
|
||||
#define boolean int
|
||||
#endif
|
||||
/* #include <cdialect.h> */
|
||||
|
||||
#ifdef IN_RMG
|
||||
#include <pfs.h> /* for ALLOCATOR_CONSISTENCY_CHECK*/
|
||||
#endif
|
||||
|
||||
typedef struct SourceID {
|
||||
char *filename;
|
||||
} _SourceID, *SourceID;
|
||||
|
||||
struct waissource{
|
||||
#ifdef ALLOCATOR_CONSISTENCY_CHECK
|
||||
int consistency;
|
||||
#endif
|
||||
char *name;
|
||||
char *directory;
|
||||
char server[STRINGSIZE];
|
||||
char service[STRINGSIZE];
|
||||
char database[STRINGSIZE];
|
||||
char cost[STRINGSIZE];
|
||||
char units[STRINGSIZE];
|
||||
char *description;
|
||||
FILE *connection;
|
||||
long buffer_length;
|
||||
boolean initp;
|
||||
char *maintainer;
|
||||
char *subjects;
|
||||
#ifdef IN_RMG
|
||||
struct waissource *next;
|
||||
struct waissource *previous;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct waissource *WAISSOURCE;
|
||||
typedef struct waissource WAISSOURCE_ST;
|
||||
|
||||
/* functions */
|
||||
|
||||
extern WAISSOURCE waissource_alloc();
|
||||
extern void waissource_free(WAISSOURCE source);
|
||||
extern void waissource_lfree(WAISSOURCE source);
|
||||
extern void waissource_freespares();
|
||||
#ifdef PFS_THREADS
|
||||
extern p_th_mutex p_th_mutexWAISSOURCE;
|
||||
#endif
|
||||
#ifdef NEVERDEFINED
|
||||
/* Uses SourceList which is obsoleted by waissource
|
||||
rebuild if need these functions in Prospero */
|
||||
#if !defined(IN_RMG) && !defined(PFS_THREADS)
|
||||
void freeSourceID (SourceID sid);
|
||||
SourceID copysourceID (SourceID sid);
|
||||
char** buildSourceItemList (SourceList sourcelist);
|
||||
char** buildSItemList (SList sourcelist);
|
||||
static short ReadSourceID (FILE* file, SourceID sid);
|
||||
SourceList ReadListOfSources (FILE* fp);
|
||||
#endif
|
||||
#endif
|
||||
static boolean ReadSource (WAISSOURCE source, FILE* file);
|
||||
static boolean ReadSourceFile (WAISSOURCE asource, char* filename, char* directory);
|
||||
static WAISSOURCE loadSource (char* name, char* sourcepath);
|
||||
static void set_connection (WAISSOURCE source);
|
||||
#ifdef NEVERDEFINED
|
||||
#if !defined(IN_RMG) && !defined(PFS_THREADS)
|
||||
boolean newSourcep (char* name);
|
||||
boolean is_source (char* name, boolean test);
|
||||
void SortSourceNames (int n);
|
||||
void GetSourceNames (char* directory);
|
||||
static void ReadSourceDirectory (char* directory, boolean test);
|
||||
void WriteSource (char* directory, Source source, boolean overwrite);
|
||||
SourceList makeSourceList (SourceID source, SourceList rest);
|
||||
SList makeSList (Source source, SList rest);
|
||||
void FreeSource (Source source);
|
||||
void FreeSources (SList sources);
|
||||
#endif
|
||||
#endif
|
||||
WAISSOURCE findsource (char* name, char* sourcepath);
|
||||
#ifdef NEVERDEFINED
|
||||
#if !defined(IN_RMG) && !defined(PFS_THREADS)
|
||||
Source findSource (int n);
|
||||
void format_source_cost (char* str, Source source);
|
||||
void freeSource (SourceID sourceID);
|
||||
void freeSourceList (SourceList slist);
|
||||
boolean init_for_source (Source source, char* request,
|
||||
long length, char* response);
|
||||
#endif /*!IN_RMG && !PFS_THREADS */
|
||||
#endif
|
||||
#endif
|
||||
138
prospero/lib/psrv/wais_gw/sourcealloc.c
Normal file
138
prospero/lib/psrv/wais_gw/sourcealloc.c
Normal file
@@ -0,0 +1,138 @@
|
||||
/* 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 "buffalloc.h"
|
||||
#include <pfs.h>
|
||||
#include <pfs_threads.h>
|
||||
#include <mitra_macros.h>
|
||||
#include "source.h"
|
||||
#define Channel_Illegal 0;
|
||||
|
||||
EXTERN_ALLOC_DECL(WAISSOURCE);
|
||||
|
||||
static WAISSOURCE lfree = NULL; /* Free waissources */
|
||||
/* 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 waissource_count = 0;
|
||||
int waissource_max = 0;
|
||||
|
||||
|
||||
/************* Standard routines to alloc, free and copy *************/
|
||||
/*
|
||||
* waissource_alloc - allocate and initialize WAISSOURCE structure
|
||||
*
|
||||
* returns a pointer to an initialized structure of type
|
||||
* WAISSOURCE. If it is unable to allocate such a structure, it
|
||||
* signals out_of_memory();
|
||||
*/
|
||||
|
||||
WAISSOURCE
|
||||
waissource_alloc()
|
||||
{
|
||||
WAISSOURCE awaissource;
|
||||
|
||||
TH_STRUC_ALLOC(waissource,WAISSOURCE,awaissource);
|
||||
awaissource->name = NULL;
|
||||
awaissource->directory = NULL;
|
||||
awaissource->description = NULL;
|
||||
awaissource->connection = NULL;
|
||||
awaissource->maintainer = NULL;
|
||||
awaissource->subjects = NULL;
|
||||
return(awaissource);
|
||||
}
|
||||
|
||||
/*
|
||||
* waissource_free - free a WAISSOURCE structure
|
||||
*
|
||||
* waissource_free takes a pointer to a WAISSOURCE structure and adds it to
|
||||
* the free list for later reuse.
|
||||
*/
|
||||
void
|
||||
waissource_free(WAISSOURCE awaissource)
|
||||
{
|
||||
stfree(awaissource->name); awaissource->name = NULL;
|
||||
stfree(awaissource->directory); awaissource->directory = NULL;
|
||||
stfree(awaissource->description); awaissource->description = NULL;
|
||||
stfree(awaissource->connection); awaissource->connection = NULL;
|
||||
stfree(awaissource->maintainer); awaissource->maintainer = NULL;
|
||||
stfree(awaissource->subjects); awaissource->subjects = NULL;
|
||||
TH_STRUC_FREE(waissource,WAISSOURCE,awaissource);
|
||||
}
|
||||
|
||||
/*
|
||||
* waissource_lfree - free a linked list of WAISSOURCE structures.
|
||||
*
|
||||
* waissource_lfree takes a pointer to a waissource structure frees it and
|
||||
* any linked
|
||||
* WAISSOURCE structures. It is used to free an entire list of WAISSOURCE
|
||||
* structures.
|
||||
*/
|
||||
void
|
||||
waissource_lfree(awaissource)
|
||||
WAISSOURCE awaissource;
|
||||
{
|
||||
TH_STRUC_LFREE(WAISSOURCE,awaissource,waissource_free);
|
||||
}
|
||||
|
||||
void
|
||||
waissource_freespares()
|
||||
{
|
||||
TH_FREESPARES(waissource,WAISSOURCE);
|
||||
}
|
||||
|
||||
#ifdef NEVERDEFINED
|
||||
/*
|
||||
* waissource_copy - allocates a new waissource structure and
|
||||
* initializes it with a copy of another
|
||||
* waissource, v.
|
||||
*
|
||||
* If r is non-zero, successive waissources will be
|
||||
* iteratively copied.
|
||||
*
|
||||
* awaissource-previous will always be null on the first link, and
|
||||
* will be appropriately filled in for iteratively copied links.
|
||||
*
|
||||
* waissource_copy returns a pointer to the new structure of type
|
||||
* WAISSOURCE. If it is unable to allocate such a structure, it
|
||||
* returns NULL.
|
||||
*
|
||||
* waissource_copy will recursively copy the link associated with
|
||||
* a waissource and
|
||||
* its associated attributes.
|
||||
*/
|
||||
|
||||
WAISSOURCE
|
||||
waissource_copy(f,r)
|
||||
WAISSOURCE f;
|
||||
int r; /* Currently ignored. */
|
||||
{
|
||||
WAISSOURCE nf;
|
||||
WAISSOURCE snf; /* Start of the chain of new links */
|
||||
WAISSOURCE tf; /* Temporary link pointer */
|
||||
|
||||
nf = waissource_alloc();
|
||||
snf = nf;
|
||||
|
||||
copyeach:
|
||||
|
||||
/* Copy f into nf */
|
||||
#ifdef ALLOCATOR_CONSISTENCY_CHECK
|
||||
assert(f->consistency == INUSE_PATTERN);
|
||||
#endif
|
||||
LOCAL STUFF NOT DEFINED
|
||||
if(r && f->next) {
|
||||
f = f->next;
|
||||
tf = nf;
|
||||
nf = waissource_alloc();
|
||||
nf->previous = tf;
|
||||
tf->next = nf;
|
||||
goto copyeach;
|
||||
}
|
||||
|
||||
return(snf);
|
||||
}
|
||||
|
||||
#endif
|
||||
BIN
prospero/lib/psrv/wais_gw/sourceparse
Normal file
BIN
prospero/lib/psrv/wais_gw/sourceparse
Normal file
Binary file not shown.
20
prospero/lib/psrv/wais_gw/sourceparse.c
Normal file
20
prospero/lib/psrv/wais_gw/sourceparse.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include "source.h"
|
||||
|
||||
void
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char sourcename[512];
|
||||
|
||||
WAISSOURCE source = waissource_alloc();
|
||||
|
||||
sprintf(sourcename,"%s.src", argv[1]);
|
||||
|
||||
source = findsource(sourcename,
|
||||
"/usr/local/wais/wais-sources/");
|
||||
if (source == NULL) { fprintf(stderr,"Error finding source.\n"); }
|
||||
else {
|
||||
printf("%s %s %s\n",source->server, source->name, source->service);
|
||||
}
|
||||
}
|
||||
186
prospero/lib/psrv/wais_gw/ustubs.c
Normal file
186
prospero/lib/psrv/wais_gw/ustubs.c
Normal file
@@ -0,0 +1,186 @@
|
||||
/* WIDE AREA INFORMATION SERVER SOFTWARE:
|
||||
Developed by Thinking Machines Corporation and put into the public
|
||||
domain with no guarantees or restrictions.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char *RCSid = "$Header: /buzza/cvsroot/technologies/archie-support/prospero/lib/psrv/wais_gw/ustubs.c,v 1.1.1.1 1999/03/18 16:50:52 pedro Exp $";
|
||||
#endif
|
||||
|
||||
/* Change log:
|
||||
* $Log: ustubs.c,v $
|
||||
* Revision 1.1.1.1 1999/03/18 16:50:52 pedro
|
||||
* This modules includes the prosper server and the berkeley db code used
|
||||
* in Archie
|
||||
*
|
||||
* Revision 1.1.1.1 1994/08/31 16:33:09 bajan
|
||||
* New Prospero release
|
||||
*
|
||||
* Revision 1.2 94/04/19 00:29:17 swa
|
||||
* (mitra) assert(P_IS_THIS_THREAD_MASTER()) added in places.
|
||||
* Added tests for SOLARIS
|
||||
*
|
||||
* Revision 1.1 93/11/10 13:35:08 swa
|
||||
* Initial revision
|
||||
*
|
||||
* Revision 1.4 92/05/06 17:35:13 jonathan
|
||||
* Modified some #if's for NeXT and Mach.
|
||||
*
|
||||
* Revision 1.3 92/03/06 11:08:49 jonathan
|
||||
* fixed incompatible return type error in HP version of getwd. Thanks to
|
||||
* cshotton@oac.hsc.uth.tmc.edu.
|
||||
*
|
||||
* Revision 1.2 92/02/12 13:54:29 jonathan
|
||||
* Added "$Log" so RCS will put the log message in the header
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* stubs for silly non-ansi c compilers */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#include "ustubs.h"
|
||||
#include "futil.h" /* for MAX_FILENAME_LEN */
|
||||
#include "cutil.h" /* for substrcmp and NULL */
|
||||
#include <pmachine.h> /* For Solaris */
|
||||
#include <stdlib.h> /* SOLARIS: for rand and srand */
|
||||
#include <pfs_threads.h> /* For P_IS_THIS_THREAD_MASTER */
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#if (defined(__svr4__) || defined(hpux) || defined(SCOUNIX)) && !defined(SOLARIS)
|
||||
char*
|
||||
getwd(char* pathname)
|
||||
{
|
||||
return((char*)getcwd(pathname, MAX_FILENAME_LEN));
|
||||
}
|
||||
|
||||
long
|
||||
random(void)
|
||||
{
|
||||
assert(P_IS_THIS_THREAD_MASTER()); /*SOLARIS: rand, srand & random MT-Unsafe */
|
||||
return(rand());
|
||||
}
|
||||
|
||||
|
||||
long
|
||||
srandom(unsigned long seed)
|
||||
{
|
||||
assert(P_IS_THIS_THREAD_MASTER()); /*SOLARIS: rand, srand & random MT-Unsafe */
|
||||
srand(seed);
|
||||
return(0);
|
||||
}
|
||||
|
||||
long
|
||||
sigmask(long sig)
|
||||
{
|
||||
}
|
||||
|
||||
long
|
||||
sigblock(long mask)
|
||||
{
|
||||
}
|
||||
|
||||
long
|
||||
sigsetmask(long mask)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
#if (defined(__svr4__) || defined(hpux))
|
||||
#include <sys/systeminfo.h>
|
||||
|
||||
long
|
||||
gethostname(char* hostname,long len)
|
||||
{
|
||||
return(sysinfo(SI_HOSTNAME,hostname,len));
|
||||
}
|
||||
|
||||
#endif /* def SYSV */
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#ifndef ANSI_LIKE /* memmove is an ANSI function not defined by K&R */
|
||||
#ifndef hpux /* but HP defines it */
|
||||
void*
|
||||
memmove(void* str1,void* str2,size_t n)
|
||||
{
|
||||
#ifdef M_XENIX
|
||||
memcpy((char*)str2,(char*)str1,(long)n); /* hope it works! */
|
||||
#else /* ndef M_XENIX */
|
||||
bcopy((char*)str2,(char*)str1,(long)n);
|
||||
#endif /* ndef M_XENIX */
|
||||
return(str1);
|
||||
}
|
||||
#endif /* ndef hpux */
|
||||
|
||||
#else /* ansi is defined */
|
||||
|
||||
#ifdef __GNUC__ /* we are ansi like, are we gcc */
|
||||
|
||||
#if !(defined(NeXT) || defined(Mach) || defined(__svr4__))
|
||||
/* and we are not on a next or solaris ! */
|
||||
|
||||
void*
|
||||
memmove(void* str1,void* str2,size_t n)
|
||||
{
|
||||
bcopy((char*)str2,(char*)str1,(long)n);
|
||||
return(str1);
|
||||
}
|
||||
|
||||
#endif /* not NeXT or Mach */
|
||||
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#endif /* else ndef ANSI_LIKE */
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#ifndef ANSI_LIKE
|
||||
|
||||
/* atoi is not defined k&r. copied from the book */
|
||||
long
|
||||
atol(char* s)
|
||||
{
|
||||
long i, n, sign;
|
||||
for(i=0; s[i]==' ' || s[i]== 'n' || s[i]=='t'; i++)
|
||||
; /* skip white space */
|
||||
sign = 1;
|
||||
if (s[i] == '+' || s[i] == '-')
|
||||
sign = (s[i++]=='+') ? 1 : -1;
|
||||
for (n=0; s[i] >= '0' && s[i] <= '9'; i++)
|
||||
n= 10 * n + s[i] - '0';
|
||||
return(sign * n);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
char*
|
||||
strstr(char* src,char* sub)
|
||||
{
|
||||
/* this is a poor implementation until the ANSI version catches on */
|
||||
char *ptr;
|
||||
for(ptr = src; (long)ptr <= (long)src + strlen(src) - strlen(sub); ptr++){
|
||||
if(substrcmp(ptr, sub))
|
||||
return(ptr);
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
int
|
||||
remove(char* filename)
|
||||
{
|
||||
return(unlink(filename));
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#endif /* ndef ANSI_LIKE */
|
||||
|
||||
|
||||
|
||||
|
||||
94
prospero/lib/psrv/wais_gw/ustubs.h
Normal file
94
prospero/lib/psrv/wais_gw/ustubs.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/* WIDE AREA INFORMATION SERVER SOFTWARE:
|
||||
Developed by Thinking Machines Corporation and put into the public
|
||||
domain with no guarantees or restrictions.
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* definitions that non-ansi (aka sun) C doesn't provide */
|
||||
|
||||
#ifndef USTUBS_H
|
||||
#define USTUBS_H
|
||||
|
||||
#include "cdialect.h"
|
||||
|
||||
#ifndef ANSI_LIKE
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef M_XENIX
|
||||
#include <string.h>
|
||||
#endif /* ndef M_XENIX */
|
||||
|
||||
#ifndef size_t
|
||||
#ifndef M_XENIX
|
||||
#define size_t unsigned long
|
||||
#endif /* ndf M_XENIX */
|
||||
#endif /* ndef size_t */
|
||||
|
||||
#ifndef ANSI_LIKE
|
||||
#ifndef M_XENIX
|
||||
#define time_t long
|
||||
#endif /* ndef M_XENIX */
|
||||
#endif /* ndef ANSI_LIKE */
|
||||
|
||||
#ifdef K_AND_R /* this might be too general, but it is needed on vaxen */
|
||||
#define void char
|
||||
#endif /* ndef K_AND_R */
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* declare these as C style functions */
|
||||
extern "C"
|
||||
{
|
||||
#endif /* def __cplusplus */
|
||||
|
||||
#ifndef SCOUNIX
|
||||
char *strstr(char *src, char *sub);
|
||||
#endif
|
||||
|
||||
#ifdef SYSV
|
||||
char *getwd (char *pathname);
|
||||
long random(void);
|
||||
long srandom(unsigned long seed);
|
||||
#ifndef SCOUNIX
|
||||
#define rename(f1,f2) {link((f1),(f2)); unlink((f1)); }
|
||||
#endif /*SCOUNIX*/
|
||||
#endif /* defu SYSV */
|
||||
|
||||
#if !(defined(NeXT) || defined(Mach))
|
||||
#ifndef M_XENIX
|
||||
#ifndef cstar
|
||||
char* malloc(size_t size);
|
||||
char* calloc(size_t nelem,size_t elsize);
|
||||
#ifndef SCOUNIX
|
||||
void free(char* ptr);
|
||||
#endif
|
||||
char* realloc(char* ptr,size_t size);
|
||||
#ifndef mips
|
||||
#ifndef hpux
|
||||
#ifndef vax
|
||||
#ifndef SCOUNIX
|
||||
char* memcpy(char* s1,char* s2,size_t c);
|
||||
#endif
|
||||
void* memmove(void* s1,void* s2,size_t n);
|
||||
#endif /* ndef vax */
|
||||
#endif /* ndef hpux */
|
||||
#endif /* ndef mips */
|
||||
char *strcat(char *s1, char *s2);
|
||||
#endif /* ndef cstar */
|
||||
#endif /* ndef M_XENIX */
|
||||
#endif /* not NeXT or Mach */
|
||||
|
||||
long atol(char *s);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* def __cplusplus */
|
||||
|
||||
#else /* def ANSI_LIKE */
|
||||
|
||||
#endif /* else ndef ANSI_LIKE */
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#endif /* ndef USTUBS_H */
|
||||
|
||||
331
prospero/lib/psrv/wais_gw/wais_gw_dsdb.c
Normal file
331
prospero/lib/psrv/wais_gw/wais_gw_dsdb.c
Normal file
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright (c) 1993 by the University of Southern California
|
||||
*
|
||||
* For copying and distribution information, please see the file
|
||||
* <usc-license.h>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <pmachine.h>
|
||||
#include <psite.h> /* for WAIS_SOURCE_DIR */
|
||||
|
||||
#include <ardp.h>
|
||||
#include <pfs.h>
|
||||
#include <pserver.h>
|
||||
#include <psrv.h>
|
||||
#include <perrno.h>
|
||||
#include <plog.h>
|
||||
|
||||
/* Could be local files. */
|
||||
#include "wprot.h"
|
||||
#include "zutil.h" /* for "any" */
|
||||
#include "source.h" /* for Source */
|
||||
#include "inface.h"
|
||||
#include "wais_gw_dsdb.h"
|
||||
#include "ietftype.h"
|
||||
#include "ietftype_parse.h"
|
||||
|
||||
|
||||
/* Definitions of constants */
|
||||
#define MAX_NUM_WAIS_LINKS 3000 /* maximum # of directory links to
|
||||
return before giving up. */
|
||||
|
||||
/* ======= Some forward definitions ============ */
|
||||
static void
|
||||
wsr_to_dirobj(WAISSearchResponse *wsr, P_OBJECT ob, char *host, char *port);
|
||||
static VLINK DocHeader2vl(WAISDocumentHeader *wdh, char *host, char *port);
|
||||
char *
|
||||
read_wais_contents(char *host, char *port, char *type,
|
||||
char *database, char *docid);
|
||||
|
||||
/* This function is passed an empty object which has been initialized with
|
||||
oballoc(). It returns a possibly populated directory and
|
||||
DIRSRV_NOT_FOUND or PSUCCESS. Note that the directory will need
|
||||
to have links within it freed, even if an error code is returned. */
|
||||
|
||||
/* This sets p_warn_string and pwarn if a unrecognized record
|
||||
or diagnostic record is received. That is good. */
|
||||
|
||||
/* Currently this routine doesnt handle all possible combinations of arguments*/
|
||||
/* It handles:
|
||||
Do a search
|
||||
hsoname= "WAIS-GW/<host>(<port>)/QUERY/<database>/<query>"
|
||||
|
||||
Do a search - alternative
|
||||
hsoname= "WAIS-GW/<host>(<port>)/QUERY/<database>"
|
||||
listopts.thiscompp[0] = <query>
|
||||
|
||||
Retrieve a document
|
||||
hsoname= "WAIS-GW/<host>(<port>)/<type>/<database>/<docid>"
|
||||
listopts.requested_attrs="+CONTENTS+"
|
||||
|
||||
Get attribute information about database
|
||||
hsoname= "WAIS-GW/<host>(<port>)/QUERY/<database>"
|
||||
listopts.requested_attrs="+#ALL+"
|
||||
listopts.thiscompp[0] = NULL
|
||||
*/
|
||||
|
||||
int
|
||||
wais_gw_dsdb(RREQ req, /* Request pointer (unused) */
|
||||
char *hsoname, /* Name of the directory */
|
||||
long version, /* Version #; currently ignored */
|
||||
long magic_no, /* Magic #; currently ignored */
|
||||
int flags, /* Currently only recognize DRO_VERIFY */
|
||||
struct dsrobject_list_options *listopts, /* options (use *remcompp
|
||||
and *thiscompp) */
|
||||
P_OBJECT ob) /* Object to be filled in */
|
||||
{
|
||||
int tmp;
|
||||
AUTOSTAT_CHARPP(hostp);
|
||||
AUTOSTAT_CHARPP(portp);
|
||||
AUTOSTAT_CHARPP(queryp);
|
||||
AUTOSTAT_CHARPP(typep);
|
||||
AUTOSTAT_CHARPP(databasep);
|
||||
WAISSearchResponse *wsr;
|
||||
char *str = NULL;
|
||||
|
||||
ob->version = 0; /* unversioned */
|
||||
ob->magic_no = 0;
|
||||
ob->inc_native = VDIN_PSEUDO;
|
||||
ob->acl = NULL;
|
||||
tmp = qsscanf(hsoname, "WAIS-GW/%&[^(](%&[^)])/%&[^/]/%&[^/]/%&[^/]/%[^\n]",
|
||||
hostp, portp, typep, databasep, queryp);
|
||||
|
||||
if (requested_contents(listopts)) {
|
||||
if (tmp == 4 && stequal(*typep,"HELP")) {
|
||||
char *db_src = NULL;
|
||||
WAISSOURCE thissource;
|
||||
db_src = qsprintf_stcopyr(db_src,"%s.src",*databasep);
|
||||
/* Dont free the source, its on a linked list for the duration*/
|
||||
if (!(thissource = findsource(db_src,WAIS_SOURCE_DIR)))
|
||||
return DIRSRV_WAIS;
|
||||
ob_atput(ob,"CONTENTS","DATA",
|
||||
thissource->description, (char *)0);
|
||||
stfree(db_src);
|
||||
return PSUCCESS;
|
||||
}
|
||||
if (tmp <5)
|
||||
return DIRSRV_WAIS;
|
||||
ob->flags = P_OBJECT_FILE;
|
||||
if (!(str = read_wais_contents(*hostp,*portp,*typep,*databasep,*queryp)))
|
||||
return DIRSRV_WAIS;
|
||||
/* (char *)1 prevents copying of potentially huge str*/
|
||||
ob_atput(ob, "CONTENTS", "DATA", (char *)1, str, (char *)0);
|
||||
return PSUCCESS;
|
||||
}
|
||||
|
||||
ob->flags = P_OBJECT_DIRECTORY;
|
||||
if (tmp < 4)
|
||||
return DIRSRV_NOT_FOUND;
|
||||
|
||||
/* For now only handle QUERY */
|
||||
if (strcmp(*typep,"QUERY") != 0)
|
||||
return DIRSRV_NOT_FOUND;
|
||||
|
||||
if (tmp <5) { /* look for query in components */
|
||||
if (!listopts || !listopts->thiscompp || !*listopts->thiscompp ||
|
||||
strequal(*listopts->thiscompp, "")
|
||||
|| strequal(*listopts->thiscompp, "*")) {
|
||||
/* last test against * might be inappropriate */
|
||||
if (listopts->requested_attrs) {
|
||||
char *w_db_src = NULL;
|
||||
WAISSOURCE thissource; /* DONT free this */
|
||||
w_db_src = qsprintf_stcopyr(w_db_src,"%s.src",*databasep);
|
||||
ob_atput(ob,"OBJECT-INTERPRETATION", "SEARCH", NULL);
|
||||
if (thissource = findsource(w_db_src,WAIS_SOURCE_DIR)) {
|
||||
if (thissource->subjects)
|
||||
ob_atput(ob,"WAIS-SUBJECTS", thissource->subjects, NULL);
|
||||
if (thissource->cost)
|
||||
ob_atput(ob,"WAIS-COST-NUM", thissource->cost, NULL);
|
||||
if (thissource->units)
|
||||
ob_atput(ob,"WAIS-COST-UNIT", thissource->units, NULL);
|
||||
if (thissource->maintainer)
|
||||
ob_atput(ob,"WAIS-MAINTAINER", thissource->maintainer, NULL);
|
||||
ob_atput(ob, "QUERY-METHOD", "wais-query(search-words)",
|
||||
"${search-words}", "", (char *) 0);
|
||||
ob_atput(ob, "QUERY-ARGUMENT", "search-words",
|
||||
"Index word(s) to search for", "mandatory char*",
|
||||
"%s", "", (char *) 0);
|
||||
if (thissource->description)
|
||||
ob_atput(ob, "QUERY-DOCUMENTATION", "wais-query()",
|
||||
thissource->description, (char *) 0);
|
||||
ob_atput(ob, "QUERY-DOCUMENTATION", "search-words",
|
||||
"This string says \
|
||||
what you're searching for or what information you're specifying.",
|
||||
"Type any string. Sometimes SPACEs are treated as implied \
|
||||
'and' operators. Sometimes the words 'and', 'or', and 'not' are recognized \
|
||||
as boolean operators.", (char *) 0);
|
||||
}
|
||||
stfree(w_db_src);
|
||||
}
|
||||
return PSUCCESS; /* Display no contents for the directory */
|
||||
}
|
||||
|
||||
/* Set the selector. */
|
||||
*queryp = stcopyr(*listopts->thiscompp, *queryp);
|
||||
/* We just used up thiscompp, so we'd better reset it. */
|
||||
if (listopts->remcompp && *listopts->remcompp) {
|
||||
*listopts->thiscompp = (*listopts->remcompp)->token;
|
||||
*listopts->remcompp = (*listopts->remcompp)->next;
|
||||
} else {
|
||||
*listopts->thiscompp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & DRO_VERIFY) return PSUCCESS;
|
||||
if ((wsr = waisQuery(*hostp,*portp,*databasep,*queryp)) == NULL)
|
||||
return DIRSRV_WAIS; /* Need to decode wais errors sensibly */
|
||||
wsr_to_dirobj(wsr,ob,*hostp,*portp);
|
||||
freeWAISSearchResponse(wsr); wsr=NULL;
|
||||
return PSUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
wsr_to_dirobj(WAISSearchResponse *wsr, P_OBJECT ob, char *host, char *port)
|
||||
{
|
||||
/* Dont need to fuss around with magic numbers, these cant be replicas*/
|
||||
|
||||
PATTRIB at = atalloc();
|
||||
VLINK vl = NULL;
|
||||
int i;
|
||||
long current_magic_no = 0L; /* set magic starting hash */
|
||||
VLINK tempvl = NULL;
|
||||
|
||||
ob_atput(ob,"WAIS_SEED_WORDS",wsr->SeedWordsUsed, (char *)0);
|
||||
if ( wsr->ShortHeaders
|
||||
|| wsr->LongHeaders
|
||||
|| wsr->Text
|
||||
|| wsr->Headlines
|
||||
|| wsr->Codes
|
||||
|| wsr->Diagnostics
|
||||
) {
|
||||
pwarn = PWARNING;
|
||||
p_warn_string = qsprintf_stcopyr(p_warn_string,
|
||||
"Unrecognized search response");
|
||||
}
|
||||
/*!! Need to handle diagnostics - ignore others */
|
||||
if (wsr->DocHeaders) {
|
||||
for (i=0; wsr->DocHeaders[i]; i++) {
|
||||
if (vl = DocHeader2vl(wsr->DocHeaders[i],host,port)) {
|
||||
/* Add new magic no to all the links returned */
|
||||
current_magic_no = generate_magic(vl);
|
||||
while (magic_no_in_list(++current_magic_no, ob->links));
|
||||
for (tempvl = vl; tempvl != NULL; tempvl= tempvl->next)
|
||||
#ifdef NEVERDEFINED
|
||||
tempvl->f_magic_no = current_magic_no;
|
||||
#else
|
||||
tempvl->f_magic_no = 0; /*clients dont understand result !!*/
|
||||
#endif
|
||||
APPEND_LISTS(ob->links, vl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
urlascii(any *docid) {
|
||||
char *str = stalloc(3 * docid->size);
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for (i=0, j=0; i< docid->size; i++)
|
||||
{
|
||||
int c = docid->bytes[i];
|
||||
if ((c < ' ') || (c > (char)126) || strchr("/\\{}|[]^~<>#%'",c)) {
|
||||
str[j++] = '%' ;
|
||||
sprintf(str+(j++),"%02x",c);
|
||||
j++;
|
||||
} else
|
||||
str[j++] = c;
|
||||
}
|
||||
str[j] = '\0'; /* Null terminated */
|
||||
return str;
|
||||
};
|
||||
|
||||
static VLINK
|
||||
DocHeader2vl(WAISDocumentHeader *wdh, char *host, char *port)
|
||||
{
|
||||
int i; /* Index into types */
|
||||
VLINK vl;
|
||||
VLINK head = NULL; /* Head of links being constructed */
|
||||
char *str = NULL; /* thisstring can be stalloc-ed or stfree-ed*/
|
||||
char *cp = NULL; /* this one cant */
|
||||
IETFTYPE it;
|
||||
PATTRIB at;
|
||||
for (i=0; wdh->Types[i]; i++) {
|
||||
vl = vlalloc();
|
||||
vl->host = stcopy(hostwport);
|
||||
str = urlascii(wdh->DocumentID); /* stalloc's string */
|
||||
if ((cp=strrchr(wdh->Source,'/')) == NULL) {
|
||||
cp = wdh->Source;
|
||||
} else {
|
||||
cp++;
|
||||
}
|
||||
vl->hsoname = qsprintf_stcopyr(vl->hsoname,"WAIS-GW/%s(%s)/%s/%s/%s",
|
||||
host, port, wdh->Types[i], cp, str);
|
||||
/*!! Check that Source always has a reasonable format */
|
||||
if (it = wais_2_ietftype(wdh->Types[i])) {
|
||||
if (at = atcopy(it->prosperotype)) {
|
||||
APPEND_ITEM(at,vl->lattrib);
|
||||
}
|
||||
}
|
||||
vl->name = stcopy(wdh->Headline);
|
||||
if (wdh->VersionNumber)
|
||||
vl->version = wdh->VersionNumber;
|
||||
if (wdh->Score) {
|
||||
vl_atput(vl, "WAIS-SCORE",
|
||||
(str = qsprintf_stcopyr(str,"%d",wdh->Score)), (char *)0);
|
||||
vl_atput(vl, "COLLATION-ORDER",
|
||||
(str = qsprintf_stcopyr(str,"-%d",wdh->Score)), (char *)0);
|
||||
}
|
||||
if (wdh->BestMatch)
|
||||
vl_atput(vl, "WAIS-BESTMATCH",
|
||||
(str = qsprintf_stcopyr(str,"%d",wdh->BestMatch)), (char *)0);
|
||||
vl_atput(vl, "SIZE",
|
||||
(str = qsprintf_stcopyr(str,"%d",wdh->BestMatch)), (char *)0);
|
||||
if (wdh->Lines)
|
||||
vl_atput(vl, "WAIS-LINES",
|
||||
(str = qsprintf_stcopyr(str,"%d",wdh->Lines)), (char *)0);
|
||||
/*!! Should convert this date to asn (timetoasn & lib/psrv/dsrfinfo*/
|
||||
/* and stuff in LAST-MODIFIED */
|
||||
if (wdh->Date)
|
||||
vl_atput(vl, "WAIS-DATE", wdh->Date, (char *)0);
|
||||
if (wdh->OriginCity)
|
||||
vl_atput(vl, "WAIS-ORIGINCITY", wdh->OriginCity, (char *)0);
|
||||
/* Route all accesses through the host for now */
|
||||
vl_atput(vl,"ACCESS-METHOD","WAIS","","","","", (char *)0);
|
||||
/*vl_atput(vl,"ACCESS-METHOD","PROSPERO-CONTENTS","","","","", (char *)0);*/
|
||||
if (strncmp("Search produced no result. Here's the Catalog",
|
||||
vl->name, 45) == 0) {
|
||||
vlfree(vl);
|
||||
} else {
|
||||
APPEND_ITEM(vl,head);
|
||||
}
|
||||
stfree(str);
|
||||
} /*for*/
|
||||
return(head);
|
||||
}
|
||||
|
||||
char *
|
||||
read_wais_contents(char *host, char *port, char *type,
|
||||
char *database, char *docid)
|
||||
{
|
||||
any *dt;
|
||||
char *str = NULL;
|
||||
int len;
|
||||
any *DocumentId;
|
||||
|
||||
DocumentId = un_urlascii(docid); /* Allocates DocumentID (throws length)*/
|
||||
len = 0 ;
|
||||
if (dt = waisRetrieve(host,port,database,DocumentId,type,len)) {
|
||||
str = dt->bytes;
|
||||
dt->bytes = NULL;
|
||||
freeAny(dt);
|
||||
}
|
||||
stfree(DocumentId->bytes);
|
||||
free(DocumentId);
|
||||
return (str);
|
||||
}
|
||||
|
||||
8
prospero/lib/psrv/wais_gw/wais_gw_dsdb.h
Normal file
8
prospero/lib/psrv/wais_gw/wais_gw_dsdb.h
Normal file
@@ -0,0 +1,8 @@
|
||||
extern int wais_gw_dsdb(RREQ req, /* Request pointer (unused) */
|
||||
char *hsoname, /* Name of the directory */
|
||||
long version, /* Version #; currently ignored */
|
||||
long magic_no, /* Magic #; currently ignored */
|
||||
int flags, /* Currently only recognize DRO_VERIFY */
|
||||
struct dsrobject_list_options *listopts, /* options (use *remcompp
|
||||
and *thiscompp) */
|
||||
P_OBJECT ob); /* Object to be filled in */
|
||||
41
prospero/lib/psrv/wais_gw/wais_gw_mutex.c
Normal file
41
prospero/lib/psrv/wais_gw/wais_gw_mutex.c
Normal 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 <pfs_threads.h>
|
||||
|
||||
#include "ietftype_parse.h"
|
||||
|
||||
#ifdef PFS_THREADS
|
||||
p_th_mutex p_th_mutexWAISMSGBUFF; /* declaration */
|
||||
p_th_mutex p_th_mutexIETFTYPE; /* declaration */
|
||||
p_th_mutex p_th_mutexWAISSOURCE; /* declaration */
|
||||
#endif
|
||||
|
||||
void
|
||||
wais_gw_init_mutexes(void)
|
||||
{
|
||||
#ifdef PFS_THREADS
|
||||
p_th_mutex_init(p_th_mutexWAISMSGBUFF);
|
||||
p_th_mutex_init(p_th_mutexIETFTYPE);
|
||||
p_th_mutex_init(p_th_mutexWAISSOURCE);
|
||||
ietftype_init(); /* Safer than mutexing it */
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void
|
||||
wais_gw_diagnose_mutexes(void)
|
||||
{
|
||||
#ifdef PFS_THREADS
|
||||
DIAGMUTEX(WAISMSGBUFF,"WAISMSGBUFF");
|
||||
DIAGMUTEX(IETFTYPE,"IETFTYPE");
|
||||
DIAGMUTEX(WAISSOURCE,"WAISSOURCE");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /*NDEBUG*/
|
||||
84
prospero/lib/psrv/wais_gw/waislog.c
Normal file
84
prospero/lib/psrv/wais_gw/waislog.c
Normal file
@@ -0,0 +1,84 @@
|
||||
/*****************************************************************************
|
||||
* (c) Copyright 1992 Wide Area Information Servers, Inc *
|
||||
* of California. All rights reserved. *
|
||||
* *
|
||||
* This notice is intended as a precaution against inadvertent publication *
|
||||
* and does not constitute an admission or acknowledgement that publication *
|
||||
* has occurred or constitute a waiver of confidentiality. *
|
||||
* *
|
||||
* Wide Area Information Server software is the proprietary and *
|
||||
* confidential property of Wide Area Information Servers, Inc. *
|
||||
*****************************************************************************/
|
||||
|
||||
#define waislog_c
|
||||
#if !defined(IN_RMG) && !defined(PFS_THREADS)
|
||||
#include "waislog.h"
|
||||
#include "futil.h"
|
||||
|
||||
void waisLogInternal(long priority,long pid,long lineNum,long code,
|
||||
char* format,va_list ap);
|
||||
|
||||
long log_line = 0;
|
||||
long wais_log_level = 10;
|
||||
char* logFile = NULL;
|
||||
boolean expertUser = false;
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
waislog(long priority,long code,char* format,...)
|
||||
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap,format);
|
||||
initMyPID();
|
||||
waisLogInternal(priority,myPID,log_line++,code,format,ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
waisLogDetailed(long priority,long pid,long lineNum,long code,
|
||||
char* format,...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap,format);
|
||||
waisLogInternal(priority,pid,lineNum,code,format,ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
waisLogInternal(long priority,long pid,long lineNum,long code,
|
||||
char* format,va_list ap)
|
||||
{
|
||||
if (priority <= wais_log_level)
|
||||
{
|
||||
FILE* log = NULL;
|
||||
|
||||
if (logToStderr(logFile))
|
||||
log = stderr;
|
||||
else if (logToStdout(logFile))
|
||||
log = stdout;
|
||||
else
|
||||
log = locked_fopen(logFile,"a");
|
||||
|
||||
if (log)
|
||||
{
|
||||
fprintf(log,"%d: %d: %s: %d: ",pid,lineNum,
|
||||
printable_time(),code);
|
||||
|
||||
vfprintf(log,format,ap);
|
||||
fprintf(log,"\n");
|
||||
fflush(log);
|
||||
|
||||
if (logToStderr(logFile) == false && logToStdout(logFile) == false)
|
||||
locked_fclose(log,logFile,FALSE);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* !defined(IN_RMG) && !defined(PFS_THREADS)*/
|
||||
/*-------------------------------------------------------------------------- */
|
||||
58
prospero/lib/psrv/wais_gw/waislog.h
Normal file
58
prospero/lib/psrv/wais_gw/waislog.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*****************************************************************************
|
||||
* (c) Copyright 1992 Wide Area Information Servers, Inc *
|
||||
* of California. All rights reserved. *
|
||||
* *
|
||||
* This notice is intended as a precaution against inadvertent publication *
|
||||
* and does not constitute an admission or acknowledgement that publication *
|
||||
* has occurred or constitute a waiver of confidentiality. *
|
||||
* *
|
||||
* Wide Area Information Server software is the proprietary and *
|
||||
* confidential property of Wide Area Information Servers, Inc. *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef waislog_h
|
||||
#define waislog_h
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "cutil.h"
|
||||
|
||||
/*-------------------------------------------------------------------------- */
|
||||
/*-------------------------------------------------------------------------- */
|
||||
|
||||
#define WLOG_HIGH (1L)
|
||||
#define WLOG_MEDIUM (5L)
|
||||
#define WLOG_LOW (9L)
|
||||
|
||||
#define WLOG_CONNECT (1L)
|
||||
#define WLOG_CLOSE (2L)
|
||||
#define WLOG_SEARCH (3L)
|
||||
#define WLOG_RESULTS (4L)
|
||||
#define WLOG_RETRIEVE (5L)
|
||||
#define WLOG_INDEX (6L)
|
||||
#define WLOG_PARSE (7L)
|
||||
#define WLOG_INFO (100L)
|
||||
#define WLOG_ERROR (-1L)
|
||||
#define WLOG_WARNING (-2L)
|
||||
|
||||
#define logToStderr(log) (log == NULL || log[0] == '\0')
|
||||
#define logToStdout(log) (log[0] == '-' && log[1] == '\0')
|
||||
#define dbg (expertUser && (logToStderr(logFile) || logToStdout(logFile)))
|
||||
|
||||
void waislog(long priority, long code, char* format,...);
|
||||
void waisLogDetailed(long priority,long pid,long lineNum,long code,
|
||||
char* format,...);
|
||||
|
||||
#ifndef waislog_c
|
||||
extern long log_line;
|
||||
extern wais_log_level;
|
||||
extern char* logFile;
|
||||
extern boolean expertUser;
|
||||
#endif /* ndef waislog_c */
|
||||
|
||||
/*-------------------------------------------------------------------------- */
|
||||
|
||||
#endif /* ndef waislog_h */
|
||||
|
||||
|
||||
|
||||
109
prospero/lib/psrv/wais_gw/wmessage.c
Normal file
109
prospero/lib/psrv/wais_gw/wmessage.c
Normal file
@@ -0,0 +1,109 @@
|
||||
/* WIDE AREA INFORMATION SERVER SOFTWARE:
|
||||
Developed by Thinking Machines Corporation and put into the public
|
||||
domain with no guarantees or restrictions.
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#include <string.h>
|
||||
#include "wmessage.h"
|
||||
#include "cutil.h"
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
readWAISPacketHeader(msgBuffer,header_struct)
|
||||
char* msgBuffer;
|
||||
WAISMessage *header_struct;
|
||||
{
|
||||
|
||||
|
||||
memmove(header_struct->msg_len,msgBuffer,(size_t)10);
|
||||
header_struct->msg_type = char_downcase((unsigned long)msgBuffer[10]);
|
||||
header_struct->hdr_vers = char_downcase((unsigned long)msgBuffer[11]);
|
||||
memmove(header_struct->server,(void*)(msgBuffer + 12),(size_t)10);
|
||||
header_struct->compression = char_downcase((unsigned long)msgBuffer[22]);
|
||||
header_struct->encoding = char_downcase((unsigned long)msgBuffer[23]);
|
||||
header_struct->msg_checksum = char_downcase((unsigned long)msgBuffer[24]);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
long
|
||||
getWAISPacketLength(header)
|
||||
WAISMessage* header;
|
||||
|
||||
{
|
||||
char lenBuf[11];
|
||||
memmove(lenBuf,header->msg_len,(size_t)10);
|
||||
lenBuf[10] = '\0';
|
||||
return(atol(lenBuf));
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
#ifdef NOTUSEDYET
|
||||
|
||||
static char checkSum _AP((char* string,long len));
|
||||
|
||||
static char
|
||||
checkSum(string,len)
|
||||
char* string;
|
||||
long len;
|
||||
|
||||
{
|
||||
register long i;
|
||||
register char chSum = '\0';
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
chSum = chSum ^ string[i];
|
||||
|
||||
return(chSum);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void
|
||||
writeWAISPacketHeader(header,
|
||||
dataLen,
|
||||
type,
|
||||
server,
|
||||
compression,
|
||||
encoding,
|
||||
version)
|
||||
char* header;
|
||||
long dataLen;
|
||||
long type;
|
||||
char* server;
|
||||
long compression;
|
||||
long encoding;
|
||||
long version;
|
||||
|
||||
{
|
||||
char lengthBuf[11];
|
||||
char serverBuf[11];
|
||||
|
||||
long serverLen = strlen(server);
|
||||
if (serverLen > 10)
|
||||
serverLen = 10;
|
||||
|
||||
sprintf(lengthBuf, "%010ld", dataLen);
|
||||
strncpy(header,lengthBuf,10);
|
||||
|
||||
header[10] = type & 0xFF;
|
||||
header[11] = version & 0xFF;
|
||||
|
||||
strncpy(serverBuf,server,serverLen);
|
||||
strncpy((char*)(header + 12),serverBuf,serverLen);
|
||||
|
||||
header[22] = compression & 0xFF;
|
||||
header[23] = encoding & 0xFF;
|
||||
header[24] = '0';
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
|
||||
58
prospero/lib/psrv/wais_gw/wmessage.h
Normal file
58
prospero/lib/psrv/wais_gw/wmessage.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* WIDE AREA INFORMATION SERVER SOFTWARE:
|
||||
Developed by Thinking Machines Corporation and put into the public
|
||||
domain with no guarantees or restrictions.
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#ifndef WMESSAGE_H
|
||||
#define WMESSAGE_H
|
||||
|
||||
#include "cdialect.h"
|
||||
|
||||
typedef struct wais_header {
|
||||
char msg_len[10];
|
||||
char msg_type;
|
||||
char hdr_vers;
|
||||
char server[10];
|
||||
char compression;
|
||||
char encoding;
|
||||
char msg_checksum;
|
||||
} WAISMessage;
|
||||
|
||||
#define HEADER_LENGTH 25
|
||||
|
||||
#define HEADER_VERSION (long)'2'
|
||||
|
||||
|
||||
#define Z3950 'z'
|
||||
#define ACK 'a'
|
||||
#define NAK 'n'
|
||||
|
||||
|
||||
#define NO_COMPRESSION ' '
|
||||
#define UNIX_COMPRESSION 'u'
|
||||
|
||||
|
||||
#define NO_ENCODING ' '
|
||||
#define HEX_ENCODING 'h'
|
||||
#define IBM_HEXCODING 'i'
|
||||
#define UUENCODE 'u'
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
void readWAISPacketHeader _AP((char* msgBuffer,WAISMessage *header_struct));
|
||||
long getWAISPacketLength _AP((WAISMessage* header));
|
||||
void writeWAISPacketHeader _AP((char* header,long dataLen,long type,
|
||||
char* server,long compression,
|
||||
long encoding,long version));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
2368
prospero/lib/psrv/wais_gw/wprot.c
Normal file
2368
prospero/lib/psrv/wais_gw/wprot.c
Normal file
File diff suppressed because it is too large
Load Diff
298
prospero/lib/psrv/wais_gw/wprot.h
Normal file
298
prospero/lib/psrv/wais_gw/wprot.h
Normal file
@@ -0,0 +1,298 @@
|
||||
/* WIDE AREA INFORMATION SERVER SOFTWARE:
|
||||
Developed by Thinking Machines Corporation and put into the public
|
||||
domain with no guarantees or restrictions.
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _H_WAIS_protocol_
|
||||
#define _H_WAIS_protocol_
|
||||
|
||||
#include "cdialect.h"
|
||||
#include "zprot.h"
|
||||
#include "ztype1.h"
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
#ifndef DF_INDEPENDENT
|
||||
#define DF_INDEPENDENT 1
|
||||
#define DF_LATER 2
|
||||
#define DF_EARLIER 3
|
||||
#define DF_SPECIFIED_RANGE 4
|
||||
#endif
|
||||
|
||||
|
||||
#define CT_document 0
|
||||
#define CT_byte 1
|
||||
#define CT_line 2
|
||||
#define CT_paragraph 3
|
||||
|
||||
|
||||
#define QT_RelevanceFeedbackQuery "3"
|
||||
#define QT_TextRetrievalQuery QT_BooleanQuery
|
||||
|
||||
|
||||
#define DT_UserInformationLength (data_tag)99
|
||||
#define DT_ChunkCode (data_tag)100
|
||||
#define DT_ChunkIDLength (data_tag)101
|
||||
#define DT_ChunkMarker (data_tag)102
|
||||
#define DT_HighlightMarker (data_tag)103
|
||||
#define DT_DeHighlightMarker (data_tag)104
|
||||
#define DT_NewlineCharacters (data_tag)105
|
||||
#define DT_SeedWords (data_tag)106
|
||||
#define DT_DocumentIDChunk (data_tag)107
|
||||
#define DT_ChunkStartID (data_tag)108
|
||||
#define DT_ChunkEndID (data_tag)109
|
||||
#define DT_TextList (data_tag)110
|
||||
#define DT_DateFactor (data_tag)111
|
||||
#define DT_BeginDateRange (data_tag)112
|
||||
#define DT_EndDateRange (data_tag)113
|
||||
#define DT_MaxDocumentsRetrieved (data_tag)114
|
||||
#define DT_SeedWordsUsed (data_tag)115
|
||||
#define DT_DocumentID (data_tag)116
|
||||
#define DT_VersionNumber (data_tag)117
|
||||
#define DT_Score (data_tag)118
|
||||
#define DT_BestMatch (data_tag)119
|
||||
#define DT_DocumentLength (data_tag)120
|
||||
#define DT_Source (data_tag)121
|
||||
#define DT_Date (data_tag)122
|
||||
#define DT_Headline (data_tag)123
|
||||
#define DT_OriginCity (data_tag)124
|
||||
#define DT_PresentStartByte (data_tag)125
|
||||
#define DT_TextLength (data_tag)126
|
||||
#define DT_DocumentText (data_tag)127
|
||||
#define DT_StockCodes (data_tag)128
|
||||
#define DT_CompanyCodes (data_tag)129
|
||||
#define DT_IndustryCodes (data_tag)130
|
||||
|
||||
|
||||
#define DT_DocumentHeaderGroup (data_tag)150
|
||||
#define DT_DocumentShortHeaderGroup (data_tag)151
|
||||
#define DT_DocumentLongHeaderGroup (data_tag)152
|
||||
#define DT_DocumentTextGroup (data_tag)153
|
||||
#define DT_DocumentHeadlineGroup (data_tag)154
|
||||
#define DT_DocumentCodeGroup (data_tag)155
|
||||
#define DT_Lines (data_tag)131
|
||||
#define DT_TYPE_BLOCK (data_tag)132
|
||||
#define DT_TYPE (data_tag)133
|
||||
|
||||
|
||||
#define ES_DocumentHeader "Document Header"
|
||||
#define ES_DocumentShortHeader "Document Short Header"
|
||||
#define ES_DocumentLongHeader "Document Long Header"
|
||||
#define ES_DocumentText "Document Text"
|
||||
#define ES_DocumentHeadline "Document Headline"
|
||||
#define ES_DocumentCodes "Document Codes"
|
||||
|
||||
typedef struct DocObj {
|
||||
any* DocumentID;
|
||||
char* Type;
|
||||
long ChunkCode;
|
||||
union {
|
||||
long Pos;
|
||||
any* ID;
|
||||
} ChunkStart;
|
||||
union {
|
||||
long Pos;
|
||||
any* ID;
|
||||
} ChunkEnd;
|
||||
} DocObj;
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
|
||||
typedef struct WAISInitResponse {
|
||||
long ChunkCode;
|
||||
long ChunkIDLength;
|
||||
char* ChunkMarker;
|
||||
char* HighlightMarker;
|
||||
char* DeHighlightMarker;
|
||||
char* NewlineCharacters;
|
||||
|
||||
} WAISInitResponse;
|
||||
|
||||
typedef struct WAISSearch {
|
||||
char* SeedWords;
|
||||
DocObj** Docs;
|
||||
char** TextList;
|
||||
long DateFactor;
|
||||
char* BeginDateRange;
|
||||
char* EndDateRange;
|
||||
long MaxDocumentsRetrieved;
|
||||
} WAISSearch;
|
||||
|
||||
typedef struct WAISDocumentHeader {
|
||||
any* DocumentID;
|
||||
long VersionNumber;
|
||||
long Score;
|
||||
long BestMatch;
|
||||
long DocumentLength;
|
||||
long Lines;
|
||||
char** Types;
|
||||
char* Source;
|
||||
char* Date;
|
||||
char* Headline;
|
||||
char* OriginCity;
|
||||
} WAISDocumentHeader;
|
||||
|
||||
typedef struct WAISDocumentShortHeader {
|
||||
any* DocumentID;
|
||||
long VersionNumber;
|
||||
long Score;
|
||||
long BestMatch;
|
||||
long DocumentLength;
|
||||
long Lines;
|
||||
} WAISDocumentShortHeader;
|
||||
|
||||
typedef struct WAISDocumentLongHeader {
|
||||
any* DocumentID;
|
||||
long VersionNumber;
|
||||
long Score;
|
||||
long BestMatch;
|
||||
long DocumentLength;
|
||||
long Lines;
|
||||
char** Types;
|
||||
char* Source;
|
||||
char* Date;
|
||||
char* Headline;
|
||||
char* OriginCity;
|
||||
char* StockCodes;
|
||||
char* CompanyCodes;
|
||||
char* IndustryCodes;
|
||||
} WAISDocumentLongHeader;
|
||||
|
||||
typedef struct WAISDocumentText {
|
||||
any* DocumentID;
|
||||
long VersionNumber;
|
||||
any* DocumentText;
|
||||
} WAISDocumentText;
|
||||
|
||||
typedef struct WAISDocumentHeadlines {
|
||||
any* DocumentID;
|
||||
long VersionNumber;
|
||||
char* Source;
|
||||
char* Date;
|
||||
char* Headline;
|
||||
char* OriginCity;
|
||||
} WAISDocumentHeadlines;
|
||||
|
||||
typedef struct WAISDocumentCodes {
|
||||
any* DocumentID;
|
||||
long VersionNumber;
|
||||
char* StockCodes;
|
||||
char* CompanyCodes;
|
||||
char* IndustryCodes;
|
||||
} WAISDocumentCodes;
|
||||
|
||||
typedef struct WAISSearchResponse {
|
||||
char* SeedWordsUsed;
|
||||
WAISDocumentHeader** DocHeaders;
|
||||
WAISDocumentShortHeader** ShortHeaders;
|
||||
WAISDocumentLongHeader** LongHeaders;
|
||||
WAISDocumentText** Text;
|
||||
WAISDocumentHeadlines** Headlines;
|
||||
WAISDocumentCodes** Codes;
|
||||
diagnosticRecord** Diagnostics;
|
||||
} WAISSearchResponse;
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
DocObj* makeDocObjUsingWholeDocument _AP((any* aDocID,char* type));
|
||||
DocObj* makeDocObjUsingBytes _AP((any* aDocID,char* type,long start,long end));
|
||||
DocObj* makeDocObjUsingLines _AP((any* aDocID,char* type,long start,long end));
|
||||
DocObj* makeDocObjUsingParagraphs _AP((any* aDocID,char* type,any* start,any* end));
|
||||
void freeDocObj _AP((DocObj* doc));
|
||||
|
||||
WAISInitResponse* makeWAISInitResponse _AP((long chunkCode,long chunkIDLen,
|
||||
char* chunkMarker,char* highlightMarker,
|
||||
char* deHighlightMarker,char* newLineChars));
|
||||
void freeWAISInitResponse _AP((WAISInitResponse* init));
|
||||
|
||||
WAISSearch* makeWAISSearch _AP((
|
||||
char* seedWords,DocObj** docs,char** textList,
|
||||
long dateFactor,char* beginDateRange,char* endDateRange,
|
||||
long maxDocsRetrieved));
|
||||
void freeWAISSearch _AP((WAISSearch* query));
|
||||
|
||||
WAISDocumentHeader* makeWAISDocumentHeader _AP((
|
||||
any* aDocID,long versionNumber,long score,long bestMatch,long docLen,
|
||||
long lines,char** types,char* source,char* theDate,char* headline,char* originCity));
|
||||
void freeWAISDocumentHeader _AP((WAISDocumentHeader* header));
|
||||
char* writeWAISDocumentHeader _AP((WAISDocumentHeader* header,char* buffer,long* len));
|
||||
char* readWAISDocumentHeader _AP((WAISDocumentHeader** header,char* buffer));
|
||||
|
||||
WAISDocumentShortHeader* makeWAISDocumentShortHeader _AP((
|
||||
any* aDocID,long versionNumber,long score,long bestMatch,long docLen,long lines));
|
||||
void freeWAISDocumentShortHeader _AP((WAISDocumentShortHeader* header));
|
||||
char* writeWAISDocumentShortHeader _AP((WAISDocumentShortHeader* header,
|
||||
char* buffer,long* len));
|
||||
char* readWAISDocumentShortHeader _AP((WAISDocumentShortHeader** header,char* buffer));
|
||||
|
||||
WAISDocumentLongHeader* makeWAISDocumentLongHeader _AP((
|
||||
any* aDocID,long versionNumber,long score,long bestMatch,long docLen,
|
||||
long lines,char** types,char* source,char* theDate, char* headline,char* originCity,
|
||||
char* stockCodes,char* companyCodes,char* industryCodes));
|
||||
void freeWAISDocumentLongHeader _AP((WAISDocumentLongHeader* header));
|
||||
char* writeWAISDocumentLongHeader _AP((WAISDocumentLongHeader* header,char* buffer,long* len));
|
||||
char* readWAISDocumentLongHeader _AP((WAISDocumentLongHeader** header,char* buffer));
|
||||
|
||||
WAISSearchResponse* makeWAISSearchResponse _AP((
|
||||
char* seedWordsUsed,WAISDocumentHeader** docHeaders,
|
||||
WAISDocumentShortHeader** shortHeaders,
|
||||
WAISDocumentLongHeader** longHeaders,
|
||||
WAISDocumentText** text,WAISDocumentHeadlines** headlines,
|
||||
WAISDocumentCodes** codes,
|
||||
diagnosticRecord** diagnostics));
|
||||
void freeWAISSearchResponse _AP((WAISSearchResponse* response));
|
||||
|
||||
WAISDocumentText* makeWAISDocumentText _AP((any* aDocID,long versionNumber,
|
||||
any* documentText));
|
||||
void freeWAISDocumentText _AP((WAISDocumentText* docText));
|
||||
char* writeWAISDocumentText _AP((WAISDocumentText* docText,char* buffer,long* len));
|
||||
char* readWAISDocumentText _AP((WAISDocumentText** docText,char* buffer));
|
||||
|
||||
WAISDocumentHeadlines* makeWAISDocumentHeadlines _AP((
|
||||
any* aDocID,long versionNumber,char* source,char* theDate,
|
||||
char* headline,char* originCity));
|
||||
void freeWAISDocumentHeadlines _AP((WAISDocumentHeadlines* docHeadline));
|
||||
char* writeWAISDocumentHeadlines _AP((WAISDocumentHeadlines* docHeadline,char* buffer,long* len));
|
||||
char* readWAISDocumentHeadlines _AP((WAISDocumentHeadlines** docHeadline,char* buffer));
|
||||
|
||||
WAISDocumentCodes* makeWAISDocumentCodes _AP((
|
||||
any* aDocID,long versionNumber,char* stockCodes,char* companyCodes,
|
||||
char* industryCodes));
|
||||
void freeWAISDocumentCodes _AP((WAISDocumentCodes* docCodes));
|
||||
char* writeWAISDocumentCodes _AP((WAISDocumentCodes* docCodes,char* buffer,long* len));
|
||||
char* readWAISDocumentCodes _AP((WAISDocumentCodes** docCodes,char* buffer));
|
||||
|
||||
any* makeWAISTextQuery _AP((DocObj** docs));
|
||||
DocObj** readWAISTextQuery _AP((any* terms));
|
||||
|
||||
void CSTFreeWAISInitResponse _AP((WAISInitResponse* init));
|
||||
void CSTFreeWAISSearch _AP((WAISSearch* query));
|
||||
void CSTFreeDocObj _AP((DocObj* doc));
|
||||
void CSTFreeWAISDocumentHeader _AP((WAISDocumentHeader* header));
|
||||
void CSTFreeWAISDocumentShortHeader _AP((WAISDocumentShortHeader* header));
|
||||
void CSTFreeWAISDocumentLongHeader _AP((WAISDocumentLongHeader* header));
|
||||
void CSTFreeWAISSearchResponse _AP((WAISSearchResponse* response));
|
||||
void CSTFreeWAISDocumentText _AP((WAISDocumentText* docText));
|
||||
void CSTFreeWAISDocumentHeadlines _AP((WAISDocumentHeadlines* docHeadline));
|
||||
void CSTFreeWAISDocumentCodes _AP((WAISDocumentCodes* docCodes));
|
||||
void CSTFreeWAISTextQuery _AP(( any* query));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user