9460 lines
256 KiB
Plaintext
9460 lines
256 KiB
Plaintext
$ write sys$output "Unpacking..."
|
||
$ if f$search("archie.dir") .eqs. "" then create/dir [.ARCHIE]
|
||
$ if f$search("[.ARCHIE]vms.dir") .eqs. "" then create/dir [.ARCHIE.VMS]
|
||
$ if f$search("[.ARCHIE]msdos.dir") .eqs. "" then create/dir [.ARCHIE.MSDOS]
|
||
$ set noverify
|
||
$! This is a DCL shar-type archive created by Unix dclshar.
|
||
$!
|
||
$CREATE [.archie]INSTALL
|
||
$DECK
|
||
[Last changed: 04/14/92 v1.3.2]
|
||
|
||
This is the minimal set of things you need to build an Archie client
|
||
that takes advantage of the Prospero system. It is derived from the
|
||
4.2beta version of Prospero, currently available as the file prospero.tar.Z
|
||
on the host cs.washington.edu.
|
||
|
||
* To make the client under Unix:
|
||
* edit the Makefile, changing CC, OPTIONS, LDFLAGS, and RM if
|
||
necessary (odds are you won't have to do this..see below)
|
||
* edit the DEFINEs as necessary
|
||
* if archie.ans.net isn't "close" to you netwise, please edit
|
||
ARCHIE in the Makefile appropriately. This is particularly important
|
||
if you're not in the US. You don't need to touch archie.h anymore.
|
||
* type `make'
|
||
|
||
I've tried to make this as portable as possible. I'd encourage you
|
||
to try doing a "make" without any changes to the Makefile, and see how
|
||
it goes. If it pukes, and you have to define something, please drop
|
||
me a line---my goal is for anybody to just type "make" and not have to
|
||
worry about things like what functions their system supports.
|
||
|
||
* To make the client under VMS, just type @MAKE and it'll ask you
|
||
which of the available Archie servers is closest. That's it!
|
||
|
||
* To make the client under MSDOS or OS/2:
|
||
* with FTP Software's PC/TCP for MSDOS (version 2.1 or higher) and
|
||
OS/2 (version 1.1 and higher), use makefile.os2 or makefile.dos
|
||
* with CUTCP (NCSA telnet), use makefile.cut
|
||
|
||
-- Brendan Kehoe (brendan@cs.widener.edu)
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]Makefile
|
||
$DECK
|
||
#
|
||
# Last changed: 4/14/92, v1.3.2
|
||
#
|
||
# Makefile for the minimal build for an archie Prospero client.
|
||
|
||
# Your C compiler:
|
||
CC=cc
|
||
|
||
# For most systems, these OPTIONS will suffice. Exceptions:
|
||
#
|
||
# * If you're on a Stardent, add -43
|
||
# * If you're running EP/IX, you may need to add -systype bsd43
|
||
# but try it without it first.
|
||
OPTIONS= -O -I. -I/usr/netinclude -I/usr/ucbinclude
|
||
|
||
# For this, DEFINES is usually ok as-is. Try it without any of these
|
||
# first; if some stuff fails or shows up undefined, then come back and
|
||
# add 'em. Also please drop me a line if you had to add anything...ideally
|
||
# things will reach a point where this whole section will be unnecessary.
|
||
#
|
||
# * if you want to include the debugging code (so you
|
||
# can help with problem-solving if any crop up), add -DDEBUG
|
||
# * if you're running Interactive Unix, add -DISC
|
||
# * if you're running System V, add -DSYSV
|
||
# * if you're running a USG (System V.2) system, add -DUSG
|
||
# * if you're running UTS, add -DUTS
|
||
# * if your system doesn't have the functions index(),
|
||
# rindex(), bcopy(), or bzero(), add -DFUNCS
|
||
# * if your system is missing the getenv(3) routine, add -DGETENV
|
||
# * if your system doesn't have the re_comp/regcmp or re_exec/regex
|
||
# routines (no regex(3)/regcmp(3X) library), then add -DNOREGEX
|
||
# * if your system is lacking strspn(), add -DSTRSPN
|
||
DEFINES= -DDEBUG
|
||
|
||
# The default Archie server; choose one of:
|
||
# archie.ans.net (USA [NY])
|
||
# archie.rutgers.edu (USA [NJ])
|
||
# archie.sura.net (USA [MD])
|
||
# archie.unl.edu (USA [NE])
|
||
# archie.mcgill.ca (Canada)
|
||
# archie.funet.fi (Finland/Mainland Europe)
|
||
# archie.au (Australia)
|
||
# archie.doc.ic.ac.uk (Great Britain/Ireland)
|
||
#
|
||
ARCHIE= archie.sura.net
|
||
|
||
# Usually LDFLAGS is empty; if, after you build this, archie
|
||
# complains that it can't resolve ARCHIE.ANS.NET (or whatever
|
||
# you defined ARCHIE_HOST as), you need to add `-lresolv'.
|
||
# * If you need the PW library (e.g. A/UX), add -lPW
|
||
# * If you're using ISC, add -linet
|
||
# * If you're using Wollongong TCP/IP on an AT&T box, use the
|
||
# arguments -lnet -lnsl_s .
|
||
# * If you're using UTS, add -lsocket
|
||
# * If you're using System V Release 4, add -L/usr/ucblib etc.
|
||
LDFLAGS=
|
||
#LDFLAGS= -lresolv
|
||
#LDFLAGS= -lnet -lnsl_s
|
||
#LDFLAGS= -lsocket
|
||
#LDFLAGS= -L/usr/ucblib -lucb -lsockdns -lnsl
|
||
|
||
# Change this if necessary.
|
||
RM=/bin/rm
|
||
|
||
# =========================
|
||
# Yer' done....make archie.
|
||
# =========================
|
||
#
|
||
CFLAGS=$(OPTIONS) $(DEFINES) -DARCHIE_HOST=\"$(ARCHIE)\"
|
||
|
||
VERSION=1.3.2
|
||
VMS_VERSION=`echo $(VERSION) | sed -e 's,\\.,_,g'`
|
||
|
||
OBJS= aquery.o archie.o atalloc.o dirsend.o get_pauth.o get_vdir.o \
|
||
perrmesg.o procquery.o ptalloc.o regex.o stcopy.o support.o \
|
||
vlalloc.o vl_comp.o
|
||
|
||
all: archie
|
||
|
||
archie: $(OBJS)
|
||
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LDFLAGS)
|
||
|
||
$(OBJS): archie.h pmachine.h pcompat.h Makefile
|
||
|
||
procquery.o: copyright.h
|
||
|
||
clean:
|
||
$(RM) -f *.o archie archie.doc
|
||
|
||
gclean: clean
|
||
$(RM) -f *~ archie.0* archie$(VMS_VERSION).com archie.tar* gmon.out archie.doc
|
||
|
||
unx-deadly:
|
||
unifdef -UXARCHIE xprocquery.c > procquery.c
|
||
|
||
udp: udp.o
|
||
$(CC) -o $@ udp.o
|
||
|
||
udptest: udp
|
||
@echo "This should print the date, if UDP's enabled, or hang if not:"
|
||
@./udp
|
||
|
||
FILES= INSTALL Makefile Prospero README README.dos archie.c archie.h \
|
||
archie.lnk archie.doc archie.man aquery.c atalloc.c dirsend.c \
|
||
get_pauth.c get_vdir.c make.com makefile.cut makefile.dos makefile.os2 \
|
||
msdos/cutcp.h msdos/hostform.h msdos/netevent.h \
|
||
perrmesg.c patchlevel.h pauthent.h pcompat.h perrno.h pfs.h pmachine.h \
|
||
pprot.h procquery.c ptalloc.c rdgram.h regex.c regex.h stcopy.c \
|
||
support.c copyright.h udp.c vl_comp.c vlalloc.c vms.h vms_support.c \
|
||
vms/fd.h vms/in.h vms/pseudos.h vms/signal.h vms/socket.h vms/time.h \
|
||
vms/types.h vms/network.h vms/multi.opt vms/ucx.opt vms/woll.opt
|
||
|
||
BFILES= $(FILES) xprocquery.c
|
||
|
||
dist: tar shar dcl
|
||
|
||
shar: archie.doc
|
||
makekit -narchie-$(VERSION). archie-$(VERSION) `echo $(FILES) | \
|
||
tr ' ' '\012' | sed -e "s/^/archie-$(VERSION)\//g"` \
|
||
vms msdos > Manifest
|
||
|
||
archie.doc: archie.man
|
||
nroff -man archie.man | tr '\010' _ | sed -e s/__//g > archie.doc
|
||
|
||
dcl: archie.doc
|
||
if [ ! -d archie$(VMS_VERSION)/ ]; then ln -s . archie$(VMS_VERSION); fi
|
||
echo '$$ write sys$$output "Unpacking..."' > archie$(VMS_VERSION).com
|
||
echo '$$ if f$$search("archie.dir") .eqs. "" then create/dir [.ARCHIE]' >> archie$(VMS_VERSION).com
|
||
echo '$$ if f$$search("[.ARCHIE]vms.dir") .eqs. "" then create/dir [.ARCHIE.VMS]' >> archie$(VMS_VERSION).com
|
||
echo '$$ if f$$search("[.ARCHIE]msdos.dir") .eqs. "" then create/dir [.ARCHIE.MSDOS]' >> archie$(VMS_VERSION).com
|
||
echo '$$ set noverify' >> archie$(VMS_VERSION).com
|
||
dclshar `echo "$(FILES)" | tr ' ' '\012' | \
|
||
sed -e "s/^/archie\//g"` >> archie$(VMS_VERSION).com
|
||
echo '$$ write sys$$output "Ok, now enter the ARCHIE directory, look at MAKE.COM, then type @MAKE ."' >> archie$(VMS_VERSION).com
|
||
|
||
tar: archie.doc
|
||
if [ ! -d archie-$(VERSION)/ ]; then ln -s . archie-$(VERSION); fi
|
||
tar cvf archie-$(VERSION).tar `echo $(FILES) |\
|
||
tr ' ' '\012' | sed -e "s/^/archie-$(VERSION)\//g"`
|
||
compress -f archie-$(VERSION).tar
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]Prospero
|
||
$DECK
|
||
Prospero also allows users to access Archie as if it were part of a
|
||
file system. Here is an example of how Prospero can be used to access
|
||
Archie in this manner.
|
||
|
||
Script started on Mon Jul 1 22:36:42 1991
|
||
% source /home/ftp/archie/pfs/bin/vfsetup.source
|
||
% vfsetup guest
|
||
% venable
|
||
% cd /archive-sites/archie/regex
|
||
% cd prospero (This command specifies the query)
|
||
% ls -l
|
||
total 0
|
||
-r--r--r-- 0 - 0 - info-prospero.arc
|
||
dr-xr-xr-x 0 - 0 - prospero
|
||
dr-xr-xr-x 0 - 0 - prospero-papers
|
||
-r--r--r-- 0 - 0 - prospero.arc
|
||
-r--r--r-- 0 - 0 - prospero.tar.Z
|
||
(Note that the "vls" command could have been used)
|
||
(to show where the files were actually stored )
|
||
% ls prospero (list a result if it is a directory)
|
||
prog.tar.Z prospero.tar.Z
|
||
% cat info-prospero.arc (The file is automatically retrieved and displayed)
|
||
>From bcn@n1dmm Tue Dec 4 02:33:36 1990
|
||
Received: from n1dmm.cs.washington.edu by june.cs.washington.edu (5.64/7.0jh)
|
||
id AA24763; Tue, 4 Dec 90 02:33:36 -0800
|
||
Received: by n1dmm.cs.washington.edu (5.64/7.0h)
|
||
id AA08497; Tue, 4 Dec 90 02:33:31 -0800
|
||
Date: Tue, 4 Dec 90 02:33:31 -0800
|
||
From: bcn@cs.washington.edu (Clifford Neuman)
|
||
...
|
||
% vdisable
|
||
% exit
|
||
script done on Mon Jul 1 22:39:33 1991
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]README
|
||
$DECK
|
||
[Last changed 04/14/92 v1.3.2]
|
||
|
||
Enclosed you'll find a Prospero client for the archie service. It'll
|
||
let you query the archie databases without actually using an
|
||
interactive process on the remote server's machine (e.g., archie.ans.net),
|
||
resulting in a MUCH better response time. It also helps lessen the
|
||
load on the archie server itself.
|
||
|
||
What's Archie? It's a system that will let you check a database containing
|
||
thousands of entries for the files that're available at FTP sites around
|
||
the world.
|
||
|
||
This is a third child of Clifford Neuman's Prospero project. It's really
|
||
the Archie client that's included in the prospero stuff, but I've taken out
|
||
everything that's unnecessary for this client to work. (Aka, you don't
|
||
have to build all of Prospero to get the Archie client.) Khun Yee Fung
|
||
wrote an archie client in Perl, George Ferguson has written a client
|
||
for use with XWindows, based in part upon this code. Also, Scott
|
||
Stark wrote a NeXT-Step client for the NeXT.
|
||
|
||
Using the Archie Prospero interface in its true form will probably be of
|
||
interest---check out the file `Prospero' for an example of its interface.
|
||
If you find it intriguing, you should probably get the full prospero kit
|
||
from the University of Washington on cs.washington.edu in pub/prospero.tar.Z.
|
||
|
||
Suffice to say, there are now a number of ways to query Archie without
|
||
bogging a server down with your logins.
|
||
|
||
Check out the man page (or archie.doc, if you're using VMS or DOS)
|
||
for instructions on how to use this archie client. VMS users please
|
||
note that you have to put quotes around args that are capital letters;
|
||
for example, $ ARCHIE "-L" to list the available servers.
|
||
|
||
Please check to make sure you don't have "archie" aliased or modified
|
||
in some way to do a telnet or rlogin (which you may've done before
|
||
this command-line ability came into being).
|
||
|
||
If Archie consistently hangs (at different times of day with
|
||
different queries), it's possible that your site has UDP traffic on
|
||
ports > 1000 blocked, for security reasons. Type `make udptest' to
|
||
check---if it prints out the date, the Archie server is probably down;
|
||
if it doesn't print out the date, either Widener's computer is down
|
||
(God forbid ;-) ) or you do indeed have UDP blocked. See your system
|
||
administrator in this case. If the problem persists and haven't the
|
||
vaguest, then write me describing the situation and what machine/OS
|
||
you're using.
|
||
|
||
Write to archie-group@cs.mcgill.ca with questions about Archie itself.
|
||
Write to info-prospero@isi.edu about the Prospero protocol.
|
||
Write to brendan@cs.widener.edu with questions about this specific package.
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]README.dos
|
||
$DECK
|
||
11/22/91 Readme.dos -- Readme file for CUTCP DOS version of Archie.
|
||
|
||
--
|
||
This version requires the use of a `standard' NCSA or CUTCP compatible
|
||
CONFIG.TEL file. If you are running NCSA telnet or CUTCP/CUTE telnet,
|
||
you should be able to run this program without modification.
|
||
|
||
As with all CUTCP programs, you may set a DOS environment variable to
|
||
point to the location of your config.tel file.
|
||
|
||
set CONFIGTEL=C:\net\config.tel
|
||
|
||
You may also set the $CUTCPnn dos environment variables to include other
|
||
'local' information (such as client IP address on a Novell lan).
|
||
|
||
This version has been compiled with the US (archie.sura.net) Prospero/Archie
|
||
server as the default. This may not be appropriate for your location. Here's
|
||
how to change it.
|
||
|
||
|
||
1. Run the archie program with the -L argument to list known
|
||
archie/prospero servers.
|
||
|
||
2. Select the server name that is closest to your site. For this example
|
||
we'll pick archie.funet.fi
|
||
|
||
3. Edit your config.tel file and add the following lines at the end
|
||
of the file.
|
||
|
||
name=archie
|
||
host=archie.funet.fi # actually substitute your select
|
||
# server name here
|
||
|
||
4. If you happen to know the IP address of the server, you may also
|
||
add the appropriate
|
||
|
||
hostip=<insert IP address here>
|
||
|
||
5. If you don't enter an IP address, archie will perform a DNS lookup
|
||
use the domain nameserver information that is in your config.tel
|
||
file.
|
||
|
||
|
||
An additional command line option (-H) has been added (vs -h) to allow the
|
||
user to specify the config.tel file location on the command line.
|
||
|
||
archie -H c:\net\config.tel emacs
|
||
|
||
During a search, you may press the <ESCAPE> key to abort the query.
|
||
|
||
|
||
|
||
If you have problems, try running archie with the -D9 option (debug).
|
||
|
||
As usual, bugs/comments to:
|
||
|
||
cutcp-bugs@omnigate.clarkson.edu
|
||
|
||
Brad Clements, Sr. Network Engineer
|
||
Educational Resources Center
|
||
Clarkson University
|
||
Potsdam, NY 13699
|
||
|
||
bkc@draco.erc.clarkson.edu
|
||
|
||
-----------
|
||
Sample Config.tel file
|
||
------------------------------
|
||
# Example host file for ARCHIE/ CUTCP version
|
||
# 11/21/91
|
||
#
|
||
# Bugs to cutcp-bugs@omnigate.clarkson.edu
|
||
|
||
#---------------------------------------------------------------------------#
|
||
# #
|
||
#** ATTENTION ATTENTION ATTENTION ATTENTION ATTENTION ATTENTION ATTENTION **#
|
||
# #
|
||
# This sample config.tel file contains every single option that you could #
|
||
# possibly use. Its meant as an example only. Please Please PLEASE don't #
|
||
# use all these options in your working config.tel file, just the ones #
|
||
# that you actually need. Many options can be left out, the default action#
|
||
# (if defined) is shown in parens () next to the option. #
|
||
# #
|
||
# Thank you for your support #
|
||
#---------------------------------------------------------------------------#
|
||
|
||
#
|
||
# This example file is for my=bootp, in which case the following items are
|
||
# determined from the bootp server: (and are thus commented out in this file)
|
||
# 1. This machine's IP Address
|
||
# 2. The network NETMASK
|
||
# 3. The default gateway (one or more)
|
||
# 4. Nameservers (one or more)
|
||
# 5. The domain search list (if this clients hostname is in the bootp packet)
|
||
#
|
||
# Your BOOTP server needs to be RFC 1048 compliant for this to work
|
||
#
|
||
# If you have nameservers, gateways or a domainslist already specified
|
||
# in this file, then the file's entry takes precedence.
|
||
# Extra gateways and nameservers will be added by BOOTP if found, however.
|
||
#----------------------------------------------------------------------------
|
||
# You can set a DOS environment variable CONFIGTEL to point to this file
|
||
# then you don't need batch files or the -h option.
|
||
#
|
||
# C> set CONFIGTEL=C:\net\myconfig.tel
|
||
#
|
||
# You may also use environment variables to include config.tel options,
|
||
# such as:
|
||
# C> set $CUTCP1=myip~197.001.42.98;netmask~255.255.252.0
|
||
# C> set $CUTCP2=name~x;hostip~128.163.298.2
|
||
#
|
||
# and so on up to $CUTCP99. Note that you use a tilde (~) instead of (=)
|
||
# in the dos set command because two ='s are not allowed by Dos.
|
||
#
|
||
# Additionally, there is a new config.tel option called include= which
|
||
# allows the nesting (up to 3) configuration files deep.
|
||
#
|
||
#
|
||
# You can use these new options on networks to make your configuration job
|
||
# easier. CUTCP always opens config.tel files as read-only, so you can mark
|
||
# your files as sharable, read only. Also, you can use the include= command
|
||
# in a $CUTCP environment variable, and on the command line.
|
||
|
||
# *Note* that you can not include a machine specific parameter before
|
||
# name=default... This used to work in old versions, but is strictly
|
||
# enforced in this version.
|
||
# --------------------------------------------------------------------------
|
||
# This file is free form
|
||
# Separators are any char <33 and :;=
|
||
#
|
||
# The form is keyword=value for each parameter.
|
||
# The first set of parameters refer to the whole program's defaults.
|
||
# These parameter values can be in any order.
|
||
# Following this are the individual machine specs.
|
||
#
|
||
|
||
myip=128.153.28.65 # (bootp)
|
||
# myip types are:
|
||
# bootp - sends out a BOOTP request for your IP
|
||
# rarp - Uses reverse ARp to get your IP
|
||
# xx.yy.zz.qq - your IP address
|
||
|
||
vjc=no # (no)
|
||
# set vjc=yes if you're running slip and
|
||
# you want to use Van Jacobson TCP header
|
||
# compression
|
||
|
||
splayc=no # (no) ack. splay compression w/ vjc.. don't
|
||
# use it, not standard, development option only
|
||
|
||
myname=userid # put your userid here, used for Rlogin
|
||
# PC-NFS version ignores this value and uses the name
|
||
# that you specified to your pcnfsd.
|
||
|
||
netmask=255.255.252.0 # needed if not using BOOTP.
|
||
# otherwise not needed because Bootp gets your netmask
|
||
# for you
|
||
|
||
hardware=packet # (packet)
|
||
# harware choices
|
||
# 3com - 3com 3c501
|
||
# 3c523 - 3com 3c523
|
||
# wd800 - Western Digitial 800E
|
||
# nicpc -
|
||
# nicps -
|
||
# ni5210 - Micom Interlan NI5210 card
|
||
# packet - FTP packet Driver spec
|
||
# (currently only Ethernet and Slip class devices are supported)
|
||
|
||
interrupt=2 # hardware IRQ interrupt
|
||
address=0 # (0)
|
||
# base memory address or packet driver class
|
||
# if using packet driver (0 == default == ethernet)
|
||
# or class=6 for slip
|
||
|
||
ioaddr=0 # (0)
|
||
# I/O address or packet int vector if using packet driver
|
||
# If = 0 and packet driver, telbin looks for first
|
||
# packet driver found between 60H and 7FH
|
||
|
||
noarpme=yes # Don't arp for myself before running? (no)
|
||
# if yes, inhibits the initial arp request
|
||
# for this IP address. However, if yes, won't
|
||
# warn you if another user is using this IP
|
||
# address. For some token ring systems, you'll
|
||
# need noarpme=yes.
|
||
|
||
include="nul" # if you want to include another file as part
|
||
# of this one (you can nest up to three includes)
|
||
# otherwise, don't use this option
|
||
|
||
domaintime=4 # domain name lookup timeout (first retry)
|
||
domainretry=4 # domain name max number of retries
|
||
domainslist="clarkson.edu,aux.clarkson.edu" # domain name search path
|
||
# domain name lookup will attach each of these
|
||
# comma seperated suffixes to
|
||
# the end of the name you are looking for to
|
||
# discover the full name and IP address.
|
||
# so, looking for x tries x.clarkson.edu and x.aux.clarkson.edu then just x
|
||
# unless you use x. which ONLY looks for x
|
||
|
||
## Also, the fewer suffixes in the domainslist
|
||
## the less time you will have to wait if you mis-type an entry.
|
||
## Finally, try not to use a suffix like . or .edu or .com this will
|
||
## waste a lot of time looking for a bogus host name if you mis-type an entry.
|
||
|
||
## ----------------------------------------------------------------- ##
|
||
## BEGIN MACHINE SPECIFIC PARAMETERS... ##
|
||
## ----------------------------------------------------------------- ##
|
||
|
||
name=default # default entry sets defaults for all following
|
||
# machines.
|
||
|
||
arptime=10 # arp timeout in seconds
|
||
#
|
||
|
||
retrans=1 # starting retransmit time out in ticks
|
||
# 1/18ths of sec MAX 100, min 1
|
||
|
||
mtu=1024 # maximum transmit unit in bytes
|
||
# outgoing packet size, MAX=1500
|
||
|
||
maxseg=1024 # largest segment we can receive
|
||
# whatever the hardware can take, MAX=4096
|
||
rwin=2048 # most bytes we can receive without ACK
|
||
# =TCP window size, MAX=4096
|
||
|
||
contime=20 # timeout in seconds to try connection
|
||
# before returning error to user
|
||
|
||
# Following are individual machine specifications
|
||
# Gateways are used in order that they appear in the file
|
||
# Nameservers rotate, #1, #2, #3, #1, #2 when a request fails
|
||
#
|
||
|
||
# ********************************************************************* ###
|
||
# Note: If you are using BOOTP above for myip=, then you do not need
|
||
# to enter a default gateway, nameserver, netmask etc (unless you want to)
|
||
# only IF your BOOTP server is rfc_1048 compliant. (Ask your Net Manager)
|
||
# You can use both bootp and entries here, in which case the entries in
|
||
# this file over-ride what BOOTP discovers. (however, bootp nameservers
|
||
# and gateways are ADDED to this file's list of entries
|
||
# ********************************************************************* ####
|
||
|
||
# Below this line, most of the communication parameters are obtained
|
||
# from the "default" host entry. Those parameters listed for a host
|
||
# override the default host values.
|
||
#
|
||
# These are examples, replace them with the correct values for your site.
|
||
#name=mynameserver
|
||
#host=omnigate.clarkson.edu
|
||
#hostip=197.001.4.2
|
||
#nameserver=1
|
||
|
||
#name=backupserver
|
||
#host=clutx.clarkson.edu
|
||
#hostip=197.001.4.3
|
||
#nameserver=2
|
||
|
||
#name=lastserver
|
||
#host=n2ngw.nyser.net
|
||
#hostip=128.145.198.2
|
||
#nameserver=3
|
||
|
||
#name=mygateway
|
||
#host=nysernet.clarkson.edu
|
||
#hostip=197.001.4.1
|
||
#gateway=1
|
||
|
||
|
||
name=archie
|
||
host=archie.funet.fi
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]archie.c
|
||
$DECK
|
||
/*
|
||
* Copyright (c) 1991 by the University of Washington
|
||
*
|
||
* For copying and distribution information, please see the file
|
||
* <copyright.h>.
|
||
*/
|
||
|
||
#include <copyright.h>
|
||
|
||
/*
|
||
* Archie client using the Prospero protocol.
|
||
*
|
||
* Suggestions and improvements to Brendan Kehoe (brendan@cs.widener.edu).
|
||
*/
|
||
|
||
#include <stdio.h>
|
||
#if defined(OS2)
|
||
# include <pctcp.h>
|
||
#endif
|
||
#ifdef MSDOS
|
||
# include <string.h>
|
||
# include <stdlib.h>
|
||
# ifdef CUTCP
|
||
# include <msdos/cutcp.h>
|
||
# include <msdos/hostform.h>
|
||
/* The default stack size for a BC program is 4k; jack it up to 16 and add the
|
||
Check for Stack Overflow option to the compiler. */
|
||
extern unsigned _stklen = 16 * 1024;
|
||
# endif
|
||
#endif
|
||
|
||
#include <pfs.h>
|
||
#include <rdgram.h>
|
||
#include <archie.h>
|
||
#include <pmachine.h>
|
||
|
||
int listflag = 0;
|
||
int sortflag = 0; /* 1 = by date */
|
||
char *progname;
|
||
#ifdef DEBUG
|
||
extern int pfs_debug;
|
||
#endif
|
||
extern int rdgram_priority;
|
||
|
||
/* To keep the code clean.. */
|
||
#ifdef VMS
|
||
# define NFLAG "\"N\""
|
||
# define LFLAG "\"L\""
|
||
# define A_EXIT SS$_NORMAL
|
||
#else
|
||
# define NFLAG "N"
|
||
# define LFLAG "L"
|
||
# define A_EXIT 1
|
||
#endif
|
||
#ifdef CUTCP
|
||
# define HFLAG "[H config.tel]]"
|
||
#else
|
||
# define HFLAG "]"
|
||
#endif
|
||
|
||
main(argc,argv)
|
||
int argc;
|
||
char *argv[];
|
||
{
|
||
char *cur_arg;
|
||
char qtype = '='; /* Default to exact string match */
|
||
char etype = '='; /* Type if only -e is specified */
|
||
int eflag = 0; /* Exact flag specified */
|
||
int max_hits = MAX_HITS;
|
||
int offset = 0;
|
||
int exitflag = 0; /* Display release identifier */
|
||
int tmp;
|
||
char *host = ARCHIE_HOST;
|
||
char *p;
|
||
static char *archies[] = { ARCHIES };
|
||
#ifdef CUTCP
|
||
int hostset = 0;
|
||
#endif
|
||
char *getenv();
|
||
|
||
progname = *argv;
|
||
argc--; argv++;
|
||
|
||
#ifdef CUTCP
|
||
if(getenv("CONFIGTEL"))
|
||
if(Shostfile(getenv("CONFIGTEL")) < 0) {
|
||
fprintf(stderr,"Error, couldn't open configtel file %s\n",
|
||
getenv("CONFIGTEL"));
|
||
exit(1);
|
||
}
|
||
#endif
|
||
|
||
if ((p = getenv("ARCHIE_HOST")) != (char *)NULL)
|
||
host = p;
|
||
|
||
while (argc > 0 && **argv == '-') {
|
||
cur_arg = argv[0]+1;
|
||
|
||
/* If a - by itself, or --, then no more arguments */
|
||
if(!*cur_arg || ((*cur_arg == '-') && (!*(cur_arg+1)))) {
|
||
argc--, argv++;
|
||
goto scandone;
|
||
}
|
||
|
||
while (*cur_arg) {
|
||
switch (*cur_arg++) {
|
||
#ifdef DEBUG
|
||
case 'D': /* Debug level */
|
||
pfs_debug = 1; /* Default debug level */
|
||
if(*cur_arg && index("0123456789",*cur_arg)) {
|
||
sscanf(cur_arg,"%d",&pfs_debug);
|
||
cur_arg += strspn(cur_arg,"0123456789");
|
||
}
|
||
else if(argc > 2) {
|
||
tmp = sscanf(argv[1],"%d",&pfs_debug);
|
||
if (tmp == 1) {argc--;argv++;}
|
||
}
|
||
break;
|
||
#endif
|
||
#ifdef CUTCP
|
||
case 'H' :
|
||
if(Shostfile(argv[1]) < 0) {
|
||
fprintf(stderr,"Error, couldn't open configtel file %s\n",argv[1]);
|
||
exit(1);
|
||
}
|
||
argc--;argv++;
|
||
break;
|
||
#endif
|
||
#ifndef XARCHIE
|
||
case 'L':
|
||
printf("Known archie servers:\n");
|
||
for (tmp = 0; tmp < NARCHIES; tmp++)
|
||
printf("\t%s\n", archies[tmp]);
|
||
printf(" * %s is the default Archie server.\n", ARCHIE_HOST);
|
||
printf(" * For the most up-to-date list, write to an Archie server and give it\n the command `servers'.\n");
|
||
exitflag = 1;
|
||
break;
|
||
#endif
|
||
|
||
case 'N': /* Priority (nice) */
|
||
rdgram_priority = RDGRAM_MAX_PRI; /* Use this if no # */
|
||
if(*cur_arg && index("-0123456789",*cur_arg)) {
|
||
sscanf(cur_arg,"%d",&rdgram_priority);
|
||
cur_arg += strspn(cur_arg,"-0123456789");
|
||
}
|
||
else if(argc > 2) {
|
||
tmp = sscanf(argv[1],"%d",&rdgram_priority);
|
||
if (tmp == 1) {argc--;argv++;}
|
||
}
|
||
if(rdgram_priority > RDGRAM_MAX_SPRI)
|
||
rdgram_priority = RDGRAM_MAX_PRI;
|
||
if(rdgram_priority < RDGRAM_MIN_PRI)
|
||
rdgram_priority = RDGRAM_MIN_PRI;
|
||
break;
|
||
|
||
case 'c': /* substring (case sensitive) */
|
||
qtype = 'C';
|
||
etype = 'c';
|
||
break;
|
||
|
||
case 'e': /* Exact match */
|
||
/* If -e specified by itself, then we use the */
|
||
/* default value of etype which must be '=' */
|
||
eflag++;
|
||
break;
|
||
|
||
case 'h': /* Host */
|
||
host = argv[1];
|
||
#ifdef CUTCP
|
||
hostset++;
|
||
#endif
|
||
argc--; argv++;
|
||
break;
|
||
|
||
case 'l': /* List one match per line */
|
||
listflag++;
|
||
break;
|
||
|
||
case '0': case '1': case '2': case '3': case '4':
|
||
case '5': case '6': case '7': case '8': case '9':
|
||
cur_arg--;
|
||
case 'm': /* Max hits */
|
||
max_hits = -1;
|
||
if(*cur_arg && index("0123456789",*cur_arg)) {
|
||
sscanf(cur_arg,"%d",&max_hits);
|
||
cur_arg += strspn(cur_arg,"0123456789");
|
||
}
|
||
else if(argc > 1) {
|
||
tmp = sscanf(argv[1],"%d",&max_hits);
|
||
if (tmp == 1) {argc--;argv++;}
|
||
}
|
||
if (max_hits < 1) {
|
||
fprintf(stderr, "%s: -m option requires a value for max hits (>= 1)\n",
|
||
progname);
|
||
exit(A_EXIT);
|
||
}
|
||
break;
|
||
|
||
case 'o': /* Offset */
|
||
if(argc > 1) {
|
||
tmp = sscanf(argv[1],"%d",&offset);
|
||
if (tmp != 1)
|
||
argc = -1;
|
||
else {
|
||
argc--; argv++;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 'r': /* Regular expression search */
|
||
qtype = 'R';
|
||
etype = 'r';
|
||
break;
|
||
|
||
case 's': /* substring (case insensitive) */
|
||
qtype = 'S';
|
||
etype = 's';
|
||
break;
|
||
|
||
case 't': /* Sort inverted by date */
|
||
sortflag = 1;
|
||
break;
|
||
|
||
case 'v': /* Display version */
|
||
fprintf(stderr,
|
||
"Client version %s based upon Prospero version %s\n",
|
||
CLIENT_VERSION, PFS_RELEASE);
|
||
exitflag++;
|
||
break;
|
||
|
||
default:
|
||
fprintf(stderr,"Usage: %s [-[cers][l][t][m#][h host][%s][%s#]%s string\n", progname, LFLAG, NFLAG, HFLAG);
|
||
exit(A_EXIT);
|
||
}
|
||
}
|
||
argc--; argv++;
|
||
}
|
||
|
||
scandone:
|
||
|
||
if (eflag) qtype = etype;
|
||
|
||
if ((argc != 1) && exitflag) exit(0);
|
||
|
||
if (argc != 1) {
|
||
fprintf(stderr, "Usage: %s [-[cers][l][t][m#][h host][%s][%s#]%s string\n", progname, LFLAG, NFLAG, HFLAG);
|
||
fprintf(stderr," -c : case sensitive substring search\n");
|
||
fprintf(stderr," -e : exact string match (default)\n");
|
||
fprintf(stderr," -r : regular expression search\n");
|
||
fprintf(stderr," -s : case insensitive substring search\n");
|
||
fprintf(stderr," -l : list one match per line\n");
|
||
fprintf(stderr," -t : sort inverted by date\n");
|
||
fprintf(stderr," -m# : specifies maximum number of hits to return (default %d)\n", max_hits);
|
||
fprintf(stderr," -h host : specifies server host\n");
|
||
fprintf(stderr," -%s : list known servers and current default\n", LFLAG);
|
||
fprintf(stderr," -%s# : specifies query niceness level (0-35765)\n", NFLAG);
|
||
#ifdef CUTCP
|
||
fprintf(stderr,"-H config.tel: specify location of config.tel file\n");
|
||
#endif
|
||
exit(A_EXIT);
|
||
}
|
||
|
||
#ifdef CUTCP
|
||
if(argc = Snetinit()) {
|
||
fprintf(stderr,"Error %d from SNetinit (bad or missing config.tel ?)\n",argc);
|
||
if(argc == -2)
|
||
netshut(); /* rarp lookup failure */
|
||
exit(1);
|
||
}
|
||
if(!hostset) { /* if no host on command line, look in config.tel file
|
||
for name=archie */
|
||
struct machinfo *mp;
|
||
|
||
mp = Shostlook("archie");
|
||
if(mp) {
|
||
host = mp->hname ? mp->hname : mp->sname;
|
||
}
|
||
}
|
||
#endif
|
||
|
||
procquery(host, argv[0], max_hits, offset, qtype, sortflag, listflag);
|
||
|
||
#ifdef CUTCP
|
||
netshut();
|
||
#endif
|
||
exit(0);
|
||
}
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]archie.h
|
||
$DECK
|
||
/*
|
||
* archie.h : Definitions for the programmatic Prospero interface to Archie
|
||
*
|
||
* Written by Brendan Kehoe (brendan@cs.widener.edu),
|
||
* George Ferguson (ferguson@cs.rochester.edu), and
|
||
* Clifford Neuman (bcn@isi.edu).
|
||
*/
|
||
|
||
/* You can't touch this. */
|
||
#ifndef XARCHIE
|
||
# define ARCHIES "archie.ans.net (USA [NY])","archie.rutgers.edu (USA [NJ])","archie.sura.net (USA [MD])","archie.unl.edu (USA [NE])","archie.mcgill.ca (Canada)","archie.funet.fi (Finland/Mainland Europe)","archie.au (Australia)","archie.doc.ic.ac.uk (Great Britain/Ireland)"
|
||
# define NARCHIES 8
|
||
#endif
|
||
|
||
/*
|
||
* Default value for max hits. Note that this is normally different
|
||
* for different client implementations. Doing so makes it easier to
|
||
* collect statistics on the use of the various clients.
|
||
*/
|
||
#ifdef VMS
|
||
# define MAX_HITS 98 /* VMS Client */
|
||
#else
|
||
# ifdef XARCHIE
|
||
# define MAX_HITS 99 /* X Client */
|
||
# else
|
||
# define MAX_HITS 95 /* Normal client */
|
||
# endif
|
||
#endif
|
||
|
||
/*
|
||
* CLIENT_VERSION may be used to identify the version of the client if
|
||
* distributed separately from the Prospero distribution. The version
|
||
* command should then identify both the client version and the Prospero
|
||
* version identifiers.
|
||
*/
|
||
#ifdef XARCHIE
|
||
# define CLIENT_VERSION "1.3-X"
|
||
#else
|
||
# define CLIENT_VERSION "1.3.2"
|
||
#endif
|
||
|
||
/* Procedures from user/aquery.c */
|
||
|
||
/* archie_query(host,string,max_hits,offset,query_type,cmp_proc,flags) */
|
||
extern VLINK archie_query();
|
||
|
||
/* defcmplink(p,q) and invdatecmplink(p,q) */
|
||
extern int defcmplink(); /* Compare by host then by filename */
|
||
extern int invdatecmplink(); /* Compare links inverted by date */
|
||
|
||
/* Definitions for the comparison procedures */
|
||
#define AQ_DEFCMP defcmplink
|
||
#define AQ_INVDATECMP invdatecmplink
|
||
|
||
/* Flags */
|
||
#define AQ_NOSORT 0x01 /* Don't sort */
|
||
#define AQ_NOTRANS 0x02 /* Don't translate Archie responses */
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]archie.lnk
|
||
$DECK
|
||
aquery.lo archie.lo atalloc.lo dirsend.lo+
|
||
Get_pauth.lo get_vdir.lo perrmesg.lo procquery.lo+
|
||
ptalloc.lo regex.lo stcopy.lo support.lo+
|
||
vlalloc.lo vl_comp.lo
|
||
archie.unp
|
||
archie/map/noi/co/li/stack:45000
|
||
lsocket lnetlib lconfig lpc llibce
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]archie.doc
|
||
$DECK
|
||
|
||
|
||
|
||
ARCHIE(1) USER COMMANDS ARCHIE(1)
|
||
|
||
|
||
|
||
NAME
|
||
archie - query the Archie anonymous FTP databases using
|
||
Prospero
|
||
|
||
SYNOPSIS
|
||
archie [ -cers ] [ -l ] [ -t ] [ -m# ] [ -N# ] [ -h hostname ]
|
||
[ -L ] string
|
||
|
||
DESCRIPTION
|
||
archie queries an archie anonymous FTP database looking for
|
||
the specified string using the Prospero protocol. This
|
||
client is based on Prospero version Beta.4.2 and is provided
|
||
to encourage non-interactive use of the Archie servers (and
|
||
subsequently better performance on both sides). This man
|
||
page describes version 1.3 of the client.
|
||
|
||
The general method of use is of the form
|
||
|
||
% archie string
|
||
|
||
This will go to the archie server and ask it to look for all
|
||
known systems that have a file named `string' in their FTP
|
||
area. archie will wait, and print out any matches.
|
||
|
||
For example,
|
||
|
||
% archie emacs
|
||
|
||
will find all anonymous FTP sites in the archie database
|
||
that have files named emacs somewhere in their FTP area.
|
||
(This particular query would probably return a lot of direc-
|
||
tories.) If you want a list of every filename that contains
|
||
emacs anywhere in it, you'd use
|
||
|
||
% archie -c emacs
|
||
|
||
Regular expressions, such as
|
||
|
||
% archie -r '[xX][lL]isp'
|
||
|
||
may also be used for searches. (See the manual of a reason-
|
||
ably good editor, like GNU Emacs or vi, for more information
|
||
on using regular expressions.)
|
||
|
||
|
||
OPTIONS
|
||
The options currently available to this archie client are:
|
||
|
||
-c Search substrings paying attention to upper &
|
||
lower case.
|
||
-e Exact string match. (This is the default.)
|
||
-r Search using a regular expression.
|
||
|
||
|
||
|
||
Archie (Prospero) Last change: 9 January 1992 1
|
||
|
||
|
||
|
||
|
||
|
||
|
||
ARCHIE(1) USER COMMANDS ARCHIE(1)
|
||
|
||
|
||
|
||
-s Search substrings ignoring the case of the
|
||
letters.
|
||
-l Output results in a form suitable for parsing by
|
||
programs.
|
||
-t Sort the results inverted by date.
|
||
-m# Specifies the maximum number of hits (matches)
|
||
to return (default of 95).
|
||
-N# Sets the niceness of a query; by default, it's
|
||
set to 0. Without an argument, ``-N'' defaults
|
||
to 35765. If you use -N with an argument
|
||
between 0 and 35765, it'll adjust itself accord-
|
||
ingly. (Note: VMS users will have to put quotes
|
||
around this argument, and -L, like "-N45"; VMS
|
||
will otherwise convert it to lowercase.)
|
||
-h hostname Tells the client to query the Archie server
|
||
hostname.
|
||
-L Lists the Archie servers known to the program
|
||
when it was compiled, as well as the name of the
|
||
default Archie server. For an up-to-date list,
|
||
write to ``archie@archie.mcgill.ca'' (or any
|
||
Archie server) with the single command of
|
||
servers.
|
||
|
||
The three search-modifying arguments (``-c'', ``-r'', and
|
||
``-s'') are all mutually exclusive; only the last one
|
||
counts. If you specify -e with any of ``-c'', ``-r'', or
|
||
``-s'', the server will first check for an exact match, then
|
||
fall back to the case-sensitive, case-insensitive, or regu-
|
||
lar expression search. This is so if there are matches that
|
||
are particularly obvious, it will take a minimal amount of
|
||
time to satisfy your request.
|
||
|
||
If you list a single `-' by itself, any further arguments
|
||
will be taken as part of the search string. This is
|
||
intended to enable searching for strings that begin with a
|
||
`-'; for example:
|
||
|
||
% archie -s - -old
|
||
|
||
will search for all filenames that contain the string `-old'
|
||
in them.
|
||
|
||
RESPONSE
|
||
Archie servers are set up to respond to a number of requests
|
||
in a queued fashion. That is, smaller requests get served
|
||
much more quickly than do large requests. As a result, the
|
||
more often you query the Archie server, or the larger your
|
||
requests, the longer the queue will become, resulting in a
|
||
longer waiting period for everyone's requests. Please be
|
||
frugal when possible, for your benefit as well as for the
|
||
other users.
|
||
|
||
|
||
|
||
|
||
Archie (Prospero) Last change: 9 January 1992 2
|
||
|
||
|
||
|
||
|
||
|
||
|
||
ARCHIE(1) USER COMMANDS ARCHIE(1)
|
||
|
||
|
||
|
||
QUERY PRIORITY
|
||
Please use the ``-N'' option whenever you don't demand
|
||
immediacy, or when you're requesting things that could gen-
|
||
erate large responses. Even when using the nice option, you
|
||
should still try to avoid big jobs during busy periods.
|
||
Here is a list of what we consider to be nice values that
|
||
accurately reflect the priority of a job to the server.
|
||
|
||
Normal 0
|
||
Nice 500
|
||
Nicer 1000
|
||
Very Nice 5000
|
||
Extremely Nice 10000
|
||
Nicest 32765
|
||
|
||
The last priority, Nicest, would be used when a job should
|
||
wait until the queue is essentially empty before running.
|
||
You should pick one of these values to use, possibly modify-
|
||
ing it slightly depending on where you think your priority
|
||
should land. For example, 32760 would mean wait until the
|
||
queue is empty, but jump ahead of other jobs that have
|
||
selected Nicest.
|
||
|
||
There are certain types of things that we suggest using
|
||
Nicest for, irregardless. In particular, any searches for
|
||
which you would have a hard time justifying the use of any-
|
||
thing but extra resources. (We all know what those searches
|
||
would be for.)
|
||
|
||
ENVIRONMENT
|
||
ARCHIE_HOST
|
||
This will change the host archie will consult when
|
||
making queries. (The default value is what's been
|
||
compiled in.) The ``-h'' option will override this.
|
||
If you're running VMS, create a symbol called
|
||
ARCHIE_HOST.
|
||
|
||
SEE ALSO
|
||
For more information on regular expressions, see the manual
|
||
pages on:
|
||
|
||
regex(3), ed(1)
|
||
|
||
Also read the file archie/doc/whatis.archie on
|
||
archie.mcgill.ca for a detailed paper on Archie as a whole.
|
||
|
||
AUTHORS
|
||
The archie service was conceived and implemented by Alan
|
||
Emtage (bajan@cs.mcgill.ca), Peter Deutsch
|
||
(peterd@cs.mcgill.ca), and Bill Heelan
|
||
(wheelan@cs.mcgill.ca). The entire Internet is in their
|
||
debt.
|
||
|
||
|
||
|
||
Archie (Prospero) Last change: 9 January 1992 3
|
||
|
||
|
||
|
||
|
||
|
||
|
||
ARCHIE(1) USER COMMANDS ARCHIE(1)
|
||
|
||
|
||
|
||
The Prospero system was created by Clifford Neuman
|
||
(bcn@isi.edu); write to info-prospero@isi.edu for more
|
||
information on the protocol and its use.
|
||
|
||
This stripped client was put together by Brendan Kehoe
|
||
(brendan@cs.widener.edu), with modifications by Clifford
|
||
Neuman and George Ferguson (ferguson@cs.rochester.edu).
|
||
|
||
BUGS
|
||
There are none; only a few unexpected features.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
Archie (Prospero) Last change: 9 January 1992 4
|
||
|
||
|
||
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]archie.man
|
||
$DECK
|
||
.\" Originally by Jeff Kellem (composer@chem.bu.edu).
|
||
.\"
|
||
.\" This is from rn (1):
|
||
.de Ip
|
||
.br
|
||
.ie \\n.$>=3 .ne \\$3
|
||
.el .ne 3
|
||
.IP "\\$1" \\$2
|
||
..
|
||
.\"
|
||
.TH ARCHIE 1 "9 January 1992" "Archie (Prospero)"
|
||
.SH NAME
|
||
archie \- query the Archie anonymous FTP databases using Prospero
|
||
.SH SYNOPSIS
|
||
.in +\w'\fBarchie \fR'u
|
||
.ti -\w'\fBarchie \fR'u
|
||
.B archie\
|
||
\ [\ \fB\-cers\fR\ ]\
|
||
\ [\ \fB\-l\fR\ ]\ [\ \fB\-t\fR\ ]\
|
||
\ [\ \fB\-m#\fR\ ]\ [\ \fB\-N#\fR\ ]\
|
||
\ [\ \fB\-h\fR\ \fIhostname\fR\ ]
|
||
[\ \fB\-L\fR\ ]\ \fIstring\fR
|
||
.SH DESCRIPTION
|
||
.B archie
|
||
queries an archie anonymous FTP database looking for the specified
|
||
.I string
|
||
using the
|
||
.B Prospero
|
||
protocol. This client is based on
|
||
.B Prospero
|
||
version Beta.4.2 and is provided to encourage non-interactive use of
|
||
the Archie servers (and subsequently better performance on both
|
||
sides). This man page describes version 1.3 of the client.
|
||
|
||
The general method of use is of the form
|
||
|
||
.RS
|
||
%
|
||
.B archie string
|
||
.RE
|
||
.PP
|
||
|
||
This will go to the archie server and ask it to look for all known
|
||
systems that have a file named `string' in their FTP area. \fBarchie\fP
|
||
will wait, and print out any matches.
|
||
|
||
For example,
|
||
|
||
.RS
|
||
%
|
||
.B archie emacs
|
||
.RE
|
||
.PP
|
||
|
||
will find all anonymous FTP sites in the archie database that have files
|
||
named
|
||
.B emacs
|
||
somewhere in their FTP area. (This particular query would probably
|
||
return a lot of directories.) If you want a list of every filename
|
||
that contains \fBemacs\fR \fIanywhere\fR in it, you'd use
|
||
|
||
.RS
|
||
%
|
||
.B archie -c emacs
|
||
.RE
|
||
.PP
|
||
|
||
Regular expressions, such as
|
||
|
||
.RS
|
||
%
|
||
.B archie -r '[xX][lL]isp'
|
||
.RE
|
||
.PP
|
||
|
||
may also be used for searches. (See the manual of a reasonably good
|
||
editor, like GNU Emacs or vi, for more information on using regular
|
||
expressions.)
|
||
|
||
.SH OPTIONS
|
||
The options currently available to this
|
||
.B archie
|
||
client are:
|
||
|
||
.PD 0
|
||
.TP 12
|
||
.BR \-c
|
||
Search substrings paying attention to upper & lower case.
|
||
.TP
|
||
.BR \-e
|
||
Exact string match. (This is the default.)
|
||
.TP
|
||
.BR \-r
|
||
Search using a regular expression.
|
||
.TP
|
||
.BR \-s
|
||
Search substrings ignoring the case of the letters.
|
||
.TP
|
||
.BR \-l
|
||
Output results in a form suitable for parsing by programs.
|
||
.TP
|
||
.BR \-t
|
||
Sort the results inverted by date.
|
||
.TP
|
||
.BI \-m#
|
||
Specifies the maximum number of hits (matches) to return (default of
|
||
\fB95\fR).
|
||
.TP
|
||
.BI \-N#
|
||
Sets the \fIniceness\fR of a query; by default, it's set to 0.
|
||
Without an argument, ``\-N'' defaults to \fB35765\fR. If you use
|
||
\fB\-N\fR with an argument between 0 and 35765, it'll adjust itself
|
||
accordingly. (\fBNote\fR: VMS users will have to put quotes around
|
||
this argument, and \fB\-L\fR, like "\fB\-N45\fR"; VMS will otherwise convert
|
||
it to lowercase.)
|
||
.TP
|
||
.BI \-h\ \fIhostname\fR
|
||
Tells the client to query the Archie server \fIhostname\fR.
|
||
.TP
|
||
.BI \-L
|
||
Lists the Archie servers known to the program when it was compiled, as
|
||
well as the name of the default Archie server. For an up-to-date
|
||
list, write to ``archie@archie.mcgill.ca'' (or any Archie server) with
|
||
the single command of \fIservers\fR.
|
||
|
||
.PP
|
||
The three search-modifying arguments (``\-c'', ``\-r'', and ``\-s'')
|
||
are all mutually exclusive; only the last one counts. If you specify
|
||
\fB\-e\fR with any of ``\-c'', ``\-r'', or ``\-s'',
|
||
the server will first check for an exact match, then fall back to the
|
||
case-sensitive, case-insensitive, or regular expression search. This is
|
||
so if there are matches that are particularly obvious, it will take a
|
||
minimal amount of time to satisfy your request.
|
||
|
||
If you list a single `\-' by itself, any further arguments will be
|
||
taken as part of the search string. This is intended to enable
|
||
searching for strings that begin with a `\-'; for example:
|
||
|
||
.RS
|
||
%
|
||
.B archie \-s \- \-old
|
||
.RE
|
||
|
||
will search for all filenames that contain the string `\-old' in them.
|
||
|
||
.SH RESPONSE
|
||
Archie servers are set up to respond to a number of requests in a
|
||
queued fashion. That is, smaller requests get served much more
|
||
quickly than do large requests. As a result, the more often you query
|
||
the Archie server, or the larger your requests, the longer the queue
|
||
will become, resulting in a longer waiting period for everyone's
|
||
requests. Please be frugal when possible, for your benefit as well as
|
||
for the other users.
|
||
|
||
.SH QUERY PRIORITY
|
||
Please use the ``-N'' option whenever you don't demand immediacy, or
|
||
when you're requesting things that could generate large responses.
|
||
Even when using the nice option, you should still try to avoid big
|
||
jobs during busy periods. Here is a list of what we consider to be
|
||
nice values that accurately reflect the priority of a job to the server.
|
||
|
||
.RS
|
||
.TP 20
|
||
.B Normal
|
||
0
|
||
.TP
|
||
.B Nice
|
||
500
|
||
.TP
|
||
.B Nicer
|
||
1000
|
||
.TP
|
||
.B Very Nice
|
||
5000
|
||
.TP
|
||
.B Extremely Nice
|
||
10000
|
||
.TP
|
||
.B Nicest
|
||
32765
|
||
.RE
|
||
|
||
The last priority, \fBNicest\fR, would be used when a job should wait until
|
||
the queue is essentially empty before running. You should pick one of
|
||
these values to use, possibly modifying it slightly depending on where
|
||
you think your priority should land. For example, 32760 would mean
|
||
wait until the queue is empty, but jump ahead of other jobs that have
|
||
selected \fBNicest\fR.
|
||
|
||
There are certain types of things that we suggest using \fBNicest\fR
|
||
for, irregardless. In particular, any searches for which you would
|
||
have a hard time justifying the use of anything but extra resources.
|
||
(We all know what those searches would be for.)
|
||
|
||
.SH ENVIRONMENT
|
||
.Ip "ARCHIE_HOST" 8
|
||
This will change the host
|
||
.IR archie
|
||
will consult when making queries. (The default value is what's been
|
||
compiled in.) The ``\-h'' option will override this. If you're
|
||
running VMS, create a symbol called ARCHIE_HOST.
|
||
|
||
.SH SEE ALSO
|
||
For more information on regular expressions, see the manual pages on:
|
||
|
||
.BR regex (3) ,
|
||
.BR ed (1)
|
||
|
||
Also read the file \fBarchie/doc/whatis.archie\fR on
|
||
\fBarchie.mcgill.ca\fR for a detailed paper on Archie as a whole.
|
||
|
||
.SH AUTHORS
|
||
The
|
||
.B archie
|
||
service was conceived and implemented by Alan Emtage (\fBbajan@cs.mcgill.ca\fR),
|
||
Peter Deutsch (\fBpeterd@cs.mcgill.ca\fR), and Bill Heelan
|
||
(\fBwheelan@cs.mcgill.ca\fR). The entire Internet is in their debt.
|
||
|
||
The \fBProspero\fR system was created by Clifford Neuman
|
||
(\fBbcn@isi.edu\fR); write to \fBinfo\-prospero@isi.edu\fR for more
|
||
information on the protocol and its use.
|
||
|
||
This stripped client was put together by Brendan Kehoe
|
||
(\fBbrendan@cs.widener.edu\fR), with modifications by
|
||
Clifford Neuman and George Ferguson (\fBferguson@cs.rochester.edu\fR).
|
||
|
||
.SH BUGS
|
||
There are none; only a few unexpected features.
|
||
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]aquery.c
|
||
$DECK
|
||
/*
|
||
* aquery.c : Programmatic Prospero interface to Archie
|
||
*
|
||
* Copyright (c) 1991 by the University of Washington
|
||
*
|
||
* For copying and distribution information, please see the file
|
||
* <copyright.h>.
|
||
*
|
||
* Originally part of the Prospero Archie client by Clifford
|
||
* Neuman (bcn@isi.edu). Modifications, addition of programmatic interface,
|
||
* and new sorting code by George Ferguson (ferguson@cs.rochester.edu)
|
||
* and Brendan Kehoe (brendan@cs.widener.edu). MSDOS and OS2 modifications
|
||
* to use with PC/TCP by Mark Towfiq (towfiq@FTP.COM).
|
||
*/
|
||
|
||
#include <copyright.h>
|
||
|
||
#include <stdio.h>
|
||
|
||
#include <pfs.h>
|
||
#include <perrno.h>
|
||
#include <archie.h>
|
||
|
||
#include <pmachine.h>
|
||
#ifdef NEED_STRING_H
|
||
# include <string.h> /* for char *index() */
|
||
#else
|
||
# include <strings.h> /* for char *index() */
|
||
#endif
|
||
|
||
static void translateArchieResponse();
|
||
|
||
extern int pwarn;
|
||
extern char p_warn_string[];
|
||
|
||
/*
|
||
* archie_query : Sends a request to _host_, telling it to search for
|
||
* _string_ using _query_type_ as the search method.
|
||
* No more than _max_hits_ matches are to be returned
|
||
* skipping over _offset_ matches.
|
||
*
|
||
* archie_query returns a linked list of virtual links.
|
||
* If _flags_ does not include AQ_NOTRANS, then the Archie
|
||
* responses will be translated. If _flags_ does not include
|
||
* AQ_NOSORT, then the list will be sorted using _cmp_proc_ to
|
||
* compare pairs of links. If _cmp_proc_ is NULL or AQ_DEFCMP,
|
||
* then the default comparison procedure, defcmplink(), is used
|
||
* sorting by host, then filename. If cmp_proc is AQ_INVDATECMP
|
||
* then invdatecmplink() is used, sorting inverted by date.
|
||
* otherwise a user-defined comparison procedure is called.
|
||
*
|
||
* archie_query returns NULL and sets perrno if the query
|
||
* failed. Note that it can return NULL with perrno == PSUCCESS
|
||
* if the query didn't fail but there were simply no matches.
|
||
*
|
||
* query_type: S Substring search ignoring case
|
||
* C Substring search with case significant
|
||
* R Regular expression search
|
||
* = Exact String Match
|
||
* s,c,e Tries exact match first and falls back to S, C, or R
|
||
* if not found.
|
||
*
|
||
* cmp_proc: AQ_DEFCMP Sort by host, then filename
|
||
* AQ_INVDATECMP Sort inverted by date
|
||
*
|
||
* flags: AQ_NOSORT Don't sort results
|
||
* AQ_NOTRANS Don't translate results
|
||
*/
|
||
VLINK
|
||
archie_query(host,string,max_hits,offset,query_type,cmp_proc,flags)
|
||
char *host,*string;
|
||
int max_hits,offset;
|
||
char query_type;
|
||
int (*cmp_proc)();
|
||
int flags;
|
||
{
|
||
char qstring[MAX_VPATH]; /* For construting the query */
|
||
VLINK links; /* Matches returned by server */
|
||
VDIR_ST dir_st; /* Filled in by get_vdir */
|
||
PVDIR dir= &dir_st;
|
||
|
||
VLINK p,q,r,lowest,nextp,pnext,pprev;
|
||
int tmp;
|
||
|
||
/* Set the cmp_proc if not given */
|
||
if (cmp_proc == NULL) cmp_proc = defcmplink;
|
||
|
||
/* Make the query string */
|
||
sprintf(qstring,"ARCHIE/MATCH(%d,%d,%c)/%s",
|
||
max_hits,offset,query_type,string);
|
||
|
||
/* Initialize Prospero structures */
|
||
perrno = PSUCCESS; *p_err_string = '\0';
|
||
pwarn = PNOWARN; *p_warn_string = '\0';
|
||
vdir_init(dir);
|
||
|
||
/* Retrieve the list of matches, return error if there was one */
|
||
#if defined(MSDOS)
|
||
if(tmp = get_vdir(host, qstring, "", dir, (long)GVD_ATTRIB|GVD_NOSORT,
|
||
NULL, NULL)) {
|
||
#else
|
||
if(tmp = get_vdir(host,qstring,"",dir,GVD_ATTRIB|GVD_NOSORT,NULL,NULL)) {
|
||
# endif
|
||
perrno = tmp;
|
||
return(NULL);
|
||
}
|
||
|
||
/* Save the links, and clear in dir in case it's used again */
|
||
links = dir->links; dir->links = NULL;
|
||
|
||
/* As returned, list is sorted by suffix, and conflicting */
|
||
/* suffixes appear on a list of "replicas". We want to */
|
||
/* create a one-dimensional list sorted by host then filename */
|
||
/* and maybe by some other parameter */
|
||
|
||
/* First flatten the doubly-linked list */
|
||
for (p = links; p != NULL; p = nextp) {
|
||
nextp = p->next;
|
||
if (p->replicas != NULL) {
|
||
p->next = p->replicas;
|
||
p->next->previous = p;
|
||
for (r = p->replicas; r->next != NULL; r = r->next)
|
||
/*EMPTY*/ ;
|
||
r->next = nextp;
|
||
nextp->previous = r;
|
||
p->replicas = NULL;
|
||
}
|
||
}
|
||
|
||
/* Translate the filenames unless NOTRANS was given */
|
||
if (!(flags & AQ_NOTRANS))
|
||
for (p = links; p != NULL; p = p->next)
|
||
translateArchieResponse(p);
|
||
|
||
/* If NOSORT given, then just hand it back */
|
||
if (flags & AQ_NOSORT) {
|
||
perrno = PSUCCESS;
|
||
return(links);
|
||
}
|
||
|
||
/* Otherwise sort it using a selection sort and the given cmp_proc */
|
||
for (p = links; p != NULL; p = nextp) {
|
||
nextp = p->next;
|
||
lowest = p;
|
||
for (q = p->next; q != NULL; q = q->next)
|
||
if ((*cmp_proc)(q,lowest) < 0)
|
||
lowest = q;
|
||
if (p != lowest) {
|
||
/* swap the two links */
|
||
pnext = p->next;
|
||
pprev = p->previous;
|
||
if (lowest->next != NULL)
|
||
lowest->next->previous = p;
|
||
p->next = lowest->next;
|
||
if (nextp == lowest) {
|
||
p->previous = lowest;
|
||
} else {
|
||
lowest->previous->next = p;
|
||
p->previous = lowest->previous;
|
||
}
|
||
if (nextp == lowest) {
|
||
lowest->next = p;
|
||
} else {
|
||
pnext->previous = lowest;
|
||
lowest->next = pnext;
|
||
}
|
||
if (pprev != NULL)
|
||
pprev->next = lowest;
|
||
lowest->previous = pprev;
|
||
/* keep the head of the list in the right place */
|
||
if (links == p)
|
||
links = lowest;
|
||
}
|
||
}
|
||
|
||
/* Return the links */
|
||
perrno = PSUCCESS;
|
||
return(links);
|
||
}
|
||
|
||
/*
|
||
* translateArchieResponse:
|
||
*
|
||
* If the given link is for an archie-pseudo directory, fix it.
|
||
* This is called unless AQ_NOTRANS was given to archie_query().
|
||
*/
|
||
static void
|
||
translateArchieResponse(l)
|
||
VLINK l;
|
||
{
|
||
char *slash;
|
||
|
||
if (strcmp(l->type,"DIRECTORY") == 0) {
|
||
if (strncmp(l->filename,"ARCHIE/HOST",11) == 0) {
|
||
l->type = stcopyr("EXTERNAL(AFTP,DIRECTORY)",l->type);
|
||
l->host = stcopyr(l->filename+12,l->host);
|
||
slash = (char *)index(l->host,'/');
|
||
if (slash) {
|
||
l->filename = stcopyr(slash,l->filename);
|
||
*slash++ = '\0';
|
||
} else
|
||
l->filename = stcopyr("",l->filename);
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* defcmplink: The default link comparison function for sorting. Compares
|
||
* links p and q first by host then by filename. Returns < 0 if p
|
||
* belongs before q, > 0 if p belongs after q, and == 0 if their
|
||
* host and filename fields are identical.
|
||
*/
|
||
int
|
||
defcmplink(p,q)
|
||
VLINK p,q;
|
||
{
|
||
int result;
|
||
|
||
if ((result=strcmp(p->host,q->host)) != 0)
|
||
return(result);
|
||
else
|
||
return(strcmp(p->filename,q->filename));
|
||
}
|
||
|
||
/*
|
||
* invdatecmplink: An alternative comparison function for sorting that
|
||
* compares links p and q first by LAST-MODIFIED date,
|
||
* if they both have that attribute. If both links
|
||
* don't have that attribute or the dates are the
|
||
* same, it then calls defcmplink() and returns its
|
||
* value.
|
||
*/
|
||
int
|
||
invdatecmplink(p,q)
|
||
VLINK p,q;
|
||
{
|
||
PATTRIB pat,qat;
|
||
char *pdate,*qdate;
|
||
int result;
|
||
|
||
pdate = qdate = NULL;
|
||
for (pat = p->lattrib; pat; pat = pat->next)
|
||
if(strcmp(pat->aname,"LAST-MODIFIED") == 0)
|
||
pdate = pat->value.ascii;
|
||
for (qat = q->lattrib; qat; qat = qat->next)
|
||
if(strcmp(qat->aname,"LAST-MODIFIED") == 0)
|
||
qdate = qat->value.ascii;
|
||
if(!pdate && !qdate) return(defcmplink(p,q));
|
||
if(!pdate) return(1);
|
||
if(!qdate) return(-1);
|
||
if((result=strcmp(qdate,pdate)) == 0) return(defcmplink(p,q));
|
||
else return(result);
|
||
}
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]atalloc.c
|
||
$DECK
|
||
/*
|
||
* Copyright (c) 1989, 1990 by the University of Washington
|
||
*
|
||
* For copying and distribution information, please see the file
|
||
* <copyright.h>.
|
||
*/
|
||
|
||
#include <copyright.h>
|
||
#include <stdio.h>
|
||
|
||
#include <pfs.h>
|
||
#include <pmachine.h> /* for correct definition of ZERO */
|
||
|
||
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()
|
||
{
|
||
PATTRIB at;
|
||
if(lfree) {
|
||
at = lfree;
|
||
lfree = lfree->next;
|
||
}
|
||
else {
|
||
at = (PATTRIB) malloc(sizeof(PATTRIB_ST));
|
||
if (!at) return(NULL);
|
||
pattrib_max++;
|
||
}
|
||
|
||
pattrib_count++;
|
||
|
||
ZERO(at);
|
||
/* Initialize and fill in default values; all items are
|
||
0 [or NULL] save precedence */
|
||
at->precedence = ATR_PREC_OBJECT;
|
||
|
||
return(at);
|
||
}
|
||
|
||
/*
|
||
* 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(at)
|
||
PATTRIB at;
|
||
{
|
||
if(at->aname) stfree(at->aname);
|
||
|
||
if((strcmp(at->avtype,"ASCII") == 0) && at->value.ascii)
|
||
stfree(at->value.ascii);
|
||
if((strcmp(at->avtype,"LINK") == 0) && at->value.link)
|
||
vlfree(at->value.link);
|
||
|
||
if(at->avtype) stfree(at->avtype);
|
||
|
||
at->next = lfree;
|
||
at->previous = NULL;
|
||
lfree = at;
|
||
pattrib_count--;
|
||
}
|
||
|
||
/*
|
||
* 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(at)
|
||
PATTRIB at;
|
||
{
|
||
PATTRIB nxt;
|
||
|
||
while(at != NULL) {
|
||
nxt = at->next;
|
||
atfree(at);
|
||
at = nxt;
|
||
}
|
||
}
|
||
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]dirsend.c
|
||
$DECK
|
||
/*
|
||
* Copyright (c) 1989, 1990, 1991 by the University of Washington
|
||
*
|
||
* For copying and distribution information, please see the file
|
||
* <copyright.h>.
|
||
*/
|
||
|
||
/* If you're going to hack on this, I'd suggest using unifdef with -UCUTCP
|
||
and possibly -UVMS, for your working copy. When you've got your changes
|
||
done, come back and add them into this main file. It's getting pretty
|
||
nasty down there. */
|
||
|
||
#include <copyright.h>
|
||
#include <stdio.h>
|
||
#include <errno.h>
|
||
|
||
#ifdef VMS
|
||
# ifdef WOLLONGONG
|
||
# include "twg$tcp:[netdist.include]netdb.h"
|
||
# else /* not Wollongong */
|
||
# ifdef UCX
|
||
# include netdb
|
||
# else /* Multinet */
|
||
# include "multinet_root:[multinet.include]netdb.h"
|
||
# endif
|
||
# endif
|
||
# include <vms.h>
|
||
#else /* not VMS */
|
||
# include <sys/types.h> /* this may/will define FD_SET etc */
|
||
# ifdef u3b2
|
||
# include <sys/inet.h> /* THIS does FD_SET etc on AT&T 3b2s. */
|
||
# endif /* u3b2 */
|
||
# include <pmachine.h>
|
||
# if defined(NEED_TIME_H) && !defined(AUX)
|
||
# include <time.h>
|
||
# else
|
||
# include <sys/time.h>
|
||
# endif
|
||
# ifdef WANT_BOTH_TIME
|
||
# include <sys/time.h>
|
||
# endif
|
||
# ifdef NEED_STRING_H
|
||
# include <string.h>
|
||
# else
|
||
# include <strings.h>
|
||
# endif
|
||
# ifdef CUTCP
|
||
# include <msdos/cutcp.h>
|
||
# include <msdos/netevent.h>
|
||
# include <msdos/hostform.h>
|
||
# else /* not CUTCP */
|
||
# include <netdb.h>
|
||
# include <sys/socket.h>
|
||
# endif
|
||
# ifdef NEED_SELECT_H
|
||
# include <sys/select.h>
|
||
# endif /* NEED_SELECT_H */
|
||
# ifndef IN_H
|
||
# include <netinet/in.h>
|
||
# define IN_H
|
||
# endif
|
||
# ifndef hpux
|
||
# include <arpa/inet.h>
|
||
# endif
|
||
#endif /* !VMS */
|
||
|
||
/* Interactive UNIX keeps some of the socket definitions in funny places. */
|
||
#ifdef ISC
|
||
# include <net/errno.h>
|
||
#endif /* ISC */
|
||
|
||
#include <pfs.h>
|
||
#include <pprot.h>
|
||
#include <pcompat.h>
|
||
#include <perrno.h>
|
||
|
||
/* Gnu C currently fails to pass structures on Sparcs properly. This directly
|
||
effects the calling of inet_ntoa(). To get around it, we use this hack;
|
||
take the address of what's being called to inet_ntoa, so it gets it
|
||
properly. This won't be necessary with gcc 2.0. */
|
||
#if defined(sun) && defined(__GNUC__) && !defined(__GNU_LIBRARY__)
|
||
# define SUN_GNU_FIX &
|
||
#else
|
||
# define SUN_GNU_FIX
|
||
#endif
|
||
|
||
static int notprived = 0;
|
||
#ifndef MSDOS
|
||
extern int errno;
|
||
#endif
|
||
extern int perrno;
|
||
extern int rdgram_priority;
|
||
#ifdef DEBUG
|
||
extern int pfs_debug;
|
||
#endif
|
||
extern int pfs_disable_flag;
|
||
|
||
char *nlsindex();
|
||
|
||
#define max(X, Y) ((X) > (Y) ? (X) : (Y))
|
||
|
||
static int dir_udp_port = 0; /* Remote UDP port number */
|
||
|
||
#ifdef CUTCP
|
||
# define NS_TIMEOUT 15
|
||
#endif
|
||
|
||
static unsigned short next_conn_id = 0;
|
||
|
||
static int client_dirsrv_timeout = CLIENT_DIRSRV_TIMEOUT;
|
||
static int client_dirsrv_retry = CLIENT_DIRSRV_RETRY;
|
||
|
||
/* These were parameters to dirsend() */
|
||
static PTEXT pkt;
|
||
static char *hostname;
|
||
static struct sockaddr_in *hostaddr;
|
||
|
||
/* These were locals in dirsend(). Note that the initializations here
|
||
* are really meaningless since we have to redo them for each call to
|
||
* dirsend() since they were formerly automatically initialized.
|
||
*/
|
||
static PTEXT first = NULL; /* First returned packet */
|
||
static PTEXT next; /* The one we are waiting for */
|
||
static PTEXT vtmp; /* For reorganizing linked list */
|
||
static PTEXT comp_thru; /* We have all packets though */
|
||
static int lp = -1; /* Opened UDP port */
|
||
static int hdr_len; /* Header Length */
|
||
static int nd_pkts; /* Number of packets we want */
|
||
static int no_pkts; /* Number of packets we have */
|
||
static int pkt_cid; /* Packet connection identifier */
|
||
static unsigned short this_conn_id; /* Connection ID we are using */
|
||
static unsigned short recvd_thru; /* Received through */
|
||
static short priority; /* Priority for request */
|
||
static short one = 0; /* Pointer to value 1 */
|
||
static short zero = 0; /* Pointer to value 0 */
|
||
static char *seqtxt; /* Pointer to text w/ sequence # */
|
||
static struct sockaddr_in us; /* Our address */
|
||
static struct sockaddr_in to; /* Address to send query */
|
||
static struct sockaddr_in from; /* Reply received from */
|
||
static int from_sz; /* Size of from structure */
|
||
static struct hostent *host; /* Host info from gethostbyname */
|
||
static long newhostaddr; /* New host address from *host */
|
||
static int req_udp_port=0; /* Requested port (optional) */
|
||
static char *openparen; /* Delimits port in name */
|
||
static char hostnoport[500];/* Host name without port */
|
||
static int ns; /* Number of bytes actually sent */
|
||
static int nr; /* Number of bytes received */
|
||
static SELECTARG readfds; /* Used for select */
|
||
static int tmp;
|
||
static char *ctlptr; /* Pointer to control field */
|
||
static short stmp; /* Temp short for conversions */
|
||
static int backoff; /* Server requested backoff */
|
||
static unsigned char rdflag11; /* First byte of flags (bit vect)*/
|
||
static unsigned char rdflag12; /* Second byte of flags (int) */
|
||
static int scpflag = 0; /* Set if any sequencd cont pkts */
|
||
static int ackpend = 0; /* Acknowledgement pending */
|
||
static int gaps = 0; /* Gaps present in recvd pkts */
|
||
static struct timeval timeout; /* Time to wait for response */
|
||
static struct timeval ackwait; /* Time to wait before acking */
|
||
static struct timeval gapwait; /* Time to wait b4 filling gaps */
|
||
static struct timeval *selwait; /* Time to wait for select */
|
||
static int retries; /* was = client_dirsrv_retry */
|
||
char to_hostname[512]; /* lmjm: saves inet_ntoa() str */
|
||
|
||
/* These are added so dirsend() "blocks" properly */
|
||
static PTEXT dirsendReturn;
|
||
static int dirsendDone;
|
||
|
||
/* And here are the values for dirsendDone */
|
||
#define DSRET_DONE 1
|
||
#define DSRET_SEND_ERROR -1
|
||
#define DSRET_RECV_ERROR -2
|
||
#define DSRET_SELECT_ERROR -3
|
||
#define DSRET_TIMEOUT -4
|
||
#define DSRET_ABORTED -5
|
||
|
||
/* New procedures to break up dirsend() */
|
||
static int initDirsend();
|
||
static void retryDirsend(), keepWaitingDirsend();
|
||
static void timeoutProc();
|
||
static void readProc();
|
||
|
||
/* Wrappers around X calls to allow non-X usage */
|
||
static void processEvent();
|
||
|
||
/* Extra stuff for the asynchronous X version of dirsend() */
|
||
typedef char *XtPointer;
|
||
typedef char *XtInputId;
|
||
typedef char *XtIntervalId;
|
||
|
||
static XtInputId inputId;
|
||
static XtIntervalId timerId = (XtIntervalId)0;
|
||
|
||
/*
|
||
* dirsend - send packet and receive response
|
||
*
|
||
* DIRSEND takes a pointer to a structure of type PTEXT, a hostname,
|
||
* and a pointer to a host address. It then sends the supplied
|
||
* packet off to the directory server on the specified host. If
|
||
* hostaddr points to a valid address, that address is used. Otherwise,
|
||
* the hostname is looked up to obtain the address. If hostaddr is a
|
||
* non-null pointer to a 0 address, then the address will be replaced
|
||
* with that found in the hostname lookup.
|
||
*
|
||
* DIRSEND will wait for a response and retry an appropriate
|
||
* number of times as defined by timeout and retries (both static
|
||
* variables). It will collect however many packets form the reply, and
|
||
* return them in a structure (or structures) of type PTEXT.
|
||
*
|
||
* DIRSEND will free the packet that it is presented as an argument.
|
||
* The packet is freed even if dirsend fails.
|
||
*/
|
||
PTEXT
|
||
dirsend(pkt_p,hostname_p,hostaddr_p)
|
||
PTEXT pkt_p;
|
||
char *hostname_p;
|
||
struct sockaddr_in *hostaddr_p;
|
||
{
|
||
/* copy parameters to globals since other routines use them */
|
||
pkt = pkt_p;
|
||
hostname = hostname_p;
|
||
hostaddr = hostaddr_p;
|
||
/* Do the initializations of formerly auto variables */
|
||
first = NULL;
|
||
lp = -1;
|
||
one = 0;
|
||
zero = 0;
|
||
req_udp_port=0;
|
||
scpflag = 0;
|
||
ackpend = 0;
|
||
gaps = 0;
|
||
retries = client_dirsrv_retry;
|
||
|
||
if (initDirsend() < 0)
|
||
return(NULL);
|
||
|
||
/* set the first timeout */
|
||
retryDirsend();
|
||
|
||
dirsendReturn = NULL;
|
||
dirsendDone = 0;
|
||
/* Until one of the callbacks says to return, keep processing events */
|
||
while (!dirsendDone)
|
||
processEvent();
|
||
|
||
/* Return whatever we're supposed to */
|
||
return(dirsendReturn);
|
||
}
|
||
|
||
|
||
/* - - - - - - - - */
|
||
/* This function does all the initialization that used to be done at the
|
||
* start of dirsend(), including opening the socket descriptor "lp". It
|
||
* returns the descriptor if successful, otherwise -1 to indicate that
|
||
* dirsend() should return NULL immediately.
|
||
*/
|
||
static int
|
||
initDirsend()
|
||
{
|
||
if(one == 0) one = htons((short) 1);
|
||
|
||
priority = htons(rdgram_priority);
|
||
|
||
timeout.tv_sec = client_dirsrv_timeout;
|
||
timeout.tv_usec = 0;
|
||
|
||
ackwait.tv_sec = 0;
|
||
ackwait.tv_usec = 500000;
|
||
|
||
gapwait.tv_sec = (client_dirsrv_timeout < 5 ? client_dirsrv_timeout : 5);
|
||
gapwait.tv_usec = 0;
|
||
|
||
comp_thru = NULL;
|
||
perrno = 0;
|
||
nd_pkts = 0;
|
||
no_pkts = 0;
|
||
pkt_cid = 0;
|
||
|
||
/* Find first connection ID */
|
||
if(next_conn_id == 0) {
|
||
srand(getpid()+time(0)); /* XXX: arg ok, but not right type. */
|
||
next_conn_id = rand();
|
||
}
|
||
|
||
|
||
/* If necessary, find out what udp port to send to */
|
||
if (dir_udp_port == 0) {
|
||
register struct servent *sp;
|
||
tmp = pfs_enable; pfs_enable = PMAP_DISABLE;
|
||
#ifdef USE_ASSIGNED_PORT
|
||
/* UCX needs 0 & -1 */
|
||
if ((sp = getservbyname("prospero","udp")) <= 0) {
|
||
#ifdef DEBUG
|
||
if (pfs_debug)
|
||
fprintf(stderr, "dirsrv: udp/prospero unknown service - using %d\n",
|
||
PROSPERO_PORT);
|
||
#endif
|
||
dir_udp_port = htons((u_short) PROSPERO_PORT);
|
||
}
|
||
#else
|
||
/* UCX needs 0 & -1 */
|
||
sp = getservbyname("dirsrv","udp");
|
||
if (sp == (struct servent *)0 || sp == (struct servent *)-1) {
|
||
#ifdef DEBUG
|
||
if (pfs_debug)
|
||
fprintf(stderr, "dirsrv: udp/dirsrv unknown service - using %d\n",
|
||
DIRSRV_PORT);
|
||
#endif
|
||
dir_udp_port = htons((u_short) DIRSRV_PORT);
|
||
}
|
||
#endif
|
||
else dir_udp_port = sp->s_port;
|
||
pfs_enable = tmp;
|
||
#ifdef DEBUG
|
||
if (pfs_debug > 3)
|
||
fprintf(stderr,"dir_udp_port is %d\n", ntohs(dir_udp_port));
|
||
#endif
|
||
}
|
||
|
||
/* If we were given the host address, then use it. Otherwise */
|
||
/* lookup the hostname. If we were passed a host address of */
|
||
/* 0, we must lookup the host name, then replace the old value */
|
||
if(!hostaddr || (hostaddr->sin_addr.s_addr == 0)) {
|
||
/* I we have a null host name, return an error */
|
||
if((hostname == NULL) || (*hostname == '\0')) {
|
||
#ifdef DEBUG
|
||
if (pfs_debug)
|
||
fprintf(stderr, "dirsrv: Null hostname specified\n");
|
||
#endif
|
||
perrno = DIRSEND_BAD_HOSTNAME;
|
||
ptlfree(pkt);
|
||
/* return(NULL); */
|
||
return(-1);
|
||
}
|
||
/* If a port is included, save it away */
|
||
if(openparen = index(hostname,'(')) {
|
||
sscanf(openparen+1,"%d",&req_udp_port);
|
||
strncpy(hostnoport,hostname,400);
|
||
if((openparen - hostname) < 400) {
|
||
*(hostnoport + (openparen - hostname)) = '\0';
|
||
hostname = hostnoport;
|
||
}
|
||
}
|
||
tmp = pfs_enable; pfs_enable = PMAP_DISABLE;
|
||
if((host = gethostbyname(hostname)) == NULL) {
|
||
pfs_enable = tmp;
|
||
/* Check if a numeric address */
|
||
newhostaddr = inet_addr(hostname);
|
||
if(newhostaddr == -1) {
|
||
#ifdef DEBUG
|
||
if (pfs_debug)
|
||
fprintf(stderr, "dirsrv: Can't resolve host %s\n",hostname);
|
||
#endif
|
||
perrno = DIRSEND_BAD_HOSTNAME;
|
||
ptlfree(pkt);
|
||
/* return(NULL); */
|
||
return(-1);
|
||
}
|
||
bzero((char *)&to, S_AD_SZ);
|
||
to.sin_family = AF_INET;
|
||
bcopy((char *) &newhostaddr, (char *)&to.sin_addr, 4);
|
||
if(hostaddr) bcopy(&to,hostaddr, S_AD_SZ);
|
||
}
|
||
else {
|
||
pfs_enable = tmp;
|
||
bzero((char *)&to, S_AD_SZ);
|
||
to.sin_family = host->h_addrtype;
|
||
#ifdef CUTCP
|
||
bcopy((char *) &host->h_addr, (char *)&to.sin_addr, host->h_length);
|
||
#else
|
||
bcopy(host->h_addr, (char *)&to.sin_addr, host->h_length);
|
||
#endif
|
||
if(hostaddr) bcopy(&to,hostaddr, S_AD_SZ);
|
||
}
|
||
}
|
||
else bcopy(hostaddr,&to, S_AD_SZ);
|
||
/* lmjm: Save away the hostname */
|
||
strncpy(to_hostname,
|
||
inet_ntoa(SUN_GNU_FIX *(struct in_addr *)&to.sin_addr),
|
||
sizeof(to_hostname)-1);
|
||
|
||
if(req_udp_port) to.sin_port = htons(req_udp_port);
|
||
else to.sin_port = dir_udp_port;
|
||
|
||
/* If a port was specified in hostaddr, use it, otherwise fill it in */
|
||
if(hostaddr) {
|
||
if(hostaddr->sin_port) to.sin_port = hostaddr->sin_port;
|
||
else hostaddr->sin_port = to.sin_port;
|
||
}
|
||
|
||
#ifndef CUTCP
|
||
/* Must open a new port each time. we do not want to see old */
|
||
/* responses to messages we are done with */
|
||
if ((lp = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
||
#ifdef DEBUG
|
||
if (pfs_debug)
|
||
fprintf(stderr,"dirsrv: Can't open socket\n");
|
||
#endif
|
||
perrno = DIRSEND_UDP_CANT;
|
||
ptlfree(pkt);
|
||
/* return(NULL); */
|
||
return(-1);
|
||
}
|
||
#endif /* not CUTCP */
|
||
|
||
/* Try to bind it to a privileged port - loop through candidate */
|
||
/* ports trying to bind. If failed, that's OK, we will let the */
|
||
/* system assign a non-privileged port later */
|
||
#ifndef CUTCP
|
||
if(!notprived) {
|
||
for(tmp = PROS_FIRST_PRIVP; tmp < PROS_FIRST_PRIVP+PROS_NUM_PRIVP;
|
||
tmp++) {
|
||
#endif
|
||
bzero((char *)&us, sizeof(us));
|
||
us.sin_family = AF_INET;
|
||
#ifndef CUTCP
|
||
us.sin_port = htons((u_short) tmp);
|
||
if (bind(lp, (struct sockaddr *)&us, sizeof(us))) {
|
||
if(errno != EADDRINUSE) {
|
||
notprived++;
|
||
break;
|
||
}
|
||
}
|
||
else break;
|
||
}
|
||
}
|
||
#else
|
||
us.sin_port = htons(PROS_FIRST_PRIVP);
|
||
netulisten(PROS_FIRST_PRIVP);
|
||
#endif
|
||
|
||
#ifndef USE_V3_PROT
|
||
/* Add header */
|
||
if(rdgram_priority) {
|
||
pkt->start -= 15;
|
||
pkt->length += 15;
|
||
*(pkt->start) = (char) 15;
|
||
bzero(pkt->start+9,4);
|
||
*(pkt->start+11) = 0x02;
|
||
bcopy(&priority,pkt->start+13,2);
|
||
}
|
||
else {
|
||
pkt->start -= 9;
|
||
pkt->length += 9;
|
||
*(pkt->start) = (char) 9;
|
||
}
|
||
this_conn_id = htons(next_conn_id++);
|
||
if(next_conn_id == 0) next_conn_id++;
|
||
bcopy(&this_conn_id,pkt->start+1,2);
|
||
bcopy(&one,pkt->start+3,2);
|
||
bcopy(&one,pkt->start+5,2);
|
||
bzero(pkt->start+7,2);
|
||
#endif
|
||
|
||
#ifdef DEBUG
|
||
if (pfs_debug > 2) {
|
||
#ifndef USE_V3_PROT
|
||
if (to.sin_family == AF_INET) {
|
||
if(req_udp_port)
|
||
fprintf(stderr,"Sending message to %s+%d(%d)...",
|
||
to_hostname, req_udp_port, ntohs(this_conn_id));
|
||
else fprintf(stderr,"Sending message to %s(%d)...",
|
||
to_hostname, ntohs(this_conn_id));
|
||
}
|
||
#else
|
||
if (to.sin_family == AF_INET)
|
||
fprintf(stderr,"Sending message to %s...", to_hostname);
|
||
#endif /* USE_V3_PROT */
|
||
else
|
||
fprintf(stderr,"Sending message...");
|
||
(void) fflush(stderr);
|
||
}
|
||
#endif /* DEBUG */
|
||
|
||
first = ptalloc();
|
||
next = first;
|
||
|
||
#ifndef CUTCP
|
||
return(lp);
|
||
#else
|
||
return(1);
|
||
#endif /* CUTCP */
|
||
}
|
||
|
||
/* - - - - - - - - */
|
||
/*
|
||
* This used to be a label to goto to retry the last packet. Now we resend
|
||
* the packet and call keepWaitingDirsend() to wait for a reply. (We
|
||
* call keepWaitingDirsend() because formerly the code dropped through
|
||
* the keep_waiting label.)
|
||
*/
|
||
static void
|
||
retryDirsend()
|
||
{
|
||
#ifdef CUTCP
|
||
int lretry = 3;
|
||
#endif
|
||
gaps = ackpend = 0;
|
||
|
||
#ifndef CUTCP
|
||
ns = sendto(lp,(char *)(pkt->start), pkt->length, 0, (struct sockaddr *)&to, S_AD_SZ);
|
||
#else
|
||
while(--lretry) {
|
||
ns = netusend(&to.sin_addr,ntohs(to.sin_port),ntohs(us.sin_port),
|
||
(char *) pkt->start, pkt->length);
|
||
if(!ns)
|
||
break;
|
||
Stask();
|
||
Stask();
|
||
Stask();
|
||
}
|
||
#endif /* CUTCP */
|
||
|
||
#ifndef CUTCP
|
||
if(ns != pkt->length) {
|
||
#else
|
||
if(ns != 0) {
|
||
#endif
|
||
#ifdef DEBUG
|
||
if (pfs_debug) {
|
||
fprintf(stderr,"\nsent only %d/%d: ",ns, pkt->length);
|
||
perror("");
|
||
}
|
||
#endif
|
||
close(lp);
|
||
perrno = DIRSEND_NOT_ALL_SENT;
|
||
ptlfree(first);
|
||
ptlfree(pkt);
|
||
/* return(NULL); */
|
||
dirsendReturn = NULL;
|
||
dirsendDone = DSRET_SEND_ERROR;
|
||
}
|
||
#ifdef DEBUG
|
||
if (pfs_debug > 2) fprintf(stderr,"Sent.\n");
|
||
#endif
|
||
keepWaitingDirsend();
|
||
}
|
||
|
||
/* - - - - - - - - */
|
||
/*
|
||
* This used to be a label to goto to set the appropriate timeout value
|
||
* and blocked in select(). Now we set selwait and the SELECTARGs to the
|
||
* appropriate values, and in X register a new timeout, then return to
|
||
* allow event processing.
|
||
*/
|
||
static void
|
||
keepWaitingDirsend()
|
||
{
|
||
/* We come back to this point (by a goto) if the packet */
|
||
/* received is only part of the response, or if the */
|
||
/* response came from the wrong host */
|
||
|
||
#ifdef DEBUG
|
||
if (pfs_debug > 2) fprintf(stderr,"Waiting for reply...");
|
||
#endif
|
||
|
||
#ifndef CUTCP
|
||
FD_ZERO(&readfds);
|
||
FD_SET(lp, &readfds);
|
||
#endif
|
||
|
||
if(ackpend) selwait = &ackwait;
|
||
else if(gaps) selwait = &gapwait;
|
||
else selwait = &timeout;
|
||
}
|
||
|
||
/* - - - - - - - - */
|
||
/*
|
||
* This routine is called when a timeout occurs. It includes the code that
|
||
* was formerly used when select() returned 0 (indicating a timeout).
|
||
*/
|
||
/*ARGSUSED*/
|
||
static void
|
||
timeoutProc(client_data,id)
|
||
XtPointer client_data;
|
||
XtIntervalId *id;
|
||
{
|
||
if (gaps || ackpend) { /* Send acknowledgment */
|
||
/* Acks are piggybacked on retries - If we have received */
|
||
/* an ack from the server, then the packet sent is only */
|
||
/* an ack and the rest of the message will be empty */
|
||
#ifdef DEBUG
|
||
if (pfs_debug > 2) {
|
||
fprintf(stderr,"Acknowledging (%s).\n",
|
||
(ackpend ? "requested" : "gaps"));
|
||
}
|
||
#endif
|
||
retryDirsend();
|
||
return;
|
||
}
|
||
|
||
if (retries-- > 0) {
|
||
timeout.tv_sec = CLIENT_DIRSRV_BACKOFF(timeout.tv_sec);
|
||
#ifdef DEBUG
|
||
if (pfs_debug > 2) {
|
||
fprintf(stderr,"Timed out. Setting timeout to %d seconds.\n",
|
||
timeout.tv_sec);
|
||
}
|
||
#endif
|
||
retryDirsend();
|
||
return;
|
||
}
|
||
|
||
#ifdef DEBUG
|
||
if (pfs_debug) {
|
||
fprintf(stderr, "select failed(timeoutProc): readfds=%x ",
|
||
readfds);
|
||
perror("");
|
||
}
|
||
#endif
|
||
#ifndef CUTCP
|
||
close(lp);
|
||
#endif
|
||
perrno = DIRSEND_SELECT_FAILED;
|
||
ptlfree(first);
|
||
ptlfree(pkt);
|
||
/* return(NULL); */
|
||
dirsendReturn = NULL;
|
||
dirsendDone = DSRET_TIMEOUT;
|
||
}
|
||
|
||
/* - - - - - - - - */
|
||
/*
|
||
* This function is called whenever there's something to read on the
|
||
* connection. It includes the code that was run when select() returned
|
||
* greater than 0 (indicating read ready).
|
||
*/
|
||
/*ARGSUSED*/
|
||
static void
|
||
readProc(client_data,source,id)
|
||
XtPointer client_data;
|
||
int *source;
|
||
XtInputId *id;
|
||
{
|
||
#ifdef CUTCP
|
||
int lretry = 3;
|
||
#endif
|
||
|
||
from_sz = sizeof(from);
|
||
next->start = next->dat;
|
||
|
||
#ifndef CUTCP
|
||
if ((nr = recvfrom(lp, next->start, sizeof(next->dat), 0, (struct sockaddr *)&from, &from_sz)) < 0) {
|
||
#else
|
||
nr = neturead(next->start);
|
||
if (nr < 1) {
|
||
#endif
|
||
#ifdef DEBUG
|
||
if (pfs_debug) perror("recvfrom");
|
||
#endif
|
||
#ifndef CUTCP
|
||
close(lp);
|
||
#endif
|
||
perrno = DIRSEND_BAD_RECV;
|
||
ptlfree(first);
|
||
ptlfree(pkt);
|
||
/* return(NULL) */
|
||
dirsendReturn = NULL;
|
||
dirsendDone = DSRET_RECV_ERROR;
|
||
return;
|
||
}
|
||
|
||
next->length = nr;
|
||
next->start[next->length] = 0;
|
||
|
||
#ifdef DEBUG
|
||
if (pfs_debug > 2)
|
||
fprintf(stderr,"Received packet from %s\n",
|
||
inet_ntoa(SUN_GNU_FIX *(struct in_addr *)&from.sin_addr));
|
||
#endif
|
||
|
||
|
||
/* For the current format, if the first byte is less than */
|
||
/* 20, then the first two bits are a version number and the next six */
|
||
/* are the header length (including the first byte). */
|
||
if((hdr_len = (unsigned char) *(next->start)) < 20) {
|
||
ctlptr = next->start + 1;
|
||
next->seq = 0;
|
||
if(hdr_len >= 3) { /* Connection ID */
|
||
bcopy(ctlptr,&stmp,2);
|
||
if(stmp) pkt_cid = ntohs(stmp);
|
||
ctlptr += 2;
|
||
}
|
||
if(pkt_cid && this_conn_id && (pkt_cid != ntohs(this_conn_id))) {
|
||
/* The packet is not for us */
|
||
/* goto keep_waiting; */
|
||
keepWaitingDirsend();
|
||
return;
|
||
}
|
||
if(hdr_len >= 5) { /* Packet number */
|
||
bcopy(ctlptr,&stmp,2);
|
||
next->seq = ntohs(stmp);
|
||
ctlptr += 2;
|
||
}
|
||
else { /* No packet number specified, so this is the only one */
|
||
next->seq = 1;
|
||
nd_pkts = 1;
|
||
}
|
||
if(hdr_len >= 7) { /* Total number of packets */
|
||
bcopy(ctlptr,&stmp,2); /* 0 means don't know */
|
||
if(stmp) nd_pkts = ntohs(stmp);
|
||
ctlptr += 2;
|
||
}
|
||
if(hdr_len >= 9) { /* Receievd through */
|
||
bcopy(ctlptr,&stmp,2); /* 1 means received request */
|
||
#ifndef USE_V3_PROT
|
||
if((stmp) && (ntohs(stmp) == 1)) {
|
||
/* Future retries will be acks only */
|
||
pkt->length = 9;
|
||
bcopy(&zero,pkt->start+3,2);
|
||
#ifdef DEBUG
|
||
if(pfs_debug > 2)
|
||
fprintf(stderr,"Server acked request - retries will be acks only\n");
|
||
#endif
|
||
}
|
||
#endif
|
||
ctlptr += 2;
|
||
}
|
||
if(hdr_len >= 11) { /* Backoff */
|
||
bcopy(ctlptr,&stmp,2);
|
||
if(stmp) {
|
||
backoff = ntohs(stmp);
|
||
#ifdef DEBUG
|
||
if(pfs_debug > 2)
|
||
fprintf(stderr,"Backing off to %d seconds\n", backoff);
|
||
#endif
|
||
timeout.tv_sec = backoff;
|
||
if ((backoff > 60) && (first == next) && (no_pkts == 0)) {
|
||
/* Probably a long queue on the server - don't give up */
|
||
retries = client_dirsrv_retry;
|
||
}
|
||
}
|
||
ctlptr += 2;
|
||
}
|
||
if(hdr_len >= 12) { /* Flags (1st byte) */
|
||
bcopy(ctlptr,&rdflag11,1);
|
||
if(rdflag11 & 0x80) {
|
||
#ifdef DEBUG
|
||
if(pfs_debug > 2)
|
||
fprintf(stderr,"Ack requested\n");
|
||
#endif
|
||
ackpend++;
|
||
}
|
||
if(rdflag11 & 0x40) {
|
||
#ifdef DEBUG
|
||
if(pfs_debug > 2)
|
||
fprintf(stderr,"Sequenced control packet\n");
|
||
#endif
|
||
next->length = -1;
|
||
scpflag++;
|
||
}
|
||
ctlptr += 1;
|
||
}
|
||
if(hdr_len >= 13) { /* Flags (2nd byte) */
|
||
/* Reserved for future use */
|
||
bcopy(ctlptr,&rdflag12,1);
|
||
ctlptr += 1;
|
||
}
|
||
if(next->seq == 0) {
|
||
/* goto keep_waiting; */
|
||
keepWaitingDirsend();
|
||
return;
|
||
}
|
||
if(next->length >= 0) next->length -= hdr_len;
|
||
next->start += hdr_len;
|
||
goto done_old;
|
||
}
|
||
|
||
pkt_cid = 0;
|
||
|
||
/* if intermediate format (between old and new), then process */
|
||
/* and go to done_old */
|
||
ctlptr = next->start + max(0,next->length-20);
|
||
while(*ctlptr) ctlptr++;
|
||
/* Control fields start after the terminating null */
|
||
ctlptr++;
|
||
/* Until old version are gone, must be 4 extra bytes minimum */
|
||
/* When no version 3 servers, can remove the -4 */
|
||
if(ctlptr < (next->start + next->length - 4)) {
|
||
/* Connection ID */
|
||
bcopy(ctlptr,&stmp,2);
|
||
if(stmp) pkt_cid = ntohs(stmp);
|
||
ctlptr += 2;
|
||
if(pkt_cid && this_conn_id && (pkt_cid != ntohs(this_conn_id))) {
|
||
/* The packet is not for us */
|
||
/* goto keep_waiting; */
|
||
keepWaitingDirsend();
|
||
return;
|
||
}
|
||
/* Packet number */
|
||
if(ctlptr < (next->start + next->length)) {
|
||
bcopy(ctlptr,&stmp,2);
|
||
next->seq = ntohs(stmp);
|
||
ctlptr += 2;
|
||
}
|
||
/* Total number of packets */
|
||
if(ctlptr < (next->start + next->length)) {
|
||
bcopy(ctlptr,&stmp,2);
|
||
if(stmp) nd_pkts = ntohs(stmp);
|
||
ctlptr += 2;
|
||
}
|
||
/* Receievd through */
|
||
if(ctlptr < (next->start + next->length)) {
|
||
/* Not supported by clients */
|
||
ctlptr += 2;
|
||
}
|
||
/* Backoff */
|
||
if(ctlptr < (next->start + next->length)) {
|
||
bcopy(ctlptr,&stmp,2);
|
||
backoff = ntohs(stmp);
|
||
#ifdef DEBUG
|
||
if(pfs_debug > 2)
|
||
fprintf(stderr,"Backing off to %d seconds\n", backoff);
|
||
#endif
|
||
if(backoff) timeout.tv_sec = backoff;
|
||
ctlptr += 2;
|
||
}
|
||
if(next->seq == 0) {
|
||
/* goto keep_waiting; */
|
||
keepWaitingDirsend();
|
||
return;
|
||
}
|
||
goto done_old;
|
||
|
||
}
|
||
|
||
/* Notes that we have to start searching 11 bytes before the */
|
||
/* expected start of the MULTI-PACKET line because the message */
|
||
/* might include up to 10 bytes of data after the trailing null */
|
||
/* The order of those bytes is two bytes each for Connection ID */
|
||
/* Packet-no, of, Received-through, Backoff */
|
||
seqtxt = nlsindex(next->start + max(0,next->length - 40),"MULTI-PACKET");
|
||
if(seqtxt) seqtxt+= 13;
|
||
|
||
if((nd_pkts == 0) && (no_pkts == 0) && (seqtxt == NULL)) goto all_done;
|
||
|
||
tmp = sscanf(seqtxt,"%d OF %d", &(next->seq), &nd_pkts);
|
||
#ifdef DEBUG
|
||
if (pfs_debug && (tmp == 0))
|
||
fprintf(stderr,"Cant read packet sequence number: %s", seqtxt);
|
||
#endif
|
||
done_old:
|
||
#ifdef DEBUG
|
||
if(pfs_debug > 2) fprintf(stderr,"Packet %d of %d\n",next->seq,nd_pkts);
|
||
#endif
|
||
if ((first == next) && (no_pkts == 0)) {
|
||
if(first->seq == 1) {
|
||
comp_thru = first;
|
||
/* If only one packet, then return it */
|
||
if(nd_pkts == 1) goto all_done;
|
||
}
|
||
else gaps++;
|
||
no_pkts = 1;
|
||
next = ptalloc();
|
||
/* goto keep_waiting; */
|
||
keepWaitingDirsend();
|
||
return;
|
||
}
|
||
|
||
if(comp_thru && (next->seq <= comp_thru->seq))
|
||
ptfree(next);
|
||
else if (next->seq < first->seq) {
|
||
vtmp = first;
|
||
first = next;
|
||
first->next = vtmp;
|
||
first->previous = NULL;
|
||
vtmp->previous = first;
|
||
if(first->seq == 1) comp_thru = first;
|
||
no_pkts++;
|
||
}
|
||
else {
|
||
vtmp = (comp_thru ? comp_thru : first);
|
||
while (vtmp->seq < next->seq) {
|
||
if(vtmp->next == NULL) {
|
||
vtmp->next = next;
|
||
next->previous = vtmp;
|
||
next->next = NULL;
|
||
no_pkts++;
|
||
goto ins_done;
|
||
}
|
||
vtmp = vtmp->next;
|
||
}
|
||
if(vtmp->seq == next->seq)
|
||
ptfree(next);
|
||
else {
|
||
vtmp->previous->next = next;
|
||
next->previous = vtmp->previous;
|
||
next->next = vtmp;
|
||
vtmp->previous = next;
|
||
no_pkts++;
|
||
}
|
||
}
|
||
|
||
ins_done:
|
||
|
||
while(comp_thru && comp_thru->next &&
|
||
(comp_thru->next->seq == (comp_thru->seq + 1))) {
|
||
comp_thru = comp_thru->next;
|
||
#ifndef USE_V3_PROT
|
||
recvd_thru = htons(comp_thru->seq);
|
||
bcopy(&recvd_thru,pkt->start+7,2); /* Let server know we got it */
|
||
#endif
|
||
/* We've made progress, so reset retry count */
|
||
retries = client_dirsrv_retry;
|
||
/* Also, next retry will be only an acknowledgement */
|
||
/* but for now, we can't fill in the ack field */
|
||
#ifdef DEBUG
|
||
if(pfs_debug > 2)
|
||
fprintf(stderr,"Packets now received through %d\n",comp_thru->seq);
|
||
#endif
|
||
}
|
||
|
||
/* See if there are any gaps */
|
||
if(!comp_thru || comp_thru->next) gaps++;
|
||
else gaps = 0;
|
||
|
||
if ((nd_pkts == 0) || (no_pkts < nd_pkts)) {
|
||
next = ptalloc();
|
||
/* goto keep_waiting; */
|
||
keepWaitingDirsend();
|
||
return;
|
||
}
|
||
|
||
all_done:
|
||
if(ackpend) { /* Send acknowledgement if requested */
|
||
#ifdef DEBUG
|
||
if (pfs_debug > 2) {
|
||
if (to.sin_family == AF_INET)
|
||
fprintf(stderr,"Acknowledging final packet to %s(%d)\n",
|
||
to_hostname, ntohs(this_conn_id));
|
||
else
|
||
fprintf(stderr,"Acknowledging final packet\n");
|
||
(void) fflush(stderr);
|
||
}
|
||
#endif
|
||
#ifndef CUTCP
|
||
ns = sendto(lp,(char *)(pkt->start), pkt->length, 0, (struct sockaddr *)&to, S_AD_SZ);
|
||
#else
|
||
while(--lretry) {
|
||
ns = netusend(&to.sin_addr, ntohs(to.sin_port), ntohs(us.sin_port),(char *) pkt->start, pkt->length);
|
||
if(!ns)
|
||
break;
|
||
Stask();
|
||
Stask();
|
||
}
|
||
#endif
|
||
|
||
#ifndef CUTCP
|
||
if(ns != pkt->length) {
|
||
#else
|
||
if(ns != 0) {
|
||
#endif
|
||
|
||
#ifdef DEBUG
|
||
if (pfs_debug) {
|
||
fprintf(stderr,"\nsent only %d/%d: ",ns, pkt->length);
|
||
perror("");
|
||
}
|
||
#endif
|
||
}
|
||
|
||
}
|
||
#ifndef CUTCP
|
||
close(lp);
|
||
#endif
|
||
ptlfree(pkt);
|
||
|
||
/* Get rid of any sequenced control packets */
|
||
if(scpflag) {
|
||
while(first && (first->length < 0)) {
|
||
vtmp = first;
|
||
first = first->next;
|
||
if(first) first->previous = NULL;
|
||
ptfree(vtmp);
|
||
}
|
||
vtmp = first;
|
||
while(vtmp && vtmp->next) {
|
||
if(vtmp->next->length < 0) {
|
||
if(vtmp->next->next) {
|
||
vtmp->next = vtmp->next->next;
|
||
ptfree(vtmp->next->previous);
|
||
vtmp->next->previous = vtmp;
|
||
}
|
||
else {
|
||
ptfree(vtmp->next);
|
||
vtmp->next = NULL;
|
||
}
|
||
}
|
||
vtmp = vtmp->next;
|
||
}
|
||
}
|
||
|
||
/* return(first); */
|
||
dirsendReturn = first;
|
||
dirsendDone = DSRET_DONE;
|
||
|
||
}
|
||
|
||
static void
|
||
processEvent()
|
||
{
|
||
#ifdef CUTCP
|
||
unsigned long now;
|
||
#endif
|
||
/* select - either recv is ready, or timeout */
|
||
/* see if timeout or error or wrong descriptor */
|
||
#ifndef CUTCP
|
||
tmp = select(lp + 1, &readfds, (SELECTARG *)0, (SELECTARG *)0, selwait);
|
||
if (tmp == 0) {
|
||
timeoutProc(NULL,&timerId);
|
||
} else if ((tmp < 0) || !FD_ISSET(lp,&readfds)) {
|
||
#ifdef DEBUG
|
||
if (pfs_debug) {
|
||
fprintf(stderr, "select failed(processEvent): readfds=%x ",
|
||
readfds);
|
||
perror("");
|
||
}
|
||
#endif
|
||
close(lp);
|
||
#else /* CUTCP's flood. */
|
||
/* while not timeout in selwait loop, stask looking for uevents */
|
||
now = time(NULL) + selwait->tv_sec;
|
||
#ifdef DEBUG
|
||
if(pfs_debug) {
|
||
fprintf(stderr,"Waiting %d seconds\n",selwait->tv_sec);
|
||
}
|
||
|
||
#endif
|
||
while(now > time(NULL)) {
|
||
int i, cl, dat;
|
||
|
||
Stask();
|
||
if (0 < (i = Sgetevent(USERCLASS, &cl, &dat))) {
|
||
/* got a user class event */
|
||
if(cl == USERCLASS &&
|
||
i == UDPDATA) {
|
||
readProc(NULL,&lp,&inputId);
|
||
return;
|
||
}
|
||
}
|
||
if(kbhit()) {
|
||
int c = getch();
|
||
if(c == 27 || c == 3)
|
||
break;
|
||
fprintf(stderr,"Press <ESCAPE> to abort\n");
|
||
}
|
||
}
|
||
if(now <= time(NULL)) { /* timeout */
|
||
timeoutProc(NULL,&timerId);
|
||
return;
|
||
}
|
||
|
||
#endif /* CUTCP */
|
||
perrno = DIRSEND_SELECT_FAILED;
|
||
ptlfree(first);
|
||
ptlfree(pkt);
|
||
/* return(NULL); */
|
||
dirsendReturn = NULL;
|
||
dirsendDone = DSRET_SELECT_ERROR;
|
||
#ifndef CUTCP
|
||
} else {
|
||
readProc(NULL,&lp,&inputId);
|
||
}
|
||
#endif /* CUTCP */
|
||
}
|
||
|
||
void
|
||
abortDirsend()
|
||
{
|
||
if (!dirsendDone) {
|
||
#ifndef CUTCP
|
||
close(lp);
|
||
#endif
|
||
ptlfree(first);
|
||
ptlfree(pkt);
|
||
dirsendReturn = NULL;
|
||
dirsendDone = DSRET_ABORTED;
|
||
}
|
||
return;
|
||
}
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]get_pauth.c
|
||
$DECK
|
||
/*
|
||
* Copyright (c) 1989, 1990 by the University of Washington
|
||
*
|
||
* For copying and distribution information, please see the file
|
||
* <copyright.h>.
|
||
*/
|
||
|
||
#include <copyright.h>
|
||
#include <stdio.h>
|
||
#ifndef VMS
|
||
# include <sys/types.h> /* this may/will define FD_SET etc */
|
||
# include <pmachine.h>
|
||
#endif
|
||
|
||
#ifdef NEED_STRING_H
|
||
# include <string.h>
|
||
#else
|
||
# include <strings.h>
|
||
#endif
|
||
|
||
#ifndef VMS
|
||
# if defined(MSDOS) && !defined(OS2)
|
||
# ifndef CUTCP
|
||
# include <rwconf.h>
|
||
# endif
|
||
# else
|
||
# include <pwd.h>
|
||
# endif
|
||
#else
|
||
# include <jpidef.h>
|
||
# include <vms.h>
|
||
#endif
|
||
|
||
#include <pcompat.h>
|
||
#include <pauthent.h>
|
||
|
||
PAUTH
|
||
get_pauth(type)
|
||
int type;
|
||
{
|
||
static PAUTH_ST no_auth_st;
|
||
static PAUTH no_auth = NULL;
|
||
#if !defined(VMS) && !defined(MSDOS) || defined(OS2)
|
||
struct passwd *whoiampw;
|
||
#else
|
||
char username[13];
|
||
unsigned short usernamelen;
|
||
struct {
|
||
unsigned short buflen;
|
||
unsigned short itmcod;
|
||
char *bufadr;
|
||
unsigned short *retlenadr;
|
||
unsigned long null;
|
||
} jpi_itemlist;
|
||
#endif
|
||
|
||
if(no_auth == NULL) {
|
||
no_auth = &no_auth_st;
|
||
strcpy(no_auth->auth_type,"UNAUTHENTICATED");
|
||
|
||
/* find out who we are */
|
||
#ifndef VMS
|
||
#if defined(MSDOS) && !defined(OS2)
|
||
#ifndef CUTCP
|
||
if (!getconf("general", "user", no_auth->authenticator, 250)
|
||
|| (strlen (no_auth->authenticator) == 0))
|
||
#endif
|
||
strcpy(no_auth->authenticator,"nobody");
|
||
#else /* not MSDOS */
|
||
DISABLE_PFS(whoiampw = getpwuid(getuid()));
|
||
if (whoiampw == 0) strcpy(no_auth->authenticator,"nobody");
|
||
else strcpy(no_auth->authenticator, whoiampw->pw_name);
|
||
#endif /* not MSDOS */
|
||
#else
|
||
jpi_itemlist.buflen = sizeof(username);
|
||
jpi_itemlist.itmcod = JPI$_USERNAME;
|
||
jpi_itemlist.bufadr = &username;
|
||
jpi_itemlist.retlenadr = &usernamelen;
|
||
jpi_itemlist.null = 0;
|
||
if (SYS$GETJPI(0, 0, 0, &jpi_itemlist, 0, 0, 0) & 0x1)
|
||
{
|
||
username[usernamelen] = 0;
|
||
strcpy(no_auth->authenticator, username);
|
||
} else
|
||
strcpy(no_auth->authenticator, "nobody");
|
||
#endif
|
||
}
|
||
return(no_auth);
|
||
}
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]get_vdir.c
|
||
$DECK
|
||
/*
|
||
* Copyright (c) 1989, 1990, 1991 by the University of Washington
|
||
*
|
||
* For copying and distribution information, please see the file
|
||
* <copyright.h>.
|
||
*/
|
||
|
||
#include <copyright.h>
|
||
#include <stdio.h>
|
||
|
||
#include <pfs.h>
|
||
#include <pprot.h>
|
||
#include <perrno.h>
|
||
#include <pcompat.h>
|
||
#include <pauthent.h>
|
||
#include <pmachine.h>
|
||
|
||
#ifdef NEED_STRING_H
|
||
# include <string.h>
|
||
#else
|
||
# include <strings.h>
|
||
#endif
|
||
|
||
#ifdef DEBUG
|
||
extern int pfs_debug;
|
||
#endif
|
||
|
||
extern int pwarn;
|
||
extern char p_warn_string[];
|
||
extern int perrno;
|
||
extern char p_err_string[];
|
||
|
||
/*
|
||
* get_vdir - Get contents of a directory given its location
|
||
*
|
||
* GET_VDIR 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: dhost - Host on which directory resides
|
||
* dfile - Directory on that host
|
||
* components - The names from the directory we want
|
||
* dir - Structure to be filled in
|
||
* flags - Options. See FLAGS
|
||
* filters - filters to be applied to result
|
||
* acomp - Pointer to remaining components
|
||
*
|
||
* 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_ATTRIB - Request attributes from directory server
|
||
* GVD_NOSORT - Do not sort links when adding to directory
|
||
*
|
||
* RETURNS: PSUCCESS (0) or error code
|
||
* On some codes addition information in p_err_string
|
||
*
|
||
* 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
|
||
* get_vdir will return all links in the requested directory.
|
||
*
|
||
* BUGS: Doesn't process union links yet
|
||
* Doesn't process errors returned from server
|
||
* Doesn't expand union links if requested to
|
||
*/
|
||
int
|
||
get_vdir(dhost,dfile,components,dir,flags,filters,acomp)
|
||
char *dhost; /* Host on which directory resides */
|
||
char *dfile; /* Name of file on that host */
|
||
char *components; /* Component name (wildcards allowed) */
|
||
PVDIR dir; /* Structure to be filled in */
|
||
long flags; /* Flags */
|
||
VLINK filters; /* Filters to be applied to result */
|
||
char *acomp; /* Components left to be resolved */
|
||
{
|
||
PTEXT request; /* Text of request to dir server */
|
||
PTEXT resp; /* Response from dir server */
|
||
|
||
char ulcomp[MAX_VPATH];/* Work space for new current component */
|
||
char *comp = components;
|
||
|
||
VLINK cur_link = NULL;/* Current link being filled in */
|
||
VLINK exp = NULL; /* The current ulink being expanded */
|
||
VLINK pul = NULL; /* Prev union link (insert new one after it) */
|
||
VLINK l; /* Temp link pointer */
|
||
int mcomp; /* Flag - check multiple components */
|
||
int unresp; /* Flag - received unresolved response */
|
||
int getattrib = 0; /* Get attributes from server */
|
||
int vl_insert_flag; /* Flags to vl_insert */
|
||
|
||
int fwdcnt = MAX_FWD_DEPTH;
|
||
|
||
int no_links = 0; /* Count of number of links found */
|
||
|
||
char options[40]; /* LIST option */
|
||
char *opt; /* After leading + */
|
||
|
||
PAUTH authinfo;
|
||
|
||
/* Treat null string like NULL (return entire directory) */
|
||
if(!components || !*components) comp = NULL;
|
||
|
||
if(acomp && !filters) mcomp = 1;
|
||
else mcomp = 0;
|
||
|
||
if(flags&GVD_ATTRIB) {
|
||
getattrib++;
|
||
flags &= (~GVD_ATTRIB);
|
||
}
|
||
|
||
if(flags&GVD_NOSORT) vl_insert_flag = VLI_NOSORT;
|
||
else vl_insert_flag = VLI_ALLOW_CONF;
|
||
flags &= (~GVD_NOSORT);
|
||
|
||
if(filters) comp = NULL;
|
||
|
||
perrno = 0;
|
||
|
||
authinfo = get_pauth(PFSA_UNAUTHENTICATED);
|
||
|
||
*options = '\0';
|
||
|
||
if(getattrib) {
|
||
strcat(options,"+ATTRIBUTES");
|
||
flags &= (~GVD_ATTRIB);
|
||
}
|
||
|
||
if(!filters) { /* Can't do remote expansion if filters to be applied */
|
||
if(flags == GVD_REMEXP) strcat(options,"+EXPAND");
|
||
if(flags == GVD_LREMEXP) strcat(options,"+LEXPAND");
|
||
}
|
||
|
||
/* If all we are doing is verifying that dfile is a directory */
|
||
/* then we do not want a big response from the directory */
|
||
/* server. A NOT-FOUND is sufficient. */
|
||
if(flags == GVD_VERIFY)
|
||
#ifdef NEWVERIFYOPT
|
||
strcat(options,"+VERIFY");
|
||
#else
|
||
comp = "%#$PRobably_nOn_existaNT$#%";
|
||
#endif
|
||
|
||
if(*options) opt = options+1;
|
||
else opt = "''";
|
||
|
||
startover:
|
||
request = ptalloc();
|
||
|
||
sprintf(request->start,
|
||
"VERSION %d %s\nAUTHENTICATOR %s %s\nDIRECTORY ASCII %s\nLIST %s COMPONENTS %s%s%s\n",
|
||
VFPROT_VNO, PFS_SW_ID, authinfo->auth_type,
|
||
authinfo->authenticator, dfile, opt,
|
||
(comp ? comp : ""), (mcomp ? "/" : ""),
|
||
(mcomp ? acomp : ""));
|
||
|
||
request->length = strlen(request->start);
|
||
|
||
#ifdef DEBUG
|
||
if(pfs_debug > 2)
|
||
fprintf(stderr,"Sending message to dirsrv:\n%s",request->start);
|
||
#endif
|
||
|
||
#if defined(MSDOS)
|
||
resp = dirsend(request,dhost,0L);
|
||
#else
|
||
resp = dirsend(request,dhost,0);
|
||
#endif
|
||
|
||
#ifdef DEBUG
|
||
if(pfs_debug && (resp == NULL)) {
|
||
fprintf(stderr,"Dirsend failed: %d\n",perrno);
|
||
}
|
||
#endif
|
||
|
||
/* If we don't get a response, then if the requested */
|
||
/* directory, return error, if a ulink, mark it unexpanded */
|
||
if(resp == NULL) {
|
||
if(exp) exp->expanded = FAILED;
|
||
else return(perrno);
|
||
}
|
||
|
||
unresp = 0;
|
||
|
||
/* Here we must parse reponse and put in directory */
|
||
/* While looking at each packet */
|
||
while(resp) {
|
||
PTEXT vtmp;
|
||
char *line;
|
||
|
||
vtmp = resp;
|
||
#ifdef DEBUG
|
||
if(pfs_debug > 3) fprintf(stderr,"%s\n",resp->start);
|
||
#endif
|
||
/* Look at each line in packet */
|
||
for(line = resp->start;line != NULL;line = nxtline(line)) {
|
||
switch (*line) {
|
||
|
||
/* Temporary variables to hold link info */
|
||
char l_linktype;
|
||
char l_name[MAX_DIR_LINESIZE];
|
||
char l_type[MAX_DIR_LINESIZE];
|
||
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;
|
||
char t_unresolved[MAX_DIR_LINESIZE];
|
||
int l_magic;
|
||
int tmp;
|
||
|
||
case 'L': /* LINK or LINK-INFO */
|
||
if(strncmp(line,"LINK-INFO",9) == 0) {
|
||
PATTRIB at;
|
||
PATTRIB last_at;
|
||
at = parse_attribute(line);
|
||
if(!at) break;
|
||
|
||
/* Cant have link info without a link */
|
||
if(!cur_link) {
|
||
perrno = DIRSRV_BAD_FORMAT;
|
||
atfree(at);
|
||
break;
|
||
}
|
||
|
||
if(cur_link->lattrib) {
|
||
last_at = cur_link->lattrib;
|
||
while(last_at->next) last_at = last_at->next;
|
||
at->previous = last_at;
|
||
last_at->next = at;
|
||
}
|
||
else {
|
||
cur_link->lattrib = at;
|
||
at->previous = NULL;
|
||
}
|
||
break;
|
||
}
|
||
|
||
/* Not LINK-INFO, must be LINK - if not check for error */
|
||
if(strncmp(line,"LINK",4) != 0) goto scanerr;
|
||
|
||
/* If only verifying, don't want to change dir */
|
||
if(flags == GVD_VERIFY) {
|
||
break;
|
||
}
|
||
/* If first link and some links in dir, free them */
|
||
if(!no_links++) {
|
||
if(dir->links) vllfree(dir->links); dir->links=NULL;
|
||
if(dir->ulinks) vllfree(dir->ulinks); dir->ulinks=NULL;
|
||
}
|
||
|
||
cur_link = vlalloc();
|
||
|
||
/* parse and insert file info */
|
||
tmp = sscanf(line,"LINK %c %s %s %s %s %s %s %d %d", &l_linktype,
|
||
l_type, l_name, l_htype, l_host,
|
||
l_ntype, l_fname, &(cur_link->version),
|
||
&(cur_link->f_magic_no));
|
||
|
||
if(tmp != 9) {
|
||
perrno = DIRSRV_BAD_FORMAT;
|
||
vlfree(cur_link);
|
||
break;
|
||
}
|
||
|
||
cur_link->linktype = l_linktype;
|
||
cur_link->type = stcopyr(l_type,cur_link->type);
|
||
cur_link->name = stcopyr(unquote(l_name),cur_link->name);
|
||
cur_link->hosttype = stcopyr(l_htype,cur_link->hosttype);
|
||
cur_link->host = stcopyr(l_host,cur_link->host);
|
||
cur_link->nametype = stcopyr(l_ntype,cur_link->nametype);
|
||
cur_link->filename = stcopyr(l_fname,cur_link->filename);
|
||
|
||
/* Double check to make sure we don't get */
|
||
/* back unwanted components */
|
||
/* OK to keep if special (URP) links */
|
||
/* or if mcomp specified */
|
||
if(!mcomp && (cur_link->linktype == 'L') &&
|
||
(!wcmatch(cur_link->name,comp))) {
|
||
vlfree(cur_link);
|
||
break;
|
||
}
|
||
|
||
/* If other optional info was sent back, it must */
|
||
/* also be parsed before inserting link *** */
|
||
|
||
|
||
if(cur_link->linktype == 'L')
|
||
vl_insert(cur_link,dir,vl_insert_flag);
|
||
else {
|
||
tmp = ul_insert(cur_link,dir,pul);
|
||
|
||
/* If inserted after pul, next one after cur_link */
|
||
if(pul && (!tmp || (tmp == UL_INSERT_SUPERSEDING)))
|
||
pul = cur_link;
|
||
}
|
||
|
||
break;
|
||
|
||
case 'F': /* FILTER, FAILURE or FORWARDED */
|
||
/* FORWARDED */
|
||
if(strncmp(line,"FORWARDED",9) == 0) {
|
||
if(fwdcnt-- <= 0) {
|
||
ptlfree(resp);
|
||
perrno = PFS_MAX_FWD_DEPTH;
|
||
return(perrno);
|
||
}
|
||
/* parse and start over */
|
||
|
||
tmp = sscanf(line,"FORWARDED %s %s %s %s %d %d",
|
||
l_htype,l_host,l_ntype,l_fname,
|
||
&l_version, &l_magic);
|
||
|
||
dhost = stcopy(l_host);
|
||
dfile = stcopy(l_fname);
|
||
|
||
if(tmp < 4) {
|
||
perrno = DIRSRV_BAD_FORMAT;
|
||
break;
|
||
}
|
||
|
||
ptlfree(resp);
|
||
goto startover;
|
||
}
|
||
if(strncmp(line,"FILTER",6) != 0) goto scanerr;
|
||
break;
|
||
|
||
|
||
case 'M': /* MULTI-PACKET (processed by dirsend) */
|
||
case 'P': /* PACKET (processed by dirsend) */
|
||
break;
|
||
|
||
case 'N': /* NOT-A-DIRECTORY or 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(flags == GVD_VERIFY) {
|
||
break;
|
||
}
|
||
|
||
/* If first link and some links in dir, free them */
|
||
if(!no_links++) {
|
||
if(dir->links) vllfree(dir->links);
|
||
if(dir->ulinks) vllfree(dir->ulinks);
|
||
dir->links = NULL;
|
||
dir->ulinks = NULL;
|
||
}
|
||
break;
|
||
}
|
||
/* If NOT-A-DIRECTORY or anything else, scan error */
|
||
goto scanerr;
|
||
|
||
case 'U': /* UNRESOLVED */
|
||
if(strncmp(line,"UNRESOLVED",10) != 0) {
|
||
goto scanerr;
|
||
}
|
||
tmp = sscanf(line,"UNRESOLVED %s", t_unresolved);
|
||
if(tmp < 1) {
|
||
perrno = DIRSRV_BAD_FORMAT;
|
||
break;
|
||
}
|
||
/* If multiple components were resolved */
|
||
if(strlen(t_unresolved) < strlen(acomp)) {
|
||
strcpy(ulcomp,acomp);
|
||
/* ulcomp is the components that were resolved */
|
||
*(ulcomp+strlen(acomp)-strlen(t_unresolved)-1) = '\0';
|
||
/* Comp gets the last component resolved */
|
||
comp = (char *) rindex(ulcomp,'/');
|
||
if(comp) comp++;
|
||
else comp = ulcomp;
|
||
/* Let rd_vdir know what remains */
|
||
strcpy(acomp,t_unresolved);
|
||
}
|
||
unresp = 1;
|
||
break;
|
||
|
||
case 'V': /* VERSION-NOT-SUPPORTED */
|
||
if(strncmp(line,"VERSION-NOT-SUPPORTED",21) == 0) {
|
||
perrno = DIRSRV_BAD_VERS;
|
||
return(perrno);
|
||
}
|
||
goto scanerr;
|
||
|
||
scanerr:
|
||
default:
|
||
if(*line && (tmp = scan_error(line))) {
|
||
ptlfree(resp);
|
||
return(tmp);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
resp = resp->next;
|
||
|
||
ptfree(vtmp);
|
||
}
|
||
|
||
/* We sent multiple components and weren't told any */
|
||
/* were unresolved */
|
||
if(mcomp && !unresp) {
|
||
/* ulcomp is the components that were resolved */
|
||
strcpy(ulcomp,acomp);
|
||
/* Comp gets the last component resolved */
|
||
comp = (char *) rindex(ulcomp,'/');
|
||
if(comp) comp++;
|
||
else comp = ulcomp;
|
||
/* If we have union links to resolve, only one component remains */
|
||
mcomp = 0;
|
||
/* Let rd_vdir know what remains */
|
||
*acomp = '\0';
|
||
}
|
||
|
||
/* If only verifying, we already know it is a directory */
|
||
if(flags == GVD_VERIFY) 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((flags & GVD_FIND) && dir->links && (!filters))
|
||
return(PSUCCESS);
|
||
|
||
/* If expand specified, and ulinks must be expanded, making sure */
|
||
/* that the order of the links is maintained properly */
|
||
|
||
expand_ulinks:
|
||
|
||
if((flags != GVD_UNION) && (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->type,"DIRECTORY") == 0) ||
|
||
(strcmp(l->type,"FILE") == 0)) {
|
||
l->expanded = TRUE;
|
||
exp = l;
|
||
pul = l;
|
||
dhost = l->host;
|
||
dfile = l->filename;
|
||
goto startover; /* was get_contents; */
|
||
}
|
||
else l->expanded = FAILED;
|
||
}
|
||
}
|
||
|
||
/* Double check to make sure we don't get */
|
||
/* back unwanted components */
|
||
/* OK to keep if special (URP) links */
|
||
if(components && *components) {
|
||
l = dir->links;
|
||
while(l) {
|
||
VLINK ol;
|
||
if((l->linktype == 'L') && (!wcmatch(l->name,components))) {
|
||
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;
|
||
}
|
||
}
|
||
|
||
return(PSUCCESS);
|
||
}
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]make.com
|
||
$DECK
|
||
$! --- MAKE.COM --- !x='f$verify(0)'
|
||
$! Description:
|
||
$! build the Archie client for VAX/VMS
|
||
$!
|
||
$! Written by Luke Brennan <brennan@coco.cchs.su.oz.au>
|
||
$!
|
||
$! Modifications:
|
||
$! Date Programmer Reason for modification.
|
||
$! 20-Jan-92 ldcb Initial coding.
|
||
$!
|
||
$!
|
||
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
$ Archie_EXECUTABLE := "archie.exe"
|
||
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
$! add a new call here with the appropriate new Archie server host(s)
|
||
$!
|
||
$ arg == 1
|
||
$ Call AddHost "archie.ans.net" "(USA [NY])"
|
||
$ Call AddHost "archie.rutgers.edu" "(USA [NJ])"
|
||
$ Call AddHost "archie.sura.net" "(USA [MD])"
|
||
$ Call AddHost "archie.unl.edu" "(USA [NE])"
|
||
$ Call AddHost "archie.mcgill.ca" "(Canada)"
|
||
$ Call AddHost "archie.funet.fi" "(Finland/Mainland Europe)"
|
||
$ Call AddHost "archie.au" "(Australia)"
|
||
$ Call AddHost "archie.doc.ic.ac.uk" "(Great Britain/Ireland)"
|
||
$ MAXHOSTS = arg - 1
|
||
$!
|
||
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
$! add a new call here with any new source file(s)
|
||
$! (P2 should be "SUPPORT" if intended for supporting an unknown TCPIP)
|
||
$!
|
||
$ arg == 1
|
||
$ Call AddSource "AQUERY"
|
||
$ Call AddSource "ARCHIE"
|
||
$ Call AddSource "ATALLOC"
|
||
$ Call AddSource "DIRSEND"
|
||
$ Call AddSource "GET_PAUTH"
|
||
$ Call AddSource "GET_VDIR"
|
||
$ Call AddSource "PERRMESG"
|
||
$ Call AddSource "PROCQUERY"
|
||
$ Call AddSource "PTALLOC"
|
||
$ Call AddSource "REGEX"
|
||
$ Call AddSource "STCOPY"
|
||
$ Call AddSource "SUPPORT"
|
||
$ Call AddSource "VLALLOC"
|
||
$ Call AddSource "VL_COMP"
|
||
$ Call AddSource "VMS_SUPPORT" "SUPPORT"
|
||
$ MAXSOURCEFILES = arg - 1
|
||
$!
|
||
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
$! add a call here with any supported TCP/IP implementations
|
||
$! P1 = name of TCP/IP product, P2 = cc/define to set,
|
||
$! P3 = logical to look for, P4 = location of link/OPT,
|
||
$! P5 = MINIMUM VERSION of TCP/IP to support
|
||
$!
|
||
$! Multinet should be last, as it can 'fake' a UCX if you want it to, so
|
||
$! UCX would come up as the 'real' net even though Multinet is used.
|
||
$!
|
||
$ arg == 1
|
||
$ Call AddTCPIP "UCX" "UCX" "UCX$DEVICE" "[.vms]ucx.opt"
|
||
$ Call AddTCPIP "WOLLONGONG" "WOLLONGONG" "TWG$TCP" "[.vms]woll.opt"
|
||
$ Call AddTCPIP "MULTINET" "MULTINET_30" "MULTINET" "[.vms]multi.opt" "V3.0"
|
||
$ MAXTCPIPTYPES = arg - 1
|
||
$!
|
||
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
$!
|
||
$ YES = (1.eq.1)
|
||
$ NO = (1.eq.0)
|
||
$!
|
||
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
$!
|
||
$ GoSub get_command_line_args
|
||
$ GoSub check_for_GNU_cc
|
||
$ GoSub check_which_TCPIP
|
||
$ GoSub ask_nearest_ARCHIE_HOST
|
||
$ GoSub check_for_strings_H
|
||
$ GoSub set_cc_defines
|
||
$ GoSub do_compiles
|
||
$ If (LINKAGE_REQUIRED)
|
||
$ Then GoSub do_link
|
||
$ Else Write Sys$OutPut "ARCHIE is up to date."
|
||
$ EndIF
|
||
$ Exit
|
||
$!
|
||
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
$!
|
||
$get_command_line_args:
|
||
$ cmdline = P1 + P2 + P3 + P4 + P5 + P6 + P7 + P8
|
||
$ If ((f$locate("DEBUG",cmdline) .ne. f$length(cmdline)) -
|
||
.or. (f$locate("DBG",cmdline) .ne. f$length(cmdline)))
|
||
$ Then debug := "/DeBug"
|
||
$ Else debug := "/NOdebug"
|
||
$ EndIF
|
||
$ If (f$locate("FORCE",cmdline) .ne. f$length(cmdline))
|
||
$ Then FORCEBUILD = YES
|
||
$ Else FORCEBUILD = NO
|
||
$ EndIF
|
||
$ If (f$locate("LINK",cmdline) .ne. f$length(cmdline))
|
||
$ Then FORCELINK = YES
|
||
$ Else FORCELINK = NO
|
||
$ EndIF
|
||
$ If ((f$locate("?",cmdline) .ne. f$length(cmdline)) -
|
||
.or. (f$locate("H",cmdline) .ne. f$length(cmdline)))
|
||
$ Then
|
||
$ Write Sys$Output "Usage:"
|
||
$ Write Sys$OutPut " @MAKE [<debug>|<force>|<link>|<help>]
|
||
$ EXIT
|
||
$ EndIF
|
||
$ RETURN
|
||
$!
|
||
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
$!
|
||
$CHECK_FOR_GNU_CC:
|
||
$ If (f$trnlnm("GNU_CC") .nes. "")
|
||
$ Then
|
||
$ cc := "GCC/Optimize/Include=([])"
|
||
$ gnu_cc = YES
|
||
$ Else
|
||
$ cc := "CC/Optimize=NOinline/Include=([])"
|
||
$ gnu_cc = NO
|
||
$ EndIF
|
||
$!
|
||
$ RETURN
|
||
$!
|
||
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
$! for product P1, cc/define=P2 if logical P3 present on system.
|
||
$! Libs/option = P4 if present. ALL get disregarded if less than version P5
|
||
$!
|
||
$CHECK_WHICH_TCPIP:
|
||
$ tcpip_flag :=
|
||
$ tcpip_libs :=
|
||
$ NO_TCPIP_SUPPORT = YES
|
||
$ i = 1
|
||
$tcp_loop:
|
||
$ If (i .gt. MAXTCPIPTYPES) Then GoTo tcp_check_done
|
||
$ If (f$type(tcpip_P2_'i') .eqs. "") Then GoTo tcp_check_done
|
||
$ If (f$type(tcpip_P3_'i') .nes. "")
|
||
$ Then
|
||
$ tcpip_logical = tcpip_P3_'i'
|
||
$ If (tcpip_logical .nes. "")
|
||
$ Then ! logical to look for
|
||
$ If (f$logical(tcpip_logical) .nes. "")
|
||
$ Then
|
||
$ tcpip_flag = tcpip_P2_'i'
|
||
$ tcpip_flag = f$fao(",!AS=1",tcpip_flag)
|
||
$ NO_TCPIP_SUPPORT = NO
|
||
$ If (f$type(tcpip_P4_'i') .nes. "")
|
||
$ Then ! link/OPT file location
|
||
$ tcpip_linkOPTs = tcpip_P4_'i'
|
||
$ If (tcpip_linkOPTs .nes. "")
|
||
$ Then
|
||
$ If (f$search(tcpip_linkOPTs) .nes. "")
|
||
$ Then
|
||
$ tcpip_libs = tcpip_P4_'i'
|
||
$ tcpip_libs = f$fao("!AS/Option",tcpip_libs)
|
||
$ EndIF
|
||
$ EndIF
|
||
$ EndIF
|
||
$ If (f$type(tcpip_P5_'i') .nes. "")
|
||
$ Then ! minimum version specified
|
||
$ If (tcpip_P5_'i' .nes. "")
|
||
$ Then
|
||
$ GoSub CheckIfVersionOK
|
||
$ If VERSION_TOO_EARLY
|
||
$ Then ! too early.. use SUPPORT files
|
||
$ tcpip_flag :=
|
||
$ tcpip_libs :=
|
||
$ NO_TCPIP_SUPPORT = YES
|
||
$ tcp_ver = tcpip_P5_'i'
|
||
$ tcp_name = tcpip_P1_'i'
|
||
$ Write Sys$OutPut f$fao( -
|
||
"Your version of !AS is earlier than !AS.",tcp_name,tcp_ver)
|
||
Write Sys$OutPut "MAKE will use STD support files instead."
|
||
$ EndIF
|
||
$ EndIF
|
||
$ EndIF
|
||
$ EndIF
|
||
$ EndIF
|
||
$ EndIF
|
||
$ i = i + 1
|
||
$ Goto tcp_loop
|
||
$tcp_check_done:
|
||
$ RETURN
|
||
$!
|
||
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
$!
|
||
$ASK_NEAREST_ARCHIE_HOST:
|
||
$GoSub CLRSCN
|
||
$ Write Sys$OutPut f$fao("!AS!/!/", -
|
||
" Enter the number of the ARCHIE HOST nearest you.")
|
||
$!
|
||
$ i = 1
|
||
$_display_loop:
|
||
$ If (i .gt. MAXHOSTS) Then GoTo _display_done
|
||
$ Write Sys$OutPut f$fao("!2SL) !25AS !AS",i,host_P1_'i',host_P2_'i')
|
||
$ i = i + 1
|
||
$ GoTo _display_loop
|
||
$_display_done:
|
||
$!
|
||
$ Assign/User_Mode/NOlog Sys$Command Sys$InPut
|
||
$_select_loop: ! get their selection
|
||
$ Read Sys$Command selection -
|
||
/End=_selection_made -
|
||
/Prompt="Enter number of your selection: "
|
||
$ If (selection .gt. MAXHOSTS)
|
||
$ Then
|
||
$ Write Sys$OutPut f$fao("!AS !2SL", "error: Options only go to", MAXHOSTS)
|
||
$ GoTo _select_loop
|
||
$ EndIF
|
||
$ ascii_string = f$edit(selection,"COLLAPSE,UPCASE")
|
||
$ ascii_char = f$extract(0,1,ascii_string)
|
||
$ If (.NOT. ("0" .les. ascii_char) .and. (ascii_char .les. "9"))
|
||
$ Then
|
||
$ Write Sys$OutPut -
|
||
f$fao("error: Enter option NUMBER (up to !2SL)", MAXHOSTS)
|
||
$ Goto _select_loop
|
||
$ EndIF
|
||
$!
|
||
$ local_archie = host_P1_'selection'
|
||
$!
|
||
$ RETURN
|
||
$!
|
||
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
$! If we're using VAXC then we need to grab STRINGS.H from SYS$LIBRARY.
|
||
$CHECK_FOR_STRINGS_H:
|
||
$ delete := delete
|
||
$ copy := copy
|
||
$ If (f$search("strings.h") .nes. "") Then delete/nolog/noconfirm []strings.h;*
|
||
$ If .NOT. (GNU_CC) Then copy/noconfirm sys$library:string.h []strings.h
|
||
$!
|
||
$ RETURN
|
||
$!
|
||
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
$! **NOTE** use of global symbol!!!
|
||
$! **NOTE** this is the only way I could pass it to the compile subroutine
|
||
$! **NOTE** without DCL and/or CC stripping off too many layers of quotes..
|
||
$! **NOTE** yeah.. I know.. It's ugly... you work it out!! :-)
|
||
$SET_CC_DEFINES:
|
||
$ archie_host = " """"""ARCHIE_HOST=""""""""''local_archie'"""""""" """""" "
|
||
$ cflags :== /define=(debug=1,funcs=1,noregex=1'tcpip_flag','archie_host')
|
||
$!
|
||
$RETURN
|
||
$!
|
||
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
$!
|
||
$DO_COMPILES:
|
||
$ GoSub CLRSCN
|
||
$ LINKAGE_REQUIRED == NO
|
||
$ If ("''f$type(Archie_EXECUTABLE)'" .nes. "")
|
||
$ Then
|
||
$ If (Archie_EXECUTABLE .nes. "")
|
||
$ Then If (f$search(Archie_EXECUTABLE) .eqs. "") Then LINKAGE_REQUIRED == YES
|
||
$ Else If (f$search("Archie.exe") .eqs. "") Then LINKAGE_REQUIRED == YES
|
||
$ EndIF
|
||
$ Else
|
||
$ If (f$search("Archie.exe") .nes. "") Then LINKAGE_REQUIRED == YES
|
||
$ EndIF
|
||
$ i = 1
|
||
$cc_loop:
|
||
$ If (i .gt. MAXSOURCEFILES) Then GoTo cc_done
|
||
$ source_file = source_P1_'i'
|
||
$ If ((f$type(source_P2_'i') .eqs. "") .or. (source_P2_'i' .eqs. ""))
|
||
$ Then Call Compile "''cc'" "''source_file'" "''debug'" 'FORCEBUILD'
|
||
$ Else
|
||
$ If ((NO_TCPIP_SUPPORT) .and. (source_P2_'i' .eqs. "SUPPORT"))
|
||
$ Then Call Compile "''cc'" "''source_file'" "''debug'" 'FORCEBUILD'
|
||
$ EndIF
|
||
$ EndIF
|
||
$ i = i + 1
|
||
$ GoTo cc_loop
|
||
$cc_done:
|
||
$ If (FORCELINK) Then LINKAGE_REQUIRED == YES
|
||
$!
|
||
$ RETURN
|
||
$!
|
||
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
$!
|
||
$DO_LINK:
|
||
$ If (f$type(Archie_EXECUTABLE) .nes. "")
|
||
$ Then
|
||
$ If (Archie_EXECUTABLE .nes. "")
|
||
$ Then executable := /Exec='Archie_EXECUTABLE'
|
||
$ Else executable := /Exec=Archie.exe
|
||
$ EndIF
|
||
$ Else
|
||
$ executable := /Exec=Archie.exe
|
||
$ EndIF
|
||
$ i = 1
|
||
$ object_files :=
|
||
$object_files_loop:
|
||
$ If (i .gt. MAXSOURCEFILES) Then GoTo object_files_done
|
||
$ object_file = source_P1_'i'
|
||
$ If ((f$type(source_P2_'i') .eqs. "") .or. (source_P2_'i' .eqs. ""))
|
||
$ Then object_files := 'object_files'+'object_file'
|
||
$ Else
|
||
$ If ((NO_TCPIP_SUPPORT) .and. (source_P2_'i' .eqs. "SUPPORT"))
|
||
$ Then object_files := 'object_files'+'object_file'
|
||
$ EndIF
|
||
$ EndIF
|
||
$ i = i + 1
|
||
$ GoTo object_files_loop
|
||
$object_files_done:
|
||
$ If (f$extract(0,1,object_files) .eqs. "+")
|
||
$ Then object_files = f$extract(1,f$length(object_files),object_files)
|
||
$ EndIF
|
||
$ If (tcpip_libs .nes. "")
|
||
$ Then object_files = object_files + ","
|
||
$ EndIF
|
||
$!
|
||
$ Set Verify
|
||
$ Link'debug''executable' 'object_files''tcpip_libs'
|
||
$ x='f$verify(0)'
|
||
$!
|
||
$ Write Sys$OutPut " "
|
||
$ Write Sys$OutPut " "
|
||
$ Write Sys$OutPut "Done! Define the symbol ARCHIE & fire away."
|
||
$!
|
||
$ RETURN
|
||
$!
|
||
$! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
$!
|
||
$CLRSCN:
|
||
$If (f$GetDVI("TT:","TT_ANSICRT")) ! ANSI compatible?
|
||
$Then
|
||
$ CSI = "x["
|
||
$ CSI[0,8] = 27
|
||
$ CLS = CSI + "H" + CSI +"2J"
|
||
$ Write Sys$OutPut CLS
|
||
$Else
|
||
$ Write Sys$Output "''f$fao("!/!/!/!/!/!/!/!/!/!/!/")
|
||
$ Write Sys$Output "''f$fao("!/!/!/!/!/!/!/!/!/!/!/!/")
|
||
$EndIF
|
||
$Return
|
||
$!
|
||
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
$!
|
||
$AddHOST: SUBROUTINE
|
||
$ host_P1_'arg' :== "''P1'"
|
||
$ host_P2_'arg' :== "''P2'"
|
||
$ arg == arg + 1 ! *NOTE* global symbols used...
|
||
$ENDSUBROUTINE
|
||
$!
|
||
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
$!
|
||
$AddSOURCE: SUBROUTINE
|
||
$ source_P1_'arg' :== "''P1'"
|
||
$ source_P2_'arg' :== "''P2'"
|
||
$ arg == arg + 1 ! *NOTE* global symbols used...
|
||
$ENDSUBROUTINE
|
||
$!
|
||
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
$!
|
||
$AddTCPIP: SUBROUTINE
|
||
$ tcpip_P1_'arg' :== "''P1'"
|
||
$ tcpip_P2_'arg' :== "''P2'"
|
||
$ tcpip_P3_'arg' :== "''P3'"
|
||
$ tcpip_P4_'arg' :== "''P4'"
|
||
$ tcpip_P5_'arg' :== "''P5'"
|
||
$ arg == arg + 1 ! *NOTE* global symbols used...
|
||
$ENDSUBROUTINE
|
||
$!
|
||
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
$! **NOTE** cflags is a GLOBAL symbol due to problems with quoted /Defines
|
||
$! **NOTE** not passing down correctly.. (I gave up!)
|
||
$Compile: SUBROUTINE
|
||
$ YES = (1.eq.1)
|
||
$! --- do a Make of only that source which has been modified since its
|
||
$! object code was generated or that is missing its object code.
|
||
$ cc = "''P1'"
|
||
$ source = "''P2'"
|
||
$ dbg = "''P3'"
|
||
$ FORCED = P4
|
||
$!
|
||
$source = source - ".C" + ".C"
|
||
$ t1 = f$search("''source'") ! source exists?
|
||
$ If (t1 .eqs. "") Then GoTo _error_source_missing ! YIPE!
|
||
$ source = source - ".C"
|
||
$ if (FORCED) Then GoTo _compile_the_source ! forced to compile
|
||
$ t1 = f$search("''source'.OBJ") ! object exist?
|
||
$ If (t1 .eqs. "") Then GoTo _compile_the_source ! object missing
|
||
$ t1 = f$file_attributes("''source'.OBJ","RDT") ! when was the OBJECT
|
||
$ t1 = f$cvtime(t1) ! produced? (rev date)
|
||
$ t2 = f$file_attributes("''source'.C","RDT") ! when was source last
|
||
$ t2 = f$cvtime(t2) ! modified?
|
||
$ If (t1 .ges. t2) Then GoTo _bypass_compile ! object still current
|
||
$_compile_the_source:
|
||
$ set verify
|
||
$ 'cc -
|
||
'cflags -
|
||
'dbg 'source
|
||
$ x='f$verify(0)'
|
||
$ LINKAGE_REQUIRED == YES
|
||
$ GoTo _cc_done
|
||
$_bypass_compile: ! didn't need to
|
||
$ GoTo _cc_done ! generate new OBJ file
|
||
$_error_source_missing:
|
||
$ Write Sys$OutPut "ERROR: unable to locate source file ''source'.C"
|
||
$_cc_done:
|
||
$ENDSUBROUTINE
|
||
$!
|
||
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
$!
|
||
$CHECKIFVERSIONOK:
|
||
$ required_version = tcpip_P5_'i'
|
||
$ tcpip_type = tcpip_P1_'i'
|
||
$ If ("MULTINET" .eqs. tcpip_type)
|
||
$ Then ! I know how to check MULTINET
|
||
$ If (f$search("MULTINET:MULTINET_VERSION.;") .nes. "")
|
||
$ Then
|
||
$ Open/share=READ fd MULTINET:MULTINET_VERSION.;
|
||
$ Read fd buffer
|
||
$ Close fd
|
||
$ v = buffer - "VERSION"
|
||
$ v = f$edit(V,"TRIM,COMPRESS")
|
||
$ If (v .ges. required_version)
|
||
$ Then VERSION_TOO_EARLY = NO
|
||
$ Else VERSION_TOO_EARLY = YES
|
||
$ EndIF
|
||
$ Else
|
||
$ VERSION_TOO_EARLY = YES
|
||
$ EndIF
|
||
$ Else ! don't know, so assume current
|
||
$ VERSION_TOO_EARLY = NO
|
||
$ EndIF
|
||
$!
|
||
$ RETURN
|
||
$!
|
||
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
|
||
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]makefile.cut
|
||
$DECK
|
||
#
|
||
# CUTCP/CUTE BC++ version 11/22/91 bkc@omnigate.clarkson.edu
|
||
# Last changed: 12/03/91 1.2.1
|
||
#
|
||
# Makefile for the minimal build for an archie Prospero client.
|
||
#.INCLUDE ../../../builtins
|
||
|
||
OBJS = aquery.obj archie.obj atalloc.obj \
|
||
get_pauth.obj get_vdir.obj perrmesg.obj procquery.obj \
|
||
ptalloc.obj regex.obj stcopy.obj support.obj\
|
||
vlalloc.obj vl_comp.obj dirsend.obj misc.obj
|
||
|
||
# dirsend.obj
|
||
|
||
HDRS = archie.h pmachine.h pcompat.h
|
||
|
||
DEFINES = -DDEBUG -DCUTCP
|
||
|
||
CFLAGS= -k -N -ml -r -v $(DEFINES) -I.
|
||
LFLAGS= /P/m/s
|
||
CC = bccx
|
||
|
||
EXE = archie.exe
|
||
|
||
all: $(EXE)
|
||
|
||
$(OBJS): $(HDRS)
|
||
|
||
.c.obj:
|
||
$(CC) $(CFLAGS) -c $<
|
||
|
||
$(EXE): $(OBJS) Makefile
|
||
tlink $(LFLAGS) @&&!
|
||
c0l $(OBJS)
|
||
!,archie,archie,@&&!
|
||
lib\tcp lib\sess lib\enet lib\vjc lib\over cl
|
||
!
|
||
|
||
clean:
|
||
+-del *.obj
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]makefile.dos
|
||
$DECK
|
||
#
|
||
# Last changed: 11/20/91, v1.2
|
||
#
|
||
# Makefile for the minimal build for an archie Prospero client.
|
||
#.INCLUDE ../../../builtins
|
||
|
||
OBJS = aquery.lo archie.lo atalloc.lo dirsend.lo \
|
||
get_pauth.lo get_vdir.lo perrmesg.lo procquery.lo \
|
||
ptalloc.lo regex.lo stcopy.lo support.lo \
|
||
vlalloc.lo vl_comp.lo
|
||
HDRS = archie.h pmachine.h pcompat.h
|
||
|
||
DEFINES = -DDEBUG -DNOREGEX -DUSG
|
||
|
||
CFLAGS = -Oeclgsz -Gs -Zi -W4 -I. $(DEFINES)
|
||
|
||
EXE = archie.exe
|
||
|
||
all: $(EXE)
|
||
|
||
$(OBJS): $(HDRS)
|
||
|
||
$(EXE): $(OBJS) Makefile archie.lnk
|
||
link @archie.lnk
|
||
exepack archie.unp archie.exe
|
||
|
||
clean:
|
||
+-del *.lo
|
||
+-del *.exe
|
||
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]makefile.os2
|
||
$DECK
|
||
#
|
||
# Last changed: 11/20/91, v1.2
|
||
#
|
||
# Makefile for the minimal build for an archie Prospero client.
|
||
.INCLUDE ../../../builtins
|
||
|
||
OBJS = aquery.obj archie.obj atalloc.obj dirsend.obj \
|
||
get_pauth.obj get_vdir.obj perrmesg.obj procquery.obj \
|
||
ptalloc.obj regex.obj stcopy.obj support.obj \
|
||
vlalloc.obj vl_comp.obj
|
||
HDRS = archie.h pmachine.h pcompat.h
|
||
|
||
DEFINES = -DDEBUG -DNOREGEX
|
||
|
||
IFLAGS = -I. -I../../../include $(DEFINES)
|
||
|
||
LFLAGS = /stack:30000/nod/noe/noi/map/CO
|
||
LIBS = pctcp bsd ftpcrt socket os2
|
||
EXE = archie.exe
|
||
|
||
all: $(EXE)
|
||
|
||
install: $(EXE)
|
||
cp $[m,*.exe,$**] ..\..\..\bin
|
||
@touch install
|
||
|
||
$(OBJS): $(HDRS)
|
||
|
||
$(EXE): $(OBJS) Makefile
|
||
$(LD) $(LFLAGS) $(L_DEBUG) <@<
|
||
$[s,"+ \n",$[m,*.obj,$**]]
|
||
$*
|
||
$*
|
||
$(LIBS)
|
||
|
||
<
|
||
+markexe lfns $@
|
||
+markexe windowcompat $@
|
||
|
||
clean:
|
||
+-del *.obj
|
||
+-del *.exe
|
||
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie.msdos]cutcp.h
|
||
$DECK
|
||
/* cutcp.h -- defs for cutcp code */
|
||
|
||
|
||
int netlisten(unsigned int port);
|
||
struct machinfo *Shostlook(char *name);
|
||
int Sdomain(char *name);
|
||
struct machinfo *Sgethost(char *name);
|
||
struct machinfo *Slookip(unsigned long *address);
|
||
void netgetftp(unsigned int array[], unsigned int port);
|
||
int netopen(unsigned long *address, unsigned int port);
|
||
int Snetopen(struct machinfo *m, unsigned int port);
|
||
int netqlen(int handle);
|
||
int netroom(int handle);
|
||
int netread(int pnum, unsigned char *buffer, unsigned int n);
|
||
int netwrite(int pnum, unsigned char *buffer, unsigned int n);
|
||
int netest(int pnum);
|
||
int netpush(int pnum);
|
||
void netulisten(unsigned int portnum);
|
||
int netusend(unsigned long *address, unsigned destport,
|
||
unsigned sourceport, unsigned char *buffer, int count);
|
||
int neturead(unsigned char *buffer);
|
||
struct machinfo *Slooknum(int pnum);
|
||
int Snetinit();
|
||
int Shostfile(char *name);
|
||
int netshut();
|
||
int Sgetevent(int classes, int *clss, int *data);
|
||
int netclose(int pnum);
|
||
unsigned int intswap(unsigned int val);
|
||
unsigned long n_clicks(void *p);
|
||
void Stask();
|
||
|
||
#define ntohs(a) (intswap(a))
|
||
#define htons(a) (intswap(a))
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie.msdos]hostform.h
|
||
$DECK
|
||
/* hfile.inc - placed into all .h files to set up for PVCS
|
||
$Header: /work/archie/Src-Depot-Clone/archie-dist/contrib/c-archie-1.3.2-vms.com,v 1.1.1.1 1994/04/28 00:56:12 bajan Exp $
|
||
Revision History ----------------------------------------------------
|
||
$Log: c-archie-1.3.2-vms.com,v $
|
||
# Revision 1.1.1.1 1994/04/28 00:56:12 bajan
|
||
# Initial import
|
||
#
|
||
*
|
||
* Rev 1.0 15 Jan 1990 19:30:22 bkc
|
||
*/
|
||
|
||
|
||
/*
|
||
* Host and local machine configuration information.
|
||
*
|
||
****************************************************************************
|
||
* *
|
||
* NCSA Telnet for the PC *
|
||
* by Tim Krauskopf, VT100 by Gaige Paulsen, Tek by Aaron Contorer *
|
||
* *
|
||
* National Center for Supercomputing Applications *
|
||
* 152 Computing Applications Building *
|
||
* 605 E. Springfield Ave. *
|
||
* Champaign, IL 61820 *
|
||
* *
|
||
* This program is in the public domain. *
|
||
* *
|
||
****************************************************************************
|
||
*/
|
||
|
||
/*
|
||
* Linked list of structures which describe other machines.
|
||
* Arranged one per session with unique session names.
|
||
*/
|
||
|
||
struct machinfo {
|
||
unsigned char
|
||
*sname, /* pointer to name of session */
|
||
*hname, /* pointer to name of that machine */
|
||
*font, /* font name, if we can do it */
|
||
*keymap, /* pointer to keymap file name */
|
||
hostip[4], /* IP number of this machine */
|
||
gateway, /* gateway preference, start with 1 */
|
||
nameserv, /* nameserver preference, start with 1 */
|
||
bksp, /* backspace value */
|
||
halfdup, /* half duplex required */
|
||
crmap, /* Strange Berkeley 4.3 CR mode needed */
|
||
vtwrap, /* flag on when need wrap mode */
|
||
vtmargin; /* col to ring bell at */
|
||
int
|
||
clearsave, /* whether to save cleared lines */
|
||
fsize, /* font size in points */
|
||
nfcolor[3], /* normal foreground */
|
||
nbcolor[3], /* normal background */
|
||
bfcolor[3], /* blink */
|
||
bbcolor[3],
|
||
ufcolor[3], /* underline */
|
||
ubcolor[3],
|
||
mno, /* machine number for reference */
|
||
mstat, /* status of this machine entry */
|
||
bkscroll, /* how many lines to save */
|
||
retrans, /* initial retrans timeout */
|
||
conto, /* time out in seconds to wait for connect */
|
||
window, /* window, will be checked against buffers */
|
||
maxseg, /* maximum receivable segment size */
|
||
mtu, /* maximum transfer unit MTU (out) */
|
||
domainsremaining, /* how many domain search list entries remain */
|
||
destport, /* yepper, you can telnet to a different port than 23 */
|
||
flags; /* general flags holder */
|
||
#define MFLAGS_SCRIPT 0x80
|
||
struct machinfo *next; /* surprise, its a linked list! */
|
||
};
|
||
|
||
struct machinfo *Sgethost(),*Shostlook(),*Slooknum(),*Slookip(),*Smadd();
|
||
|
||
/*
|
||
* status fields for mstat, what do we know about that machine?
|
||
*/
|
||
#define NOIP 1 /* we don't have IP number */
|
||
#define UDPDOM 3 /* there is a UDP request pending on it */
|
||
/* The next 20 numbers are reserved for UDPDOM */
|
||
#define HAVEIP 50 /* at least we have the # */
|
||
#define HFILE 70 /* we have IP number from host file */
|
||
#define DOM 71 /* we have an IP number from DOMAIN */
|
||
#define FROMKIP 72 /* have IP# from KIP server */
|
||
|
||
|
||
|
||
/*
|
||
* Configuration information which
|
||
* the calling program may want to obtain from the hosts file.
|
||
* The calling program should include hostform.h and call
|
||
* Sgetconfig(cp)
|
||
* struct config *cp;
|
||
* which will copy the information to the user's data structure.
|
||
*/
|
||
struct config {
|
||
unsigned char
|
||
netmask[4], /* subnetting mask being used */
|
||
havemask, /* do we have a netmask? */
|
||
irqnum, /* which hardware interrupt */
|
||
myipnum[4], /* what is my IP #? */
|
||
me[32], /* my name description (first 30 chars) */
|
||
color[3], /* default colors to use */
|
||
hw[10], /* hardware type for network */
|
||
video[10], /* video graphics hardware available */
|
||
bios, /* flag, do we want to use BIOS for screen access */
|
||
tek, /* flag, enable tektronix graphics */
|
||
ftp, /* flag, enable ftp server */
|
||
rcp, /* flag, enable rcp server */
|
||
comkeys, /* flag, commandkeys=yes */
|
||
*termtype, /* terminal type specification */
|
||
*zone, /* AppleTalk zone for KIP NBP */
|
||
*defdom, /* default domain */
|
||
*capture, /* pointer to where the capture file name is */
|
||
*pass, /* pointer to where the password file name is */
|
||
*hpfile, /* HP file name */
|
||
*psfile, /* PS file name */
|
||
*tekfile; /* tek file name */
|
||
int
|
||
nstype, /* nameserver = 1-domain 2-IEN116 */
|
||
domto, /* time out for UDP domain request */
|
||
ndom, /* number of retries for domain requests */
|
||
timesl, /* time slice */
|
||
address, /* segment address */
|
||
ioaddr; /* I/O address */
|
||
char *domainpath; /* domain name search path */
|
||
char *map3270; /* path to 3270 map */
|
||
char tnmode; /* how we decide to connect to 3270 streams */
|
||
long sys_flags;
|
||
#define SYS_FLAGS_VISUAL_BELL 0x1 /* use visual bell */
|
||
|
||
};
|
||
|
||
|
||
#define TNMODE_FLAGGED 0
|
||
#define TNMODE_AUTO 1
|
||
#define TNMODE_NOTFLAGGED 2
|
||
#define TNMODE_OFF 3
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie.msdos]netevent.h
|
||
$DECK
|
||
/* hfile.inc - placed into all .h files to set up for PVCS
|
||
$Header: /work/archie/Src-Depot-Clone/archie-dist/contrib/c-archie-1.3.2-vms.com,v 1.1.1.1 1994/04/28 00:56:12 bajan Exp $
|
||
Revision History ----------------------------------------------------
|
||
$Log: c-archie-1.3.2-vms.com,v $
|
||
# Revision 1.1.1.1 1994/04/28 00:56:12 bajan
|
||
# Initial import
|
||
#
|
||
*
|
||
* Rev 1.0 15 Jan 1990 19:29:26 bkc
|
||
*/
|
||
|
||
|
||
/*
|
||
* Events for event processing in NCSA Telnet.
|
||
* Used for netgetevent().
|
||
*/
|
||
|
||
|
||
#define USERCLASS 1 /* the user program will accept these events */
|
||
#define ICMPCLASS 2 /* ICMP in netsleep will look for these */
|
||
#define ERRCLASS 4 /* the user may or may not read these error messages */
|
||
#define SCLASS 8 /* the background server will take these */
|
||
#define CONCLASS 0x10 /* the application manages connections with these */
|
||
|
||
#define ERR1 1 /* an error message is waiting, ERRCLASS */
|
||
|
||
#define IREDIR 1 /* ICMP redirect, ICMPCLASS */
|
||
|
||
#define CONOPEN 1 /* connection has opened, CONCLASS */
|
||
#define CONDATA 2 /* there is data available on this connection */
|
||
#define CONCLOSE 3 /* the other side has closed its side of the connection */
|
||
#define CONFAIL 4 /* connection open attempt has failed */
|
||
|
||
#define UDPDATA 1 /* UDP data has arrived on listening port, USERCLASS */
|
||
#define DOMOK 2 /* domain name ready */
|
||
#define DOMFAIL 3 /* domain name lookup failed */
|
||
#define FTPCOPEN 20 /* FTP command connection has opened */
|
||
#define FTPCLOSE 21 /* FTP command connection has closed */
|
||
#define FTPBEGIN 22 /* FTP transfer beginning, dat =1 for get, 0 for put */
|
||
#define FTPEND 23 /* FTP transfer ending */
|
||
#define FTPLIST 24 /* FTP file listing taking place */
|
||
#define FTPUSER 25 /* FTP user name has been entered */
|
||
#define FTPPWOK 26 /* FTP password verified */
|
||
#define FTPPWNO 27 /* FTP password failed */
|
||
#define RCPBEGIN 30 /* RCP beginning */
|
||
#define RCPEND 31 /* RCP ending */
|
||
|
||
#define UDPTO 1 /* UDP request from DOMAIN timed out, SCLASS */
|
||
#define FTPACT 2 /* FTP transfer is active, keep sending */
|
||
#define TCPTO 3 /* TCP for DOMAIN timed out */
|
||
#define RCPACT 4 /* rcp is active, needs CPU time */
|
||
#define RETRYCON 5 /* retry connection packet, might be lost */
|
||
#define DOMNEXT 6 /* search next domain list entry */
|
||
#define E_CLOCK 7
|
||
#ifdef SCRIPT
|
||
#define SCRIPT_EVENT 1 /* script next step */
|
||
#define SCRIPT_DATA 2 /* received some data */
|
||
#define SCRIPT_PROC 3 /* just process stuff */
|
||
#define SCRIPT_CLOSE 4 /* connection was closed */
|
||
#define SCRIPT_FORCE 5 /* user forced connection closed */
|
||
#define SCRIPT_DOMAIN 6 /* domain name lookup ok */
|
||
#define SCRIPT_FUNC 8
|
||
/* int Script_Event(int type, void *twin, unsigned int data); */
|
||
#endif
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]perrmesg.c
|
||
$DECK
|
||
/*
|
||
* Copyright (c) 1989, 1990, 1991 by the University of Washington
|
||
*
|
||
* For copying and distribution information, please see the file
|
||
* <copyright.h>.
|
||
*/
|
||
|
||
#include <copyright.h>
|
||
#include <perrno.h>
|
||
#include <stdio.h>
|
||
|
||
/* This file and perrno.h should always be updated simultaneously */
|
||
|
||
int perrno = 0;
|
||
int pwarn = 0;
|
||
char p_err_string[P_ERR_STRING_SZ];
|
||
char p_warn_string[P_ERR_STRING_SZ];
|
||
|
||
char *p_err_text[256] = {
|
||
/* 0 */ "Success (prospero)",
|
||
/* 1 */ "Port unknown (dirsend)",
|
||
/* 2 */ "Can't open local UDP port (dirsend)",
|
||
/* 3 */ "Can't resolve hostname (dirsend)",
|
||
/* 4 */ "Unable to send entire message (dirsend)",
|
||
/* 5 */ "Timed out (dirsend)",
|
||
/* 6 */ "Recvfrom failed (dirsend)",
|
||
/* 7 */ "", /* 8 */ "", /* 9 */ "", /* 10 */ "",
|
||
/* 11 */ "Sendto failed (reply)",
|
||
/* 12 */ "", /* 13 */ "", /* 14 */ "", /* 15 */ "",
|
||
/* 16 */ "", /* 17 */ "", /* 18 */ "", /* 19 */ "",
|
||
/* 20 */ "",
|
||
/* 21 */ "Link already exists (vl_insert)",
|
||
/* 22 */ "Link with same name already exists (vl_insert)",
|
||
/* 23 */ "", /* 24 */ "",
|
||
/* 25 */ "Link already exists (ul_insert)",
|
||
/* 26 */ "Replacing existing link (ul_insert)",
|
||
/* 27 */ "Previous entry not found in dir->ulinks (ul_insert)",
|
||
/* 28 */ "", /* 29 */ "", /* 30 */ "", /* 31 */ "",
|
||
/* 32 */ "", /* 33 */ "", /* 34 */ "", /* 35 */ "",
|
||
/* 36 */ "", /* 37 */ "", /* 38 */ "", /* 39 */ "",
|
||
/* 40 */ "",
|
||
/* 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 */ "", /* 46 */ "", /* 47 */ "", /* 48 */ "",
|
||
/* 49 */ "", /* 50 */ "",
|
||
/* 51 */ "File access method not supported (pfs_access)",
|
||
/* 52 */ "", /* 53 */ "", /* 54 */ "",
|
||
/* 55 */ "Pointer to cached copy - delete on close (pmap_cache)",
|
||
/* 56 */ "Unable to retrieve file (pmap_cache)",
|
||
/* 57 */ "", /* 58 */ "", /* 59 */ "", /* 60 */ "",
|
||
/* 61 */ "Directory already exists (mk_vdir)",
|
||
/* 62 */ "Link with same name already exists (mk_vdir)",
|
||
/* 63 */ "", /* 64 */ "",
|
||
/* 65 */ "Not a virtual system (vfsetenv)",
|
||
/* 66 */ "Can't find directory (vfsetenv)",
|
||
/* 67 */ "", /* 68 */ "", /* 69 */ "", /* 70 */ "",
|
||
/* 71 */ "Link already exists (add_vlink)",
|
||
/* 72 */ "Link with same name already exists (add_vlink)",
|
||
/* 73 */ "", /* 74 */ "", /* 75 */ "", /* 76 */ "",
|
||
/* 77 */ "", /* 78 */ "", /* 79 */ "", /* 80 */ "",
|
||
/* 81 */ "", /* 82 */ "", /* 83 */ "", /* 84 */ "",
|
||
/* 85 */ "", /* 86 */ "", /* 87 */ "", /* 88 */ "",
|
||
/* 89 */ "", /* 90 */ "", /* 91 */ "", /* 92 */ "",
|
||
/* 93 */ "", /* 94 */ "", /* 95 */ "", /* 96 */ "",
|
||
/* 97 */ "", /* 98 */ "", /* 99 */ "", /* 100 */ "",
|
||
/* 101 */ "", /* 102 */ "", /* 103 */ "", /* 104 */ "",
|
||
/* 105 */ "", /* 106 */ "", /* 107 */ "", /* 108 */ "",
|
||
/* 109 */ "", /* 110 */ "", /* 111 */ "", /* 112 */ "",
|
||
/* 113 */ "", /* 114 */ "", /* 115 */ "", /* 116 */ "",
|
||
/* 117 */ "", /* 118 */ "", /* 119 */ "", /* 120 */ "",
|
||
/* 121 */ "", /* 122 */ "", /* 123 */ "", /* 124 */ "",
|
||
/* 125 */ "", /* 126 */ "", /* 127 */ "", /* 128 */ "",
|
||
/* 129 */ "", /* 130 */ "", /* 131 */ "", /* 132 */ "",
|
||
/* 133 */ "", /* 134 */ "", /* 135 */ "", /* 136 */ "",
|
||
/* 137 */ "", /* 138 */ "", /* 139 */ "", /* 140 */ "",
|
||
/* 141 */ "", /* 142 */ "", /* 143 */ "", /* 144 */ "",
|
||
/* 145 */ "", /* 146 */ "", /* 147 */ "", /* 148 */ "",
|
||
/* 149 */ "", /* 150 */ "", /* 151 */ "", /* 152 */ "",
|
||
/* 153 */ "", /* 154 */ "", /* 155 */ "", /* 156 */ "",
|
||
/* 157 */ "", /* 158 */ "", /* 159 */ "", /* 160 */ "",
|
||
/* 161 */ "", /* 162 */ "", /* 163 */ "", /* 164 */ "",
|
||
/* 165 */ "", /* 166 */ "", /* 167 */ "", /* 168 */ "",
|
||
/* 169 */ "", /* 170 */ "", /* 171 */ "", /* 172 */ "",
|
||
/* 173 */ "", /* 174 */ "", /* 175 */ "", /* 176 */ "",
|
||
/* 177 */ "", /* 178 */ "", /* 179 */ "", /* 180 */ "",
|
||
/* 181 */ "", /* 182 */ "", /* 183 */ "", /* 184 */ "",
|
||
/* 185 */ "", /* 186 */ "", /* 187 */ "", /* 188 */ "",
|
||
/* 189 */ "", /* 190 */ "", /* 191 */ "", /* 192 */ "",
|
||
/* 193 */ "", /* 194 */ "", /* 195 */ "", /* 196 */ "",
|
||
/* 197 */ "", /* 198 */ "", /* 199 */ "", /* 200 */ "",
|
||
/* 201 */ "", /* 202 */ "", /* 203 */ "", /* 204 */ "",
|
||
/* 205 */ "", /* 206 */ "", /* 207 */ "", /* 208 */ "",
|
||
/* 209 */ "", /* 210 */ "", /* 211 */ "", /* 212 */ "",
|
||
/* 213 */ "", /* 214 */ "", /* 215 */ "", /* 216 */ "",
|
||
/* 217 */ "", /* 218 */ "", /* 219 */ "", /* 220 */ "",
|
||
/* 221 */ "", /* 222 */ "", /* 223 */ "", /* 224 */ "",
|
||
/* 225 */ "", /* 226 */ "", /* 227 */ "", /* 228 */ "",
|
||
/* 229 */ "",
|
||
/* 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 */ "", /* 237 */ "", /* 238 */ "", /* 239 */ "",
|
||
/* 240 */ "", /* 241 */ "",
|
||
/* 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 */ "", /* 250 */ "",
|
||
/* 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 */ ""};
|
||
|
||
#ifndef ARCHIE
|
||
perrmesg(prefix,no,text)
|
||
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)));
|
||
}
|
||
|
||
sperrmesg(buf,prefix,no,text)
|
||
char *buf;
|
||
char *prefix;
|
||
int no;
|
||
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)));
|
||
}
|
||
|
||
pwarnmesg(prefix,no,text)
|
||
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)));
|
||
}
|
||
|
||
spwarnmesg(buf,prefix,no,text)
|
||
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)));
|
||
}
|
||
#endif
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]patchlevel.h
|
||
$DECK
|
||
/*
|
||
* Archie v1.3
|
||
*
|
||
* History:
|
||
*
|
||
* 04/14/92 v1.3.2 - Release.
|
||
* 01/10/92 v1.3.1 - Release.
|
||
* 01/09/92 v1.3 - Release.
|
||
* 12/13/91 - added UCX support
|
||
* 12/03/91 - added CUTCP support
|
||
* 11/20/91 v1.2 - Release.
|
||
* 11/18/91 - ported to DOS & OS/2
|
||
* 11/12/91 - finally got to test under Multinet 3.0
|
||
* 10/03/91 - replaced regex.c for oz
|
||
* 09/25/91 - added Wollongong support
|
||
* 08/30/91 - ported to VMS
|
||
* 08/20/91 v1.1 - Major revisions
|
||
* 07/31/91 v1.0 - Original
|
||
*/
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]pauthent.h
|
||
$DECK
|
||
/*
|
||
* Copyright (c) 1989, 1990, 1991 by the University of Washington
|
||
*
|
||
* For copying and distribution information, please see the file
|
||
* <copyright.h>.
|
||
*/
|
||
|
||
#include <copyright.h>
|
||
|
||
#define PFSA_UNAUTHENTICATED 1
|
||
|
||
struct pfs_auth_info {
|
||
char auth_type[100];
|
||
char authenticator[250];
|
||
};
|
||
|
||
typedef struct pfs_auth_info *PAUTH;
|
||
typedef struct pfs_auth_info PAUTH_ST;
|
||
|
||
PAUTH get_pauth();
|
||
|
||
#ifndef VMS
|
||
# ifndef IN_H
|
||
# include <netinet/in.h>
|
||
# define IN_H
|
||
# endif
|
||
#else
|
||
# ifndef _ARCHIE_VMS
|
||
# include <vms.h>
|
||
# endif
|
||
#endif
|
||
|
||
struct client_info {
|
||
int ainfo_type;
|
||
char *auth_type;
|
||
char *authenticator;
|
||
char *userid;
|
||
short port;
|
||
struct in_addr haddr;
|
||
struct pfs_auth_info *previous;
|
||
struct pfs_auth_info *next;
|
||
};
|
||
|
||
typedef struct client_info *CINFO;
|
||
typedef struct client_info CINFO_ST;
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]pcompat.h
|
||
$DECK
|
||
/*
|
||
* Copyright (c) 1989, 1990 by the University of Washington
|
||
*
|
||
* For copying and distribution information, please see the file
|
||
* <copyright.h>.
|
||
*/
|
||
|
||
#include <copyright.h>
|
||
|
||
/*
|
||
* pcompat.h - Definitions for compatability library
|
||
*
|
||
* This file contains the defintions used by the compatability
|
||
* library. Among the definitions are the possible values for
|
||
* pfs_disable_flag. This file also contains the external
|
||
* declaration of that variable. Note, however that the
|
||
* the module pfs_disable_flag.o is included in libpfs.a
|
||
* because some of the routines in that library set it.
|
||
* The only place it is checked, however, is in pfs_access,
|
||
* found in libpcompat.a
|
||
*
|
||
*/
|
||
|
||
extern int pfs_default;
|
||
extern int pfs_enable;
|
||
|
||
/* Definitions for values of pfs_enable */
|
||
#define PMAP_DISABLE 0
|
||
#define PMAP_ENABLE 1
|
||
#define PMAP_COLON 2
|
||
#define PMAP_ATSIGN_NF 3
|
||
#define PMAP_ATSIGN 4
|
||
|
||
#define DISABLE_PFS(stmt) do {int DpfStmp; DpfStmp = pfs_enable;\
|
||
pfs_enable = PMAP_DISABLE; \
|
||
stmt; \
|
||
pfs_enable = DpfStmp;} while (0)
|
||
|
||
/* Definitions for PFS_ACCESS */
|
||
#define PFA_MAP 0 /* Map the file name only */
|
||
#define PFA_CREATE 1 /* Create file if not found */
|
||
#define PFA_CRMAP 2 /* Map file name. Map to new name if not found */
|
||
#define PFA_RO 4 /* Access to file is read only */
|
||
|
||
#define check_pfs_default() \
|
||
do { if (pfs_default == -1) get_pfs_default(); } while (0)
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]perrno.h
|
||
$DECK
|
||
/*
|
||
* Copyright (c) 1989, 1990 by the University of Washington
|
||
*
|
||
* For copying and distribution information, please see the file
|
||
* <copyright.h>.
|
||
*/
|
||
|
||
#include <copyright.h>
|
||
|
||
/* This file and perrmesg.c should be updated simultaneously. */
|
||
|
||
/*
|
||
* perrno.h - definitions for perrno
|
||
*
|
||
* This file contains the declarations and defintions of of the external
|
||
* error values in which errors are returned by the pfs and psrv
|
||
* libraries.
|
||
*/
|
||
|
||
#define P_ERR_STRING_SZ 100 /* Size of error string */
|
||
|
||
extern int perrno;
|
||
extern char p_err_string[];
|
||
extern char *p_err_text[];
|
||
|
||
extern int pwarn;
|
||
extern char p_warn_string[];
|
||
extern char *p_warn_text[];
|
||
|
||
/* Error codes returned or found in verrno */
|
||
|
||
#ifndef PSUCCESS
|
||
#define PSUCCESS 0
|
||
#endif
|
||
|
||
/* dirsend (perrno) */
|
||
#define DIRSEND_PORT_UNKN 1 /* DIRSRV UDP port unknown */
|
||
#define DIRSEND_UDP_CANT 2 /* Can't open local UDP port */
|
||
#define DIRSEND_BAD_HOSTNAME 3 /* Can't resolve hostname */
|
||
#define DIRSEND_NOT_ALL_SENT 4 /* Didn't send entire message */
|
||
#define DIRSEND_SELECT_FAILED 5 /* Select failed */
|
||
#define DIRSEND_BAD_RECV 6 /* Recvfrom failed */
|
||
|
||
/* reply */
|
||
#define REPLY_NOTSENT 11 /* Reply: sendto failed */
|
||
|
||
/* vl_insert */
|
||
#define VL_INSERT_ALREADY_THERE 21 /* Link already exists */
|
||
#define VL_INSERT_CONFLICT 22 /* Link exists with same name */
|
||
|
||
/* ul_insert */
|
||
#define UL_INSERT_ALREADY_THERE 25 /* Link already exists */
|
||
#define UL_INSERT_SUPERSEDING 26 /* Replacing existing link */
|
||
#define UL_INSERT_POS_NOTFOUND 27 /* Prv entry not in dir->ulinks */
|
||
|
||
/* rd_vdir */
|
||
#define RVD_DIR_NOT_THERE 41 /* Temporary NOT_FOUND */
|
||
#define RVD_NO_CLOSED_NS 42 /* Namespace not closed w/ object:: */
|
||
#define RVD_NO_NS_ALIAS 43 /* No alias for namespace NS#: */
|
||
#define RVD_NS_NOT_FOUND 44 /* Specified namespace not found */
|
||
|
||
/* pfs_access */
|
||
#define PFSA_AM_NOT_SUPPORTED 51 /* Access method not supported */
|
||
|
||
/* pmap_cache */
|
||
#define PMC_DELETE_ON_CLOSE 55 /* Delete cached copy on close */
|
||
#define PMC_RETRIEVE_FAILED 56 /* Unable to retrieve file */
|
||
|
||
/* mk_vdir */
|
||
/* #define MKVD_ALREADY_EXISTS 61 /* Directory already exists */
|
||
/* #define MKVD_NAME_CONFLICT 62 /* Link with name already exists */
|
||
|
||
/* vfsetenv */
|
||
#define VFSN_NOT_A_VS 65 /* Not a virtual system */
|
||
#define VFSN_CANT_FIND_DIR 66 /* Not a virtual system */
|
||
|
||
/* add_vlink */
|
||
/* #define ADDVL_ALREADY_EXISTS 71 /* Directory already exists */
|
||
/* #define ADDVL_NAME_CONFLICT 72 /* Link with name already exists */
|
||
|
||
/* Local error codes on server */
|
||
|
||
/* dsrdir */
|
||
#define DSRDIR_NOT_A_DIRECTORY 111 /* Not a directory name */
|
||
/* dsrfinfo */
|
||
#define DSRFINFO_NOT_A_FILE 121 /* Object not found */
|
||
#define DSRFINFO_FORWARDED 122 /* Object has moved */
|
||
|
||
/* Error codes that may be returned by various procedures */
|
||
#define PFS_FILE_NOT_FOUND 230 /* File not found */
|
||
#define PFS_DIR_NOT_FOUND 231 /* Directory in path not found */
|
||
#define PFS_SYMLINK_DEPTH 232 /* Max sym-link depth exceeded */
|
||
#define PFS_ENV_NOT_INITIALIZED 233 /* Can't read environment */
|
||
#define PFS_EXT_USED_AS_DIR 234 /* Can't use externals as dirs */
|
||
#define PFS_MAX_FWD_DEPTH 235 /* Exceeded max forward depth */
|
||
|
||
/* Error codes returned by directory server */
|
||
/* some of these duplicate errors from individual routines */
|
||
/* some of those error codes should be eliminated */
|
||
#define DIRSRV_AUTHENT_REQ 242 /* Authentication required */
|
||
#define DIRSRV_NOT_AUTHORIZED 243 /* Not authorized */
|
||
#define DIRSRV_NOT_FOUND 244 /* Not found */
|
||
#define DIRSRV_BAD_VERS 245
|
||
#define DIRSRV_NOT_DIRECTORY 246
|
||
#define DIRSRV_ALREADY_EXISTS 247 /* Identical link already exists */
|
||
#define DIRSRV_NAME_CONFLICT 248 /* Link with name already exists */
|
||
|
||
#define DIRSRV_UNIMPLEMENTED 251 /* Unimplemented command */
|
||
#define DIRSRV_BAD_FORMAT 252
|
||
#define DIRSRV_ERROR 253
|
||
#define DIRSRV_SERVER_FAILED 254 /* Unspecified server failure */
|
||
|
||
#ifndef PFAILURE
|
||
#define PFAILURE 255
|
||
#endif
|
||
|
||
/* Warning codes */
|
||
|
||
#define PNOWARN 0 /* No warning indicated */
|
||
#define PWARN_OUT_OF_DATE 1 /* Software is out of date */
|
||
#define PWARN_MSG_FROM_SERVER 2 /* Warning in p_warn_string */
|
||
#define PWARN_UNRECOGNIZED_RESP 3 /* Unrecognized line in response */
|
||
#define PWARNING 255 /* Warning in p_warn_string */
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]pfs.h
|
||
$DECK
|
||
/*
|
||
* Copyright (c) 1989, 1990, 1991 by the University of Washington
|
||
*
|
||
* For copying and distribution information, please see the file
|
||
* <copyright.h>.
|
||
*/
|
||
|
||
#include <copyright.h>
|
||
|
||
#ifdef VMS
|
||
# include <vms.h>
|
||
#else /* not VMS */
|
||
# ifndef _TYPES_
|
||
# include <sys/types.h>
|
||
# endif /* _TYPES_ */
|
||
# ifndef IN_H
|
||
# include <netinet/in.h>
|
||
# define IN_H
|
||
# endif
|
||
#endif /* VMS */
|
||
|
||
#ifndef NULL
|
||
# ifdef MSDOS
|
||
# include <stdio.h>
|
||
# else
|
||
# define NULL 0
|
||
# endif /* MSDOS */
|
||
#endif /* NULL */
|
||
|
||
#define PFS_RELEASE "Beta.4.2E"
|
||
#define PFS_SW_ID "B42E"
|
||
|
||
/* moved up for vdir_init */
|
||
#define ZERO(p) bzero((char *)(p), sizeof(*(p)))
|
||
|
||
/* General Definitions */
|
||
|
||
#define MAX_PTXT_LEN 1250 /* Max length of PTEXT structure */
|
||
#define MAX_PTXT_HDR 32 /* Max offset for start */
|
||
#define P_ERR_STRING_SZ 100 /* Size of error string */
|
||
#define MAX_VPATH 1024 /* Max length of virtual pathname */
|
||
|
||
/* Definition of text structure used to pass text around */
|
||
|
||
struct ptext {
|
||
int length; /* Length of text (from start) */
|
||
char *start; /* Start of text */
|
||
char dat[MAX_PTXT_LEN+2*MAX_PTXT_HDR];/* The data itself */
|
||
unsigned long mbz; /* ZERO to catch runaway strings */
|
||
struct ptext *previous; /* Previous element in list */
|
||
struct ptext *next; /* Next element in linked list */
|
||
int seq; /* Sequence Number */
|
||
};
|
||
|
||
typedef struct ptext *PTEXT;
|
||
typedef struct ptext PTEXT_ST;
|
||
|
||
/* Request structure: maintains information about server requests */
|
||
struct preq {
|
||
int cid; /* Connection ID */
|
||
short priority; /* Connection priority */
|
||
int pf_priority; /* Priority assigned by pri_func */
|
||
int recv_tot; /* Total # of packets received */
|
||
int trns_tot; /* Total # of packets to transmit */
|
||
struct ptext *cpkt; /* Current packet being filled in */
|
||
struct ptext *recv; /* Received packets */
|
||
struct ptext *trns; /* Transmitted packets */
|
||
int rcvd_thru; /* Received all packets through # */
|
||
struct preq *previous; /* Previous element in list */
|
||
struct preq *next; /* Next element in linked list */
|
||
struct sockaddr_in fromto; /* Sender/Destination */
|
||
};
|
||
|
||
typedef struct preq *PREQ;
|
||
typedef struct preq PREQ_ST;
|
||
|
||
|
||
/* Definition of structure containing information on virtual link */
|
||
|
||
struct vlink {
|
||
int dontfree; /* Flag: don't free this link */
|
||
char *name; /* Component of path name */
|
||
char linktype; /* L = Link, U = Union, N= Native */
|
||
int expanded; /* Has a union link been expanded */
|
||
char *type; /* Type of object pointed to */
|
||
struct vlink *filters; /* Filters associated with link */
|
||
struct vlink *replicas; /* Replicas (* see comment below) */
|
||
char *hosttype; /* Type of hostname */
|
||
char *host; /* Files physical location */
|
||
char *nametype; /* Type of filename */
|
||
char *filename; /* System level filename */
|
||
long version; /* Version number of destination */
|
||
long f_magic_no; /* File's magic number */
|
||
struct acl *acl; /* ACL for link */
|
||
long dest_exp; /* Expiration for dest of link */
|
||
long link_exp; /* Expiration of link itself */
|
||
char *args; /* Arguments if this is a filter */
|
||
struct pattrib *lattrib; /* Attributes associated w/ link */
|
||
struct pfile *f_info; /* Info to be assoicated w/ file */
|
||
struct vlink *previous; /* Previous elt in linked list */
|
||
struct vlink *next; /* Next element in linked list */
|
||
};
|
||
|
||
typedef struct vlink *VLINK;
|
||
typedef struct vlink VLINK_ST;
|
||
|
||
/* * Note that vlink->replicas is not really a list of replicas of the */
|
||
/* object. Instead, it is a list of the objects returned during name */
|
||
/* resolution that share the same name as the current object. Such */
|
||
/* an object should only be considered a replica if it also shares */
|
||
/* the same non-zero magic number. */
|
||
|
||
/* Definition of structure continiaing virtual directory information */
|
||
|
||
struct vdir {
|
||
int version; /* Version of local directory fmt */
|
||
int inc_native; /* Include the native directory */
|
||
long magic_no; /* Magic number of current file */
|
||
struct acl *dacl; /* Default acl for links in dir */
|
||
struct pfile *f_info; /* Directory file info */
|
||
struct vlink *links; /* The directory entries */
|
||
struct vlink *lastlink; /* Last directory entry */
|
||
struct vlink *ulinks; /* The entries for union links */
|
||
struct vdir *previous; /* Previous element in linked list */
|
||
struct vdir *next; /* Next element in linked list */
|
||
};
|
||
|
||
typedef struct vdir *PVDIR;
|
||
typedef struct vdir VDIR_ST;
|
||
|
||
/* Initialize directory */
|
||
#define vdir_init(dir) ZERO(dir)
|
||
/* XXX: was
|
||
|
||
dir->version = 0; dir->inc_native = 0; \
|
||
dir->magic_no = 0; dir->f_info = NULL; \
|
||
dir->links = NULL; dir->lastlink = NULL; \
|
||
dir->ulinks = NULL; dir->dacl = NULL; \
|
||
dir->previous = NULL; dir->next = NULL;
|
||
*/
|
||
|
||
#define vdir_copy(d1,d2) d2->version = d1->version; \
|
||
d2->inc_native = d1->inc_native; \
|
||
d2->magic_no = d1->magic_no; \
|
||
d2->f_info = d1->f_info; \
|
||
d2->links = d1->links; \
|
||
d2->lastlink = d1->lastlink; \
|
||
d2->ulinks = d1->ulinks; \
|
||
d2->dacl = d1->dacl; \
|
||
d2->previous = d1->previous; \
|
||
d2->next = d1->next;
|
||
|
||
/* Values of ->inc_native in vdir structure */
|
||
#define VDIN_REALONLY -1 /* Include native files, but not . and .. */
|
||
#define VDIN_NONATIVE 0 /* Do not include files from native directory */
|
||
#define VDIN_INCLNATIVE 1 /* Include files from native directory */
|
||
#define VDIN_NATIVEONLY 2 /* All entries in directory are from native dir */
|
||
#define VDIN_PSEUDO 3 /* Directory is not real */
|
||
|
||
|
||
/* Definition of structure containing information on a specific file */
|
||
|
||
union avalue {
|
||
char *ascii; /* Character string */
|
||
struct vlink *link; /* A link */
|
||
};
|
||
|
||
|
||
struct pattrib {
|
||
char precedence; /* Precedence for link attribute */
|
||
char *aname; /* Name of the attribute */
|
||
char *avtype; /* Type of the attribute value */
|
||
union avalue value; /* Attribute Value */
|
||
struct pattrib *previous; /* Previous element in linked list */
|
||
struct pattrib *next; /* Next element in linked list */
|
||
};
|
||
|
||
typedef struct pattrib *PATTRIB;
|
||
typedef struct pattrib PATTRIB_ST;
|
||
|
||
#define ATR_PREC_OBJECT 'O' /* Authoritative answer for object */
|
||
#define ATR_PREC_LINK 'L' /* Authoritative answer for link */
|
||
#define ATR_PREC_CACHED 'C' /* Object info cached w/ link */
|
||
#define ATR_PREC_REPLACE 'R' /* From link (replaces O) */
|
||
#define ATR_PREC_ADD 'A' /* From link (additional value) */
|
||
|
||
/* **** Incomplete **** */
|
||
struct pfile {
|
||
int version; /* Version of local finfo format */
|
||
long f_magic_no; /* Magic number of current file */
|
||
long exp; /* Expiration date of timeout */
|
||
long ttl; /* Time to live after reference */
|
||
long last_ref; /* Time of last reference */
|
||
struct vlink *forward; /* List of forwarding pointers */
|
||
struct vlink *backlinks; /* Partial list of back links */
|
||
struct pattrib *attributes; /* List of file attributes */
|
||
struct pfile *previous; /* Previous element in linked list */
|
||
struct pfile *next; /* Next element in linked list */
|
||
};
|
||
|
||
typedef struct pfile *PFILE;
|
||
typedef struct pfile PFILE_ST;
|
||
|
||
/* Definition of structure contining an access control list entry */
|
||
|
||
struct acl {
|
||
int acetype; /* Access Contol Entry type */
|
||
char *atype; /* Authentication type */
|
||
char *rights; /* Rights */
|
||
char *principals; /* Authorized principals */
|
||
struct restrict *restrictions; /* Restrictions on use */
|
||
struct acl *previous; /* Previous elt in linked list */
|
||
struct acl *next; /* Next element in linked list */
|
||
};
|
||
typedef struct acl *ACL;
|
||
typedef struct acl ACL_ST;
|
||
|
||
#define ACL_NONE 0 /* Nobody authorized by ths entry */
|
||
#define ACL_DEFAULT 1 /* System default */
|
||
#define ACL_SYSTEM 2 /* System administrator */
|
||
#define ACL_OWNER 3 /* Directory owner */
|
||
#define ACL_DIRECTORY 4 /* Same as directory */
|
||
#define ACL_ANY 5 /* Any user */
|
||
#define ACL_AUTHENT 6 /* Authenticated principal */
|
||
#define ACL_LGROUP 7 /* Local group */
|
||
#define ACL_GROUP 8 /* External group */
|
||
#define ACL_ASRTHOST 10 /* Check host and asserted userid */
|
||
#define ACL_TRSTHOST 11 /* ASRTHOST from privileged port */
|
||
|
||
|
||
/* Definition of structure contining access restrictions */
|
||
/* for future extensions */
|
||
struct restrict {
|
||
struct acl *previous; /* Previous elt in linked list */
|
||
struct acl *next; /* Next element in linked list */
|
||
};
|
||
|
||
/* Definitions for send_to_dirsrv */
|
||
#define CLIENT_DIRSRV_TIMEOUT 4 /* time between retries */
|
||
#define CLIENT_DIRSRV_BACKOFF(x) (2 * x) /* Backoff algorithm */
|
||
#define CLIENT_DIRSRV_RETRY 3 /* retry this many times */
|
||
|
||
/* Definitions for rd_vlink and rd_vdir */
|
||
#define SYMLINK_NESTING 10 /* Max nesting depth for sym links */
|
||
|
||
/* Definition fo check_acl */
|
||
#define ACL_NESTING 10 /* Max depth for ACL group nesting */
|
||
|
||
/* Flags for mk_vdir */
|
||
#define MKVD_LPRIV 1 /* Minimize privs for creator in new ACL */
|
||
|
||
/* Flags for get_vdir */
|
||
#define GVD_UNION 0 /* Do not expand union links */
|
||
#define GVD_EXPAND 1 /* Expand union links locally */
|
||
#define GVD_LREMEXP 3 /* Request remote expansion of local links */
|
||
#define GVD_REMEXP 7 /* Request remote expansion of all links */
|
||
#define GVD_VERIFY 8 /* Only verify args are for a directory */
|
||
#define GVD_FIND 16 /* Stop expanding when match is found */
|
||
#define GVD_ATTRIB 32 /* Request attributes from remote server */
|
||
#define GVD_NOSORT 64 /* Do not sort links when adding to dir */
|
||
|
||
/* Flags for rd_vdir */
|
||
#define RVD_UNION GVD_UNION
|
||
#define RVD_EXPAND GVD_EXPAND
|
||
#define RVD_LREMEXP GVD_LREMEXP
|
||
#define RVD_REMEXP GVD_REMEXP
|
||
#define RVD_DFILE_ONLY GVD_VERIFY /* Only return ptr to dir file */
|
||
#define RVD_FIND GVD_FIND
|
||
#define RVD_ATTRIB GVD_ATTRIB
|
||
#define RVD_NOSORT GVD_NOSORT
|
||
#define RVD_NOCACHE 128
|
||
|
||
/* Flags for add_vlink */
|
||
#define AVL_UNION 1 /* Link is a union link */
|
||
|
||
/* Flags for vl_insert */
|
||
#define VLI_NOCONFLICT 0 /* Do not insert links w/ conflicting names */
|
||
#define VLI_ALLOW_CONF 1 /* Allow links with conflicting names */
|
||
#define VLI_NOSORT 2 /* Allow conflicts and don't sort */
|
||
|
||
/* Flags for mapname */
|
||
#define MAP_READWRITE 0 /* Named file to be read and written */
|
||
#define MAP_READONLY 1 /* Named file to be read only */
|
||
|
||
/* Flags for modify_acl */
|
||
#define MACL_NOSYSTEM 0x01
|
||
#define MACL_NOSELF 0x02
|
||
#define MACL_DEFAULT 0x08
|
||
#define MACL_SET 0x0C
|
||
#define MACL_INSERT 0x14
|
||
#define MACL_DELETE 0x10
|
||
#define MACL_ADD 0x1C
|
||
#define MACL_SUBTRACT 0x18
|
||
#define MACL_LINK 0x00
|
||
#define MACL_DIRECTORY 0x20
|
||
#define MACL_OBJECT 0x60
|
||
#define MACL_INCLUDE 0x40
|
||
|
||
#define MACL_OP (MACL_DEFAULT|MACL_SET|MACL_INSERT|\
|
||
MACL_DELETE|MACL_ADD|MACL_SUBTRACT)
|
||
|
||
#define MACL_OTYPE (MACL_LINK|MACL_DIRECTORY|MACL_OBJECT|MACL_INCLUDE)
|
||
|
||
/* Flags for dsrdir */
|
||
#define DSRD_ATTRIBUTES 0x1 /* Fill in attributes for links */
|
||
|
||
/* Access methods returned by Pget_am */
|
||
#define P_AM_ERROR 0
|
||
#define P_AM_FTP 1
|
||
#define P_AM_AFTP 2 /* Anonymous FTP */
|
||
#define P_AM_NFS 4
|
||
#define P_AM_KNFS 8 /* Kerberized NFS */
|
||
#define P_AM_AFS 16
|
||
|
||
/* Return codes */
|
||
|
||
#define PSUCCESS 0
|
||
#define PFAILURE 255
|
||
|
||
/* Hush up warnings. */
|
||
void vllfree();
|
||
|
||
/* Procedures in libpfs.a */
|
||
|
||
char *pget_wdhost(), *pget_wdfile(), *pget_wd(), *pget_hdhost();
|
||
char *pget_hdfile(), *pget_hd(), *pget_rdhost(), *pget_rdfile();
|
||
char *pget_dhost(), *pget_dfile(), *pget_vsname(), *nlsindex();
|
||
char *sindex(), *strtok(), *nxtline(), *unquote(), *stcopy();
|
||
char *stcopyr(), *readheader(), *month_sname();
|
||
|
||
long asntotime();
|
||
void procquery();
|
||
|
||
PTEXT ptalloc();
|
||
PTEXT dirsend();
|
||
void ptfree();
|
||
void ptlfree();
|
||
|
||
PREQ pralloc();
|
||
PREQ get_next_request();
|
||
|
||
VLINK rd_slink();
|
||
VLINK rd_vlink();
|
||
VLINK vl_delete();
|
||
VLINK vlalloc();
|
||
VLINK vlcopy();
|
||
void vlfree();
|
||
|
||
PFILE pfalloc();
|
||
|
||
PATTRIB parse_attribute();
|
||
PATTRIB atalloc();
|
||
PATTRIB pget_at();
|
||
void atfree();
|
||
void atlfree();
|
||
|
||
ACL acalloc();
|
||
ACL get_acl();
|
||
|
||
void stfree();
|
||
|
||
/* Miscellaneous useful definitions */
|
||
#ifndef TRUE
|
||
#define TRUE 1
|
||
#define FALSE 0
|
||
#endif
|
||
|
||
#define AUTHORIZED 1
|
||
#define NOT_AUTHORIZED 0
|
||
#define NEG_AUTHORIZED -1
|
||
|
||
#ifndef NULL
|
||
#define NULL 0
|
||
#endif
|
||
|
||
#define FAILED -1
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]pmachine.h
|
||
$DECK
|
||
/*
|
||
* Miscellaneous system dependencies.
|
||
*
|
||
* I kept the name pmachine.h because it was already in all of the files...this
|
||
* barely resembles the pmachine.h that comes with the real Prospero, tho.
|
||
*/
|
||
|
||
#ifdef u3b2
|
||
# define USG
|
||
# define NOREGEX
|
||
# define MAXPATHLEN 1024 /* There's no maxpathlen in any 3b2 .h file. */
|
||
#endif
|
||
|
||
#ifdef hpux
|
||
# ifndef bcopy
|
||
# define FUNCS /* HP/UX 8.0 has the fns. */
|
||
# endif
|
||
# define NOREGEX
|
||
# define NEED_STRING_H
|
||
#endif
|
||
|
||
#if defined(USG) || defined(SYSV)
|
||
# define FUNCS
|
||
#endif
|
||
|
||
#ifdef ISC
|
||
# define FUNCS
|
||
# define STRSPN
|
||
# define NOREGEX
|
||
#endif
|
||
|
||
#ifdef CUTCP
|
||
# define FUNCS
|
||
# define NOREGEX
|
||
# define NEED_STRING_H
|
||
# define SELECTARG int
|
||
# define MSDOS
|
||
#endif
|
||
|
||
#ifdef _AUX_SOURCE
|
||
# define AUX
|
||
# define NOREGEX
|
||
# define NBBY 8 /* Number of bits in a byte. */
|
||
# define long Fd_mask;
|
||
# define NFDBITS (sizeof(Fd_mask) * NBBY) /* bits per mask */
|
||
#endif
|
||
|
||
#ifdef OS2
|
||
# define NOREGEX
|
||
# include <pctcp.h>
|
||
#endif
|
||
#ifdef MSDOS
|
||
# define USG
|
||
# define NOREGEX
|
||
# include <string.h>
|
||
# include <stdlib.h>
|
||
#endif
|
||
|
||
#ifdef _AIX
|
||
# ifdef u370
|
||
# define FUNCS
|
||
# endif /* AIX/370 */
|
||
# define _NONSTD_TYPES
|
||
# define _BSD_INCLUDES
|
||
# define NEED_STRING_H
|
||
# define NEED_SELECT_H
|
||
# define NEED_TIME_H
|
||
#endif
|
||
|
||
/* ==== */
|
||
#ifdef FUNCS
|
||
# define index strchr
|
||
/* According to mycroft. */
|
||
# ifdef _IBMR2
|
||
char *strchr();
|
||
# endif
|
||
# define rindex strrchr
|
||
# ifndef _AUX_SOURCE
|
||
# define bcopy(a,b,n) memcpy(b,a,n)
|
||
# define bzero(a,n) memset(a,0,n)
|
||
# ifdef _IBMR2
|
||
char *memset();
|
||
# endif
|
||
# endif
|
||
#endif
|
||
|
||
#if defined(_IBMR2) || defined(_BULL_SOURCE)
|
||
# define NEED_SELECT_H
|
||
#endif
|
||
#if defined(USG) || defined(UTS)
|
||
# define NEED_STRING_H
|
||
#endif
|
||
#if defined(USG) || defined(UTS) || defined(_AUX_SOURCE)
|
||
# define NEED_TIME_H
|
||
# ifdef UTS
|
||
# define WANT_BOTH_TIME
|
||
# endif
|
||
#endif
|
||
|
||
#ifdef VMS
|
||
/* Get the system status stuff. */
|
||
# include <ssdef.h>
|
||
#endif /* VMS */
|
||
|
||
/*
|
||
* FD_SET: lib/pfs/dirsend.c, user/vget/ftp.c
|
||
*/
|
||
#ifndef CUTCP
|
||
|
||
#define SELECTARG fd_set
|
||
#if !defined(FD_SET) && !defined(VMS) && !defined(NEED_SELECT_H)
|
||
#define FD_SETSIZE 32
|
||
#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
|
||
#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
|
||
#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
|
||
#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
|
||
#endif
|
||
|
||
#endif /* not CUTCP */
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]pprot.h
|
||
$DECK
|
||
/*
|
||
* Copyright (c) 1989, 1990, 1991 by the University of Washington
|
||
*
|
||
* For copying and distribution information, please see the file
|
||
* <copyright.h>.
|
||
*/
|
||
|
||
#include <copyright.h>
|
||
|
||
#ifndef MAXPATHLEN
|
||
# ifdef VMS
|
||
# define MAXPATHLEN 32
|
||
# else /* not VMS */
|
||
# if defined(MSDOS) && !defined(OS2)
|
||
# define MAXPATHLEN 255
|
||
# else /* not MSDOS */
|
||
# ifdef ISC
|
||
# define MAXPATHLEN 512
|
||
# else /* not Interactive..normal! (gasp) */
|
||
# include <sys/param.h>
|
||
# endif /* ISC */
|
||
# endif /* MSDOS && !OS2 */
|
||
# endif /* VMS */
|
||
#endif
|
||
|
||
/* Protocol Definitions */
|
||
|
||
#define VFPROT_VNO 1 /* Protocol Version Number */
|
||
|
||
#define DIRSRV_PORT 1525 /* Server port used if not in srvtab */
|
||
#define PROSPERO_PORT 191 /* Officially assigned prived port */
|
||
#define PROS_FIRST_PRIVP 901 /* First privileged port to try */
|
||
#define PROS_NUM_PRIVP 20 /* Number of privileged ports to try */
|
||
|
||
#define MAXPKT 1024 /* Max size of response from server */
|
||
#define SEQ_SIZE 32 /* Max size of sequence text in resp */
|
||
#define MAX_DIR_LINESIZE 160+MAXPATHLEN /* Max linesize in directory */
|
||
|
||
#define MAX_FWD_DEPTH 20 /* Max fwd pointers to follow */
|
||
|
||
#define S_AD_SZ sizeof(struct sockaddr_in)
|
||
|
||
/* Replacement for strtok that doesn't keep state. Both the variable */
|
||
/* S and the variable S_next must be defined. To initialize, assign */
|
||
/* the string to be stepped through to S_next, then call get_token on */
|
||
/* S. The first token will be in S, and S_next will point to the next */
|
||
/* token. Like strtok, this macro does modify the string passed to it */
|
||
#ifdef __GNUC__
|
||
#define get_token(S,C) \
|
||
do { \
|
||
S = S##_next; \
|
||
if(S) { \
|
||
while(*S == C) S++; \
|
||
S##_next = index(S,C); \
|
||
if(S##_next) *(S##_next++) = '\0'; \
|
||
if(!*S) S = NULL; \
|
||
} \
|
||
} while (0)
|
||
#else
|
||
#define get_token(S,C) \
|
||
S = S/**/_next; \
|
||
do { \
|
||
if(S) { \
|
||
while(*S == C) S++; \
|
||
S/**/_next = index(S,C); \
|
||
if(S/**/_next) *(S/**/_next++) = '\0'; \
|
||
if(!*S) S = NULL; \
|
||
} \
|
||
} while (0)
|
||
#endif /* __GNUC__ */
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]procquery.c
|
||
$DECK
|
||
/*
|
||
* procquery.c : Routines for processing results from Archie
|
||
*
|
||
* Originally part of the Prospero Archie client by Cliff Neuman (bcn@isi.edu).
|
||
* Modified by Brendan Kehoe (brendan@cs.widener.edu).
|
||
* Re-modified by George Ferguson (ferguson@cs.rochester.edu).
|
||
*
|
||
* Copyright (c) 1991 by the University of Washington
|
||
*
|
||
* For copying and distribution information, please see the file
|
||
* <copyright.h>.
|
||
*
|
||
*/
|
||
|
||
#include <copyright.h>
|
||
#include <stdio.h>
|
||
#include <pfs.h>
|
||
#include <perrno.h>
|
||
#include <pmachine.h>
|
||
#include <archie.h>
|
||
|
||
#ifdef NEED_TIME_H
|
||
# include <time.h>
|
||
#else
|
||
# ifndef VMS
|
||
# include <sys/time.h>
|
||
# endif
|
||
#endif
|
||
|
||
extern int client_dirsrv_timeout,client_dirsrv_retry; /* dirsend.c */
|
||
extern char *progname;
|
||
|
||
|
||
/*
|
||
* Functions defined here
|
||
*/
|
||
void display_link(), procquery();
|
||
|
||
/*
|
||
* Data defined here
|
||
*/
|
||
extern int pwarn, perrno;
|
||
#ifdef DEBUG
|
||
int pfs_debug;
|
||
#endif
|
||
static struct tm *presenttime;
|
||
static char lastpath[MAX_VPATH] = "\001";
|
||
static char lasthost[MAX_VPATH] = "\001";
|
||
|
||
/* - - - - - - - - */
|
||
/*
|
||
* display_link : Prints the contents of the given virtual link. If
|
||
* listflag is 0, then this uses last{host,path} to save state
|
||
* between calls for a less verbose output. If listflag is non-zero
|
||
* then all information is printed every time.
|
||
*/
|
||
void
|
||
display_link(l,listflag)
|
||
VLINK l;
|
||
int listflag;
|
||
{
|
||
PATTRIB ap;
|
||
char linkpath[MAX_VPATH];
|
||
int dirflag = 0;
|
||
#ifdef MSDOS
|
||
unsigned long size = 0L;
|
||
#else
|
||
int size = 0;
|
||
#endif
|
||
char *modes = "";
|
||
char archie_date[20];
|
||
char *gt_date = "";
|
||
int gt_year = 0;
|
||
int gt_mon = 0;
|
||
int gt_day = 0;
|
||
int gt_hour = 0;
|
||
int gt_min = 0;
|
||
|
||
/* Initialize local buffers */
|
||
*archie_date = '\0';
|
||
|
||
/* Remember if we're looking at a directory */
|
||
if (sindex(l->type,"DIRECTORY"))
|
||
dirflag = 1;
|
||
else
|
||
dirflag = 0;
|
||
|
||
/* Extract the linkpath from the filename */
|
||
strcpy(linkpath,l->filename);
|
||
*(linkpath + (strlen(linkpath) - strlen(l->name) - 1)) = '\0';
|
||
|
||
/* Is this a new host? */
|
||
if (strcmp(l->host,lasthost) != 0) {
|
||
if (!listflag)
|
||
printf("\nHost %s\n\n",l->host);
|
||
strcpy(lasthost,l->host);
|
||
*lastpath = '\001';
|
||
}
|
||
|
||
/* Is this a new linkpath (location)? */
|
||
if(strcmp(linkpath,lastpath) != 0) {
|
||
if (!listflag)
|
||
printf(" Location: %s\n",(*linkpath ? linkpath : "/"));
|
||
strcpy(lastpath,linkpath);
|
||
}
|
||
|
||
/* Parse the attibutes of this link */
|
||
for (ap = l->lattrib; ap; ap = ap->next) {
|
||
if (strcmp(ap->aname,"SIZE") == 0) {
|
||
#ifdef MSDOS
|
||
sscanf(ap->value.ascii,"%lu",&size);
|
||
#else
|
||
sscanf(ap->value.ascii,"%d",&size);
|
||
#endif
|
||
} else if(strcmp(ap->aname,"UNIX-MODES") == 0) {
|
||
modes = ap->value.ascii;
|
||
} else if(strcmp(ap->aname,"LAST-MODIFIED") == 0) {
|
||
gt_date = ap->value.ascii;
|
||
sscanf(gt_date,"%4d%2d%2d%2d%2d",>_year,
|
||
>_mon, >_day, >_hour, >_min);
|
||
if ((12 * (presenttime->tm_year + 1900 - gt_year) +
|
||
presenttime->tm_mon - gt_mon) > 6)
|
||
sprintf(archie_date,"%s %2d %4d",month_sname(gt_mon),
|
||
gt_day, gt_year);
|
||
else
|
||
sprintf(archie_date,"%s %2d %02d:%02d",month_sname(gt_mon),
|
||
gt_day, gt_hour, gt_min);
|
||
}
|
||
}
|
||
|
||
/* Print this link's information */
|
||
if (listflag)
|
||
#if defined(MSDOS)
|
||
printf("%s %6lu %s %s%s\n",gt_date,size,l->host,l->filename,
|
||
(dirflag ? "/" : ""));
|
||
#else
|
||
printf("%s %6d %s %s%s\n",gt_date,size,l->host,l->filename,
|
||
(dirflag ? "/" : ""));
|
||
#endif
|
||
else
|
||
#ifdef MSDOS
|
||
printf(" %9s %s %10lu %s %s\n",(dirflag ? "DIRECTORY" : "FILE"),
|
||
modes,size,archie_date,l->name);
|
||
#else
|
||
printf(" %9s %s %10d %s %s\n",(dirflag ? "DIRECTORY" : "FILE"),
|
||
modes,size,archie_date,l->name);
|
||
#endif /* MSDOS */
|
||
|
||
|
||
/* Free the attibutes */
|
||
atlfree(l->lattrib);
|
||
l->lattrib = NULL;
|
||
}
|
||
|
||
/* - - - - - - - - */
|
||
/*
|
||
* procquery : Process the given query and display the results. If
|
||
* sortflag is non-zero, then the results are sorted by increasing
|
||
* date, else by host/filename. If listflag is non-zero then each
|
||
* entry is printed on a separate, complete line. Note that listflag
|
||
* is ignored by xarchie.
|
||
*/
|
||
void
|
||
procquery(host,str,max_hits,offset,query_type,sortflag,listflag)
|
||
char *host,*str;
|
||
int max_hits,offset;
|
||
char query_type;
|
||
int sortflag,listflag;
|
||
{
|
||
VLINK l;
|
||
long now;
|
||
extern int rdgram_priority;
|
||
|
||
/* initialize data structures for this query */
|
||
(void)time(&now);
|
||
presenttime = localtime(&now);
|
||
|
||
/* Do the query */
|
||
if (sortflag == 1)
|
||
l = archie_query(host,str,max_hits,offset,query_type,AQ_INVDATECMP,0);
|
||
else
|
||
l = archie_query(host,str,max_hits,offset,query_type,NULL,0);
|
||
|
||
/* Error? */
|
||
if (perrno != PSUCCESS) {
|
||
if (p_err_text[perrno]) {
|
||
if (*p_err_string)
|
||
fprintf(stderr, "%s: failed: %s - %s\n", progname,
|
||
p_err_text[perrno], p_err_string);
|
||
else
|
||
fprintf(stderr, "%s failed: %s\n", progname, p_err_text[perrno]);
|
||
} else
|
||
fprintf(stderr, "%s failed: Undefined error %d (prospero)", perrno);
|
||
}
|
||
|
||
/* Warning? */
|
||
if (pwarn != PNOWARN) {
|
||
if (*p_warn_string)
|
||
fprintf(stderr, "%s: Warning! %s - %s\n", progname,
|
||
p_warn_text[pwarn], p_warn_string);
|
||
else
|
||
fprintf(stderr, "%s: Warning! %s\n", progname, p_warn_text[pwarn]);
|
||
}
|
||
|
||
|
||
/* Display the results */
|
||
|
||
if (l == (VLINK)NULL && pwarn == PNOWARN && perrno == PSUCCESS) {
|
||
if (! listflag) puts ("No matches.");
|
||
#ifdef CUTCP
|
||
netshut();
|
||
#endif
|
||
exit (1);
|
||
}
|
||
|
||
*lasthost = '\001';
|
||
*lastpath = '\001';
|
||
while (l != NULL) {
|
||
display_link(l,listflag);
|
||
l = l->next;
|
||
}
|
||
}
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]ptalloc.c
|
||
$DECK
|
||
/*
|
||
* Copyright (c) 1989, 1990, 1991 by the University of Washington
|
||
*
|
||
* For copying and distribution information, please see the file
|
||
* <copyright.h>.
|
||
*/
|
||
|
||
#include <copyright.h>
|
||
#include <stdio.h>
|
||
|
||
#include <pfs.h>
|
||
#include <pmachine.h> /* for correct definition of ZERO */
|
||
#ifdef MSDOS
|
||
# define free _pfree /* otherwise we get conflicts with free() */
|
||
#endif
|
||
|
||
static PTEXT free = NULL;
|
||
int ptext_count = 0;
|
||
int ptext_max = 0;
|
||
|
||
/*
|
||
* ptalloc - allocate and initialize ptext structure
|
||
*
|
||
* PTALLOC returns a pointer to an initialized structure of type
|
||
* PTEXT. If it is unable to allocate such a structure, it
|
||
* returns NULL.
|
||
*/
|
||
PTEXT
|
||
ptalloc()
|
||
{
|
||
PTEXT vt;
|
||
if(free) {
|
||
vt = free;
|
||
free = free->next;
|
||
}
|
||
else {
|
||
vt = (PTEXT) malloc(sizeof(PTEXT_ST));
|
||
if (!vt) return(NULL);
|
||
ptext_max++;
|
||
}
|
||
ptext_count++;
|
||
|
||
/* nearly all parts are 0 [or NULL] */
|
||
ZERO(vt);
|
||
/* The offset is to leave room for additional headers */
|
||
vt->start = vt->dat + MAX_PTXT_HDR;
|
||
|
||
return(vt);
|
||
}
|
||
|
||
/*
|
||
* ptfree - free a VTEXT structure
|
||
*
|
||
* VTFREE takes a pointer to a VTEXT structure and adds it to
|
||
* the free list for later reuse.
|
||
*/
|
||
void
|
||
ptfree(vt)
|
||
PTEXT vt;
|
||
{
|
||
vt->next = free;
|
||
vt->previous = NULL;
|
||
free = vt;
|
||
ptext_count--;
|
||
}
|
||
|
||
/*
|
||
* ptlfree - free a VTEXT structure
|
||
*
|
||
* VTLFREE takes a pointer to a VTEXT structure frees it and any linked
|
||
* VTEXT structures. It is used to free an entrie list of VTEXT
|
||
* structures.
|
||
*/
|
||
void
|
||
ptlfree(vt)
|
||
PTEXT vt;
|
||
{
|
||
PTEXT nxt;
|
||
|
||
while(vt != NULL) {
|
||
nxt = vt->next;
|
||
ptfree(vt);
|
||
vt = nxt;
|
||
}
|
||
}
|
||
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]rdgram.h
|
||
$DECK
|
||
/*
|
||
* Copyright (c) 1991 by the University of Washington
|
||
*
|
||
* For copying and distribution information, please see the file
|
||
* <copyright.h>.
|
||
*/
|
||
|
||
#include <copyright.h>
|
||
|
||
/* Queuing priorities for datagrams */
|
||
#define RDGRAM_MAX_PRI 32765 /* Maximum user proiority */
|
||
#define RDGRAM_MAX_SPRI 32767 /* Maximum priority for system use */
|
||
#define RDGRAM_MIN_PRI -32765 /* Maximum user proiority */
|
||
#define RDGRAM_MIN_SPRI -32768 /* Maximum priority for system use */
|
||
|
||
int rdgram_priority = 0;
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]regex.c
|
||
$DECK
|
||
#include <pmachine.h>
|
||
|
||
#ifdef NOREGEX
|
||
/*
|
||
* These routines are BSD regex(3)/ed(1) compatible regular-expression
|
||
* routines written by Ozan S. Yigit, Computer Science, York University.
|
||
* Parts of the code that are not needed by Prospero have been removed,
|
||
* but most of the accompanying information has been left intact.
|
||
* This file is to be included on those operating systems that do not
|
||
* support re_comp and re_exec.
|
||
*/
|
||
|
||
/*
|
||
* regex - Regular expression pattern matching
|
||
* and replacement
|
||
*
|
||
* by: Ozan S. Yigit (oz@nexus.yorku.ca)
|
||
* Dept. of Computing Services
|
||
* York University
|
||
*
|
||
* These routines are the PUBLIC DOMAIN equivalents
|
||
* of regex routines as found in 4.nBSD UN*X, with minor
|
||
* extensions.
|
||
*
|
||
* Modification history:
|
||
*
|
||
* $Log: c-archie-1.3.2-vms.com,v $
|
||
# Revision 1.1.1.1 1994/04/28 00:56:12 bajan
|
||
# Initial import
|
||
#
|
||
* Revision 1.3 89/04/01 14:18:09 oz
|
||
* Change all references to a dfa: this is actually an nfa.
|
||
*
|
||
* Revision 1.2 88/08/28 15:36:04 oz
|
||
* Use a complement bitmap to represent NCL.
|
||
* This removes the need to have seperate
|
||
* code in the pmatch case block - it is
|
||
* just CCL code now.
|
||
*
|
||
* Use the actual CCL code in the CLO
|
||
* section of pmatch. No need for a recursive
|
||
* pmatch call.
|
||
*
|
||
* Use a bitmap table to set char bits in an
|
||
* 8-bit chunk.
|
||
*
|
||
* Routines:
|
||
* re_comp: compile a regular expression into
|
||
* a NFA.
|
||
*
|
||
* char *re_comp(s)
|
||
* char *s;
|
||
*
|
||
* re_exec: execute the NFA to match a pattern.
|
||
*
|
||
* int re_exec(s)
|
||
* char *s;
|
||
*
|
||
* Regular Expressions:
|
||
*
|
||
* [1] char matches itself, unless it is a special
|
||
* character (metachar): . \ [ ] * + ^ $
|
||
*
|
||
* [2] . matches any character.
|
||
*
|
||
* [3] \ matches the character following it, except
|
||
* when followed by a left or right round bracket,
|
||
* a digit 1 to 9 or a left or right angle bracket.
|
||
* (see [7], [8] and [9])
|
||
* It is used as an escape character for all
|
||
* other meta-characters, and itself. When used
|
||
* in a set ([4]), it is treated as an ordinary
|
||
* character.
|
||
*
|
||
* [4] [set] matches one of the characters in the set.
|
||
* If the first character in the set is "^",
|
||
* it matches a character NOT in the set, i.e.
|
||
* complements the set. A shorthand S-E is
|
||
* used to specify a set of characters S upto
|
||
* E, inclusive. The special characters "]" and
|
||
* "-" have no special meaning if they appear
|
||
* as the first chars in the set.
|
||
* examples: match:
|
||
*
|
||
* [a-z] any lowercase alpha
|
||
*
|
||
* [^]-] any char except ] and -
|
||
*
|
||
* [^A-Z] any char except uppercase
|
||
* alpha
|
||
*
|
||
* [a-zA-Z] any alpha
|
||
*
|
||
* [5] * any regular expression form [1] to [4], followed by
|
||
* closure char (*) matches zero or more matches of
|
||
* that form.
|
||
*
|
||
* [6] + same as [5], except it matches one or more.
|
||
*
|
||
* [7] a regular expression in the form [1] to [10], enclosed
|
||
* as \(form\) matches what form matches. The enclosure
|
||
* creates a set of tags, used for [8] and for
|
||
* pattern substution. The tagged forms are numbered
|
||
* starting from 1.
|
||
*
|
||
* [8] a \ followed by a digit 1 to 9 matches whatever a
|
||
* previously tagged regular expression ([7]) matched.
|
||
*
|
||
* [9] \< a regular expression starting with a \< construct
|
||
* \> and/or ending with a \> construct, restricts the
|
||
* pattern matching to the beginning of a word, and/or
|
||
* the end of a word. A word is defined to be a character
|
||
* string beginning and/or ending with the characters
|
||
* A-Z a-z 0-9 and _. It must also be preceded and/or
|
||
* followed by any character outside those mentioned.
|
||
*
|
||
* [10] a composite regular expression xy where x and y
|
||
* are in the form [1] to [10] matches the longest
|
||
* match of x followed by a match for y.
|
||
*
|
||
* [11] ^ a regular expression starting with a ^ character
|
||
* $ and/or ending with a $ character, restricts the
|
||
* pattern matching to the beginning of the line,
|
||
* or the end of line. [anchors] Elsewhere in the
|
||
* pattern, ^ and $ are treated as ordinary characters.
|
||
*
|
||
*
|
||
* Acknowledgements:
|
||
*
|
||
* HCR's Hugh Redelmeier has been most helpful in various
|
||
* stages of development. He convinced me to include BOW
|
||
* and EOW constructs, originally invented by Rob Pike at
|
||
* the University of Toronto.
|
||
*
|
||
* References:
|
||
* Software tools Kernighan & Plauger
|
||
* Software tools in Pascal Kernighan & Plauger
|
||
* Grep [rsx-11 C dist] David Conroy
|
||
* ed - text editor Un*x Programmer's Manual
|
||
* Advanced editing on Un*x B. W. Kernighan
|
||
* regexp routines Henry Spencer
|
||
*
|
||
* Notes:
|
||
*
|
||
* This implementation uses a bit-set representation for character
|
||
* classes for speed and compactness. Each character is represented
|
||
* by one bit in a 128-bit block. Thus, CCL always takes a
|
||
* constant 16 bytes in the internal nfa, and re_exec does a single
|
||
* bit comparison to locate the character in the set.
|
||
*
|
||
* Examples:
|
||
*
|
||
* pattern: foo*.*
|
||
* compile: CHR f CHR o CLO CHR o END CLO ANY END END
|
||
* matches: fo foo fooo foobar fobar foxx ...
|
||
*
|
||
* pattern: fo[ob]a[rz]
|
||
* compile: CHR f CHR o CCL bitset CHR a CCL bitset END
|
||
* matches: fobar fooar fobaz fooaz
|
||
*
|
||
* pattern: foo\\+
|
||
* compile: CHR f CHR o CHR o CHR \ CLO CHR \ END END
|
||
* matches: foo\ foo\\ foo\\\ ...
|
||
*
|
||
* pattern: \(foo\)[1-3]\1 (same as foo[1-3]foo)
|
||
* compile: BOT 1 CHR f CHR o CHR o EOT 1 CCL bitset REF 1 END
|
||
* matches: foo1foo foo2foo foo3foo
|
||
*
|
||
* pattern: \(fo.*\)-\1
|
||
* compile: BOT 1 CHR f CHR o CLO ANY END EOT 1 CHR - REF 1 END
|
||
* matches: foo-foo fo-fo fob-fob foobar-foobar ...
|
||
*
|
||
*/
|
||
|
||
#define MAXNFA 1024
|
||
#define MAXTAG 10
|
||
|
||
#define OKP 1
|
||
#define NOP 0
|
||
|
||
#define CHR 1
|
||
#define ANY 2
|
||
#define CCL 3
|
||
#define BOL 4
|
||
#define EOL 5
|
||
#define BOT 6
|
||
#define EOT 7
|
||
#define BOW 8
|
||
#define EOW 9
|
||
#define REF 10
|
||
#define CLO 11
|
||
|
||
#define END 0
|
||
|
||
/*
|
||
* The following defines are not meant
|
||
* to be changeable. They are for readability
|
||
* only.
|
||
*
|
||
*/
|
||
#define MAXCHR 128
|
||
#define CHRBIT 8
|
||
#define BITBLK MAXCHR/CHRBIT
|
||
#define BLKIND 0170
|
||
#define BITIND 07
|
||
|
||
#define ASCIIB 0177
|
||
|
||
typedef /*unsigned*/ char CHAR;
|
||
|
||
static int tagstk[MAXTAG]; /* subpat tag stack..*/
|
||
static CHAR nfa[MAXNFA]; /* automaton.. */
|
||
static int sta = NOP; /* status of lastpat */
|
||
|
||
static CHAR bittab[BITBLK]; /* bit table for CCL */
|
||
/* pre-set bits... */
|
||
static CHAR bitarr[] = {1,2,4,8,16,32,64,128};
|
||
|
||
static int internal_error;
|
||
|
||
static void
|
||
chset(c)
|
||
register CHAR c;
|
||
{
|
||
bittab[((c) & BLKIND) >> 3] |= bitarr[(c) & BITIND];
|
||
}
|
||
|
||
#define badpat(x) return (*nfa = END, x)
|
||
#define store(x) *mp++ = x
|
||
|
||
char *
|
||
re_comp(pat)
|
||
char *pat;
|
||
{
|
||
register char *p; /* pattern pointer */
|
||
register CHAR *mp = nfa; /* nfa pointer */
|
||
register CHAR *lp; /* saved pointer.. */
|
||
register CHAR *sp = nfa; /* another one.. */
|
||
|
||
register int tagi = 0; /* tag stack index */
|
||
register int tagc = 1; /* actual tag count */
|
||
|
||
register int n;
|
||
register CHAR mask; /* xor mask -CCL/NCL */
|
||
int c1, c2;
|
||
|
||
if (!pat || !*pat)
|
||
if (sta)
|
||
return 0;
|
||
else
|
||
badpat("No previous regular expression");
|
||
sta = NOP;
|
||
|
||
for (p = pat; *p; p++) {
|
||
lp = mp;
|
||
switch(*p) {
|
||
|
||
case '.': /* match any char.. */
|
||
store(ANY);
|
||
break;
|
||
|
||
case '^': /* match beginning.. */
|
||
if (p == pat)
|
||
store(BOL);
|
||
else {
|
||
store(CHR);
|
||
store(*p);
|
||
}
|
||
break;
|
||
|
||
case '$': /* match endofline.. */
|
||
if (!*(p+1))
|
||
store(EOL);
|
||
else {
|
||
store(CHR);
|
||
store(*p);
|
||
}
|
||
break;
|
||
|
||
case '[': /* match char class..*/
|
||
store(CCL);
|
||
|
||
if (*++p == '^') {
|
||
mask = 0377;
|
||
p++;
|
||
}
|
||
else
|
||
mask = 0;
|
||
|
||
if (*p == '-') /* real dash */
|
||
chset(*p++);
|
||
if (*p == ']') /* real brac */
|
||
chset(*p++);
|
||
while (*p && *p != ']') {
|
||
if (*p == '-' && *(p+1) && *(p+1) != ']') {
|
||
p++;
|
||
c1 = *(p-2) + 1;
|
||
c2 = *p++;
|
||
while (c1 <= c2)
|
||
chset(c1++);
|
||
}
|
||
#ifdef EXTEND
|
||
else if (*p == '\\' && *(p+1)) {
|
||
p++;
|
||
chset(*p++);
|
||
}
|
||
#endif
|
||
else
|
||
chset(*p++);
|
||
}
|
||
if (!*p)
|
||
badpat("Missing ]");
|
||
|
||
for (n = 0; n < BITBLK; bittab[n++] = (char) 0)
|
||
store(mask ^ bittab[n]);
|
||
|
||
break;
|
||
|
||
case '*': /* match 0 or more.. */
|
||
case '+': /* match 1 or more.. */
|
||
if (p == pat)
|
||
badpat("Empty closure");
|
||
lp = sp; /* previous opcode */
|
||
if (*lp == CLO) /* equivalence.. */
|
||
break;
|
||
switch(*lp) {
|
||
|
||
case BOL:
|
||
case BOT:
|
||
case EOT:
|
||
case BOW:
|
||
case EOW:
|
||
case REF:
|
||
badpat("Illegal closure");
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if (*p == '+')
|
||
for (sp = mp; lp < sp; lp++)
|
||
store(*lp);
|
||
|
||
store(END);
|
||
store(END);
|
||
sp = mp;
|
||
while (--mp > lp)
|
||
*mp = mp[-1];
|
||
store(CLO);
|
||
mp = sp;
|
||
break;
|
||
|
||
case '\\': /* tags, backrefs .. */
|
||
switch(*++p) {
|
||
|
||
case '(':
|
||
if (tagc < MAXTAG) {
|
||
tagstk[++tagi] = tagc;
|
||
store(BOT);
|
||
store(tagc++);
|
||
}
|
||
else
|
||
badpat("Too many \\(\\) pairs");
|
||
break;
|
||
case ')':
|
||
if (*sp == BOT)
|
||
badpat("Null pattern inside \\(\\)");
|
||
if (tagi > 0) {
|
||
store(EOT);
|
||
store(tagstk[tagi--]);
|
||
}
|
||
else
|
||
badpat("Unmatched \\)");
|
||
break;
|
||
case '<':
|
||
store(BOW);
|
||
break;
|
||
case '>':
|
||
if (*sp == BOW)
|
||
badpat("Null pattern inside \\<\\>");
|
||
store(EOW);
|
||
break;
|
||
case '1':
|
||
case '2':
|
||
case '3':
|
||
case '4':
|
||
case '5':
|
||
case '6':
|
||
case '7':
|
||
case '8':
|
||
case '9':
|
||
n = *p-'0';
|
||
if (tagi > 0 && tagstk[tagi] == n)
|
||
badpat("Cyclical reference");
|
||
if (tagc > n) {
|
||
store(REF);
|
||
store(n);
|
||
}
|
||
else
|
||
badpat("Undetermined reference");
|
||
break;
|
||
#ifdef EXTEND
|
||
case 'b':
|
||
store(CHR);
|
||
store('\b');
|
||
break;
|
||
case 'n':
|
||
store(CHR);
|
||
store('\n');
|
||
break;
|
||
case 'f':
|
||
store(CHR);
|
||
store('\f');
|
||
break;
|
||
case 'r':
|
||
store(CHR);
|
||
store('\r');
|
||
break;
|
||
case 't':
|
||
store(CHR);
|
||
store('\t');
|
||
break;
|
||
#endif
|
||
default:
|
||
store(CHR);
|
||
store(*p);
|
||
}
|
||
break;
|
||
|
||
default : /* an ordinary char */
|
||
store(CHR);
|
||
store(*p);
|
||
break;
|
||
}
|
||
sp = lp;
|
||
}
|
||
if (tagi > 0)
|
||
badpat("Unmatched \\(");
|
||
store(END);
|
||
sta = OKP;
|
||
return 0;
|
||
}
|
||
|
||
|
||
static char *bol;
|
||
static char *bopat[MAXTAG];
|
||
static char *eopat[MAXTAG];
|
||
char *pmatch();
|
||
|
||
/*
|
||
* re_exec:
|
||
* execute nfa to find a match.
|
||
*
|
||
* special cases: (nfa[0])
|
||
* BOL
|
||
* Match only once, starting from the
|
||
* beginning.
|
||
* CHR
|
||
* First locate the character without
|
||
* calling pmatch, and if found, call
|
||
* pmatch for the remaining string.
|
||
* END
|
||
* re_comp failed, poor luser did not
|
||
* check for it. Fail fast.
|
||
*
|
||
* If a match is found, bopat[0] and eopat[0] are set
|
||
* to the beginning and the end of the matched fragment,
|
||
* respectively.
|
||
*
|
||
*/
|
||
|
||
int
|
||
re_exec(lp)
|
||
register char *lp;
|
||
{
|
||
register char c;
|
||
register char *ep = 0;
|
||
register CHAR *ap = nfa;
|
||
|
||
bol = lp;
|
||
|
||
bopat[0] = 0;
|
||
bopat[1] = 0;
|
||
bopat[2] = 0;
|
||
bopat[3] = 0;
|
||
bopat[4] = 0;
|
||
bopat[5] = 0;
|
||
bopat[6] = 0;
|
||
bopat[7] = 0;
|
||
bopat[8] = 0;
|
||
bopat[9] = 0;
|
||
|
||
switch(*ap) {
|
||
|
||
case BOL: /* anchored: match from BOL only */
|
||
ep = pmatch(lp,ap);
|
||
break;
|
||
case CHR: /* ordinary char: locate it fast */
|
||
c = *(ap+1);
|
||
while (*lp && *lp != c)
|
||
lp++;
|
||
if (!*lp) /* if EOS, fail, else fall thru. */
|
||
return 0;
|
||
default: /* regular matching all the way. */
|
||
while (*lp) {
|
||
if ((ep = pmatch(lp,ap)))
|
||
break;
|
||
lp++;
|
||
}
|
||
break;
|
||
case END: /* munged automaton. fail always */
|
||
return 0;
|
||
}
|
||
if (!ep)
|
||
return 0;
|
||
|
||
if (internal_error)
|
||
return -1;
|
||
|
||
bopat[0] = lp;
|
||
eopat[0] = ep;
|
||
return 1;
|
||
}
|
||
|
||
/*
|
||
* pmatch:
|
||
* internal routine for the hard part
|
||
*
|
||
* This code is mostly snarfed from an early
|
||
* grep written by David Conroy. The backref and
|
||
* tag stuff, and various other mods are by oZ.
|
||
*
|
||
* special cases: (nfa[n], nfa[n+1])
|
||
* CLO ANY
|
||
* We KNOW ".*" will match ANYTHING
|
||
* upto the end of line. Thus, go to
|
||
* the end of line straight, without
|
||
* calling pmatch recursively. As in
|
||
* the other closure cases, the remaining
|
||
* pattern must be matched by moving
|
||
* backwards on the string recursively,
|
||
* to find a match for xy (x is ".*" and
|
||
* y is the remaining pattern) where
|
||
* the match satisfies the LONGEST match
|
||
* for x followed by a match for y.
|
||
* CLO CHR
|
||
* We can again scan the string forward
|
||
* for the single char without recursion,
|
||
* and at the point of failure, we execute
|
||
* the remaining nfa recursively, as
|
||
* described above.
|
||
*
|
||
* At the end of a successful match, bopat[n] and eopat[n]
|
||
* are set to the beginning and end of subpatterns matched
|
||
* by tagged expressions (n = 1 to 9).
|
||
*
|
||
*/
|
||
|
||
/*
|
||
* character classification table for word boundary
|
||
* operators BOW and EOW. the reason for not using
|
||
* ctype macros is that we can let the user add into
|
||
* our own table. see re_modw. This table is not in
|
||
* the bitset form, since we may wish to extend it
|
||
* in the future for other character classifications.
|
||
*
|
||
* TRUE for 0-9 A-Z a-z _
|
||
*/
|
||
static char chrtyp[MAXCHR] = {
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||
1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
|
||
0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
|
||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||
1, 0, 0, 0, 0, 1, 0, 1, 1, 1,
|
||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||
1, 1, 1, 0, 0, 0, 0, 0
|
||
};
|
||
|
||
#define inascii(x) (0177&(x))
|
||
#define iswordc(x) chrtyp[inascii(x)]
|
||
#define isinset(x,y) ((x)[((y)&BLKIND)>>3] & bitarr[(y)&BITIND])
|
||
|
||
/*
|
||
* skip values for CLO XXX to skip past the closure
|
||
*
|
||
*/
|
||
|
||
#define ANYSKIP 2 /* [CLO] ANY END ... */
|
||
#define CHRSKIP 3 /* [CLO] CHR chr END ... */
|
||
#define CCLSKIP 18 /* [CLO] CCL 16bytes END ... */
|
||
|
||
static char *
|
||
pmatch(lp, ap)
|
||
register char *lp;
|
||
register CHAR *ap;
|
||
{
|
||
register int op, c, n;
|
||
register char *e; /* extra pointer for CLO */
|
||
register char *bp; /* beginning of subpat.. */
|
||
register char *ep; /* ending of subpat.. */
|
||
char *are; /* to save the line ptr. */
|
||
|
||
while ((op = *ap++) != END)
|
||
switch(op) {
|
||
|
||
case CHR:
|
||
if (*lp++ != *ap++)
|
||
return 0;
|
||
break;
|
||
case ANY:
|
||
if (!*lp++)
|
||
return 0;
|
||
break;
|
||
case CCL:
|
||
c = *lp++;
|
||
if (!isinset(ap,c))
|
||
return 0;
|
||
ap += BITBLK;
|
||
break;
|
||
case BOL:
|
||
if (lp != bol)
|
||
return 0;
|
||
break;
|
||
case EOL:
|
||
if (*lp)
|
||
return 0;
|
||
break;
|
||
case BOT:
|
||
bopat[*ap++] = lp;
|
||
break;
|
||
case EOT:
|
||
eopat[*ap++] = lp;
|
||
break;
|
||
case BOW:
|
||
if (lp!=bol && iswordc(lp[-1]) || !iswordc(*lp))
|
||
return 0;
|
||
break;
|
||
case EOW:
|
||
if (lp==bol || !iswordc(lp[-1]) || iswordc(*lp))
|
||
return 0;
|
||
break;
|
||
case REF:
|
||
n = *ap++;
|
||
bp = bopat[n];
|
||
ep = eopat[n];
|
||
while (bp < ep)
|
||
if (*bp++ != *lp++)
|
||
return 0;
|
||
break;
|
||
case CLO:
|
||
are = lp;
|
||
switch(*ap) {
|
||
|
||
case ANY:
|
||
while (*lp)
|
||
lp++;
|
||
n = ANYSKIP;
|
||
break;
|
||
case CHR:
|
||
c = *(ap+1);
|
||
while (*lp && c == *lp)
|
||
lp++;
|
||
n = CHRSKIP;
|
||
break;
|
||
case CCL:
|
||
while ((c = *lp) && isinset(ap+1,c))
|
||
lp++;
|
||
n = CCLSKIP;
|
||
break;
|
||
default:
|
||
internal_error++;
|
||
return 0;
|
||
}
|
||
|
||
ap += n;
|
||
|
||
while (lp >= are) {
|
||
if (e = pmatch(lp, ap))
|
||
return e;
|
||
--lp;
|
||
}
|
||
return 0;
|
||
default:
|
||
internal_error++;
|
||
return 0;
|
||
}
|
||
return lp;
|
||
}
|
||
#endif /* Need regex libraries? Compile to nothing if not. */
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]regex.h
|
||
$DECK
|
||
/*
|
||
* regex.h : External defs for Ozan Yigit's regex functions, for systems
|
||
* that don't have them builtin. See regex.c for copyright and other
|
||
* details.
|
||
*
|
||
* Note that this file can be included even if we're linking against the
|
||
* system routines, since the interface is (deliberately) identical.
|
||
*
|
||
* George Ferguson, ferguson@cs.rochester.edu, 11 Sep 1991.
|
||
*/
|
||
|
||
#if defined(_AUX_SOURCE) || defined(USG)
|
||
/* Let them use ours if they wish. */
|
||
# ifndef NOREGEX
|
||
extern char *regcmp();
|
||
extern char *regex();
|
||
#define re_comp regcmp
|
||
#define re_exec regex
|
||
# endif
|
||
#else
|
||
extern char *re_comp();
|
||
extern int re_exec();
|
||
#endif
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]stcopy.c
|
||
$DECK
|
||
/*
|
||
* Copyright (c) 1989, 1990, 1991 by the University of Washington
|
||
*
|
||
* For copying and distribution information, please see the file
|
||
* <copyright.h>.
|
||
*/
|
||
|
||
#include <copyright.h>
|
||
#include <stdio.h>
|
||
#include <pmachine.h>
|
||
|
||
#ifdef NEED_STRING_H
|
||
# include <string.h>
|
||
#else
|
||
# include <strings.h>
|
||
#endif
|
||
|
||
#if defined(MSDOS)
|
||
# include <stdlib.h>
|
||
#endif
|
||
|
||
char *stcopyr();
|
||
|
||
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.
|
||
*/
|
||
|
||
char *
|
||
stcopy(st)
|
||
char *st;
|
||
{
|
||
if (!st) return(NULL);
|
||
if (string_max < ++string_count) string_max = string_count;
|
||
|
||
return strcpy((char *)malloc(strlen(st) + 1), st);
|
||
}
|
||
|
||
/*
|
||
* stcopyr - copy a string allocating space if necessary
|
||
*
|
||
* STCOPYR takes a 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(s,r)
|
||
char *s;
|
||
char *r;
|
||
{
|
||
int sl;
|
||
|
||
if(!s && r) {
|
||
free(r);
|
||
string_count--;
|
||
return(NULL);
|
||
}
|
||
else if (!s) return(NULL);
|
||
|
||
sl = strlen(s) + 1;
|
||
|
||
if(r) {
|
||
if ((strlen(r) + 1) < sl) {
|
||
free(r);
|
||
r = (char *) malloc(sl);
|
||
}
|
||
}
|
||
else {
|
||
r = (char *) malloc(sl);
|
||
string_count++;
|
||
if(string_max < string_count) string_max = string_count;
|
||
}
|
||
|
||
return strcpy(r,s);
|
||
}
|
||
|
||
/*
|
||
* 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(st)
|
||
char *st;
|
||
{
|
||
if(st) {
|
||
free(st);
|
||
string_count--;
|
||
}
|
||
}
|
||
|
||
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]support.c
|
||
$DECK
|
||
/*
|
||
* Copyright (c) 1989, 1990, 1991 by the University of Washington
|
||
*
|
||
* For copying and distribution information, please see the file
|
||
* <copyright.h>.
|
||
*/
|
||
|
||
/*
|
||
* Miscellaneous routines pulled from ~beta/lib/pfs and ~beta/lib/filters
|
||
*/
|
||
|
||
#include <copyright.h>
|
||
#include <stdio.h>
|
||
|
||
#include <errno.h>
|
||
|
||
#ifdef VMS
|
||
# ifdef WOLLONGONG
|
||
# include "twg$tcp:[netdist.include]netdb.h"
|
||
# else /* not Wollongong */
|
||
# ifdef UCX
|
||
# include netdb
|
||
# else /* Multinet */
|
||
# include "multinet_root:[multinet.include]netdb.h"
|
||
# endif
|
||
# endif
|
||
# include <vms.h>
|
||
#else /* not VMS */
|
||
# include <sys/types.h>
|
||
# include <pmachine.h>
|
||
# ifdef NEED_STRING_H
|
||
# include <string.h>
|
||
# else
|
||
# include <strings.h>
|
||
# endif
|
||
# ifndef CUTCP
|
||
# include <netdb.h>
|
||
# endif
|
||
# if !defined(MSDOS) || defined(OS2)
|
||
# include <sys/file.h>
|
||
# include <sys/param.h>
|
||
# endif
|
||
#endif /* VMS */
|
||
|
||
#include <pfs.h>
|
||
#include <pprot.h>
|
||
#include <perrno.h>
|
||
#include <pcompat.h>
|
||
#include <pauthent.h>
|
||
|
||
#include "regex.h"
|
||
|
||
int pfs_enable = PMAP_ATSIGN;
|
||
|
||
#ifndef FALSE
|
||
# define TRUE 1
|
||
# define FALSE 0
|
||
#endif
|
||
|
||
/*
|
||
* wcmatch - Match string s against template containing widlcards
|
||
*
|
||
* WCMATCH takes a string and a template, and returns
|
||
* true if the string matches the template, and
|
||
* FALSE otherwise.
|
||
*
|
||
* ARGS: s - string to be tested
|
||
* template - Template containing optional wildcards
|
||
*
|
||
* RETURNS: TRUE (non-zero) on match. FALSE (0) otherwise.
|
||
*
|
||
* NOTE: If template is NULL, will return TRUE.
|
||
*
|
||
*/
|
||
int
|
||
wcmatch(s,template)
|
||
char *s;
|
||
char *template;
|
||
{
|
||
char temp[200];
|
||
char *p = temp;
|
||
|
||
if(!template) return(TRUE);
|
||
*p++ = '^';
|
||
|
||
while(*template) {
|
||
if(*template == '*') {*(p++)='.'; *(p++) = *(template++);}
|
||
else if(*template == '?') {*(p++)='.';template++;}
|
||
else if(*template == '.') {*(p++)='\\';*(p++)='.';template++;}
|
||
else if(*template == '[') {*(p++)='\\';*(p++)='[';template++;}
|
||
else if(*template == '$') {*(p++)='\\';*(p++)='$';template++;}
|
||
else if(*template == '^') {*(p++)='\\';*(p++)='^';template++;}
|
||
else if(*template == '\\') {*(p++)='\\';*(p++)='\\';template++;}
|
||
else *(p++) = *(template++);
|
||
}
|
||
|
||
*p++ = '$';
|
||
*p++ = '\0';
|
||
|
||
if(re_comp(temp)) return(FALSE);
|
||
|
||
#ifdef AUX
|
||
if (re_exec(s) == (char *)NULL)
|
||
return 0;
|
||
return 1;
|
||
#else
|
||
return(re_exec(s));
|
||
#endif
|
||
}
|
||
|
||
/*
|
||
* ul_insert - Insert a union link at the right location
|
||
*
|
||
* UL_INSERT takes a directory and a union link to be added
|
||
* to a the list of union links in the directory. It then
|
||
* inserts the union link in the right spot in the linked
|
||
* list of union links associated with that directory.
|
||
*
|
||
* If an identical link already exists, then the link which
|
||
* would be evaluated earlier (closer to the front of the list)
|
||
* wins and the other one is freed. If this happens, an error
|
||
* will also be returned.
|
||
*
|
||
* ARGS: ul - link to be inserted
|
||
* vd - directory to get link
|
||
* p - vl that this link will apper after
|
||
* NULL - This vl will go at end of list
|
||
* vd - This vl will go at head of list
|
||
*
|
||
* RETURNS: Success, or UL_INSERT_ALREADY_THERE or UL_INSERT_SUPERSEDING
|
||
*/
|
||
int
|
||
ul_insert(ul,vd,p)
|
||
VLINK ul; /* Link to be inserted */
|
||
PVDIR vd; /* Directory to receive link */
|
||
VLINK p; /* Union link to appear prior to new one */
|
||
{
|
||
VLINK current;
|
||
|
||
/* This is the first ul in the directory */
|
||
if(vd->ulinks == NULL) {
|
||
vd->ulinks = ul;
|
||
ul->previous = NULL;
|
||
ul->next = NULL;
|
||
return(PSUCCESS);
|
||
}
|
||
|
||
/* This ul will go at the head of the list */
|
||
if(p == (VLINK) vd) {
|
||
ul->next = vd->ulinks;
|
||
ul->next->previous = ul;
|
||
vd->ulinks = ul;
|
||
ul->previous = NULL;
|
||
}
|
||
/* Otherwise, decide if it must be inserted at all */
|
||
/* If an identical link appears before the position */
|
||
/* at which the new one is to be inserted, we can */
|
||
/* return without inserting it */
|
||
else {
|
||
current = vd->ulinks;
|
||
|
||
while(current) {
|
||
/* p == NULL means we insert after last link */
|
||
if(!p && (current->next == NULL))
|
||
p = current;
|
||
|
||
if(vl_comp(current,ul) == 0) {
|
||
vlfree(ul);
|
||
return(UL_INSERT_ALREADY_THERE);
|
||
}
|
||
|
||
if(current == p) break;
|
||
current = current->next;
|
||
}
|
||
|
||
/* If current is null, p was not found */
|
||
if(current == NULL)
|
||
return(UL_INSERT_POS_NOTFOUND);
|
||
|
||
/* Insert ul */
|
||
ul->next = p->next;
|
||
p->next = ul;
|
||
ul->previous = p;
|
||
if(ul->next) ul->next->previous = ul;
|
||
}
|
||
|
||
/* Check for identical links after ul */
|
||
current = ul->next;
|
||
|
||
while(current) {
|
||
if(vl_comp(current,ul) == 0) {
|
||
current->previous->next = current->next;
|
||
if(current->next)
|
||
current->next->previous = current->previous;
|
||
vlfree(current);
|
||
return(UL_INSERT_SUPERSEDING);
|
||
}
|
||
current = current->next;
|
||
}
|
||
|
||
return(PSUCCESS);
|
||
}
|
||
|
||
/*
|
||
* vl_insert - Insert a directory link at the right location
|
||
*
|
||
* VL_INSERT takes a directory and a link to be added to a
|
||
* directory and inserts it in the linked list of links for
|
||
* that directory.
|
||
*
|
||
* If a link already exists with the same name, and if the
|
||
* information associated with the new link matches that in
|
||
* the existing link, an error is returned. If the information
|
||
* associated with the new link is different, but the magic numbers
|
||
* match, then the new link will be added as a replica of the
|
||
* existing link. If the magic numbers do not match, the new
|
||
* link will only be added to the list of "replicas" if the
|
||
* allow_conflict flag has been set.
|
||
*
|
||
* If the link is not added, an error is returned and the link
|
||
* is freed. Ordering for the list of links is by the link name.
|
||
*
|
||
* If vl is a union link, then VL_INSERT calls ul_insert with an
|
||
* added argument indicating the link is to be included at the
|
||
* end of the union link list.
|
||
*
|
||
* ARGS: vl - Link to be inserted, vd - directory to get link
|
||
* allow_conflict - insert links with conflicting names
|
||
*
|
||
* RETURNS: Success, or VL_INSERT_ALREADY_THERE
|
||
*/
|
||
int
|
||
vl_insert(vl,vd,allow_conflict)
|
||
VLINK vl; /* Link to be inserted */
|
||
PVDIR vd; /* Directory to receive link */
|
||
int allow_conflict; /* Allow duplicate names */
|
||
{
|
||
VLINK current; /* To step through list */
|
||
VLINK crep; /* To step through list of replicas */
|
||
int retval; /* Temp for checking returned values */
|
||
|
||
/* This can also be used to insert union links at end of list */
|
||
if(vl->linktype == 'U') return(ul_insert(vl,vd,NULL));
|
||
|
||
/* If this is the first link in the directory */
|
||
if(vd->links == NULL) {
|
||
vd->links = vl;
|
||
vl->previous = NULL;
|
||
vl->next = NULL;
|
||
vd->lastlink = vl;
|
||
return(PSUCCESS);
|
||
}
|
||
|
||
/* If no sorting is to be done, just insert at end of list */
|
||
if(allow_conflict == VLI_NOSORT) {
|
||
vd->lastlink->next = vl;
|
||
vl->previous = vd->lastlink;
|
||
vl->next = NULL;
|
||
vd->lastlink = vl;
|
||
return(PSUCCESS);
|
||
}
|
||
|
||
/* If it is to be inserted at start of list */
|
||
if(vl_comp(vl,vd->links) < 0) {
|
||
vl->next = vd->links;
|
||
vl->previous = NULL;
|
||
vl->next->previous = vl;
|
||
vd->links = vl;
|
||
return(PSUCCESS);
|
||
}
|
||
|
||
current = vd->links;
|
||
|
||
/* Otherwise, we must find the right spot to insert it */
|
||
while((retval = vl_comp(vl,current)) > 0) {
|
||
if(!current->next) {
|
||
/* insert at end */
|
||
vl->previous = current;
|
||
vl->next = NULL;
|
||
current->next = vl;
|
||
vd->lastlink = vl;
|
||
return(PSUCCESS);
|
||
}
|
||
current = current->next;
|
||
}
|
||
|
||
/* If we found an equivilant entry already in list */
|
||
if(!retval) {
|
||
if(vl_equal(vl,current)) {
|
||
vlfree(vl);
|
||
return(VL_INSERT_ALREADY_THERE);
|
||
}
|
||
if((allow_conflict == VLI_NOCONFLICT) &&
|
||
((vl->f_magic_no != current->f_magic_no) ||
|
||
(vl->f_magic_no==0)))
|
||
return(VL_INSERT_CONFLICT);
|
||
/* Insert the link into the list of "replicas" */
|
||
/* If magic is 0, then create a pseudo magic number */
|
||
if(vl->f_magic_no == 0) vl->f_magic_no = -1;
|
||
crep = current->replicas;
|
||
if(!crep) {
|
||
current->replicas = vl;
|
||
vl->next = NULL;
|
||
vl->previous = NULL;
|
||
}
|
||
else {
|
||
while(crep->next) {
|
||
/* If magic was 0, then we need a unique magic number */
|
||
if((crep->f_magic_no < 0) && (vl->f_magic_no < 1))
|
||
(vl->f_magic_no)--;
|
||
crep = crep->next;
|
||
}
|
||
/* If magic was 0, then we need a unique magic number */
|
||
if((crep->f_magic_no < 0) && (vl->f_magic_no < 1))
|
||
(vl->f_magic_no)--;
|
||
crep->next = vl;
|
||
vl->previous = crep;
|
||
vl->next = NULL;
|
||
}
|
||
return(PSUCCESS);
|
||
}
|
||
|
||
/* We found the spot where vl is to be inserted */
|
||
vl->next = current;
|
||
vl->previous = current->previous;
|
||
current->previous = vl;
|
||
vl->previous->next = vl;
|
||
return(PSUCCESS);
|
||
}
|
||
|
||
/*
|
||
* nlsindex - Find first instance of string 2 in string 1 following newline
|
||
*
|
||
* NLSINDEX scans string 1 for the first instance of string
|
||
* 2 that immediately follows a newline. If found, NLSINDEX
|
||
* returns a pointer to the first character of that instance.
|
||
* If no instance is found, NLSINDEX returns NULL (0).
|
||
*
|
||
* NOTE: This function is only useful for searching strings that
|
||
* consist of multiple lines. s1 is assumed to be preceeded
|
||
* by a newline. Thus, if s2 is at the start of s1, it will
|
||
* be found.
|
||
* ARGS: s1 - string to be searched
|
||
* s2 - string to be found
|
||
* RETURNS: First instance of s2 in s1, or NULL (0) if not found
|
||
*/
|
||
char *
|
||
nlsindex(s1,s2)
|
||
char *s1; /* String to be searched */
|
||
char *s2; /* String to be found */
|
||
{
|
||
register int s2len = strlen(s2);
|
||
char *curline = s1; /* Pointer to start of current line */
|
||
|
||
/* In case s2 appears at start of s1 */
|
||
if(strncmp(curline,s2,s2len) == 0)
|
||
return(curline);
|
||
|
||
/* Check remaining lines of s1 */
|
||
while((curline = (char *) index(curline,'\n')) != NULL) {
|
||
curline++;
|
||
if(strncmp(curline,s2,s2len) == 0)
|
||
return(curline);
|
||
}
|
||
|
||
/* We didn't find it */
|
||
return(NULL);
|
||
}
|
||
|
||
/*
|
||
* 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]);
|
||
}
|
||
|
||
/*
|
||
* 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
|
||
*/
|
||
char *
|
||
sindex(s1,s2)
|
||
char *s1; /* String to be searched */
|
||
char *s2; /* String to be found */
|
||
{
|
||
register int s2len = strlen(s2);
|
||
char *s = s1; /* Temp pointer to string */
|
||
|
||
/* Check for first character of s2 */
|
||
while((s = (char *) index(s,*s2)) != NULL) {
|
||
if(strncmp(s,s2,s2len) == 0)
|
||
return(s);
|
||
s++;
|
||
}
|
||
|
||
/* We didn't find it */
|
||
return(NULL);
|
||
}
|
||
|
||
int
|
||
scan_error(erst)
|
||
char *erst;
|
||
{
|
||
*p_err_string = '\0';
|
||
|
||
if(strncmp(erst,"NOT-A-DIRECTORY",15) == 0)
|
||
return(DIRSRV_NOT_DIRECTORY);
|
||
|
||
if(strncmp(erst,"UNIMPLEMENTED",13) == 0) {
|
||
perrno = DIRSRV_UNIMPLEMENTED;
|
||
sscanf(erst+13,"%*[^\n \t\r]%*[ \t]%[^\n]",p_err_string);
|
||
return(perrno);
|
||
}
|
||
|
||
if(strncmp(erst,"WARNING ",8) == 0) {
|
||
erst += 8;
|
||
*p_warn_string = '\0';
|
||
sscanf(erst,"%*[^\n \t\r]%*[ \t]%[^\n]",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;
|
||
sscanf(erst,"%[^\n]",p_warn_string);
|
||
return(PSUCCESS);
|
||
}
|
||
else if(strncmp(erst,"ERROR",5) == 0) {
|
||
if(*(erst+5)) sscanf(erst+6,"%[^\n]",p_err_string);
|
||
perrno = DIRSRV_ERROR;
|
||
return(perrno);
|
||
}
|
||
/* The rest start with "FAILURE" */
|
||
else if(strncmp(erst,"FAILURE",7) != 0) {
|
||
/* Unrecognized - Give warning, but return PSUCCESS */
|
||
if(pwarn == 0) {
|
||
*p_warn_string = '\0';
|
||
pwarn = PWARN_UNRECOGNIZED_RESP;
|
||
sscanf(erst,"%[^\n]",p_warn_string);
|
||
}
|
||
return(PSUCCESS);
|
||
}
|
||
|
||
if(strncmp(erst,"FAILURE ",8) != 0) {
|
||
perrno = PFAILURE;
|
||
return(perrno);
|
||
}
|
||
erst += 8;
|
||
|
||
sscanf(erst,"%*[^\n \t\r]%*[ \t]%[^\n]",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-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,"SERVER-FAILED",13) == 0)
|
||
perrno = DIRSRV_SERVER_FAILED;
|
||
/* Use it whether it starts with FAILURE or not */
|
||
else if(strncmp(erst,"NOT-A-DIRECTORY",15) == 0)
|
||
perrno = DIRSRV_NOT_DIRECTORY;
|
||
else perrno = PFAILURE;
|
||
|
||
return(perrno);
|
||
}
|
||
|
||
PATTRIB
|
||
parse_attribute(line)
|
||
char *line;
|
||
{
|
||
char l_precedence[MAX_DIR_LINESIZE];
|
||
char l_name[MAX_DIR_LINESIZE];
|
||
char l_type[MAX_DIR_LINESIZE];
|
||
char l_value[MAX_DIR_LINESIZE];
|
||
PATTRIB at;
|
||
int tmp;
|
||
|
||
tmp = sscanf(line,"OBJECT-INFO %s %s %[^\n]", l_name, l_type, l_value);
|
||
|
||
if(tmp < 3) {
|
||
tmp = sscanf(line,"LINK-INFO %s %s %s %[^\n]", l_precedence,
|
||
l_name, l_type, l_value);
|
||
if(tmp < 4) {
|
||
perrno = DIRSRV_BAD_FORMAT;
|
||
return(NULL);
|
||
}
|
||
}
|
||
|
||
at = atalloc();
|
||
|
||
if(tmp == 4) {
|
||
if(strcmp(l_precedence,"CACHED") == 0)
|
||
at->precedence = ATR_PREC_CACHED;
|
||
else if(strcmp(l_precedence,"LINK") == 0)
|
||
at->precedence = ATR_PREC_LINK;
|
||
else if(strcmp(l_precedence,"REPLACEMENT") == 0)
|
||
at->precedence = ATR_PREC_REPLACE;
|
||
else if(strcmp(l_precedence,"ADDITIONAL") == 0)
|
||
at->precedence = ATR_PREC_ADD;
|
||
}
|
||
|
||
at->aname = stcopy(l_name);
|
||
at->avtype = stcopy(l_type);
|
||
if(strcmp(l_type,"ASCII") == 0)
|
||
at->value.ascii = stcopy(l_value);
|
||
else if(strcmp(l_type,"LINK") == 0) {
|
||
char ftype[MAX_DIR_LINESIZE];
|
||
char lname[MAX_DIR_LINESIZE];
|
||
char htype[MAX_DIR_LINESIZE];
|
||
char host[MAX_DIR_LINESIZE];
|
||
char ntype[MAX_DIR_LINESIZE];
|
||
char fname[MAX_DIR_LINESIZE];
|
||
VLINK al;
|
||
|
||
al = vlalloc();
|
||
at->value.link = al;
|
||
|
||
tmp = sscanf(l_value,"%c %s %s %s %s %s %s %d %d",
|
||
&(al->linktype),
|
||
ftype,lname,htype,host,ntype,fname,
|
||
&(al->version),
|
||
&(al->f_magic_no));
|
||
if(tmp == 9) {
|
||
al->type = stcopyr(ftype,al->type);
|
||
al->name = stcopyr(unquote(lname),al->name);
|
||
al->hosttype = stcopyr(htype,al->hosttype);
|
||
al->host = stcopyr(host,al->host);
|
||
al->nametype = stcopyr(ntype,al->nametype);
|
||
al->filename = stcopyr(fname,al->filename);
|
||
}
|
||
else {
|
||
perrno = DIRSRV_BAD_FORMAT;
|
||
return(NULL);
|
||
}
|
||
|
||
}
|
||
|
||
return(at);
|
||
}
|
||
|
||
/*
|
||
* nxtline - Find the next line in the string
|
||
*
|
||
* NXTLINE takes a string and returns a pointer to
|
||
* the character immediately following the next newline.
|
||
*
|
||
* ARGS: s - string to be searched
|
||
*
|
||
* RETURNS: Next line or NULL (0) on failure
|
||
*/
|
||
char *
|
||
nxtline(s)
|
||
char *s; /* String to be searched */
|
||
{
|
||
s = (char *) index(s,'\n');
|
||
if(s) return(++s);
|
||
else return(NULL);
|
||
}
|
||
|
||
|
||
/*
|
||
* unquote - unquote string if necessary
|
||
*
|
||
* UNQUOTE takes a string and unquotes it if it has been quoted.
|
||
*
|
||
* ARGS: s - string to be unquoted
|
||
*
|
||
* RETURNS: The original string. If the string has been quoted, then the
|
||
* result appears in static storage, and must be copied if
|
||
* it is to last beyond the next call to quote.
|
||
*
|
||
*/
|
||
char *
|
||
unquote(s)
|
||
char *s; /* String to be quoted */
|
||
{
|
||
static char unquoted[200];
|
||
char *c = unquoted;
|
||
|
||
if(*s != '\'') return(s);
|
||
|
||
s++;
|
||
|
||
/* This should really treat a quote followed by other */
|
||
/* than a quote or a null as an error */
|
||
while(*s) {
|
||
if(*s == '\'') s++;
|
||
if(*s) *c++ = *s++;
|
||
}
|
||
|
||
*c++ = '\0';
|
||
|
||
return(unquoted);
|
||
}
|
||
|
||
#if defined(DEBUG) && defined(STRSPN)
|
||
/* needed for -D option parsing */
|
||
/*
|
||
* 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
|
||
*/
|
||
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);
|
||
}
|
||
#endif
|
||
|
||
#ifdef CUTCP
|
||
char
|
||
*inet_ntoa(struct in_addr in)
|
||
{
|
||
static char buff[36];
|
||
|
||
unsigned char *c = (char *) &in.address;
|
||
sprintf(buff,"%d.%d.%d.%d",*c,*(c+1),*(c+2),*(c+3));
|
||
return(buff);
|
||
}
|
||
|
||
long
|
||
inet_addr(char *cp)
|
||
{
|
||
long value = 0;
|
||
unsigned v1,v2,v3,v4;
|
||
|
||
v1 = v2 = v3 = v4 = 0xff;
|
||
sscanf(cp,"%d.%d.%d.%d",&v1,&v2,&v3,&v4);
|
||
value = (v1 << 24) | (v2 << 16) | (v3 << 8) | v4;
|
||
return(value);
|
||
}
|
||
|
||
struct hostent
|
||
*gethostbyname(char *name)
|
||
{
|
||
struct machinfo *mp;
|
||
int mnum;
|
||
unsigned long now;
|
||
static struct hostent ht;
|
||
extern int pfs_debug;
|
||
|
||
mp = Shostlook(name);
|
||
if(!mp || (!mp->hostip[0])) { /* DNS lookup */
|
||
#ifdef DEBUG
|
||
if (pfs_debug)
|
||
fprintf(stderr, "Domain name lookup of %s\n", name);
|
||
#endif
|
||
mnum = Sdomain(name); /* start a DNS lookup */
|
||
now = time(NULL) + NS_TIMEOUT;
|
||
while(now > time(NULL)) {
|
||
int i, class, dat;
|
||
|
||
Stask();
|
||
i = Sgetevent(USERCLASS, &class, &dat);
|
||
if(i == DOMOK) { /* domain lookup ok */
|
||
mp = Slooknum(mnum);
|
||
#ifdef DEBUG
|
||
if (pfs_debug)
|
||
fprintf(stderr, "Domain name lookup of %s Completed OK\n", name);
|
||
#endif
|
||
break;
|
||
}
|
||
}
|
||
if(!mp) { /* get here if timeout */
|
||
#ifdef DEBUG
|
||
if (pfs_debug)
|
||
fprintf(stderr, "Domain name lookup of %s Failed\n", name);
|
||
#endif
|
||
return(NULL);
|
||
}
|
||
}
|
||
ht.h_addr = *((unsigned long *) mp->hostip);
|
||
ht.h_length = 4;
|
||
ht.h_addrtype = AF_INET;
|
||
return(&ht);
|
||
|
||
}
|
||
#endif /* CUTCP */
|
||
|
||
#ifdef GETENV
|
||
/*
|
||
* Copyright (c) 1987 Regents of the University of California.
|
||
* All rights reserved.
|
||
*
|
||
* Redistribution and use in source and binary forms are permitted
|
||
* provided that: (1) source distributions retain this entire copyright
|
||
* notice and comment, and (2) distributions including binaries display
|
||
* the following acknowledgement: ``This product includes software
|
||
* developed by the University of California, Berkeley and its contributors''
|
||
* in the documentation or other materials provided with the distribution
|
||
* and in all advertising materials mentioning features or use of this
|
||
* software. Neither the name of the University nor the names of its
|
||
* contributors may be used to endorse or promote products derived
|
||
* from this software without specific prior written permission.
|
||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||
*/
|
||
|
||
#if defined(LIBC_SCCS) && !defined(lint)
|
||
static char sccsid[] = "@(#)getenv.c 5.7 (Berkeley) 6/1/90";
|
||
#endif /* LIBC_SCCS and not lint */
|
||
|
||
#include <stdlib.h>
|
||
#include <stddef.h>
|
||
|
||
/*
|
||
* getenv --
|
||
* Returns ptr to value associated with name, if any, else NULL.
|
||
*/
|
||
char *
|
||
getenv(name)
|
||
char *name;
|
||
{
|
||
int offset;
|
||
char *_findenv();
|
||
|
||
return(_findenv(name, &offset));
|
||
}
|
||
|
||
/*
|
||
* _findenv --
|
||
* Returns pointer to value associated with name, if any, else NULL.
|
||
* Sets offset to be the offset of the name/value combination in the
|
||
* environmental array, for use by setenv(3) and unsetenv(3).
|
||
* Explicitly removes '=' in argument name.
|
||
*
|
||
* This routine *should* be a static; don't use it.
|
||
*/
|
||
char *
|
||
_findenv(name, offset)
|
||
register char *name;
|
||
int *offset;
|
||
{
|
||
extern char **environ;
|
||
register int len;
|
||
register char **P, *C;
|
||
|
||
for (C = name, len = 0; *C && *C != '='; ++C, ++len);
|
||
for (P = environ; *P; ++P)
|
||
if (!strncmp(*P, name, len))
|
||
if (*(C = *P + len) == '=') {
|
||
*offset = P - environ;
|
||
return(++C);
|
||
}
|
||
return(NULL);
|
||
}
|
||
#endif
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]copyright.h
|
||
$DECK
|
||
/* These are the uw-copyright.h and usc-copyright.h files that appear in
|
||
the Prospero distribution. */
|
||
|
||
/*
|
||
Copyright (c) 1989, 1990, 1991 by the University of Washington
|
||
|
||
Permission to use, copy, modify, and distribute this software and its
|
||
documentation for non-commercial purposes and without fee is hereby
|
||
granted, provided that the above copyright notice appear in all copies
|
||
and that both the copyright notice and this permission notice appear in
|
||
supporting documentation, and that the name of the University of
|
||
Washington not be used in advertising or publicity pertaining to
|
||
distribution of the software without specific, written prior
|
||
permission. The University of Washington makes no representations
|
||
about the suitability of this software for any purpose. It is
|
||
provided "as is" without express or implied warranty.
|
||
|
||
Prospero was written by Clifford Neuman (bcn@isi.edu).
|
||
|
||
Questions concerning this software should be directed to
|
||
info-prospero@isi.edu.
|
||
|
||
*/
|
||
|
||
/*
|
||
Copyright (c) 1991, 1992 by the University of Southern California
|
||
All rights reserved.
|
||
|
||
Permission to use, copy, modify, and distribute this software and its
|
||
documentation in source and binary forms for non-commercial purposes
|
||
and without fee is hereby granted, provided that the above copyright
|
||
notice appear in all copies and that both the copyright notice and
|
||
this permission notice appear in supporting documentation. and that
|
||
any documentation, advertising materials, and other materials related
|
||
to such distribution and use acknowledge that the software was
|
||
developed by the University of Southern California, Information
|
||
Sciences Institute. The name of the University may not be used to
|
||
endorse or promote products derived from this software without
|
||
specific prior written permission.
|
||
|
||
THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about
|
||
the suitability of this software for any purpose. THIS SOFTWARE IS
|
||
PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
|
||
INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||
|
||
Other copyrights might apply to parts of the Prospero distribution
|
||
and are so noted when applicable.
|
||
|
||
Prospero was originally written by Clifford Neuman (bcn@isi.edu).
|
||
Contributors include Benjamin Britt (britt@isi.edu)
|
||
and others identified in individual modules.
|
||
|
||
Questions concerning this software should be directed to
|
||
info-prospero@isi.edu.
|
||
|
||
*/
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]udp.c
|
||
$DECK
|
||
/*
|
||
* udp - Check if UDP traffic is allowed on this host; we open port 1527 on
|
||
* a system (default of cs.widener.edu), which is expecting it; the
|
||
* date is output (e.g. very similar to the daytime service). This
|
||
* will conclusively tell us if UDP traffic on ports > 1000 is allowed.
|
||
*
|
||
* It should print out the date if UDP traffic's not blocked on your
|
||
* system. If it just hangs, try these tests too:
|
||
* a. run it with -d (e.g. "udp -d"); that goes to the normal UDP port
|
||
* to print the date. If it works, then you can be sure that any
|
||
* UDP traffic > port 1000 is blocked on your system.
|
||
* b. if it hangs too, try "telnet 147.31.254.130 13" and see if
|
||
* _that_ prints the date; if it doesn't, it's another problem (your
|
||
* network can't get to me, e.g.).
|
||
*
|
||
* Compile by: cc -o udp udp.c
|
||
*
|
||
* Brendan Kehoe, brendan@cs.widener.edu, Oct 1991.
|
||
*/
|
||
|
||
#include <stdio.h>
|
||
#include <sys/types.h>
|
||
#include <sys/socket.h>
|
||
#include <netinet/in.h>
|
||
#ifndef hpux
|
||
# include <arpa/inet.h>
|
||
#endif
|
||
|
||
#define SIZE 2048
|
||
#define HOST "147.31.254.130" /* cs.widener.edu */
|
||
#define PORT 1527
|
||
|
||
main (argc, argv)
|
||
int argc;
|
||
char **argv;
|
||
{
|
||
int s, len;
|
||
struct sockaddr_in server, sa;
|
||
char buf[SIZE];
|
||
|
||
if ((s = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
|
||
{
|
||
perror ("socket()");
|
||
exit (1);
|
||
}
|
||
|
||
bzero ((char *) &sa, sizeof (sa));
|
||
sa.sin_family = AF_INET;
|
||
sa.sin_addr.s_addr = htonl (INADDR_ANY);
|
||
sa.sin_port = htons (0);
|
||
|
||
if (bind (s, (struct sockaddr *) &sa, sizeof (sa)) < 0)
|
||
{
|
||
perror ("bind()");
|
||
exit (1);
|
||
}
|
||
|
||
bzero ((char *) &server, sizeof (server));
|
||
server.sin_family = AF_INET;
|
||
server.sin_addr.s_addr = inet_addr (HOST);
|
||
if (argc > 1 && strcmp(*(argv + 1), "-d") == 0)
|
||
server.sin_port = htons ((unsigned short) 13);
|
||
else
|
||
server.sin_port = htons ((unsigned short) PORT);
|
||
|
||
/* yoo hoo, we're here .. */
|
||
if (sendto (s, "\n", 1, 0, &server, sizeof (server)) < 0)
|
||
{
|
||
perror ("sendto()");
|
||
exit (1);
|
||
}
|
||
|
||
/* slurp */
|
||
len = sizeof (server);
|
||
if (recvfrom (s, buf, sizeof (buf), 0, &server, &len) < 0)
|
||
{
|
||
perror ("recvfrom");
|
||
exit (1);
|
||
}
|
||
|
||
printf ("%s", buf);
|
||
close (s);
|
||
}
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]vl_comp.c
|
||
$DECK
|
||
/*
|
||
* Copyright (c) 1989, 1990, 1991 by the University of Washington
|
||
*
|
||
* For copying and distribution information, please see the file
|
||
* <copyright.h>.
|
||
*/
|
||
|
||
#include <copyright.h>
|
||
#include <pfs.h>
|
||
|
||
/*
|
||
* vl_comp - compare the names of two virtual links
|
||
*
|
||
* VL_COMP compares the names of two links. It returns
|
||
* 0 if they are equal, negative if vl1 < vl2, and positive if
|
||
* vl1 > vl2.
|
||
*
|
||
* ARGS: vl1,vl2 - Virtual links to be compared
|
||
*
|
||
* RETURNS: 0 if equal, + is vl1 > vl2, - if vl1 < vl2
|
||
*
|
||
* NOTES: Order of significance is as follows. Existence,
|
||
* name. If names do not exist, then hosttype, host,
|
||
* native filenametype, native filename. The only time
|
||
* the name will not exist if if the link is a union link.
|
||
*/
|
||
int
|
||
vl_comp(vl1,vl2)
|
||
VLINK vl1;
|
||
VLINK vl2;
|
||
{
|
||
int retval;
|
||
|
||
if(vl1->name && !vl2->name) return(1);
|
||
if(!vl1->name && vl2->name) return(-1);
|
||
if(vl1->name && vl2->name && (*(vl1->name) || *(vl2->name)))
|
||
return(strcmp(vl1->name,vl2->name));
|
||
|
||
retval = strcmp(vl1->hosttype,vl2->hosttype);
|
||
if(!retval) retval = strcmp(vl1->host,vl2->host);
|
||
if(!retval) retval = strcmp(vl1->nametype,vl2->nametype);
|
||
if(!retval) retval = strcmp(vl1->filename,vl2->filename);
|
||
return(retval);
|
||
}
|
||
|
||
/*
|
||
* vl_equal - compare the values of two virtual links
|
||
*
|
||
* VL_EQUAL compares the values of two links. It returns
|
||
* 1 if all important fields are the same, and 0 otherwise.
|
||
*
|
||
* ARGS: vl1,vl2 - Virtual links to be compared
|
||
*
|
||
* RETURNS: 1 if equal, 0 if not equal
|
||
*
|
||
*/
|
||
int
|
||
vl_equal(vl1,vl2)
|
||
VLINK vl1;
|
||
VLINK vl2;
|
||
{
|
||
return strcmp(vl1->name, vl2->name) == 0 &&
|
||
vl1->linktype == vl2->linktype &&
|
||
strcmp(vl1->type, vl2->type) == 0 &&
|
||
strcmp(vl1->hosttype, vl2->hosttype) == 0 &&
|
||
strcmp(vl1->host, vl2->host) == 0 &&
|
||
strcmp(vl1->nametype, vl2->nametype) == 0 &&
|
||
strcmp(vl1->filename, vl2->filename) == 0 &&
|
||
vl1->version == vl2->version &&
|
||
vl1->f_magic_no == vl2->f_magic_no ;
|
||
|
||
}
|
||
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]vlalloc.c
|
||
$DECK
|
||
/*
|
||
* Copyright (c) 1989, 1990, 1991 by the University of Washington
|
||
*
|
||
* For copying and distribution information, please see the file
|
||
* <copyright.h>.
|
||
*/
|
||
|
||
#include <copyright.h>
|
||
#include <stdio.h>
|
||
|
||
#include <pfs.h>
|
||
#include <pmachine.h>
|
||
|
||
static VLINK lfree = NULL;
|
||
int vlink_count = 0;
|
||
int vlink_max = 0;
|
||
|
||
/*
|
||
* vlalloc - allocate and initialize vlink structure
|
||
*
|
||
* VLALLOC returns a pointer to an initialized structure of type
|
||
* VLINK. If it is unable to allocate such a structure, it
|
||
* returns NULL.
|
||
*/
|
||
VLINK
|
||
vlalloc()
|
||
{
|
||
VLINK vl;
|
||
if(lfree) {
|
||
vl = lfree;
|
||
lfree = lfree->next;
|
||
}
|
||
else {
|
||
vl = (VLINK) malloc(sizeof(VLINK_ST));
|
||
if (!vl) return(NULL);
|
||
vlink_max++;
|
||
}
|
||
|
||
vlink_count++;
|
||
|
||
/* Initialize and fill in default values */
|
||
/* Since all but four are set to a zero-value,
|
||
why not just wipe it clean? */
|
||
ZERO(vl);
|
||
|
||
vl->linktype = 'L';
|
||
vl->type = stcopy("FILE");
|
||
vl->hosttype = stcopy("INTERNET-D");
|
||
vl->nametype = stcopy("ASCII");
|
||
|
||
return(vl);
|
||
}
|
||
|
||
/*
|
||
* vlfree - free a VLINK structure
|
||
*
|
||
* VLFREE takes a pointer to a VLINK structure and adds it to
|
||
* the free list for later reuse.
|
||
*/
|
||
void
|
||
vlfree(vl)
|
||
VLINK vl;
|
||
{
|
||
extern int string_count;
|
||
|
||
if(vl->dontfree) return;
|
||
/* many of these don't need to call stfree(); since a check
|
||
for pointer validity's already done before even calling
|
||
it, we can just call free() here then do one big decrement
|
||
of string_count at the end. */
|
||
if(vl->name) free(vl->name);
|
||
stfree(vl->type);
|
||
if(vl->replicas) vllfree(vl->replicas);
|
||
stfree(vl->hosttype);
|
||
if(vl->host) free(vl->host);
|
||
stfree(vl->nametype);
|
||
if(vl->filename) free(vl->filename);
|
||
if(vl->args) free(vl->args);
|
||
if(vl->lattrib) atlfree(vl->lattrib);
|
||
/* No allocation routines for f_info yet */
|
||
vl->f_info = NULL;
|
||
vl->next = lfree;
|
||
vl->previous = NULL;
|
||
lfree = vl;
|
||
vlink_count--;
|
||
string_count -= 4; /* freed name, host, filename, and args */
|
||
}
|
||
|
||
/*
|
||
* vllfree - free a VLINK structure
|
||
*
|
||
* VLLFREE takes a pointer to a VLINK structure frees it and any linked
|
||
* VLINK structures. It is used to free an entrie list of VLINK
|
||
* structures.
|
||
*/
|
||
void
|
||
vllfree(vl)
|
||
VLINK vl;
|
||
{
|
||
VLINK nxt;
|
||
|
||
while((vl != NULL) && !vl->dontfree) {
|
||
nxt = vl->next;
|
||
vlfree(vl);
|
||
vl = nxt;
|
||
}
|
||
}
|
||
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]vms.h
|
||
$DECK
|
||
#ifndef _ARCHIE_VMS
|
||
#define _ARCHIE_VMS
|
||
#include <pmachine.h>
|
||
|
||
#if !defined(MULTINET_30) && !defined(WOLLONGONG) && !defined(UCX)
|
||
#include "[.vms]pseudos.h"
|
||
#include "[.vms]types.h"
|
||
#include "[.vms]in.h"
|
||
#include "[.vms]signal.h"
|
||
#include "[.vms]socket.h"
|
||
#include "[.vms]time.h"
|
||
|
||
#else
|
||
|
||
/* time_t gets multiply defined <ekup> */
|
||
#ifndef __TYPES
|
||
#define __TYPES
|
||
#endif
|
||
#ifdef MULTINET_30
|
||
# include "multinet_root:[multinet.include.sys]types.h"
|
||
# include "multinet_root:[multinet.include.netinet]in.h"
|
||
# include "multinet_root:[multinet.include.sys]socket.h"
|
||
# include "multinet_root:[multinet.include.sys]time.h"
|
||
#endif /* MULTINET_30 */
|
||
|
||
#ifdef WOLLONGONG
|
||
/* We don't want size_t defined. */
|
||
# ifndef __STDDEF
|
||
# define __STDDEF
|
||
# endif
|
||
# include "twg$tcp:[netdist.include.sys]types.h"
|
||
# include "twg$tcp:[netdist.include.netinet]in.h"
|
||
# include "twg$tcp:[netdist.include.sys]socket.h"
|
||
# include "twg$tcp:[netdist.include.sys]time.h"
|
||
#endif /* WOLLONGONG */
|
||
|
||
#ifdef UCX
|
||
# include <types.h>
|
||
# include <in.h>
|
||
# include <socket.h>
|
||
# include <time.h>
|
||
# include "[.vms]fd.h"
|
||
#endif /* UCX */
|
||
|
||
#endif /* Multinet or Wallongong or UCX */
|
||
|
||
#endif /* _ARCHIE_VMS */
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie]vms_support.c
|
||
$DECK
|
||
/* Emulation of 4.2 UNIX socket interface routines includes drivers for
|
||
Wollongong, CMU-TEK, UCX tcp/ip interface and also emulates the SUN
|
||
version of X.25 sockets. The TWG will also work for MultiNet. */
|
||
|
||
/* This is from unixlib, by P.Kay@massey.ac.nz; wonderful implementation.
|
||
You can get the real thing on 130.123.1.4 as unixlib_tar.z. */
|
||
|
||
#include <stdio.h>
|
||
#include <errno.h>
|
||
#include <ssdef.h>
|
||
#include <dvidef.h>
|
||
#include <signal.h>
|
||
#include <sys$library:msgdef.h>
|
||
#include <iodef.h>
|
||
#include <ctype.h>
|
||
#include <vms.h>
|
||
#include "[.vms]network.h"
|
||
|
||
#define QIO_FAILED (st != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL)
|
||
#define QIO_ST_FAILED (st != SS$_NORMAL)
|
||
|
||
/* Socket routine. */
|
||
int
|
||
VMSsocket (domain, type, protocol)
|
||
int domain, type, protocol;
|
||
{
|
||
struct descriptor inetdesc, x25desc, mbxdesc;
|
||
int i, st, s, p_initialise ();
|
||
long ucx_sock_def;
|
||
char *getenv ();
|
||
|
||
if (!tcp_make)
|
||
set_tcp_make ();
|
||
|
||
if (p_initialised == 0)
|
||
{
|
||
for (i = 0; i < 32; i++)
|
||
p_initialise (i);
|
||
|
||
p_initialised = 1;
|
||
}
|
||
|
||
/* First of all, get a file descriptor and file ptr we can associate with
|
||
the socket, allocate a buffer, and remember the socket details. */
|
||
s = dup (0);
|
||
if (s > 31)
|
||
{
|
||
errno = EMFILE;
|
||
close (s);
|
||
return -1;
|
||
}
|
||
|
||
p[s].fptr = fdopen (s, "r");
|
||
p[s].fd_buff = (unsigned char *) malloc (BUF_SIZE);
|
||
p[s].domain = domain;
|
||
p[s].type = type;
|
||
p[s].protocol = protocol;
|
||
|
||
/* Handle the case of INET and X.25 separately. */
|
||
if (domain == AF_INET)
|
||
{
|
||
if (tcp_make == NONE)
|
||
{
|
||
printf ("Trying to obtain a TCP socket when we don't have TCP!\n");
|
||
exit (1);
|
||
}
|
||
if (tcp_make == CMU)
|
||
{
|
||
/* For CMU we need only assign a channel. */
|
||
inetdesc.size = 3;
|
||
inetdesc.ptr = "IP:";
|
||
if (sys$assign (&inetdesc, &p[s].channel, 0, 0) != SS$_NORMAL)
|
||
return -1;
|
||
}
|
||
else if (tcp_make == UCX)
|
||
{
|
||
/* For UCX assign channel and associate a socket with it. */
|
||
inetdesc.size = 3;
|
||
inetdesc.ptr = "BG:";
|
||
if (sys$assign (&inetdesc, &p[s].channel, 0, 0) != SS$_NORMAL)
|
||
return -1;
|
||
|
||
ucx_sock_def = (domain << 24) + (type << 16) + protocol;
|
||
st = sys$qiow (0, p[s].channel, IO$_SETMODE, p[s].iosb, 0, 0,
|
||
&ucx_sock_def, 0, 0, 0, 0, 0);
|
||
if (QIO_FAILED)
|
||
return -1;
|
||
}
|
||
else
|
||
{
|
||
/* For TWG we assign the channel and associate a socket with it. */
|
||
inetdesc.size = 7;
|
||
inetdesc.ptr = "_INET0:";
|
||
|
||
if (sys$assign (&inetdesc, &p[s].channel, 0, 0) != SS$_NORMAL)
|
||
return -1;
|
||
|
||
st = sys$qiow (0, p[s].channel, IO$_SOCKET, p[s].iosb, 0, 0,
|
||
domain, type, 0, 0, 0, 0);
|
||
if (QIO_FAILED)
|
||
return -1;
|
||
}
|
||
}
|
||
else
|
||
/* We don't handle any other domains yet. */
|
||
return -1;
|
||
|
||
/* For each case if we are successful we return the descriptor. */
|
||
return s;
|
||
}
|
||
|
||
/* Bind routine. */
|
||
VMSbind (s, name, namelen)
|
||
int s;
|
||
union socket_addr *name;
|
||
int namelen;
|
||
{
|
||
char infobuff[1024], lhost[32];
|
||
int st;
|
||
|
||
if (!tcp_make)
|
||
set_tcp_make ();
|
||
|
||
if (p[s].domain == AF_INET)
|
||
{
|
||
/* One main problem with bind is that if we're given a port number
|
||
of 0, then we're expected to return a unique port number. Since
|
||
we don't KNOW, we return 1050+s and look to Lady Luck. */
|
||
if (tcp_make == CMU)
|
||
{
|
||
if (name->in.sin_port == 0 && p[s].type != SOCK_DGRAM)
|
||
name->in.sin_port = 1050 + s;
|
||
p[s].namelen = namelen;
|
||
bcopy (name, &(p[s].name), namelen);
|
||
|
||
if (p[s].type == SOCK_DGRAM)
|
||
{
|
||
/* Another problem is that CMU still needs an OPEN request
|
||
even if it's a datagram socket. */
|
||
st = sys$qiow (0, p[s].channel, TCP$OPEN, p[s].iosb,
|
||
0, 0, 0, 0, ntohs (p[s].name.in.sin_port),
|
||
0, 1, 0);
|
||
if (QIO_ST_FAILED)
|
||
return -1;
|
||
|
||
p[s].cmu_open = 1;
|
||
sys$qiow (0, p[s].channel, TCP$INFO, p[s].iosb,
|
||
0, 0, &infobuff, 1024, 0, 0, 0, 0);
|
||
bcopy (infobuff + 264, &(p[s].name.in.sin_port), 2);
|
||
p[s].name.in.sin_port = htons (p[s].name.in.sin_port);
|
||
|
||
/* So get it another way. */
|
||
bcopy (infobuff + 136, lhost, infobuff[1]);
|
||
lhost[infobuff[1]] = '\0';
|
||
sys$qiow (0, p[s].channel, GTHST, p[s].iosb,
|
||
0, 0, &infobuff, 1024, 1, lhost, 0, 0);
|
||
bcopy (infobuff + 4, &(p[s].name.in.sin_addr), 4);
|
||
|
||
/* Be prepared to receive a message. */
|
||
hang_a_read (s);
|
||
}
|
||
}
|
||
else if (tcp_make == UCX)
|
||
{
|
||
/* UCX will select a prot for you. If the port's number is 0,
|
||
translate "name" into an item_2 list. */
|
||
struct itemlist lhost;
|
||
lhost.length = namelen;
|
||
lhost.code = 0;
|
||
lhost.dataptr = (char *) name;
|
||
|
||
st = sys$qiow (0, p[s].channel, IO$_SETMODE, p[s].iosb, 0, 0,
|
||
0, 0, &lhost, 0, 0, 0);
|
||
if (QIO_FAILED)
|
||
return -1;
|
||
|
||
if (p[s].type == SOCK_DGRAM)
|
||
hang_a_read (s);
|
||
|
||
}
|
||
else
|
||
{
|
||
/* WG is more straightforward */
|
||
st = sys$qiow (0, p[s].channel, IO$_BIND, p[s].iosb,
|
||
0, 0, name, namelen, 0, 0, 0, 0);
|
||
if (QIO_FAILED)
|
||
return -1;
|
||
|
||
/* If it's a datagram, get ready for the message. */
|
||
if (p[s].type == SOCK_DGRAM)
|
||
hang_a_read (s);
|
||
}
|
||
}
|
||
else
|
||
/* We don't handle any other domain yet. */
|
||
return -1;
|
||
|
||
return 0;
|
||
}
|
||
|
||
/* Connect routine. */
|
||
VMSconnect (s, name, namelen)
|
||
int s;
|
||
union socket_addr *name;
|
||
int namelen;
|
||
{
|
||
int pr, fl, st;
|
||
char *inet_ntoa ();
|
||
static struct
|
||
{
|
||
int len;
|
||
char name[128];
|
||
} gethostbuf;
|
||
extern int connect_ast ();
|
||
|
||
if (!tcp_make)
|
||
set_tcp_make ();
|
||
|
||
/* For datagrams we need to remember who the name was so we can send all
|
||
messages to that address without having to specify it all the time. */
|
||
if (p[s].connected)
|
||
{
|
||
if (p[s].connected == 1)
|
||
errno = EISCONN;
|
||
else
|
||
{
|
||
errno = ECONNREFUSED;
|
||
p[s].connected = 0;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
if (p[s].connect_pending)
|
||
{
|
||
errno = EALREADY;
|
||
return -1;
|
||
}
|
||
|
||
p[s].passive = 0;
|
||
p[s].tolen = namelen;
|
||
bcopy (name, &(p[s].to), namelen);
|
||
|
||
if (p[s].domain == AF_INET)
|
||
{
|
||
if (tcp_make == CMU)
|
||
{
|
||
|
||
/* Get the info about the remote host and open up a connection. */
|
||
st = sys$qiow (0, p[s].channel, GTHST, p[s].iosb, 0, 0, &gethostbuf,
|
||
132, 2, name->in.sin_addr.s_addr, 0, 0);
|
||
if (QIO_FAILED)
|
||
{
|
||
strcpy (gethostbuf.name, inet_ntoa (name->in.sin_addr.s_addr));
|
||
gethostbuf.len = strlen (gethostbuf.name);
|
||
}
|
||
gethostbuf.name[gethostbuf.len] = 0;
|
||
|
||
/* TCP */
|
||
pr = 0;
|
||
/* Active */
|
||
fl = 1;
|
||
|
||
/* Nothing else for datagrams. */
|
||
if (p[s].type == SOCK_DGRAM)
|
||
return (0);
|
||
st = sys$qio (s, p[s].channel, TCP$OPEN, p[s].iosb, connect_ast,
|
||
&p[s], &(gethostbuf.name), ntohs (name->in.sin_port),
|
||
ntohs (p[s].name.in.sin_port), fl, pr, 0);
|
||
if (QIO_ST_FAILED)
|
||
return -1;
|
||
}
|
||
else if (tcp_make == UCX)
|
||
{
|
||
/* Both UDP and TCP can use a connect - IO$_ACCESS */
|
||
p[s].rhost.length = namelen;
|
||
p[s].rhost.code = 0;
|
||
p[s].rhost.dataptr = (char *) name;
|
||
|
||
st = sys$qio (s, p[s].channel, IO$_ACCESS, p[s].iosb, connect_ast,
|
||
&p[s], 0, 0, &p[s].rhost, 0, 0, 0);
|
||
if (QIO_ST_FAILED)
|
||
return -1;
|
||
}
|
||
else
|
||
{
|
||
/* TWG */
|
||
if (p[s].type == SOCK_DGRAM)
|
||
return (0);
|
||
st = sys$qio (s, p[s].channel, IO$_CONNECT, p[s].iosb, connect_ast,
|
||
&p[s], name, namelen, 0, 0, 0, 0);
|
||
if (QIO_ST_FAILED)
|
||
return -1;
|
||
}
|
||
}
|
||
else
|
||
/* We don't handle any other domain yet. */
|
||
return -1;
|
||
|
||
if (p[s].non_blocking)
|
||
{
|
||
if (p[s].connected)
|
||
{
|
||
if (p[s].connected == 1)
|
||
return 0;
|
||
else
|
||
{
|
||
p[s].connected = 0;
|
||
errno = ECONNREFUSED;
|
||
return -1;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
p[s].connect_pending = 1;
|
||
errno = EINPROGRESS;
|
||
return -1;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/* wait for the connection to occur */
|
||
if (p[s].connected)
|
||
{
|
||
if (p[s].connected == 1)
|
||
return 0;
|
||
else
|
||
{
|
||
p[s].connected = 0;
|
||
errno = ECONNREFUSED;
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
/* Timed out? */
|
||
if (wait_efn (s) == -1)
|
||
return -1;
|
||
|
||
if (p[s].connected != SS$_NORMAL)
|
||
{
|
||
errno = ECONNREFUSED;
|
||
return -1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
/* Listen routine. */
|
||
VMSlisten (s, backlog)
|
||
int s;
|
||
int backlog;
|
||
{
|
||
int st;
|
||
|
||
if (!tcp_make)
|
||
set_tcp_make ();
|
||
|
||
p[s].passive = 1;
|
||
p[s].backlog = backlog;
|
||
if (p[s].domain == AF_INET)
|
||
{
|
||
if (tcp_make == CMU)
|
||
{
|
||
/* For the CMU sockets we can't do the open call in listen;
|
||
we have to do it in hang_an_accept, because when we close
|
||
off the connection we have to be ready to accept another
|
||
one. accept() also calls hang_an_accept on the old
|
||
descriptor. */
|
||
|
||
/* Nothing */
|
||
}
|
||
else if (tcp_make == UCX)
|
||
{
|
||
|
||
/* Doc Verbage sez backlog is descriptor of byte. Doc examples
|
||
and common sense say backlog is value. Value doesn't work,
|
||
so let's try descriptor of byte after all. */
|
||
struct descriptor bl;
|
||
unsigned char ucx_backlog;
|
||
|
||
ucx_backlog = (unsigned char) backlog;
|
||
bl.size = sizeof (ucx_backlog);
|
||
bl.ptr = (char *) &ucx_backlog;
|
||
|
||
st = sys$qiow (0, p[s].channel, IO$_SETMODE, p[s].iosb, 0, 0,
|
||
0, 0, 0, &bl, 0, 0);
|
||
if (QIO_FAILED)
|
||
return -1;
|
||
}
|
||
else
|
||
{
|
||
/* TWG */
|
||
st = sys$qiow (0, p[s].channel, IO$_LISTEN, p[s].iosb, 0, 0,
|
||
backlog, 0, 0, 0, 0, 0);
|
||
if (QIO_FAILED)
|
||
return -1;
|
||
}
|
||
}
|
||
else
|
||
/* We don't handle any other domain yet. */
|
||
return -1;
|
||
|
||
p[s].status = LISTENING;
|
||
hang_an_accept (s);
|
||
return 0;
|
||
}
|
||
|
||
/* Accept routine. */
|
||
int
|
||
VMSaccept (s, addr, addrlen)
|
||
int s;
|
||
union socket_addr *addr;
|
||
int *addrlen;
|
||
{
|
||
int news, st;
|
||
struct descriptor inetdesc;
|
||
|
||
if (!tcp_make)
|
||
set_tcp_make ();
|
||
|
||
if (p[s].non_blocking && !p[s].accept_pending)
|
||
{
|
||
errno = EWOULDBLOCK;
|
||
return -1;
|
||
}
|
||
|
||
/* hang_an_accept set up an incoming connection request so we have first
|
||
to hang around until one appears or we time out. */
|
||
if (p[s].domain == AF_INET)
|
||
{
|
||
if (tcp_make == CMU)
|
||
{
|
||
char infobuff[1024];
|
||
|
||
/* Timed out? */
|
||
if (wait_efn (s) == -1)
|
||
return -1;
|
||
|
||
/* Ok, get a new descriptor ... */
|
||
news = dup (0);
|
||
if (news > 31)
|
||
{
|
||
errno = EMFILE;
|
||
close (news);
|
||
return -1;
|
||
}
|
||
|
||
/* ... and copy all of our data across. */
|
||
bcopy (&p[s], &p[news], sizeof (p[0]));
|
||
|
||
/* But not this field, of course! */
|
||
p[news].s = news;
|
||
|
||
sys$qiow (0, p[news].channel, TCP$INFO, p[news].iosb,
|
||
0, 0, &infobuff, 1024, 0, 0, 0, 0);
|
||
|
||
/* Copy across the connection info if necessary. */
|
||
if (addr != 0)
|
||
{
|
||
*addrlen = sizeof (struct sockaddr_in);
|
||
bcopy (infobuff + 132, &(addr->in.sin_port), 2);
|
||
addr->in.sin_port = htons (addr->in.sin_port);
|
||
addr->in.sin_family = AF_INET;
|
||
bcopy (infobuff + 272, &(addr->in.sin_addr), 4);
|
||
p[news].fromlen = *addrlen;
|
||
bcopy (addr, &(p[news].from), *addrlen);
|
||
}
|
||
p[news].status = PASSIVE_CONNECTION;
|
||
|
||
/* Get a new file ptr for the socket. */
|
||
p[news].fptr = fdopen (news, "r");
|
||
|
||
/* Reset this field. */
|
||
p[news].accept_pending = 0;
|
||
|
||
/* Allocate a buffer. */
|
||
p[news].fd_buff = (unsigned char *) malloc (BUF_SIZE);
|
||
p[news].fd_leftover = 0;
|
||
|
||
/* Be prepared to get msgs. */
|
||
hang_a_read (news);
|
||
|
||
/* Now fix up our previous socket so it's again listening
|
||
for connections. */
|
||
inetdesc.size = 3;
|
||
inetdesc.ptr = "IP:";
|
||
if (sys$assign (&inetdesc, &p[s].channel, 0, 0) != SS$_NORMAL)
|
||
return -1;
|
||
p[s].status = LISTENING;
|
||
hang_an_accept (s);
|
||
|
||
/* Return the new socket descriptor. */
|
||
return news;
|
||
}
|
||
else if (tcp_make == UCX)
|
||
{
|
||
/* UCX does the actual accept from hang_an_accept. The accept info
|
||
is put into the data structure for the "listening" socket.
|
||
These just need to be copied into a newly allocated socket for
|
||
the connect and the listening socket re-started. */
|
||
|
||
/* Wait for event flag from accept being received inside
|
||
of hang_an_accept(). */
|
||
|
||
if (wait_efn (s) == -1)
|
||
/* Timed out. */
|
||
return -1;
|
||
|
||
/* Ok, get a new descriptor ... */
|
||
news = dup (0);
|
||
if (news > 31)
|
||
{
|
||
errno = EMFILE;
|
||
close (news);
|
||
return -1;
|
||
}
|
||
/* ... and copy all of our data across. */
|
||
bcopy (&p[s], &p[news], sizeof (p[0]));
|
||
p[news].s = news; /* but not this field */
|
||
p[news].channel = p[s].ucx_accept_chan;
|
||
|
||
/* Initialize the remote host address item_list_3 struct. */
|
||
p[news].rhost.length = sizeof (struct sockaddr_in);
|
||
p[news].rhost.code = 0;
|
||
p[news].rhost.dataptr = (char *) &p[news].from;
|
||
p[news].rhost.retlenptr = &p[news].fromdummy;
|
||
|
||
if (addr != 0)
|
||
{
|
||
/* Return the caller's info, if requested. */
|
||
*addrlen = p[news].fromdummy;
|
||
bcopy (&p[news].from, addr, p[news].fromdummy);
|
||
}
|
||
|
||
/* Finish fleshing out the new structure. */
|
||
p[news].status = PASSIVE_CONNECTION;
|
||
|
||
/* Get a new file pointer for the socket. */
|
||
p[news].fptr = fdopen (news, "r");
|
||
|
||
/* Reset this field. */
|
||
p[news].accept_pending = 0;
|
||
|
||
/* Allocate a buffer. */
|
||
p[news].fd_buff = (unsigned char *) malloc (BUF_SIZE);
|
||
p[news].fd_leftover = 0;
|
||
|
||
/* Get it started reading. */
|
||
hang_a_read (news);
|
||
|
||
p[s].status = LISTENING;
|
||
hang_an_accept (s);
|
||
|
||
return news;
|
||
}
|
||
else
|
||
{
|
||
/* TWG */
|
||
struct descriptor inetdesc;
|
||
int size;
|
||
|
||
/* Time out? */
|
||
if (wait_efn (s) == -1)
|
||
return -1;
|
||
|
||
/* Ok, get a new descriptor ... */
|
||
news = dup (0);
|
||
if (news > 31)
|
||
{
|
||
errno = EMFILE;
|
||
close (news);
|
||
return -1;
|
||
}
|
||
|
||
/* Assign a new channel. */
|
||
inetdesc.size = 7;
|
||
inetdesc.ptr = "_INET0:";
|
||
st = sys$assign (&inetdesc, &p[news].channel, 0, 0);
|
||
if (QIO_ST_FAILED)
|
||
{
|
||
p[s].accept_pending = 0;
|
||
sys$clref (s);
|
||
return -1;
|
||
}
|
||
|
||
/* From info needs an int length field! */
|
||
size = sizeof (p[s].from) + 4;
|
||
st = sys$qiow (0, p[news].channel, IO$_ACCEPT, p[news].iosb, 0, 0,
|
||
&p[s].fromdummy, size, p[s].channel, 0, 0, 0);
|
||
|
||
if (QIO_ST_FAILED || p[news].iosb[0] != SS$_NORMAL)
|
||
{
|
||
p[s].accept_pending = 0;
|
||
sys$clref (s);
|
||
return -1;
|
||
}
|
||
|
||
if (addr != 0)
|
||
{
|
||
/* Return the caller's info if requested. */
|
||
*addrlen = p[s].fromdummy;
|
||
bcopy (&p[s].from, addr, *addrlen);
|
||
}
|
||
|
||
/* Fix up our new data structure. */
|
||
p[news].status = PASSIVE_CONNECTION;
|
||
p[news].domain = AF_INET;
|
||
p[news].passive = 1;
|
||
p[news].fptr = fdopen (news, "r");
|
||
/* Allocate a buffer. */
|
||
p[news].fd_buff = (unsigned char *) malloc (BUF_SIZE);
|
||
|
||
/* Be prepared to accept msgs. */
|
||
hang_a_read (news);
|
||
|
||
/* Get the old descriptor back onto accepting. */
|
||
hang_an_accept (s);
|
||
return news;
|
||
}
|
||
}
|
||
else
|
||
/* We don't handle any other domain yet. */
|
||
return -1;
|
||
}
|
||
|
||
/* Recv routine. */
|
||
int
|
||
VMSrecv (s, buf, len, flags)
|
||
int s;
|
||
char *buf;
|
||
int len, flags;
|
||
{
|
||
return recvfrom (s, buf, len, flags, 0, 0);
|
||
}
|
||
|
||
/* Revfrom routine. */
|
||
int
|
||
VMSrecvfrom (s, buf, len, flags, from, fromlen)
|
||
int s;
|
||
char *buf;
|
||
int len, flags;
|
||
union socket_addr *from;
|
||
int *fromlen;
|
||
{
|
||
int number;
|
||
|
||
if (!tcp_make)
|
||
set_tcp_make ();
|
||
|
||
if (p[s].domain != AF_INET && p[s].domain != AF_X25)
|
||
return -1;
|
||
|
||
/* If we're not onto datagrams, then it's possible that a previous
|
||
call to recvfrom didn't read all the data, and left some behind.
|
||
So first of all, look in our data buffer for any leftovers that
|
||
will satisfy this read. */
|
||
|
||
/* We couldn't satisfy the request from previous calls so we must now
|
||
wait for a message to come through. */
|
||
if (wait_efn (s) == -1)
|
||
/* Timed out. */
|
||
return -1;
|
||
|
||
if (p[s].closed_by_remote == 1)
|
||
{
|
||
/* This could have happened! */
|
||
errno = ECONNRESET;
|
||
return -1;
|
||
}
|
||
|
||
if (from != NULL)
|
||
{
|
||
if (tcp_make == CMU)
|
||
{
|
||
if (p[s].type == SOCK_DGRAM)
|
||
{
|
||
/* Not documented but we get the from data from the beginning of
|
||
the data buffer. */
|
||
*fromlen = sizeof (p[s].from.in);
|
||
from->in.sin_family = AF_INET;
|
||
bcopy (&p[s].fd_buff[8], &(from->in.sin_port), 2);
|
||
from->in.sin_port = htons (from->in.sin_port);
|
||
bcopy (&p[s].fd_buff[0], &(from->in.sin_addr), 4);
|
||
|
||
/* Remove the address data from front of data buffer. */
|
||
bcopy (p[s].fd_buff + 12, p[s].fd_buff, p[s].fd_buff_size);
|
||
}
|
||
else
|
||
{
|
||
*fromlen = p[s].fromlen;
|
||
bcopy (&p[s].from, from, p[s].fromlen);
|
||
}
|
||
}
|
||
else if (tcp_make == UCX)
|
||
{
|
||
*fromlen = p[s].fromdummy;
|
||
bcopy (&p[s].from, from, p[s].fromdummy);
|
||
}
|
||
else
|
||
{
|
||
*fromlen = p[s].fromlen;
|
||
bcopy (&p[s].from, from, p[s].fromlen);
|
||
}
|
||
}
|
||
|
||
/* We may've received too much. */
|
||
number = p[s].fd_buff_size;
|
||
if (number <= len)
|
||
{
|
||
/* If we haven't give back all the data available. */
|
||
bcopy (p[s].fd_buff, buf, number);
|
||
p[s].fd_leftover = 0;
|
||
hang_a_read (s);
|
||
return (number);
|
||
}
|
||
else
|
||
{
|
||
/* If we have too much data then split it up. */
|
||
p[s].fd_leftover = p[s].fd_buff;
|
||
bcopy (p[s].fd_leftover, buf, len);
|
||
/* And change the pointers. */
|
||
p[s].fd_leftover += len;
|
||
p[s].fd_buff_size -= len;
|
||
return (len);
|
||
}
|
||
}
|
||
|
||
/* Send routine. */
|
||
int
|
||
VMSsend (s, msg, len, flags)
|
||
int s;
|
||
char *msg;
|
||
int len, flags;
|
||
{
|
||
return sendto (s, msg, len, flags, 0, 0);
|
||
}
|
||
|
||
/* Sendto routine. */
|
||
int
|
||
VMSsendto (s, msg, len, flags, to, tolen)
|
||
int s;
|
||
unsigned char *msg;
|
||
int len, flags;
|
||
union socket_addr *to;
|
||
int tolen;
|
||
{
|
||
int i, j, st, size;
|
||
unsigned char udpbuf[BUF_SIZE + 12];
|
||
char infobuff[1024], lhost[32];
|
||
unsigned short int temp;
|
||
|
||
if (!tcp_make)
|
||
set_tcp_make ();
|
||
|
||
/* First remember who we sent it to and set the value of size. */
|
||
if (to != 0)
|
||
{
|
||
p[s].tolen = tolen;
|
||
bcopy (to, &(p[s].to), tolen);
|
||
size = tolen;
|
||
}
|
||
else
|
||
size = 0;
|
||
|
||
if (p[s].domain == AF_INET)
|
||
{
|
||
/* We might never have started a read for udp (socket/sendto) so
|
||
put one here. */
|
||
if (p[s].type == SOCK_DGRAM)
|
||
hang_a_read (s);
|
||
|
||
if (tcp_make == CMU)
|
||
{
|
||
if (p[s].type == SOCK_DGRAM)
|
||
{
|
||
/* We might never have opened up a udp connection yet,
|
||
so check. */
|
||
if (p[s].cmu_open != 1)
|
||
{
|
||
st = sys$qiow (0, p[s].channel, TCP$OPEN, p[s].iosb, 0, 0,
|
||
0, 0, 0, 0, 1, 0);
|
||
if (QIO_ST_FAILED)
|
||
return -1;
|
||
|
||
p[s].cmu_open = 1;
|
||
sys$qiow (0, p[s].channel, TCP$INFO, p[s].iosb,
|
||
0, 0, &infobuff, 1024, 0, 0, 0, 0);
|
||
bcopy (infobuff + 264, &(p[s].name.in.sin_port), 2);
|
||
p[s].name.in.sin_port = htons (p[s].name.in.sin_port);
|
||
bcopy (infobuff + 136, lhost, infobuff[1]);
|
||
lhost[infobuff[1]] = '\0';
|
||
sys$qiow (0, p[s].channel, GTHST, p[s].iosb,
|
||
0, 0, &infobuff, 1024, 1, lhost, 0, 0);
|
||
bcopy (infobuff + 4, &(p[s].name.in.sin_addr), 4);
|
||
}
|
||
|
||
/* This isn't well documented. To send to a UDP socket, we
|
||
need to put the address info at the beginning of the
|
||
buffer. */
|
||
bcopy (msg, udpbuf + 12, len);
|
||
bcopy (&p[s].to.in.sin_addr, udpbuf + 4, 4);
|
||
temp = ntohs (p[s].to.in.sin_port);
|
||
bcopy (&temp, udpbuf + 10, 2);
|
||
bcopy (&p[s].name.in.sin_addr, udpbuf, 4);
|
||
temp = ntohs (p[s].name.in.sin_port);
|
||
bcopy (&temp, udpbuf + 8, 2);
|
||
temp = len + 12;
|
||
st = sys$qiow (0, p[s].channel, TCP$SEND, p[s].iosb, 0, 0,
|
||
udpbuf, temp, 0, 0, 0, 0);
|
||
if (QIO_FAILED)
|
||
return -1;
|
||
}
|
||
else
|
||
{
|
||
/* TCP (! UDP) */
|
||
st = sys$qiow (0, p[s].channel, TCP$SEND, p[s].iosb, 0, 0,
|
||
msg, len, 0, 0, 0, 0);
|
||
if (QIO_FAILED)
|
||
return -1;
|
||
}
|
||
return len;
|
||
}
|
||
else if (tcp_make == UCX)
|
||
{
|
||
struct itemlist rhost;
|
||
rhost.length = sizeof (struct sockaddr_in);
|
||
rhost.code = 0;
|
||
rhost.dataptr = (char *) &p[s].to;
|
||
|
||
st = sys$qiow (0, p[s].channel, IO$_WRITEVBLK, p[s].iosb, 0, 0,
|
||
msg, len, &rhost, 0, 0, 0);
|
||
if (QIO_FAILED)
|
||
return -1;
|
||
|
||
return len;
|
||
}
|
||
else
|
||
{
|
||
/* TWG */
|
||
st = sys$qiow (0, p[s].channel, IO$_WRITEVBLK, p[s].iosb,
|
||
0, 0, msg, len, 0, &p[s].to, size, 0);
|
||
if (QIO_FAILED)
|
||
return -1;
|
||
|
||
return len;
|
||
}
|
||
}
|
||
else
|
||
/* We don't handle any other domain yet. */
|
||
return -1;
|
||
}
|
||
|
||
/* Getsockname routine. */
|
||
int
|
||
VMSgetsockname (s, name, namelen)
|
||
int s;
|
||
union socket_addr *name;
|
||
int *namelen;
|
||
{
|
||
int st;
|
||
|
||
if (!tcp_make)
|
||
set_tcp_make ();
|
||
|
||
if (p[s].domain == AF_INET)
|
||
{
|
||
if (tcp_make == CMU)
|
||
{
|
||
/* For CMU we just return values held in our data structure. */
|
||
*namelen = p[s].namelen;
|
||
bcopy (&(p[s].name), name, *namelen);
|
||
return (0);
|
||
}
|
||
else if (tcp_make == UCX)
|
||
{
|
||
/* An item_list_3 descriptor. */
|
||
struct itemlist lhost;
|
||
|
||
lhost.length = *namelen;
|
||
lhost.code = 0;
|
||
lhost.dataptr = (char *) name;
|
||
|
||
/* Fill in namelen with actual ret len value. */
|
||
lhost.retlenptr = (short int *) namelen;
|
||
|
||
st = sys$qiow (0, p[s].channel, IO$_SENSEMODE, p[s].iosb, 0, 0,
|
||
0, 0, &lhost, 0, 0, 0);
|
||
if (QIO_FAILED)
|
||
return -1;
|
||
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
/* TWG gives us the information. */
|
||
st = sys$qiow (0, p[s].channel, IO$_GETSOCKNAME, p[s].iosb,
|
||
0, 0, name, namelen, 0, 0, 0, 0);
|
||
if (QIO_FAILED)
|
||
return -1;
|
||
|
||
return 0;
|
||
}
|
||
}
|
||
else
|
||
/* We don't handle any other domain yet. */
|
||
return -1;
|
||
}
|
||
|
||
/* Select routine. */
|
||
int
|
||
VMSselect (nfds, readfds, writefds, exceptfds, timeout)
|
||
int nfds;
|
||
fd_set *readfds, *writefds, *exceptfds;
|
||
struct timeval *timeout;
|
||
{
|
||
int timer, fd, alarm_set, total, end;
|
||
long mask, cluster;
|
||
struct descriptor termdesc;
|
||
static fd_set new_readfds, new_writefds, new_exceptfds;
|
||
|
||
FD_ZERO (&new_readfds);
|
||
FD_ZERO (&new_writefds);
|
||
FD_ZERO (&new_exceptfds);
|
||
total = 0;
|
||
|
||
/* Assign a terminal channel if we haven't already. */
|
||
if (terminal.chan == -1)
|
||
{
|
||
termdesc.size = 10;
|
||
termdesc.ptr = "SYS$INPUT:";
|
||
sys$assign (&termdesc, &terminal.chan, 0, 0);
|
||
}
|
||
alarm_set = 0;
|
||
if (timeout != NULL)
|
||
{
|
||
/* If a timeout is given then set the alarm. */
|
||
end = timeout->tv_sec;
|
||
if (timer != 0)
|
||
{
|
||
/* We need to reset the alarm if it didn't fire, but we set it. */
|
||
alarm_set = 1;
|
||
si_alarm (end);
|
||
}
|
||
}
|
||
else
|
||
end = 1;
|
||
|
||
do
|
||
{
|
||
if (exceptfds)
|
||
{
|
||
/* Nothing */ ;
|
||
}
|
||
|
||
if (writefds)
|
||
{
|
||
for (fd = 0; fd < nfds; fd++)
|
||
if (FD_ISSET (fd, writefds))
|
||
{
|
||
if (p[fd].connect_pending)
|
||
/* Nothing */ ;
|
||
else if ((p[fd].status == ACTIVE_CONNECTION)
|
||
|| (p[fd].status == PASSIVE_CONNECTION))
|
||
{
|
||
FD_SET (fd, &new_writefds);
|
||
total++;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (readfds)
|
||
{
|
||
/* True if data pending or an accept. */
|
||
for (fd = 3; fd < nfds; fd++)
|
||
if (FD_ISSET (fd, readfds) &&
|
||
((p[fd].fd_buff_size != -1) || (p[fd].accept_pending == 1)))
|
||
{
|
||
FD_SET (fd, &new_readfds);
|
||
total++;
|
||
}
|
||
}
|
||
|
||
if (total || (end == 0))
|
||
break;
|
||
|
||
/* Otherwise, wait on an event flag. It's possible that the wait can
|
||
be stopped by a spurious event flag being set -- i.e. one that's
|
||
got a status not normal. So we've got to be prepared to loop
|
||
around the wait until a valid reason happens. */
|
||
|
||
/* Set up the wait mask. */
|
||
cluster = 0;
|
||
mask = 0;
|
||
for (fd = 3; fd < nfds; fd++)
|
||
{
|
||
sys$clref (fd);
|
||
if (readfds)
|
||
if FD_ISSET
|
||
(fd, readfds) mask |= (1 << fd);
|
||
if (writefds)
|
||
if FD_ISSET
|
||
(fd, writefds) mask |= (1 << fd);
|
||
if (exceptfds)
|
||
if FD_ISSET
|
||
(fd, exceptfds) mask |= (1 << fd);
|
||
}
|
||
|
||
mask |= (1 << TIMER_EFN);
|
||
|
||
/* Clear it off just in case. */
|
||
sys$clref (TIMER_EFN);
|
||
|
||
/* Wait around. */
|
||
sys$wflor (cluster, mask);
|
||
|
||
mask = 0;
|
||
if (read_efn (TIMER_EFN))
|
||
{
|
||
errno = EINTR;
|
||
break;
|
||
}
|
||
} while (1);
|
||
/*NOTREACHED*/
|
||
|
||
/* Unset the alarm if we set it. */
|
||
if (alarm_set == 1)
|
||
alarm (0);
|
||
|
||
if (readfds)
|
||
*readfds = new_readfds;
|
||
|
||
if (writefds)
|
||
*writefds = new_writefds;
|
||
|
||
if (exceptfds)
|
||
*exceptfds = new_exceptfds;
|
||
|
||
return total;
|
||
}
|
||
|
||
/* Shutdown routine. */
|
||
VMSshutdown (s, how)
|
||
int s, how;
|
||
{
|
||
int st;
|
||
int ucx_how;
|
||
|
||
if (!tcp_make)
|
||
set_tcp_make ();
|
||
|
||
if (p[s].domain == AF_INET)
|
||
{
|
||
if (tcp_make == CMU)
|
||
{
|
||
/* For CMU we just close off. */
|
||
si_close (s);
|
||
return 0;
|
||
}
|
||
else if (tcp_make == UCX)
|
||
{
|
||
st = sys$qiow (0, p[s].channel, IO$_DEACCESS | IO$M_SHUTDOWN,
|
||
p[s].iosb, 0, 0, 0, 0, 0, how, 0, 0);
|
||
if (QIO_FAILED)
|
||
return -1;
|
||
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
/* TWG lets us do it. */
|
||
st = sys$qiow (0, p[s].channel, IO$_SHUTDOWN, p[s].iosb, 0, 0, how,
|
||
0, 0, 0, 0, 0);
|
||
if (QIO_FAILED)
|
||
return -1;
|
||
|
||
return 0;
|
||
}
|
||
}
|
||
else /* it wasn't a socket */
|
||
return -1;
|
||
}
|
||
|
||
/* */
|
||
|
||
/* The following routines are used by the above socket calls. */
|
||
|
||
/* hang_a_read sets up a read to be finished at some later time. */
|
||
hang_a_read (s)
|
||
int s;
|
||
{
|
||
extern int read_ast ();
|
||
int size, st;
|
||
|
||
/* Don't bother if we already did it. */
|
||
if (p[s].read_outstanding == 1)
|
||
return;
|
||
|
||
/* Have a read outstanding. */
|
||
p[s].read_outstanding = 1;
|
||
size = sizeof (p[s].from) + 4;
|
||
sys$clref (s);
|
||
|
||
/* Clear off the event flag just in case, and reset the buf size. */
|
||
p[s].fd_buff_size = -1;
|
||
if (p[s].domain == AF_INET)
|
||
{
|
||
if (tcp_make == CMU)
|
||
{
|
||
st = sys$qio (s, p[s].channel, TCP$RECEIVE, p[s].iosb, read_ast,
|
||
&p[s], p[s].fd_buff, BUF_SIZE, 0, 0, 0, 0);
|
||
if (QIO_ST_FAILED)
|
||
return -1;
|
||
}
|
||
else if (tcp_make == UCX)
|
||
{
|
||
|
||
p[s].rhost.length = sizeof (struct sockaddr_in);
|
||
p[s].rhost.code = 0;
|
||
p[s].rhost.dataptr = (char *) &p[s].from;
|
||
p[s].rhost.retlenptr = &p[s].fromdummy;
|
||
|
||
st = sys$qio (s, p[s].channel, IO$_READVBLK, p[s].iosb, read_ast,
|
||
&p[s], p[s].fd_buff, BUF_SIZE, &p[s].rhost, 0, 0, 0);
|
||
if (QIO_ST_FAILED)
|
||
return -1;
|
||
}
|
||
else
|
||
{
|
||
/* TWG */
|
||
st = sys$qio (s, p[s].channel, IO$_READVBLK, p[s].iosb, read_ast,
|
||
&p[s], p[s].fd_buff, BUF_SIZE, 0, &p[s].fromlen,
|
||
size, 0);
|
||
if (QIO_ST_FAILED)
|
||
return -1;
|
||
}
|
||
}
|
||
else
|
||
/* We don't handle any other domain yet. */
|
||
return -1;
|
||
}
|
||
|
||
/* hang_an_accept waits for a connection request to come in. */
|
||
hang_an_accept (s)
|
||
int s;
|
||
{
|
||
extern int accept_ast ();
|
||
int st;
|
||
|
||
/* Clear the event flag just in case. */
|
||
sys$clref (s);
|
||
|
||
/* Reset our flag & buf size. */
|
||
p[s].accept_pending = 0;
|
||
p[s].fd_buff_size = -1;
|
||
if (p[s].domain == AF_INET)
|
||
{
|
||
if (tcp_make == CMU)
|
||
{
|
||
st = sys$qio (s, p[s].channel, TCP$OPEN, p[s].iosb, accept_ast,
|
||
&p[s], 0, 0, ntohs (p[s].name.in.sin_port), 0, 0, 0);
|
||
if (QIO_ST_FAILED)
|
||
return -1;
|
||
}
|
||
else if (tcp_make == UCX)
|
||
{
|
||
struct descriptor inetdesc;
|
||
|
||
/* Assign channel for actual connection off listener. */
|
||
inetdesc.size = 3;
|
||
inetdesc.ptr = "BG:";
|
||
if (sys$assign (&inetdesc, &p[s].ucx_accept_chan, 0,
|
||
0) != SS$_NORMAL)
|
||
return -1;
|
||
|
||
/* UCX's accept returns remote host info and the channel for a new
|
||
socket to perform reads/writes on, so a sys$assign isn't
|
||
really necessary. */
|
||
p[s].rhost.length = sizeof (struct sockaddr_in);
|
||
p[s].rhost.dataptr = (char *) &p[s].from;
|
||
p[s].fromdummy = 0;
|
||
p[s].rhost.retlenptr = &p[s].fromdummy;
|
||
|
||
st = sys$qio (s, p[s].channel, IO$_ACCESS | IO$M_ACCEPT, p[s].iosb,
|
||
accept_ast, &p[s], 0, 0, &p[s].rhost,
|
||
&p[s].ucx_accept_chan, 0, 0);
|
||
if (QIO_ST_FAILED)
|
||
return -1;
|
||
}
|
||
else
|
||
{
|
||
st = sys$qio (s, p[s].channel, IO$_ACCEPT_WAIT, p[s].iosb,
|
||
accept_ast, &p[s], 0, 0, 0, 0, 0, 0);
|
||
if (QIO_ST_FAILED)
|
||
return -1;
|
||
}
|
||
}
|
||
else
|
||
/* We don't handle any other domain yet. */
|
||
return -1;
|
||
}
|
||
|
||
/* wait_efn just sets up a wait on either an event or the timer. */
|
||
wait_efn (s)
|
||
int s;
|
||
{
|
||
long mask, cluster;
|
||
|
||
cluster = 0;
|
||
sys$clref (TIMER_EFN);
|
||
mask = (1 << s) | (1 << TIMER_EFN);
|
||
sys$wflor (cluster, mask);
|
||
|
||
if (read_efn (TIMER_EFN))
|
||
{
|
||
errno = EINTR;
|
||
return -1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
/* read_ast is called by the system whenever a read is done. */
|
||
read_ast (p)
|
||
struct fd_entry *p;
|
||
{
|
||
int i, j;
|
||
unsigned char *v, *w;
|
||
|
||
/* Reset the outstanding flag. */
|
||
p->read_outstanding = 0;
|
||
if (p->iosb[0] == SS$_NORMAL)
|
||
{
|
||
/* Check no errors. */
|
||
p->fd_buff_size = p->iosb[1];
|
||
if (tcp_make == CMU)
|
||
{
|
||
/* fiddle for DGRMs */
|
||
if (p->type == SOCK_DGRAM)
|
||
p->fd_buff_size -= 12;
|
||
}
|
||
if (p->sig_req == 1)
|
||
gsignal (SIGIO);
|
||
}
|
||
else if (p->iosb[0] == SS$_CLEARED)
|
||
p->closed_by_remote = 1;
|
||
else if (tcp_make == UCX)
|
||
{
|
||
if (p->iosb[0] == SS$_LINKDISCON)
|
||
p->closed_by_remote = 1;
|
||
}
|
||
}
|
||
|
||
/* accept_ast is called whenever an incoming call is detected. */
|
||
accept_ast (p)
|
||
struct fd_entry *p;
|
||
{
|
||
if (p->iosb[0] == SS$_NORMAL)
|
||
p->accept_pending = 1;
|
||
else
|
||
/* If it failed set up another listen. */
|
||
listen (p->s, p[p->s].backlog);
|
||
}
|
||
|
||
/* connect_ast is called whenever an async connect is made. */
|
||
connect_ast (p)
|
||
struct fd_entry *p;
|
||
{
|
||
p->connect_pending = 0;
|
||
if ((p->connected = p->iosb[0]) == SS$_NORMAL)
|
||
{
|
||
/* We made the connection. */
|
||
p->status = ACTIVE_CONNECTION;
|
||
|
||
/* Be prepared to accept a msg. */
|
||
hang_a_read (p->s);
|
||
}
|
||
}
|
||
|
||
/* */
|
||
/* These routines handle stream I/O. */
|
||
|
||
/* si_close -- must close off any connection in progress. */
|
||
si_close (s)
|
||
int s;
|
||
{
|
||
if (!tcp_make)
|
||
set_tcp_make ();
|
||
|
||
if ((s < 0) || (s > 31))
|
||
return -1;
|
||
|
||
if (p[s].channel != 0)
|
||
{
|
||
/* Was it one of our descriptors? */
|
||
if (p[s].domain == AF_INET)
|
||
{
|
||
if (tcp_make == CMU)
|
||
sys$qiow (0, p[s].channel, TCP$CLOSE, p[s].iosb,
|
||
0, 0, 0, 0, 0, 0, 0, 0);
|
||
if (p[s].status != HANDED_OFF)
|
||
sys$dassgn (p[s].channel);
|
||
close (s);
|
||
free (p[s].fd_buff);
|
||
p_initialise (s);
|
||
}
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
/* Re-initialise data structure just in case. */
|
||
p[s].fd_buff_size = -1;
|
||
p[s].accept_pending = 0;
|
||
p[s].status = INITIALISED;
|
||
return close (s);
|
||
}
|
||
}
|
||
|
||
/* si_alarm -- insert a call to our own alarm function. */
|
||
si_alarm (i)
|
||
int i;
|
||
{
|
||
extern int pre_alarm ();
|
||
|
||
/* Make the call to pre_alarm instead of what the user wants;
|
||
pre_alarm will call his routine when it finishes. */
|
||
/* VAX needs this call each time! */
|
||
signal (SIGALRM, pre_alarm);
|
||
alarm (i);
|
||
}
|
||
|
||
/* pre_alarm -- gets called first on an alarm signal. */
|
||
pre_alarm ()
|
||
{
|
||
/* Come here first so we can set our timer event flag. */
|
||
sys$setef (TIMER_EFN);
|
||
(*alarm_function) ();
|
||
}
|
||
|
||
/* p_initialise - initialise our data array. */
|
||
p_initialise (s)
|
||
int s;
|
||
{
|
||
int j;
|
||
for (j = 0; j < 4; j++)
|
||
p[s].iosb[j] = 0;
|
||
p[s].channel = 0;
|
||
p[s].fd_buff_size = -1;
|
||
p[s].accept_pending = 0;
|
||
p[s].connect_pending = 0;
|
||
p[s].connected = 0;
|
||
p[s].fd_buff = NULL;
|
||
p[s].fd_leftover = NULL;
|
||
p[s].fptr = NULL;
|
||
p[s].s = s;
|
||
p[s].name.in.sin_port = 0;
|
||
p[s].masklen = 4;
|
||
for (j = 0; j < 16; j++)
|
||
p[s].mask[j] = 0xff;
|
||
p[s].need_header = 0;
|
||
p[s].status = INITIALISED;
|
||
p[s].read_outstanding = 0;
|
||
p[s].cmu_open = 0;
|
||
p[s].x25_listener = 0;
|
||
p[s].mother = s;
|
||
p[s].child = 0;
|
||
p[s].no_more_accepts = 0;
|
||
p[s].closed_by_remote = 0;
|
||
p[s].non_blocking = 0;
|
||
p[s].sig_req = 0;
|
||
sys$clref (s);
|
||
}
|
||
|
||
/* read_efn -- see whether an event flag is set. */
|
||
read_efn (i)
|
||
int i;
|
||
{
|
||
int j;
|
||
sys$readef (i, &j);
|
||
j &= (1 << i);
|
||
|
||
return j;
|
||
}
|
||
|
||
static
|
||
set_tcp_make ()
|
||
{
|
||
struct descriptor inetdesc;
|
||
int channel;
|
||
/* first try CMU */
|
||
inetdesc.size = 3;
|
||
inetdesc.ptr = "IP:";
|
||
if (sys$assign (&inetdesc, &channel, 0, 0) == SS$_NORMAL)
|
||
{
|
||
sys$dassgn (channel);
|
||
tcp_make = CMU;
|
||
return;
|
||
}
|
||
|
||
/* next try TWG */
|
||
inetdesc.size = 7;
|
||
inetdesc.ptr = "_INET0:";
|
||
if (sys$assign (&inetdesc, &channel, 0, 0) == SS$_NORMAL)
|
||
{
|
||
sys$dassgn (channel);
|
||
tcp_make = WG;
|
||
return;
|
||
}
|
||
|
||
/* next try UCX */
|
||
inetdesc.size = 4;
|
||
inetdesc.ptr = "BG0:";
|
||
if (sys$assign (&inetdesc, &channel, 0, 0) == SS$_NORMAL)
|
||
{
|
||
sys$dassgn (channel);
|
||
tcp_make = UCX;
|
||
return;
|
||
}
|
||
|
||
/* nothing there oh dear!*/
|
||
tcp_make = NONE;
|
||
return;
|
||
}
|
||
|
||
static char *
|
||
getdevicename (channel)
|
||
unsigned short int channel;
|
||
{
|
||
int st;
|
||
struct
|
||
{
|
||
struct itemlist id;
|
||
int eol;
|
||
} itmlst;
|
||
static char name[64];
|
||
short int lgth;
|
||
|
||
name[0] = '\0';
|
||
itmlst.id.code = DVI$_DEVNAM;
|
||
itmlst.id.length = 64;
|
||
itmlst.id.dataptr = name;
|
||
itmlst.id.retlenptr = &lgth;
|
||
itmlst.eol = 0;
|
||
st = sys$getdvi (0, channel, 0, &itmlst, 0, 0, 0, 0);
|
||
if (QIO_ST_FAILED)
|
||
fprintf (stderr, "error getting device name %d\n", st);
|
||
|
||
return (name);
|
||
}
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie.vms]fd.h
|
||
$DECK
|
||
#ifndef _VMS_FD
|
||
#define _VMS_FD
|
||
|
||
typedef struct fd_set
|
||
{
|
||
int fds_bits[1];
|
||
} fd_set;
|
||
|
||
#define FD_SETSIZE (sizeof (fd_set) * 8)
|
||
#define FD_SET(f,s) ((s)->fds_bits[0] |= (1 << (f)))
|
||
#define FD_CLR(f,s) ((s)->fds_bits[0] &= ~(1 << (f)))
|
||
#define FD_ISSET(f,s) ((s)->fds_bits[0] & (1 << (f)))
|
||
#define FD_ZERO(s) ((s)->fds_bits[0] = 0)
|
||
|
||
#endif /* _VMS_FD */
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie.vms]in.h
|
||
$DECK
|
||
/* netinet/in.h */
|
||
struct in_addr
|
||
{
|
||
union
|
||
{
|
||
struct
|
||
{
|
||
unsigned char s_b1, s_b2, s_b3, s_b4;
|
||
} S_un_b;
|
||
struct
|
||
{
|
||
unsigned short s_w1, s_w2;
|
||
} S_un_w;
|
||
unsigned long S_addr;
|
||
} S_un;
|
||
#define s_addr S_un.S_addr
|
||
#define s_host S_un.S_un_b.s_b2
|
||
#define s_net S_un.S_un_b.s_b1
|
||
#define s_imp S_un.S_un_w.s_w2
|
||
#define s_impno S_un.S_un_b.s_b4
|
||
#define s_lh S_un.S_un_b.s_b3
|
||
};
|
||
|
||
#define INADDR_ANY 0x00000000
|
||
#define INADDR_BROADCAST 0xffffffff
|
||
#define INADDR_LOOPBACK 0x7f000001
|
||
|
||
struct sockaddr_in
|
||
{
|
||
short sin_family;
|
||
unsigned short sin_port;
|
||
struct in_addr sin_addr;
|
||
char sin_zero[8];
|
||
};
|
||
|
||
#define ntohl(x) (( (((unsigned long) x) >> 24)& 0x000000ff ) |\
|
||
( (((unsigned long) x) >> 8) & 0x0000ff00 ) |\
|
||
( (((unsigned long) x) << 8) & 0x00ff0000 ) |\
|
||
( (((unsigned long) x) << 24)& 0xff000000 ))
|
||
#define ntohs(x) (( (((unsigned short) x) >> 8) |\
|
||
( (((unsigned short) x) << 8)) & 0xffff ))
|
||
#define htonl(x) (( (((unsigned long) x) >> 24)& 0x000000ff ) |\
|
||
( (((unsigned long) x) >> 8) & 0x0000ff00 ) |\
|
||
( (((unsigned long) x) << 8) & 0x00ff0000 ) |\
|
||
( (((unsigned long) x) << 24)& 0xff000000 ))
|
||
#define htons(x) (( (((unsigned short) x) >> 8) |\
|
||
( (((unsigned short) x) << 8)) & 0xffff ))
|
||
|
||
#define IPPORT_RESERVED 1024
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie.vms]pseudos.h
|
||
$DECK
|
||
/* These are so we don't end up using the MultiNet versions. */
|
||
#define socket VMSsocket
|
||
#define bind VMSbind
|
||
#define connect VMSconnect
|
||
#define listen VMSlisten
|
||
#define accept VMSaccept
|
||
#define select VMSselect
|
||
#define recv VMSrecv
|
||
#define recvfrom VMSrecvfrom
|
||
#define send VMSsend
|
||
#define sendto VMSsendto
|
||
#define getsockname VMSgetsockname
|
||
#define shutdown VMSshutdown
|
||
#define getsockopt VMSgetsockopt
|
||
#define setsockopt VMSsetsockopt
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie.vms]signal.h
|
||
$DECK
|
||
/* signal.h */
|
||
#define SIGURG 16
|
||
#define SIGTSTP 18
|
||
#define SIGCHLD 20
|
||
#define SIGIO 23
|
||
#define sigmask(m) (1 << ((m)-1))
|
||
|
||
#ifndef __GNUC__
|
||
# include <sys$library:signal.h>
|
||
#else /* Gnu C */
|
||
# include <gnu_cc_include:[000000]signal.h>
|
||
#endif /* not Gnu C */
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie.vms]socket.h
|
||
$DECK
|
||
/* sys/socket.h */
|
||
#define SOCK_STREAM 1
|
||
#define SOCK_DGRAM 2
|
||
|
||
#define SO_DEBUG 0x01
|
||
#define SO_ACCEPTCONN 0x02
|
||
#define SO_REUSEADDR 0x04
|
||
#define SO_KEEPALIVE 0x08
|
||
#define SO_LINGER 0x80
|
||
#define SO_DONTLINGER (~SO_LINGER)
|
||
|
||
#define AF_UNSPEC 0
|
||
#define AF_ERROR 0
|
||
#define AF_INET 2
|
||
#define AF_CCITT 10
|
||
#define AF_X25 10
|
||
|
||
struct sockaddr
|
||
{
|
||
unsigned short sa_family;
|
||
char sa_data[14];
|
||
};
|
||
|
||
#define SOL_SOCKET 0xffff
|
||
|
||
#define MSG_OOB 1
|
||
#define MSG_PEEK 2
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie.vms]time.h
|
||
$DECK
|
||
#ifndef __PKTIME
|
||
#define __PKTIME
|
||
|
||
struct timeval
|
||
{
|
||
long tv_sec;
|
||
long tv_usec;
|
||
};
|
||
|
||
struct timezone
|
||
{
|
||
int tz_minuteswest;
|
||
int tz_dsttime;
|
||
};
|
||
|
||
struct itimerval
|
||
{
|
||
struct timeval it_interval;
|
||
struct timeval it_value;
|
||
};
|
||
|
||
#define ITIMER_REAL 0
|
||
#define timerclear(x) (x)->tv_sec = (x)->tv_usec = 0
|
||
|
||
#ifndef __GNUC__
|
||
# include <sys$library:time.h>
|
||
#else /* not Gnu C */
|
||
# include <gnu_cc_include:[000000]time.h>
|
||
#endif /* Gnu C */
|
||
|
||
#endif /* __PKTIME */
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie.vms]types.h
|
||
$DECK
|
||
/* sys/types.h */
|
||
#ifndef _types_
|
||
#define _types_
|
||
|
||
#ifndef __GNUC__
|
||
# include <sys$library:stddef.h>
|
||
#endif /* not Gnu C */
|
||
|
||
typedef unsigned char u_char;
|
||
typedef unsigned short u_short;
|
||
typedef unsigned int u_int;
|
||
typedef unsigned long u_long;
|
||
|
||
typedef long daddr_t;
|
||
typedef char *caddr_t;
|
||
|
||
#include <sys$library:types.h>
|
||
|
||
typedef unsigned short ino_t;
|
||
typedef char *dev_t;
|
||
typedef unsigned int off_t;
|
||
typedef long key_t;
|
||
|
||
#include "[.vms]fd.h"
|
||
|
||
#endif /* _types */
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie.vms]network.h
|
||
$DECK
|
||
/* Miscellaneous things for the networking library. */
|
||
|
||
/* Actually an itemlist_3, but can be used for itemlist_2's. */
|
||
struct itemlist
|
||
{
|
||
short length;
|
||
short code;
|
||
char *dataptr;
|
||
short *retlenptr;
|
||
};
|
||
|
||
union socket_addr
|
||
{
|
||
struct sockaddr_in in;
|
||
};
|
||
|
||
#define TCP$SEND (IO$_WRITEVBLK)
|
||
#define TCP$RECEIVE (IO$_READVBLK)
|
||
#define TCP$OPEN (IO$_CREATE)
|
||
#define TCP$CLOSE (IO$_DELETE)
|
||
#define TCP$ABORT (IO$_DEACCESS)
|
||
#define TCP$STATUS (IO$_ACPCONTROL)
|
||
#define TCP$INFO (IO$_MODIFY)
|
||
#define GTHST (IO$_SKIPFILE)
|
||
|
||
#define IO$_SEND (IO$_WRITEVBLK)
|
||
#define IO$_RECEIVE (IO$_READVBLK)
|
||
#ifndef IO$S_FCODE
|
||
#define IO$S_FCODE 0x0006
|
||
#endif
|
||
#define IO$_SOCKET (IO$_ACCESS | (0 << IO$S_FCODE))
|
||
#define IO$_BIND (IO$_ACCESS | (1 << IO$S_FCODE))
|
||
#define IO$_LISTEN (IO$_ACCESS | (2 << IO$S_FCODE))
|
||
#define IO$_ACCEPT (IO$_ACCESS | (3 << IO$S_FCODE))
|
||
#define IO$_CONNECT (IO$_ACCESS | (4 << IO$S_FCODE))
|
||
#define IO$_SETSOCKOPT (IO$_ACCESS | (5 << IO$S_FCODE))
|
||
#define IO$_GETSOCKOPT (IO$_ACCESS | (6 << IO$S_FCODE))
|
||
#define IO$_IOCTL (IO$_ACCESS | (8 << IO$S_FCODE))
|
||
#define IO$_ACCEPT_WAIT (IO$_ACCESS | (10 << IO$S_FCODE))
|
||
#define IO$_NETWORK_PTY (IO$_ACCESS | (11 << IO$S_FCODE))
|
||
#define IO$_SHUTDOWN (IO$_ACCESS | (12 << IO$S_FCODE))
|
||
#define IO$_GETSOCKNAME (IO$_ACCESS | (13 << IO$S_FCODE))
|
||
#define SETCHAR_HANDOFF (1<<2)
|
||
|
||
#define NFB$C_DECLNAME 0x15
|
||
|
||
#define TIMER_EFN 1
|
||
#define TERM_EFN 2
|
||
#define BUF_SIZE 2000
|
||
|
||
#define INITIALISED 0
|
||
#define ACTIVE_CONNECTION 1
|
||
#define PASSIVE_CONNECTION 2
|
||
#define LISTENING 3
|
||
#define HANDED_OFF 4
|
||
|
||
static struct fd_entry
|
||
{
|
||
unsigned short int channel; /* vms channel assigned to this socket */
|
||
unsigned short int iosb[4]; /* returned status block */
|
||
int fd_buff_size; /* number of chrs in buffer still to be read */
|
||
int accept_pending; /* a call is waiting to be accepted */
|
||
int connect_pending; /* a connect is outstanding*/
|
||
int connected; /* this descriptor is connected */
|
||
unsigned char *fd_buff; /* pointer to buffer dyn assigned */
|
||
unsigned char *fd_leftover; /* pointer to any chrs still to be read */
|
||
FILE *fptr; /* we need to assgn a file ptr for stream io */
|
||
int s; /* socket number - needed in the ast's */
|
||
int namelen; /* our socket address name */
|
||
union socket_addr name;
|
||
short int fromdummy; /* wg - accept wants an int - recvfrom wants a short!!*/
|
||
short int fromlen; /* the from socket address name */
|
||
union socket_addr from;
|
||
int tolen; /* wg - sendto wants an int*/
|
||
union socket_addr to; /* the to socket address name */
|
||
int passive; /* still needed because of x25 close ambig */
|
||
int backlog; /* backlog - not handled well! */
|
||
int domain; /* domain of socket AF_INET or AF_X25 */
|
||
int type; /* type of socket stream or datagram */
|
||
int protocol; /* protocol of socket - ignored */
|
||
int mbx_channel; /* mailbox channel - needed for x25 */
|
||
unsigned char mbx_buff[255]; /* mailbox buffer */
|
||
unsigned short int miosb[4]; /* mailbox status block */
|
||
int ncb_size; /* x25 connection information */
|
||
unsigned char ncb[128];
|
||
unsigned char masklen; /* x25 user data mask */
|
||
unsigned char mask[16];
|
||
int need_header; /* x25 header field gives data status if req*/
|
||
int send_type; /* x25 data packet type eg more bit set etc */
|
||
int status; /* status of socket */
|
||
int closed_by_remote; /* flag for remote dropouts */
|
||
int read_outstanding; /* flag so we don't hang two reads */
|
||
int cmu_open; /* flag to say whether a cmu open was hung */
|
||
int x25_listener; /* flag to say we are an x25 listener */
|
||
int oob_type; /* handles interrupt messages */
|
||
int mother; /* mother socket for X25 accepts */
|
||
int child; /* child socket for X25 accepts */
|
||
int no_more_accepts; /* don't accept anymore calls */
|
||
char int_data; /* interrupt data - only 1 char supported */
|
||
int non_blocking; /* don't block on a read if no data */
|
||
int sig_req; /* generate SIGIO on data ready */
|
||
struct itemlist rhost; /* descriptor pointing to "p[].from" info for UCX */
|
||
unsigned short ucx_accept_chan; /* Channel returned by a UCX accept via hang_an_accept */
|
||
} p[32];
|
||
|
||
/* So we can handle select on terminal input. */
|
||
static struct term_entry
|
||
{
|
||
int chan;
|
||
short int iosb[4];
|
||
short int char_available;
|
||
short int read_outstanding;
|
||
char c[1];
|
||
} terminal =
|
||
|
||
{
|
||
-1, 0, 0, 0, 0, 0, 0
|
||
};
|
||
|
||
#define CMU 1
|
||
#define WG 2
|
||
#define NONE 3
|
||
#define TGV 4
|
||
#define UCX 5
|
||
static int tcp_make = 0;
|
||
|
||
struct descriptor
|
||
{
|
||
int size;
|
||
char *ptr;
|
||
};
|
||
|
||
/* Initialize certain things 1st time thru. */
|
||
static int p_initialised = 0;
|
||
|
||
/* A routine to point SIGALRM and SIGURG at. */
|
||
static int
|
||
si_dummy ()
|
||
{
|
||
}
|
||
static int (*alarm_function) () = si_dummy;
|
||
static int (*sigurg_function) () = si_dummy;
|
||
|
||
FILE *fdopen ();
|
||
static set_tcp_make ();
|
||
static char *getdevicename ();
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie.vms]multi.opt
|
||
$DECK
|
||
sys$library:vaxcrtl.exe/share
|
||
multinet:multinet_socket_library.exe/share
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie.vms]ucx.opt
|
||
$DECK
|
||
sys$library:vaxcrtl.exe/share
|
||
sys$library:ucx$ipc/lib
|
||
$EOD
|
||
$!
|
||
$CREATE [.archie.vms]woll.opt
|
||
$DECK
|
||
sys$library:vaxcrtl.exe/share
|
||
twg$tcp:[netdist.lib]twglib.olb/lib
|
||
$EOD
|
||
$ write sys$output "Ok, now enter the ARCHIE directory, look at MAKE.COM, then type @MAKE ."
|