Intial commit

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

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

@@ -0,0 +1 @@
Makefile

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

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

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

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

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

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

View File

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

View File

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

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

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

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

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

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

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

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

View File

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

View File

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

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

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

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

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

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

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,26 @@
/*
* 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 <sys/types.h>
#include <sys/stat.h>
/* Is this a file? uses stat() */
#include <pfs.h> /* for prototypes */
/* Is it a regular file? 1 = yes, 0 = no, -1 = failure? */
extern int
is_file(const char native_filename[])
{
struct stat st_buf;
if(stat(native_filename, &st_buf) == 0)
return S_ISREG(st_buf.st_mode) ? 1 : 0;
else
return -1;
}

20
prospero/lib/pfs/length.c Normal file
View File

@@ -0,0 +1,20 @@
/*
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the file <usc-copyr.h>
*/
/* Author: Steven Augart, swa@isi.edu */
#include <usc-copyr.h>
#include <pfs.h>
/* Return the length of a sequence. Works like the Common Lisp LENGTH function
on sequences. */
int
length(TOKEN s)
{
int len;
for (len = 0; s; s = s->next, ++len)
;
return len;
}

View File

@@ -0,0 +1,98 @@
/*
* 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 <string.h>
#include <netdb.h>
#include <pfs.h>
#include <psite.h>
#include <pcompat.h>
#include <perrno.h>
#include <pmachine.h>
/*
* see pcompat.h for the meanings of the flags
*/
/* This function looks a heck of a lot like retrieve_link() in user/vget.c. If
there's a bug here, there's one there too. */
/* This can be easily changed to use the stcopyr() interface, and should be at
some point in the future. */
int
mapname(vl,npath, npathlen, flags)
VLINK vl;
char *npath; /* local pathname for file you can work with.
This is filled in by mapname(). */
int npathlen;
int flags;
{
TOKEN am_args; /* filled in by pget_am */
int am;
int tmp;
int methods = P_AM_LOCAL; /* local filenames always are supported.
*/
#ifdef P_NFS
methods |= P_AM_NFS;
#endif P_NFS
#ifdef P_AFS
methods |= P_AM_AFS;
#endif P_AFS
/* P_AM_FTP requires prompting for a password, which is not something
transparent to the user. That's why the programmer must explicitly
specify the MAP_PROMPT_OK flag. */
if ((flags | MAP_READONLY) && (flags | MAP_PROMPT_OK)) methods |= P_AM_FTP;
if(flags | MAP_READONLY)
methods |= P_AM_AFTP | P_AM_GOPHER | P_AM_RCP \
| P_AM_PROSPERO_CONTENTS | P_AM_WAIS;
am = pget_am(vl,&am_args,methods);
if(!am && perrno) {
return(perrno);
}
switch(am) {
#ifdef P_NFS
case P_AM_NFS:
/* XXX You must change pmap_nfs() to meet the needs of your site. */
tmp = pmap_nfs(vl->host,vl->hsoname,npath, npathlen, am_args);
return(tmp);
#endif P_NFS
#ifdef P_AFS
case P_AM_AFS:
strcpy(npath,P_AFS);
strcat(npath,elt(am_args,4)); /* 4th element is the hsoname. */
return(PSUCCESS);
#endif P_AFS
case P_AM_AFTP:
case P_AM_FTP:
case P_AM_GOPHER:
case P_AM_WAIS:
case P_AM_PROSPERO_CONTENTS:
tmp = p__map_cache(vl, npath, npathlen, am_args);
return(tmp);
case P_AM_LOCAL:
strcpy(npath, elt(am_args, 4));
return PSUCCESS;
default:
return(PFSA_AM_NOT_SUPPORTED);
}
}

148
prospero/lib/pfs/mk_vdir.c Normal file
View File

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

121
prospero/lib/pfs/mkdirs.c Normal file
View File

@@ -0,0 +1,121 @@
/*
* 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 <sys/param.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <pmachine.h>
#include <pfs.h>
#include <perrno.h>
/*
* mkdirs - Make a directory and all superior directories
*
* MKDIRS takes a pathame for a directory, checks to see
* whether it exists, and if not creates it. Any parent
* directories which do not exist will be created as
* well.
*
* ARGS: path - path of the directoriy to be created
*
* RETURNS: 0 on success
* the contents of errno on error
*/
/*
* I've mutilated this file because most calls I found where having to
* go through the effort of making a string for the directory name
* from a file
*
* The old version also had a bug (though I found it through looking at
* the code, not from experience, and a number of non-standards etc
* Specifically:
* if errno was non-zero on entry, and the directory exists, then
* the code would find stat==0, it was a directory, tmp is zero,
* and it would return the errno (or even fail to recreate the directory)
* it should return immediately if the directory exists
*
* rindex is not POSIX
*
* it uses MAXPATHLEN, also non-POSIX
*
* the headers in here, conflicted with those in pfs.h
*/
#define RETURN(r1) { retval=r1 ; goto cleanup; }
/* Argument should be TRUE if one should not strip off the trailing suffix,
* false if one does need to strip off the trailing suffix.
*/
int
p__mkdirs(const char path[], int wantdir)
{
char *prefix = NULL;
char *suffix; /* Pointer into prefix */
struct stat st;
int mode = 0777;
int retval = 0;
if (stat(path, &st) == 0) { /* exists, either dir. or file */
if (!wantdir)
return 0; /* File exists, so directory must */
if (wantdir && !S_ISDIR(st.st_mode))
return (EEXIST); /* already exists and is not dir. */
return 0; /* Directory exists */
}
if (!wantdir) { /* Want file, build parent directory */
prefix = stcopy(path);
if (!(suffix = strrchr(prefix, '/'))) {
RETURN(PSUCCESS); /* No directory to build - thats ok*/
} else {
*suffix = '\0';
RETURN(p__mkdirs(prefix, 1)) ; /* Recurse on directory*/
}
} else { /*wantdir*/
/* If want directory, but specified trailing slash*/
if (path[strlen(path)-1] == '/') {
prefix = stcopy(path);
prefix[strlen(prefix)-1] = '\0';
RETURN(p__mkdirs(prefix, 1)); /*recurse without /*/
}
if (!mkdir(path, mode)) {
chmod(path, mode);
RETURN(0);
}
switch (errno) {
case ENOENT: /* Failed because no parent, recurse for it */
prefix = stcopy(path);
if (suffix = strrchr(prefix, '/'))
*suffix = '\0';
else
*prefix = '\0';
assert(*prefix != '\0'); /* Is no parent, strange */
if (retval = p__mkdirs(prefix, TRUE))
RETURN(retval); /* Recurse on parent */
RETURN(p__mkdirs(path,TRUE)); /* Recurse on self */
case EEXIST: /* Someone else created it for us */
RETURN(PSUCCESS);
default: /* mkdir failed for some other reason */
p_err_string = qsprintf_stcopyr(p_err_string,
"Couldnt create %s: %s", path, unixerrstr());
RETURN(errno);
}
} /*wantdir*/
cleanup:
stfree(prefix);
return(retval);
}
/* back compatibility*/
int
mkdirs(const char *path)
{
return p__mkdirs(path, 1);
}

View File

@@ -0,0 +1,164 @@
/*
* Copyright (c) 1991 by the University of Washington
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>.
*/
#include <uw-copyright.h>
#include <usc-copyr.h>
#include <stdio.h>
#include <string.h>
#include <ardp.h>
#include <pfs.h>
#include <pprot.h>
#include <perrno.h>
#include <pparse.h>
extern int pfs_debug;
extern char *acltypes[];
/*
*
* Flags:
*/
int
modify_acl(dlink,lname,a,flags)
VLINK dlink; /* Directory link */
const char *lname; /* Link name. Must be empty for DIRECTORY
option. OBJECT option not implemented, so
don't worry about it. */
ACL a; /* ACL entry to add/delete/modify */
int flags; /* Flags */
{
RREQ req; /* Text of request to dir server */
char options[100]; /* List of options */
char *optptr; /* Options minus leading + */
int tmp;
OUTPUT_ST out_st;
OUTPUT out = &out_st;
INPUT_ST in_st;
INPUT in = &in_st;
int fwdcnt = MAX_FWD_DEPTH;
*options = '\0';
if(flags&EACL_NOSYSTEM) strcat(options,"+NOSYSTEM");
if(flags&EACL_NOSELF) strcat(options,"+NOSELF");
if((flags&EACL_OP) == EACL_DEFAULT) strcat(options,"+DEFAULT");
else if((flags&EACL_OP) == EACL_SET) strcat(options,"+SET");
else if((flags&EACL_OP) == EACL_INSERT) strcat(options,"+INSERT");
else if((flags&EACL_OP) == EACL_DELETE) strcat(options,"+DELETE");
else if((flags&EACL_OP) == EACL_ADD) strcat(options,"+ADD");
else if((flags&EACL_OP) == EACL_CREATE) strcat(options,"+CREATE");
else if((flags&EACL_OP) == EACL_DESTROY) strcat(options,"+DESTROY");
else if((flags&EACL_OP) == EACL_SUBTRACT) strcat(options,"+SUBTRACT");
else RETURNPFAILURE; /* bad operation */
if((flags&EACL_OTYPE) == EACL_LINK) strcat(options,"+LINK");
else if((flags&EACL_OTYPE) == EACL_DIRECTORY) strcat(options,"+DIRECTORY");
else if((flags&EACL_OTYPE) == EACL_OBJECT) strcat(options,"+OBJECT");
else if((flags&EACL_OTYPE) == EACL_INCLUDE) strcat(options,"+INCLUDE");
else if((flags&EACL_OTYPE) == EACL_NAMED) strcat(options,"+NAMED");
else RETURNPFAILURE; /* bad target */
/* CREATE and DESTROY are only valid with NAMED. */
if (((flags & EACL_OP) == EACL_CREATE || (flags & EACL_OP) == EACL_DESTROY)
&& (flags & EACL_OTYPE) != EACL_NAMED)
RETURNPFAILURE;
optptr = options + 1;
if(lname == NULL) lname = "";
if(strcmp(dlink->target,"NULL") == 0) return(PFS_EXT_USED_AS_DIR);
if(strcmp(dlink->target,"EXTERNAL") == 0) return(PFS_EXT_USED_AS_DIR);
startover:
req = p__start_req(dlink->host);
/* XXX need to add capability for ID specification.. */
requesttoout(req,out);
if(((flags&EACL_OTYPE) == EACL_DIRECTORY) ||
((flags&EACL_OTYPE) == EACL_LINK)) {
p__add_req(req,"DIRECTORY ASCII %'s\n", dlink->hsoname);
}
if((flags&EACL_OTYPE) == EACL_OBJECT)
p__add_req(req,"EDIT-ACL %s %'s\n",optptr, dlink->hsoname);
else p__add_req(req,"EDIT-ACL %s %'s\n",optptr, lname);
out_acl(out, a);
perrno = 0;
tmp = ardp_send(req,dlink->host,0,ARDP_WAIT_TILL_TO);
if(tmp) {
if (pfs_debug) fprintf(stderr,"ardp_send failed: %d\n",tmp);
perrno = tmp;
}
/* If we don't get a response, then return error */
if(req->rcvd == NOPKT) {
ardp_rqfree(req);
return(perrno);
}
/* Here we must parse reponse - While looking at each packet */
rreqtoin(req, in);
while(!in_eof(in)) {
char *line;
char *next_word;
if (tmp = in_line(in, &line, &next_word)) {
ardp_rqfree(req);
return(tmp);
}
switch (*line) {
case 'F': /* FAILURE or FORWARDED */
/* FORWARDED */
if(qsscanf(line, "FORWARDED%~%r", &next_word) == 1) {
if(fwdcnt-- <= 0) {
ardp_rqfree(req);
perrno = PFS_MAX_FWD_DEPTH;
return(perrno);
}
if (tmp = in_forwarded_data(in, line, next_word, dlink)) {
perrno = DIRSRV_BAD_FORMAT;
ardp_rqfree(req);
break;
}
/* Success; scan again. */
ardp_rqfree(req);
goto startover;
}
/* If FAILURE or anything else scan error */
goto scanerr;
case 'S': /* SUCCESS */
if(strncmp(line,"SUCCESS",7) == 0) {
ardp_rqfree(req);
return(PSUCCESS);
}
goto scanerr;
scanerr:
default:
if(*line && (tmp = scan_error(line, req))) {
ardp_rqfree(req);
return(tmp);
}
break;
}
}
perrno = DIRSRV_BAD_FORMAT;
ardp_rqfree(req);
return(perrno);
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (c) 1989 by the University of Washington
*
* For copying and distribution information, please see the file
* <uw-copyright.h>.
*/
#include <uw-copyright.h>
/*
* month_sname - Return a month name from it's number
*
* MONTH_SNAME takes a number in the range 0
* to 12 and returns a pointer to a string
* representing the three letter abbreviation
* for that month. If the argument is out of
* range, MONTH_SNAME returns a pointer to "Unk".
*
* ARGS: n - Number of the month
* RETURNS: Abbreviation for selected month
*/
char *month_sname(n)
int n; /* Month number */
{
static char *name[] = {"Unk",
"Jan","Feb","Mar","Apr","May","Jun",
"Jul","Aug","Sep","Oct","Nov","Dec"
};
return((n < 1 || n > 12) ? name[0] : name[n]);
}

117
prospero/lib/pfs/myhost.c Normal file
View File

@@ -0,0 +1,117 @@
/*
* Copyright (c) 1993,1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*
* Original author: BCN (washington) (1989, 1991).
* Hacked by SWA.
*/
#include <usc-license.h>
#include <pcompat.h> /* for DISABLE_PFS() */
#include <sys/param.h>
#include <netdb.h>
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 255 /* limit in 4.2BSD manual pages. */
#endif
#include <pfs.h> /* for definitions of myhostname and myaddress.*/
/* These are mutexed below. */
static char myhname[MAXHOSTNAMELEN + 1];
static long myhaddr = 0L;
char *myhostname();
/* The auto-initialization mutexing here works, but is not used. */
/* If you turn it on, you'll have to change lib/pfs/pfs_mutexes.c and
include/pfs.h to add p_th_mutexPFS_MYHOSTNAME. */
#undef P__MYHOST_MUTEX_AUTOINITIALIZATION
long
myaddress(void)
{
/* First time called, make sure myhostname has been run */
if(!myhaddr) {
#ifndef P__MYHOST_MUTEX_AUTOINITIALIZATION
/* myaddress() should be called as part of any general
library initialization when running multi-threaded. */
assert(P_IS_THIS_THREAD_MASTER());
#endif
myhostname();
}
return(myhaddr);
}
/* myhostname() always returns the official name of the host (see comment below
for an exception to this claim; do not rely on it.
This might be different from the version returned by gethostname(), and
might well be different from the version stored in the 'hstname' environment
variable defined in dirsrv.c */
/* This is normally called by dirsrv in p_init_mutexes() so that it
will not fail in a multi-threaded environment. */
/*
* Implementation and Specification Comments:
* From the SunOS 4.1.3 manual page for "gethostbyname(3)":
* "The members of this structure are:
h_name Official name of the host. [ ... ]"
*
* Under Solaris 2.3, Mitra reports that a short name that is not the fully
* qualified domain name is being returned in the h_name member. This makes
* myhostname() return a name that is not the official name of the host.
*
*
* Problems if we don't get the fully qualified domain name (swa went through
* all the existing code calling this function to check and make sure no
* problems would arise):
* dirsrv.c: no problem; envar overrides #define overrides myhostname()
* ftp.c (in vcache): used to contstruct password for anonymous FTP.
* So: no problem.
* Not used elsewhere in the existing code; future code will be aware of the
* potential problem.
*/
char *
myhostname()
{
static int initialized = 0;
/* First time called, find out hostname and remember it */
if(!initialized) {
struct hostent *current_host;
#ifdef P__MYHOST_MUTEX_AUTOINITIALIZATION
#ifdef PFS_THREADS
p_th_mutex_lock(p_th_mutexPFS_MYHOSTNAME);
if (!initialized) { /* check again */
#endif
#else
assert(P_IS_THIS_THREAD_MASTER()); /* autoinitializing */
#endif
gethostname(myhname,sizeof(myhname));
/* gethostbyname reads files, so we must disable pfs */
p_th_mutex_lock(p_th_mutexGETHOSTBYNAME);
DISABLE_PFS(current_host = gethostbyname(myhname));
strcpy(myhname,current_host->h_name);
/* Save the address too */
/* Length of the address is h_length; in practice, is always 4. */
bcopy(current_host->h_addr,&myhaddr, current_host->h_length);
/* We're now done copying data out of the current_host structure,
so we can safely unlock the mutex around GETHOSTBYNAME */
p_th_mutex_unlock(p_th_mutexGETHOSTBYNAME);
ucase(myhname);
++initialized;
#ifdef P__MYHOST_MUTEX_AUTOINITIALIZATION
#ifdef PFS_THREADS
p_th_mutex_unlock(p_th_mutexPFS_MYHOSTNAME);
}
#endif
#endif
}
return(myhname);
}

139
prospero/lib/pfs/oballoc.c Normal file
View File

@@ -0,0 +1,139 @@
/*
* 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 <stdio.h>
#include <stdlib.h> /* For malloc and free */
#include <pfs.h>
static P_OBJECT lfree = NULL;
int p_object_count = 0;
int p_object_max = 0;
/*
* oballoc - allocate and initialize p_object structure
*
* OBALLOC returns a pointer to an initialized structure of type
* P_OBJECT. If it is unable to allocate such a structure, it
* signals out_of_memory();
*/
P_OBJECT
oballoc(void)
{
P_OBJECT ob;
p_th_mutex_lock(p_th_mutexOBALLOC);
if(lfree) {
ob = lfree;
lfree = lfree->next;
}
else {
ob = (P_OBJECT) malloc(sizeof(P_OBJECT_ST));
if (!ob) out_of_memory();
p_object_max++;
}
p_object_count++;
p_th_mutex_unlock(p_th_mutexOBALLOC);
/* Initialize and fill in default values */
#ifdef ALLOCATOR_CONSISTENCY_CHECK
ob->consistency = INUSE_PATTERN;
#endif
ob->version = 0; /* version is always zero. */
ob->flags = 0; /* no flags set */
ob->inc_native = VDIN_UNINITIALIZED; /* don't write out object until this
is reset. Used only on server. */
ob->magic_no = 0L; /* zero means unset */
ob->acl = NULL; /* */
ob->exp = 0;
ob->ttl = 0;
ob->last_ref = 0;
ob->forward = NULL;
ob->backlinks = NULL;
ob->attributes = NULL;
ob->links = NULL;
ob->ulinks = NULL;
ob->native_mtime = 0;
ob->shadow_file = NULL; /* used only on server.*/
ob->status = DQ_INACTIVE; /* used only in client mode. */
ob->dqs = NULL; /* ditto */
ob->statbuf = NULL; /* Used only on server */
ob->app.ptr = NULL; /* On every architecture I ever heard of, ob->
app.flg is now 0 too */
ob->previous = NULL;
ob->next = NULL;
return(ob);
}
static void (*obappfreefunc)(P_OBJECT) = NULL;
/*
* Specify which special freeing function (if any) to be used to free the
* app.ptr member of the P_OBJECT structure, if set.
*/
void
obappfree(void (* appfreefunc)(P_OBJECT))
{
obappfreefunc = appfreefunc;
}
/*
* obfree - free a P_OBJECT structure
*
* OBFREE takes a pointer to a P_OBJECT structure and adds it to
* the free list for later reuse.
*/
void
obfree(P_OBJECT ob)
{
#ifdef ALLOCATOR_CONSISTENCY_CHECK
assert(ob->consistency == INUSE_PATTERN);
ob->consistency = FREE_PATTERN;
#endif
if(ob->acl) aclfree(ob->acl); ob->acl = NULL;
if(ob->forward) { vllfree(ob->forward); ob->forward = NULL;}
if(ob->backlinks) { vllfree(ob->backlinks); ob->backlinks = NULL;}
if(ob->attributes) { atlfree(ob->attributes); ob->attributes = NULL;}
if(ob->links) { vllfree(ob->links); ob->links = NULL; }
if(ob->ulinks) { vllfree(ob->ulinks); ob->ulinks = NULL; }
if(ob->shadow_file) {stfree(ob->shadow_file); ob->shadow_file = NULL;}
if(ob->statbuf) {stfree(ob->statbuf); ob->statbuf = NULL;}
/* If ob->dqs signal a memory leak. */
if(obappfreefunc && ob->app.ptr) {
(*obappfreefunc)(ob->app.ptr);
ob->app.ptr = NULL;
}
p_th_mutex_lock(p_th_mutexOBALLOC);
ob->next = lfree;
ob->previous = NULL;
lfree = ob;
p_object_count--;
p_th_mutex_unlock(p_th_mutexOBALLOC);
}
/*
* oblfree - free a P_OBJECT structure list
*
* OBLFREE takes a pointer to a P_OBJECT structure frees it and any linked
* P_OBJECT structures. It is used to free an entire list of P_OBJECT
* structures.
*/
void
oblfree(P_OBJECT ob)
{
P_OBJECT nxt;
while(ob != NULL) {
nxt = ob->next;
obfree(ob);
ob = nxt;
}
}

View File

@@ -0,0 +1,21 @@
/* Other routines - written by Mitra - that deal with P_OBJECT's
*
* Steve - feel free to move anywhere you want
*/
#include <pfs.h>
/* Syntactically same as atput in goph_gw_dsdb.c */
/* Note caller must pass last arg as (char *)0 */
/* Note an arg of *char *)1 will force next arg to be pointed at rather
than copied */
void ob_atput(P_OBJECT po, char *name, ...)
{
va_list ap;
PATTRIB at;
va_start(ap, name);
at = vatbuild(name, ap);
APPEND_ITEM(at, po->attributes);
va_end(ap);
}

203
prospero/lib/pfs/opentcp.c Normal file
View File

@@ -0,0 +1,203 @@
/*
* 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/types.h>
#include <sys/socket.h>
#include <unistd.h> /* for fcntl() */
#include <fcntl.h> /* for fcntl() */
#include <errno.h> /* for EINPROGRESS. etc.*/
#ifdef AIX /* lucb */
#include <sys/select.h>
#endif
#include <errno.h>
#include <pfs_threads.h>
#include <ardp.h>
#include <perrno.h>
#include <pfs.h>
#include <sys/time.h> /* For gettimeofday */
#include <sockettime.h> /* for xxx_APPROACH */
/* Open a TCP stream from here to the HOST at the PORT. */
/* Return socket descriptor on success, or -1 on failure. */
/* This is mostly swiped from user/vcache/gopherget.c */
/* It is part of the Prospero library. It includes special goodies to keep
the connect() operation from blocking in a multi-threaded environment.
Non-blocking or briefly-blocking TCP opens are important here. */
/* Uses hostname2addr() in the ARDP library. */
/* Like close, but try again if EINTR */
static int
sure_close(int s)
{
int retval;
while ((((retval = close(s)) == -1) && (errno == EINTR)));
return(retval);
}
/* Wait till the file descriptor is writable or times out */
/* Returns: 1 success, 0, timeout, -1 (& errno) error */
static int
wait_till_writable(int s,int timeout)
{
struct timeval time_out;
fd_set writefds;
int retval;
int soerror;
int lensoerrors = sizeof(soerror);
time_out.tv_sec = timeout;
time_out.tv_usec = 0;
FD_ZERO(&writefds);
FD_SET(s,&writefds);
switch (retval = select(FD_SETSIZE, NULL, &writefds, NULL, &time_out)) {
case 1:
retval = getsockopt(s, SOL_SOCKET, SO_ERROR,
(char *)&soerror, &lensoerrors);
/* While we'd like the error back in soerror,
it fails when there is an error*/
if (retval) return -1;
return 1;
case 0:
case -1:
default:
return(retval);
}
}
/* Wait till the file descriptor is readable or times out */
/* Returns: 1 success, 0, timeout, -1 (& errno) error */
int
wait_till_readable(int s,int timeout)
{
struct timeval time_out;
fd_set readfds;
time_out.tv_sec = timeout;
time_out.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(s,&readfds);
return(select(FD_SETSIZE, &readfds, NULL, NULL, &time_out));
}
int
quick_open_tcp_stream(const char host[], int port, int timeout)
{
extern int ardp_hostname2addr(const char *hostname, struct sockaddr_in *hostaddr);
struct sockaddr_in server; /* server side socket. */
int s; /* the socket */
int tmp; /* return from subfunctions. */
if(ardp_hostname2addr(host, &server)) {
p_err_string = qsprintf_stcopyr(p_err_string,
"%s: unknown host\n", host);
return -1; /* p_err_string not set in callee */
}
server.sin_port = htons(port);
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Couldn't reach host %s: Call to socket(AF_INET, SOCK_STREAM,\
0) failed: errno %d: %s", host, errno, unixerrstr());
return -1;
}
#ifdef SETSOCKOPTS
/* Actually, these may be generally usefull. */
#define M_SETSOCKOPT(f,sol,p1,p2,p3) \
if (setsockopt(f,sol,p1,p2,p3)) { \
p_err_string = qsprintf_stcopyr(p_err_string, \
"INTERNAL: setsockopt failure: %s %s", "##p1##",unixerrstr()); \
sure_close(f); \
return -1; \
}
#ifndef UCX
M_SETSOCKOPT(s, SOL_SOCKET, ~SO_LINGER, 0, 0);
#endif
/* Allow address reuse, I forget exactly why, but its something to do
with a time delay before address:port pairs can be reused otherwise */
M_SETSOCKOPT(s, SOL_SOCKET, SO_REUSEADDR, 0, 0);
/* Attempt to keep a silent connection alive, and so fail if it goes down */
M_SETSOCKOPT(s, SOL_SOCKET, SO_KEEPALIVE, 0, 0);
#endif /*SETSOCKOPTS*/
#if defined(NONBLOCKING_APPROACH) || defined(SELECT_APPROACH)
/* This is one approach to multi-threading. The problem with it is
that we seem to get 'address in use' errors. */
/* Set the socket non-blocking if we're running multithreaded. The main
downside of this approach is that we're not going to be able to get a
great error message if the call to connect() fails, which is why we
don't normally enable this in the non-threaded case. */
/* This code has not been fully tested. If the FNDELAY operation is
unavailable on your version of unix, you will need an alternative
approach. Mitra has one in his TCPTIME patch. */
/* This may be FDELAY on some systems -
its O_NODELAY or O_NONBLOCK on Solaris2.3 & POSIX*/
if(fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
p_err_string = qsprintf_stcopyr(p_err_string,
"call to fcntl(s, F_SETFL, \
FNDELAY) failed: errno %d: %s", errno, unixerrstr());
/* Close the socket so we don't have trash data hanging around. */
sure_close(s);
return -1;
}
#endif /*NONBLOCKING_APPROACH||SELECT_APPROACH*/
/* Connect will do the bind for us! Hooray! That's a relief. */
/* connect() will return -1 if the connection is already in progress. */
#ifdef TIMEOUT_APPROACH
if ((quick_connect(s, (struct sockaddr *) &server, sizeof server, timeout))
==-1) {
#else /*!TIMEOUT_APPROACH*/
redo_connect:
tmp = connect(s, (struct sockaddr *) &server, sizeof server);
if (tmp == -1) {
/* Ick - doing an fprintf, meant that in the non-debugging mode,
where there is no stderr, this will fail and CHANGE errno to "Bad
FileNo */
switch (errno) {
case EINPROGRESS:
#ifdef SELECT_APPROACH
switch (wait_till_writable(s,timeout)) {
case -1: p_err_string = qsprintf_stcopyr(p_err_string,
"unable to connect to: %s(%d)", host, port);
/* "call to select failed: %s", unixerrstr()); */
sure_close(s);
return -1;
case 0:
p_err_string = qsprintf_stcopyr(p_err_string,
"took more than %d secs to connect to: %s(%d)",
timeout, host, port);
sure_close(s);
return -1;
}
/* Default is going to be 1 - which is success */
#endif /*SELECT_APPROACH*/
return s; /* Non-blocking*/
case EINTR: goto redo_connect; /* Interrupted*/
}
#endif /*!TIMEOUT_APPROACH*/
/* I've changed this cos users will see it all the time, lets make
it friendly - this has all the relevant info! - Mitra */
p_err_string = qsprintf_stcopyr(p_err_string,
"Couldn't connect to host %s: %s", host, unixerrstr());
/* Now close it so we don't have the descriptor and associated data
hanging around. */
sure_close(s);
return -1;
}
return s;
}

View File

@@ -0,0 +1,45 @@
/*
* 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>
static int out_ac(OUTPUT out, ACL ac);
int
out_acl(OUTPUT out, ACL acl)
{
int retval = PSUCCESS;
/* This check helps us track down a possible bug involving occasional loops
as a result of subtraction of ACL rights. */
int num_times = 0; /* # of times through loop */
ACL sentinel_acl = NULL; /* mark a sentinel after we've been
through too many times */
for (; acl; acl = acl->next) {
if (acl == sentinel_acl)
internal_error("Found an ACL with a cycle in it");
if(++num_times == 100) sentinel_acl = acl;
if (!retval) retval = out_ac(out, acl);
}
return retval;
}
/* Spits out an ACL line describing the ACL entry "ac". */
static int
out_ac(OUTPUT out, ACL ac)
{
extern char *acltypes[]; /* defined in lib/pfs/acltypes.c */
qoprintf(out, "ACL %'s %'s %'s", acltypes[ac->acetype],
(ac->atype ? ac->atype : ""),
(ac->rights ? ac->rights : ""), 0);
return out_sequence(out, ac->principals);
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file <usc-copyr.h>
*/
#include <usc-license.h>
#include <pfs.h>
#include <pparse.h>
#include <pprot.h>
extern int p__server; /* set if server is calilng this code. */
/* This function sends a protocol reply line in appropriate format describing
the attribute AT. It only outputs for a single attribute, not for a list
of them. */
int
out_atr(OUTPUT out, PATTRIB at, int nesting)
{
int i;
assert(at);
qoprintf(out, "ATTRIBUTE");
for (i = nesting; i; --i) {
qoprintf(out, ">");
}
if (at->nature == ATR_NATURE_FIELD) {
qoprintf(out, " %'s FIELD %'s",
lookup_precedencename_by_precedence(at->precedence),
at->aname);
#ifndef REALLY_NEW_FIELD
/* Databases (files) get the new format right away. */
if (!p__server || out->f ||
lookup_avtype_by_field_name(at->aname) == ATR_UNKNOWN) {
#endif
qoprintf(out, " %'s", lookup_avtypename_by_avtype(at->avtype));
#ifndef REALLY_NEW_FIELD
}
#endif
} else if (at->nature == ATR_NATURE_INTRINSIC) {
qoprintf(out, " %'s INTRINSIC %'s %'s",
lookup_precedencename_by_precedence(at->precedence),
at->aname, lookup_avtypename_by_avtype(at->avtype));
} else {
assert(at->nature == ATR_NATURE_APPLICATION);
qoprintf(out, " %'s APPLICATION %'s %'s",
lookup_precedencename_by_precedence(at->precedence),
at->aname, lookup_avtypename_by_avtype(at->avtype));
}
switch(at->avtype) {
case ATR_SEQUENCE:
return out_sequence(out, at->value.sequence);
break;
case ATR_FILTER:
return out_filter(out, at->value.filter, nesting + 1);
break;
case ATR_LINK:
return out_link(out, at->value.link, nesting + 1, (TOKEN) NULL);
break;
default:
internal_error("Unimplemented or Invalid attribute type!");
/*NOTREACHED */
}
assert(0); /* NOTREACHED */
return(-1); /* To keep GCC happy */
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the file <usc-copyr.h>
*/
#include <usc-copyr.h>
#include <pfs.h>
#include <pparse.h>
int
out_atrs(OUTPUT out, PATTRIB at, int nesting)
{
int retval = PSUCCESS;
for (; at; at = at->next)
if (!retval) retval = out_atr(out, at, nesting);
return retval;
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the file <usc-copyr.h>
*/
#include <usc-copyr.h>
#include <pfs.h>
#include <pparse.h>
/* This sends out the data for a filter, but does not prefix it with the words
ATTRIBUTE FILTER, or anything like that. */
int
out_filter(OUTPUT out, FILTER fil, int nesting)
{
assert(fil); /* sanity checks */
switch(fil->type) {
case FIL_DIRECTORY:
qoprintf(out, " DIRECTORY");
break;
case FIL_HIERARCHY:
qoprintf(out, " HIERARCHY");
break;
case FIL_OBJECT:
qoprintf(out, " OBJECT");
break;
case FIL_UPDATE:
qoprintf(out, " UPDATE");
break;
default:
internal_error("unknown fil->type value.");
}
switch(fil->execution_location) {
case FIL_SERVER:
qoprintf(out, " SERVER");
break;
case FIL_CLIENT:
qoprintf(out, " CLIENT");
break;
default:
internal_error("unknown fil->execution_location");
}
switch(fil->pre_or_post) {
case FIL_PRE:
qoprintf(out, " PRE");
break;
case FIL_POST:
qoprintf(out, " POST");
break;
default:
internal_error("unknown fil->pre_or_post");
}
if (fil->name) {
qoprintf(out, " PREDEFINED %'s", fil->name);
qoprintf(out, " ARGS");
return out_sequence(out, fil->args); /* sequence_reply() terminates
with a \n for us. */
} else {
assert(fil->link);
qoprintf(out, " LINK ");
out_link(out, fil->link, nesting, fil->args);
}
return PSUCCESS;
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the file <usc-copyr.h>
*/
#include <usc-copyr.h>
#include <pfs.h>
#include <pparse.h>
/* This just sends out the data for a link, but does not prefix it with the
word LINK. It will suffix it with arguments, if needed. */
#define chknl(s) ((s) ? (s) : "")
int
out_link(OUTPUT out, VLINK vl, int nesting, TOKEN args)
{
int retval;
assert(vl);
qoprintf(out, " %c %s %'s %s %'s %s %'s %ld", vl->linktype,
chknl(vl->target), chknl(vl->name), chknl(vl->hosttype),
chknl(vl->host), chknl(vl->hsonametype), chknl(vl->hsoname),
vl->version, 0);
if (vl->dest_exp) {
char * cp = NULL;
qoprintf(out, " DEST-EXP %s",
cp = p_timetoasn_stcopyr(vl->dest_exp, cp));
stfree(cp);
}
if (args) {
qoprintf(out, " ARGS");
retval = out_sequence(out, args); /* out_sequence() terminates
with a \n for us. */
} else {
retval = qoprintf(out, "\n");
}
#if 0
if (vl->f_magic_no)
qoprintf(out, "ID REMOTE %ld\n", vl->f_magic_no, 0);
#else /* There has been a minor format change; ID is now preferably sent as an
ID line, not as an attribute line. */
if(vl->f_magic_no) {
int i;
qoprintf(out, "ATTRIBUTE", 0);
for (i = nesting; i; --i) {
qoprintf(out, ">", 0);
}
qoprintf(out, " LINK FIELD ID SEQUENCE REMOTE %ld\n", vl->f_magic_no);
retval = qoprintf(out, "\n");
}
#endif
/* Send recursive sub-attributes if we're already nested. But, if we're at
the top-level (nesting == 0), we could only have gotten here by being
called by list_name(), which makes its own decisions about which
attributes to send. Well, we might have also been called by dswdir(),
but that's OK. */
if (nesting) {
PATTRIB at;
for (at = vl->lattrib; at; at = at->next)
out_atr(out, at, nesting);
}
return(retval);
}

View File

@@ -0,0 +1,20 @@
/*
* 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 <pfs.h>
#include <pparse.h>
#include <pprot.h>
int
out_sequence(OUTPUT out, TOKEN tk)
{
for(; tk; tk = tk->next)
qoprintf(out, " %'b", tk->token);
return qoprintf(out, "\n");
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*/
#include <usc-license.h>
/* Written, 9/18/92, swa@isi.edu */
/* Made use 'previous' member 6/14/93, swa@isi.edu */
/* Turned into qbstokenize 19 Nov 1993, swa@isi.edu */
/* Break up a string into space-separated tokens and recognize Prospero
quoting. This strips off the quoting in the process. This function could
also be called p__tokenize_newstyle_mcomp(), and it serves that function.
It assumes the input string is correctly quoted.
*/
#include <pfs.h>
/* loc is a pointer into the string pointed to by header, where we
should start tokenizing, it is NOT const, but used within the loop,
however since not passed as &loc, it wont be returned as NULL
*/
TOKEN
#ifdef OLDSWA
p__qbstokenize(const char * head, const char *loc)
#else
p__qbstokenize(const char * head, char *loc)
#endif
{
TOKEN retval;
int tmp;
CHECK_MEM();
CHECK_PTRinBUFF(head,loc);
if (!head || !loc) return NULL;
retval = NULL;
for (;;) {
TOKEN tk;
char *buf = NULL;
tmp = p__qbstscanf(head, loc, "%'&b %r", &buf, &loc);
assert(tmp >= 0); /* no possible error, I hope! */
if (tmp == 0)
return retval;
tk = tkalloc(NULL);
tk->token = buf; buf = NULL;
APPEND_ITEM(tk, retval);
if (tmp == 1) return retval; /* no more to tokenize. */
}
}

View File

@@ -0,0 +1,50 @@
/* p__qbstscanf.c
Author: Steven Augart (swa@isi.edu)
Designed, Documented, and Written: 7/18/92 -- 7/27/92
Ported from Gnu C to full ANSI C & traditional C, 10/5/92
& modifier added, detraditionalized: 2/16/93.
Made a wrapper around qscanf(), 3/2/93
Turned into p__qbstscanf(), 19 Nov 1993
*/
/* This file is not a final interface; use it for internal purposes only. */
/* Copyright (c) 1992, 1993 by the University of Southern California. */
/* For copying and distribution information, see the file <usc-license.h> */
#include <usc-license.h>
#include <stdarg.h> /* ANSI variable arguments facility. */
#include <pfs.h>
#include <pparse.h>
int
p__qbstscanf(const char *sthead, /* Start of the string stpos is in */
const char *stpos, /* position for the read ptr. */
const char *format, /* What to scan for. */
...) /* remaining args: pointers to places to store
the data we read, or integers (field widths).
*/
{
va_list ap; /* for varargs */
int retval;
INPUT_ST in_st;
INPUT in = &in_st;
#ifdef P_ALLOCATOR_CONSISTENCY_CHECK
assert(p__bst_consistency_fld(sthead) == P__INUSE_PATTERN);
#endif
CHECK_PTRinBUFF(sthead,stpos);
in->sourcetype = IO_BSTRING;
in->rreq = NULL;
in->s = stpos;
in->file = NULL;
in->bstring_length = p_bstlen(sthead);
assert(sthead <= stpos);
in->offset = stpos - sthead;
assert(in->offset <= in->bstring_length); /* make sure consistent. */
in->flags = PERCENT_R_TARGET_IS_STRING;
va_start(ap, format);
retval = vqscanf(in, format, ap);
va_end(ap);
return retval;
}

718
prospero/lib/pfs/p__req.c Normal file
View File

@@ -0,0 +1,718 @@
/*
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-copyr.h>
*
* Written by swa 1992 to provide common code for starting request
* Modified by prasad 1992 to add Kerberos support
* Modified by bcn 1/93 to use new ardp library and rreq structure
* Modified by swa 6/93 to construct multiple-packet messages.
*/
#include <usc-copyr.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
extern int h_errno;
/* For compatability between GCC-2.3.1 running under SunOS 4.1 and the sunOS
* standard include files (they define size_t and others differently), we MUST
* include stddef and stdarg after anything that might include the sun include
* file <sys/stdtypes.h> (in this case, <pwd.h> includes <sys/stdtypes.h>).
*/
#include <stddef.h>
#include <stdarg.h>
#include <ardp.h>
#include <psite.h> /* must precede pfs.h for defs. of P_KERBEROS, */
/* P_P_PASSWORD */
#include <pfs.h>
#include <pprot.h>
#include <perrno.h>
#include <pcompat.h>
#ifdef P_KERBEROS
#include <krb5/krb5.h>
#endif /* P_KERBEROS */
/* gives us a name for this buffer, which we need so we
can keep the reference around. */
/* Ok that this is static, since it's read-only. */
static char pfs_sw_id_buf[] = PFS_SW_ID;
static char *pfs_sw_id = pfs_sw_id_buf;
/* Oops - I dont think a "char p__username" is very usefull! - Mitra*/
char *p__username = NULL;
extern int pfs_debug;
static PAUTH p__get_pauth(int type, const char *hostname);
#ifdef P_P_PASSWORD
char *ppw_encode();
#endif /* P_P_PASSWORD */
char *get_psession_filename();
static char *uid_to_name();
#ifdef P_ACCOUNT
static void p__add_acc_req();
#endif
/* This code handles possible multiple resettings of the software ID
without any memory leaks.
It is internal; should only be called through p_initialize(). Nothing will
break if you ignore this admonition, but it keeps the library interface
smaller. */
void
p__set_sw_id(char *app_sw_id)
{
assert(P_IS_THIS_THREAD_MASTER());
if (app_sw_id && *app_sw_id) {
if (pfs_sw_id == pfs_sw_id_buf)
pfs_sw_id = qsprintf_stcopyr(NULL,"%s(%s)",app_sw_id,PFS_SW_ID);
else
pfs_sw_id = qsprintf_stcopyr(pfs_sw_id,"%s(%s)",app_sw_id,
PFS_SW_ID);
} else {
/* Resetting software ID to normal values. */
if (pfs_sw_id == pfs_sw_id_buf)
; /* Same as before; leave set to default. */
else {
stfree(pfs_sw_id); /* must be set to some allocated memory. */
pfs_sw_id = pfs_sw_id_buf;
}
}
}
/*
* p__start_req - start a prospero request
*
* p__start_req takes the name of the server (used by Kerberos to
* determine what credentials are needed), it allocates a request
* structure, and it fills in the start, including the Prospero
* version and software ID, and authentication information. The
* function returns a request of type RREQ, which can be used
* in subsequent calls to p__addreq, and passed to ardp_send.
*/
RREQ
p__start_req(const char server_hostname[])
{
RREQ req = ardp_rqalloc(); /* The request to fill in */
PAUTH authinfo; /* Structure containing authentication info */
PAUTH authp; /* To iterate through authinfo list */
TOKEN prin; /* To Iterate through principal names */
#ifdef CLIENTS_REQUEST_VERSION_FROM_SERVER
p__add_req(req, "VERSION\n");
#endif
p__add_req(req, "VERSION %d %s", VFPROT_VNO, pfs_sw_id);
authinfo = p__get_pauth(PFSA_UNAUTHENTICATED, server_hostname);
if (authinfo) {
p__add_req(req, "\nAUTHENTICATE '' UNAUTHENTICATED %'s",
authinfo->authenticator);
/* For the UNAUTHENTICATED and KERBEROS authentication types, */
/* the principals are optional additional information for */
/* debugging use. We don't worry about them here. */
for(prin = authinfo->principals; prin; prin = prin->next)
p__add_req(req, " %'s", prin->token);
pafree(authinfo);
}
#ifdef P_KERBEROS
authinfo = p__get_pauth(PFSA_KERBEROS, server_hostname);
for (authp = authinfo; authp; authp = authp->next) {
p__add_req(req, "\nAUTHENTICATE '' KERBEROS %'s",
authp->authenticator);
/* For the UNAUTHENTICATED and KERBEROS authentication types, the
principals are optional additional information for debugging use.
We don't worry about them here. */
for (prin = authp->principals; prin; prin = prin->next)
p__add_req(req, " %'s", prin->token);
}
if (authinfo)
palfree(authinfo);
#endif
#ifdef P_P_PASSWORD
authinfo = p__get_pauth(PFSA_P_PASSWORD, server_hostname);
for (authp = authinfo; authp; authp = authp->next) {
p__add_req(req, "\nAUTHENTICATE OPTIONAL P_PASSWORD %'s",
authp->authenticator);
/* Principal NOT optional here! */
for (prin = authp->principals; prin; prin = prin->next)
p__add_req(req, " %'s", prin->token);
}
if (authinfo)
palfree(authinfo);
#endif
p__add_req(req, "\n");
#ifdef P_ACCOUNT
p__add_acc_req(req, server_hostname);
#endif
return(req);
}
/* Adds stuff to a Prospero request. */
int
p__add_req(RREQ req, const char fmt[], ...)
{
int retval;
va_list ap;
va_start(ap,fmt);
retval = vp__add_req(req, fmt, ap);
va_end(ap);
return(retval);
}
int
vp__add_req(RREQ req, const char fmt[], va_list ap)
{
PTEXT ptmp; /* packet being written to. */
int mesglen; /* # of characters in this message, NOT
including trailing NUL which doesn't need to
be sent. */
AUTOSTAT_CHARPP(bufp); /* buffer for long packets */
int numsent; /* How many chars. out of buf have been sent so
far? */
if(!req->outpkt) {
ptmp = ardp_ptalloc();
if(!ptmp) RETURNPFAILURE;
APPEND_ITEM(ptmp,req->outpkt);
} else {
ptmp = req->outpkt->previous; /* last member of list. */
}
/* Subtract 1: Trailing NUL character isn't sent,
since the length of the message is encoded into the message. Recipient
will automatically append the NUL byte for convenience of the users. */
/* Add one to buffer space available, since it includes an MBZ byte to
catch runaway strings. vqsprintf() will always null-terminate the
strings it writes. */
mesglen =
vqsprintf(ptmp->ioptr, ARDP_PTXT_LEN + 1 - ptmp->length, fmt, ap) - 1;
if (ptmp->length + mesglen <= ARDP_PTXT_LEN) {
ptmp->length += mesglen;
ptmp->ioptr = ptmp->start + ptmp->length;
return(PSUCCESS);
}
/* Ran out of room. Have to write it to a temporary buffer, then copy. */
/* Four-line Optimization: we already know we're going to need mesglen + 1
of buffer space. By doing this, we save a possible double calling of
vqsprintf() in p__vqbstprintf_stcopyr(). */
if (p__bstsize(*bufp) < mesglen + 1) {
stfree(*bufp);
*bufp = stalloc(mesglen + 1);
}
/* There used to be a lot of code here that did this in a slightly more
efficient way, but I am willing to suffer a performance penalty
in order to make this work more transparently. */
*bufp = p__vqbstprintf_stcopyr(*bufp, fmt, ap);
assert(mesglen == p_bstlen(*bufp));
/* Record what we already sent. */
numsent = ARDP_PTXT_LEN - ptmp->length;
ptmp->length = ARDP_PTXT_LEN;
/* Start this loop with the current ptmp full of as much data as it can
hold. */
while (numsent < mesglen) {
ptmp = ardp_ptalloc();
if(!ptmp) RETURNPFAILURE;
APPEND_ITEM(ptmp,req->outpkt);
ptmp->length = ( mesglen - numsent > ARDP_PTXT_LEN
? ARDP_PTXT_LEN : mesglen - numsent);
strncpy(ptmp->start, *bufp + numsent, ptmp->length);
ptmp->ioptr = ptmp->start + ptmp->length;
numsent += ptmp->length;
}
return PSUCCESS;
}
void
p__set_username(char *un)
{
p__username = stcopyr(un, p__username);
}
static
PAUTH p__get_pauth(int type, const char server_hostname[])
{
#ifdef P_KERBEROS
krb5_data buf;
krb5_checksum send_cksum;
krb5_ccache ccdef;
krb5_principal server;
static char *tkt_file = NULL;
int retval = 0;
#endif
#ifdef P_P_PASSWORD
PAUTH curr_auth = NULL;
static char *password = NULL;
typedef struct _p_passwd {
char *hostname;
char *princ_name;
char *password;
struct _p_passwd *next;
} p_passwd;
p_passwd *p_list = NULL, *p_ptr;
#endif
PAUTH auth = paalloc();
int ruid, euid;
FILE *psession_fp;
char *psession_filename = get_psession_filename();
char line[255];
AUTOSTAT_CHARPP(hostnamep);
AUTOSTAT_CHARPP(princ_namep);
int num, entry_exists = 0;
char full_hname[255];
struct hostent *host;
char *cp;
char *hostaddr = NULL;
struct in_addr haddr;
#if defined(P_KERBEROS) || defined(P_P_PASSWORD)
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
#endif
CHECK_MEM();
auth->principals = NULL; /* not really needed. Let's be paranoid. */
/* Convert hostname into canonical form */
qsprintf(full_hname, sizeof full_hname, "%s", server_hostname);
/* Strip off the trailing (portnum), if any */
for (cp = full_hname; *cp; ++cp)
;
if (cp > full_hname && *--cp == ')') {
while (*--cp && cp >= full_hname) {
if (*cp == '(') {
*cp = '\0';
break;
}
if (!isdigit(*cp))
break;
}
}
/* Look up server host */
/* Not multi-threaded yet because clients not done yet. */
CHECK_MEM();
assert(P_IS_THIS_THREAD_MASTER());
if ((host = gethostbyname(full_hname)) == (struct hostent *) 0) {
if (pfs_debug)
fprintf(stderr, "p__get_pauth(): unknown host %s\n",
full_hname);
pafree(auth);
return NULL;
}
qsprintf(full_hname, sizeof full_hname, "%s", host->h_name);
bcopy(host->h_addr,&haddr,sizeof(haddr));
hostaddr = stcopy(inet_ntoa(haddr));
switch(auth->ainfo_type = type) {
case PFSA_UNAUTHENTICATED:
if (p__username) {
auth->authenticator = stcopy(p__username);
return auth;
}
/* Upper-case to use in search of password file */
for (cp = full_hname; *cp; cp++)
if (islower(*cp))
*cp = toupper(*cp);
/* Get the real and effective user ids */
ruid = getuid();
euid = geteuid();
/* check if the psession file exists */
if (!(psession_fp = fopen(psession_filename, "r")))
/* No file; send real uid across */
auth->authenticator = uid_to_name(ruid);
else {
while (fgets(line, sizeof(line), psession_fp)) {
num = qsscanf(line,
"AUTHENTICATE %'&s UNAUTHENTICATED %'&s\n",
&(*hostnamep), &(*princ_namep));
if (num < 2)
continue;
if (wcmatch(full_hname, (*hostnamep)) ||
strequal(hostaddr, (*hostnamep))) {
entry_exists = 1;
break;
}
}
fclose(psession_fp);
/* No entry in file; */
/* no UNAUTHENTICATED authentication sent */
if (!entry_exists) {
pafree(auth);
return NULL;
}
if ((*princ_namep)[0] && (!ruid || euid))
#ifdef OVERRIDE_DEFAULT_USERNAME
auth->authenticator = stcopy((*princ_namep));
#else
auth->authenticator = uid_to_name(ruid);
#endif
else
auth->authenticator = uid_to_name(ruid);
}
return(auth);
break;
#ifdef P_KERBEROS /* 4/5/93 Made error handling pass errors
to higher layers. */
case PFSA_KERBEROS:
if (!(psession_fp = fopen(psession_filename, "r"))) {
/* No file; do not send KERBEROS authentication */
pafree(auth);
return NULL;
}
while (fgets(line, sizeof(line), psession_fp)) {
num = qsscanf(line, "AUTHENTICATE %'&s KERBEROS %'&s %'&s\n",
&(*hostnamep), &(*princ_namep), &tkt_file);
if (num < 3)
continue;
if (wcmatch(full_hname, (*hostnamep)) ||
strequal(hostaddr, (*hostnamep))) {
entry_exists = 1;
break;
}
}
fclose(psession_fp);
if (!entry_exists) {
/* No entry; do not send KERBEROS authentication */
pafree(auth);
return NULL;
}
/* If ticket-file name not empty, tell KRB5 routines to look */
/* at it. */
if (tkt_file[0])
setenv("KRB5CCNAME", tkt_file, 1);
/* PREPARE KRB_AP_REQ MESSAGE */
/* compute checksum, using CRC-32 */
if (!(send_cksum.contents = (krb5_octet *)
stalloc(krb5_checksum_size(CKSUMTYPE_CRC32)))) {
if (pfs_debug)
fprintf(stderr, "p__get_pauth(): Cannot allocate Kerberos checksum\n");
pafree(auth);
return NULL;
}
/* choose some random stuff to compute checksum from */
if (retval = krb5_calculate_checksum(CKSUMTYPE_CRC32,
(char *) server_hostname,
strlen(server_hostname),
0,
0, /* if length is 0, */
/* crc-32 doesn't use */
/* the seed */
&send_cksum)) {
if (pfs_debug)
fprintf(stderr, "p__get_pauth(): Error while computing Kerberos checksum\n");
stfree(send_cksum.contents);
pafree(auth);
return NULL;
}
/* Get credentials for server, create krb_mk_req message */
if (retval = krb5_cc_default(&ccdef)) {
if (pfs_debug)
fprintf(stderr, "p__get_pauth(): Error while getting default \
Kerberos cache\n");
stfree(send_cksum.contents);
pafree(auth);
return NULL;
}
/* Format service name into a principal structure and */
/* canonicalizes host name. */
if (retval = krb5_sname_to_principal(full_hname,
KERBEROS_SERVICE,
1, /* Canonicalize */
&server)) {
if (pfs_debug)
fprintf(stderr, "p__get_pauth(): Error while setting up \
Kerberos server principal\n");
stfree(send_cksum.contents);
pafree(auth);
return NULL;
}
if (retval = krb5_mk_req(server, 0 /* default options */, &send_cksum,
ccdef, &buf)) {
if (pfs_debug) fprintf(stderr, "p__get_pauth(): Error while \
preparing Kerberos AP_REQ\n");
pafree(auth);
stfree(send_cksum.contents);
return NULL;
}
stfree(send_cksum.contents);
auth->authenticator = stalloc(AUTHENTICATOR_SZ);
retval = binencode(buf.data, buf.length,
auth->authenticator,
AUTHENTICATOR_SZ);
if (retval >= AUTHENTICATOR_SZ) {
internal_error("binencode: Buffer too small");
}
return(auth);
break;
#endif /* P_KERBEROS */
#ifdef P_P_PASSWORD
case PFSA_P_PASSWORD:
/* Upper-case to use in search of password file */
for (cp = full_hname; *cp; cp++)
if (islower(*cp))
*cp = toupper(*cp);
if (!(psession_fp = fopen(psession_filename, "r"))) {
#if 0 /* This is annoying. It's NOT AN ERROR for
somebody not to have set up a session file, at
least not right now. --swa, 9 May 1994 */
if (pfs_debug)
fprintf(stderr, "p__get_pauth(): Error in P_PASSWORD \
authentication: Cannot open psession file %s\n", psession_filename);
#endif
pafree(auth);
return NULL;
}
while (fgets(line, sizeof(line), psession_fp)) {
if (line[0] == '#')
continue;
num = qsscanf(line, "AUTHENTICATE %'&s P_PASSWORD %'&s %'&s\n",
&(*hostnamep), &(*princ_namep), &password);
if (num < 3) /* Ignore if no password */
continue;
if (wcmatch(full_hname, (*hostnamep)) ||
strequal(hostaddr, (*hostnamep))) {
p_passwd *last = NULL;
for (p_ptr = p_list; p_ptr; last = p_ptr, p_ptr = p_ptr->next)
if (!strcmp((*princ_namep), p_ptr->princ_name)) {
if (isdigit(p_ptr->hostname[0]))
break; /* Already have most specific */
/* address */
if (isdigit((*hostnamep)[0]) ||
strlen((*hostnamep)) > strlen(p_ptr->hostname)) {
p_ptr->hostname = stcopyr((*hostnamep), p_ptr->hostname);
p_ptr->password = stcopyr(password, p_ptr->password);
}
break;
}
if (!p_ptr) {
if (!last) {
p_list = (p_passwd *) stalloc(sizeof(p_passwd));
last = p_list;
}
else {
last->next = (p_passwd *) stalloc(sizeof(p_passwd));
last = last->next;
}
last->hostname = stcopy((*hostnamep));
last->princ_name = stcopy((*princ_namep));
last->password = stcopy(password);
last->next = NULL;
}
}
}
(void) fclose(psession_fp);
pafree(auth);
auth = NULL;
for (p_ptr = p_list; p_ptr; p_ptr = p_ptr->next) {
if (!auth)
auth = curr_auth = paalloc();
else {
curr_auth->next = paalloc();
curr_auth = curr_auth->next;
}
curr_auth->ainfo_type = type;
curr_auth->authenticator = stcopy(ppw_encode(p_ptr->password));
curr_auth->principals = tkalloc(p_ptr->princ_name);
curr_auth->next = NULL;
}
return(auth);
break;
#endif /* P_P_PASSWORD */
default:
fprintf(stderr, "p__get_pauth(): Unknown authenticator type: %d\n", type);
internal_error("Unknown authenticator type!");
/* NOTREACHED */
}
assert(FALSE); /*Unreached*/
return(NULL); /* To keep GCC happy*/
}
#ifdef P_ACCOUNT
static void
p__add_acc_req(RREQ req, char *server_hostname)
{
FILE *psession_fp;
char *psession_filename = get_psession_filename();
char line[255];
static char *hostname = NULL, *acc_method = NULL;
static char *acc_server = NULL, *acc_name = NULL;
static char *acc_verifier = NULL, *int_bill_ref = NULL;
static char *currency = NULL, *prompt_amt = NULL, *max_amt = NULL;
struct hostent *host;
char *cp;
char *hostaddr = NULL;
struct in_addr haddr;
int num, entry_exists = 0;
char full_hname[255];
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
/* Convert hostname into canonical form */
qsprintf(full_hname, sizeof full_hname, "%s", server_hostname);
/* Strip off the trailing (portnum), if any */
for (cp = full_hname; *cp; ++cp)
;
if (cp > full_hname && *--cp == ')') {
while (*--cp && cp >= full_hname) {
if (*cp == '(') {
*cp = '\0';
break;
}
if (!isdigit(*cp))
break;
}
}
/* Look up server host */
assert(P_IS_THIS_THREAD_MASTER());
if ((host = gethostbyname(full_hname)) == (struct hostent *) 0) {
if (pfs_debug)
fprintf(stderr, "p__add_acc_req(): unknown host %s\n",
full_hname);
return;
}
qsprintf(full_hname, sizeof full_hname, "%s", host->h_name);
bcopy(host->h_addr,&haddr,sizeof(haddr));
hostaddr = stcopy(inet_ntoa(haddr));
/* Upper-case to use in search of password file */
for (cp = full_hname; *cp; cp++)
if (islower(*cp))
*cp = toupper(*cp);
if (!(psession_fp = fopen(psession_filename, "r")))
return;
while (fgets(line, sizeof(line), psession_fp)) {
num = qsscanf(line, "ACCOUNT %'&s %'&s %'&s %'&s %'&s %'&s\n",
&hostname, &acc_method, &acc_server, &acc_name,
&acc_verifier, &int_bill_ref);
if (num < 6)
continue;
if (wcmatch(full_hname, hostname) ||
strequal(hostaddr, hostname)) {
p__add_req(req, "ACCOUNT MANDATORY %'s %'s %'s %'s %'s",
acc_method, acc_server, acc_name,
ppw_encode(acc_verifier), int_bill_ref);
while(fgets(line, sizeof(line), psession_fp) &&
strnequal(line, "CURRENCY", strlen("CURRENCY"))) {
num = qsscanf(line, "CURRENCY %'&s %'&s %'&s\n",
&currency, &prompt_amt, &max_amt);
if (num < 2)
continue;
p__add_req(req, " %'s %'s", currency, prompt_amt);
}
p__add_req(req, "\n");
break;
}
}
fclose(psession_fp);
}
#endif /* P_ACCOUNT */
/* returns name of user's psession file. */
char *get_psession_filename()
{
int uid;
char *home;
static char *psession_filename = NULL;
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
if (!(psession_filename = stcopy(getenv("PSESSION")))) {
uid = getuid();
if (!(home = getenv("HOME"))) {
if (pfs_debug)
fprintf(stderr,
"ERROR: Could not get value of HOME!\n");
return NULL;
}
psession_filename = qsprintf_stcopyr(psession_filename,
"%s/.psession_%d",
home, uid);
}
return psession_filename;
}
/* Converts a uid into a username. If unknown uid, returns a string of */
/* the form "uid#<uid>" */
static char *uid_to_name(int uid)
{
struct passwd *whoiampw;
assert(P_IS_THIS_THREAD_MASTER()); /*getpwuid MT-Unsafe*/
DISABLE_PFS(whoiampw = getpwuid(uid));
if (whoiampw == 0) {
char tmp_uid_str[100];
qsprintf(tmp_uid_str, sizeof tmp_uid_str, "uid#%d", uid);
return stcopy(tmp_uid_str);
}
else {
return stcopy(whoiampw->pw_name);
}
}
/* Two-way function to encode string.*/
char *ppw_encode(char *str)
{
static char *retstr = NULL;
int i;
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
retstr = stcopyr(str, retstr);
for (i = 0; retstr[i]; i++)
if (retstr[i] > 31 && retstr[i] < 127)
retstr[i] = 126 - retstr[i] + 32;
return retstr;
}

View File

@@ -0,0 +1,654 @@
/*
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*
* Written by bcn 1989 modified 1989-1992
* Modified by swa 1992 to use qsscanf()
* Modified by bcn 1/93 to use ardp library
* bug fix by cheang 11/93 pre server filters.
*/
#include <usc-license.h>
#include <stdio.h>
#include <string.h>
#include <pprot.h>
#include <ardp.h>
#include <pfs.h>
#include <perrno.h>
#include <pparse.h>
#include <pmachine.h>
extern int pfs_debug;
extern TOKEN p__tokenize_midstyle_mcomp(char *nextname);
static void build_out(VDIR dir, OUTPUT out, char *options, FILTER *ptr_filters) {
/* Build dir->dqs->preq and out */
/* Note side effect, filters updated to point to first client filter */
struct dqstate *dqs = dir->dqs;
FILTER filters = *ptr_filters;
dir->status = DQ_ACTIVE;
dqs->preq = p__start_req(dqs->dl->host);
requesttoout(dqs->preq,out); /* two ways to output to this. */
if(dqs->flags & GVD_MOTD) p__add_req(dqs->preq, "PARAMETER GET MOTD\n");
if(dqs->flags & GVD_MOTD_O) return; /* Skip over query */
/* The Server FILTER option should be applied only once before */
/* union link expansion. */
if(filters && filters->execution_location == FIL_SERVER) {
static char * fil_option = NULL;
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
fil_option = qsprintf_stcopyr(fil_option, "%s+FILTER", options);
p__add_req(dqs->preq, "DIRECTORY ASCII %'s\nLIST %s COMPONENTS",
dqs->dl->hsoname, fil_option + 1);
}
else
p__add_req(dqs->preq, "DIRECTORY ASCII %'s\nLIST %s COMPONENTS",
dqs->dl->hsoname,
(*options) ? options+1 : "''" );
if(dqs->comp) {
p__add_req(dqs->preq, " %'s", dqs->comp);
if (dqs->mcomp) {
#ifdef CLIENT_SEND_NEW_MCOMP
out_sequence(out, *dqs->acomp); /* terminates with a \n. */
#else
TOKEN acp;
for (acp = *dqs->acomp; acp; acp = acp->next) {
if(!(acp->token) || (!*(acp->token)))
p__add_req(dqs->preq, "/*", acp->token);
else p__add_req(dqs->preq, "/%'s", acp->token);
}
p__add_req(dqs->preq, "\n");
#endif
} else {
p__add_req(dqs->preq, "\n");
}
} else {
p__add_req(dqs->preq, "\n");
}
/* Append any appropriate filters to the request. */
while (filters && filters->execution_location == FIL_SERVER
&& (filters->type == FIL_DIRECTORY
|| filters->type == FIL_HIERARCHY)) {
qoprintf(out, "FILTER");
out_filter(out, filters, 0);
filters = filters->next;
}
}
static int
retrieve_and_parse( VDIR dir)
{
/* Retrieve and parse a ardp response, */
INPUT_ST in_st; /* Input pointer for response contents */
INPUT in = &in_st;
struct dqstate *dqs = dir->dqs;
CHECK_MEM();
rreqtoin(dqs->preq, in);
while(!in_eof(in)) {
int tmp;
char *line;
char *next_word;
CHECK_MEM();
if (tmp = in_line(in, &line, &next_word))
return(tmp);
switch (*line) {
char l_htype[MAX_DIR_LINESIZE];
char l_host[MAX_DIR_LINESIZE];
char l_ntype[MAX_DIR_LINESIZE];
char l_fname[MAX_DIR_LINESIZE];
int l_version;
int l_magic;
char t_unresolved[MAX_DIR_LINESIZE];
case 'A': /* ATTRIBUTE lines that apply to this
directory. */
if (!strnequal(line, "ATTRIBUTE", sizeof "ATTRIBUTE" - 1))
goto scanerr;
if (tmp = in_ge1_atrs(in, line, next_word, &dir->attributes)) {
if (pfs_debug)
perrmesg("p_get_dir()", 0, NULL);
return(tmp);
}
case 'L': /* LINK or LINK-INFO */
if(!strnequal(line,"LINK",4))
goto scanerr;
/* If only verifying, don't want to change dir */
if(dqs->flags & GVD_VERIFY) {
break;
}
/* If first link and some links in dir, free them */
if(!dqs->newlinks++) {
if(dir->links) vllfree(dir->links); dir->links=NULL;
if(dir->ulinks) vllfree(dir->ulinks); dir->ulinks=NULL;
}
CHECK_MEM();
if (tmp = in_link(in,line,next_word,0,&(dqs->clnk),
(TOKEN *) NULL)) {
if (pfs_debug)
perrmesg("p_get_dir()", 0, NULL);
return(DIRSRV_BAD_FORMAT);
}
/* Double check to make sure we don't get */
/* back unwanted components */
/* OK to keep if special (URP) links */
/* or if dqs->mcomp specified */
if(!dqs->mcomp &&
((dqs->clnk->linktype == 'L') ||
(dqs->clnk->linktype == 'I')) && dqs->comp
&& (!wcmatch(dqs->clnk->name,dqs->comp))) {
vlfree(dqs->clnk); dqs->clnk = NULL;
break;
}
/* If other optional info was sent back, it must */
/* also be parsed before inserting link *** */
if(dqs->clnk->linktype == 'L' || dqs->clnk->linktype == 'I')
vl_insert(dqs->clnk,dir,
(dqs->flags & GVD_NOSORT) ? VLI_NOSORT : VLI_ALLOW_CONF
);
else {
tmp = ul_insert(dqs->clnk,dir,dqs->pulnk);
/* If inserted after dqs->pulnk, next one after dqs->clnk*/
if(dqs->pulnk && (!tmp || (tmp == UL_INSERT_SUPERSEDING)))
dqs->pulnk = dqs->clnk;
}
break;
case 'F': /* FAILURE or FORWARDED */
/* FORWARDED */
if(strncmp(line,"FORWARDED",9) == 0) {
if((dqs->fwdcnt)-- <= 0) {
perrno = PFS_MAX_FWD_DEPTH;
if (pfs_debug)
perrmesg("p_get_dir()", 0, NULL);
return(perrno);
}
/* parse and start over */
tmp = qsscanf(line,"FORWARDED %s %'s %s %'s %d %d",
l_htype,l_host,l_ntype,l_fname,
&l_version, &l_magic);
dqs->dl->host = stcopyr(l_host, dqs->dl->host);
dqs->dl->hsoname = stcopyr(l_fname, dqs->dl->hsoname);
if(tmp < 4) {
if (pfs_debug)
fprintf(stderr,
"p_get_dir(): Malformed FORWARDED line: %s",
line);
return(DIRSRV_BAD_FORMAT);
}
ardp_rqfree(dqs->preq);
dqs->preq = NOREQ;
dir->status = DQ_INACTIVE;
return(DSRFINFO_FORWARDED);
}
goto scanerr;
break;
case 'N': /* NONE-FOUND */
/* NONE-FOUND, we just have no links to insert */
/* It is not an error, but we must clear any */
/* old links in the directory arg */
if(strncmp(line,"NONE-FOUND",10) == 0) {
/* If only verifying, don't want to change dir */
if(dqs->flags & GVD_VERIFY) {
break;
}
/* If first link and some links in dir, free them */
if(!dqs->newlinks++) {
if(dir->links) vllfree(dir->links);
if(dir->ulinks) vllfree(dir->ulinks);
dir->links = NULL;
dir->ulinks = NULL;
}
break;
}
/* If anything else, scan error */
goto scanerr;
case 'U': /* UNRESOLVED */ {
char *p_unresolved;
TOKEN new_acomp;
int newlen, oldlen;
tmp = qsscanf(line,"UNRESOLVED %r", &p_unresolved);
if(tmp < 1) goto scanerr;
#ifndef DONT_ACCEPT_OLD_MCOMP
new_acomp = p__tokenize_midstyle_mcomp(p_unresolved);
#else /* guaranteed a new reply from server */
new_acomp = qtokenize(p_unresolved);
#endif
newlen = length(new_acomp);
oldlen = length(*dqs->acomp);
/* If multiple components were resolved */
/* Must be a proper suffix. */
if (newlen != oldlen) {
if (oldlen <= newlen) goto badunresolved;
/* Comp gets the last component resolved. (NB: Indexing
for elt() starts at 0.) */
dqs->comp = stcopy(elt(*dqs->acomp, oldlen - newlen - 1));
dqs->stfree_comp = 1;
/* Let rd_vdir know what remains */
tklfree(*dqs->acomp);
*dqs->acomp = new_acomp;
}
dqs->unresp = 1;
break;
badunresolved:
if (pfs_debug)
fprintf(stderr, "p_get_dir(): Received an UNRESOLVED \
response not a proper suffix of the acomp sent. This is not legal: %s\n",
line);
#if 0 /* mitra commented these out; unclear why */
ardp_rqfree(dir->dqs->preq);
if (dir->dqs->stfree_comp) stfree(dir->dqs->comp);
stfree(dir->dqs); dir->dqs = NULL;
#endif
return perrno = dir->status = DIRSRV_BAD_FORMAT;
} /* case 'U' (unresolved) */
scanerr:
default:
if(tmp = scan_error(line, dqs->preq)) {
/* XXX memory leak? check this mitracode. */
/* change 1 follows */
return(tmp);
}
break;
} /* switch */
} /*while*/
return PSUCCESS;
} /* bad_p_get_dir( */
/*
* p_get_dir - Get contents of a directory given its location
*
* P_GET_DIR takes a directory location, a list of desired
* components, a pointer to a directory structure to be
* filled in, and flags. It then queries the appropriate
* directory server and retrieves the desired information.
*
* ARGS: dlink - Host and host specific object name for directory
* plus any filters to be applied (->filters)
* components - The first component of the name we want to
* resolve in that directory. Wildcards are
* allowed if there are no additional components.
* NULL or the empty string means 'all'.
* dir - Structure to be filled in (or possibly in the
* process of being filled in, if GVD_ASYNC)
* flags - Options. See FLAGS
* acomp - Pointer to a token list consisting of the
* remaining components of the name we
* want to resolve in that directory. This
* argument might get modified. If it is, acomp
* will be left pointing to a suffix (not
* necessarily a proper suffix) of the token list or
* NULL, and the extra tokens will be freed by
* p_get_dir().
*
* FLAGS: GVD_UNION - Do not expand union links
* GVD_EXPAND - Expand union links locally
* GVD_REMEXP - Request remote expansion (& local if refused)
* GVD_LREMEXP - Request remote expansion of local union links
* GVD_VERIFY - Only verify that args are for a directory
* GVD_FIND - Stop expanding when a match is found
* GVD_ATTRIB - Request attributes from directory server
* GVD_NOSORT - Do not sort links when adding to directory
* GVD_MOTD - Request MOTD string from server
* GVD_MOTD_O - Request MOTD and nothing else
* GVD_ASYNC - Process request asynchronously
*
* RETURNS: PSUCCESS (0) or error code on completion.
* On some codes addition information in p_err_string.
* DQ_ACTIVE if request if GVD_ASYNC specified and
* request is still active.
*
* NOTES: If acomp is non-null the string it points to might be modified
*
* If the directory passed as an argument already has
* links or union links, then those lists will be freed
* before the new contents are filled in.
*
* If a filter is passed to the procedure, and application of
* the filter results in additional union link, then those links
* will (or will not) be expanded as specified in the FLAGS field.
*
* If the list of components in NULL, or the null string, then
* p_get_dir will return all links in the requested directory.
*/
/* XXX
* See bug report in /nfs/pfs/bugs/p_get_dir_modifies_argument for
* an explanation of what needs to be done to make this code
* more aesthetic and maintainable. this is a quick fix to get it working.
*/
#define RETURN(rv) { retval = (rv); goto cleanup ; }
static int
bad_p_get_dir(VLINK dlink, /* Directory to examine */
const char *components,/* Component name (wildcards allowed). */
VDIR dir, /* Structure to be filled in */
long flags, /* Flags */
TOKEN *acomp) /* Components left to be resolved */
{
struct dqstate *dqs; /* State of current query */
OUTPUT_ST out_st; /* Output pointer for packet contents */
OUTPUT out = &out_st;
int ardptime; /* Time to wait for ardp_send */
int tmp; /* To check return values */
VLINK tl = NULL; /* Temp link used for apply_filter() */
/* Setting it to NULL shuts up GCC; never used
before set. */
VLINK l; /* Temp link pointer */
FILTER filters; /* Filters to apply this time through */
char options[40]; /* LIST option */
char *tchar; /* Temporary chatacter pointer */
int retval; /* Hold return value */
perrno = 0;
if((dir->status == DQ_ACTIVE) && dir->dqs) {
dqs = dir->dqs;
/* Turn off this query's GVD_ASYNC flag if it was set on a previous
call to P_GET_DIR. */
if(!(flags & GVD_ASYNC)) dqs->flags &= (~GVD_ASYNC);
}
else {
/* Initialize a new dqstate structure. */
dqs = (struct dqstate *) stalloc(sizeof(struct dqstate));
if(!dqs) RETURN(PFAILURE);
dir->dqs = dqs;
dqs->dl = dlink;
if (!components || (*components == '\0')) dqs->comp = NULL;
else dqs->comp = (char *) components; /* strip off CONST. */
dqs->stfree_comp = 0;
dqs->acomp = acomp;
dqs->flags = flags;
dqs->fwdcnt = MAX_FWD_DEPTH;
dqs->newlinks = 0;
dqs->clnk = NULL;
dqs->cexp = NULL;
dqs->pulnk = NULL;
/* If filters, don't do remote expansion of union links! */
#ifdef NEVERDEFINED
/* I cant see why not! */
if(dqs->dl->filters) {
dqs->flags &= (~(GVD_REMEXP&(~GVD_EXPAND)));
dqs->comp = NULL;
}
#endif
if(acomp && *acomp && !dlink->filters) dqs->mcomp = 1;
else dqs->mcomp = 0;
}
*options = '\0';
if(dqs->flags & GVD_ATTRIB) strcat(options,"+ATTRIBUTES");
if((dqs->flags & GVD_EXPMASK) == GVD_REMEXP) strcat(options,"+EXPAND");
if((dqs->flags & GVD_EXPMASK) == GVD_LREMEXP) strcat(options,"+LEXPAND");
/* If all we are doing is verifying a directory */
/* we do not want a big response from the directory */
/* server. A NOT-FOUND is sufficient. */
if(dqs->flags & GVD_VERIFY) strcat(options,"+VERIFY");
if((dir->status == DQ_ACTIVE) && dir->dqs) goto cont_async;
startover:
filters = dqs->dl->filters;
if(filters) {
if(tl) vlfree(tl); /* Loop with filter leaked old copy */
tl = vlalloc(); /* Pased to apply_filters */
tl->name = stcopy("UNNEEDED");
tl->host = stcopy(dqs->dl->host);
tl->hsoname = stcopy(dqs->dl->hsoname);
tl->filters = flcopy(filters,1); /* otherwise gets freed twice*/
}
get_contents:
/* Build dir->dqs->preq and out */
/* Side effect, filters now points to first client-side filter */
build_out(dir, out, options, &filters);
cont_async:
if(dqs->flags & GVD_ASYNC) ardptime = 0;
else ardptime = ARDP_WAIT_TILL_TO;
if(dqs->preq->status == ARDP_STATUS_NOSTART)
tmp = ardp_send(dqs->preq,dqs->dl->host,0,ardptime);
else tmp = ardp_retrieve(dqs->preq,ardptime);
if((dqs->flags & GVD_ASYNC) && (tmp == ARDP_PENDING)) RETURN(DQ_ACTIVE);
/* If we don't get a response, then if the requested */
/* directory, return error, if a ulink, mark it unexpanded */
if(tmp != PSUCCESS) {
if (pfs_debug)
fprintf(stderr,"ardp_send failed: %d\n",tmp);
if(dqs->cexp) dqs->cexp->expanded = FAILED;
else {
ardp_rqfree(dir->dqs->preq);
/* change 1 done*/
if (dir->dqs->stfree_comp) stfree(dir->dqs->comp);
stfree(dir->dqs); dir->dqs = NULL;
RETURN(perrno = dir->status = tmp);
}
}
/* Claim that we don't have any more unresolved components to process. If
we get an UNRESOLVED response, we'll set this back on. */
dqs->unresp = 0;
if (tmp == PSUCCESS) {
/* Here we must parse reponse and put in directory */
/* While looking at each packet */
switch (tmp = retrieve_and_parse(dir)) {
case PSUCCESS: break;
case DSRFINFO_FORWARDED: goto startover;
default:
if (dqs->cexp) dqs->cexp->expanded = FAILED;
else {
ardp_rqfree(dqs->preq);
if (dqs->stfree_comp) stfree(dqs->comp);
stfree(dqs); dqs = NULL;
RETURN(perrno = dir->status = tmp);
}
} /*switch*/
}
/* We sent multiple components and weren't told any */
/* were unresolved */
if(dqs->mcomp && !dqs->unresp) {
TOKEN acp;
for (acp = *dqs->acomp; acp->next; acp = acp->next)
;
/* acp now points to the last additional component */
dqs->comp = acp->token;
acp->token = NULL;
/* Free the entries. */
tklfree(*dqs->acomp);
/* Let rd_vdir know what remains */
*(dqs->acomp) = NULL;
/* If we have union links to resolve, only one component remains */
dqs->mcomp = 0;
}
/* If only verifying, we already know it is a directory */
if(dqs->flags & GVD_VERIFY) {
ardp_rqfree(dqs->preq);
if (dir->dqs->stfree_comp) stfree(dir->dqs->comp);
stfree(dir->dqs); dir->dqs = NULL;
dir->status = DQ_COMPLETE;
RETURN(PSUCCESS);
}
/* Don't return if matching was delayed by the need to filter */
/* if FIND specified, and dir->links is non null, then we have */
/* found a match, and should return. */
if((dqs->flags & GVD_FIND) && dir->links && (!filters)) {
ardp_rqfree(dqs->preq);
if (dir->dqs->stfree_comp) stfree(dir->dqs->comp);
stfree(dir->dqs); dir->dqs = NULL;
dir->status = DQ_COMPLETE;
RETURN(PSUCCESS);
}
/* If expand specified, and ulinks must be expanded, making sure */
/* that the order of the links is maintained properly */
expand_ulinks:
if ((dqs->flags & GVD_FIND) ||
(((dqs->flags & GVD_EXPMASK) != GVD_UNION) &&
!(dqs->flags & GVD_VERIFY))) {
l = dir->ulinks;
/* Find first unexpanded ulink */
while(l && l->expanded && (l->linktype == 'U')) l = l->next;
/* Only expand if a FILE or DIRECTORY - Mark as */
/* failed otherwise */
/* We must still add support for symbolic ulinks */
if(l) {
if ((strcmp(l->target,"DIRECTORY") == 0) ||
(strcmp(l->target,"FILE") == 0)) {
l->expanded = TRUE;
dqs->cexp = l;
dqs->pulnk = l;
dqs->dl->host = stcopyr(l->host, dqs->dl->host);
dqs->dl->hsoname = stcopyr(l->hsoname, dqs->dl->hsoname);
/* When we're expanding union links, we need to turn off
support for multiple components. Otherwise, p_get_dir() is
confused by a NONE-FOUND response during the expansion
process and zeroes out the dqs->acomp. */
dqs->mcomp = 0;
goto get_contents;
}
else l->expanded = FAILED;
}
}
/* Right now, give off no error messages if inappropriate filters are
encountered (e.g., a SERVER filter following a CLIENT filter).
We just don't worry about it right now. Maybe we should do error
reporting. Presumably, only client filters are left right now. XXX */
if(filters && filters->execution_location == FIL_CLIENT &&
(filters->type == FIL_DIRECTORY || filters->type == FIL_HIERARCHY)) {
apply_filters(dir,filters,tl,0); /* Apply a single filter */
filters = filters->next;
goto expand_ulinks;
}
/* Double check to make sure we don't get */
/* back unwanted components */
/* OK to keep if special (URP) links */
if(dqs->comp && *(dqs->comp)) {
l = dir->links;
while(l) {
VLINK ol;
if((l->linktype == 'L' || l->linktype == 'I')
&& (!wcmatch(l->name,dqs->comp))) {
if(l == dir->links)
dir->links = l->next;
else l->previous->next = l->next;
if(l->next) l->next->previous = l->previous;
ol = l;
l = l->next;
vlfree(ol);
}
else l = l->next;
}
}
ardp_rqfree(dqs->preq);
if (dir->dqs->stfree_comp) stfree(dir->dqs->comp);
stfree(dir->dqs); dir->dqs = NULL;
dir->status = DQ_COMPLETE;
RETURN(PSUCCESS);
cleanup:
if (tl) vlfree(tl);
return(retval);
}
int
p_get_dir(VLINK dlink, const char *components, VDIR dir,
long flags, TOKEN *acomp)
{
VLINK vl;
int retval;
/* the distributed p_get_dir hacks dlink if the resulting directory contains
any union links, or is forwarded, fix this behaviour */
vl = vlcopy(dlink,FALSE);
retval = bad_p_get_dir(vl, components, dir, flags, acomp);
vlfree(vl);
return retval;
}
/* Older interfaces (backwards compatability) */
int
p_get_vdir(VLINK dlink, /* Directory to examine */
const char *components,/* Component name (wildcards allowed). */
VDIR dir, /* Structure to be filled in */
long flags, /* Flags */
TOKEN *acomp) /* Components left to be resolved */
{
return p_get_dir(dlink, components, dir, flags, acomp);
}
int
get_vdir(VLINK dlink, /* Directory to examine */
const char *components,/* Component name (wildcards allowed). */
VDIR dir, /* Structure to be filled in */
long flags, /* Flags */
TOKEN *acomp) /* Components left to be resolved */
{
return p_get_dir(dlink, components, dir, flags, acomp);
}

View File

@@ -0,0 +1,69 @@
/*
* 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_threads.h>
#include <pfs.h>
#include <perrno.h>
#include <pfs_threads.h>
#include <pcompat.h> /* For PMAP_ATSIGN*/
static void
p_thread_initialize_master_and_daughters()
{
pfs_enable = PMAP_ATSIGN;
if (!p_err_string) p_err_string = stcopy("");
if (!p_warn_string) p_warn_string = stcopy("");
p_clear_errors();
}
void
p_thread_initialize()
{
#ifdef PFS_THREADS
#ifndef MASTER_IS_ONLY_SUBTHREAD
/* This should probably be a general purpose initialization fnctn*/
p_th_allocate_self_num();
#endif
#endif
p_thread_initialize_master_and_daughters();
}
/* p_initialize(), written by swa@isi.edu, 6 Nov 1993 */
void
p_initialize(char *software_id, int flags, struct p_initialize_st * arg_st)
{
if (pfs_debug == 0) { /* if specified in a command line flag or
otherwise by the program itself, this
overrides the environment variable. */
char *pfs_debug_string; /* temporary */
if(pfs_debug_string = getenv("PFS_DEBUG"))
sscanf(pfs_debug_string, "%d", &pfs_debug);
}
/* Carefull not to put anything in here specific to the server */
/* No flags currently defined. */
/* Currently no options to set in the p_initialize_st */
#ifdef PFS_THREADS
p__th_set_self_master(); /* must be called first. */
#endif
p__set_sw_id(software_id);
/* Initialize error messages to null string, if they're currently set to
NULL ptr. This means that it will never be wrong to dereference
p_err_string. */
p_thread_initialize_master_and_daughters();
ardp_init_mutexes(); /* need not be called if not running threaded.
Won't hurt though. */
p__init_mutexes(); /* ditto */
}
#ifndef NDEBUG
void
p_diagnose(void)
{
ardp_diagnose_mutexes();
p__diagnose_mutexes();
}
#endif /*NDEBUG*/

View File

@@ -0,0 +1,64 @@
/*
* 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>
char *
p_uln_rindex(const char *s, char c)
{
const char *lastmatch = NULL;
for (; *s; ++s) {
if (*s == '\\') {
if (*++s == '\0') /* special case this error condition */
return (char *) lastmatch; /* done. Flush the CONST.*/
else
continue; /* don't match a quoted symbol */
}
if (*s == c) lastmatch = s;
}
return (char *) lastmatch; /* done. flush the CONST. */
}
char *
p_uln_index(const char *s, char c)
{
for (; *s; ++s) {
if (*s == '\\') {
if (*++s == '\0') /* special case this error condition */
return NULL; /* done */
else
continue; /* don't match a quoted symbol */
}
if (*s == c) return (char *) s; /* done. flush the CONST. */
}
return NULL;
}
/* Get a linkname from the last component of a user level name.
Returns memory that will be freed on the next call. */
char *
p_uln_lastcomp_to_linkname(const char *s)
{
static char *buf = NULL;
char *outp;
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
if (p__bstsize(buf) < strlen(s) + 1) {
stfree(buf);
buf = stalloc(strlen(s) + 1);
}
outp = buf;
while (*s) {
if (*s == '\\')
++s;
*outp++ = *s++;
}
*outp = '\0';
return buf;
}

120
prospero/lib/pfs/paalloc.c Normal file
View File

@@ -0,0 +1,120 @@
/*
* 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>.
*/
/* Munged by swa to handle multiple principals. */
#include <uw-copyright.h>
#include <stdio.h>
#include <stdlib.h> /* For malloc and free */
#include <pfs.h>
static PAUTH pauthflist = NULL;
int pauth_count = 0;
int pauth_max = 0;
/*
* paalloc - allocate and initialize pacess control list structure
*
* PAALLOC returns a pointer to an initialized structure of type
* PAUTH. If it is unable to allocate such a structure, it
* signals out_of_memory();
*/
/* We dynamically allocate these because the server end may have several of
them hanging out. */
PAUTH
paalloc()
{
PAUTH pauth_ent;
p_th_mutex_lock(p_th_mutexPAALLOC);
if(pauthflist) {
pauth_ent = pauthflist;
pauthflist = pauthflist->next;
}
else {
pauth_ent = (PAUTH) malloc(sizeof(PAUTH_ST));
if (!pauth_ent) out_of_memory();
pauth_max++;
}
pauth_count++;
p_th_mutex_unlock(p_th_mutexPAALLOC);
/* Initialize and fill in default values */
#ifdef ALLOCATOR_CONSISTENCY_CHECK
pauth_ent->consistency = INUSE_PATTERN;
#endif
pauth_ent->ainfo_type = 0;
pauth_ent->authenticator = NULL;
pauth_ent->principals = NULL;
pauth_ent->app.ptr = NULL; /* On every architecture I ever heard
of, pauth_ent->app.flg is now 0 too
*/
pauth_ent->next = NULL;
return(pauth_ent);
}
static void (*paappfreefunc)(PAUTH) = NULL;
/*
* Specify which special freeing function (if any) to be used to free the
* app.ptr member of the PAUTH structure, if set.
*/
void
paappfree(void (* appfreefunc)(PAUTH))
{
paappfreefunc = appfreefunc;
}
/*
* pafree - free an PAUTH structure
*
* PAFREE takes a pointer to an PAUTH structure and adds it to
* the free list for later reuse.
*/
void
pafree(PAUTH pauth_ent)
{
#ifdef ALLOCATOR_CONSISTENCY_CHECK
assert(pauth_ent->consistency == INUSE_PATTERN);
pauth_ent->consistency = FREE_PATTERN;
#endif
pauth_ent->ainfo_type = 0;
if(pauth_ent->authenticator) stfree(pauth_ent->authenticator);
if(pauth_ent->principals) tklfree(pauth_ent->principals);
if(paappfreefunc && pauth_ent->app.ptr) {
(*paappfreefunc)(pauth_ent->app.ptr); pauth_ent->app.ptr = NULL;
}
p_th_mutex_lock(p_th_mutexPAALLOC);
pauth_ent->next = pauthflist;
pauthflist = pauth_ent;
pauth_count--;
p_th_mutex_unlock(p_th_mutexPAALLOC);
}
/*
* palfree - free a PAUTH structure
*
* PALFREE takes a pointer to an PAUTH structure frees it and any linked
* PAUTH structures. It is used to free an entrie list of PAUTH
* structures.
*/
void
palfree(PAUTH pauth_ent)
{
PAUTH nxt;
while(pauth_ent != NULL) {
nxt = pauth_ent->next;
pafree(pauth_ent);
pauth_ent = nxt;
}
}

486
prospero/lib/pfs/penviron.c Normal file
View File

@@ -0,0 +1,486 @@
/*
* Copyright (c) 1989, 1990, 1991 by the University of Washington
* Copyright (c) 1991, 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 <pcompat.h>
#include <pfs.h>
#include <psite.h>
#include <pmachine.h>
#include <perrno.h>
#ifdef SOLARIS
/* #include "p_solaris_stdlib.h" \* Special tricks to prototype setenv() */
#else
#include <stdlib.h> /* For malloc and free, getenv etc */
#endif
static char vsroot_host[MAX_VPATH] = "";
static char vsroot_file[MAX_VPATH] = "";
static char vswork_host[MAX_VPATH] = "";
static char vswork_file[MAX_VPATH] = "";
static char vswork[MAX_VPATH] = "";
static char vshome_host[MAX_VPATH] = "";
static char vshome_file[MAX_VPATH] = "";
static char vshome[MAX_VPATH] = "";
static char vsdesc_host[MAX_VPATH] = "";
static char vsdesc_file[MAX_VPATH] = "";
static char vsname[MAX_VPATH] = "";
/*
* Note that there is one more environment variable used, PFS_DEFAULT,
* but that environment variable is per process and is handled in the
* pcompat library.
*/
#ifdef PUTENV /* If we don't have the lib. function */
static setenv();
#endif
void
pset_wd(wdhost,wdfile,wdname)
char *wdhost;
char *wdfile;
char *wdname;
{
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
if(wdhost) {
strcpy(vswork_host,wdhost);
setenv("VSWORK_HOST",wdhost,1);
}
if(wdfile) {
strcpy(vswork_file,wdfile);
setenv("VSWORK_FILE",wdfile,1);
}
if(wdname) {
strcpy(vswork,wdname);
setenv("VSWORK",wdname,1);
}
}
char * pget_wdhost()
{
char *env_st;
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
if(!*vswork_host && (env_st = getenv("VSWORK_HOST")))
strcpy(vswork_host,env_st);
if(*vswork_host) return(vswork_host);
else return(NULL);
}
char * pget_wdfile()
{
char *env_st;
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
if(!*vswork_file && (env_st = getenv("VSWORK_FILE")))
strcpy(vswork_file,env_st);
if(*vswork_file) return(vswork_file);
else return(NULL);
}
char * pget_wd()
{
char *env_st;
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
if(!*vswork && (env_st = getenv("VSWORK")))
strcpy(vswork,env_st);
if(*vswork) return(vswork);
else return(NULL);
}
void
pset_hd(hdhost,hdfile,hdname)
char *hdhost;
char *hdfile;
char *hdname;
{
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
if(hdhost) {
strcpy(vshome_host,hdhost);
setenv("VSHOME_HOST",hdhost,1);
}
if(hdfile) {
strcpy(vshome_file,hdfile);
setenv("VSHOME_FILE",hdfile,1);
}
if(hdname) {
strcpy(vshome,hdname);
setenv("VSHOME",hdname,1);
}
}
char * pget_hdhost()
{
char *env_st;
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
if(!*vshome_host && (env_st = getenv("VSHOME_HOST")))
strcpy(vshome_host,env_st);
if(*vshome_host) return(vshome_host);
else return(NULL);
}
char * pget_hdfile()
{
char *env_st;
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
if(!*vshome_file && (env_st = getenv("VSHOME_FILE")))
strcpy(vshome_file,env_st);
if(*vshome_file) return(vshome_file);
else return(NULL);
}
char * pget_hd()
{
char *env_st;
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
if(!*vshome && (env_st = getenv("VSHOME")))
strcpy(vshome,env_st);
if(*vshome) return(vshome);
else return(NULL);
}
void
pset_rd(rdhost,rdfile)
char *rdhost;
char *rdfile;
{
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
if(rdhost) {
strcpy(vsroot_host,rdhost);
setenv("VSROOT_HOST",rdhost,1);
}
if(rdfile) {
strcpy(vsroot_file,rdfile);
setenv("VSROOT_FILE",rdfile,1);
}
}
char * pget_rdhost()
{
char *env_st;
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
if(!*vsroot_host && (env_st = getenv("VSROOT_HOST")))
strcpy(vsroot_host,env_st);
if(*vsroot_host) return(vsroot_host);
else return(NULL);
}
char * pget_rdfile()
{
char *env_st;
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
if(!*vsroot_file && (env_st = getenv("VSROOT_FILE")))
strcpy(vsroot_file,env_st);
if(*vsroot_file) return(vsroot_file);
else return(NULL);
}
void
pset_desc(dhost,dfile,vsnm)
char *dhost;
char *dfile;
char *vsnm;
{
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
if(dhost) {
strcpy(vsdesc_host,dhost);
setenv("VSDESC_HOST",dhost,1);
}
if(dfile) {
strcpy(vsdesc_file,dfile);
setenv("VSDESC_FILE",dfile,1);
}
if(vsnm) {
strcpy(vsname,vsnm);
setenv("VSNAME",vsnm,1);
}
}
char * pget_dhost()
{
char *env_st;
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
if(!*vsdesc_host && (env_st = getenv("VSDESC_HOST")))
strcpy(vsdesc_host,env_st);
if(*vsdesc_host) return(vsdesc_host);
else return(NULL);
}
char * pget_dfile()
{
char *env_st;
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
if(!*vsdesc_file && (env_st = getenv("VSDESC_FILE")))
strcpy(vsdesc_file,env_st);
if(*vsdesc_file) return(vsdesc_file);
else return(NULL);
}
char * pget_vsname()
{
char *env_st;
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
if(!*vsname && (env_st = getenv("VSNAME")))
strcpy(vsname,env_st);
if(*vsname) return(vsname);
else return(NULL);
}
/*
* Pprint shell string prints command on the standard output which when
* interpreted by the shell will set environment variable and define
* aliases needed to pass the prospero environment from program to
* program. This routine is called by vfsetup and vcd.
*
* The argument is a bit vector indicating which variable should be set.
* The low order bit is (0x0):
*
* 0x001 Print aliases
* 0x002 Print virtual system description
* 0x004 Print working directory
* 0x008 Print home directory
* 0x010 Print root directory
* 0x1e0 Mask indicating which shell to print strings for. We leave room
* for 16 possibilities for when more shells with their own weird
* syntaxes show up.
*/
#define SHELL_MASK 0x1e0
#define SHELL_ERROR 0x0 /* 0 is undefined */
#define SHELL_SH 0x020
#define SHELL_CSH 0x040
void
p__print_shellstring(int which)
{
int shell = which & SHELL_MASK;
if((which & 0x1)&&(shell == SHELL_CSH)) {
printf("alias vwd 'echo $VSWORK';\n");
printf("alias vwp 'echo $VSWORK_HOST $VSWORK_FILE';\n");
printf("alias vwho 'echo $VSNAME';\n");
printf("alias vcd 'p__vcd -s csh \\!* >! /tmp/vfs$$;source /tmp/vfs$$;\
/bin/rm /tmp/vfs$$'\n");
#ifndef P_NO_PCOMPAT
printf("alias venable 'setenv PFS_DEFAULT %d;if($?Poldcd == 0) set Poldcd = `alias cd`;alias pwd vwd;alias cd vcd';\n",PMAP_ATSIGN_NF);
printf("set Presetcd = 'unalias cd;alias cd $Poldcd;unset Poldcd';\n");
printf("alias vdisable 'unsetenv PFS_DEFAULT;unalias pwd;if($?Poldcd) eval $Presetcd';\n");
#endif P_NO_PCOMPAT
} else if((which & 0x1)&&(shell == SHELL_SH)) {
printf("vwd () { echo $VSWORK \n}\n");
printf("vwp () { echo $VSWORK_HOST $VSWORK_FILE \n}\n");
printf("vwho () { echo $VSNAME \n}\n");
printf("vcd () { p__vcd -s sh $* > /tmp/vfs$$ ;. /tmp/vfs$$; /bin/rm /tmp/vfs$$ \n}\n");
#ifndef P_NO_PCOMPAT
/* Note that this will bash any existing cd alias */
printf("venable () { PFS_DEFAULT=%d;export PFS_DEFAULT;alias cd=vcd;alias pwd=vwd \n}\n",PMAP_ATSIGN_NF);
printf("vdisable () { unset PFS_DEFAULT;unalias cd; unalias pwd\n}\n");
#endif P_NO_PCOMPAT
}
if((which & 0x2)&&(shell == SHELL_CSH)) {
printf("setenv VSDESC_HOST \"%s\";\n",pget_dhost());
printf("setenv VSDESC_FILE \"%s\";\n",pget_dfile());
printf("setenv VSNAME \"%s\";\n",pget_vsname());
}
else if((which & 0x2)&&(shell == SHELL_SH)) {
printf("VSDESC_HOST=\"%s\";export VSDESC_HOST\n",pget_dhost());
printf("VSDESC_FILE=\"%s\";export VSDESC_FILE\n",pget_dfile());
printf("VSNAME=\"%s\";export VSNAME\n",pget_vsname());
}
if((which & 0x4)&&(shell == SHELL_CSH)) {
printf("setenv VSWORK_HOST \"%s\";\n",pget_wdhost());
printf("setenv VSWORK_FILE \"%s\";\n",pget_wdfile());
printf("setenv VSWORK \"%s\";\n",pget_wd());
}
else if((which & 0x4)&&(shell == SHELL_SH)) {
printf("VSWORK_HOST=\"%s\";export VSWORK_HOST\n",pget_wdhost());
printf("VSWORK_FILE=\"%s\";export VSWORK_FILE\n",pget_wdfile());
printf("VSWORK=\"%s\";export VSWORK\n",pget_wd());
}
if((which & 0x8)&&(shell == SHELL_CSH)) {
printf("setenv VSHOME_HOST \"%s\";\n",pget_hdhost());
printf("setenv VSHOME_FILE \"%s\";\n",pget_hdfile());
printf("setenv VSHOME \"%s\";\n",pget_hd());
}
else if((which & 0x8)&&(shell == SHELL_SH)) {
printf("VSHOME_HOST=\"%s\";export VSHOME_HOST\n",pget_hdhost());
printf("VSHOME_FILE=\"%s\";export VSHOME_FILE\n",pget_hdfile());
printf("VSHOME=\"%s\";export VSHOME\n",pget_hd());
}
if((which & 0x10)&&(shell == SHELL_CSH)) {
printf("setenv VSROOT_HOST \"%s\";\n",pget_rdhost());
printf("setenv VSROOT_FILE \"%s\";\n",pget_rdfile());
}
else if((which & 0x10)&&(shell == SHELL_SH)) {
printf("VSROOT_HOST=\"%s\";export VSROOT_HOST\n",pget_rdhost());
printf("VSROOT_FILE=\"%s\";export VSROOT_FILE\n",pget_rdfile());
}
}
/* return a flag value for the shell that can be given to
p__print_shellstring(). If no shell defined, return 0 and set
p_err_string. This functions is only called by the VCD and VFSETUP
commands at this time. */
int
p__get_shellflag(const char *shellname)
{
char *shellenvar;
int shellenvarlen;
if (shellname) {
if (strequal(shellname, "sh")) return SHELL_SH;
if (strequal(shellname, "csh")) return SHELL_CSH;
p_err_string = qsprintf_stcopyr(p_err_string,
"The system doesn't know about shells of type \"%s\". \
Please see the person who maintains Prospero at your site.", shellname);
perrno = PFAILURE;
return SHELL_ERROR;
}
/* this part is going to go away eventually. The -s flag to p__vfsetup and
p__vcd has effectively obsoleted it. It's still around for a while, (a)
in case people are using old versions of vfsetup.source or
vfsetup.profil. and (b) because I'm too sentimental to flush it yet :).
*/
shellenvar = getenv("SHELL");
if (!shellenvar) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Couldn't find SHELL environment variable; \
I don't know what kind of SHELL you're using. Please see your maintainer.");
perrno = PFAILURE;
return SHELL_ERROR; /* undefined */
}
shellenvarlen = strlen(shellenvar);
if (shellenvarlen >= 3 && strequal(shellenvar + shellenvarlen - 3, "csh"))
return SHELL_CSH;
else
return SHELL_SH;
}
#ifdef PUTENV
static int
setenv(char *n,char *v, int o)
{
int tmp;
/* Allocate space for environment variable */
char *template = (char *) stalloc(strlen(n)+strlen(v)+2);
sprintf(template,"%s=%s",n,v);
tmp = putenv(template);
return(tmp);
/* Potential memory leak - it is not clear whether putenv */
/* deallocates the string with the old value of the */
/* envorinment variable. If not, then we should do so here. */
/* This concern is not valid (swa, 5/27/93):
From the SUN OS 4.1.3 manual page for 'putenv()':
int putenv(string)
char *string;
"the string pointed to by string becomes part of the environment, so
altering the string will change the environment. "
The HP-UX 8.05 manual page is similarly worded.
*/
}
#endif PUTENV
#ifdef BADSETENV
/*
* Copyright (c) 1987 Regents of the University of California.
* This file may be freely redistributed provided that this
* notice remains attached.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)setenv.c 1.2 (Berkeley) 3/13/87";
#endif LIBC_SCCS and not lint
#include <sys/types.h>
#include <stdio.h>
/*
* setenv(name,value,rewrite)
* Set the value of the environmental variable "name" to be
* "value". If rewrite is set, replace any current value.
*/
setenv(name,value,rewrite)
register char *name,
*value;
int rewrite;
{
extern char **environ;
static int alloced; /* if allocated space before */
register char *C;
int l_value,
offset;
char *_findenv();
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
if (*value == '=') /* no `=' in value */
++value;
l_value = strlen(value);
if ((C = _findenv(name,&offset))) { /* find if already exists */
if (!rewrite)
return(0);
#if BUG
if (strlen(C) <= l_value) { /* smaller; copy over */
while (*C++ = *value++);
return(0);
}
#else
if (l_value <= strlen(C)) { /* smaller; copy over */
while (*C++ = *value++);
return(0);
}
#endif BUG
}
else { /* create new slot */
register int cnt;
register char **P;
for (P = environ,cnt = 0;*P;++P,++cnt);
if (alloced) { /* just increase size */
environ = (char **)realloc((char *)environ,
(u_int)(sizeof(char *) * (cnt + 2)));
if (!environ)
return(-1);
}
else { /* get new space */
alloced = 1; /* copy old entries into it */
P = (char **)malloc((u_int)(sizeof(char *) *
(cnt + 2)));
if (!P)
return(-1);
bcopy(environ,P,cnt * sizeof(char *));
environ = P;
}
environ[cnt + 1] = NULL;
offset = cnt;
}
for (C = name;*C && *C != '=';++C); /* no `=' in name */
if (!(environ[offset] = /* name + `=' + value */
malloc((u_int)((int)(C - name) + l_value + 2))))
return(-1);
for (C = environ[offset];(*C = *name++) && *C != '=';++C);
for (*C++ = '=';*C++ = *value++;);
return(0);
}
#endif BADSETENV

383
prospero/lib/pfs/perrmesg.c Normal file
View File

@@ -0,0 +1,383 @@
/*
* 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 <perrno.h>
#include <stdio.h>
#include <pfs_threads.h>
/* This file and perrno.h should always be updated simultaneously */
/* Don't declare perrno here
because some Prospero applications declare it themselves, internally,
and the two can conflict.
There is a version of perrno provided in lib/ardp/ardp_perrno.c
which will be linked in in case of a problem.
int perrno = 0;
*/
/* These need to be per-thread in case of two simultaneous errors*/
#ifdef NEVERDEFINED
int pwarn = 0;
char *p_err_string = NULL;
char *p_warn_string = NULL;
#endif
EXTERN_INT_DEF(pwarn);
EXTERN_CHARP_DEF(p_err_string);
EXTERN_CHARP_DEF(p_warn_string);
/* These are initialized in p_initialize(). */
/* This depends upon the internals of lib/ardp/ardp_error.c */
char *ardp___please_do_not_optimize_me_out_of_existence;
/* See lib/ardp/usc_lic_str.c */
extern char *usc_license_string;
/* This function definition is shadowed in lib/ardp/ardp_error.c. Change it
there too if you change it here. */
void
p_clear_errors(void)
{
ardp___please_do_not_optimize_me_out_of_existence = usc_license_string;
perrno = PSUCCESS; if (p_err_string) p_err_string[0] = '\0';
pwarn = PNOWARN; if (p_warn_string) p_warn_string[0] = '\0';
}
char *p_err_text[256] = {
/* 0 */ "Success (prospero)",
/* 1 */ "Port unknown (ardp)",
/* 2 */ "Can't open local UDP port (ardp)",
/* 3 */ "Can't resolve hostname (ardp)",
/* 4 */ "Attempt to send message failed (ardp)",
/* 5 */ "Select failed (ardp)",
/* 6 */ "Recvfrom failed (ardp)",
/* 7 */ "Unknown protocol version number (ardp)",
/* 8 */ "Inconsistent or unexpected form for request structure (ardp)",
/* 9 */ "Timed out (ardp)",
/* 10 */ "Connection refused by server (ardp)",
/* 11 */ "Generic failure sending or receiving message (ardp)",
/* 12 */ "Undefined error 12 (prospero)",
/* 13 */ "Undefined error 13 (prospero)",
/* 14 */ "Undefined error 14 (prospero)",
/* 15 */ "Undefined error 15 (prospero)",
/* 16 */ "Undefined error 16 (prospero)",
/* 17 */ "Undefined error 17 (prospero)",
/* 18 */ "Undefined error 18 (prospero)",
/* 19 */ "Undefined error 19 (prospero)",
/* 20 */ "Undefined error 20 (prospero)",
/* 21 */ "Link already exists (vl_insert)",
/* 22 */ "Link with same name already exists (vl_insert)",
/* 23 */ "Undefined error 23 (prospero)",
/* 24 */ "Undefined error 24 (prospero)",
/* 25 */ "Link already exists (ul_insert)",
/* 26 */ "Replacing existing link (ul_insert)",
/* 27 */ "Previous entry not found in dir->ulinks (ul_insert)",
/* 28 */ "Undefined error 28 (prospero)",
/* 29 */ "Undefined error 29 (prospero)",
/* 30 */ "Undefined error 30 (prospero)",
/* 31 */ "Undefined error 31 (prospero)",
/* 32 */ "Undefined error 32 (prospero)",
/* 33 */ "Undefined error 33 (prospero)",
/* 34 */ "Undefined error 34 (prospero)",
/* 35 */ "Undefined error 35 (prospero)",
/* 36 */ "Undefined error 36 (prospero)",
/* 37 */ "Undefined error 37 (prospero)",
/* 38 */ "Undefined error 38 (prospero)",
/* 39 */ "Undefined error 39 (prospero)",
/* 40 */ "Undefined error 40 (prospero)",
/* 41 */ "Temporary not found (rd_vdir)",
/* 42 */ "Namespace not closed with object (rd_vdir)",
/* 43 */ "Alias for namespace not defined (rd_vdir)",
/* 44 */ "Specified namespace not found (rd_vdir)",
/* 45 */ "Undefined error 45 (prospero)",
/* 46 */ "Undefined error 46 (prospero)",
/* 47 */ "Undefined error 47 (prospero)",
/* 48 */ "Undefined error 48 (prospero)",
/* 49 */ "Undefined error 49 (prospero)",
/* 50 */ "Undefined error 50 (prospero)",
/* 51 */ "File access method not supported (pfs_access)",
/* 52 */ "Undefined error 52 (prospero)",
/* 53 */ "Undefined error 53 (prospero)",
/* 54 */ "Undefined error 54 (prospero)",
/* 55 */ "Pointer to cached copy - delete on close (p__map_cache)",
/* 56 */ "Unable to retrieve file (p__map_cache)",
/* 57 */ "Undefined error 57 (prospero)",
/* 58 */ "Undefined error 58 (prospero)",
/* 59 */ "Undefined error 59 (prospero)",
/* 60 */ "Undefined error 60 (prospero)",
/* 61 */ "Directory already exists (mk_vdir)",
/* 62 */ "Link with same name already exists (mk_vdir)",
/* 63 */ "Undefined error 63 (prospero)",
/* 64 */ "Undefined error 64 (prospero)",
/* 65 */ "Not a virtual system (vfsetenv)",
/* 66 */ "Can't find directory (vfsetenv)",
/* 67 */ "Undefined error 67 (prospero)",
/* 68 */ "Undefined error 68 (prospero)",
/* 69 */ "Undefined error 69 (prospero)",
/* 70 */ "Undefined error 70 (prospero)",
/* 71 */ "Link already exists (add_vlink)",
/* 72 */ "Link with same name already exists (add_vlink)",
/* 73 */ "Undefined error 73 (prospero)",
/* 74 */ "Undefined error 74 (prospero)",
/* 75 */ "Undefined error 75 (prospero)",
/* 76 */ "Undefined error 76 (prospero)",
/* 77 */ "Undefined error 77 (prospero)",
/* 78 */ "Undefined error 78 (prospero)",
/* 79 */ "Undefined error 79 (prospero)",
/* 80 */ "Undefined error 80 (prospero)",
/* 81 */ "This link does not refer to an object; can't set an OBJECT \
attribute on it (pset_at)",
/* 82 */ "Undefined error 82 (prospero)",
/* 83 */ "Undefined error 83 (prospero)",
/* 84 */ "Undefined error 84 (prospero)",
/* 85 */ "Undefined error 85 (prospero)",
/* 86 */ "Undefined error 86 (prospero)",
/* 87 */ "Undefined error 87 (prospero)",
/* 88 */ "Undefined error 88 (prospero)",
/* 89 */ "Undefined error 89 (prospero)",
/* 90 */ "Undefined error 90 (prospero)",
/* 91 */ "Undefined error 91 (prospero)",
/* 92 */ "Undefined error 92 (prospero)",
/* 93 */ "Undefined error 93 (prospero)",
/* 94 */ "Undefined error 94 (prospero)",
/* 95 */ "Undefined error 95 (prospero)",
/* 96 */ "Undefined error 96 (prospero)",
/* 97 */ "Undefined error 97 (prospero)",
/* 98 */ "Undefined error 98 (prospero)",
/* 99 */ "Undefined error 99 (prospero)",
/* 100 */ "Undefined error 100 (prospero)",
/* 101 */ "Error parsing Prospero Protocol Input",
/* 102 */ "Undefined error 102 (prospero)",
/* 103 */ "Undefined error 103 (prospero)",
/* 104 */ "Undefined error 104 (prospero)",
/* 105 */ "Undefined error 105 (prospero)",
/* 106 */ "Undefined error 106 (prospero)",
/* 107 */ "Undefined error 107 (prospero)",
/* 108 */ "Undefined error 108 (prospero)",
/* 109 */ "Undefined error 109 (prospero)",
/* 110 */ "Undefined error 110 (prospero)",
/* 111 */ "Undefined error 111 (prospero)",
/* 112 */ "Undefined error 112 (prospero)",
/* 113 */ "Undefined error 113 (prospero)",
/* 114 */ "Undefined error 114 (prospero)",
/* 115 */ "Undefined error 115 (prospero)",
/* 116 */ "Undefined error 116 (prospero)",
/* 117 */ "Undefined error 117 (prospero)",
/* 118 */ "Undefined error 118 (prospero)",
/* 119 */ "Undefined error 119 (prospero)",
/* 120 */ "Undefined error 120 (prospero)",
/* 121 */ "Undefined error 121 (prospero)",
/* 122 */ "Undefined error 122 (prospero)",
/* 123 */ "Undefined error 123 (prospero)",
/* 124 */ "Undefined error 124 (prospero)",
/* 125 */ "Undefined error 125 (prospero)",
/* 126 */ "Undefined error 126 (prospero)",
/* 127 */ "Undefined error 127 (prospero)",
/* 128 */ "Undefined error 128 (prospero)",
/* 129 */ "Undefined error 129 (prospero)",
/* 130 */ "Undefined error 130 (prospero)",
/* 131 */ "Undefined error 131 (prospero)",
/* 132 */ "Undefined error 132 (prospero)",
/* 133 */ "Undefined error 133 (prospero)",
/* 134 */ "Undefined error 134 (prospero)",
/* 135 */ "Undefined error 135 (prospero)",
/* 136 */ "Undefined error 136 (prospero)",
/* 137 */ "Undefined error 137 (prospero)",
/* 138 */ "Undefined error 138 (prospero)",
/* 139 */ "Undefined error 139 (prospero)",
/* 140 */ "Undefined error 140 (prospero)",
/* 141 */ "Undefined error 141 (prospero)",
/* 142 */ "Undefined error 142 (prospero)",
/* 143 */ "Undefined error 143 (prospero)",
/* 144 */ "Undefined error 144 (prospero)",
/* 145 */ "Undefined error 145 (prospero)",
/* 146 */ "Undefined error 146 (prospero)",
/* 147 */ "Undefined error 147 (prospero)",
/* 148 */ "Undefined error 148 (prospero)",
/* 149 */ "Undefined error 149 (prospero)",
/* 150 */ "Undefined error 150 (prospero)",
/* 151 */ "Undefined error 151 (prospero)",
/* 152 */ "Undefined error 152 (prospero)",
/* 153 */ "Undefined error 153 (prospero)",
/* 154 */ "Undefined error 154 (prospero)",
/* 155 */ "Undefined error 155 (prospero)",
/* 156 */ "Undefined error 156 (prospero)",
/* 157 */ "Undefined error 157 (prospero)",
/* 158 */ "Undefined error 158 (prospero)",
/* 159 */ "Undefined error 159 (prospero)",
/* 160 */ "Undefined error 160 (prospero)",
/* 161 */ "Undefined error 161 (prospero)",
/* 162 */ "Undefined error 162 (prospero)",
/* 163 */ "Undefined error 163 (prospero)",
/* 164 */ "Undefined error 164 (prospero)",
/* 165 */ "Undefined error 165 (prospero)",
/* 166 */ "Undefined error 166 (prospero)",
/* 167 */ "Undefined error 167 (prospero)",
/* 168 */ "Undefined error 168 (prospero)",
/* 169 */ "Undefined error 169 (prospero)",
/* 170 */ "Undefined error 170 (prospero)",
/* 171 */ "Undefined error 171 (prospero)",
/* 172 */ "Undefined error 172 (prospero)",
/* 173 */ "Undefined error 173 (prospero)",
/* 174 */ "Undefined error 174 (prospero)",
/* 175 */ "Undefined error 175 (prospero)",
/* 176 */ "Undefined error 176 (prospero)",
/* 177 */ "Undefined error 177 (prospero)",
/* 178 */ "Undefined error 178 (prospero)",
/* 179 */ "Undefined error 179 (prospero)",
/* 180 */ "Undefined error 180 (prospero)",
/* 181 */ "Undefined error 181 (prospero)",
/* 182 */ "Undefined error 182 (prospero)",
/* 183 */ "Undefined error 183 (prospero)",
/* 184 */ "Undefined error 184 (prospero)",
/* 185 */ "Undefined error 185 (prospero)",
/* 186 */ "Undefined error 186 (prospero)",
/* 187 */ "Undefined error 187 (prospero)",
/* 188 */ "Undefined error 188 (prospero)",
/* 189 */ "Undefined error 189 (prospero)",
/* 190 */ "Undefined error 190 (prospero)",
/* 191 */ "Undefined error 191 (prospero)",
/* 192 */ "Undefined error 192 (prospero)",
/* 193 */ "Undefined error 193 (prospero)",
/* 194 */ "Undefined error 194 (prospero)",
/* 195 */ "Undefined error 195 (prospero)",
/* 196 */ "Undefined error 196 (prospero)",
/* 197 */ "Undefined error 197 (prospero)",
/* 198 */ "Undefined error 198 (prospero)",
/* 199 */ "Undefined error 199 (prospero)",
/* 200 */ "Undefined error 200 (prospero)",
/* 201 */ "Undefined error 201 (prospero)",
/* 202 */ "Undefined error 202 (prospero)",
/* 203 */ "Undefined error 203 (prospero)",
/* 204 */ "Undefined error 204 (prospero)",
/* 205 */ "Undefined error 205 (prospero)",
/* 206 */ "Undefined error 206 (prospero)",
/* 207 */ "Undefined error 207 (prospero)",
/* 208 */ "Undefined error 208 (prospero)",
/* 209 */ "Undefined error 209 (prospero)",
/* 210 */ "Undefined error 210 (prospero)",
/* 211 */ "Undefined error 211 (prospero)",
/* 212 */ "Undefined error 212 (prospero)",
/* 213 */ "Undefined error 213 (prospero)",
/* 214 */ "Undefined error 214 (prospero)",
/* 215 */ "Undefined error 215 (prospero)",
/* 216 */ "Undefined error 216 (prospero)",
/* 217 */ "Undefined error 217 (prospero)",
/* 218 */ "Undefined error 218 (prospero)",
/* 219 */ "Undefined error 219 (prospero)",
/* 220 */ "Undefined error 220 (prospero)",
/* 221 */ "Undefined error 221 (prospero)",
/* 222 */ "Undefined error 222 (prospero)",
/* 223 */ "Undefined error 223 (prospero)",
/* 224 */ "Undefined error 224 (prospero)",
/* 225 */ "Undefined error 225 (prospero)",
/* 226 */ "Undefined error 226 (prospero)",
/* 227 */ "Undefined error 227 (prospero)",
/* 228 */ "Undefined error 228 (prospero)",
/* 229 */ "Undefined error 229 (prospero)",
/* 230 */ "File not found (prospero)",
/* 231 */ "Directory not found (prospero)",
/* 232 */ "Symbolic links nested too deep (prospero)",
/* 233 */ "Environment not initialized - source vfsetup.source then run vfsetup",
/* 234 */ "Can't traverse an external file (prospero)",
/* 235 */ "Forwarding chain is too long (prospero)",
/* 236 */ "Undefined error 236 (prospero)",
/* 237 */ "Undefined error 237 (prospero)",
/* 238 */ "Undefined error 238 (prospero)",
/* 239 */ "Undefined error 239 (prospero)",
/* 240 */ "WAIS gateway",
/* 241 */ "Gopher gateway",
/* 242 */ "Authentication required (prospero server)",
/* 243 */ "Not authorized (prospero server)",
/* 244 */ "Not found (prospero server)",
/* 245 */ "Bad version number (prospero server)",
/* 246 */ "Not a directory (prospero server)",
/* 247 */ "Already exists (prospero server)",
/* 248 */ "Link with same name already exists (prospero server)",
/* 249 */ "Too many items to return (prospero server)",
/* 250 */ "Undefined error 250 (prospero)",
/* 251 */ "Command not implemented on server (dirsrv)",
/* 252 */ "Bad format for response (dirsrv)",
/* 253 */ "Protocol error (prospero server)",
/* 254 */ "Unspecified server failure (prospero server)",
/* 255 */ "Generic Failure (prospero)"};
char *p_warn_text[256] = {
/* 0 */ "No warning",
/* 1 */ "You are using an old version of this program",
/* 2 */ "From server",
/* 3 */ "Unrecognized line in response from server",
/* 4-254 */ "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
/* 255 */ ""};
void
perrmesg(char *prefix, int no, char *text)
{
fprintf(stderr,"%s%s%s%s\n", (prefix ? prefix : ""),
(no ? p_err_text[no] : p_err_text[perrno]),
((text ? (*text ? " - " : "") :
(!no && *p_err_string ? " - " : ""))),
(text ? text : (no ? "" : p_err_string)));
}
void
sperrmesg(char *buf, const char *prefix, int no, const char *text)
{
sprintf(buf,"%s%s%s%s\n", (prefix ? prefix : ""),
(no ? p_err_text[no] : p_err_text[perrno]),
((text ? (*text ? " - " : "") :
(!no && *p_err_string ? " - " : ""))),
(text ? text : (no ? "" : p_err_string)));
}
void
pwarnmesg(char *prefix, int no, char *text)
{
fprintf(stderr,"%s%s%s%s\n", (prefix ? prefix : ""),
(no ? p_warn_text[no] : p_warn_text[pwarn]),
((text ? (*text ? " - " : "") :
(!no && *p_warn_string ? " - " : ""))),
(text ? text : (no ? "" : p_warn_string)));
}
void
spwarnmesg(char *buf, char *prefix, int no, char *text)
{
sprintf(buf,"%s%s%s%s\n", (prefix ? prefix : ""),
(no ? p_warn_text[no] : p_warn_text[pwarn]),
((text ? (*text ? " - " : "") :
(!no && *p_warn_string ? " - " : ""))),
(text ? text : (no ? "" : p_warn_string)));
}
#ifdef DEBUG_PFAILURE
void
it_failed()
{
static int itfailed = 0;
itfailed++; /* So not optimized out of existence */
}
#endif

108
prospero/lib/pfs/pfalloc.c Normal file
View File

@@ -0,0 +1,108 @@
/*
* 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 <stdio.h>
#include <stdlib.h> /* For malloc and free */
#include <pfs.h>
static PFILE lfree = NULL;
int pfile_count = 0;
int pfile_max = 0;
/*
* fialloc - allocate and initialize pfile structure
*
* PFALLOC returns a pointer to an initialized structure of type
* PFILE. If it is unable to allocate such a structure, it
* signals out_of_memory();
*/
PFILE
pfalloc(void)
{
PFILE pf;
p_th_mutex_lock(p_th_mutexPFALLOC);
if(lfree) {
pf = lfree;
lfree = lfree->next;
}
else {
pf = (PFILE) malloc(sizeof(PFILE_ST));
if (!pf) out_of_memory();
pfile_max++;
}
pfile_count++;
p_th_mutex_unlock(p_th_mutexPFALLOC);
/* Initialize and fill in default values */
#ifdef ALLOCATOR_CONSISTENCY_CHECK
pf->consistency = INUSE_PATTERN;
#endif
pf->version = 0;
pf->f_magic_no = 0;
pf->oacl = NULL;
pf->exp = 0;
pf->ttl = 0;
pf->last_ref = 0;
pf->forward = NULL;
pf->backlinks = NULL;
pf->attributes = NULL;
pf->previous = NULL;
pf->next = NULL;
return(pf);
}
/*
* pffree - free a PFILE structure
*
* PFFREE takes a pointer to a PFILE structure and adds it to
* the free list for later reuse.
*/
void
pffree(PFILE pf)
{
if (!pf) return;
#ifdef ALLOCATOR_CONSISTENCY_CHECK
assert(pf->consistency == INUSE_PATTERN);
pf->consistency = FREE_PATTERN;
#endif
if(pf->oacl) aclfree(pf->oacl); pf->oacl = NULL;
if(pf->forward) vllfree(pf->forward); pf->forward = NULL;
if(pf->backlinks) vllfree(pf->backlinks); pf->backlinks = NULL;
if(pf->attributes) atlfree(pf->attributes); pf->attributes = NULL;
p_th_mutex_lock(p_th_mutexPFALLOC);
pf->next = lfree;
pf->previous = NULL;
lfree = pf;
pfile_count--;
p_th_mutex_unlock(p_th_mutexPFALLOC);
}
/*
* pflfree - free a PFILE structure list
*
* PFLFREE takes a pointer to a PFILE structure frees it and any linked
* PFILE structures. It is used to free an entire list of PFILE
* structures.
*/
void
pflfree(PFILE pf)
{
PFILE nxt;
while(pf != NULL) {
nxt = pf->next;
pffree(pf);
pf = nxt;
}
}

View File

@@ -0,0 +1,16 @@
/*
* Copyright (c) 1989 by the University of Washington
*
* For copying and distribution information, please see the file
* <uw-copyright.h>.
*/
#include <uw-copyright.h>
/*
* pfs_debug - a global variable containing debugging flag
*
* Included in the library in case users forget to
* include it themselves.
*/
int pfs_debug = 0;

View File

@@ -0,0 +1,26 @@
/*
/*
* Copyright (c) 1993,1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
/*
* pfs_enable - Disable Virtual File System interpetation of filenames to
* syscalls
*
* Included in the library in case users forget to
* include it themselves and initialize.
*
* This is initialized in p_initialize() (in libpfs) to PMAP_DISABLE.
* By default,
* which means that file names will be
*/
#include <pcompat.h>
int pfs_enable;

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 1991-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 <string.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/param.h>
#include <errno.h>
#include <pfs.h>
#include <pcompat.h>
#include <perrno.h>
#include <pmachine.h>
/*SEE: pfs_open if you want a fd instead of a file returned */
FILE *pfs_fopen(VLINK vl, const char *type)
{
char npath[MAXPATHLEN];
int tmp;
int mapflags;
FILE *fopen_return;
if(strcmp(type,"r") == 0) mapflags = MAP_READONLY;
else mapflags = MAP_READWRITE;
tmp = mapname(vl, npath, sizeof npath, mapflags);
if(tmp && (tmp != PMC_DELETE_ON_CLOSE)) {
errno = ENOENT;
return(NULL);
}
DISABLE_PFS(fopen_return = fopen(npath,type));
if(tmp == PMC_DELETE_ON_CLOSE) unlink(npath);
return(fopen_return);
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) 1993-1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
#include <pfs_threads.h>
#include <pfs.h>
#ifdef PFS_THREADS
p_th_mutex p_th_mutexATALLOC;
p_th_mutex p_th_mutexACALLOC;
p_th_mutex p_th_mutexFLALLOC;
p_th_mutex p_th_mutexOBALLOC;
p_th_mutex p_th_mutexPAALLOC;
p_th_mutex p_th_mutexPFALLOC;
p_th_mutex p_th_mutexPFS_VQSCANF_NW_CS;
p_th_mutex p_th_mutexPFS_VQSPRINTF_NQ_CS;
p_th_mutex p_th_mutexPFS_TIMETOASN;
p_th_mutex p_th_mutexTOKEN;
p_th_mutex p_th_mutexVLINK;
p_th_mutex p_th_mutexREGEX;
#endif
void
p__init_mutexes(void)
{
#ifdef PFS_THREADS
myaddress(); /* Calling myaddress() will initialize this
function, which is good, since it's not
inherently multithreaded when called for the
1st time. */
p_th_mutex_init(p_th_mutexATALLOC);
p_th_mutex_init(p_th_mutexACALLOC);
p_th_mutex_init(p_th_mutexFLALLOC);
p_th_mutex_init(p_th_mutexOBALLOC);
p_th_mutex_init(p_th_mutexPAALLOC);
p_th_mutex_init(p_th_mutexPFALLOC);
p_th_mutex_init(p_th_mutexPFS_TIMETOASN); /* does calls to gmtimes */
p_th_mutex_init(p_th_mutexPFS_VQSCANF_NW_CS);
p_th_mutex_init(p_th_mutexPFS_VQSPRINTF_NQ_CS);
p_th_mutex_init(p_th_mutexTOKEN);
p_th_mutex_init(p_th_mutexVLINK);
p_th_mutex_init(p_th_mutexREGEX);
#endif
}
#ifndef NDEBUG
void
p__diagnose_mutexes(void)
{
#ifdef PFS_THREADS
DIAGMUTEX(ATALLOC,"ATALLOC");
DIAGMUTEX(ACALLOC,"ACALLOC");
DIAGMUTEX(FLALLOC,"FLALLOC");
DIAGMUTEX(OBALLOC,"OBALLOC");
DIAGMUTEX(PAALLOC,"PAALLOC");
DIAGMUTEX(PFALLOC,"PFALLOC");
DIAGMUTEX(PFS_TIMETOASN,"PFS_TIMETOASN"); /* does calls to gmtimes */
DIAGMUTEX(PFS_VQSCANF_NW_CS,"PFS_VQSCANF_NW_CS");
DIAGMUTEX(PFS_VQSPRINTF_NQ_CS,"PFS_VQSPRINTF_NQ_CS");
DIAGMUTEX(TOKEN,"TOKEN");
DIAGMUTEX(VLINK,"VLINK");
DIAGMUTEX(REGEX,"REGEX");
#endif
}
#endif /*NDEBUG*/

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 1989, 1990, 1991 by the University of Washington
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>.
*/
#include <uw-copyright.h>
#include <usc-copyr.h>
#include <stdio.h>
#include <string.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/file.h>
#include <errno.h>
/* needed for SCO Unix*/
#include <fcntl.h>
#include <pfs.h>
#include <pcompat.h>
#include <perrno.h>
#include <pmachine.h>
/*SEE: pfs_fopen if you want a FILE rather than fd returned */
int
pfs_open(VLINK vl,int flags)
{
char npath[MAXPATHLEN];
int tmp;
int mapflags;
int open_return;
/* Test flags for validity. */
if (flags & (O_EXCL | O_SYNC)) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Bad flags specified to pfs_open().");
return -1;
}
if((flags & (O_ACCMODE)) == O_RDONLY) mapflags = MAP_READONLY;
else mapflags = MAP_READWRITE;
tmp = mapname(vl, npath, sizeof npath, mapflags);
if(tmp && (tmp != PMC_DELETE_ON_CLOSE)) {
errno = ENOENT;
return(-1);
}
DISABLE_PFS(open_return = open(npath, flags));
if(tmp == PMC_DELETE_ON_CLOSE) unlink(npath);
return(open_return);
}

262
prospero/lib/pfs/pget_am.c Normal file
View File

@@ -0,0 +1,262 @@
/*
* Copyright (c) 1989, 1990, 1991 by the University of Washington
* Copyright (c) 1991, 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>.
*/
#include <uw-copyright.h>
#include <usc-copyr.h>
#include <stdio.h>
#include <string.h>
#include <pfs.h>
#include <perrno.h>
#include <pmachine.h>
extern int pfs_debug;
static PATTRIB expand_amat(PATTRIB ca, VLINK vl);
static int match_am(PATTRIB list, TOKEN *ainfop, int methods);
/* Returns the chosen access method, or zero if failure.
We do NOT modify link, unless the object that is the target oflink was
forwarded, in which case vl may be returned updated. */
/* This interface is suboptimal, since it doesn't allow for retries in case
one of the access methods fails. */
int
pget_am(vl,ainfop,methods)
VLINK vl;
TOKEN *ainfop; /* This will be filled in with access info
data. */
int methods; /* Methods this client supports */
{
PATTRIB hits = NULL; /* list of the hits. */
PATTRIB ats; /* attributes returned by pget_at() */
PATTRIB ca; /* index variable */
int retval;
perrno = PSUCCESS;
if(strcmp(vl->target,"NULL") == 0)
return(0);
*ainfop = (TOKEN) NULL;
/* For an EXTERNAL link, the access method should be somewhere on
the lattrib member. This is guaranteed in the protocol. Look on the
lattrib member in any case, so that we avoid going over the network for
the ACCESS-METHOD attribute if it was already cached or otherwise
available (perhaps it was returned as an OBJECT attribute). */
for (ca = vl->lattrib; ca; ca = ca->next) {
if (strequal(ca->aname, "ACCESS-METHOD")) {
PATTRIB amat = expand_amat(ca, vl);
if (amat) /* if the amat was correctly formed */
APPEND_ITEM(amat, hits);
}
}
retval = match_am(hits, ainfop, methods);
if (retval) return retval; /* found a match. */
/* If no match found on the link's attribute list try to retrieve the
ACCESS-METHOD attribute directly from the object.
pget_at() will always return NULL for EXTERNAL links; we take advantage
of this. */
hits = NULL; /* no hits for this try. */
ats = pget_at(vl, "ACCESS-METHOD");
for (ca = ats; ca; ca = ca->next)
if (strequal(ca->aname, "ACCESS-METHOD")) {
PATTRIB amat = expand_amat(ca, vl);
if (amat) /* if the amat was correctly formed */
APPEND_ITEM(amat, hits);
}
atlfree(ats);
if (!hits)
p_err_string = qsprintf_stcopyr(p_err_string, "No ACCESS-METHOD");
return match_am(hits, ainfop, methods);
}
static void wrong_length(PATTRIB ca);
/* Takes responsibility for freeing the list of attributes passed to it. */
/* Returns a matching access method found on the list, or zero if failure. */
static int
match_am(PATTRIB hits, TOKEN *ainfop, int methods)
{
PATTRIB ca;
/* Now, go through each of the hits, if any. */
for (ca = hits; ca; ca = ca->next) {
/* First element of the sequence is the name of the access method. */
if (!ca->value.sequence) {
wrong_length(ca); /* Record that it was malformed */
continue;
}
if((methods & P_AM_LOCAL)
&& (strequal(ca->value.sequence->token,"LOCAL"))) {
if (length(ca->value.sequence) != 5) {
wrong_length(ca);
continue;
}
*ainfop = ca->value.sequence;
ca->value.sequence = (TOKEN) NULL;
atlfree(hits);
return(P_AM_LOCAL);
}
if((methods & P_AM_NFS)
&& (strequal(ca->value.sequence->token,"NFS"))) {
if (length(ca->value.sequence) != 6) {
wrong_length(ca);
continue;
}
*ainfop = ca->value.sequence;
ca->value.sequence = (TOKEN) NULL;
atlfree(hits);
return(P_AM_NFS);
}
if((methods & P_AM_PROSPERO_CONTENTS)
&& (strequal(ca->value.sequence->token,"PROSPERO-CONTENTS"))) {
if (length(ca->value.sequence) != 5) {
wrong_length(ca);
continue;
}
*ainfop = ca->value.sequence;
ca->value.sequence = (TOKEN) NULL;
atlfree(hits);
return(P_AM_PROSPERO_CONTENTS);
}
if((methods & P_AM_WAIS)
&& (strequal(ca->value.sequence->token,"WAIS"))) {
if (length(ca->value.sequence) != 5) {
wrong_length(ca);
continue;
}
*ainfop = ca->value.sequence;
ca->value.sequence = (TOKEN) NULL;
atlfree(hits);
return(P_AM_WAIS);
}
if((methods & P_AM_TELNET)
&& (strequal(ca->value.sequence->token,"TELNET"))) {
if (length(ca->value.sequence) < 5) {
wrong_length(ca);
continue;
}
*ainfop = ca->value.sequence;
ca->value.sequence = (TOKEN) NULL;
atlfree(hits);
return(P_AM_TELNET);
}
if((methods & P_AM_AFS)
&& (strequal(ca->value.sequence->token,"AFS"))) {
if (length(ca->value.sequence) != 5) {
wrong_length(ca);
continue;
}
*ainfop = ca->value.sequence;
ca->value.sequence = (TOKEN) NULL;
atlfree(hits);
return(P_AM_AFS);
}
if((methods & P_AM_AFTP)
&& (strequal(ca->value.sequence->token,"AFTP"))) {
if (length(ca->value.sequence) != 6) {
wrong_length(ca);
continue;
}
*ainfop = ca->value.sequence;
ca->value.sequence = (TOKEN) NULL;
atlfree(hits);
return(P_AM_AFTP);
}
if((methods & P_AM_GOPHER)
&& (strequal(ca->value.sequence->token,"GOPHER"))) {
int len = length(ca->value.sequence);
if (len != 5 && len != 6) {
wrong_length(ca);
continue;
}
*ainfop = ca->value.sequence;
ca->value.sequence = (TOKEN) NULL;
if (len == 5) {
/* Canonicalize 5-token format to six-token format internally.
*/
TOKEN tmp = tkalloc(" ");
*(tmp->token) = *elt(*ainfop, 4);
APPEND_ITEM(tmp, *ainfop);
}
atlfree(hits);
return(P_AM_GOPHER);
}
if((methods & P_AM_RCP)
&& (strequal(ca->value.sequence->token,"RCP"))) {
if (length(ca->value.sequence) != 5) {
wrong_length(ca);
continue;
}
*ainfop = ca->value.sequence;
ca->value.sequence = (TOKEN) NULL;
atlfree(hits);
return(P_AM_RCP);
}
/* The FTP method requires prompting for a password, which is not
transparent to the user. Thus, it is the least desirable method,
from our point of view. */
if((methods & P_AM_FTP)
&& (strequal(ca->value.sequence->token,"FTP"))) {
if (length(ca->value.sequence) != 6) {
wrong_length(ca);
continue;
}
*ainfop = ca->value.sequence;
ca->value.sequence = (TOKEN) NULL;
atlfree(hits);
return(P_AM_FTP);
}
}
atlfree(hits);
*ainfop = NULL;
return 0;
}
/* Inform the user of a problem if pfs_debug is set. */
static void
wrong_length(PATTRIB ca)
{
p_warn_string = qsprintf_stcopyr(p_warn_string,
"Parse error: the server returned ACCESS-METHOD %s%swith %d \
elements; not what was expected by pget_am()!",
length(ca->value.sequence) > 0 ? ca->value.sequence->token : "",
length(ca->value.sequence) > 0 ? " " : "",
length(ca->value.sequence));
if (pfs_debug) {
fputs(p_warn_string, stderr);
fputc('\n', stderr);
}
pwarn = PWARNING;
}
/* Copy an attribute and expand it. */
static PATTRIB
expand_amat(PATTRIB ca, VLINK vl)
{
TOKEN tk;
if (length(ca->value.sequence) < 5) return NULL; /* malformed. */
ca = atcopy(ca); /* don't modify the original. */
/* atcopy has been fixed to do this properly! - Mitra*/
#ifdef NEVERDEFINED
ca->value.sequence = tkcopy(ca->value.sequence); /* copy the data too! */
#endif
tk = ca->value.sequence;
tk = tk->next; /* skip access method name */
if(*tk->token == '\0') tk->token = stcopyr(vl->hosttype, tk->token);
tk = tk->next; /* go on */
if(*tk->token == '\0') tk->token = stcopyr(vl->host, tk->token);
tk = tk->next; /* go on */
if(*tk->token == '\0') tk->token = stcopyr(vl->hsonametype, tk->token);
tk = tk->next; /* go on */
if(*tk->token == '\0') tk->token = stcopyr(vl->hsoname, tk->token);
return ca;
}

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

@@ -0,0 +1,130 @@
/*
* 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 <stdio.h>
#include <string.h>
#include <ardp.h>
#include <pfs.h>
#include <pprot.h>
#include <perrno.h>
#include <pparse.h>
extern int pfs_debug;
/* Obtain object attributes from a remote host.. */
/* Use pget_linkat() to obtain link attributes. */
PATTRIB pget_at(vl,atname)
VLINK vl;
const char *atname;
{
RREQ req; /* Text of request to dir server */
PATTRIB retval = NULL; /* Start of list of attributes */
INPUT_ST in_st;
INPUT in = &in_st;
int tmp; /* return value from subfunctions. Value is
only used for a couple of lines after it's
set each time. */
int fwdcnt = MAX_FWD_DEPTH;
perrno = PSUCCESS; /* must set perrno, since that's how we report
success or failure. */
/* It's not an error to ask; However, we already know that there won't be
any object attributes, so we just report that fact and don't waste the
time for the request to time out. */
if (vl->target && !strequal(vl->target, "OBJECT")
&& !strequal(vl->target, "FILE")
&& !strequal(vl->target, "DIRECTORY")
&& !strequal(vl->target, "DIRECTORY+FILE"))
return NULL;
startover:
CHECK_MEM();
req = p__start_req(vl->host);
p__add_req(req, "GET-OBJECT-INFO %'s ASCII %'s 0\n",
atname, vl->hsoname);
if (vl->f_magic_no)
p__add_req(req, "SELECT OBJECT FIELD ID REMOTE %ld\n",
vl->f_magic_no);
tmp = ardp_send(req,vl->host,0,ARDP_WAIT_TILL_TO);
/* If the request fails or if we don't get a response, then return error */
if(tmp || req->rcvd == NULL) return(NULL);
rreqtoin(req, in);
while (!in_eof(in)) {
char *line;
char *next_word;
if (in_line(in, &line, &next_word)) {
ardp_rqfree(req);
return(NULL);
}
switch (*line) {
case 'A': /* ATTRIBUTE */
/* If anything but ATTRIBUTE scan error */
if(!strnequal(line,"ATTRIBUTE", 9))
goto scanerr;
if (in_ge1_atrs(in, line, next_word, &retval)) {
ardp_rqfree(req);
return NULL; /* perrno will be set. */
}
break;
case 'N': /* NONE-FOUND */
/* NONE-FOUND, we just have no attributes to insert. No error;
just don't do anything. */
if(strncmp(line,"NONE-FOUND",10) == 0)
break;
goto scanerr;
case 'F':/* FORWARDED, FAILURE */
if(strncmp(line,"FORWARDED",9) == 0) {
if(fwdcnt-- <= 0) {
ardp_rqfree(req);
perrno = PFS_MAX_FWD_DEPTH;
return(NULL);
}
/* parse and start over */
tmp = qsscanf(line,"FORWARDED %&'s %&'s %&'s %&'s %ld %ld",
&vl->hosttype, &vl->host, &vl->hsonametype,
&vl->hsoname,
&(vl->version), &(vl->f_magic_no));
if(tmp < 2) {
perrno = DIRSRV_BAD_FORMAT;
break;
}
ardp_rqfree(req);
goto startover;
}
/* If FAILURE or anything but FORWARDED, scan error */
goto scanerr;
scanerr:
default:
if(*line && (tmp = scan_error(line, req))) {
ardp_rqfree(req);
perrno = tmp;
return(NULL);
}
break;
} /* end of moby switch */
} /* while in_nextline(in) */
ardp_rqfree(req);
return(retval);
}

View File

@@ -0,0 +1,293 @@
/*
* 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>
#if 0 /* This code should be deleted if this
clean-compiles. */
/* For SCO which doesn't define MAXPATHLEN */
#ifndef MAXPATHLEN
#define MAXPATHLEN 1024
#endif
#endif /* 0 */
#include <stdio.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <pfs.h>
#include <pcompat.h>
#include <psite.h>
#include <perrno.h>
#include <mitra_macros.h> /* For L2 */
#include <pmachine.h> /* for INCLUDE_FILES_LACK_TEMPNAM_PROTOTYPE */
static int pmap_getcache(char *npath, TOKEN am_args);
#define SECONDSPERDAY (60*60*24)
/* This defines our caching policy -- a simple cut-off. A more sophisticated
* policy could be used but doesn't seem necessary.
*
* This policy does not take into account the issues of swiftly-changing data.
*/
#define MAXFILECACHEAGE (1*SECONDSPERDAY)
/* p__map_cache(): Retrieve a file and cache it.
*
* The interface should be changed to be char **npath and use stcopy for name.
*/
/* Note returns 0 or PMC_DELETE_ON_CLOSE for success */
#ifndef P_CACHE_ENABLED
/* Retrieve file caching it in /tmp/pfs_cache */
int
p__map_cache(VLINK vl, /* link to object - NOT USED at this time. */
char *npath, /* Buffer to write filename into */
int npathlen, /* length of buffer */
TOKEN am_args) /* Access mode args
access_method,INTERNET-D,host,ASCII,remote*/
{
qsprintf(npath, npathlen, "/tmp/pfs_cache/%s/%s%s%s", elt(am_args,2),
elt(am_args, 0), ((*elt(am_args,4) == '/') ? "" : "/"),
elt(am_args, 4));
return pmap_getcache(npath,am_args);
}
#else
/* Retrieve file caching it in P_CACHE_VC */
int
p__map_cache(VLINK vl, /* link to object - NOT USED at this time. */
char *npath, /* Buffer to write filename into */
int npathlen, /* length of buffer */
TOKEN am_args) /* Access mode args
access_method,INTERNET-D,host,ASCII,remote*/
{
int retval = 0;
char *cachename = NULL;
char *tempfile = NULL;
/* Name of cached version is -- P_CACHE_VC/host/method/remote */
cachename = qsprintf_stcopyr(cachename, "%s/%s/%s%s%s",
P_CACHE_VC, elt(am_args,2),
elt(am_args, 0), ((*elt(am_args,4) == '/') ? "" : "/"),
elt(am_args, 4));
if ((strlen(cachename) > 250 )
&& (strncmp(elt(am_args, 4), "WAIS-GW",7) == 0) ) {
/* Horrible Kludge alert, make component length smaller for
WAIS docid's */
char *cp;
for (cp=cachename; *cp; cp++)
if (*cp == '%')
*cp = '/';
}
/* Determine whether a cached copy already exists */
if (!file_incache(cachename) || (stat_age(cachename) > MAXFILECACHEAGE) ) {
switch (retval = pmap_getcache(cachename,am_args)) {
case PMC_DELETE_ON_CLOSE:
case PSUCCESS:
break;
/*PMC_RETRIEVE_FAILED:*/
default:
if (file_incache(cachename)) {
/* Old copy stil available */
break;
} else {
/* Failed */
stfree(cachename);
return(retval);
}
}
}
/* Either succeeded in fetching, or already had it */
/* Assuming caller opens this file, then it will touch access time*/
tempfile = tempnam(P_CACHE_P,NULL);
if (link(cachename, tempfile)) {
retval=errno;
} else {
qsprintf(npath,npathlen,tempfile);
}
stfree(cachename);
free(tempfile);
return(retval);
}
#endif /* P_CACHE_ENABLED */
/*
* Retrieves a file with access method am_args into the file
* named NPATH. This breakout is attributable to mitra (thanks).
*
* Return codes:
* 0 or PMC_DELETE_ON_CLOSE is success.
* All other return codes indicate a failure. Currently always returns
* PMC_DELETE_ON_CLOSE.
*/
static
int
pmap_getcache(char *npath, TOKEN am_args)
{
static char *vcachebin;
int pid;
#ifdef BSD_UNION_WAIT
union wait status;
#else
int status;
#endif
int tmp;
char *vcargv[12]; /* vcache's ARGV. Enough to hold any known
access method arguments. */
char **vcargvp = vcargv; /* pointer to vcache's argv. */
#ifndef INCREASE_CLIENT_EXECUTABLE_SIZE_DO_NOT_EXEC_VCACHE
char *p_binaries;
#else /*INCREASE_CLIENT_EXECUTABLE_SIZE_DO_NOT_EXEC_VCACHE*/
char *host, *method, *remote;
#endif /*INCREASE_CLIENT_EXECUTABLE_SIZE_DO_NOT_EXEC_VCACHE*/
assert(P_IS_THIS_THREAD_MASTER()); /* Not thread safe yet */
#ifndef INCREASE_CLIENT_EXECUTABLE_SIZE_DO_NOT_EXEC_VCACHE
/* should really do this on our own without */
/* calling system, but... */
/* Set args first. This makes it easier to debug on debuggers that don't
take kindly to subprocesses forking. */
p_binaries = getenv("P_BINARIES");
assert(P_IS_THIS_THREAD_MASTER());
#ifdef P_BINARIES
if (!p_binaries)
p_binaries = P_BINARIES;
#endif
*vcargvp++ = "vcache";
#ifdef P_CACHE_ENABLED
*vcargvp++ = "-m"; /* manage the cache argument */
#endif
*vcargvp++ = npath;
#else /*INCREASE_CLIENT_EXECUTABLE_SIZE_DO_NOT_EXEC_VCACHE*/
if (!am_args) return PMC_RETRIEVE_FAILED;
method = am_args->token ; am_args = am_args->next;
if (!am_args) return PMC_RETRIEVE_FAILED;
if (strcmp(am_args->token,"INTERNET-D")) return PMC_RETRIEVE_FAILED;
am_args = am_args->next;
if (!am_args) return PMC_RETRIEVE_FAILED;
host = am_args->token ; am_args = am_args->next;
if (!am_args) return PMC_RETRIEVE_FAILED;
if (strcmp(am_args->token,"ASCII")) return PMC_RETRIEVE_FAILED;
am_args = am_args->next;
if (!am_args) return PMC_RETRIEVE_FAILED;
remote = am_args->token ; am_args = am_args->next;
#endif /*INCREASE_CLIENT_EXECUTABLE_SIZE_DO_NOT_EXEC_VCACHE*/
for (;am_args; am_args = am_args->next) {
*vcargvp++ = am_args->token;
}
*vcargvp = NULL;
#ifndef INCREASE_CLIENT_EXECUTABLE_SIZE_DO_NOT_EXEC_VCACHE
pid = fork();
if (pid < 0) {
if (pfs_debug) {
perror("p__map_cache(): failed to fork().");
}
return PMC_RETRIEVE_FAILED;
}
#if 0
#define atline() if(pfs_debug > 10) fprintf(stderr, "%s:%d\n", __FILE__, __LINE__)
#else
#define atline() do ; while (0)
#endif
if (pid == 0) {
if (pfs_debug > 10)
fprintf(stderr, "p__map_cache(): just forked.\n");
atline();
if (!p_binaries || !*p_binaries) {
atline();
/* In execl, add the "-m" option if cache to be managed */
/* Add the "-r" option if existing item is out of date */
DISABLE_PFS(execvp("vcache",vcargv));
atline();
if (!vcachebin) vcachebin = stcopy("vcache");
strcpy(vcachebin, "vcache"); /* for error reporting */
atline();
} else {
atline();
if (!vcachebin)
vcachebin = qsprintf_stcopyr(vcachebin,
"%s/vcache",p_binaries);
atline();
/* In execl, add the "-m" option if cache to be managed */
/* Add the "-r" option if existing item is out of date */
DISABLE_PFS(execv(vcachebin,vcargv));
atline();
}
atline();
if (pfs_debug) {
fprintf(stderr,
"p__map_cache(): exec failed for %s (errno=%d): ",
vcachebin,errno);
perror(NULL);
}
atline();
exit(1);
}
else {
wait(&status);
}
#ifdef BSD_UNION_WAIT
tmp = status.w_T.w_Retcode;
#else
tmp = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
#endif
#else /*INCREASE_CLIENT_EXECUTABLE_SIZE_DO_NOT_EXEC_VCACHE*/
/* This is an experiment in calling vcache directly */
DISABLE_PFS(tmp=vcache2a(host, remote, npath, method, vcargv,
#ifdef P_CACHE_ENABLED
TRUE /* argument to manage the cache */
#else
FALSE
#endif
));
#endif /*INCREASE_CLIENT_EXECUTABLE_SIZE_DO_NOT_EXEC_VCACHE*/
if(tmp) return(PMC_RETRIEVE_FAILED);
/* Return PMC_DELETE_ON_CLOSE if cache is not being managed */
/* I left this, because we are making a copy, that the caller
needs to delete -- Mitra */
return(PMC_DELETE_ON_CLOSE);
/* return(PSUCCESS);*/
}
int
file_incache(char *local)
{
struct stat buf;
/* This is probably lazy bad code, stat fails if and only if the
file doesn't exist in the cache*/
return (stat(local,&buf) == 0);
}
#if 0 /* not used; different test up above. */
int
file_incache_and_uptodate(char *local)
{
/* For now, everything is up to date, need to be much cleverer !!*/
return (file_incache(local));
}
#endif

133
prospero/lib/pfs/pmap_nfs.c Normal file
View File

@@ -0,0 +1,133 @@
/*
* Copyright (c) 1989, 1990 by the University of Washington
*
* For copying and distribution information, please see the file
* <uw-copyright.h>.
*/
#include <uw-copyright.h>
#include <psite.h>
#ifdef P_NFS
#include <sys/types.h>
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/wait.h>
#include <stdio.h>
#include <pfs.h>
#include <pcompat.h>
#include <pmachine.h>
#ifdef ULTRIX
#include <sys/fs_types.h>
#else
#include <mntent.h>
#endif
pmap_nfs(host,rpath,npath, npathlen, am_args)
char *host;
char *rpath;
char *npath;
int npathlen;
TOKEN am_args;
{
char rfile[MAXPATHLEN];
char lmpt[MAXPATHLEN];
char *rmpt; /* remote mount point */
char rmparg[MAXPATHLEN];
char *suffix; /* path from remote mount point. */
char *rf = rfile;
char *a;
int devnl;
int tmp;
int pid;
#ifdef BSD_UNION_WAIT
union wait status;
#else
int status;
#endif
int start = 0;
#ifdef ULTRIX
struct fs_data buffer;
struct fs_data *buf = &buffer;
#else
struct mntent *mtentry;
FILE *mtab;
#endif
rmpt = elt(am_args, 5); /* mount point on remote host. */
suffix = elt(am_args, 4); /* object handle used by NFS on remote host */
sprintf(rf,"%s:%s/%s",host,rmpt,suffix);
#ifdef ULTRIX
while(getmountent(&start, buf, 1) > 0) {
devnl = strlen(buf->fd_devname);
if(!strncmp(rfile,buf->fd_devname,devnl)) {
qsprintf(npath, npathlen, "%s%s",buf->fd_path,rfile+devnl);
return(PSUCCESS);
}
}
#else
DISABLE_PFS(mtab = setmntent("/etc/mtab","r"));
while(mtentry = getmntent(mtab)) {
devnl = strlen(mtentry->mnt_fsname);
if(!strncmp(rfile,mtentry->mnt_fsname,devnl)) {
qsprintf(npath, npathlen, "%s%s",mtentry->mnt_dir,rfile+devnl);
endmntent(mtab);
return(PSUCCESS);
}
}
endmntent(mtab);
#endif
sprintf(lmpt,"/tmp/pfs_mount/%s%s",host,rmpt);
a = lmpt + strlen(lmpt) - strlen(rmpt);
while(*a) {
if(*a == '/') *a = '-';
a++;
}
mkdir("/tmp/pfs_mount",0777);
chmod("/tmp/pfs_mount",0777);
mkdir(lmpt,0777);
chmod(lmpt,0777);
sprintf(rmparg,"%s:%s",host,rmpt);
/* should really do this on our own without */
/* calling system, but... */
pid = fork();
if (pid == 0) {
#ifdef ULTRIX
DISABLE_PFS(execl("/etc/mount","mount", "-t", "nfs",
"-o", "rw,hard,intr,retry=20",
rmparg, lmpt, 0));
#else
DISABLE_PFS(execl("/etc/mount","mount", rmparg, lmpt, 0));
#endif
exit(1);
}
else {
wait(&status);
}
#ifdef BSD_UNION_WAIT
tmp = status.w_T.w_Retcode;
#else
tmp = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
#endif
if(tmp) RETURNPFAILURE;
qsprintf(npath, npathlen, "%s/%s",lmpt,suffix);
return(PSUCCESS);
}
#endif P_NFS

116
prospero/lib/pfs/pset_at.c Normal file
View File

@@ -0,0 +1,116 @@
/*
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file <usc-license.h>
*/
/* Author: Steven Augart, swa@isi.edu */
#include <usc-license.h>
#include <stdio.h>
#include <ardp.h>
#include <pfs.h>
#include <pparse.h>
#include <pprot.h>
#include <perrno.h>
static int eoi_parse_resp(RREQ resp);
extern int pfs_debug;
/* Sets OBJECT attributes appropriately. */
/* Returns PSUCCESS upon successful execution, failure code otherwise. */
int
pset_at(VLINK vl, int flags, PATTRIB attributes)
{
RREQ req;
OUTPUT_ST out_st;
OUTPUT out = &out_st;
INPUT_ST in_st;
INPUT in = &in_st;
int fwdcnt = MAX_FWD_DEPTH;
int tmp; /* error return code from functions. Value only
used a few lines after set, each time. */
if (vl->target && !strequal(vl->target, "OBJECT")
&& !strequal(vl->target, "FILE")
&& !strequal(vl->target, "DIRECTORY")
&& !strequal(vl->target, "DIRECTORY+FILE")) {
p_err_string = qsprintf_stcopyr(p_err_string,
"pset_at(): Asked to munge the attributes of the object \
pointed to by a link with a target of %s. Cannot do this.\n", vl->target);
return perrno = PSET_AT_TARGET_NOT_AN_OBJECT;
}
startover:
req = p__start_req(vl->host);
p__add_req(req, "EDIT-OBJECT-INFO ");
switch(flags) {
case EOI_ADD:
p__add_req(req, "ADD");
break;
case EOI_DELETE:
p__add_req(req, "DELETE");
break;
case EOI_DELETE_ALL:
p__add_req(req, "DELETE-ALL");
break;
case EOI_REPLACE:
p__add_req(req, "REPLACE");
break;
default:
p_err_string = qsprintf_stcopyr(p_err_string,
"edit_object_info(): Illegal flag value: %d", flags);
break;
return perrno = PFAILURE;
}
p__add_req(req, " %'s %'s\n", vl->hsonametype, vl->hsoname);
requesttoout(req,out);
out_atrs(out, attributes, 0);
tmp = ardp_send(req, vl->host, 0, ARDP_WAIT_TILL_TO);
if(tmp) {
if (pfs_debug) fprintf(stderr,"ardp_send failed: %d\n",perrno);
return perrno = tmp;
}
if(req->rcvd == NULL) return(perrno);
rreqtoin(req, in);
while(!in_eof(in)) {
char *line;
char *next_word;
if (tmp = in_line(in, &line, &next_word)) {
ardp_rqfree(req);
return(tmp);
}
if(strncmp(line,"FORWARDED",9) == 0) {
if(fwdcnt-- <= 0) {
ardp_rqfree(req);
perrno = PFS_MAX_FWD_DEPTH;
return(perrno);
}
/* parse and start over */
tmp = qsscanf(line,"FORWARDED %&'s %&'s %&s %&'s",
&vl->hosttype, &vl->host,
&vl->hsonametype,&vl->hsoname);
if(tmp < 2) {
ardp_rqfree(req);
perrno = DIRSRV_BAD_FORMAT;
break;
}
ardp_rqfree(req);
goto startover;
}
if(strncmp(line,"SUCCESS",7) == 0) {
ardp_rqfree(req);
return(PSUCCESS);
}
/* If FAILURE or anything else scan error */
if (tmp = scan_error(line, req)) {
ardp_rqfree(req);
return tmp;
}
}
ardp_rqfree(req);
return PSUCCESS;
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the file <usc-copyr.h>
*/
/* Author: Steven Augart, swa@isi.edu */
#include <usc-copyr.h>
#include <stdio.h>
#include <ardp.h>
#include <pfs.h>
#include <pparse.h>
#include <perrno.h>
static int eoi_parse_resp(RREQ resp);
extern int pfs_debug;
/* Returns PSUCCESS upon successful execution, PFAILURE for whatever failure
reason. */
int
pset_linkat(VLINK dlink, char lname[], int flags, PATTRIB attributes)
{
RREQ req;
OUTPUT_ST out_st;
OUTPUT out = &out_st;
int tmp;
req = p__start_req(dlink->host);
p__add_req(req, "DIRECTORY ASCII %'s 0\nEDIT-LINK-INFO ", dlink->hsoname);
switch(flags) {
case EOI_ADD:
p__add_req(req, "ADD");
break;
case EOI_DELETE:
p__add_req(req, "DELETE");
break;
case EOI_DELETE_ALL:
p__add_req(req, "DELETE-ALL");
break;
case EOI_REPLACE:
p__add_req(req, "REPLACE");
break;
default:
p_err_string = qsprintf_stcopyr(p_err_string,
"edit_object_info(): Illegal flag value: %d", flags);
break;
RETURNPFAILURE;
}
p__add_req(req, " %'s\n", lname);
requesttoout(req,out);
out_atrs(out, attributes, 0);
tmp = ardp_send(req, dlink->host, 0, ARDP_WAIT_TILL_TO);
if(tmp) {
fprintf(stderr,"Dirsend failed: %d\n",perrno);
perrno = tmp;
}
if(req->rcvd == NULL) return(perrno);
return eoi_parse_resp(req);
}
static int
eoi_parse_resp(RREQ resp)
{
INPUT_ST in_st;
INPUT in = &in_st;
rreqtoin(resp, in);
while(!in_eof(in)) {
char *line;
char *next_word;
int tmp; /* error return code from functions */
if (tmp = in_line(in, &line, &next_word)) {
ardp_rqfree(resp);
return(tmp);
}
/* Scanerr() will handle SUCCESS or FAILURE or any other error return
codes. It parses it all for us! */
if (tmp = scan_error(line, resp)) {
ardp_rqfree(resp);
return tmp;
}
}
return PSUCCESS;
}

View File

@@ -0,0 +1,40 @@
/*
* 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>
char *
p__qbstprintf_stcopyr(char *buf, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
buf = p__vqbstprintf_stcopyr(buf, fmt, ap);
va_end(ap);
return buf;
}
char *
p__vqbstprintf_stcopyr(char *buf, const char *fmt, va_list ap)
{
int tmp;
assert(p__bst_consistent(buf));
again:
tmp = qsprintf(buf, p__bstsize(buf), fmt, ap);
if (tmp > p__bstsize(buf)) {
stfree(buf);
buf = stalloc(tmp);
goto again;
}
/* Tmp is now the size of the total output area, including a trailing null.
Need to set the size to tmp -1, since trailing null is not included. */
p_bst_set_buffer_length_nullterm(buf, tmp - 1);
return buf;
}

View File

@@ -0,0 +1,22 @@
/* Copyright (c) 1992 by the University of Southern California. */
/* For copying and distribution information, see the file <usc-copyr.h> */
#include <usc-copyr.h>
#include <pfs.h>
#include <pprot.h>
/* See vqsprintf() for documentation.
This is slightly inefficient, since it wastes a function call. Oh well.
Return PFAILURE or PSUCCESS.
*/
int
qfprintf(FILE *outf, const char fmt[], ...)
{
va_list ap;
int retval;
va_start(ap,fmt);
retval = vqfprintf(outf, fmt, ap);
va_end(ap);
return retval;
}

55
prospero/lib/pfs/qindex.c Normal file
View File

@@ -0,0 +1,55 @@
/* qindex.c
This program works just like "index()", but it recognizes Prospero quoting.
Looks for first unquoted instance of "c" in string s.
Returns NULL if none found.
If it finds a mis-quoted string, returns NULL and sets perrno to
PARSE_ERROR.
Author: swa@isi.edu, 8/17/92
*/
#include <pfs.h> /* to make sure we match definition. */
#include <perrno.h>
char *
qindex(const char *s, char c)
{
enum { OUTSIDE_QUOTATION, IN_QUOTATION,
SEEN_POSSIBLE_CLOSING_QUOTE } state;
const char *start = s;
state = OUTSIDE_QUOTATION;
for (; *s; ++s) {
switch (state) {
case OUTSIDE_QUOTATION:
if (*s == '\'')
state = IN_QUOTATION;
else if (*s == c)
return (char *) s; /* flush CONST */
break;
case IN_QUOTATION:
if (*s == '\'')
state = SEEN_POSSIBLE_CLOSING_QUOTE;
break;
case SEEN_POSSIBLE_CLOSING_QUOTE:
if (*s == '\'') {
if (c == '\'')
return (char *) s; /* flush CONST */
state = IN_QUOTATION;
} else {
state = OUTSIDE_QUOTATION;
if (*s == c)
return (char *) s; /* flush CONST */
}
break;
default:
internal_error("qindex(): impossible state!");
}
}
if (state == IN_QUOTATION) {
perrno = PARSE_ERROR;
p_err_string = qsprintf_stcopyr(p_err_string,
"qindex(): encountered text with unbalanced quoting: %'s", start);
}
return NULL;
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the file <usc-copyr.h>
*/
#include <usc-copyr.h>
#include <pfs.h>
#include <pparse.h>
/* This function will be reset by the server to srv_qoprintf.c, which is found
in libpsrv. This hack lets us avoid linking the client with
srv_qoprintf.c, and thereby cuts down on the client code size. */
/* This function, in its client and server incarnations, qprintfs to an OUTPUT
structure. */
#ifdef __STDC__
int (*qoprintf)(OUTPUT out, const char format[], ...) = cl_qoprintf;
#else
int (*qoprintf)() = cl_qoprintf;
#endif

View File

@@ -0,0 +1,23 @@
/* Copyright (c) 1992, 1993 by the University of Southern California. */
/* For copying and distribution information, see the file <usc-copyr.h> */
#include <usc-copyr.h>
#include <pfs.h>
/* Like rindex(), but respecting Prospero quoting. */
char *
qrindex(const char *s, char c)
{
char *thisc;
char *lastc = NULL;
assert(c); /* it'll blow up otherwise, cause we might
shoot off the end of the string. */
for(thisc = qindex(s, c); thisc;
lastc = thisc, thisc = qindex(thisc + 1, c))
;
return lastc;
}

18
prospero/lib/pfs/qscanf.c Normal file
View File

@@ -0,0 +1,18 @@
/* Copyright (c) 1993 by the University of Southern California.
* For copying information, see the file <usc-copyr.h>
*/
#include <usc-copyr.h>
#include <pparse.h>
extern int
qscanf(INPUT in, const char fmt[], ...)
{
int retval;
va_list ap;
va_start(ap, fmt);
retval = vqscanf(in, fmt, ap);
va_end(ap);
return retval;
}

View File

@@ -0,0 +1,40 @@
/*
* 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>
char *
qsprintf_stcopyr(char *buf, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
buf = vqsprintf_stcopyr(buf, fmt, ap);
va_end(ap);
return buf;
}
char *
vqsprintf_stcopyr(char *buf, const char *fmt, va_list ap)
{
int tmp;
again:
tmp = vqsprintf(buf, p__bstsize(buf), fmt, ap);
if (tmp > p__bstsize(buf)) {
stfree(buf);
buf = stalloc(tmp);
goto again;
}
/* The count returned by vqsprintf includes a trailing null. */
/* Mark this so that vqsprintf_stcopyr() returns a properly sized bstring.
*/
p_bst_set_buffer_length_nullterm(buf, tmp - 1);
return buf;
}

View File

@@ -0,0 +1,30 @@
/* vqsprintf.c
Author: Steven Augart <swa@isi.edu>
Written: 7/18/92 -- 7/24/92
Long support added, 10/2/92
vqsprintf() added, 10/6/92
I am really interested in comments on this code, suggestions for making it
faster, and criticism of my style. Please send polite suggestions for
improvement to swa@isi.edu.
*/
/* Copyright (c) 1992 by the University of Southern California. */
/* For copying and distribution information, see the file <usc-copyr.h> */
#include <usc-copyr.h>
#include <pfs.h>
/* See vqsprintf() for documentation.
This is slightly inefficient, since it wastes a function call. Oh well.
*/
size_t
qsprintf(char *buf, size_t buflen, const char *fmt, ...)
{
va_list ap;
size_t retval;
va_start(ap,fmt);
retval = vqsprintf(buf, buflen, fmt, ap);
va_end(ap);
return retval;
}

View File

@@ -0,0 +1,43 @@
/* qsscanf.c
Author: Steven Augart (swa@isi.edu)
Designed, Documented, and Written: 7/18/92 -- 7/27/92
Ported from Gnu C to full ANSI C & traditional C, 10/5/92
& modifier added, detraditionalized: 2/16/93.
Made a wrapper around qscanf(), 3/2/93
*/
/* Copyright (c) 1992, 1993 by the University of Southern California. */
/* For copying and distribution information, see the file <usc-copyr.h> */
#include <usc-copyr.h>
#include <stdarg.h> /* ANSI variable arguments facility. */
#include <pfs.h>
#include <pparse.h>
int
qsscanf(const char *s, const char *fmt, ...)
/* s: source string
fmt: format describing what to scan for.
remaining args: pointers to places to store the data we read, or
integers (field widths).
*/
{
va_list ap; /* for varargs */
int retval;
INPUT_ST in_st;
INPUT in = &in_st;
/* Otherwise vqscanf will fail an assertion*/
if (!s || s[0] == '\0') return 0;
in->sourcetype = IO_STRING;
in->rreq = NULL;
in->s = s;
in->file = NULL;
in->flags = PERCENT_R_TARGET_IS_STRING;
va_start(ap, fmt);
retval = vqscanf(in, fmt, ap);
va_end(ap);
return retval;
}

View File

@@ -0,0 +1,64 @@
/*
* 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>
/* Written, 9/18/92, swa@isi.edu */
/* Made use 'previous' member 6/14/93, swa@isi.edu */
/* Got rid of double invocation of stcopy() for efficiency,. 5/15/94,
swa@ISI.EDU */
/* Break up a string into space-separated tokens and recognize Prospero
quoting. This strips off the quoting in the process. This function could
also be called p__tokenize_newstyle_mcomp(), and it serves that function.
It assumes the input string is correctly quoted.
*/
#include <pfs.h>
#include <pprot.h>
TOKEN
qtokenize(const char *s)
{
TOKEN retval;
int tmp;
AUTOSTAT_CHARPP(bufp);
/* We need a new interface to tkalloc() so we can avoid doing two stcopy()
operations on the same data. */
/* swa, 5/15/94: I decided to just make the code a bit longer, but used the
existing TKALLOC interface instead. This seems like less hassle than a
new interface, since it is not used very frequently. */
if (!s) return NULL;
retval = NULL;
for (;;) {
#if 1 /* 5/15/94 change --swa */
TOKEN tmptok;
#endif
tmp = qsscanf(s, "%'&s %r", bufp, &s);
assert(tmp >= 0); /* no possible error, I hope! */
if (tmp == 0)
return retval;
#if 1
tmptok = tkalloc((char *) NULL);
tmptok->token = *bufp;
*bufp = NULL; /* Leaving out this step cost almost a day's
work. Since *bufp sticks around, we should
mark it as free so that it is not reused
inappropriately. I now understand what
broke and why. --swa, 5/16/94 */
APPEND_ITEM(/* new */ tmptok, /* head */ retval);
/* This version just avoided the stcopy(). */
#else
/* This is the old less efficient version: --swa, 5/15/94 */
retval = tkappend(*bufp, retval);
#endif
if (tmp == 1) return retval; /* no more to tokenize. */
}
}

640
prospero/lib/pfs/rd_vdir.c Normal file
View File

@@ -0,0 +1,640 @@
/*
* 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 <stdio.h>
#include <string.h>
#include <pfs.h>
#include <perrno.h>
#include <pmachine.h>
static TOKEN p__rvdslashpath2tkl(char *nextcomp);
static void p__tkl_back_2rvdslashpath(TOKEN nextcomp_tkl, char *nextcomp);
/*
*/
int
rd_vdir(dirarg,comparg,dir,flags)
const char *dirarg; /* Virtual name for the directory */
const char *comparg; /* Component name (wildcards allowed) */
VDIR dir; /* Structure to be filled in */
long flags; /* Flags */
{
/* Note: We use a working copy of dirarg because we want to */
/* modify the working copy, and we would prefer not to */
/* modify the directory name passed to this procedure. */
/* dirnm is required because we need a character pointer */
/* later on (dirname), but the compiler only allows */
/* automatic allocation for a character array. */
/* components is a working copy of comparg which might be */
/* modified if a magic number has been specified. */
char dirnm[MAX_VPATH]; /* Working copy of dirarg */
char *dirname = dirnm; /* Pointer to dirnm */
char components[MAX_VPATH];/* Working copy of comparg */
char *dirhst; /* Host of current directory */
char *remdir; /* Dir on remote host */
char *homedir; /* Name of home directory */
char *workdir; /* Name of working directory */
int hdlen; /* Length of homedir name */
int wdlen; /* Length of workdir name */
char relativeto; /* 0 = name relative to root */
FILTER filters = NULL; /* Filters to be applied */
char *ndname; /* Next component of dirname */
char *magic_str; /* Magic number part of ndname */
int magic_no; /* Magic number from magic_str */
int poundsign; /* Flag, nextcomp contains # */
char wdname[MAX_VPATH]; /* Working directory name */
VLINK ltmp; /* To look for unexpanded links */
PATTRIB closure; /* Namespace from closed object */
int retval; /* Return value */
int depth; /* Depth for sym-link expansion */
char stmp[MAX_VPATH]; /* Temporary string */
char *colon; /* Pointer to colon in path */
char *nsname; /* Possible name of new ns */
int beyondcolon; /* Length of text after colon */
char *nextcomp; /* 4 steppng through components */
long intflags; /* Flags for intermediate query */
depth = SYMLINK_NESTING;
strcpy(dirname,dirarg);
strcpy(components,(comparg ? comparg : ""));
nsname = dirname;
colon = p_uln_index(dirname,':');
if(colon) {
/* Name can not start with a ":" */
if(colon == nsname) return(RVD_NS_NOT_FOUND);
/* Don't support name space aliases yet, so return an error */
/* if the colon is preceded by a "#". */
if(*(colon-1) == '#') return(RVD_NO_NS_ALIAS);
}
/* In most cases, we start from a specific directory */
/* and don't care about the full pathname from root */
/* We only want to deal with the pathname for the root */
/* directory if the name starts with ../'s or ~/../'s */
*wdname = '\0';
if(*dirname == '\0') {
relativeto = 2;
dirhst = pget_wdhost();
remdir = pget_wdfile();
}
else if(*dirname == '/') {
relativeto = 0;
dirhst = pget_rdhost();
remdir = pget_rdfile();
dirname++;
}
else if((strncmp(dirname,"~/",2) == 0)||(strcmp(dirname,"~") == 0)) {
/* Set wdname to homedir and later check for ../'s */
relativeto = 1;
strcpy(wdname,pget_hd());
dirhst = pget_hdhost();
remdir = pget_hdfile();
dirname++;
/* We only want to step over the next byte if it is not the */
/* end of the string. It will be if string was ~ */
if(*dirname) dirname++;
}
else {
/* Set wdname and later check for ../'s */
relativeto = 2;
workdir = pget_wd();
if(workdir) strcpy(wdname,workdir);
else return(PFS_ENV_NOT_INITIALIZED);
dirhst = pget_wdhost();
remdir = pget_wdfile();
}
/* If Prospero environment has not been initialized return error */
if((dirhst == NULL) || (*dirhst == '\0'))
return(PFS_ENV_NOT_INITIALIZED);
/* If we still allow ../'s and the dirname starts */
/* as such, determine the correct name for the new */
/* file relative to VSROOT, and use that instead */
if(*wdname && (strncmp(dirname,"..",2) == 0)) {
char *slash;
relativeto = 0;
dirhst = pget_rdhost();
remdir = pget_rdfile();
while((strncmp(dirname,"../",3) == 0) ||
(strcmp(dirname,"..") == 0)) {
dirname += 2;
if(*dirname == '/') dirname++;
slash = p_uln_rindex(wdname,'/');
colon = p_uln_rindex(wdname,':');
if(slash && (!colon || (slash > colon))) *slash = '\0';
else if(colon) *(colon+1) = '\0';
else *wdname = '\0';
if(!*wdname) strcpy(wdname,"/");
}
/* Remove a ./ if it caused termination of ../s */
if(strncmp(dirname,"./",2) == 0) {
dirname++;
dirname++;
}
if(*dirname && (*(wdname + strlen(wdname)-1) != '/'))
strcat(wdname,"/");
strcat(wdname,dirname);
dirname = wdname;
}
/* Special case "." if appears by itself */
if(strcmp(dirname,".") == 0) {
dirname++;
}
/* And finally, remove a ./ if it appears at start */
else if(strncmp(dirname,"./",2) == 0) {
dirname++;
dirname++;
}
/* Check to see if working or home directory is a */
/* prefix of the directory to be listed */
if(! (flags & RVD_NOCACHE) ) {
workdir = pget_wd();
homedir = pget_hd();
if((relativeto == 0) && (*dirname != '/')) {
workdir++;
homedir++;
}
wdlen = strlen(workdir);
hdlen = strlen(homedir);
/* Do not cache if remaining part of name has any */
/* single colons. Right now the check disables caching */
/* if it finds any colons. It should allow it if it is */
/* a double colon. */
if((strncmp(dirname,workdir,wdlen) == 0) &&
((hdlen <= wdlen) || (strncmp(dirname,homedir,hdlen) != 0)) &&
((*(dirname+wdlen) == '/') || (*(dirname+wdlen) == '\0'))&&
(p_uln_index(dirname+wdlen,':') == 0)) {
dirname = dirname + wdlen;
if(*dirname == '/') dirname++;
relativeto = 2;
dirhst = pget_wdhost();
remdir = pget_wdfile();
}
else if((strncmp(dirname,homedir,hdlen) == 0) &&
((*(dirname+hdlen) == '/') || (*(dirname+hdlen) == '\0'))&&
(p_uln_index(dirname+hdlen,':') == 0)) {
dirname = dirname + hdlen;
if(*dirname == '/') dirname++;
relativeto = 1;
dirhst = pget_hdhost();
remdir = pget_hdfile();
}
}
else flags &= (~ RVD_NOCACHE);
startover:
/* The target of a symbolic link must be an absolute path */
/* from the root of the specified virtual system. Thus */
/* if chasing a link, we skip the code above that checks */
/* for ../s, and ~/s. */
nsname = dirname;
/* If the directory includes :s, find correct namespace */
while(colon = p_uln_index(dirname,':')) {
/* If the vs name is null, return an error */
if(colon == nsname) return(RVD_NS_NOT_FOUND);
/* If an alias, return error. Aliases are only allowed for */
/* the first : and if an alias, it was resolved previously */
if(*(colon-1) == '#') return(RVD_NO_NS_ALIAS);
/* object closure */
if(*(colon+1) == ':') {
*(colon++) = '\0';
colon++;
ltmp = rd_vlink(dirname);
if(!ltmp) return(RVD_NO_CLOSED_NS);
closure = pget_at(ltmp,"CLOSURE");
vllfree(ltmp);
if(!closure) return(RVD_NO_CLOSED_NS);
/* XXX This must change! */
if (closure->avtype != ATR_SEQUENCE) {
atlfree(closure);
return(RVD_NO_CLOSED_NS);
}
if (qsprintf(stmp,sizeof stmp,
"%s:%s",closure->value.sequence->token,colon) >
sizeof stmp)
internal_error("stmp too small!");
atlfree(closure);
strcpy(dirnm,stmp);
dirname = dirnm;
nsname = dirname;
continue;
}
/* text between nsname and colon is name space */
*(colon++) = '\0';
if (sizeof stmp <
qsprintf(stmp, sizeof stmp,
"/VIRTUAL-SYSTEMS/%s/ROOT%s%s",nsname,
((!*colon || (*colon == '/')) ? "" : "/"),colon))
internal_error("stmp too small!");
/* Remember how much text after colon before we overwite dirname */
beyondcolon = strlen(colon);
/* Keep part of dirname that defines root of old namespace */
if((nsname > dirname) && (*(nsname-1) == '/')) *(nsname-1) = '\0';
else *nsname = '\0';
/* And append path to root of new one */
strcat(dirname,stmp);
/* Keep track of the root of the new name space */
nsname = dirname + strlen(dirname) - beyondcolon;
/* Start search from root of active name space */
relativeto = 0;
dirhst = pget_rdhost();
remdir = pget_rdfile();
}
ndname = dirname;
while(*ndname == '/') ndname++; /* multiple slashes treated as one slash */
nextcomp = p_uln_index(ndname,'/');
if(nextcomp) {
*(nextcomp++) = '\0';
if(!*nextcomp) nextcomp = NULL; /* trailing slash ignored. */
}
if(!*ndname) ndname = NULL;
/* If we only want the directory file, and we have a null */
/* dirname (ndname is first component), then we must create */
/* a fictitious directory entry from dirhst and remdir */
if(!ndname && (flags & RVD_DFILE_ONLY)) {
VLINK vl;
char *tmp_wdname = pget_wd(); /* working directory. */
char *s; /* link name */
/* If links remain in dir, free them */
vdir_freelinks(dir);
/* Allocate the pseudo link */
dir->links = vl = vlalloc();
if (!vl) out_of_memory();
/* and fill it in */
vl->host = stcopy(dirhst);
vl->hsoname = stcopy(remdir);
vl->target = stcopyr("DIRECTORY", vl->target);
/* Set a NAME field of some sort. */
if (tmp_wdname && *tmp_wdname) {
char *sp = p_uln_rindex(tmp_wdname, '/'); /* slashptr */
char *cp = p_uln_rindex(tmp_wdname, ':'); /* colonptr */
char *lastwdcomp; /* last comp in tmp_wdname */
s = ((cp < sp) ? sp : cp) + 1;
if (s && *s) vl->name = stcopyr(s, vl->name);
else vl->name = stcopyr(tmp_wdname, vl->name);
} else if (s = strrchr(remdir, '/')) {
vl->name = stcopyr(s, vl->name);
} else {
vl->name = stcopyr(remdir, vl->name);
}
}
while(ndname) {
TOKEN nextcomp_tkl; /* Token list form of nextcomp variable;
a temporary var. */
TOKEN thiscomp_tkl; /* used to convert quoted component strings to
normal format. */
VLINK dlink = vlalloc();
dlink->host = stcopyr(dirhst, dlink->host);
dlink->hsoname = stcopyr(remdir, dlink->hsoname);
dlink->filters = flcopy(filters, 1);
/* Check for magic number */
magic_no = 0;
magic_str = p_uln_rindex(ndname,'#');
/* Make sure that the rest of magic str is digits */
if(magic_str && *(magic_str + 1) &&
(strspn(magic_str+1,"-0123456789") == strlen(magic_str+1))) {
*(magic_str++) = '\0';
sscanf(magic_str,"%d",&magic_no);
}
/* Find out if there is a # in any remaining components */
/* and if so, don't reolve multiple components */
if(nextcomp && p_uln_index(nextcomp,'#')) poundsign = 1;
else poundsign = 0;
intflags = (magic_no ? GVD_LREMEXP : GVD_FIND);
if((*ndname == '#')&&(*(ndname+1))) {
intflags = GVD_UNION;
poundsign = 1;
}
/* if((flags & RVD_DFILE_ONLY) && (flags & RVD_ATTRIB)) */
/* intflags |= GVD_ATTRIB; */
/* It might not be a directory in which case we want the */
/* attributes */
if(flags & RVD_ATTRIB) intflags |= GVD_ATTRIB;
if ((*ndname != '#') || (!*(ndname + 1))) {
thiscomp_tkl = p__rvdslashpath2tkl(ndname);
assert(thiscomp_tkl && !thiscomp_tkl->next);
} else
thiscomp_tkl = NULL;
if (!magic_no && !poundsign) {
nextcomp_tkl = p__rvdslashpath2tkl(nextcomp);
retval = p_get_dir(dlink,
thiscomp_tkl? thiscomp_tkl->token : (char *)NULL,
dir, intflags, &nextcomp_tkl);
p__tkl_back_2rvdslashpath(nextcomp_tkl, nextcomp);
tklfree(nextcomp_tkl);
} else {
retval = p_get_dir(dlink,
thiscomp_tkl? thiscomp_tkl->token : (char *)NULL,
dir, intflags, NULL);
}
if (thiscomp_tkl) tklfree(thiscomp_tkl);
if(retval) {
vlfree(dlink);
if (retval == DIRSRV_NOT_DIRECTORY) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Directory %s not found.",ndname);
return(PFS_DIR_NOT_FOUND);
}
else return(retval);
}
if(*ndname == '#' && *(ndname+1)) {
vllfree(dir->links);
dir->links = dir->ulinks;
dir->ulinks = NULL;
while(dir->links && (strcmp(dir->links->name,ndname+1) != 0)) {
ltmp = dir->links;
dir->links = dir->links->next;
vlfree(ltmp);
}
}
/* Find the one with the correct magic number. */
/* We can get rid of those that don't match */
if(dir->links && magic_no && (magic_no != dir->links->f_magic_no)){
ltmp = dir->links->replicas;
while(ltmp && (ltmp->f_magic_no != magic_no)) {
dir->links->replicas = ltmp->next;
vlfree(ltmp);
ltmp = dir->links->replicas;
}
/* found it, replace primary link */
if(ltmp) {
ltmp->replicas = ltmp->next;
if(ltmp->replicas) ltmp->replicas->previous = NULL;
ltmp->next = dir->links->next;
ltmp->previous = dir->links->previous;
dir->links->replicas = NULL;
vlfree(dir->links);
dir->links = ltmp;
}
/* Otherwise get rid of primary link */
else {
ltmp = dir->links;
dir->links = ltmp->next;
vlfree(ltmp);
dir->links->previous = NULL;
}
}
/* Can't find next directory link */
if(dir->links == NULL) {
p_err_string = qsprintf_stcopyr(p_err_string,
"Directory %s not found.",ndname);
/* If unexpanded ulinks, return temporary error */
ltmp = dir->ulinks;
while(ltmp) {
if(ltmp->expanded != TRUE) {
vlfree(dlink);
return(RVD_DIR_NOT_THERE);
}
ltmp = ltmp->next;
}
vlfree(dlink);
return(PFS_DIR_NOT_FOUND);
}
/* If a symbolic link, expand it */
if((strncmp(dir->links->target,"SYMBOLIC",8) == 0) &&
(strncmp(dir->links->hosttype,"VIRTUAL-SYSTEM",14) == 0)) {
if(depth-- > 0) {
sprintf(stmp,"%s:%s",dir->links->host,
dir->links->hsoname);
if(nextcomp && !*nextcomp) nextcomp = NULL;
while(ndname = nextcomp) {
nextcomp = p_uln_index(ndname,'/');
if(nextcomp) {
*(nextcomp++) = '\0';
if(*nextcomp == '\0') nextcomp = NULL;
}
strcat(stmp,"/");
strcat(stmp,ndname);
}
strcpy(dirnm,stmp);
dirname = dirnm;
vlfree(dlink); /* Goto's considered harmfull! */
goto startover;
}
else {
vlfree(dlink);
return(PFS_SYMLINK_DEPTH);
}
/* NOTREACHED */
assert(0); /* should never get here. */
}
/* found next directory - update dirhost and remdir - continue */
dirhst = dir->links->host;
remdir = dir->links->hsoname;
filters = dir->links->filters;
/* remove the next line */
dir->links->filters = NULL;
/* Find the next component of the path name */
if(nextcomp && !*nextcomp) nextcomp = NULL;
ndname = nextcomp;
if(ndname) {
nextcomp = p_uln_index(ndname,'/');
if(nextcomp) {
*(nextcomp++) = '\0';
if(*nextcomp == '\0') nextcomp = NULL;
}
}
/* If more components, and not a real link, then */
/* return an error */
if (ndname && (strcmp(dir->links->target,"DIRECTORY") != 0) &&
(strcmp(dir->links->target,"FILE") != 0)) {
/* Ooops - Release does vlfree but not return, good
reason to bracket EVERY if - Mitra */
vlfree(dlink);
return (PFS_EXT_USED_AS_DIR);
}
vlfree(dlink); /* For drop-thru or loop */
} /*while */
/* if magic number specified, chop it off before making request */
magic_no = 0;
magic_str = p_uln_rindex(components,'#');
/* Make sure that the rest of magic str is digits */
if(magic_str && *(magic_str + 1) &&
(strspn(magic_str+1,"-0123456789") == strlen(magic_str+1))) {
*(magic_str++) = '\0';
sscanf(magic_str,"%d",&magic_no);
/* If alternate version specified, don't stop looking */
if(flags & GVD_FIND) flags = (flags & (~GVD_FIND)) | GVD_LREMEXP;
}
/* If a normal link, then we do a listing of the */
/* directory. If not a directory, then get_vidr */
/* will fail We will pass through the error code */
/* Dir will contain the single directory link */
/* corresponding to the file */
if(!dir->links || (strcmp(dir->links->target,"DIRECTORY") == 0) ||
(strcmp(dir->links->target,"FILE") == 0)) {
VLINK dlink = vlalloc();
dlink->host = stcopyr(dirhst, dlink->host);
dlink->hsoname = stcopyr(remdir, dlink->hsoname);
dlink->filters = flcopy(filters, 1);
retval = p_get_dir(dlink,components,dir,flags, NULL);
/* Find the one with the correct magic number. */
/* We can get rid of those that don't match */
/* This code is not applicable for all flags combos */
if(dir->links && magic_no && (magic_no != dir->links->f_magic_no)){
ltmp = dir->links->replicas;
while(ltmp && (ltmp->f_magic_no != magic_no)) {
dir->links->replicas = ltmp->next;
vlfree(ltmp);
ltmp = dir->links->replicas;
}
/* found it, replace primary link */
if(ltmp) {
ltmp->replicas = ltmp->next;
if(ltmp->replicas) ltmp->replicas->previous = NULL;
ltmp->next = dir->links->next;
ltmp->previous = dir->links->previous;
dir->links->replicas = NULL;
vlfree(dir->links);
dir->links = ltmp;
}
/* Otherwise get rid of primary link */
else {
ltmp = dir->links;
dir->links = ltmp->next;
vlfree(ltmp);
dir->links->previous = NULL;
}
}
vlfree(dlink);
return(retval);
}
else return(DIRSRV_NOT_DIRECTORY);
}
/* These are not thread safe */
static int oldpathlen;
#ifndef NDEBUG /* for assertions */
static char *oldnextcomp;
#endif
static
TOKEN
p__rvdslashpath2tkl(char *nextcomp)
{
TOKEN retval = NULL;
char *cp;
char thiscomp[MAX_VPATH]; /* buffer for current comp. strip backslashes.
*/
char *thisp = thiscomp;
assert(P_IS_THIS_THREAD_MASTER());
oldpathlen = 0;
#ifndef NDEBUG
oldnextcomp = nextcomp;
#endif
if (!nextcomp) return NULL;
for (cp = nextcomp; *cp; cp++) {
if (*cp == '/') {
*thisp = '\0';
/* Skip multiple slashes (as rd_vdir() does.) */
if (thisp > thiscomp) {
++oldpathlen;
retval = tkappend(thiscomp, retval);
thisp = thiscomp; /* set for next */
}
continue;
} else if (*cp == '\\') {
++cp;
if (*cp == '\0') --cp; /* special case trailing \; treat it as a
literal backslash. */
}
*thisp++ = *cp; /* process quoted and literal characters */
}
/* Handle the last component. Skip trailing slashes. (as rd_vdir does). */
*thisp = '\0';
if (thisp > thiscomp) {
++oldpathlen;
retval = tkappend(thiscomp, retval);
}
return retval;
}
/* Should only be called when p__rvdslashpath2tkl was called. */
static
void
p__tkl_back_2rvdslashpath(TOKEN nextcomp_tkl, char *nextcomp)
{
char buf[MAX_VPATH];
/* Make sure the functions were called in the proper order. This assertion
helps make sure we don't write too much back into the old nextcomp
buffer. */
assert(P_IS_THIS_THREAD_MASTER());
assert(oldnextcomp == nextcomp);
*buf = '\0';
/* Optimize common case (no change). */
if (oldpathlen == length(nextcomp_tkl))
return;
assert(oldpathlen > length(nextcomp_tkl)); /* sanity */
for(; nextcomp_tkl; nextcomp_tkl = nextcomp_tkl->next) {
strcat(buf, nextcomp_tkl->token);
strcat(buf, "/");
}
assert(strlen(buf) <= strlen(nextcomp));
strcpy(nextcomp, buf);
}

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

@@ -0,0 +1,129 @@
/*
* Copyright (c) 1989, 1990 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 <stdio.h>
#include <string.h>
#include <pfs.h>
#include <perrno.h>
#include <pmachine.h>
static VLINK rd_vslink();
/*
* rd_vlink will read the named link, expanding any symbolic links
* along the way. Call rd_slink if you do not want to expand the
* final sym_link.
*/
VLINK
rd_vlink(const char *path)
{
return(rd_vslink(path,SYMLINK_NESTING));
}
/*
* rd_slink will read the named link, returing the result without
* expansion, even if the result is a symbolic link.
*/
VLINK
rd_slink(const char *path)
{
return(rd_vslink(path,-1));
}
extern char *p_uln_lastcomp_to_linkname(const char *s);
static VLINK
rd_vslink(path,depth)
const char *path; /* Pathname for links to be returned */
int depth; /* How many levels of sym links to expand */
{
char pth[MAX_VPATH]; /* Working copy of pathname */
char *p = pth; /* So we can use it as a pointer */
char *c; /* Component part of name */
char *d; /* Directory part of name */
char *slash; /* Position of slash */
char *colon; /* Position of colon */
int flags;
VDIR_ST dir_st;
VDIR dir = &dir_st;
VLINK v;
vdir_init(dir);
/* special case just a . as a name for the current working directory,
by mapping it onto the empty string. . */
if (strequal(path, ".")) ++path;
strcpy(p,path);
d = p;
slash = p_uln_rindex(p,'/');
colon = p_uln_rindex(p,':');
if(colon && (!slash || (colon > slash))) {
*(colon + 1) = '\0';
c = p_uln_lastcomp_to_linkname(p_uln_rindex(path,':') + 1);
}
else if(slash) {
if(slash == p) d = "/";
*slash = '\0';
c = p_uln_lastcomp_to_linkname(slash + 1);
}
else if (strequal(path, "..")) {
/* Special case just .. as a name for the superior directory. */
d = "..";
c = NULL;
} else {
d = "";
c = p_uln_lastcomp_to_linkname(p);
}
if(c && *c) flags = RVD_FIND;
else flags = RVD_DFILE_ONLY;
perrno = rd_vdir(d,c,dir,flags);
if(perrno || !dir->links) {
if (!perrno) perrno = PFAILURE;
vllfree(dir->links);
vllfree(dir->ulinks);
return(NULL);
}
vllfree(dir->ulinks);
if((strncmp(dir->links->target,"SYMBOLIC",8) == 0) &&
(strncmp(dir->links->hosttype,"VIRTUAL-SYSTEM",14) == 0)) {
if(depth > 0) {
if (sizeof pth <
qsprintf(pth, sizeof pth,
"/VIRTUAL-SYSTEMS/%s/ROOT%s%s",dir->links->host,
((*(dir->links->hsoname) == '/') ? "" : "/"),
dir->links->hsoname))
internal_error("pth too small!");
v = rd_vslink(pth,depth-1);
vllfree(dir->links);
if (!perrno) perrno = PFAILURE;
return(v);
}
else if(depth == 0) {
vllfree(dir->links);
perrno = PFS_SYMLINK_DEPTH;
return(NULL);
} /* depth < 0 means don't expand symlink. */
}
return(dir->links);
}

View File

@@ -0,0 +1,51 @@
/*
* 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>
#ifdef PFS_THREADS
extern p_th_mutex p_th_mutexREGEX;
#endif
/* This routine combines RE_COMP and RE_EXEC in an appropriate thread-safe
interface. It currently operates by mutexing the use of the regex package.
It will later be revised to take advantage of thread-safe library calls,
as they become available in standard system libraries. If you need
to do multithreaded matches right now, then you could do so by using the
routine in misc/regex.c.
This can also be linked with the versions of re_comp() and re_exec() that
your system library provides; Prospero will do this by default.
*/
/*
* Returns zero if successfully compiled and matched.
* Returns 1 if not.
* This is probably inefficient, since we always compile, even in the common
* case where the pattern string has not changed. Need to rethink this at
* a later date. (but not right now.)
*/
int
p__re_comp_exec(char *temp, char *s)
{
int retval;
p_th_mutex_lock(p_th_mutexREGEX);
if(re_comp(temp)) {
/* There should be a way to pass this error information up to the
caller,but we don't have one right now. Need to look at this again
later. */
retval= 0;
} else {
/* -1 is internal error for re_exec(). 1 is match. 0 is failure to
match. */
retval = (re_exec(s) > 0);
}
p_th_mutex_unlock(p_th_mutexREGEX);
return(retval);
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 1989, 1990 by the University of Washington
*
* For copying and distribution information, please see the file
* <uw-copyright.h>.
*/
#include <uw-copyright.h>
#include <stdio.h>
#include <string.h>
#include <pfs.h>
#include <pmachine.h>
/*
* readheader will read the f until it comes across a line with
* header whose name ends in h. It will then return the next token
* on the same line.
*
* IMPORTANT: The returned value is static. It must be copied if it is
* to be used after the next call to readheader.
*
* BUGS: The present implementation only looks for the first occurance of the
* last character in h. This may cause problems if the character is not
* unique. Ideally it should be something like a ":".
*/
char *readheader(f,h)
FILE *f;
char *h;
{
static char hv[MAX_VPATH];
char temp[MAX_VPATH+40];
char *p;
int hl = strlen(h); /* Length of h */
char *he = h + hl - 1; /* Last char in h */
assert(P_IS_THIS_THREAD_MASTER());
while(fgets(temp,sizeof(temp),f)) {
/* Note, for now, we only check the first occurance of */
/* the last character. It had better be a uniqe one */
/* such as a ":". */
if(p = strchr(temp + hl - 1, *he)) {
if(strcncmp(p-hl+1,h,hl) == 0) {
sscanf(++p,"%s",hv);
return(hv);
}
}
}
return(NULL);
}

View File

@@ -0,0 +1,137 @@
/*
* 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 <stdio.h>
#include <string.h>
#include <pfs.h>
#include <perrno.h>
char *p_motd = NULL; /* motd is read here. */
static void fix_server_might_append_null_to_packet(RREQ req);
int
scan_error(char *erst, RREQ req)
{
p_clear_errors();
if (strequal(erst, "SUCCESS"))
return PSUCCESS;
#ifdef CLIENTS_REQUEST_VERSION_FROM_SERVER
if (qsscanf(erst, "VERSION %*d %&s", &req->peer_sw_id) == 1) {
#ifdef SERVER_MIGHT_APPEND_NULL_TO_PACKET
if (req->peer_sw_id && (strnequal(req->peer_sw_id, "A50", 3) ||
strnequal(req->peer_sw_id, "A51", 3) ||
strnequal(req->peer_sw_id, "B51", 3) ||
strnequal(req->peer_sw_id, "A52", 3)))
fix_server_might_append_null_to_packet(req);
#endif
return PSUCCESS;
}
#endif
if(strncmp(erst,"VERSION-NOT-SUPPORTED",21) == 0) {
qsscanf(erst,"%'&[^\n]",&p_err_string);
return perrno = DIRSRV_BAD_VERS;
}
if(strncmp(erst,"WARNING ",8) == 0) {
erst += 8;
*p_warn_string = '\0';
qsscanf(erst,"%~%*[^\n \t\r]%~%'&[^\n\r]",
&p_warn_string);
/* Return values for warnings are negative */
if(strncmp(erst,"OUT-OF-DATE",11) == 0) {
pwarn = PWARN_OUT_OF_DATE;
return(PSUCCESS);
}
if(strncmp(erst,"MESSAGE",7) == 0) {
pwarn = PWARN_MSG_FROM_SERVER;
return(PSUCCESS);
}
pwarn = PWARNING;
qsscanf(erst,"%'&[^\n]",&p_warn_string);
return(PSUCCESS);
}
else if(strncmp(erst,"ERROR",5) == 0) {
if(*(erst+5))
qsscanf(erst+6,"%'&[^\n\r]",&p_err_string);
perrno = DIRSRV_ERROR;
return(perrno);
}
else if (strnequal(erst, "PARAMETER", 9)) {
qsscanf(erst, "PARAMETER%~VALUE%*( \t)MOTD%*( \t)%'&s",
&p_motd);
/* It doesn't matter whether we successfully read in a value
for p_motd, since we return SUCCESS anyway, and since
p_motd is initialized to the empty string. */
return PSUCCESS;
}
/* FAILURE on a line by itself. */
else if (strequal(erst, "FAILURE")) return perrno = PFAILURE;
/* The rest start with "FAILURE " */
else if(!strnequal(erst,"FAILURE ", 8)) {
/* Unrecognized Protocol message - Give warning, but return PSUCCESS */
if(pwarn == 0) {
*p_warn_string = '\0';
pwarn = PWARN_UNRECOGNIZED_RESP;
qsscanf(erst,"%'&[^\n\r]", &p_warn_string);
}
return(PSUCCESS);
}
erst += 8;
qsscanf(erst,"%*[^\n \t\r]%*[ \t]%&'[^\n\r]", &p_err_string);
/* Still to add */
/* DIRSRV_AUTHENT_REQ 242 */
/* DIRSRV_BAD_VERS 245 */
if(strncmp(erst,"NOT-FOUND",9) == 0)
perrno = DIRSRV_NOT_FOUND;
else if(strncmp(erst,"NOT-FOUND",9) == 0)
perrno = DIRSRV_NOT_FOUND;
else if(strncmp(erst,"NOT-AUTHORIZED",13) == 0)
perrno = DIRSRV_NOT_AUTHORIZED;
else if(strncmp(erst,"ALREADY-EXISTS",14) == 0)
perrno = DIRSRV_ALREADY_EXISTS;
else if(strncmp(erst,"NAME-CONFLICT",13) == 0)
perrno = DIRSRV_NAME_CONFLICT;
else if(strncmp(erst,"TOO-MANY",8) == 0)
perrno = DIRSRV_TOO_MANY;
else if(strncmp(erst,"SERVER-FAILED",13) == 0)
perrno = DIRSRV_SERVER_FAILED;
else if(strncmp(erst,"UNIMPLEMENTED",13) == 0) {
perrno = DIRSRV_UNIMPLEMENTED;
} else if(strncmp(erst,"NOT-A-DIRECTORY",15) == 0)
perrno = DIRSRV_NOT_DIRECTORY;
else perrno = PFAILURE;
return perrno;
}
#ifdef SERVER_MIGHT_APPEND_NULL_TO_PACKET
/* This allows clients to fix output they get from the 5.0, 5.1, and 5.2
servers. */
static
void
fix_server_might_append_null_to_packet(RREQ req)
{
PTEXT pt = req->rcvd;
for ( ; pt; pt = pt->next) {
/* If the packet has a text area with at least one character in it */
if ((pt->start + pt->length - pt->text > 0)
/* and that character is ASCII NUL */
&& (pt->start[pt->length - 1] == '\0')) {
--pt->length; /* get rid of it (shorten the packet by 1) */
}
}
}
#endif

45
prospero/lib/pfs/sindex.c Normal file
View File

@@ -0,0 +1,45 @@
/*
* 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 <stdio.h>
#include <string.h>
#include <pmachine.h>
#include <pfs.h>
/*
* sindex - Find first instance of string 2 in string 1
*
* SINDEX scans string 1 for the first instance of string
* 2. If found, SINDEX returns a pointer to the first
* character of that instance. If no instance is found,
* SINDEX returns NULL (0).
*
* ARGS: s1 - string to be searched
* s2 - string to be found
* RETURNS: First instance of s2 in s1, or NULL (0) if not found
*/
const char *
sindex(const char *s1 /* String to be searched */,
const char *s2 /* String to be found */)
{
const char *s = s1; /* Temp pointer to string */
/* Check for first character of s2 */
while((s = strchr(s,*s2)) != NULL) {
if(strncmp(s,s2,strlen(s2)) == 0)
return(s);
s++;
}
/* We didn't find it */
return(NULL);
}

View File

@@ -0,0 +1,72 @@
/*
* 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>
static int oldpathlen;
#ifndef NDEBUG /* for assertions */
static char *oldnextcomp;
#endif
TOKEN
p__slashpath2tkl(char *nextcomp)
{
TOKEN retval = NULL;
char *cp;
assert(P_IS_THIS_THREAD_MASTER());
oldpathlen = 0;
#ifndef NDEBUG
oldnextcomp = nextcomp;
#endif
if (!nextcomp) return NULL;
for (cp = nextcomp; *cp; cp++) {
if (*cp == '/') {
if (cp == nextcomp)
/* eliminate double-slashes */
++nextcomp;
else {
*cp = '\0';
++oldpathlen;
retval = tkappend(nextcomp, retval);
*cp = '/'; /* restore it */
nextcomp = cp + 1;
}
}
}
/* Handle the last component. */
if (cp > nextcomp)/* More components. (Path didn't end in a slash). */
tkappend(nextcomp, retval);
return retval;
}
/* Should only be called when p__slashpath2tkl was called. */
void
p__tkl_back_2slashpath(TOKEN nextcomp_tkl, char *nextcomp)
{
char buf[MAX_VPATH];
assert(P_IS_THIS_THREAD_MASTER());
/* Make sure the functions were called in the proper order. This assertion
helps make sure we don't write too much back into the old nextcomp
buffer. */
assert(oldnextcomp == nextcomp);
*buf = '\0';
/* Optimize common case (no change). */
if (oldpathlen == length(nextcomp_tkl))
return;
assert(oldpathlen > length(nextcomp_tkl)); /* sanity */
for(; nextcomp_tkl; nextcomp_tkl = nextcomp_tkl->next) {
strcat(buf, nextcomp_tkl->token);
strcat(buf, "/");
}
assert(strlen(buf) <= strlen(nextcomp));
strcpy(nextcomp, buf);
}

View File

@@ -0,0 +1,28 @@
/*
* 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>
/* Used by ARCHIE database code to convert slashpath to token lists.
We can use the same regular p__slashpath2tkl to convert back. */
/* Jan 10, 1994: I believe this code is now vestigial. If it isn't, it must
be rewritten. */
char *
p__tkl_2slashpath(TOKEN nextcomp_tkl)
{
char buf[MAX_VPATH];
assert("p__tkl_2slashpath() must be rewritten.");
*buf = '\0';
for(; nextcomp_tkl; nextcomp_tkl = nextcomp_tkl->next) {
strcat(buf, nextcomp_tkl->token);
strcat(buf, "/");
}
return buf;
}

223
prospero/lib/pfs/socket.c Normal file
View File

@@ -0,0 +1,223 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
/* These routines are pulled from lib/psrv/gopher_gw/goph_gw_dsdb.c
and user/vcache/gopherget.c since they are common to both*/
#include <usc-license.h>
#include <netdb.h> /* Must be before pmachine.h */
#include <pfs.h>
#include <pmachine.h>
#include <errno.h>
#include <perrno.h>
#include <posix_signal.h>
#include <setjmp.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pfs_threads.h>
#include <sockettime.h>
#ifdef TIMEOUT_APPROACH
EXTERN_TYPEP_DEF(jmp_buf, Jmpenv);
#define Jmpenv p_th_arJmpenv[p__th_self_num()]
static void
reprimeAlarm(int oldalarm, SIGNAL_RET_TYPE(*oldintr)())
{
if (signal(SIGALRM, oldintr) == SIG_ERR)
perror("signal died:"), exit(-1);
alarm(oldalarm);
}
/* These are probably not used, can remove if usefull for threading */
EXTERN_INT_DEF(syscall_oldalarmtime); /* Save old alarm time */
#define syscall_oldalarmtime p_th_arsyscall_oldalarmtime[p__th_self_num()]
/* SIGNAL_RET_TYPE (*syscall_oldintr)();*/ /* Old signal */
EXTERN_TYPEP_DEF(void *,syscall_oldintr); /* Old signal */
#define syscall_oldintr p_th_arsyscall_oldintr[p__th_self_num()]
static SIGNAL_RET_TYPE
alarmJmp(int sig)
{
reprimeAlarm(syscall_oldalarmtime,syscall_oldintr);
longjmp(Jmpenv,1);
}
#endif /*TIMEOUT_APPROACH*/
#ifdef SELECT_APPROACH
int
wait_till_stream_readable(FILE *str, int timeout)
{
if (str->_cnt > 0) return 1;
return (wait_till_readable(fileno(str),timeout));
}
#endif /*SELECT_APPROACH*/
/* This is adapted from interruptable_connect in gopher */
int
quick_connect(int s, struct sockaddr *name, int namelen, int timeout)
{
int retval;
#ifdef TIMEOUT_APPROACH
syscall_oldalarmtime = alarm(timeout);
if ((syscall_oldintr = signal(SIGALRM, alarmJmp)) == SIG_ERR)
perror("signal died:\n"), exit(-1);
if (setjmp(Jmpenv)) {
/* Note alarmJmp will reprime alarm*/
errno = ETIMEDOUT;
return(-1);
}
#endif
while ( (((retval = connect(s, name, namelen)) == -1)
&& (errno == EINTR)));
#ifdef TIMEOUT_APPROACH
reprimeAlarm(syscall_oldalarmtime,syscall_oldintr);
#endif
return retval;
}
int
quick_read(int fd, char *nptr, int nbytes, int timeout)
{
int retval;
#ifdef TIMEOUT_APPROACH
syscall_oldalarmtime = alarm(timeout);
if ((syscall_oldintr = signal(SIGALRM, alarmJmp)) == SIG_ERR)
perror("signal died:\n"), exit(-1);
if (setjmp(Jmpenv)) {
/* Note alarmJmp will reprime alarm*/
errno = ETIMEDOUT;
return(-1);
}
#endif /*TIMEOUT_APPROACH*/
#ifdef SELECT_APPROACH
switch (wait_till_readable(fd,timeout)) {
case -1: p_err_string = qsprintf_stcopyr(p_err_string,
"INTERNAL: read select failed: %s", unixerrstr());
return NULL;
case 0: p_err_string = qsprintf_stcopyr(p_err_string,
"Waited more than %d secs for response", timeout);
return NULL;
}
/* Default is going to be 1 - which is success */
#endif /*SELECT_APPROACH*/
retval = read(fd, nptr, nbytes); /* socket or -1 */
#ifdef TIMEOUT_APPROACH
reprimeAlarm(syscall_oldalarmtime,syscall_oldintr);
#endif
return retval;
}
char *
quick_fgets(char *s, int n, FILE *stream, int timeout)
/* Do a fgets, with opportunity for timeout handling, depending on system
same return code as fgets, but can return NULL (and not set error)
in some circumstances */
{
char *retval;
#ifdef TIMEOUT_APPROACH
syscall_oldalarmtime = alarm(timeout);
if ((syscall_oldintr = signal(SIGALRM, alarmJmp)) == SIG_ERR)
perror("signal died:\n"), exit(-1);
if (setjmp(Jmpenv)) {
/* Note alarmJmp will reprime alarm*/
errno = ETIMEDOUT;
return(NULL);
}
#endif
#ifdef SELECT_APPROACH
switch (wait_till_stream_readable(stream,timeout)) {
case -1: p_err_string = qsprintf_stcopyr(p_err_string,
"INTERNAL: read select failed: %s", unixerrstr());
return NULL;
case 0: p_err_string = qsprintf_stcopyr(p_err_string,
"waited more than %d secs for a response", timeout);
errno = ETIMEDOUT;
return NULL;
}
/* Default is going to be 1 - which is success */
#endif /*SELECT_APPROACH*/
retval = fgets(s, n, stream);
#ifdef SELECT_APPROACH
/* fgets can retunr an incomplete line, since it is non-blocking */
if (retval) {
int buflen = strlen(s);
if ((s[buflen -1 ] != '\n') && (n-1 > buflen)) {
retval = quick_fgets(s+buflen, n-buflen, stream, timeout);
}
}
#endif /*SELECT_APPROACH*/
#ifdef TIMEOUT_APPROACH
reprimeAlarm(syscall_oldalarmtime,syscall_oldintr);
#endif
return retval;
}
#if 0
int
quick_fgetc(FILE *stream, int timeout)
{
int retval;
#ifdef TIMEOUT_APPROACH
syscall_oldalarmtime = alarm(timeout);
if ((syscall_oldintr = signal(SIGALRM, alarmJmp)) == SIG_ERR)
perror("signal died:\n"), exit(-1);
if (setjmp(Jmpenv)) {
/* Note alarmJmp will reprime alarm*/
errno = ETIMEDOUT;
return(EOF);
}
#endif
#ifdef SELECT_APPROACH
switch (wait_till_stream_readable(stream,timeout)) {
case -1: p_err_string = qsprintf_stcopyr(p_err_string,
"INTERNAL: quick_fgetc: select failed: %s", unixerrstr());
return EOF;
case 0: p_err_string = qsprintf_stcopyr(p_err_string,
"waited more than %d secs for a response", timeout);
errno = ETIMEDOUT;
return EOF;
}
/* Default is going to be 1 - which is success */
#endif /*SELECT_APPROACH*/
retval = getc(stream);
#ifdef TIMEOUT_APPROACH
reprimeAlarm(syscall_oldalarmtime,syscall_oldintr);
#endif
return retval;
}
#endif
int quick_fgetc (FILE *stream, int timeout)
{
char c[2];
char *retval;
if (!(retval = quick_fgets(c, 2, stream, timeout))) {
/* errno set in quick_fgets */
return EOF;
}
return c[0];
}

49
prospero/lib/pfs/stat.c Normal file
View File

@@ -0,0 +1,49 @@
/*
* 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>
/* Stuff that handles stat, scrounged from other places */
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <pfs.h> /* for prototypes for these functions */
/* Stat and get a modification time. Returns 0 upon failure. */
extern time_t
mtime(const 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? */
extern int
is_dir(const 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;
}
/* Return age of file in seconds -1 on failure*/
int
stat_age(const char *path) {
time_t then;
return ((then = mtime(path)) ? time((time_t *) 0)-then : -1);
}

211
prospero/lib/pfs/stcopy.c Normal file
View File

@@ -0,0 +1,211 @@
/*
* 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 <string.h>
#include <ardp.h> /* For ALLOCATOR_CONSISTENCY_CHECK */
#include <pfs.h> /* for defs. of functions in this file. */
#include <stdlib.h> /*SOLARIS: for malloc, free etc*/
/* #define DREADFUL_TEMPORARY_HACK_TO_FIX_URGENT_CRASH_5_16_94 *//* my fault --swa */
/* See pfs.h for discussion of the string format we use and for macros that
manipulate it. . */
int string_count = 0;
int string_max = 0;
/*
* stcopy - allocate space for and copy a string
*
* STCOPY takes a string as an argument, allocates space for
* a copy of the string, copies the string to the allocated space,
* and returns a pointer to the copy.
* Cannot fail - calls out_of_memory
*/
char *
stcopy(const char *st)
{
return(stcopyr(st,(char *)0));
}
/*
* stcopyr - copy a string allocating space if necessary
*
* STCOPYR takes a conventional string, S, as an argument, and a pointer to
* a second string, R, which is to be replaced by S. If R is long enough
* to hold S, S is copied. Otherwise, new space is allocated, and R is
* freed. S is then copied to the newly allocated space. If S is
* NULL, then R is freed and NULL is returned.
*
* In any event, STCOPYR returns a pointer to the new copy of S,
* or a NULL pointer.
*/
char *
stcopyr(const char *s, char *r)
{
int sl;
int rl;
CHECK_MEM();
assert(p__bst_consistent(r));
if(!s && r) {
stfree(r);
return(NULL);
}
else if (!s) return(NULL);
sl = strlen(s) + 1;
if(r) {
rl = p__bstsize(r);
if(rl < sl) {
stfree(r);
r = (char *) malloc(sl + p__bst_header_sz);
/* Check for out of memory. not too cool, but better than segfaulting. */
if (!r) out_of_memory();
string_count++;
r += p__bst_header_sz;
p__bst_size_fld(r) = sl;
p__bst_length_fld(r) = P__BST_LENGTH_NULLTERMINATED;
#ifdef P_ALLOCATOR_CONSISTENCY_CHECK
p__bst_consistency_fld(r) = P__INUSE_PATTERN;
#endif
}
}
else {
r = (char *) malloc(sl + p__bst_header_sz);
if (!r) out_of_memory();
string_count++;
r += p__bst_header_sz;
p__bst_size_fld(r) = sl;
p__bst_length_fld(r) = P__BST_LENGTH_NULLTERMINATED;
#ifdef P_ALLOCATOR_CONSISTENCY_CHECK
p__bst_consistency_fld(r) = P__INUSE_PATTERN;
#endif
if(string_max < string_count) string_max = string_count;
}
strcpy(r,s);
return(r);
}
/*
* stalloc - Allocate space for a string
*
* STALLOC allocates space for a string by calling malloc.
* STALLOC guarantees never to honor requests for zero or fewer bytes of
* memory.
*/
char *
stalloc(int size)
{
void *st;
if (size <= 0) return NULL;
st = (void *) malloc(size + p__bst_header_sz);
if(!st) out_of_memory();
string_count++;
st += p__bst_header_sz;
p__bst_size_fld(st) = size;
#ifdef ALLOCATOR_CONSISTENCY_CHECK
p__bst_consistency_fld(st) = INUSE_PATTERN;
#endif
p__bst_length_fld(st) = P__BST_LENGTH_NULLTERMINATED;
if(string_max < string_count) string_max = string_count;
return(st);
}
/*
* stfree - free space allocated by stcopy or stalloc
*
* STFREE takes a string that was returned by stcopy or stalloc
* and frees the space that was allocated for the string.
*/
void
stfree(void *st)
{
#ifndef DREADFUL_TEMPORARY_HACK_TO_FIX_URGENT_CRASH_5_16_94 /* my fault --swa */
assert(p__bst_consistent(st));
#else
if (!p__bst_consistent(st))
return;
#endif
if(st) {
#ifdef ALLOCATOR_CONSISTENCY_CHECK
p__bst_consistency_fld(st) = FREE_PATTERN;
#endif
free(st - p__bst_header_sz);
string_count--;
}
}
/* Take the length of a Prospero bstring. Must be allocated by Prospero. */
int
p_bstlen(const char *s)
{
assert(p__bst_consistent(s));
if (!s) return 0;
else if (p__bst_length_fld(s) == P__BST_LENGTH_NULLTERMINATED)
return strlen(s);
else
return p__bst_length_fld(s);
}
/* Mark the length field of a buffer appropriately, when BUFLEN amount of data
has been read into it. Give preference to using a raw length. */
/* This is what you do after allocating a buffer with stalloc(), and it might
be seen as part of the interface. */
void
p_bst_set_buffer_length_nullterm(char *buf, int buflen)
{
register int i;
assert(p__bst_consistent(buf));
assert(p__bstsize(buf) >= buflen + 1);
for (i = 0; i < buflen; ++i) {
if (buf[i] == '\0') {
/* If a null is present in the data, have to set an explicit
count. */
p__bst_length_fld(buf) = buflen;
goto done;
}
}
p__bst_length_fld(buf) = P__BST_LENGTH_NULLTERMINATED;
done:
buf[buflen] = '\0';
}
void
p_bst_set_buffer_length_explicit(char *buf, int buflen)
{
assert(p__bst_consistent(buf));
assert(p__bst_size_fld(buf) < buflen + 1);
p__bst_length_fld(buf) = buflen;
buf[buflen] = '\0';
}
/* This is called through the CHECK_MEM macro */
void
check_mem()
{
static int check_mem_val = 2000 ; /* Not thread safe, but not a prob */
void *t1;
if (++check_mem_val > 20000)
check_mem_val = 2000;
t1 = malloc(check_mem_val++);
assert(t1);
free(t1);
}

View File

@@ -0,0 +1,23 @@
/* Copyright (c) 1992 -- 1993by the University of Southern California.
* For copying and distribution information, please see the file
* <usc-copyr.h>.
*/
#include <usc-copyr.h>
#include <pfs.h>
/* Equality tester for strings. This is used because there are a number of
places in the Prospero code where string pointersare left set to NULL.
Rather than paranoically guard against all such places, we can just use this
function to test string equality, where appropriate.
*/
int
stequal(const char *s1, const char *s2)
{
if (s1 == s2) /* test for case when both NULL*/
return TRUE;
if (!s1 || !s2) /* Test for case where one is NULL; other is not */
return FALSE;
return strequal(s1, s2);
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 1989, 1990 by the University of Washington
*
* For copying and distribution information, please see the file
* <uw-copyright.h>.
*/
#include <uw-copyright.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define toupper(x) (islower(x) ? (x & 0xdf) : x)
/*
* strccmp - Compare two strings ignoring case
*
* STRCCMP compare two strings ignoring case. It
* returns 0 if the strings are equal, negative is
* string 1 is less than string 2, and positive
* if string 1 is greater than string 2.
* ARGS: s1 - first string
* s2 - second string
*
* RETURNS: +,- or 0 depending on comparison
*/
int
strccmp(s1,s2)
char *s1; /* First String */
char *s2; /* Second String */
{
int tmp;
while ((*s1 != '\0') && (*s2 != '\0')) {
tmp = toupper(*s1) - toupper(*s2);
if(tmp) return (tmp);
s1++; s2++;
}
return(toupper(*s1) - toupper(*s2));
}
/*
* strcncmp - Compare two strings ignoring case and stoping after n chars
*
* STRCCMP compare two strings ignoring case. It
* returns 0 if the strings are equal, negative is
* string 1 is less than string 2, and positive
* if string 1 is greater than string 2.
* ARGS: s1 - first string
* s2 - second string
* n - number of characters to check
*
* RETURNS: +,- or 0 depending on comparison
*/
int
strcncmp(s1,s2,n)
char *s1; /* First String */
char *s2; /* Second String */
int n; /* Number of chars */
{
int tmp;
while ((n-- > 0) && (*s1 != '\0') && (*s2 != '\0')) {
tmp = toupper(*s1) - toupper(*s2);
if(tmp) return (tmp);
s1++; s2++;
}
if(n >= 0) return(toupper(*s1) - toupper(*s2));
return(0);
}

View File

@@ -0,0 +1,39 @@
/*
* 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>
#ifndef NULL
#define NULL 0
#endif
/*
* strpbrk - Find first instance of character from chrs in s
*
* SINDEX scans a string for the first instance of a character
* from chrs. If found, STRPBRK returns a pointer to the
* character in s. If no instance is found STRPBRK returns
* NULL (0).
*
* ARGS: s - string to be searched
* chrs - string of characters we are looking for
* RETURNS: First instance of chrs in s, or NULL (0) if not found
*/
char *
strpbrk(s,chrs)
char *s; /* String to search */
char *chrs; /* String of characters we are looking for */
{
char *cp; /* Pointer to the current character in chrs */
while(*s) {
for(cp = chrs;*cp;cp++)
if(*cp == *s) return(s);
s++;
}
return(NULL);
}

44
prospero/lib/pfs/strspn.c Normal file
View File

@@ -0,0 +1,44 @@
/*
* 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>
/*
* strspn - Count initial characters from chrs in s
*
* STRSPN counts the occurances of chacters from chrs
* in the string s preceeding the first occurance of
* a character not in s.
*
* ARGS: s - string to be checked
* chrs - string of characters we are looking for
*
* RETURNS: Count of initial characters from chrs in s
*/
int
strspn(s,chrs)
char *s; /* String to search */
char *chrs; /* String of characters we are looking for */
{
char *cp; /* Pointer to the current character in chrs */
int count; /* Count of characters seen so far */
count = 0;
while(*s) {
for(cp = chrs;*cp;cp++)
if(*cp == *s) {
s++;
count++;
goto done;
}
return(count);
done:
;
}
return(count);
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 1992, 1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*/
#include <usc-license.h>
/* Written by swa@ISI.EDU, October 2, 1992 */
/* Mutexed, swa@ISI.EDU, November 1993. */
/* Interface changed: swa@ISI.EDU, Feb. 16, 1994 */
/* got rid of appearance of number 22 anywhere here; converted back to
qsprintf: swa, April 20, 1994. */
#include <time.h>
#include <pfs.h>
#include <pfs_threads.h>
/*
* Writes timetoasn() stamp into target.
*/
char *
p_timetoasn_stcopyr(time_t ourtime, char *target)
{
/* This mutexes GMTIME and sprintf. These are the only
problematic cases. */
p_th_mutex_lock(p_th_mutexPFS_TIMETOASN);
{
struct tm *mt = gmtime(&ourtime);
target = qsprintf_stcopyr(target, "%04d%02d%02d%02d%02d%02dZ",
mt->tm_year+1900,mt->tm_mon+1,mt->tm_mday,
mt->tm_hour, mt->tm_min,mt->tm_sec);
}
p_th_mutex_unlock(p_th_mutexPFS_TIMETOASN);
return target;
}

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