diff --git a/release/A/Release-Notes-3.5 b/release/A/Release-Notes-3.5 new file mode 100644 index 0000000..976f53d --- /dev/null +++ b/release/A/Release-Notes-3.5 @@ -0,0 +1,149 @@ + + + + + Archie 3.5 Beta + --------------- + + + +Patch level 3: +============== + + - Support for ls-lR.gz files + - New WWW front-end to the Archie database. + - Improved search speed. + - ISO-Latin-1 support for searches. + - bug fixes as well.. + + +Some notes on how to install or take advantage of the new features. + + +ls-lR.gz +-------- + You must have gzip and gunzip on your system. + You need to edit the files + + ~archie/etc/arretdefs.cf + + modify the line anonftp:unix_bsd:image:.Z:anonymous:::-R:*?:ls-lR + to anonftp:unix_bsd:image:.gz,.Z:anonymous:::-R:*?:ls-lR + + you need to modify the file + + ~archie/etc/options.cf (read the instructions in that file) + + +WWW front-end +------------- + + Thw files related to the WWW front-end are in ~archie/cgi + + You will find in ~archie/cgi/bin + a perl script (archie) and a binary program (cgi-client). + + The top part of the perl script will tell you what needs to + be setup. + + In ~archie/cgi/html are the different gif files and search forms. + They are not in their final stage ... so do not hesitate to + give us your comments. + + The files archie and archie-adv in that directory should + be modified to indicate where the perl script is located. + + We recommend that a uniform url be used for archie so that + Archie users will easily find the search page. + + http://archie.foo.bar/archie and + http://archie.foo.bar/archie-adv + + + +New in this release: +==================== + +Here are the major added components to the system with some +of the key points involved in each one of them. + + +- Support for a new database module (webindex) + - retrieval of HTML pages through http protocol + - Keyword extraction + - Controlled crawling of the WWW + - Site by site basis + - Content extraction + - configurable stoplist (keyword exclusion) + +- New database structure + - More reliable structure. + + +- New search engine + - Based on a paged tree structured index + - Faster searches + - Less memory required + - More disk space for construction of the index + +- New search interface + - cgi-bin compliant interface + + +- A better domain filter for anonftp + - results can be pre-configured to return in a certain order + (e.g. ftp sites close to the server first) + - configurable on a server basis + + + +Fixed bugs +========== + + +- the ``-t'' switch on arcontrol creates the new files and work files + in the specified temp directory and not in ~archie/db/tmp + + +- Lock files are now created in ~archie/db/locks + +- host_manage can handle multiple preferred hostsnames + + + + +Currently working on: +===================== + +- Rewrite of the cgi-bin front-end to be more flexible. + +- Archie Help page + +- Regular Expressions with the new search engine. + +- New set of manpages and documentation. + +- Additional type of searches + + + + + +Currently testing: +================== + +- dirsrv with the new database technology. + + + + +Known Problems: +=============== + +- arexchange of webindex will not fully functional + it will not transfer .excerpt files. We still need to experiment + with indexing of the Web and see what is involved with + exchanges of data. + + + diff --git a/release/A/Version b/release/A/Version new file mode 100644 index 0000000..b9bfc26 --- /dev/null +++ b/release/A/Version @@ -0,0 +1 @@ +Version 3.5, Patch Level 4 diff --git a/release/A/config/Makefile b/release/A/config/Makefile new file mode 100644 index 0000000..cc10dc3 --- /dev/null +++ b/release/A/config/Makefile @@ -0,0 +1,128 @@ +# archie Version 3.5-beta +# Bunyip Information Systems, 1994 +# $Id: Makefile,v 1.10 1995/03/17 13:50:36 pedro Exp $ +# +# This is the configuration Makefile for the archie V 3.5 distribution +# +# Change the following 2 definitions if you don't like the defaults MAKE +# SURE that you have allocated the archie user codes before running this +# Makefile The name of the archie administrative code. You might want to +# create an archie group as well +# +# YOU MUST RUN THIS MAKEFILE AS SUPERUSER +# + +ARCHUSER=archie +ARCHGRP =archie + +# The place for the manpages describing the binaries + +MANEXT=n +MAN=../man + +#MAN5EXT=$(MANEXT) +MAN5EXT=5 +MAN5=$(MAN)/man${MAN5EXT} + +# Default permissions for archie binaries + +AR_PERMS=711 +ARS_PERMS=755 + +all: su links manpages owners archieb pfs links + + +su: + @echo "Making sure you're superuser" + @id=`id | sed 's/(.*$$//' | sed 's/^.*=//'`; \ + echo "Your uid is $$id"; \ + if [ "$$id" -ne "0" ]; then \ + echo "You must be running as superuser to configure archie"; \ + exit 2;\ + fi + +owners: + @echo Changing ownership to the archie user: $(ARCHUSER) + (cd ..; chown -R $(ARCHUSER) *; chgrp -R $(ARCHGRP) *;\ + chown $(ARCHUSER) . ; chgrp $(ARCHGRP) .; \ + chown $(ARCHUSER) .*; chgrp $(ARCHGRP) .*; chmod 755 .) + +archieb: + @echo Copying the shell and perl scripts into the bin directory + (cd ../scripts; tar cf - . | gzip > /tmp/scripts.tgz ; cd ../bin ;\ + ../scripts/untar /tmp/scripts.tgz) + @echo Setting permissions for binaries + for i in `find ../bin -type f -print | grep -v CVS | \ + sed 's?../bin/??g'`; do\ + chmod $(AR_PERMS) ../bin/$$i;\ + done + @echo Setting permissions for scripts + cd ../bin; /bin/file ./* | egrep -v '(demand|link|directory)' | \ + sed 's?:.*$$??' | xargs -t chmod $(ARS_PERMS) + @echo Setting permissions for logs + chmod 662 ../logs/email.log + @echo Setting permissions for tmp directory + chmod 1777 ../db/tmp ../tmp + @echo Taking care of the pager + cp ../bin/less* ../pager/bin + chmod 555 ../pager/bin/less* + @echo Setting permissions for telnet client + chown root ../bin/telnet-client + chmod 111 ../bin/telnet-client + chmod u+s ../bin/telnet-client + chmod 755 ../bin ../etc ../logs + chmod 644 ../etc/* + @echo Setting permissions for cgi progs + chmod 755 ../cgi ../cgi/* + chmod 644 ../cgi/html/* + chmod 755 ../cgi/bin/archie.cgi + chmod 755 ../cgi/bin/cgi-client + chmod u+s ../cgi/bin/cgi-client + @echo Setting permissions for databases + chmod o+rx ../db ../db/* + +manpages: + -mkdir $(MAN) && chmod 755 $(MAN) + -mkdir $(MAN)/man$(MANEXT) && chmod 755 $(MAN)/man$(MANEXT) + -mkdir $(MAN5) && chmod 755 $(MAN5) + for i in `find ../manpages/*.n -type f -print | grep -v CVS |\ + sed 's?../manpages/??g' | sed 's/\..$$//g'`; do\ + cp ../manpages/$$i.n $(MAN)/man$(MANEXT)/$$i.$(MANEXT);\ + chmod 644 $(MAN)/man$(MANEXT)/$$i.$(MANEXT);\ + if [ -f /usr/ucb/echo ] ; then /usr/ucb/echo -n "." ; \ + else echo -n "." ; fi \ + done + @echo "" + for i in `find ../manpages/*.5 -type f -print | grep -v CVS |\ + sed 's?../manpages/??g' | sed 's/\..$$//g'`; do\ + cp ../manpages/$$i.5 $(MAN5)/$$i.$(MAN5EXT);\ + chmod 644 $(MAN5)/$$i.$(MAN5EXT);\ + if [ -f /usr/ucb/echo ] ; then /usr/ucb/echo -n "." ; \ + else echo -n "." ; fi \ + done + @echo "" + @echo "Done"; + +pfs: + @echo "Taking care of things in /pfs" + find ../pfs -type f -print | xargs -t chmod 644 + find ../pfs -type d -print | xargs -t chmod 755 + find ../pfs/bin -type f -print | xargs -t chmod 755 + chown root ../pfs/bin/pstart + chmod gu+s ../pfs/bin/pstart + +links: + @echo "Creating /pfs link" + -rm -f /pfs + ln -s `pwd | sed 's?/config??'`/pfs /pfs + @echo "Creating other links" + -cd .. ; rm -f bin/-telnet-client bin/arexchange bin/arretrieve + cd ../bin; ln -s telnet-client ./-telnet-client; \ + ln -s arserver arexchange; \ + ln -s arserver arretrieve; \ + ln -s update_anonftp update_webindex + + + + + diff --git a/release/A/etc/ardomains.cf b/release/A/etc/ardomains.cf new file mode 100644 index 0000000..c33f9f3 --- /dev/null +++ b/release/A/etc/ardomains.cf @@ -0,0 +1,18 @@ +# +westeurope1 de:ie:pt:es:uk:at:fr:it:be:nl +westeurope2 ch:cy:gr:li:lu:tr +westeurope westeurope1:westeurope2 Western Europe +easteurope bg:cs:cz:hr:hu:pl:ro:sk:si Eastern Europe +scandinavia no:dk:se:fi:ee:is Scandinavia +europe westeurope:easteurope:scandinavia Europe +usa edu:com:mil:gov:us:org:net United States +northamerica usa:ca:mx North America +southamerica ar:bo:br:cl:co:cr:cu:ec:pe:ve South American +centralamerica sv:gt:hn Central America +asia kr:hk:sg:jp:cn:my:tw:in Asia +mideast eg:.il:kw:sa Middle East +africa za Africa +anzac au:nz OZ & New Zealand +world1 europe:scandinavia:northamerica +world2 centralamerica:southamerica:mideast:africa:anzac:as +world world1:world2 The World diff --git a/release/A/etc/motd b/release/A/etc/motd new file mode 100644 index 0000000..8f01bbd --- /dev/null +++ b/release/A/etc/motd @@ -0,0 +1,3 @@ + + Welcome to Archie! + Vers 3.3 diff --git a/release/A/etc/serverlist b/release/A/etc/serverlist new file mode 100644 index 0000000..7666698 --- /dev/null +++ b/release/A/etc/serverlist @@ -0,0 +1,45 @@ +--------------------< List of active archie servers >-------------------- + + Last Update: Jun 21 1996 + + archie.au 139.130.23.2 Australia + archie.univie.ac.at 131.130.1.23 Austria + archie.belnet.be 193.190.248.18 Belgium + archie.bunyip.com 192.77.55.2 Canada + archie.cs.mcgill.ca 132.206.51.250 Canada + archie.funet.fi 128.214.6.102 Finland + archie.univ-rennes1.fr 129.20.254.2 France + archie.th-darmstadt.de 130.83.22.1 Germany + archie.ac.il 132.65.208.15 Israel + archie.unipi.it 131.114.21.10 Italy + archie.wide.ad.jp 133.4.3.6 Japan + archie.hana.nm.kr 128.134.1.1 Korea + archie.kornet.nm.kr 168.126.63.10 Korea + archie.sogang.ac.kr 163.239.1.11 Korea + archie.nz 140.200.128.13 New Zealand + archie.uninett.no 128.39.2.20 Norway + archie.icm.edu.pl 148.81.209.5 Poland + archie.rediris.es 130.206.1.5 Spain + archie.luth.se 130.240.12.23 Sweden + archie.switch.ch 130.59.1.40 Switzerland + archie.switch.ch 130.59.10.40 Switzerland + archie.ncu.edu.tw 192.83.166.12 Taiwan + archie.doc.ic.ac.uk 146.169.16.11 UK + archie.doc.ic.ac.uk 146.169.17.5 UK + archie.doc.ic.ac.uk 146.169.2.10 UK + archie.doc.ic.ac.uk 146.169.32.5 UK + archie.doc.ic.ac.uk 146.169.33.5 UK + archie.doc.ic.ac.uk 146.169.43.1 UK + archie.doc.ic.ac.uk 155.198.1.40 UK + archie.doc.ic.ac.uk 155.198.191.4 UK + archie.hensa.ac.uk 129.12.200.130 UK + archie.sura.net 192.239.16.130 USA (MD) + archie.unl.edu 129.93.1.14 USA (NE) + archie.internic.net 192.20.239.132 USA (NJ) + archie.internic.net 198.49.45.10 USA (NJ) + archie.internic.net 204.179.186.65 USA (NJ) + archie.rutgers.edu 128.6.21.13 USA (NJ) + archie.ans.net 147.225.1.10 USA (NY) + + +-------------------------------------------------------------------------- diff --git a/release/base/Archierc b/release/base/Archierc new file mode 100644 index 0000000..4da7236 --- /dev/null +++ b/release/base/Archierc @@ -0,0 +1,22 @@ +# sample .archierc file. +# +# This file contains customization variables for the +# bunyip telnet archie client. +# + +set prompt "archie> " +set server localhost +#set pager_path bin/less +set pager_opts "" +set pager_help_opts "" +set search sub +set mail_service archiemail +set help_dir help/english +set servers_file etc/serverlist +set whatis_file etc/whatis +set man_ascii_file etc/manpage.ascii +set man_roff_file etc/manpage.roff +#set tmpdir db/tmp +set maxhits 25 +set search exact +set sortby time diff --git a/release/base/Manifest b/release/base/Manifest new file mode 100644 index 0000000..7800bd3 --- /dev/null +++ b/release/base/Manifest @@ -0,0 +1,303 @@ +drwxr-s--- . +-rw-r----- ./Archierc +-rw-r----- ./Manifest +-rw-r----- ./Release-Notes-3.5 +-rw-r----- ./Version +drwxr-s--- ./bin +-rwxr-x--- ./bin/arcontrol +-rwxr-x--- ./bin/ardomains +-rwxr-x--- ./bin/arserver +-rwxr-x--- ./bin/convert_hostdb +-rwxr-x--- ./bin/db_build +-rwxr-x--- ./bin/db_check +-rwxr-x--- ./bin/db_dump +-rwxr-x--- ./bin/db_reorder +-rwxr-x--- ./bin/db_siteidx +-rwxr-x--- ./bin/db_stats +-rwxr-x--- ./bin/delete_anonftp +-rwxr-x--- ./bin/delete_webindex +-rwxr-x--- ./bin/email-client +-rwxr-x--- ./bin/extern_urls +-rwxr-x--- ./bin/fix_start_db +-rwxr-x--- ./bin/host_manage +-rwxr-x--- ./bin/insert_anonftp +-rwxr-x--- ./bin/insert_webindex +-rwxr-x--- ./bin/less +-rwxr-x--- ./bin/net_anonftp +-rwxr-x--- ./bin/net_webindex +-rwxr-x--- ./bin/parse_anonftp +-rwxr-x--- ./bin/parse_anonftp_novell +-rwxr-x--- ./bin/parse_anonftp_unix_bsd +-rwxr-x--- ./bin/parse_anonftp_vms_std +-rwxr-x--- ./bin/parse_webindex +-rwxr-x--- ./bin/partial_webindex +-rwxr-x--- ./bin/retrieve_anonftp +-rwxr-x--- ./bin/retrieve_webindex +-rwxr-x--- ./bin/split_file +-rwxr-x--- ./bin/telnet-client +-rwxr-x--- ./bin/update_anonftp +-rwxr-x--- ./bin/weaseld +drwxr-s--- ./cgi +drwxr-s--- ./cgi/bin +-rw-r----- ./cgi/bin/archie.cgi +-rw-r----- ./cgi/bin/cgi-client +drwxr-s--- ./cgi/html +-rw-r----- ./cgi/html/archie-adv.html +-rw-r----- ./cgi/html/archie-help.html +-rw-r----- ./cgi/html/archie.html +-rw-r----- ./cgi/html/query.gif +-rw-r----- ./cgi/html/results.gif +drwxr-s--- ./config +-rw-r----- ./config/Makefile +drwxr-s--- ./contrib +-rw-r----- ./contrib/README +-rw-r----- ./contrib/archie.el +-rw-r----- ./contrib/archie.zip +-rw-r----- ./contrib/c-archie-1.3.2-vms.com +-rw-r----- ./contrib/c-archie-1.4.1.tar.gz +-rw-r----- ./contrib/less-177-for-archie.tar.gz +-rw-r----- ./contrib/mac-archie-client-09.hqx +-rw-r----- ./contrib/perl-archie-3.8.tar.gz +-rw-r----- ./contrib/xarchie-2.0.8.tar.gz +drwxr-s--- ./db +drwxr-s--- ./db/anonftp_db +drwxr-s--- ./db/anonftp_db/start_db +drwxr-s--- ./db/host_db +-rw-r----- ./db/host_db/domain-db.dir +-rw-r----- ./db/host_db/domain-db.pag +-rw-r----- ./db/host_db/host-db.dir +-rw-r----- ./db/host_db/host-db.pag +-rw-r----- ./db/host_db/hostaux-db.dir +-rw-r----- ./db/host_db/hostaux-db.pag +-rw-r----- ./db/host_db/hostbyaddr.dir +-rw-r----- ./db/host_db/hostbyaddr.pag +drwxr-s--- ./db/locks +drwxr-s--- ./db/tmp +drwxr-s--- ./db/webindex_db +drwxr-s--- ./db/webindex_db/start_db +drwxr-s--- ./doc +-rw-r----- ./doc/manual-3.5.ps.gz +drwxr-s--- ./etc +-rw-r----- ./etc/ardomains.cf +-rw-r----- ./etc/arretdefs.cf +-rw-r----- ./etc/arretrieve.cf +-rw-r----- ./etc/arretrieve.cf~ +-rw-r----- ./etc/arupdate.cf +-rw-r----- ./etc/catalogs.cf +-rw-r----- ./etc/domain.order +-rw-r----- ./etc/email.help +-rw-r----- ./etc/find_files.cf +-rw-r----- ./etc/hm_db.cf +-rw-r----- ./etc/inform_web +-rw-r----- ./etc/manpage.ascii +-rw-r----- ./etc/manpage.roff +-rw-r----- ./etc/motd +-rw-r----- ./etc/options.cf +-rw-r----- ./etc/resolv.conf +-rw-r----- ./etc/serverlist +-rw-r----- ./etc/sites.glist +-rw-r----- ./etc/sites.update +-rw-r----- ./etc/stoplist +-rw-r----- ./etc/termcap +-rw-r----- ./etc/whatis +drwxr-s--- ./help +drwxr-s--- ./help/english +-rw-r----- ./help/english/= +drwxr-s--- ./help/english/about +-rw-r----- ./help/english/about/= +drwxr-s--- ./help/english/bugs +-rw-r----- ./help/english/bugs/= +drwxr-s--- ./help/english/bye +-rw-r----- ./help/english/bye/= +drwxr-s--- ./help/english/compress +-rw-r----- ./help/english/compress/= +drwxr-s--- ./help/english/domains +-rw-r----- ./help/english/domains/= +drwxr-s--- ./help/english/done +-rw-r----- ./help/english/done/= +drwxr-s--- ./help/english/email +-rw-r----- ./help/english/email/= +drwxr-s--- ./help/english/exit +-rw-r----- ./help/english/exit/= +drwxr-s--- ./help/english/find +-rw-r----- ./help/english/find/= +drwxr-s--- ./help/english/general +-rw-r----- ./help/english/general/= +drwxr-s--- ./help/english/help +-rw-r----- ./help/english/help/= +drwxr-s--- ./help/english/list +-rw-r----- ./help/english/list/= +drwxr-s--- ./help/english/mail +-rw-r----- ./help/english/mail/= +drwxr-s--- ./help/english/manpage +-rw-r----- ./help/english/manpage/= +drwxr-s--- ./help/english/motd +-rw-r----- ./help/english/motd/= +drwxr-s--- ./help/english/nopager +-rw-r----- ./help/english/nopager/= +drwxr-s--- ./help/english/pager +-rw-r----- ./help/english/pager/= +drwxr-s--- ./help/english/path +-rw-r----- ./help/english/path/= +drwxr-s--- ./help/english/prog +-rw-r----- ./help/english/prog/= +drwxr-s--- ./help/english/quit +-rw-r----- ./help/english/quit/= +drwxr-s--- ./help/english/regex +-rw-r----- ./help/english/regex/= +drwxr-s--- ./help/english/servers +-rw-r----- ./help/english/servers/= +drwxr-s--- ./help/english/set +-rw-r----- ./help/english/set/= +drwxr-s--- ./help/english/set/autologout +-rw-r----- ./help/english/set/autologout/= +drwxr-s--- ./help/english/set/compress +-rw-r----- ./help/english/set/compress/= +drwxr-s--- ./help/english/set/encode +-rw-r----- ./help/english/set/encode/= +drwxr-s--- ./help/english/set/language +-rw-r----- ./help/english/set/language/= +drwxr-s--- ./help/english/set/mailto +-rw-r----- ./help/english/set/mailto/= +drwxr-s--- ./help/english/set/match_domain +-rw-r----- ./help/english/set/match_domain/= +drwxr-s--- ./help/english/set/match_path +-rw-r----- ./help/english/set/match_path/= +drwxr-s--- ./help/english/set/max_split_size +-rw-r----- ./help/english/set/max_split_size/= +drwxr-s--- ./help/english/set/maxhits +-rw-r----- ./help/english/set/maxhits/= +drwxr-s--- ./help/english/set/maxhitspm +-rw-r----- ./help/english/set/maxhitspm/= +drwxr-s--- ./help/english/set/maxmatch +-rw-r----- ./help/english/set/maxmatch/= +drwxr-s--- ./help/english/set/output_format +-rw-r----- ./help/english/set/output_format/= +drwxr-s--- ./help/english/set/pager +-rw-r----- ./help/english/set/pager/= +drwxr-s--- ./help/english/set/search +-rw-r----- ./help/english/set/search/= +drwxr-s--- ./help/english/set/server +-rw-r----- ./help/english/set/server/= +drwxr-s--- ./help/english/set/sortby +-rw-r----- ./help/english/set/sortby/= +drwxr-s--- ./help/english/set/status +-rw-r----- ./help/english/set/status/= +drwxr-s--- ./help/english/set/term +-rw-r----- ./help/english/set/term/= +drwxr-s--- ./help/english/show +-rw-r----- ./help/english/show/= +drwxr-s--- ./help/english/site +-rw-r----- ./help/english/site/= +drwxr-s--- ./help/english/stty +-rw-r----- ./help/english/stty/= +drwxr-s--- ./help/english/term +-rw-r----- ./help/english/term/= +drwxr-s--- ./help/english/unset +-rw-r----- ./help/english/unset/= +drwxr-s--- ./help/english/version +-rw-r----- ./help/english/version/= +drwxr-s--- ./help/english/whatis +-rw-r----- ./help/english/whatis/= +drwxr-s--- ./help/francais +-rw-r----- ./help/francais/.doit +-rw-r----- ./help/francais/.nl +-rw-r----- ./help/francais/= +drwxr-s--- ./include +drwxr-s--- ./logs +-rw-r----- ./logs/archie.log +-rw-r----- ./logs/email.log +drwxr-s--- ./manpages +-rw-r----- ./manpages/anonftp_parser_output.5 +-rw-r----- ./manpages/archie.n +-rw-r----- ./manpages/archie_clients.n +-rw-r----- ./manpages/archie_headers.5 +-rw-r----- ./manpages/archie_protocol.5 +-rw-r----- ./manpages/arcontrol.n +-rw-r----- ./manpages/ardomains.n +-rw-r----- ./manpages/arexchange.n +-rw-r----- ./manpages/arretrieve.n +-rw-r----- ./manpages/arserver.n +-rw-r----- ./manpages/convert_hostdb.n +-rw-r----- ./manpages/db_build.n +-rw-r----- ./manpages/db_check.n +-rw-r----- ./manpages/db_dump.n +-rw-r----- ./manpages/db_reorder.n +-rw-r----- ./manpages/db_siteidx.n +-rw-r----- ./manpages/db_stats.n +-rw-r----- ./manpages/delete_anonftp.n +-rw-r----- ./manpages/delete_webindex.n +-rw-r----- ./manpages/handle_header.n +-rw-r----- ./manpages/host_manage.n +-rw-r----- ./manpages/insert_anonftp.n +-rw-r----- ./manpages/insert_webindex.n +-rw-r----- ./manpages/mail_stats.n +-rw-r----- ./manpages/net_anonftp.n +-rw-r----- ./manpages/parse_anonftp.n +-rw-r----- ./manpages/parse_anonftp_unix_bsd.n +-rw-r----- ./manpages/parse_anonftp_vms_std.n +-rw-r----- ./manpages/retrieve_anonftp.n +-rw-r----- ./manpages/update_anonftp.n +-rw-r----- ./manpages/weaseld.n +drwxr-s--- ./pager +drwxr-s--- ./pager/bin +-rw-r----- ./pager/bin/less.hlp +-rw-r----- ./pager/bin/less.sh +drwxr-s--- ./pager/etc +-rw-r----- ./pager/etc/termcap +drwxr-s--- ./pfs +drwxr-s--- ./pfs/bin +-rwxr-x--- ./pfs/bin/als +-rwxr-x--- ./pfs/bin/archie +-rwxr-x--- ./pfs/bin/dirsrv +-rwxr-x--- ./pfs/bin/fakebin +-rwxr-x--- ./pfs/bin/gen_vfsetup +-rwxr-x--- ./pfs/bin/list_acl +-rwxr-x--- ./pfs/bin/menu +-rwxr-x--- ./pfs/bin/newvs +-rwxr-x--- ./pfs/bin/p__vcd +-rwxr-x--- ./pfs/bin/p__vfsetup +-rwxr-x--- ./pfs/bin/padmin +-rwxr-x--- ./pfs/bin/pfs +-rwxr-x--- ./pfs/bin/psession +-rwxr-x--- ./pfs/bin/pstart +-rwxr-x--- ./pfs/bin/pstatus +-rwxr-x--- ./pfs/bin/set_acl +-rwxr-x--- ./pfs/bin/set_atr +-rwxr-x--- ./pfs/bin/vget +-rwxr-x--- ./pfs/bin/vln +-rwxr-x--- ./pfs/bin/vls +-rwxr-x--- ./pfs/bin/vmkdir +-rwxr-x--- ./pfs/bin/vrm +drwxr-s--- ./pfs/history +drwxr-s--- ./pfs/info-tree +-rw-r----- ./pfs/pfs.log +drwxr-s--- ./pfs/pfsdat +drwxr-s--- ./pfs/shadow +drwxr-s--- ./scripts +-rwxr-x--- ./scripts/archie.shell +-rwxr-x--- ./scripts/archiemail +-rwxr-x--- ./scripts/aslip +-rwxr-x--- ./scripts/batch-email +-rwxr-x--- ./scripts/daily.admin +-rwxr-x--- ./scripts/eval-perf.pl +-rwxr-x--- ./scripts/filter_anonftp_novell +-rwxr-x--- ./scripts/filter_anonftp_unix_bsd +-rwxr-x--- ./scripts/filter_anonftp_unix_bsd.nowork +-rwxr-x--- ./scripts/filter_anonftp_unix_bsd.perl +-rwxr-x--- ./scripts/filter_anonftp_unix_bsd.sed +-rwxr-x--- ./scripts/filter_anonftp_vms_std +-rwxr-x--- ./scripts/mail_handler +-rwxr-x--- ./scripts/mail_inform +-rwxr-x--- ./scripts/mail_receiver +-rwxr-x--- ./scripts/mail_stats +-rwxr-x--- ./scripts/process-email +-rwxr-x--- ./scripts/prospero-stats.pl +-rwxr-x--- ./scripts/rotate +-rwxr-x--- ./scripts/show_arcompress +-rwxr-x--- ./scripts/start-weaseld +-rwxr-x--- ./scripts/trimplog.pl +-rwxr-x--- ./scripts/unrotate +-rwxr-x--- ./scripts/untar +drwxr-s--- ./tmp +-rw-r----- ./tmp/db.tar diff --git a/release/base/Release-Notes-3.5 b/release/base/Release-Notes-3.5 new file mode 100644 index 0000000..976f53d --- /dev/null +++ b/release/base/Release-Notes-3.5 @@ -0,0 +1,149 @@ + + + + + Archie 3.5 Beta + --------------- + + + +Patch level 3: +============== + + - Support for ls-lR.gz files + - New WWW front-end to the Archie database. + - Improved search speed. + - ISO-Latin-1 support for searches. + - bug fixes as well.. + + +Some notes on how to install or take advantage of the new features. + + +ls-lR.gz +-------- + You must have gzip and gunzip on your system. + You need to edit the files + + ~archie/etc/arretdefs.cf + + modify the line anonftp:unix_bsd:image:.Z:anonymous:::-R:*?:ls-lR + to anonftp:unix_bsd:image:.gz,.Z:anonymous:::-R:*?:ls-lR + + you need to modify the file + + ~archie/etc/options.cf (read the instructions in that file) + + +WWW front-end +------------- + + Thw files related to the WWW front-end are in ~archie/cgi + + You will find in ~archie/cgi/bin + a perl script (archie) and a binary program (cgi-client). + + The top part of the perl script will tell you what needs to + be setup. + + In ~archie/cgi/html are the different gif files and search forms. + They are not in their final stage ... so do not hesitate to + give us your comments. + + The files archie and archie-adv in that directory should + be modified to indicate where the perl script is located. + + We recommend that a uniform url be used for archie so that + Archie users will easily find the search page. + + http://archie.foo.bar/archie and + http://archie.foo.bar/archie-adv + + + +New in this release: +==================== + +Here are the major added components to the system with some +of the key points involved in each one of them. + + +- Support for a new database module (webindex) + - retrieval of HTML pages through http protocol + - Keyword extraction + - Controlled crawling of the WWW + - Site by site basis + - Content extraction + - configurable stoplist (keyword exclusion) + +- New database structure + - More reliable structure. + + +- New search engine + - Based on a paged tree structured index + - Faster searches + - Less memory required + - More disk space for construction of the index + +- New search interface + - cgi-bin compliant interface + + +- A better domain filter for anonftp + - results can be pre-configured to return in a certain order + (e.g. ftp sites close to the server first) + - configurable on a server basis + + + +Fixed bugs +========== + + +- the ``-t'' switch on arcontrol creates the new files and work files + in the specified temp directory and not in ~archie/db/tmp + + +- Lock files are now created in ~archie/db/locks + +- host_manage can handle multiple preferred hostsnames + + + + +Currently working on: +===================== + +- Rewrite of the cgi-bin front-end to be more flexible. + +- Archie Help page + +- Regular Expressions with the new search engine. + +- New set of manpages and documentation. + +- Additional type of searches + + + + + +Currently testing: +================== + +- dirsrv with the new database technology. + + + + +Known Problems: +=============== + +- arexchange of webindex will not fully functional + it will not transfer .excerpt files. We still need to experiment + with indexing of the Web and see what is involved with + exchanges of data. + + + diff --git a/release/base/Version b/release/base/Version new file mode 100644 index 0000000..b9bfc26 --- /dev/null +++ b/release/base/Version @@ -0,0 +1 @@ +Version 3.5, Patch Level 4 diff --git a/release/base/cgi/bin/archie.cgi b/release/base/cgi/bin/archie.cgi new file mode 100644 index 0000000..22ddd8d --- /dev/null +++ b/release/base/cgi/bin/archie.cgi @@ -0,0 +1,435 @@ +#!/usr/local/bin/perl +# +# Archie Perl Client (front-end) +# This script needs the binary cgi-client (back-end) to pass the query parameters +# to. It then reads the result returned from cgi-client and reformats it +# for the http server. +############################################################################## + +############################################################################## +# These few lines MUST be configured according to your system. +# The first variable holds the full path to your cgi-client binary which could +# be of any name you wish. The $archie_user variable holds the user name under which +# your archie service is running. +############################################################################## + +$archiebin = "/services/archie/archie-3.5/cgi/bin/cgi-client"; + # You can rename the binary to archie.bin or any other suitable name you + # choose. + +$archieperl = "http://services.bunyip.com:8800/cgi-bin/archie.cgi"; + # This same perl script you are looking at. Where will its URL be? + +$archie_user = "archie"; + # If your archie server is running under another user name then please + # change this accordingly. + +$adv_page = "/archie-adv.html"; +$smpl_page = "/archie.html"; + # The above URLs will take you to our web pages! We don't mind but we doubt + # that you setup an Archie server for nothing! Please change the web site + # in those lines to your web site name. + +$gif_url = "http://services.bunyip.com:8800/results.gif"; + # Where the results.gif file is. +############################################################################## +# The following lines hold the different strings sent back to the httpd +# server. It is optional to modify them to comply with your HTML-look +# preference. +############################################################################## + +$excerpt_offset = 9; +$site_offset = 6; +$info_offset = 5; + +$archie_title = "Archie Results\n"; +$archie_header_plain = "

Archie Results

\n";
+$archie_header_logo = "\"Archie\n";
+$archie_continue_button = "
New Advanced Query | New Simple Query
Modify Search
:
\n"; +$archie_pages = "
New Advanced Query | New Simple Query
\n"; +$str1 = "

Found %d Hit(s)

\n"; +$str2 = "(%d) %s

\n"; +$str3 = "\n"; +$str4 = "\n"; +$str5 = "(%d)%s

\n"; +$str6 = "(%d)%s

\n"; +$str7 = ' 'x$info_offset."%d "; +$str8 = ' 'x$site_offset."%s"; +$str9 = "Keyword: %s"; +$str10 = "Date: %s"; +$str11 = ' 'x$info_offset."Size: %d"; +$str12 = ' 'x$excerpt_offset."

%s

";
+$str13 = "
\n"; + + +format OUTINFO = +~
@<<<<<<<<<<<<<@<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<< @* +$perms, $size, $date, $strout +. + + +format OUTPATH = +@* +$path +. + +############################################################################## +# END OF CHANGES +############################################################################## + +%proto =( +"Anonymous FTP", "ftp", +"Web Index", "http" +); + +%main_tran =( + FORM_PLAIN_OUTPUT_FLAG, "oflag", + FORM_CASE, "case", + FORM_CASE_SENS, "Sensitive", + FORM_CASE_INS, "Insensitive", + FORM_QUERY, "query", + FORM_OLD_QUERY, "oldquery", + FORM_STRINGS_ONLY, "strings", + FORM_MORE_SEARCH, "more", + FORM_SERV_URL, "url", + FORM_GIF_URL, "gifurl", + FORM_STR_HANDLE, "strhan", + FORM_STRINGS_NO, "NO", + FORM_STRINGS_YES, "YES", + FORM_DB, "database", + FORM_ANONFTP_DB, "Anonymous FTP", + FORM_WEB_DB, "Web Index", + I_ANONFTP_DB, 0, + I_WEBINDEX_DB, 1, + FORM_TYPE, "type", + FORM_EXACT, "Exact", + FORM_SUB, "Sub String", + FORM_REGEX, "Regular Expression", + FORM_MAX_HITS, "maxhits", + FORM_MAX_HPM, "maxhpm", + FORM_MAX_MATCH, "maxmatch", + FORM_PATH_REL, "pathrel", + FORM_PATH, "path", + FORM_EXCLUDE_PATH, "expath", + FORM_AND, "AND", + FORM_OR, "OR", + FORM_START_STRING, "start_string", + FORM_START_STOP, "start_stop", + FORM_START_SITE_STOP, "start_site_stop", + FORM_START_SITE_FILE, "start_site_file", + FORM_START_SITE_PRNT, "start_site_prnt", + PATH_AND, 0, + PATH_OR, 1, + FORM_DOMAINS, "domains", + FORM_DOMAIN_1, "domain1", + FORM_DOMAIN_2, "domain2", + FORM_DOMAIN_3, "domain3", + FORM_DOMAIN_4, "domain4", + FORM_DOMAIN_5, "domain5", + PLAIN_HITS, "HITS", + FORM_ERROR, "ERROR", + FORM_FORMAT, "format", + FORM_FORMAT_KEYS, "Keywords Only", + FORM_FORMAT_EXC, "Excerpts Only", + FORM_FORMAT_LINKS, "Links Only", + FORM_FORMAT_STRINGS_ONLY, "Strings Only", + I_FORMAT_KEYS, 2, + I_FORMAT_EXC, 0, + I_FORMAT_LINKS, 1 +); + +%result_tran=( + PLAIN_START, "START_RESULT", + PLAIN_END, "END_RESULT", + PLAIN_URL, "URL", + PLAIN_STRING, "STRING", + PLAIN_TITLE, "TITLE", + PLAIN_NO_TITLE, "NO_TITLE", + PLAIN_SITE, "SITE", + PLAIN_PATH, "PATH", + PLAIN_TYPE, "TYPE", + PLAIN_WEIGHT, "WEIGHT", + PLAIN_TEXT, "TEXT", + PLAIN_PERMS, "PERMS", + PLAIN_SIZE, "SIZE", + PLAIN_DATE, "DATE", + PLAIN_FILE, "FILE", + PLAIN_KEY, "KEY", + PLAIN_START_STRINGS, "START_STRINGS_ONLY", + PLAIN_END_STRINGS, "END_STRINGS_ONLY" +); + +$ENV{"ARCH_USER"} = $archie_user; +$| = 1; +open(stdin,"-"); +open(IN,"$archiebin < '$stdin' |"); + +$i = 1; +$s = 1; +$top=1; +$k = 1; +$no_sites = 1; +$entry{"FORM_GIF_URL"} = $gif_url; +$entry{"FORM_SERV_URL"} = $archieperl; +while (){ + chop; + if( $_ =~ /^$main_tran{"FORM_PLAIN_OUTPUT_FLAG"}/ ){ + ($junk,$flag) = split(/=/,$_,2); + if( $flag == 1 ){ + ## This is for plain results returned to the web + ## server in record-like format (no processing is + ## done on the results). Used for certain types + ## of URAs. Unlikely to be used by our clients! + print STDOUT "Content-type: text/plain\n\n"; + print STDOUT $_."\n"; + foreach $k (keys %entry){ + print STDOUT "$main_tran{$k}=$entry{$k}\n"; + } + while (){ + print STDOUT $_; + } + exit 1; + } + } + if ( $_ =~ /^$main_tran{"FORM_ERROR"}/ ) { + $entry{"PLAIN_HITS"} = 0; + ($junk,$err) = split(/=/,$_,2); + &print_error($err,$entry{"FORM_GIF_URL"}); + last; + }elsif( ($i == 0) && !( $_ =~ /^$main_tran{"PLAIN_HITS"}/ )){ + &print_error("Returned results are incorrect",$entry{"FORM_GIF_URL"}); + last; + }else{ + if( !($_ =~ /=/) ) { + last; + } + ($junk,$value) = split(/=/,$_,2); + if( ($i == 1) && ( $junk eq $main_tran{"PLAIN_HITS"} ) && ($value == 0)){ + &print_error("No hits",$entry{"FORM_GIF_URL"}); + exit 1; + } + if($value eq ""){ + next; + } + $main = 0; + foreach $key (keys (%main_tran)) { + if( $main_tran{$key} eq $junk ){ + $entry{$key} = $value; + $main = 1; + last; + } + } + $strings_only=0; + if($result_tran{"PLAIN_START_STRINGS"} eq $junk){ + $strings_only = 1; + &print_header($entry{"FORM_GIF_URL"},$entry{"FORM_SERV_URL"}); + printf STDOUT $str1,$entry{"PLAIN_HITS"}; + $_ = ; + if( $_ eq "" ){ + last; + } + chop; + if( $_ !~ /=/ ) { + last; + } + ($junk,$value) = split(/=/,$_,2); + if($value eq ""){ + next; + } + }elsif( ($main == 0) && ($junk ne $result_tran{"PLAIN_START"}) ){ + $entry{$junk} = $value; + $main = 1; + } + + if( $main == 0 ){ + if( defined($entry{"FORM_DB"}) && ($entry{"FORM_DB"} eq $main_tran{"FORM_ANONFTP_DB"} )){ + $db = $main_tran{"I_ANONFTP_DB"}; + }else{ + $db = $main_tran{"I_WEBINDEX_DB"}; + } + if (($strings_only == 0) && (!defined( $entry{"FORM_SERV_URL"} )) ){ + &print_error("The submitted information does not include URL information. Read the HELP pages to setup your html page correctly.",$entry{"FORM_GIF_URL"}); + exit 1; + } +# do while instead + + while (1){ + if($result_tran{"PLAIN_END_STRINGS"} eq $junk){ + last; + }elsif($strings_only == 1){ + printf STDOUT $str2, $s ,$value; + $s++; + }elsif( $result_tran{"PLAIN_START"} eq $junk ){ + $rec_num = $value+1; + if($top != 1){ + $old_site = $curr_site; + $old_str = $curr_str; + } + }elsif( $result_tran{"PLAIN_END"} eq $junk ){ + if ($top == 1){ + &print_header($entry{"FORM_GIF_URL"},$entry{"FORM_SERV_URL"}); + printf STDOUT $archie_continue_button, $entry{"FORM_OLD_QUERY"}; + foreach $k ( keys %entry ){ + if( $k eq "PLAIN_HITS" ){ + printf STDOUT $str1, $entry{$k}; + printf STDOUT $str3; + }else{ + printf STDOUT $str4, $main_tran{$k}, $entry{$k}; + } + } + print STDOUT "
\n";
+												$top=0;
+										}
+										if($db == $main_tran{"I_ANONFTP_DB"}){
+												if( $old_site ne $curr_site ){
+														## Do some processing for a new site
+														$no_sites++;
+														printf STDOUT "

"; + + if($result{"PLAIN_STRING"} ne $result{"PLAIN_SITE"}){ + printf STDOUT $str5, $rec_num, $result{"PLAIN_SITE"}; + }else{ + printf STDOUT $str6, $rec_num, $result{"PLAIN_URL"}, $result{"PLAIN_SITE"}; + } + } + $str = $result{"PLAIN_STRING"}; + $size = $result{"PLAIN_SIZE"}; + $date = $result{"PLAIN_DATE"}; + $perms = $result{"PLAIN_PERMS"}; + if($result{"PLAIN_STRING"} ne $result{"PLAIN_SITE"}){ + $path = $result{"PLAIN_PATH"}; + &print_spaces($info_offset); + printf STDOUT $str7, $proto{"Anonymous FTP"}, $result{"PLAIN_SITE"}, $result{"PLAIN_PATH"}, $rec_num; + + $~ = "OUTPATH"; + write; + + $strout = "".$result{"PLAIN_STRING"}."

"; + $~ = "OUTINFO"; + write; + } + }elsif($db == $main_tran{"I_WEBINDEX_DB"}){ + if( defined( $result{"PLAIN_TITLE"})){ + $title =$result{"PLAIN_TITLE"}; + }else{ + $title = $result{"PLAIN_NO_TITLE"}; + } + + (defined ($result{"PLAIN_SITE"})) && ($site = $result{"PLAIN_SITE"}); + (defined ($result{"PLAIN_TEXT"})) && ($text = $result{"PLAIN_TEXT"}); + (defined ($result{"PLAIN_STRING"})) && ($str = $result{"PLAIN_STRING"}); + (defined ($result{"PLAIN_SIZE"})) && ($size = $result{"PLAIN_SIZE"}); + (defined ($result{"PLAIN_WEIGHT"})) && ($weight = $result{"PLAIN_WEIGHT"}); + (defined ($result{"PLAIN_DATE"})) && ($date = $result{"PLAIN_DATE"}); + (defined ($result{"PLAIN_URL"})) && ($strurl = $result{"PLAIN_URL"}); + if ($strurl eq $title) { + $title =~ s/:80\//\//; + $strurl = $title; + $title = "(NO-TITLE) $title"; + }elsif($strurl !~ /:80\d+/){ + $strurl =~ s/:80//; + } + if($site !~ /:80\d+/){ + $site =~ s/:80//; + } + if( $old_site ne $curr_site ){ + ## Do some processing for a new site + $no_sites++; + print STDOUT "

"; + + if($result{"PLAIN_STRING"} ne $result{"PLAIN_SITE"}){ + printf STDOUT $str5, $rec_num, $site; + }else{ + printf STDOUT $str6, $rec_num, $strurl, $site; + } + } + + if($result{"PLAIN_STRING"} ne $result{"PLAIN_SITE"}){ + &print_spaces($site_offset); + printf STDOUT $str8, $strurl, $title; + defined( $weight ) && (print STDOUT "\n\n".' 'x$site_offset) && (printf STDOUT $str9, $str); + defined( $date ) && (print STDOUT "\n\n".' 'x$site_offset) && (printf STDOUT $str10, $date) && (&print_spaces($info_offset)) && (printf STDOUT $str11, $size); + printf STDOUT $str12, $text; + } + } + + undef(%result); + undef $site; undef $text; undef $str; undef $size; undef $weight; undef $date; undef $strurl; + }else{ + foreach $key (keys (%result_tran)) { + if( $result_tran{$key} eq $junk ){ + $result{$key} = $value; + if($key eq "PLAIN_SITE"){ + $curr_site = $value; + } + if($key eq "PLAIN_STRING"){ + $curr_str = $value; + } + $main = 1; + last; + } + } + } + $_ = ; + if( $_ eq "" ){ + last; + } + chop; + if( $_ !~ /=/ ) { + last; + } + ($junk,$value) = split(/=/,$_,2); + if($value eq ""){ + next; + } + } + last; + } + } + $i++; +} +# printf STDOUT $archie_continue_button, $entry{"FORM_OLD_QUERY"}; +if( !defined( $entry{"PLAIN_HITS"} ) ){ + &print_error("No hits",$entry{"FORM_GIF_URL"}); +}elsif($err eq ""){ + print STDOUT $str13; +} +exit 1; + + + +sub print_error { + local($error_msg,$gifurl) = @_; + print STDOUT "Content-type: text/html\n\n"; + if( $gifurl eq "" ){ + print STDOUT "

Archie Results


\n\n"; + }else{ + printf STDOUT $archie_header_logo, $gifurl; + print STDOUT "

Archie Results


\n\n"; + } +# print STDOUT "

Archie Error


\n\n"; + + print STDOUT "".$error_msg."

\n"; + printf STDOUT $archie_pages; + print STDOUT "\n"; + return(1); +} + +sub print_header { + local($gifurl, $url) = @_; + print STDOUT "Content-type: text/html\n\n"; + printf STDOUT $archie_title; + if( $gifurl eq "" ){ + printf STDOUT $archie_header_plain; + }else{ + printf STDOUT $archie_header_logo, $gifurl; + } + print STDOUT "
\n"; + return(1); +} + +sub print_spaces { + local($n) = $_; + print STDOUT ' 'x$n; + return(1); +} diff --git a/release/base/cgi/html/archie-adv.html b/release/base/cgi/html/archie-adv.html new file mode 100644 index 0000000..14f1a2f --- /dev/null +++ b/release/base/cgi/html/archie-adv.html @@ -0,0 +1,47 @@ + + +Search in Archie + + + +
+Archie Query Form
+Search for:
+

+

+
+
+Database: Anonymous FTP Web Index +Search Type: Sub String Exact Regular Expression +Case: Insensitive Sensitive

+Output Format For Web Index Search: Keywords Excerpts + Links Strings +

+
+
+

Optional Search Parameters

+
    +

    +

  • Maximum Hits:
    + +
  • If you want to limit the search so that it only looks in certain domains +(such as ca, edu or com), enter one or more in the following boxes:
    + +
    + +
  • Limit the search results to match a directory path (this is optional): +

    + +
  • You can use as many terms as you like in your path restriction field, as long as you separate them by spaces. The operator among these terms is: +
    OR AND
    + +
  • Exclude search results that match a directory path you don't want (this is also optional): +

    +
+
+Help | Simple Search | Archie's Home Page +
+
+ diff --git a/release/base/cgi/html/archie-help.html b/release/base/cgi/html/archie-help.html new file mode 100644 index 0000000..d650ade --- /dev/null +++ b/release/base/cgi/html/archie-help.html @@ -0,0 +1,138 @@ + +Archie Help +

Archie Help

+
This help file explains in moderate detail what each field in the search page +means. If you still can't locate the help you need or you want to report an +error please mail us at archie-group@bunyip.com and we +will get back to you as soon as we can. +
+
+
+Search For: +
+Here you type in the search variable. If regular expression is the type of +search you are using then the string would be the +regular expression you are +looking for. +
+ +Database: +
+The database which will be undergoing the search. If you are searching the +web then press on the Web Index button. Otherwise if you are searching +the FTP sites then press on the other button. +
+ +Search Type: +
+
    +
  • Exact: +
  • Sub String:
    +Substring (case insensitive): A match occurs if +the file (or directory) name in the database contains +the user-given substring, without regard to case. +
    +Example:
    +
    +               The pattern:
    +                    is
    +
    +               matches any of the following:
    +
    +                    islington
    +                    this
    +                    poison
    +
    +
    +Substring (case sensitive): As above, but taking case as significant. + +
    +Example:
    +
    +               The pattern:
    +
    +                    TeX
    +
    +               will match:
    +
    +                    LaTeX
    +
    +               but neither of the following:
    +
    +                    Latex
    +                    TExTroff
    +
    +
  • Regular Expression: + Regular expressions follow the conventions of the ed(1) command, + allowing sophisticated pattern matching. Regular expressions imbue + certain characters with special meaning, providing a quoting mechanism to remove + this special meaning when required. +
+
+ +Case: +
+This option only affects searches of type Regular Expression and Substring. +
+ +Output Format: +
+This controls the output format for results from the Web Index database. +
    +
  • Keywords Only: The most frequently occurring Keywords in each document will +be displayed after the document's URL. +
  • Excerpts Only: A short excerpt from each document is displayed +after its URL. +
  • Links Only: Only links are displayed with no further details. No excerpts +or Keywords are displayed with each URL. +
+
+ +

Optional Parameters

+
    +
  • Path restriction or exclusion: Several parameters could be used to +improve your search results. But first you must specify what type of operation +to be used on those upcoming fields. If you specify OR then you ask +that the strings you provide in these fields have an OR relationship among +them. Otherwise if you specify AND then you are asking for all the +strings that you provide in these fields to be considered. +
      +
    • Path Restriction : You can improve the results by restricting on +the path of each URL that comes back. The strings you provide in these field +will be matched against the paths returned in the result and paths that do not +contain these strings will be disregarded. If you have chosen the OR +as your operator among the strings then if any of the strings occur in a path +this path will be considered valid. However if you have chosen AND as +your operator then unless all the entered strings appear in the path, the path +is invalid. +
    • Path Exclusion : You can exclude certain results from coming back +if they contain a specific string you don't need to see. By specifying this +string in this field you will achieve your goal. +
    +
  • Domains: This variable allows you to restrict the scope of +your search based upon the Fully Qualified Domain Names (FQDN) of the +anonymous FTP or Web sites being searched. In this way, you can specify a +list of domain names to which all returned sites must match. + +
  • Maximum Hits : Allows Archie to generate at most the +specified number of matches (permissible range: 0-200; default: 100). + +
  • Maximum Hits Per Match : Across all the anonymous FTP and +Web archives on the Internet (and even on one single anonymous FTP archive) many +files will have the same name. For example, if you +search for a very common filename like "README" you can +get hundreds even thousands of matches. You can limit +the number of files with the same name through this variable. + +
  • Maximum Match : This variable will limit the number filenames (or +strings matched) returned. +For example, if maxmatch is set to 2 and you perform a +substring search for the string "etc", and the database +contains filenames "etca", "betc" and "detc" only the +filenames "etca" and "betc" will be returned. However, +depending on the values of maxhitspm and maxhits you +will get back a number of actual files with those +names. +
+ \ No newline at end of file diff --git a/release/base/cgi/html/archie.html b/release/base/cgi/html/archie.html new file mode 100644 index 0000000..e297eee --- /dev/null +++ b/release/base/cgi/html/archie.html @@ -0,0 +1,30 @@ + + +Search in Archie + +
+ + +
+Archie Query Form
+Search for:
+
+ +
+
+
+Database: Anonymous FTP Web Index +Search Type: Sub String Exact Regular Expression +Case: Insensitive Sensitive

+Output Format For Web Index Search: Keywords + Excerpts + Links + Strings +

+
+
+
+Help | Advanced Search | Archie's Home Page +
+
+ diff --git a/release/base/cgi/html/query.gif b/release/base/cgi/html/query.gif new file mode 100644 index 0000000..9708601 Binary files /dev/null and b/release/base/cgi/html/query.gif differ diff --git a/release/base/cgi/html/results.gif b/release/base/cgi/html/results.gif new file mode 100644 index 0000000..f76ebcd Binary files /dev/null and b/release/base/cgi/html/results.gif differ diff --git a/release/base/config/Makefile b/release/base/config/Makefile new file mode 100644 index 0000000..cc10dc3 --- /dev/null +++ b/release/base/config/Makefile @@ -0,0 +1,128 @@ +# archie Version 3.5-beta +# Bunyip Information Systems, 1994 +# $Id: Makefile,v 1.10 1995/03/17 13:50:36 pedro Exp $ +# +# This is the configuration Makefile for the archie V 3.5 distribution +# +# Change the following 2 definitions if you don't like the defaults MAKE +# SURE that you have allocated the archie user codes before running this +# Makefile The name of the archie administrative code. You might want to +# create an archie group as well +# +# YOU MUST RUN THIS MAKEFILE AS SUPERUSER +# + +ARCHUSER=archie +ARCHGRP =archie + +# The place for the manpages describing the binaries + +MANEXT=n +MAN=../man + +#MAN5EXT=$(MANEXT) +MAN5EXT=5 +MAN5=$(MAN)/man${MAN5EXT} + +# Default permissions for archie binaries + +AR_PERMS=711 +ARS_PERMS=755 + +all: su links manpages owners archieb pfs links + + +su: + @echo "Making sure you're superuser" + @id=`id | sed 's/(.*$$//' | sed 's/^.*=//'`; \ + echo "Your uid is $$id"; \ + if [ "$$id" -ne "0" ]; then \ + echo "You must be running as superuser to configure archie"; \ + exit 2;\ + fi + +owners: + @echo Changing ownership to the archie user: $(ARCHUSER) + (cd ..; chown -R $(ARCHUSER) *; chgrp -R $(ARCHGRP) *;\ + chown $(ARCHUSER) . ; chgrp $(ARCHGRP) .; \ + chown $(ARCHUSER) .*; chgrp $(ARCHGRP) .*; chmod 755 .) + +archieb: + @echo Copying the shell and perl scripts into the bin directory + (cd ../scripts; tar cf - . | gzip > /tmp/scripts.tgz ; cd ../bin ;\ + ../scripts/untar /tmp/scripts.tgz) + @echo Setting permissions for binaries + for i in `find ../bin -type f -print | grep -v CVS | \ + sed 's?../bin/??g'`; do\ + chmod $(AR_PERMS) ../bin/$$i;\ + done + @echo Setting permissions for scripts + cd ../bin; /bin/file ./* | egrep -v '(demand|link|directory)' | \ + sed 's?:.*$$??' | xargs -t chmod $(ARS_PERMS) + @echo Setting permissions for logs + chmod 662 ../logs/email.log + @echo Setting permissions for tmp directory + chmod 1777 ../db/tmp ../tmp + @echo Taking care of the pager + cp ../bin/less* ../pager/bin + chmod 555 ../pager/bin/less* + @echo Setting permissions for telnet client + chown root ../bin/telnet-client + chmod 111 ../bin/telnet-client + chmod u+s ../bin/telnet-client + chmod 755 ../bin ../etc ../logs + chmod 644 ../etc/* + @echo Setting permissions for cgi progs + chmod 755 ../cgi ../cgi/* + chmod 644 ../cgi/html/* + chmod 755 ../cgi/bin/archie.cgi + chmod 755 ../cgi/bin/cgi-client + chmod u+s ../cgi/bin/cgi-client + @echo Setting permissions for databases + chmod o+rx ../db ../db/* + +manpages: + -mkdir $(MAN) && chmod 755 $(MAN) + -mkdir $(MAN)/man$(MANEXT) && chmod 755 $(MAN)/man$(MANEXT) + -mkdir $(MAN5) && chmod 755 $(MAN5) + for i in `find ../manpages/*.n -type f -print | grep -v CVS |\ + sed 's?../manpages/??g' | sed 's/\..$$//g'`; do\ + cp ../manpages/$$i.n $(MAN)/man$(MANEXT)/$$i.$(MANEXT);\ + chmod 644 $(MAN)/man$(MANEXT)/$$i.$(MANEXT);\ + if [ -f /usr/ucb/echo ] ; then /usr/ucb/echo -n "." ; \ + else echo -n "." ; fi \ + done + @echo "" + for i in `find ../manpages/*.5 -type f -print | grep -v CVS |\ + sed 's?../manpages/??g' | sed 's/\..$$//g'`; do\ + cp ../manpages/$$i.5 $(MAN5)/$$i.$(MAN5EXT);\ + chmod 644 $(MAN5)/$$i.$(MAN5EXT);\ + if [ -f /usr/ucb/echo ] ; then /usr/ucb/echo -n "." ; \ + else echo -n "." ; fi \ + done + @echo "" + @echo "Done"; + +pfs: + @echo "Taking care of things in /pfs" + find ../pfs -type f -print | xargs -t chmod 644 + find ../pfs -type d -print | xargs -t chmod 755 + find ../pfs/bin -type f -print | xargs -t chmod 755 + chown root ../pfs/bin/pstart + chmod gu+s ../pfs/bin/pstart + +links: + @echo "Creating /pfs link" + -rm -f /pfs + ln -s `pwd | sed 's?/config??'`/pfs /pfs + @echo "Creating other links" + -cd .. ; rm -f bin/-telnet-client bin/arexchange bin/arretrieve + cd ../bin; ln -s telnet-client ./-telnet-client; \ + ln -s arserver arexchange; \ + ln -s arserver arretrieve; \ + ln -s update_anonftp update_webindex + + + + + diff --git a/release/base/contrib/README b/release/base/contrib/README new file mode 100644 index 0000000..cc7e1b2 --- /dev/null +++ b/release/base/contrib/README @@ -0,0 +1,49 @@ +The archie standalone clients are the property of the individual authors +and are included here for the convenience of our customers. All of these +clients are available on the Internet via anonymous FTP. + +The modified sources for less used with the archie system are included +in less-177-for-archie.tar.Z + +NOTE: These sources do _NOT_ contain the prospero patch for V2/V3 + archie/prospero systems. However, the fix is included if you would + perform the patch yourself. It is in prospero-fix. + + + Archie Standalone clients + +File name Author Comments +---------- ------ ------------ + +c-archie-1.[1-3].tar.Z + Brendan Kehoe Command line interface + (brendan@cygnus.com) written in C + +c-archie-1.[2,3]-for-vms.com + Brendan Kehoe Command line interface + (brendan@cygnus.com) written for VMS + + +archie.el + Brendan Kehoe Command line interface + (brendan@cygnus.com) written for emacs + +perl-archie-3.8.tar.Z + Khun Yee Fung Command line interface + (clipper@csd.uwo.ca) written in Perl + +xarchie-2.0.8.tar.Z + George Ferguson X11(R4) interface + (ferguson@cs.rochester.edu) Athena widget set + +archie-one-liner.sh + Mark Moraes + (moraes@deshaw.com) /bin/sh interface + +archie.zip Brad Clemens + (bkc@omnigate.clarkson.edu) PC DOS client + +mac-archie-client-09.hqx + Chris J McNeil + cmcneil@macc2.mta.ca Mac archie client + (This is shareware) diff --git a/release/base/contrib/archie.el b/release/base/contrib/archie.el new file mode 100644 index 0000000..7ee046c --- /dev/null +++ b/release/base/contrib/archie.el @@ -0,0 +1,71 @@ +;; +;; archie.el v1.0 -- by Brendan Kehoe (brendan@cs.widener.edu) +;; +;; A mock-interface to Archie for Emacs. This will shave by when you need +;; it. ARCHIE-SEZ will insert the result of the query in the current buffer, +;; and plain ARCHIE will create a separate buffer . +;; +;; TODO: hack ange-ftp to use the output of archie -l, and let you select +;; from a magic list which one you want to FTP into an Emacs buffer. +;; + +(defvar archie-program "/usr/local/bin/archie" + "Program that queries archie servers.") + +(defvar archie-server "archie.sura.net" + "Server for \\[archie] searches. + +Known archie servers: + archie.ans.net (USA [NY]) + archie.sura.net (USA [MD]) + archie.mcgill.ca (Canada) + archie.funet.fi (Finland/Mainland Europe) + archie.au (Australia) + archie.doc.ic.ac.uk (Great Britain/Ireland) +") + +(defvar archie-search-type "-e" + "Search type for \\[archie] searches. +Can be one of: -c for substring searches + -e for exact matches (default) + -r for a regexp + -s for a case-insensitive substring search +") + +(defun archie-sez (string) + "Insert the results of an archie query on STRING into the current buffer. + Uses the function `archie' for its main work." + (interactive (list (read-string "String: " nil))) + (archie string nil t)) + +(defun archie (string &optional type inplace) + "Look for STRING on an Archie server. +Optional second arg TYPE is the type of search to make -- by default, it's +`archie-search-type'. Possible values are substring, subcase (case insensitive +substring), and regexp (a regular expression). Interactively, a prefix arg +will make it prompt for this." + (interactive (list (read-string "String: " nil) + (and current-prefix-arg + (read-string "Search type [-c/-e/-r/-s]: " + archie-search-type)))) + (let ((buf (or inplace (get-buffer-create "*Archie*")))) + (if inplace + (progn + (push-mark (point) t) + (insert "Archie sez: \n")) + (progn + (pop-to-buffer buf) + (setq buffer-read-only nil + mode-line-process (concat ": " string) + mode-name "Query for" + minor-mode-alist nil) + (erase-buffer))) + (call-process archie-program nil buf nil + "-h" archie-server + (or type archie-search-type) + string)) + + (if (not inplace) + (progn + (setq buffer-read-only t) + (goto-char (point-min))))) diff --git a/release/base/contrib/archie.zip b/release/base/contrib/archie.zip new file mode 100644 index 0000000..aacc45d Binary files /dev/null and b/release/base/contrib/archie.zip differ diff --git a/release/base/contrib/c-archie-1.3.2-vms.com b/release/base/contrib/c-archie-1.3.2-vms.com new file mode 100644 index 0000000..ba066d9 --- /dev/null +++ b/release/base/contrib/c-archie-1.3.2-vms.com @@ -0,0 +1,9459 @@ +$ 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= + + 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 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 + * . + */ + +#include + +/* + * Archie client using the Prospero protocol. + * + * Suggestions and improvements to Brendan Kehoe (brendan@cs.widener.edu). + */ + +#include +#if defined(OS2) +# include +#endif +#ifdef MSDOS +# include +# include +# ifdef CUTCP +# include +# include +/* 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 +#include +#include +#include + +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 + * . + * + * 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 + +#include + +#include +#include +#include + +#include +#ifdef NEED_STRING_H +# include /* for char *index() */ +#else +# include /* 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 + * . + */ + +#include +#include + +#include +#include /* 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 + * . + */ + +/* 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 +#include +#include + +#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 +#else /* not VMS */ +# include /* this may/will define FD_SET etc */ +# ifdef u3b2 +# include /* THIS does FD_SET etc on AT&T 3b2s. */ +# endif /* u3b2 */ +# include +# if defined(NEED_TIME_H) && !defined(AUX) +# include +# else +# include +# endif +# ifdef WANT_BOTH_TIME +# include +# endif +# ifdef NEED_STRING_H +# include +# else +# include +# endif +# ifdef CUTCP +# include +# include +# include +# else /* not CUTCP */ +# include +# include +# endif +# ifdef NEED_SELECT_H +# include +# endif /* NEED_SELECT_H */ +# ifndef IN_H +# include +# define IN_H +# endif +# ifndef hpux +# include +# endif +#endif /* !VMS */ + +/* Interactive UNIX keeps some of the socket definitions in funny places. */ +#ifdef ISC +# include +#endif /* ISC */ + +#include +#include +#include +#include + +/* 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 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 + * . + */ + +#include +#include +#ifndef VMS +# include /* this may/will define FD_SET etc */ +# include +#endif + +#ifdef NEED_STRING_H +# include +#else +# include +#endif + +#ifndef VMS +# if defined(MSDOS) && !defined(OS2) +# ifndef CUTCP +# include +# endif +# else +# include +# endif +#else +# include +# include +#endif + +#include +#include + +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 + * . + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef NEED_STRING_H +# include +#else +# include +#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 +$! +$! 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 [|||] +$ 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 + * . + */ + +#include +#include +#include + +/* 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 + * . + */ + +#include + +#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 +# define IN_H +# endif +#else +# ifndef _ARCHIE_VMS +# include +# 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 + * . + */ + +#include + +/* + * 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 + * . + */ + +#include + +/* 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 + * . + */ + +#include + +#ifdef VMS +# include +#else /* not VMS */ +# ifndef _TYPES_ +# include +# endif /* _TYPES_ */ +# ifndef IN_H +# include +# define IN_H +# endif +#endif /* VMS */ + +#ifndef NULL +# ifdef MSDOS +# include +# 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 +#endif +#ifdef MSDOS +# define USG +# define NOREGEX +# include +# include +#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 +#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 + * . + */ + +#include + +#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 +# 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 + * . + * + */ + +#include +#include +#include +#include +#include +#include + +#ifdef NEED_TIME_H +# include +#else +# ifndef VMS +# include +# 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 + * . + */ + +#include +#include + +#include +#include /* 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 + * . + */ + +#include + +/* 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 + +#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 + * . + */ + +#include +#include +#include + +#ifdef NEED_STRING_H +# include +#else +# include +#endif + +#if defined(MSDOS) +# include +#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 + * . + */ + +/* + * Miscellaneous routines pulled from ~beta/lib/pfs and ~beta/lib/filters + */ + +#include +#include + +#include + +#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 +#else /* not VMS */ +# include +# include +# ifdef NEED_STRING_H +# include +# else +# include +# endif +# ifndef CUTCP +# include +# endif +# if !defined(MSDOS) || defined(OS2) +# include +# include +# endif +#endif /* VMS */ + +#include +#include +#include +#include +#include + +#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 +#include + +/* + * 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 +#include +#include +#include +#ifndef hpux +# include +#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 + * . + */ + +#include +#include + +/* + * 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 + * . + */ + +#include +#include + +#include +#include + +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 + +#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 */ +#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 +# include +# include +# include +# 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 +#include +#include +#include +#include +#include +#include +#include +#include +#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 +#else /* Gnu C */ +# include +#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 +#else /* not Gnu C */ +# include +#endif /* Gnu C */ + +#endif /* __PKTIME */ +$EOD +$! +$CREATE [.archie.vms]types.h +$DECK +/* sys/types.h */ +#ifndef _types_ +#define _types_ + +#ifndef __GNUC__ +# include +#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 + +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 ." diff --git a/release/base/contrib/c-archie-1.4.1.tar.gz b/release/base/contrib/c-archie-1.4.1.tar.gz new file mode 100644 index 0000000..4948d76 Binary files /dev/null and b/release/base/contrib/c-archie-1.4.1.tar.gz differ diff --git a/release/base/contrib/less-177-for-archie.tar.gz b/release/base/contrib/less-177-for-archie.tar.gz new file mode 100644 index 0000000..779616c Binary files /dev/null and b/release/base/contrib/less-177-for-archie.tar.gz differ diff --git a/release/base/contrib/mac-archie-client-09.hqx b/release/base/contrib/mac-archie-client-09.hqx new file mode 100644 index 0000000..efc407b --- /dev/null +++ b/release/base/contrib/mac-archie-client-09.hqx @@ -0,0 +1,1126 @@ +Date: Thu, 17 Dec 92 08:22:58 PST +From: "Chris J McNeil" +Subject: Archie Client Repost + +Enclosed is a repost of version 0.9 of an Archie Client for the Mac. + +The previous posted file had been binhexed twice and this is confusing to +people. ( I forgot that my mailer automatically binhexes enclosures, sorry :( ) + +What does it do ? +Archie allows you to query an Archie server to find files that are available +via anonymous ftp. + +What do I need to run it ? +You must have MacTCP installed on your machine. I have only tested this program +under system 7.01 and MacTCP 1.01. + +What does it cost ? +Archie is Shareware and costs $6.00 US. See the README file or About Archie for +details. + +Please replace info-mac/comm/archie-client-0.9.hqx with this one. + +Chris McNeil +MTA University +Sackville NB Canada +cmcneil@mta.ca + +(This file must be converted with BinHex 4.0) + +:#N&bBfKTC5jcC@%!39"36%9B9&)J!*!$R1d!!$$k[j-"!CIb!!#FFB"AH(KhHC! +$LAUDLSQ*QSQ)DRU+LBQBKhL*N!5)LAQ(H(KhL(KiL(KiL(L)H*Q*L(GhKhD(L(G +hH*!$L)LCLBPiLBQ)N!5(LBQCQ)Q*Q)PjLCLCGTQBQ)Q)LCQCHBQCLBQCQ*Q*LCU +*QT!%UkUCQUbVUTZFQTUEN!5+LSPe)!!"-d4@CRL)L*QTUXZkZX[0$,blh-$3d!$ +0`0!0$!$C3#4%9QCRCRH(GiH)GhL)KiH)KiH)H)KiH)L)H)L3")PiLCQ*L*!$Q)Q +)LBL*QC!)L*Q3!kQTUTUTLDU##1!6rch))2Z!55r!$GP*@0P@9pR-jq2!fNRk@Nb +',S-M(33k[@5%%%MLl+TcpC9F9"c&dG(NFCS-P16N'VeR3G0r9lL25q4N2rX1"%M +r[e3'N!$mL!Zbk'MdPRPV-4k,-e,h4k$F`Ai)lVa8"H6""(J4d2Mr`iXZJ)J)#(5 +52J#hD[@ARmUSD%[)JJZNh*!$KA+VN!")612Sk-#-a2jA,Br*d86V*6&jHNS*qLT +-IM-A5C2+a-[42"#IRSPG6e-T2Br+cq-"h04-APXCMmI%aH9aP"Mjr"C,&dQ-S,r +eq$`1$`1@kV"#+5Q4aq@T)Q,T+6+iqGbp*2jD*M-RNU2*d3KZ@L5N&fBjH*PDV4k +5YXp'''4ap&N)Q4JJap&56q9STqNQ*k*!a)Ke$%NS-RPU34Y#UBap&MFR%aQ,aP! ++[PXIf8qe6Rh(X[4BqPQ-PNji80r)Nb1,be)K*MmEM`1D6d9K%b92Ce1IUY(%Xl# +*P0*9@@SLBf`dPIRZLJJKKZHrJJk$*jD*2f9PB@3LR2beKC@@S`-5RL@99Sl$5@9 +694+qUUXp9Ck*8DL*CjqXdF5RXE'YV+QRXkb`ViP66epIB@F5SUSP@L*6-5NS%F" +M!pd@NV"!JcTl1*U"#AD)9GC@e85riZaXFP6k'UXSQHX+R59e9AfI9)JpCAKP940 +(6eb)R@ji)+H[cd62dqPURBcAS#dk)j94,'bX0"990Qa&G0@@HIL5mcCD1bUCG&S +UUmAQCLB`A$3UA9eKT0(94"UE%8iBZ[e%63e3c&K%&[XjNJ!kE%dGP99G9C99I8e +@Ma,B(d%p'rQ02qM35Zp3AU3eeGi4*&PNMf[d%M")%N%MJZHeJJREh"4`5Y&Q))+ +,18@Nf',cfHbeRT+ZV"qaJSY*4D4!3"!J`8P1aF&-`5Nh-`5B%ADLi%Gdi#I9Hi* +D5QCQ(RSJ'cbBidHcaSkF4,-3h0$A`5F@lcX9$B,TG$,U*b''NY8-0TM+f`dG8k- +3b!5iKfbSCPDURccdKR1L9fajm5ML8H$cm%e-8%22BLe"A`mqA"UAbN[P*HXJa@# +r)**K1acX219)XcC9PQp*%V'"aGJ%P4L*1LZ1PRR5qCQXVmpBDBGZL@5erJ[%AT0 +$,CH#,*k#8SVLmr"65&&FAlGX34d4B63i-)VcS1V4bcY&VcamRrQ#8TVZpaDrGUJ +XLBE'HX-CB9pRC@&DaZ(5)Al3hd4$T0"HhCYdh,cGV625$8@E9i$EC**&@2Vd3NM +FDm%k3Upk'p#&AE3ALq-3EkU5eTT4JCIX#em+Ne&L)#aZ"!(k0adqR9Z1NI$F2K( +VelMa(Vba(VA&e0R@D@RXkTdX,p%J[APUN!"+[K)*I3a!LPY"dih#b0JUeY0+Z`l +pAd8@FQI$'%be52$9VTK')3LJGiXL$*@'HUUdYLCkXTkf`LXG)4[)m!3V@G9C1%, +N35$8pB1#f2XkUZBLfN4A+(EaCa!M"5dEj%#2bDNSlbhj`'ZE*b++K)SU[Te*Vr" +KTZDJKMGTJTU#850lmrc8YUk3!+Zc8+rDa!(3aeE4MrKfN6L(6X9U'4`KQiH)CJ@ +QRlRf0(`S@EHP#RI)S02h%,6ci@1m`Bp"+cN%P861-jd'*jNjmArBFI$4A&cFdek +!ER8ei,DE&8dX!e(6%!81U5!+(c%GeVTk`Rmp@%&FY$pd2-!6j)Ii`rdKqQ(l#@* +cjhb%Im)CT3YTSqBcX22`FeEq(iQ0mhl)HIQ122+pjYD5bTl(&k@RV+fRU'5r#m9 +qb#6lX",DB@,E,946UTkR3jDXl9NcL(keYi*V5e9PSdQ*8A!Jje$RFb)PqHFf8I3 +c'bMb$R@i+DYkD15E&T3@ZNlQF&0D,24)MKKLVj3qBa4JHN%(UV5epQqN1ZU*49C +kcVhd05)P%M&c"EX68(j-(04d&[-*1`SB+5eUjbG"bQa+MNH(AeKep`Q9I$pPE)J +jG+D@F9kjq9&HTEAmpI$rk+4-#C!!H60m9ZXF0eU0'5N+ZX'5JS02LGd'Ac@e6EB +DJVYY4fpIEh-ET)f$MFZGh-EYL"VZ)PmYX)K%+jGBXK4F#2rS)F*0d@+!bi&JrK4 +A%V089acq8#Pj5%#(RUmC-E(lND+0JF9I-(*%*dR8D8K1f$N*dlj#%8EX3fq5PYD +EXU#Zf2di)SN4Z*685"!Ma%p66V3cGJCKQKQq!`Z,P$2*!bpMP**SK`eR965A8MJ +JaZYQPXN6VTk`deI"dN2e`kb(F3lf(bBI2Kj%2`3r-P'*kACbL%A0#R'AX4ehplT +"LTMBrA(ik#'p58R-33E(m)[6bYG"GGMp-@rc[N5dM3@Nh"'a3bNH+aH+(JE(QeF +Q+G(4[FTT1q50&FFkfT,A)r2"af1SS2l`AP%ZYl1r9faqV"G$Ek1refajZ#k'LZ1 +KZmcXid[3D'#@Yr&`A3aU`1[(!Mp1#PD+iP1E-NLLhdH4qHmXTE6eKPl(2&a-N!! +KrH1Na"2U`8VEk05cPUXhrfBj-p*8-P5fX@lYYZ*0YYPmT!&bVj*#3CkKNL44L33 +q*m%Rllj*0Q&*#"XVhVfKaI*4qbRGb*09TGVC(jjDd9Q'2%I9Ek#KcX@r#)D"'N* +Rf3Jce[D*IM!F%!0GUVdh!MV*Vm8p@D23cqP@K8M&6T!!U,$4p8h03r6EjZaMZ&i +GA1UbAq'-P&N8B!QI#l8-Nf84"1q4'[YrcX59LhMX06"*L#-9$3pKRGMq'!b1aqT +LeB+5QF2(rH4X3%Ti-U(`iZ(3)LAcK)raIfZ'[VNpCbrQ`GrJLF+XJPkZ84!+D33 +'L54)Q%5%1ZNATjhU4F)8M5*PQl`8'#Q,R1@p0Hlj65dELZab0BhZq&6`1%GTJKm +5(MhZ!N(G(XITUbi3ZEQGkP5MZ+'q&YCY!D'-LbB%5)45F`383mqQNdA4,JT(Q,G +,IlR15M++ire58-!qj+aHNQjN54JTQb6)Ca3K&d%)ZcBb#*lmBP0C-64(mN3U0D# +HCaiH4!mSKlLK`FaXIT*Dh5e%d5eU0h3Njm&0-J0`kDrJ0c+DA%@[#80[aUdSEIM +r5QPPQP&!#2qT+'hiHBVK#%$AP$TB2-($p8)ib(f`)pZ(P`r,$m3&I8J)i%2B1@f +mS2lb468P09HjMDiM%c'ePF$-E+6RCMBrfTTd5VN8-aYF2&[+`@G*1aD#ZfYhLCf +fcZ+Y*d'+5eI%H"15ZDqKJ*eea+$'AZYS4#)[SqU)e9bYaAE@9Uj(MF$C5FA#PfG +03DY,d+''0UErRF&+a[c-I!J,Jl#ff$(F8GV&PG$+CHFLb1J%3`ba9%5ejffi450 +YTjhU35k4&JT,8T(2&F5C9,'$)5iXP6ePINE#`,F1!2)lBqcJ05QQpXIEC5`5hBe +8'TJTVlkYGXICVT!!e-I6G2%b855S12rcX2Kim3[FZ&El(fkZ3e-G64q9ae$)aIP +PC'#156FYZBL4C23dPJQ1%*%-KAE(j++irp(m2[RD-Tf$d(fB+4e-#j)8QQ+3!$6 +ID,aLD(1eFT*c-&dKjX@2e-F#hf1%3H5Lb2*5,0#CAY8@q8&Z2L[-+CPapp)d)kH +MYDB`j)IXGid(hq%dF`G(Di&N,L+j2@&5YpC`h8e$,fpSN6!MAm"mbBf2XJ9lBP9 +I$`d[D)he8-c$`iTMp3qL#R'*8@'CMp'"-eVJ8PND+jm["5U`)FU0FAr1cXcFmA" +NJD,5k(-CQFLiR38H9R0"dr8DQ#cZH%S0jS$DHjiDKR%TX)"'58DbbM@C8DRJD[, +SDc+M@28Dapca-&0*!&JTQji9"Ah2&`9h&JmmH5jbZdZm@c5)bE[k2%IGc3FiS#F +FBJB6lZ'f@TKLFXJjaibeV1X#D#9D&FD"DcM%#rmMd$*fr`5aN5G1TYAE(q,$DGc +l$3#,YImkfk3baU&BY-G"C,349C-HZIideiH+YjMY&&H!ZF&*DU15h-SVL3c#R!1 +8YU6,#B*rhcd%T@rQ+YH+YiVAhAS2VMl[LC-#fcQJJkX'$kNaFkTP"#KVB+fYNj[ +!`9XEd+DmbYDDBeE9MqL*Ppp%8X%a401-)6b09(8efMF9,P+K%!LaqUJ&)@iUSI$ +Url*4i5[PXIl,2fQMFGJYraSVL#p6[8MR[9`8eeFK)Dfhr'K[Q#QZB`FdK6-p@Vk +5adrL5q!S!LNm&04*#3Y%'NYY0Mp&[Y%HBHY+6",0331,f`[e)lkarDl18qSl$hm +e(,pNF,A`5[lHA6819fIRHp8b-Vq@$S+[ljRSGlY+((@%U0p&LG$YpT0`@rG+05k +hpflXIVjPI$Fd((eIq0Mb+#F`NaXH4Z*bEMTf,EplPGRImKjh,U1,NIR[9SMb@bb +@SRV+Rde*9DGQJp$r@Jr[I&6UGViIT*DAN!"+bPThb!)QT##9'U[ZG`8TEk-YM,[ +Ekm"VaEl+*AQ894c'IJNiHD!dUY&VkVICiQCKqVq"-)!6kbG9cp[A`mfbqAiTbJp +IZIDl(&`rIBrd4CZaR)EPEC*)UZE'q+rAc"*U+5Z#ZNEpEXL0SfM[qIJa@UJLC'f +kUrhHBRSIkhkH`8SLX5d%R*friraVa%VZ'(1Qc,JKj[-R`ir!FehN5Nq(l)*AcIH +UTC%'jR*`eMBdhl[XKrVPFF1meZ@R!SqkKR,!d1SIZ`58Q,60fVL&Im9iJNc$q&[ +hPrk(+MNZ-!N@8F4+SmE"5Q#QVc")5Y[q,S8JKd!XR9S05F#3!-`aA[Mf(04l$ZU +1bFYj[Q`8NlN0IMb1`Vi,Z2h9ferVEj4b40K*#3f&[q0M",AbKR)Y)4!E"(5@pQ" +94LS+E$Spd5D+%"*j6*eF4A1'Q5*"(q&HFqE"690GEZ4(*-Bbf1SFGAqbA$(0+`M +B`'5S0M4Tbq-K0)R290+S4UV5B!"K8BRDD2XBjcDb59dh3+P+M#P1DFGdj[pIa5Q +eckK+EAqbB`BS(UTS)FrLTS)Frl%YM1IfVEQTRDm["S'FTG"40",lPd&2ZKqbG+Y +Nl`0VL3%a3#6XlAEA'J*3&me3J*4i[r'ea*+bjlG`D9@m1$5,IF!4ME(QTN545-* +*AdETErR6%J-*4`fC15ejSBBq[Ul"QLCJT@ab2LAZrd#2&&pPH@2*3lkrTRS**d# +kLUY-`a8b5a3NR6d[m*NS6[N"GCdYU*T+aZP[fGLC#f[J&AJ",ZjB8fCMP902CCj +UEA(0SD+ircFPQV@'hKU5CSPe9(4[@`'GfhCB+BfhC&$VlTRJ!C06f9c'9MC*5#2 +8JcLKPd8-U&$*"3bV8-ZUKQJ4"$X0GF"'FD%9$3LVD%D"-AL0edEVeY`VPG)T*q( +G&J5jA9iRV$&e&KT,0R%#MGA0bN)$+J'J+)82Z*4qfhC0hq))f0*hL"(RpMREP8% +-33RrZDfbB,$,r5hd'+[M3V3c4SS4FESCl06N@Cd%R56N@lk#p8dL*&K+DrcD*0X +#lQ[b"AipU"9k3+rcj)&G)J9d1q!U63+["R'$1BGbS)5+XP99qNDrT3PU5,+Lh8L +,G'a&0+1Jc%UA6pHbdqhZ)5a+F*@%QFR-Gb,H#8iGSbM*YU83U9LbL,i*GL+C12j +!T8'fE%'T+bcEhTLJeI$&ife+bkXA-Q)SXalFp)cXb2E6--1RJ-*"D4A8Cml-ebP ++",@bFM'P5lS1fSjHBGTl%pG!Z@k+SG[9b(D`8dIfXF)0q0$GBUjN6p-aV-Hc25& +$Tj6KC9L,IL)T""l,bq#JJmr!9ffU0Y5Abk*#-682JS5eP9bG$)9FKBL5@-GI)%N +E!eaAi'NZ50fSe+&@6mAX1A8(08r"XQ!0RVhh5Dq!&GN+*R0Y562'2!NQca3J9G9 +#T`#T*3V$!9*U&B(0fV$#q569DkGG4+#$[fXe(Uc@`Hl0IMppllPKKq2e80dcEm- +9q2-8N!"H2apY3T*(R'F@MmH'a1,hjN0bd`YVhVQQ(Ih[AY*YSS865[aeK2'k5q5 +5@`J(EkK)6XhDaBq0ejNS,4QfE0I")VLV+5U1DCRa*UEV-68DQ0AU2e1@G#8md5b +VS5R'LABZK+JD*Bad*AjJPfVY'ZV85N-604hhZK5CF&,SDY$46#1#RFIM0h90RL8 +Mm9"Bah-VYVGZ`R0VGX9aS1N-jDG5lZ'dr-"Q*`B16*H!A20*aQb!Mr55P,RQi+" +#BNiI"NIXJqLjqY[+pPUUR*XmlT,1cX&X$CL%l2#[jF#2SEp1*E&8*LY4C2"G#NV +#0dkGTj1decX8Z,aE`5$3KC,R@9m&fFar#S1Z,%Q-j1lP6k433r4RB1NGFML@`(0 +kc8`G""@TJ5CNPJV25YQP9jB,90QpKDp*2@H0dJCLChFZkMc5L*LZ"$hVAM)NEjl +haS)j`1YrbV2ilNlKhUY,VmSPVAJPeDLAG2"+C85ec`5`LL@[H#@'85f$`5QP%YN +m%MXe!PV(JP2+*E&i*8#c@,H#)#RjVmY),E*CZ66'HhQU9R[I8Zcm(5@hk8[K#mX +q"1L"B%T9,hC#$d[TJ[eAH8#U$2`Ae28SN8!lj*0L[m"&eEk)ZVI"&-[SLQA`4B4 +p%@%I"&KU[Td'R2%i$hDd-"Vc*JjD9T*01N'a,8'QR`JdiqL+FI"&22SLRR`48$k +)U"`LCJmGfhh426h+2-'+!4V0HiL4+-3+6Yq!E98bqHldj!8P',"INMI+Yhje,4l +ie54[[%I#5,Ri&eP+0irS)0h+c-(435G@YX!*aKPVIIN,R+dHHHL1MGTM$bQB-i1 +,EX*Gd0*k0LY9H+E+P+L66PQDSRmAYkY,drAdC4re'JmVV(ckJSrQ%L`BEEXk5(Y +&%Pb`rf4lD2j)pC8YUfA9dU5kPX2H)6[VbmQ#)'BP1C*-M**C!)GN%R62#4!ak*0 +JdN2j#G%L"Md5E&T)P`Ni5)'24*Ud*'MPdGV&%2-83U1Hi#*'rBdN6QbGX0d$a'N +$(T'YBm4VShXE5c`f3-HMEZAKXIJL2a*'C9Vci-),3&+Km8IN$(T"1kDh(jAK)JB +p%Q[H*3raGI0,V`U&F$DQ1!rQ@2l34,)fE6)HmMCRe#h$RmH2FHEpR%qh'hCpZ(` +I3rf90Pr@#[EIfYpeEldkb*3`I*%iXX2El`LJZN&dYr"3U`8e$cbdT'B'(r5beZE +L3EH!bIaT,1YV+qUc,UP8GkV%,ABUm%I#)bf*pcDq-MVqUC*e"AE)d#Sri'"%V+h +XaP%Ye+Zl)*)4!p`U0[XB+CM-V(,99NI(jM#-bZ+$3idhr*A36K[q([LKhClJK1% +LX%'ZBf-1RkjUlZp+BQ4PYF46AC!!8S01JND)Q)EPY8GP99Di@%2#6c[Brr'fVjh +c)H0-C'(N&G,hPc$1%[I3P$iD9m2Z5jGI5q``FN[Q`63DCH$90*M+0c!d2I`E5Pa +(hR+TDSjTfPVQB-!b(R(ISkAEEK0+6EEXer*AEEh&rC!!mh!8'fYM*HmDGc,[Qm6 +UJQCQ(le@E,ce(SkU[cbSppZ#NK"[cEEF#!5Hfh8lAEEajhJEDhHZIK6aR*%(9P9 +8iG+EAJk)%-(f,'IUB9,"qB@`'FLCeGaEQE%3#LX,1XUp3L"89a*@)G'`9Fr&LNk +0,Z+0AEE5lEEi[r'fm`BEGB$8`39e0Y[#aIq)1'V,9ffmB(2,!cahZce)N!"8*Yc +r,`8PLrXjrPicr(2k5aT)RlmTlN22kJCVRmjhGP*[9,STEGBD1"(A#b%UrRq@GP3 +qdAieE3cUd#*ZDZ[rZ#2,3,0CiU"(KZIEVXdCBH$bQNUV)Bac5)e-'+N8m2beQX( +B`9Ihi14bZ04a'%NXVMNJUr,`Mmk`9IdZD+'abeQGQq,M+Fl0bpML5e8&0,)J!A5 +[jH&BQKXa%#B",F,(9[pA1e0T$m[)GZcKQ-K&NmVMXVjN%R6IDirXe*-LRJ,*3hI +QKmYUV6NQ5pIdE@L-G#KZjMQ5*MQ5V[(+rcCcZj5J)mUp2likLE($jadM0mEMT5M +fadSpq-G*f,ASh!$l6)#-a[SRKZI5aPl039dIK'AeK!Gj)m&"G$,5dm"iKSPcZP" +[!2(GZ9IFVYV)&+ii5)P(+i1$)f-%8B""6e5q!X2Q61DHL5JXE%QhIMijdC@9k09 +CI2G"(8SLh4A2JD@#QU(dLQ2I++1`bZMp,(80dUjN5D8IG*[-%QPEa"3h48QMp2d +)@*kcVT&m,5`BQ3rKMLT*bRf@+M3mZ++iZR-F2!fR`fJJm*k+[bFD#*4P4Cm#4Nm +2J52+Bq"+k2S5)5(X*G&4h89TVF1PD+*himJ9V$0pP%TUT,jTmGj(A1j'F)F%,VK +(633hrY4k#V`HR[6arMG#+'%SqR9F`Z%2kAT888dPh`D5llQKlESrc(KTqTB"%0# +!S02d[XDA25"TfVKS2)Glmdp66ciJ``4,U[)$KN!!'L8A-pSMZk+jhH9RhSUP +k,i[Dr+)X$'1Hid)*+##@kR9IFlUjhE3V`,NT!A1l`FqB95qZ!aM[QTVkj)b53P@ +RAFqN+qCk)V#$RrHpX@5@'B`jGp,l(%4)D5)i4IS-0L$+Z"h@%V4Z5-`1Zl*Gd5M +20"S5@K4pC1-Pl0)1N50K[SJmTQ)mk1PQG2Bk@C%k1R'LjLD#Kac-f5%[8-V9D25 +9YQ8Q(HJ3dXppQJKp9bjS)-pXM-a4dEYc%LG4K&)'jD$d3-`NYUba)k'81(-DTZC +"q`U(Ip`rpL'4kQ6+X$`b*jcXLi%Idk%eUj9UGP(!MqVE9Ui%I,XUhE9P@jl)BRE +fe8GUB$J@[VP&L@`G0"`ZXTMqrY9"fXGB`m`mSR#aY@F'f9aT`DI,,'!G![p,E)S +HBb`VV'RXQGiCPrpf1TKqZ(R!0mUL(2H[9jJ-lYC"6V(epCCd&2AjjH-"ICp-E@3 +MIVA$+qjPjFImp(EEbc1HjCa(D31TB[SLpb,T+irqmE&)35ZfmDNYDXr(&M"Jc"8 +jKMVB#FfUb%Qm0&+qIddh)-FafRUZGq$Djb""IE+%FJ#2rPV[IJlV[*@--1#fBQf +#J9I#H4YVBd8*#+5G0YE5i#5`(F,US*&&L&dk[&&kTmpi298DeAeI)M,6'G'Zdm% +e%QERlY[`0V,B)I`JSE+rm1dU,[Bp$krq0VGV,S8q#($&LV4"LC0Iap*Zk03cPE) +(RUZajpT01SSYaYDE(hDQ!GjP'GIM,mECj@TdT"VBf&ISakfE2l8-$lj9rM5iJmG +2'`Z,j(4Tp2fd$b$'fG$%HSa(Y'0+k'$'D"Lk0'-ik'*"4L38B*%5eb1Vd0r+j(6 +k#4+j&fAa9AQQ*hN0SRVbKh#H[+(aPrMlcdA,D-rS!q"'MAqK%4`G-,%d+&8D&#M +0#K1(LC81KS"-ZV9-V`UCBHQkYkDbQ[ldd5qCCdc&-N$cTMPkPXCRkUTd+4bIL42 +G(HHe5%cRfpREdDlIPS2HDFp$QT[qG`8VEk1r%STH%`C+8`XcY)hjPe"VMS+A8`( +PmJJq32ZG39d(+SVMmZT2SCcMYr33FF5(M#l(KFd%Q,`8S+C24a""iiDGqB@4%a- +fJpGaX6"-l0)RLfmMX(2VSFFj)[U'ILkI8`DU#9Rpr$@c3$Ir@''dm2Zqe)chMLj +IMcNUh6FJ&A$3b35)G1p!6[ifcAeS(f`M*k2X)T!!9hilS"0f!RK0)1JD3G*US06 +($U1K2VjcKQZecGUPi&$Ic$DlP06#hdD6+,cpUeT-G9@EPPdb"VK*F$G8cP*m$,T +FBU#Be--1rZIapbGh-E5B'q#YHi1J5f'qYR5p)C`PjBlIh+H"UV6Gdq*NS!3jC3( +2Z0[VQbIVf5IT(&6@rjp0GTAc')Y&q$&62iMeedq`1[i811Lb'$NUD6`"rAQbNdX +[-NeE,)f&KSF[Bi[2CjQJ-c,Q6)DXCkAq9-Qj5CPb&4f5IHG5CIm%Nk$6bF&[5d2 +Kf%KBaaj(&SCE3EUNXUHa5KbfM8HZ#5JQ3`e*m2%N5@pH2S4maR8Z+N%2*83L$`R +#m1VNqVQL+'#QN8#*"FeL(EAU#9N5Y,DeGi$+5S02*3fp,-hbiep4)c)6@rKN5NN +H(4l)YEq'l4C2CBj3%fb+rLp,6ePDRZ(DXReXq,K&0pSmPpdlQ5#DjAkh([+"Ek` +@rSH1"IIK1dD8GThZeZbNJUe'MXkUZaYK@jjN'"Df-X#EQVEJ#q38**!!SYi2L90 +9B4*+'%-je$RDZ2e8G3b9AGRIpa3kHQkY&)Y#mbUE1bV@F1L%!CI%q8q0-"Ejj&# +aP(6ep9@Ze#ZGGJT%eD0aLrXZGG-8%1kl%[%SI#05ET)I2l%RD3ljGAVA,SB8)TP +)1SmIK'E3F0Nc$j)&5YAK46*Q#@&!k3L@eemAG-JqUD[L23Ck[XV&H(cH82KeFM0 +b-EGddKJj'QZaqdYma++E`V'(!VCblaRQkBVq0X,+HSXUDjSkMR%"L6'#N!#&!,h +$YiFjAZ*VYE1TX4`QHUY+1@`L55)B8NN,'0S(KTMACTA2$5jZA`DBCiD8cpM6P2J +dMl'&ZKNQ&TNp*CCA'Zp0bKi(ilk+R`80E#($BT*+6abQ!c[ild)YkIRU,'i1$[P +04B+Br(HaY`L3!%@9(Q*)H+rKLYI'hF5Zr(Hfh9)$B#Mr(I-P,34d[AIM[U,ZjU# +KaTF8'*X%R9U$ITR41-()Z5`0Sh%1X+eQd3LV(99r@Q[D8G!bhe&YhbI@-$-4aiA +*ihVZ!L3@,%BPe3`qFe-U5`C-PHa`KSiB'-FKJbB0X8,D5`$Km'A52$+k[%LRkr5 +9f-TkR2Yr`Cr#Y'2-iFE*L8892A1IfXrJkNRCeh9!hrU(qKS95($6AC+PBD`B)`% +ZLXU'FUm8c!#C[#*[f-[ASea%cTUrA(qG5G*deLmVM+"4Df[qGL8Q!SpP*Pl&iX6 +)fhkD+iq+b0kl$d9apNiP44DMMF6`beU3!!6-&Y&PD%#,#mT@JZD5V2Qj",dej!D +rd9amR0TVY3c'bZY@8Z[hS)I6B`(S+dM1IU1rSY6CIYFQ,&USkQSTXPD,bNGPJTN +T#A(lZ(3N+8AT*Xj8'F0Abb'9aZE2q'Ca0A0+!RC!*QifcCfAN4C)`Siel294@[, +SFDLJI,EZ4-E9)Q#SGT+kUVfj2(h'"&4Ne",NkjEE(IG'fUrm"jN2hISViI`,ri2 +0J6N*l+e95G`0k1$'`Ha`Pm-L9"GMbjqFb'`bqB)[X6[K-jHQRKRV3pV-!4$rB"[ +k3r9L[-KqNQ$IfYqm6*bKq[&@LK(e6F&[hDS%Gmk*RFhDdA-f'41qHL5X9*%JAQL +H)e%9'ZDU0FpRMiFjNQS)M*1d%IXbcJXfkqP&&YXZ1TPUUcbqMUV*L"[5M1G$6Y6 +VRF2P6RqI4PY@p'6R4LU`*@5IGBU%9D,*apI$h%0c65-&I"D#e2CGQP@fNjQ#2*e +dYI`m[JE%R6J4qbcGUcUSfFrAT5rRR'358S[M#Z,Q9[mi*m'8De$aF%,B$I6e*9D +GN!#Sl,2aqKd@EGd@*)!G&N-$AL%ifM0XKJBG3UmYVd4LLdM(NNaiR"l`N!!a$S0 +YBT8L,0+RLJ8b+!Y$5U`8UPRD#8Qi)e5iTL2l,N%e&KTh9@#8SCE-Q#K,@PmPQTG +jLcM*k`GPDPL8XPdcT-""'!UeVMMXV6jkX5h+A$1kP-2CT94U8CXbP*6EJKP8rE% +VJl42p3Ha&L@q5*U%TiI'`AIDIbY4N!$jpUb![[FN"'Np(-N"@rM0e%LkeXmI8Yr +mjPEal**jEj8C`Ha4NU-I#fFpB)J6T4REcR2N&HF5"admKY%H3Xkh'Cq`V+PbKNi +BIlq1rcNlQ5`G6B1q-N5*M'2NZDpPlL2NB0I2&X6d68pE9@GQfkmS2l`*cS5M8@e +9q4&ZKM9'$Zr#cYA+')4d-DR`rKR*j5'8CGie5C1M-IUHX-N9jUc,@CXX2PA-1eM +*@0RP#,XN1$'F`8VJc$H`8R'l-GG+m)k!ZdpHHMVhUf5F('kfSh61bHqdR,RI`FE +T@@m0VI'NSm-Aa"&cUpkJLa4LB)TcRci%kd$(1@92TU1`XG*B[T!!#CHN!QAf3#b +Fp`6p$lrAf[Q4!b3TXf5&-M6e&9@YpL#Y)dfZ(XQR!fe'm6$+hqFL5SklkeAM-#$ +GCNDc4Vjb'@%%ZUT@MJMU[-)&6'IJP&6VRfqL)&#F%L'4YEBah-cSq*,9H$6)q1Y +3,*ZrRr9$lLI9L0rFrHNS#eh2DCdP0*Y#TE94dXhc`E,'ePECe9Na29fj%TH2&!c +Er93*@V2p@9RJDAF+VCUq810La%kI%'*Z4Dh#+CdJS8VUSj2HXZlBbXia5'3L0ZY +QU*)eG%Y,Lr`4r#(KUZF4*PYR*8",Y0TF&2+'L!b8')f3!&%$h%!JlQ)IFfBJa-( +8a#(l#eaKb89,&Tk9[SQ'UJ`-V%aZ*[m&[Jrbk'#1e2CcN@lk#6T*b,GUD#1Vdl( +%GR`+[1RKpc!3A@9N)1LLp1!edLhF"[caEX!dc9jk6`!MpfLjY5#43JUj$#pe65' +&id%H3h'CBpl[#'%5b@XHiii-CUFUlfM&*f1)hDBcl)IX`HTJNlEX*Hd3@,&RD'& +&""r4U533I+*"Te6UTLbB$D8lVhXa-D2cCq$aX,DG*)D'GN)k$5aF0S*-#2m4HRT +X*Pik,(df"5fqMYp3jA1&#VmmjFf4LZ)*EYf*6Z9TT&46F819X!HIKHQD-P(1jDQ +b-6!0IZ[`@A9lPMTRVp0h8i1$$JTVd4JG$'lLK[PAdQ,raXITaRl)RliRld"++ip +h6p4MS,[NIR[4Xf,pM*@LjQf,IH[ce2CCjN!cVAkk1")RYMpb494X$KljJj!!Lj[ +3pPQT`E+4T*c38G0)GR18e#R)GXIZMGM-h`,T+hd"Sb)%D(%T&TK$DN6fa4dEh+D +r'1pI@pLS[Z%e6)rGdYV6ACT")X##-4Hf38APm$NpBDBN+i+5-HUk'XCe-h03`d& +GXIT41,R1@p0Hlj65dELZaL0BhZq,E)*iK2``5BZR1Yl1GQ)Hr6Q`44#e4q#8ZU' +#VNk%-L"MKQ4"dB&'19lZPRHT9#"i#,C!a*l(k5%#ZJN3JNErAE(kUD44"QEhe#D +[%ATeQBIJKXMlL5S+,ErRcX2Id`Z$d0&ier9"LK&1UjTL8!aq#pF&STPIX(-E(kC +@FJNkLpBcR3BRQ6RaIpMk(`Q%j@TaGFRd8iZ[Ff54D@qM1!kjG8-XPBCkRVCr5Q4 +Y!DiRd3m`"2S3%Kq5(q-2d1AddkF)dDqd2KaEdMP+C-h"+[AaX[TU@e4A)[e,GFC ++`dUiG0C6eYJ[m[3h0#CQ9A8$jN%A0QCYIbb**l@mVC+Pde5-YMmC4*Qi@pm-dLq +KGL)[5)-D1[cd4d-Am1X#!Q$!3f+U#ZfYhLCffcQ+Y1acX0bZFKKeU@6eJjqSdl, +(eB+5XBkBR,RkRcYB8&G$ZNaJ$0F0l+1kI&AbKaeACTf3!+jq`&2U%Ja!-GALVjB +al8!GM5@`b$8Jq4SrfK4UB1[U#&m$LIbm$M"3$*F3*GmKP%K-BJrpqVCZ42iAVK[ +GHLe0qdZ`"bN2,CXdBc3C+F65)SmD%8kLD!jrCp0KRRdf'%IbE""TqVB!drNf!12 +GX(1Y3m2c'YeHXN-$i8(#JS-&**[D8p9TE2"69K6f0LIiYpakZ1T`Fed&mYl`L%1 +Kl2@&5$h1IU2@+MedMhkMfLdKl&kkk(1-l(NPm)Rb5QX(04rjd&*A(IkT'c%1DUY +*`069G@D24i+DkXA4I98HeC*e'$QVYqCTTfG@Hp5QNajb3a8erUN`EDFLeIT*,95 +64-9"3iiih$`63E[X5jD3!*(,PJ6#f6P!9-TE"68`*CJTUY,pe%b`Fe*p)L9#333 +ETU)(2`U)DGHl)QZTpq$QT#5D89(Dae05X'X&G6[+D24a%N'*ab!*[MCbaS%$F5d +Sdb[k2j3Qij!!q-V3@e&FArqLM9f"Lf"+h&kh'EYFVh9ajN2hf$1*`9b2N!#h[%e +I%C*R,ilC4fhec`Q,FqcF2#6D2(4H5q5THeP)4[5`'GZDK3b18-Ujhb,Ij3)cP[4 +XH`S#hFYl%"TDhX9fR%%2RBqF0jrH5`k6P-$I*Q45hDUi$NBeaKeBirU5Y1ec0)L +&rcU!ep8'[bJh9h`S[9ferMEr2-9faqk(RKT""mA'i'ajSqPbNrNkhdDIaPJVqEE +9r)!ZK(iV*IP*E`5#-&&Q@rJBr-"L,5F2eJ0+Q0e-S#3rAJLq5KR*RCMph3frpU1 +eDH5ESiNhlR%Qq$MEaF#jrFLQRhUDFe+aJ#IIJLLpFr(-l,"G$JT5hrV4fTUZ'Ya +ErfCMQ!Tp*H)G*%VVQV`8YEj3(%[I[idef("Ie"!l'L#!CI[#cpiR(lm&GEIpjIe +,iqQrJ#65JC6e1NXNX04VBINd&$`,R34Dm4M3@e#J0%SqRP[Xk,8`&qe&83ND$Mr +ml#*4i,"bFKEk!NHA@+@f8h*H6qHrjfQ%3Qj+0k4[Z2#Vp'dNj#KZYA*a*@,)'r9 +3jA'X4M"bdI1Ga$`XEAq21m#jVmMmmXpPD9505R!&eGmLAAEK&CG(`l5Yd$$c&5d +IMZiKB'64Mq8(YlANd$%BDQerXC13!"-Vd`NSCE3'(&j0kTT88,UX&GlI+!4eH$N +HCMM2bNqCaiNRUq636M#`rIdIJ*pfU54N%!'I6ZJ*JV*VU)''8BaCU0KaHTEl,X6 +BVkSG*2C4VXI#"&![e-MJXIPFFpR"Bk[jBrGS)hLML0!MM,HM%milCd8U1%reIml +JjLjdr#V54CMD(bi*#VP-"UCXY`,QcTT5*@T&KJ+1jXdk82dH@[qT69*2dY)Z*9q +*lPM`d!ei@$cTk!ZEf!JecTfB&&"rH1Nk'BZE++Q)Gcda0!Sj@+[Q!e+)!)N$M&! +BE#X@K25PAB`C!!0GK1A1R(-8DFH#ma!mY@bDIFkHR$d(*JU-P['kFCC#D)h0Qm$ +"(cGh9!)qEJ!LN!$Zi,qm$HNZBEQhM6&*$pp0)TFE4V+GkQ0Sb2+@@5"pkk9(!+k +Ap'M'0CK'5Fa"G0Mq%A$P8Vm0ZU-#V@2BcN2h!PpqhT&fEUEK'495@YDQGK+i-lC +bk(L"8IIbif`BV!4A0K)iJ"S)pSKcUf8A[,Fl%%-"X"$cPK)BIc#kN3-jYE*U2Fh +$fL+P,0fH%e1%HN6&%XBrQEHrcLcd$fN-9i#TEEMF!4H!52lb8-Zi'5#"M()*X6* +XC@pZDZ(0K6@bjkZ%qdG9pF2efmCRd'Ee4*G8*VaAN!"#AMA9c*+&%[H$m0Q5F"R +6i2`k(ARri!9+dGT!ZU9Hd#Mb!3&6b1@#aM#If4K"rK%HAQ3*+PfYr#Cc,([NNej +L[l3r8a4J)PEIb`%m3NS6U5a)NP5@R#m1S6fqIf5!`*2l)8@qV)"#cPEq)r9!%2" +J&JNUr235CcS#"5Y[jP$I%i2RDd*fb%djKr+3!$@kNkdJ#JNi*!%*%%*44#8JN@N +%UN%8%Uk),XSKGS*&driE&b2pGL88SHH!dLCH6*i#2RF"ZBd`Xq*VT%MFISk59Kq +3!!D@KrJ%(b12m!Cp8Dbl%JZKqB"T'(k%J+KqC(#4XQCVAa$Q2LKrSeib#$C2(MY +5r$ae-U3(U@KR+'!q'NJp223rdASXe4'erD#3!!'qQ"*8$$#@8`Zkm`bq[JZ`[,Q +GTEq*4fTCBZm@46Y48@hHckN%*6)BJ&cc(DB-IQG$ARj(l*DdKj6MmbEN#A@62,J +Qc-cCb6bi2bmFrZmF3JB+lMC@HU&b(P[#H2,33ECq(Q(68IMp+Y4+ZN'QD1eIfHJ +r(K+FATkHJr()c*314"VRk6"#PRl[8CadK'IHkJA2Q8GUphX2aaVdpJZ`eclHcYk +0Ib-AdNEA'HecNM)Yp'lMUI40X*A1`4fCj-mBRL&6Z1a*9#A8NrCC)dp%S5(MU6i +T5TJT(rM4d"qQ*5*5@dbC`b6[*5GPPkM&2VPD,a0QMUDbHH@MbD'$0NMj[69D!*V +!%eXECdddJSPfe$VN*+Z9aIq,RA(FbJXC5fQ8TJB)KQZ5K9dpDTm"JGEF"0`[93D +d9ccNdb,R9-qkM1-j1aB9QYBhaUBf$XJ'pb1mDh+3!!Z3!2Fd3,[8hhSk#Jdm--l +e)j6mUY02*DXYdi6LH&"Gc&3QS02(6P[j"6Bl@JcjjB)*D@`5F(RfQk9m#GNip25 +pNiZl"2)ehFl8%ElhG'TQDBhj0(,0dZfSFkNk*aq4j*8jiQ@3!)-pET[A,ER*)8( +e'HS,kVhGk'5LhmT450"@RUkZ)GmVcei-T!%%'"([C(-@9lJT,8,,fl'QrcdI`Yd +ZH#+M3L6M-G86[T5TdLN6&D@`A0!DlYjqNNbFp3CMQ)-&04fBMbm'Q#`a$p)$I4$ +pIBkISI*KqR&#mEd0*Se1[#C[I,Gm*Qj@r11Pb9LhXmL!2EF(N[9SHH"A0QepKNE +U+DlU*BiTZ&*!*XD"A16`5"FC!K*ir1Y8CeI$A56a3mp0%haQ@!3#GUQ8JC(%X8P +-q-0pp$MUk4qB[hUD3!Em+('edMr%95QN!'A!dQj+EN4([`!6lfAcP[fbGr+-NlE +8*NA1dd5cX*P+Vqh*1EN[9,I")$Vj"'RcmA*GBIfFP*A0bXaCb$b#0MA1h-SGiLb +0VY1a8JLRHTYlVf1GZ@lG6I93R-p*Tc282HeFM%bd6CddVID5*PCI,5qhLC@*Xlr +Xc*kE))3`MT2`1@ZpCGd1$PUNBP*Ik09@PE$liNUp8P!Z9(Ycle$hX@C[Y)TGPEk +&c*qh#aeEpX6+hkMmlhUZ3RHp-L,,5q9Pp[k(aeFIIpP%k%6Kb(K(a)$0djVdpP, +TC-M35%A5[M1m3QP6e)%"L$4Rj5%DPF#V(rXUfIK0`'AGQR"3MkPV(lJBqrEiiYd +-fk0Xbr9'PmTR9ZY!4a3(0!4T-43FjU&5ET3*1EN98,la+(&!Ne6cm0[M49K5R5J +5ET3(`M6&!FmdMQE`Me53!%dEXTQq*m"Y$Ij#FJ[%@mVj(T635Y0H6b2AHQZfTKT +TE8ae0+c8P2BfQNCU5TSr8`(0&dK0%2IpL69-`GejJTLG5ceR0A4ILN`Qa9m5jm@ +RjV'I$DD[RUifP,Tb*5Al2`4#1b5SZm2LX,%cpH0@DmT'`f4PdNVMS0A9p@a%Pk, +NM+ZaF@Cr&Ab*d-@HF9+EZXh)dAH8f&LG$9p1pbDENP[jVR0fY0H)P*qM)34(#!h +$1N3L&%9K'b!PemSZHR5j`E"*f@"[LD6#kc&fFeQ-9Ii-j64qUJif1VEfi9B154q ++091##HHUQkGi(1KSJ'KMGSVm#k&MT1,&U8CpL8@h9-#,r4iV!`5HpT%eD'UY66@ +"J[2[r2kZ0Li8aC)KS!5jUN)25dEpml&BTM4$q6k)[PDN"$)c41@!"fT&!iR"@DM +c58b2-j1$`GM8*Mp@(fVrlh6[Td4U[D[R`4qp05aV655`a,%)N3$T(LiFHl22'BU ++(1f&%p03F*!!m5VUljPCqDZ[mFGPXDUU)c&MBdeGGJ1pYJG68eKGNS%&eK%*(eq +TE8K!m*if(d1P1jT53PSerDpSRYdVVQS6Xk2PB%,1U#b#6!Dl`5VTLT3YV+f#l'I +`X,5blQ#NU#NVIr,$)$#UG+R"T)@mCVi(-G)&MF6JB*AGQT43HeXrVJ[,M9B5IS+ +b''0fEhF8MD6@$XDB`b-U8qLP9Fid$29T9lR$YS#i5qr"1eQdleGV-EDhlCH`%Zl +)qGZK,cidZ2[VEb48AGa3$rB2441#89%D4Ff`[!4IQH%AIK&JmfEL6,[,U$#DJNh +Uk1ZLD24Hc&-5@&'@"UrjmEL90DLN0HUM54*ABNe%Zp[di88,b9--""d8I1(e,J[ +3&IaR-Grj6ACY'+6+-Ac*@'LH9")ISd+Ck6*ULhR4`iG(KfT&HK)S),Dr8LBUbGX +,0@R-lfqcQ+k5DkZ#2kZ4S2DrKXiNqBRAef-K,r,P2FKjmR*339FLHmVkkDqd11d +%6$R"G3HcmZcaRfA2eXaLSNpE6*@56[TIA'J$#1,ZDCKq`#Sm#LQm"9f8+Z5QYpG +[VaM!J-`cB*j9VIBJ0pY[XJ8rc3@RB6N2HXq9cHc4-E+3!%pD6+q59T[*aX3kJRS +5MHT%FdC2V`8UZVFIVK+)5h3PbB2#I8$l8,MqL%`&[VGe1*f,EfMFBj+U`X62#!M +ldFHCXJFRShpbrJT2bDQ$@3AdkqRQRmNJ!N-'bSNUjDh$2ep0,q[T904l"RC%)"% +Y!5H$id-1UJHDLbrTKQ8PEfL))h&`P""-h'rZpCF5NdVEfRBkQ#%[G%aU#Z8Rc`D +D*p@X2'rZJe,HC$rYp*%(MKXQ3"0`2$LPF5a+UbHI6Z)88a@-Nihpm9I&$%m-bjC +NbRm)1E2MG)*HZLMQ+-fE%l#(e*Re)r!ZMarCc6dB6*IA%Qj**%Q*&RRLI,Qp*[[ +-jG&`fSKH4EjRHD5qmSVL8*'!k5BKlf0m#GkTh+H4!&1[68kP81N,!)b$lNh'GNb +IIb#8Yr`G33(Z1Bc609Cr6@@BcMdMe[l`M5EUhrCeJ5)@AAQ8B9Gi5p,V"GEIF'X +TrYJ3Hrrm,IF@r,6b2EDFYq8602IGD"LmF'#QXP2d@A%mPQZ3!*a,"%#GBaMP*(P +FV(PFmqaPHCAh21l'FZHGBhF#L2bj52a)-*Q'",19cc8Xj$9*!45-BVX5IdaM!+4 +`dREq*L[-"525DmLl)(,)#lY458--43jdkclc('5Td[mI1eZ[fG-'+##h`A3TcY4 +ZZ($*h-*b(ll(l'*e$q&M**L9*Pd@24*L4*Pd*aU@rLV,-@-!p4(3cGhA-DRa)ZK +*QR2,LK*UN!"0hHhk'C[L%"Q+6kT`Qq4pmBpabGeLKcThrPlUf$[R#T!![Y&$-2i +D03QPm6&#+)K-[jFE1V#cHVJDC+SP$RF`kdD(f()Yj)+TDKA,qPM4b)0PP34UPm9 +Q*0YAK`icEQ-8aDPa(QFAdYJr$PbcjIUb$D8h9Q6P54#6G`Sd&jUlbMJ(CTaXl9b +1#k%J8UBQ@[e'BRRa0dj$!fFSL,QK+S"LS5ci83dfK4+M"rPi@GUfBh&2K[$+Q'@ +%)r+U$2jY`@FN%Se-aFR8rCIrQA5NP%)&V#+&-a0(#Lq-eQ%L+FlCR0Fe2%kB[5q +H+9rSem0`,LXq'L`QD*%f,ITHBb0@RVNmb(QeG#H&b1f2iCMfjk4E8-[l1mBj6H* +h%QRL8LQfj$cliT-B)hadfBQjMBrJJSI,6Y5QdZ24%,,(#5riCMh-$T1V[0"A3E* +#a,Jb(Qd9app%EM&fTZNH#R!JXJ8P(QUm5aVrTqJqb*5&`e(VQ35+h28QI(ElPBE +p6U88KBhc",9%["-m3)Zj(9J31`-&hCUY4Vql0+$qpmC"!L6CCk5Bd),NY%FicU1 +H@L1Ei4DHEY*GI"ek8+1iK6D56U5DTQ!kZq82G4F)ZCaBQCaG56GI�"KM0iQj! +!QlSbe)09V++irlebP4QX%0R0G3f$hM'JMAXHd6lSEjUhIa6"5@#3!2"-K%XdcX! +QJMNralq0[CTYJ(D`PLB)rEY#(Y@XSP(fX2m!8hBf"65jZhRdQM6[NH6e9qcTmNX +i*!6H)1LmR!L18E3lSe$TeA65m2d!0ISIkc[8Y[`[S5r'Yr*[*SZ'T3"Jm"q!m"p +hkq2aYI@b'"NVlN%YJ2*`#6QU[HL@GAjhceFKr!H@LC9k4*1h4Bh3Yi[k,fh2SjN +rQ$K'XIa",qc3MqUHN!!')eKp"%j#T-"[VJ,6M[#!6B+Fd6(6VT*A@B4MS$4HNkZ +@A#SP'k&'p6&mQj)l*'*3NMApMp(qIQFf0SPK")Bck8[aZNPTEMbdG9mhZrGL5Ij +B)R3-(%YrUD3PJL+`R1RCD*JM(BdP$TirED'A`Fe"Yr&aX[3!4iINBhLHj&PTI1a +-lJljJZJYY[0cL&#)%$dG,d&0)h6m[3amG!"dYr5Fbdj1dUBUQ%2HP%dmIjR@kP2 +Gp+hq#'$S)Xl3RB+ViJ+3!-%HU9B2V8Vm!Cd-[S,k"NI"(dekRDa6+2#b@LbB,5! +,5)%A5#2"b3PF2"(af#Vj5@`mGJXV1IPR)**8-ZdRKi*$SCH,)rP@`C+kHEKMpY8 +-$ZJPX2(h[&mk(Xm)FKA#LCRhBHIPFAeZ,JP+($arGk'mp*KilrB`I4bT4SUj3AM +q2jFr"*3G&eZRMjD#l81RZRi9dm*eGJqQTf,P!qLC2V02+8X&jXC2I8eAIHXcm'& +J['qNU[TrdCq$XS-(qM8cq9aq3J[9M(!p)pERi,a"GLCGfX6(bqGcH6aA'qV@dA` +T"dQ3!2@ip&JT0!Ufi(LihcIR,F`K-m6J(2p*bq`TVpLqG"KX(0I9P*F&Z(ZSXM3 +lU,dP0q'-jd%6pR-S[K8QY*fF+DNXQa"4Qa!&f9T[XdY9CD-afkDZTkR2J4RY(U0 +(T3)f&MC@&5"'iUl(54!)hZLcd4!MkG$8Ci#)lTkHcVG#"%lA9b%%GRV+RVN#0K@ +J5J4"UpC*RJfeNZ32@-K+eN'N+*(55YC(k92#KPCbQNCE$b[%cGT633deM"Jm2(G +N"@B*&b[h!C3N!%K(B+,Kf[iB@*NrZY))2r1T`I5c0"+cPm[-@m5Xj0hQ,,!0KiY +f",$a5PC6AB6D8X5%UaZKmQMh%3`-JNVleJjT(KVkV`hPA6b-Dc-fiZ`Uj%-S$JU +"#2$+jq"N*%&iPk$T,c&JZILiF&Aq#5@!FiDaN5-P)A@6k##aJ@&Um2D&U65&U@[ +m%N&fYC%0AAK'DPI0P4-BXU!edVT$,6M&JZDCk9LhY4@-2(5I&f%@8c9U@mPiYl8 +cCS,R%T+FY[e60TS)qGh*!PRHN[Q$[P$(4C!!mM'ddIiZ0QGJJT,Ab*RDZ3YMCNm +D!rS"f*5!*5##4FkI"%bIk%qAR5GBRc5[%lIi1R!6mmlEN4A6fe0+cN2`9FIE*k' +*2#@m&j)G1N5(4,`K0eC%!$U6J[0Y(!j+)1(r5Fc+H[64p(klT)*1#)%dY"H4#*A +p'8J[XlRi-#**-d*SV@dI64pYG%4T"kAYi,r4CbABN5,&`Rh@)dmVC-C6T-Ap-%4 +&FXCDfQAXEFG6D88fNi,aEIQ6(-3L1!jfLh5+35c%@YT1V[$%DUlXA!d5Aq`NdHC +"+fh4"jH'SpGRMYR52+IG!p*%ekb45@G6(XbmHQH2K50M(U,4lf&T$IIQTSrarc2 +B5Zi*AGl(8NTe*2JkP!SP(X*5S*5UL4Fl6Z8LDH8qZfr93fPKGSP'#8RK0dJaK0Z +5rXR4F`V$B-%*@GM34lSU[epSk5K`Q#JPZ(f9Idq@aGGH)P#C-K21Mc9iSjciq2E +61@aG0p14qH9J1133CdGAq*4dP!(8K`k@[[3GAQ,dMdGFcMKap4"p(N0JF@B%6FI +JT2JIp@FK4Fk(ll1!"[X+0b9PSk-J9)4,5LjaZ$)&B*Dh(f-AUR[-ErLCm1LdP2, +4[NT[`Tj50qfQqfRN)hlUEkN3#Kcm(MD'6PmkD59Y4I$NIRZNG4FcV2m`5-T`N!$ +5GmM0C0c58S"[Shia,j5j23hq9*VAEae9)i1DZHKTMK+c@6`@(P1+q5M35-lTj6K +8dT1LUGCaj6K@-$EbE6bR&YZUc@6Qm2+F*0A"$Ba6VQNbFhR4IN(ZV#Dq5qG`'GJ +Zm[P#De+ITS)1VL6P&c*hUBPFRm"5emC6Q%kQXY5CAp+D88Df55p1rNLAb,,a*b* +4i1mi3UN4Ea`jbSk5aJbf,Lb-YHIKip0q%Y,C@F55BbJ`4@DNUVANbB%Vr5Z*QB, +aJ64LRC!!bpVJTUVX+h2'#KUD+ire[X9I+Z9-Fl8bC3CLaqRMU'3Lp2Pl@EZZ#N5 +`G,'"&d0M"ErTl(1`ANb0[kbZZ+-QMLcXVVV1UVV',LCAA@0P99FA#5ZZUY2CemA +UjAA90RC9X@APGG6eeIT)[6bZZdGRC@C3d#L[XiXTf1TKq"8+hGM"-6N1iPCqdJU +llf*H`3lSfd[#XBm&VM&rC$D*HhBU#VVHaViH,$hp0)GM2`prBb)2H-$h1Q+#'f8 +Q`D%dVMSIJLbe$MU[$Pap(`3FFlF8A!UL#*0r!"1%KG[T)4,Tc+HrK&P-2jN2Ihi +#UD8eAlDD4$b2eAlHaad&jb2fARlBFmfGC,8A-f@0ap&2Bh*j'HRmU1L(Q1AJT*H +XVjXZRj'jGLI##LZ1IM6M)(U$Z1IdAXT#K#(AFl6(Z03b9SZCVk$(6p*Q-RN@)3) +0GMVi6GDrSc8DHN5rhr3HdHA1Q[S-Xl20GJT)1,a$i3FG*$jkS9ZMJQYZS4$[%9Y +YmU(DjU(I!U`*ZHEe'Q&BeMYT0I3C1MRk,+ieaS"(,ZUU5d22AIkqP85HcCIl[$T +%[k#*AKie9fSZCVN4(-ccAC!!L%R$r4k2ZGpJcc+1a,1eq-b16bdqKHp+!3!IfIC +11GpLTa,#FI@Mf5290HbqPpP)f)pMQCl(d@0bDSiIJVSj1mNS"2DTeC[9(m2G*+k +H4JMZbVX+Pm&iQ0*$AdT5dYqRXBj%`j[K%PlkH&iF@lNPD4`9e`8VI*!!YqR&qZj +'0bb0#'(khBdRFi-M,1*+@"Bj'"![L00,(4C-LQr@GB'fbpVBVfqPr(Rh(3jjBAD +95j!!5r"ZAeca#2Z"V0X-%5),2F"+m%X59*[%&mN)hXpMR88#0`F9I,'2i5DR!2+ +B#('PmL3GlKcPLGL`UAbiF9+VMm9)GCbC5Q*8Ae`AI)rC,IE$mEZ+cD-K8RmYMFI +NCma#EV(c*!G+!*b#i"SGjm&&F&-q,3DJhEi5iIN+$-ThcjI%`r04HG,(XPJVD,E +a[[c40[l+IbZ6*rGYIFbJG2BZNaD"d6-PfRTqJNllPDDlB6jDZ8`R6ddI1p-PI(d +rGUrXMH,'m95l+cq4BA@hkSP(r5F[[48dMK,cqd5)bZqE'm8Z8mlK,cKEc`U8X8m +kKRBYc4IE%jl46G2"6R0&*f[P0[Lkk4jNjLrY0'@@3F-KdZpF&Li*#A,UA"%qqJr +[03Af#r4e"1qcl&rJkZ1S*rh2Dq1HS*f3!q2kr-eKdac8Z6khf0ZX)FB2##$D2h) +06%MRp5,![kN%Ul3+KY0"HU(9k#9RV5HeB04!'dNpD!9H&%Y)$NSSe)JYT*P1ml$ +`l5TNCFaYk,5F,Ae%VDH[36Q%JRCbJR+,5F2Ae(6c+KL#e"MX9"3BlEH[Jj+Jaf% +NU,5)j,qQ`rTX3QjYTkr(eq%ZR)imcG+$(I"ak$(I&VkU6h'XU*!!40$(9rV4D3a +i#'fk5d%'PR6)6(TS)Lr5@1MIE"Z'K(MY#,KS4mM!L1CZjrE(B&S440#+pJ4(hpS +KJ`)M`)Y'"%IS'K'`B%G$p$!L9ic!LlGNd)fl!Mp#)J"%amE!M#A,!LDL-#,rM3) +ZNElHVjM3K#!#-!L%!4%4J!)PjCJ4I8A"!LFD%C9S4RQK(M0#29D%FKJ4qU4D%CY +J4IX-d)S'K&Dd)iE3MkQK(hY#1F`)kP25qJ4GfK&qD%B9S4-Y#2QB%ApTK%fM3La +B%AA6Y#2i-#*&V3G#Ma!%5Z4D%0Fad@YB%AEMX#1N6dhJ4q6ffL'bB%IPMf"&hdV +!MmfBD%0C#m0HBk92N!"S%0I!kC+bD"#2i!4dkI-9!KUBIR5""!KV-ATVQ1SDFG3 +dB[H+D%0AL)e+&N))%*)!!LkI%`)N'`BA9T3[Zr3)e63Mq,!L1E!"(0GK(01%Z-U +AlB*%#*%Z4*!!krj8m$jjX5j3MV6+)$hF"C(Vr,c(fE2aB)1[q3"2h36@TeHXP1f +lEYG2TE24KYCfHPdrDkV@DlCEI[Gci(Jq%#AJq$i(I@Z[lM6D,3e@Gl1Pbf4af-R +FC2d&&Q1dTiYGT1if'hhHrmcLqKk2TA&ak2RmAKH6EGjVqhdGC6jV+j'IQX0K-(J +qYkqEap(Q1dUUrYHkfqmmVcq0aq4l(XHakr(pEdr1mR`VA@kLZcfET++Ia1%`29G +9J-&KT[(C+NcF@ceHehINqIk[XHclIZHllR*j2XqVaI)hHfeQPd02QXTMZ``Q"[p +rkV!GCLFAMU,-8eGfZZllIm1iir)pVhIH&UpcNHP`2%llBGYBaFjQ-Kf)9AkrAqC +`hBKA5e9Ph'fh[PHGkIVHalR[F[hreqrlRVF2ar"YGCTV#VcH6aH'`A9K9JHYa(B +ic(jA1D(8E$`2(i2RmEeq6bJUq$PHakAQElFl1ddYE8jQJQX*J1T[er`(@GGeme1 +d1BUG&UpaEH6j[SHTl2Zqpm(-jR,p[e1*'hZi4`(DC+F`dceGr[r9i,#BA$iV'dH +Ed'Sf@khhNqEk2(p[PHrm2`rVphMqK`Gri&Vh@TXUV,ilXHZ`@!kVUjM"B2VF418 +1AU0&V0[Zr&mVLHRkrYqpc2LjR[HaaZ,jALERDkc6k$XXMLm2Jm$J3T`H%`de2C2 +Xp"fZ`h(Jq,jIRqVl2+#VPqhk`L[KGlXV5bU+6(cH'`Fc-B,"61#kh$cQ2T+LbY0 +PhRJlrKHPaq6m(`mchq6b10jhPq0i@ieqSV1cbFmVp'#Q*R"i@DRmRQp$TpCY1ph +XELHRl([IVr@&AUHK`EHflrDGaBe1Cb-lLF0e[@pC-K9LCh)dXA4kRZVA`"32@j2 +[HrlhYmMeI5iRPlr`Y[h0R&cH8adhf(ApGK"3KP-IPkQ[dfVfIIH('iR'pVPHpb[ +EpMMqRaH"j'plhAkI3dfAb'-a@*kr#i2"B,#BEXFGPFj@D28klEl[a[-p(NHjb[G +#VMHI`[*hfkfHTX-pf9(36[BiK&X4[U,XXp@k6Z0MheYj2%p6f2Ej2YHakrUHK`q +"iqph'YdfKTXaNXGLqa`r@pCeJpm*rRBZLlC&Ui(SmIfIDpRf"2r2iIPq0i'ce9P +&l5Nb10aIBGGeQ$kcVH[l('dHDTkc4p[X4[r1p6erC#Ver8Z22i9[[0[VG4Ae"'R +MCX4A"i6VX6LmK5C[29qReQehAMF,d[9pFM6j((p6dZ,jHqlrC@QNd"&6N!$'BR# +pBNIf+af6brD#JDlFEb0`lMeH2kr)j((pEe24iG[i@hlVYDqUcQCbH0l(VaDZYkq +DRXKP-e6k$5@QblraH"aEK%@*0('mrJEiJqdYG9GTQ-PM1``h@S96Z1b@@l229rD +klFEfhiARh(UHYkrVmF8$cI(m,[0MUV1YUHc(`-4KF)0p0cq2bHAcQIXY9XYb52r +1p,e2@&#ipaa2+hfkffYlA4CqQc'3!*fDkr#pEKH[l'GaZ3bP,89fSlVZr#mEbH& +jhTSYJmV`I)hK)6dpK&l6+8%jLF0ehAGIf%f+"5CZVXY9XqqhRMH9`r4ihVHZ1!p +2LH9iZlfq[lM5eY4Q-P2N#[ABE%pM0ic(dG,6k(6Dfeh1pmEbZ*kAU)9FEcq$j(K +ppYHke**TbZ2RCV%BM%GK068h2j'Nl5,CDVBEIG@hNF%@X@Re23mhb['m,[GTh)q +"5dG"16@*8UaP"4CI1k$6D`M8mAb[0mrdq2b12kYaja&4ZYaXV65k$1jI)cdhf-d +6%ZaQjkKbRCe@LlEZGTh[KH0j4E9mG#S4AHEQeehE@"0qb10RCZEa8ef-h1ih*CQ +RVY-6NK31"aI6pEe[9ihT#+li8"*[e,4iqIRCc&63S!L[C99KTV4#Zhi2SFEe8+[ +0mVar%hHhehDf0AQk6*Br'cf,aABpMLKe@BTp"CGUUJHAaI5p4#VKqC'hqplrD%e +22C[,j1KaXkK91$Ij[29YRUHkffjm0)&[6p1ip(c[0i%EaI"l[ADQbcp0QXYNXI2 +6Fd,8MbQGUUl5paVp[Z[%mVKqIk2SqKk(RF2Jq@2+l+ddeIRZdc18b9"1MJX9La& +HcTkc4DJ8$HH4jR$i[RqKk(RmAcH$j1q(kZhXp"8pT5jA)6mjLK2jl(j5PcP8Y", +`2&mRKF6LqF)Va20i!LZdlRYE(2e'Ec'6S-CLjbFaH-S-RPqbTXrBkG*DRMqA`Z( +a21mlLm6L*E8@Z[e9RA4DIXk3!+-b&@0b18c#XU5e0pEm$Jm2c[2#[cH"iqm)&1e +XUfUcSmX`USD,+dU)VDE([2"m6b1!3eqYab6BX)@p(lG6Be+3!)ABBM$iRX1`a1( +a(B6FrNXafP6SG*UYEXGRYYahhJH#AN2KEffm2`1mffcf1[lVZZkeqcYHlfqefHa +f@j!$AEEAEGhZ0[XYAU,+YUkBPPBiJ,l$VCRUbkfkh%ic*pTS02V0MhIJq2aH2b[ +MrMrcpRhmhrll[VrVraqch26m`[%04SFeM-(%r,d&dMNT,aedNZLZpkkV%BrXklZ +0aEqRlhbIbrVpIhFhrIqrpIqrGrRrVjrfHaa2&llBpY@jh,Br'GMeq#r9HlcH,cq +HqAh!B@FSFYf@FUDbalA@E#ell`YrjI#i2P@rMlrb2)hrLq*iRLq,i[LEc`1qlh[ +Hml[ElIElMZpU8VV$39G2fHAbH4b'2Rj[VqX`(9B#B`@&&Tl+VX0*UGEY[#MHGaq +9qhqIeIEphfrCpAp[rhm[MjA(mrblEF@QKTFEKZV[I55NJP1Q2NHMr2Im02jH,UE +A`q"k(VqmKKpriIrIkrqqlk[Qq(fQhYHIcZAarBB1r4,hHVee&mr9-iDD)(b8l&X +0,fqZh(JllILZH0imEb[,m[br-i*)LmA`r#m,`I!h2IGlhrIGhY0EUG*BeT!!XjQ +Nbf8b40bkh"MS#HlMFRQFj8Cq[drG$bA$p8H5qMk2jrcrRr6qIm[hFchIBZ1$EEA +YY$Qk,&pEIlhdYhr*dA35%I(h@9ZpkkRVFCQ-rTdRcm(e2GrCr(q[rrr[lr[qhkI +SqApI*p6c5h$fQXdqKl1LRF4eXae0pr6qVUTMV1Ykh$BQFS+-KddAEkqeli`EGji +JYINNF[&mhJ@rLfeYiHmm(`0eZphZYaXGAffPXV$3eG4RFjQkA,C#IQjV%iI$%iJ +[fFV5CRY+U`)bZrhh#p2f%TMr&qhphl[fr&c2eqpl9ajAKE6Z,22pRNmBLE4,cq5 +9k'lINZr6IS`')aY)PdRVqqm6JHMb2IrIr2rRqhpISrirGqchbq"55,YHid5a9iR +$B8FJ8(1Xkh$iUHSD20Ck[dZTlMZGIXqllrGlhI%RN@Rc2*YlG)4,EIEkfm,[GVV +pCUZedZLVDc2eHHcQAb@15EH6XTbIaq3b'5+"&@@cqbhAMHCjhTHVb$!*rAc1Cm2 +l2LrAlRU&3cZpGfYK9CZNb'-a%aIEed[jV[Gladm5rpCf%mA+QIdQVfZkmAKHYlh +l2PrKr$prbr,mRaHrl[XmHiiG[ZpVh&RS5jBamp1cFeKm*JTLB,iAX-A3CAXkQXV +Y&T1feH[fZih@pmEbH$j["m`K"mU0EM)H4irLlcGEMDl(@paffQXp(SUk,RDA+C( +(ifGR*bF+c%r26aGC*,ddZXfZjm2Iq6jR&p2erDp`UDrXrCq[h12k2#Yr$llCk[6 +f*G(6q)QEp,h[TqQkEmm5rB(V1Zl$&d1BU#m6lca1"kAVqeb[Jq%I)q6idU,T#"h +QalM5D'Rl,-C6)6deeh@6*Jfi3`4+'Mc(C%LUadhEkdZB0pEq6'M4[*i("i2QF"! +AbYrEE[[paDl2ADcZ1h(PUbRl2-C@LSD$'cq3!ifIRFALjh'L!GT9f1SeQaf[HH" +E4LLpkrYm[QI&m2[qjl2VHPa'hA0GRFXBF8cIrdrSL5pp[h8hr!B,VT[(jE1D$5k +hZpjirPm6d[@j+-jmBYA[HaFF+hYYcYGEU6MHcZCb8rf2ApFP0SP+%!16be,R-pS +E,6fQbh'km,HEffhbbP[-iAQqE`I+mIIEh`[!llFEECE$ZYAffMVSY4R1b&Vb14b +",q,R1GRN[QkDXd@QlI@DlDpr[GrjI$p,erEjA[HllRYQ$%PAE`pcDP6M1dQ46%0 +`8aJ-!B[R9B(#&6e&UeQclXZk1&k(VHelU,Cc19l2UqM`r+m8CrAG`8EqbbLABIB +BM%pM1'aUC,Q5bSYGETG9VYRYG[Z%LXhp[jI#iR%iK&GirMEkfhQlhAIpiPbBeDU +6,C@M+'"4E&UaaGBN2ePTG5MkCHCh((pJKf5TVFHI`r-Yppi"80VFpfH@A%i+dH! +-RUC`Z*)2UI3k2YYB8Nr%mRKqMka#&m(,phfPCraYlZqpfhGDL`ULmCb!P)L"GjP +*h'j&&Ud1Me'UlRBlC9UmIbZ$j[$mhK%@(NfqrhhKlcGprhHceZUdpPAk#VBmV3i +fH)1mC2#dj3["UV3@1RlMZQAl[RHPa[9pEeZ1Ue1B'pMRkDP-6LG6$N-AR#pIf%j +3%jjEa2EGm'aGd&h1BG2U*IK'![YpKUqfXbmC9,D$'c`YZ0S#mGc'ETa,G,UGAh@ +b9Dr%mAIq3XT$Iq0iSmTi(IlKN[jaDdH@bG&4C1MSbhNl21e1IVaTpEXY[hflm2a +VIbq$j[%iR&+44$jiRK)dK)d5qM(36dl1#,N1P$48RC8d@[Xp6V5%$Hq,'i(QT6r +5QVjRNlr`pf6EV6YG(@XFa4d@4$@L%X58P9k#[XNN@E,EGhhRIlVGq&[2$YJHm2` +b+E[qml[EE,ADh9NT,4k)@[29&0RHdcIC8TGBGPQmj6jj$[6p[U`l'PhRLH0ip[j +2PH9j0[irMH)VjQZY1e4D@4`80"53!cN40F`UdGVDDlDGhhb3!!XEbL@"`H"j2NE +ra2"9c'TdYPA4DQQl60CR,dK6Rc&+*BUcDAYG9Uqjea6Lfqilc[Hqh*3[m$GESZh +paYbr&efYePTfqSdYRC@0I@k!Z8kQRTMmbe!XPGB@@Pe(EfL0%Lcq'8H['*i[KMi +rHlICkl9kR5k+ZV+URl3I(bY'0hP-YPmb3fePICkJF[XlA[I!hRKliCb0j5-l[r% +hZlllZpN6PdKZb@2af1RX89kZ[a1+653LefMdhETKe4Z(kRYHpbrF6-#pIe26p,c +Z&iqjf@UdPI9jY('BfD`Z"C6PRU2-pPQqdU0$CkVAlI`M9bp5ip,ddaBNaZr1mJ` +q0AU0&@k#,RXfCr40K5i)b19be*58Y0&VY,DE6GlrbZ"jAPHBBDh%mrdq0FHE[Yc +Dl(@p[T,'`VY$8PZT16NhLTc'j,,jUPTDAY+Z[dQUf(HllbI,mZhmJ"I+MH9`H&j +HqlhB@QSdGE99&68drCC-Za*h'&CcXUV3k'YVG&U,6AEBZM24Z23mhc2-*8[NH2j +(MEh[0D0e8GR5C6+j@MSCc%BBbH*c'dICaE$4@HQe@ah(JElbr3pMh16l(UA&akA +Rm6Jm$J@rKlM@@HJTqbbY$MFGMClX6@8[q"`I@iR'jA1aDbYXZelUeh1qmbij2`' +YjlRZFRfZ4k['p2d1$i[HDibVmlPk1Lb%rf%aqQqG4I2dIT[q$l$(C,*jE09&IU1 +jYGjj9al2ZFVPF[iIM(m%ZVI8i"UlpcTkqVU1cbf0`h9ISr2dh5rQ[-6UF%PrcM+ +20jr5klFaZ+8LIFjRbI`rPr2q[drfqIp[Z(B"hRGpefqRXFpPmCKHVPled[jE[de +lr6qVp0pk[#BSeKY(VHqm5hmcLHRlA[r&qlqAp2lrhrRqri2DpAcr,m6[pYXGAT+ +V+icVjMUCHpp4qLqhmf1ZV`H*aQ5c9CU0MhQkhQqmRLQ`IlraI,qrp[`HckRSF+h +m6`1mYGMh'LTk5KR66S`RABI%iI#pDP,ZMl,2k6ZGRYZllhGq+A[GaarEpcfI9mr +K'8,[0chZi'1d&05j6*BqI5r4,"Z,24GPXh@D5defZeqcfqjhQqYr-mldbh*i2NP +dPZqrlc[,AApYA9(CjI+C+KSD+MSmP3Bh(*EPC`dTA4P`L4%KPEq0[I!lhF)NKfk +5[$M-CMD#JaXk@'XK4jM1efSeZb-LC+DA#p%fQc3%+XZqm,FpjYpMh&PRXeP8S(i +LDa@+l$Vm0KjUGaq8l1XdQVf'cfrIlcaq"a,Mf19c#NVadZ9priIJlQeePR9CS`S +F4KHYkl$BA"i$UjM#BI&6jB&deTVGMhCX*FAe16q[p[bI(c19lAVTD!hpYZGPUDk +RTFRMC[X-2Km0K*MUIeG6eH$,9p*6D$4DAYqkfZjYVIKqVbIer&c2JjA*5MQ@6I) ++MU3i89"2BbFa2@i"0[E"GGf12bhCe&A@fD@b(LQ*Mb5hhpVN%TRdq,EQkIffLUq +dc19bG$1iRV-$eI9G9JF(eq,SD-V49GMf[FlA`2)iRUH[krVV[!*f"VMKH0ZGS'G +C6jZPbY"0pF8YqV%Ma@0b0(PPf#0IZ,Eb[1Z260GjdC(FdCCLl6-C%a9Lk6kcVF4 +Lk"k-Z*k2T"QDA[UQQ"jjX*)NQJcfGcHB+EUbm-2LM'ibqC61B$,Hq4`H*a21p$d +[6p2dNlSR$+X*BC%NUDBl@8iBp@&`f*1"R+8QBl1RcpMU1jfaZ2F(K'L@&rTqTkP +ajh!@mVlA4QARRF[N-Af!C*AGRmG3j%`0XqE2RHEhar+mcKqHZHRlAYqbEP(NH(Z +GYVHhdfL0p90YC1j9K-0L1`0E!e"UU`e1ch2LH4j4$9b2Ep`UT-hK[&m#eeeTU,, +2pNQ51QqpJ-(e[@R!8'HFd'QefihILH2jC@Z6ILq)hC12k2"0Z4-'0-ikF`q%Q6H +m-RG1$`Nd9HMeHdlhGlhaM$$%Q0d(h13Q``@JpTh@UXi[Cj5JRCV$BA#pGL-5E$f ++R6MaTY$U0EY0ahkD6h&Z2@pNlcAV-L5hIIlIB0fc*cX6!Bl&$1ERXH@-V&,Y89V +b$()j(YqhlAVVDqhpY[0eYqke"%QDIdf'IBGHL9GL4mC[2k2YY@BF[Kq4jRRFBYd +IG*!!ra[3iIPq2[[#llCDQ`UNUFcIBpJEa'#`@$`RApM2C+PceKTY9VGSBLr!1!V +Pr"lrZqhl*ZaF,bI(m2Fl69@9AQmY3i[X-3Q&@R$i3hj$,dqJd@RY'F2LQA++a+- +C`2(m,ZqjdeDRDVaK*V`T9GkZC1"M'dIC91KXY4UpRh[KErJT`0FSZ@$JFp$LHDQ +q3Q3fEZCVjpKKF&-B'C1-R&NQNKZdqXfIHEcb20'lj2Y'qJ0pk(RF+0iDmNK-QSM +6G`r@TaGM&6p&PmeRBT*U6KUiTYrmKQ*ck['p$JQC!4m&$0FN%i4%XXiK)PNP1kJ +P1q0jRRmCC$aH[TLDTZ',fGkA+'h&er@R)G-TP5TZGCk[deTXK*8XBqclI*j+XCj +rQEr`Zm1jp@jlY$ZIiV$VTQpD4N&DA09&ETE6C(D#i2R*`-*`Y-h4YlhUCKUAff3 +,l2VqZ)"LqfRXJZb@-9h[KH+Qp!EjDiNA%m`RpEIB@M$-V,iV%iFf5MD5S++Nl1S +d'M6(em&+-IS(G9pCF8NlB1kBCPl&48#C&1(a-dBhKK[pR8Q2RVGThRJRDFELrqT +kARm2J%Bcf5Bd4@'DH3UZ0cJf!daX@T0kA%$,GpiPB@YcfFc0'Q5HEXq+R&-PfJ& +9Mb"*I40aMde56a2"le*P0I&TZbT#ZZfYX9ee-ZfeH`YHr-j0e@eiAPq2E&JIApa +Tl'XU5iQ6)+$)Q6*MZ*RLp`5DYe[2%5`(a!DA'Fm([VABDcYV1[V-pR+9+k'1"PD +jhC8eA@TNhlAF&f+DqaMSF6KPj5ABak,PaQDBKZb+Cpq0S5R-Nl!c%be"j4Eqm9& +@mlKm)c%YlhV1b2N-Cf1)kr$B6!AkA,pV"&&l,8eIU,6AlAFq0`VMNHjm2r(rlrr +rMrVq[mINq,h[Bp,J&R(E@PGfH2l$V1T[R5p(+bYfr*dNYGVYdRjlpK-9N!$Xl$@ +'%R`[2pEh[NqMkIVrlrqrhq21qlkIiIVpUii1ql`j(Ul1j,X1VkMmefk#kadI)bY +h[26hUqG6eXhNZcV04XpjjPaarCpci2PqIrRkIUq[l2mrjrkrPc2Ai[Nq',"SY$R +XjPXCKIeIRkAm[j1M%S[XaK1Ykl$cG$PkHYdhGERb225M'QPhmIar(mRbI(m(XqM +j55+1idPIS+URTD(&B6!pAIah1"`Xe2*AbbRCRLmlFf2r,iBi*1&Ecr1mqi+Br"h +qlh'ff2FkR5@3!&eG8pP4j$(d&"MXDR#e6GTfHDl-a`UiiM0RhRI'UZQ"0hqjhGY +ie[j"EZGhYl@efZbf4SBTGa&DfXUkLSUkbYd#iM'@bf9bZAl62D'[VG$@D'adKRB +%SlIaMClhrN4[,i(PR#ea6AQh'b+rHNVM)VU-hP-DA2kGRdAA*C8aS8[)Y6VEAH4 +[1*5((j!![ZHphh[Hplf[5mX1GCfYLD$q@bH1a-cqRU,d,re%[JF0LdKVc99BRMq +m2JA(Yr"c2Kq&0Trphl6@[rAbI5mRGlA@pVBjl-PZ2Lm4-ITkEmSErQk@pp9KCbJ +b@@c96BGVVZlm'hp(f[K6Xlr[riririrHGaMPqjkhQllZqj0)hXU*06E#p9I,adR +5AHmG0e(kX(f13T-eR+QYdqYfblS[aK[mRar(qciIJj4kREMcGrZGIffLLNLQHaF +hLX4Jlr%-B3h5ZZaH4TDE29LF[44TmVd2AjA`F[PHf6K[@p2cc1Vm[aceTV,qbq8 +bP(4j'Hl(VL$`mJXrNk@RUiSmHDB1c+QhPF6cq,`q#F%c1hD4XppXqje@SdPMS)X +@VUbkVS#9K)T0TcZGcQFTU[3k,5pYV0ThfmhaQH$iaX'm!TVm,bI'm*PR28DI6D3 +mZf9b'2aaX#ibJb@80*&*42D90BH5EZpci'lm%l$FEbbQeFHSQY4iqqhRJGkYRM9 +@HIcH@5BVLZaQmAM-CLjXR4RSdc92ADI@l1elcFT0qmqi6B3prhID@N0ifphAHEE +CDc5eRCdG!Ha("B(!c1%khV-%AH1(QmGNqcV0,VGX@G5qZ0XrPFa)j[ePpLRPdm$ +[0TVY6Adq@+b"`6hkrpA-Pf*JF&ebAl'GVZeeqhliZ8Z&k(U&1AiIfr+F%r*6e!H +0iAI@ZalRY3i+,q'`DFX1$kc"*m"TV'C$,"aVV8dLhDB'+DAm#GKI[paY0GfqLca +C-a@),br"'!QRGMa"i%-[RDh8Gd@kAJRQ@+0A)pa,ilf1-Xp,GplDl,A)jJRTBZD +-HE%iT+C#GedlV@JdRF-dM&hX`l5kJiCE[,B)fjGXD'TcQD(NmG2cq12"kCiUd3L +m-dQSe*XrP"*E"KS8Ri)6AMmMIlkfhHif(ETX'Q6UECTm31[klVeU(8G,89PGBk2 +6fQ[*mbh[K4)iajmL3)A#THqpd86D[1dZ@bH4SFDFcD0(eaI5RMdTkXl1UHRca2+ +-aFaR#6ZBYKk,Z*`2'hHf@k'25`RJk`r@$jD8hL!6-GPRDPPj&[I*i[UFMf2C)MN +kB[8p,Kq6iIHE#d2`CfQB06l'GKKCMUMlpi'C2TiRRVcP9B*k3$l+FENHebH5Q"p +lIXTIX*M[E29[Ji$RV$GiSd1+p2DGZr(i4rF3PdKlAY)EqRk2$M(H&lRYY(SDR0j +R,8H3!-BF5@$6)+krXFCN-TPkAXkI3*5@ll`lIKqMFFEM'0U,,aZ0kITFAc2(-HT +'J1`hQXXB*4J-(F@ki`5XMNmU9i%YiM,12M9k(ST5Fik1E2RGj*I)Pb`C#e3I2,( +6E1GY*BZ2b9(PFcfLdScfm&i6`L[4kI'"ldaD6Glh5E6TXreP6fH@SCjHG(%RYBa +f2SFJheCDcCppi9X[Kk$T2PYar6mlJTSCEICDh9DJDE0'Z-B&4m[%q58j1*l`%X- +'V5A[RPm2d$pV*K%*CZi0ZP0MZZi8iSTm@T1-2VX4f"Jc&F9*'+Dd+8Y1%RbNpRf +amce@9b0eZ0Q0)3HdKi1d6(#iA$GH4d-1%D-h#6hC*K*1II4khY@I)i16DMGi1&J +N8[IEZf-J00qa`hF`$p0A(mLTJjcRBP8eF*Y['#Pqq59cGj9j2M*Jm*JMVJ+fQR6 +h&,Jp-hX@I!0-%U[-(eRKk0l-XYqJI$0-"XR2lRZpMV1fdPK@9,H)aP696RXXjRY +"BPJPkhl$j-V8jm3qYf`0d@`-+`eM8m9`dDF%C&1QlfB9fflhGfhMq9`Jh%62P*` +2*$GANY,Bk$21qpi'cH)qVVE)SGl*(1H0j"iGq%B3RQQpX60$#%f'XlG'MC[eP-J +PA)EpQT[fqXf'flc`$IU3!0q'R*LV2Nrj&Rd4kUmjf55`JfZT`4)cc(-1Z#)i)H& +`MJNDEl%ZUMZXe1G0l0R%EGD)dFN0kl4,aklI[PhY$MeYidDhmIa6HdI2(RPXSEp +Pe+GEHm*CZFc#F4#AF,[IYfQZ2DTSNJ#bbI@XjcTZHS$ab(@$CpaXbbC'A)%55BA +E(KlNiZYATkfSl+N+3H9c+E[UI)kblI@kiqP@[eqZf'dfZclVYV1aVUc2jr2ePA6 +CXiS$*#efeY@D'2RmIf[BpEd1(`I*mAHH"Z0KU)Y,NXCL-*-pAe2k1P+I[6bmc0C +(0*rXhHq,j[)q6rppAq2mIircpReIhrVmhaqej[KfZUVkE-C'GkfqIN6TVN1Kr0q +HqIUQ-238YCUGa[Ma2qZA6hlrRrTp(lrJpRdr0mG2mA%HSXDIlA06KId6LkMhDpc +VpPY,A[[!m+fhrNH2iQjYGPhAFDRYG0Sp$R4kdj2qdUp$@R,[DE$ZpiAihSHGjhR +P%2LF'0[5rkVUM0CE)T[Ch[mr6p4qR!iFr[l+C[3DMBq&`[9p[hrKrGmhrlqhrAe +r9r6jH9kRQq,hZ[lHbUmcM-*IVeGjD@k6T6f0AbrB5ESUDclNR+'#clR-rImhcIm +I(m(ZH[k2QQG"Y1ed'F,G-mCq+`rAGGKm9MD20k#cl8`653e[q"`Z#Ak'p0fMDDr +9kDXcQCbQ4SFMNmYPmXPJQZdrGGiC02NVR(qelAVqPjRMH&hQaeIDk+,QXGL-&e- +6U1S[PpkRUF"eQ)aP(R,(@QN&`[6j2aI`rrIAp[fIpIcrImAZqVa8rLc3*MXp9qQ +phVTIbAESrbp0qM!pKNZb,GhAGkHm(NmcirfrXq%lKrYQpr'01,4eK,XSmILfEMq +4T8mD'Ne4V8@hN4VG2N"[I#m(FphVc+*TXePm[PmaPmVP-XCFQIdGTX565DjTVrN +kJEJ[qG[X06ApTNjrX$)AkVUVrIIdp6JF,LU(0D$6D[ClRaH&aZ6qcjrlIh2SPr( +p[[qhar3MERZG&8jHJl(VNqS9h)E8qS%pNXc8f(El2`)hTHelhkqCm2a(e[rAlhX +HKEq#@P88+M2GhKF)B*FrN!$*TfMp2UpTZ[%hkH-Vb[*mRbShMH$DpefqN5@jfHB +SXI3Br)8@@l1UV6h2*rrFELQI&k4QZ&q&iKpM0(RqdbY#DEZ&`+pjA$i[*CM14E, +9E,FlrLFMPRaP6k)IVprNqYa2&lhADI3Ch,j('BI!N!$Cdh6h[p8cead0jQUXZif +fpm[cr8pIf[GplPqrq[hrGpIcr+m6[cfrf1Il5MaUAKCZ*6XmRDK2IADq"iHr5ih +!$Lm+0E*qqG*BCqSc4AYQm8DP'6T+8[,Y,DE2Fq-6ebpN+6[VHRa2*h[HE%lBHGc +&&M1[QErICG(P-60idrh$4k[Zpp`I4irYm[i[NqApjB$pm6r`paVY6SUV-d(BGCe +AkBN6p(kMS!`Q*RmTR+l9E6[lDhmfipIfrH0[APRi3i1rhRIlE@kE2RF2*54H$BN +fQFMPmlS6rX0[ZNUfm6dEMdH,jNBkMNkpke1()j@8ir9q1QMlMD,U$V01pIe$q!I +%1k*h'Nd'FbTp&c'R0a2#Qd2NFc8f@Xffj-*2eIE4jIp[`qpl2'iJi(DDUaTXYMT +V#B(UZTkQrAhpA962A6H3!+@,CkVBpj[#SMl+rA!VL(1V[HpeqRd0-DC%fRFI2Ta +LFAMk5Qd1Me*TkllbH*kI(j(VVD4YpmBEfQd00Q-NPKNjGc%46jd@HT5%"2R3bpN +6k-GrY1id@Hl)IRl"0X%i*F20d'@TkiLVll`r*i[Uqjm(-jR`Hpb6(Di4b!@PP9p +N8mm4ef$1"hUjR#c8qD058lr"mMKqSCf(Z*IaQ(IElbeeQPd'Fbq6aq-Ce-BAX*k +Lc1GcpPUGGYph[r0,kBJ86C*0YhD@LEEZ@b@1R-4ebm5q2bbDj*fc[$mVd2@j#GX +Y'@i2NH&YP45LadhKm(JHVk[!Tc38G+PbVYr"Yr2pBhbdhDH51Um[Hphh3kQPbH1 +a4LCAlpA8c'&QLFVfG@NDaqR5aPb8mh2(Z20Ap-D+X#aXT)lKp$P-e89fRlQem)` +58idcPV-T!meQXdYG9jh-d8qRF*161ISD,,jfXdHUfAIH)GJj,S`qFr'mrJEjK9R ++6)B[%*Zq'lh1Rd8@2h`[)i2RmC%rphhH6krTF)e%YFD'IDCA'pMek2IGCef((!j +A0aE29fZl,8LCL[Zqpb[E6MVhQi+iGG8CJaMm0e[@RId2Gka`&UH&pELVf6KBi[! +0R&1G1V1CilpKYriUF0[mM6dfYFqb4FU*EfH6[ME(5+Xj2alj0edh`D)QqDRAfZk +2pa2jRphPHjl5IlE[YfEhYQ)U,AebBcU1#,HHalEZGSFCTc&qclIY$pC&4EEXH9V +kNmS@-QjSa*Z[#T*5CU!lGIc3CRbH38ljTQ!DUbcqFT+%e-c0Ya2BiZI,`mVcGd+ +"Em,d5+T05G+hU2,D"#UF0SIVNi"jr*jUUX$ZeGji*hYH1C23bUEYIKppXG6BeAC +j6(RRc*0"q&9ii9N+TP5VhB4DZ'FKqieaDBl,+C!!Rc1cBi")J'53!#0a,Jf#8LU +-BAa9raJ[iFPMLM++!&5H(j1mlZI%m[LQ0QCXCVSqAia)8ChQFK2PY8ZFINcHd6[ ++priK`hqRa[8p6M*b8RN,f9TT$Mfbf5,B(%BI$Nha1*XXM**T6(361h-YRbr'hGV +hAED)48mQDTr0,hZ#SFkL!A-((kNLUdpI9GTPc6")UN@TXDQXfTD'1)Me2@)!%PT +LJG`BZTi@8b5F0KddV5`@HNrZZlm&5Y1,2MHJMIlIAG[T%lQD2,,aTij9!dZVf[I +la1+`XPqUX#T08eTmLkE-&a5H(`db5KjPdp8RG,%!GKPK9'm3NIQd`LJ'()IqpM$ +LIbT'TT1if*P%lrbZ$`r1p(d5lU5jq)e0'G,aNPB`Aj2h!`Uf'h6hkm%@[M*051b +YY6@(3U6apc8dCLk1UUDih@'Gqp-6BmNk@QpaXHh54rNCmXmGJPRQGaZ5c*1rY"3 +#)!e0dG81!mEHGkR2j8CV+*NUTbI*K8CUT2A(VYXH,EJ&9FbL9rA5ALLH(r,&H(( +6mp26q126SjQ[fabbR'@[(l[1r6FJ)&FY4RpUS9BmG6&X0)QU+cQ"I++,PUiT(PF +GNX[R+Y0YAElVI(Z90-P1rZDlIJRB854q[1dN3%h2j$,(38[5UN3$1JG)e$alG[S +dlS5G("k96eFT&9@SLb`eqJRZcmj2")Hdp9V%@aQ,R*`[34m"0'8e5GlirPK@1U3 +UYYeDTDEcfEc#jfVSU,5E)&9CEcq+Qi5HpI8(9"fHAbC!XQCe3j2,[E`(m6LQc@k +m"Ci28jj4e@0aq5Ci"fD1CJ*F(c6MX6RI(P%e`FkcY'c`LMG8GHb@QGd[4kII0Z[ +CRZdc*kA*p2"DNK61eCE8Yd@'U"'mA`Hpfb4rTSSj2)'EV)&948@dhERNI@SR`3@ +i%CG58kH6ZS1CQ-Jh`QRkEfKi6I%mAIq4j(NH2ibjrZYe6Fm6-jFj3Q@8,!XRklC +pfQDYiT`GTC*lil%Km69cYma5CA+0+Uqc2ImK9[GpihML+lp-K$Dkmdqkj8rT$*p +SmV5CPhTkGri*D*mJ96Iq)QHYVcX$TXCUY9'Q1Nq8@mIIq0[[$m)kY0Gh$8@9DXY +PmbZSKT@D'AJEbfhhLL,#+pmcB9CRj8ZBT+4#US6['Q6dQm%D%`9Eh`[!llZpVX( +@Jp6Cc0JYR+LUcpD&@UeQZf@e1MlGE[`I"hHkllZpXCU!8QGm&@GcQEl61dp5D)& +PTZh#REGhhb&(KH&i2JGrhKQpDXl4bTrQqbT4&'D0DDLD1!4DYpiPYEH([2!lcEE +&([h&U-P8d0(Z@H(EH*[YpE$+QNKV&jDe4I0CVXmhR+C5YiS3PM9XDS@HU+BePDM +21&'a2&kM+E[`0chfifqderFfREkKVI'S[89+P,Y[GcZ[!m$GGrhJL)RMMTfSMA@ +*UH)8@Zilh[N+4%Mb2kl9p[Tp(B9c8lZV%l9%N6`+GeZ@P,L*"668e28248cbm$( +GrhZifqef1ZeREkM5D+ZV)Y98diLXJi9p[UpDl4E[ZpGSYBefJ2,#,6946["[#V[ +!qh#HFF469GYTl1bXE#ZVG"RaDG"@eqLdHP11M9pcVYKXGRY0YDK0Y0PVqkePTfr +DkI5S99pD)PAf0PCkA8G[DDc@klBE)*K%GYY0RX3SeAE$aD%cL)@0PT01a1YRYEA +EKie11e4$N!#G&MN+[2k#ZX,*86lVAMafhl[[1ml`@3BcZG@l,0AV**&MXad+,&X +YSU*b&VDlEDE&&Ne$XTBRJ9G[h$&Q#XE3+GGVGCh!afN3U%4Vl"@0e1U41pKXYRY +0VYNBcB)R1TBfYLMSDfYB9#)k[Z6C29d'f(2E"U)UjqZ%6ZSR1MDLB9)8LbSLEk+ +E#ad@MdQQBm8*k,+LaSLHV4iTK6SG"RmrS#ebaiYM(K5VGE98rDh53$eQJd1K&V4 +DJY4P&6q4fHcF4E6D64k*@5%!Va3%+@,@1!"3lFfYlRZGCD)hfQdPRCSA$)k1c#R +8GXT9h1YeSZ$5MZ1h9di8D*1Nm+0*TN4,Z,3G3T4X0KVqkeV85dYRSp(C@1VeNQU +`SKlAMYPXYJi8+k45D88QG+pXYRXpTY('+Dqkf**h!-mHc8U41&FrBf#PNJ`X9&h +f6a@fdb&ir!1G9MHfe2Ep`VEKmMCfPTh(FDV8pYU01MS42JN4cHTBfSFkc9ZL-3c +9kcS@1llKL$2(HZ%E(+b)p13RS9-9YfqMUl33pMC#([KJ%FYXGJ%lTmj'Z%3X8JJ +G1B@##6'S#GL'SrX%i5-4&U`JQX$6'#&$(*D3!'P!T'R('fL&!US*+6GXX0JMcA& +XB%(ZkefZ'`#Ta@PDQ599h'$@"[CE%I$Hl"Se,Z85Ur5,MM9KNGZhE%irC0Q+j)D +-IDI-#%QkM$4Th'$lAYZfefle2M3334)!eTZMqLqFfqFhmR-Q0ef'I`A0r2,G,Yl +cJj@QZPS$XK)!,dpi[!$AQm3AJ,S%$2bJ9*3)))3G)%&i!44Z3D%AC"*"P#D8"'9 +8LNf#kNV#G!k63i89DIG%`9ZS$)&5F-)+p'STGN#lY$*S+U#JT)U3!(4)(mIMJ0a +q1JY*)+bU"9eKNe"rP4+8&T5%#C2jIP"G%&3BN8'"$k#3!iIP4#R$0LHp"#RK(#e +8e$*54`CNN!"P9,H`S+Sp"k*1ULA9l#`$+V$h1ZK83k&LEX%9Bp9K4IP@j60(ai" +2i)3'G123Hq[k`5"`'J'"T@m!8DjJ[UpCq4#Iki2V334"hJRpIeS(-9U@9$S!SH` +SK`d8&R883RB*-8Q@G+55$&@d#%A,9kcTJ,9qHm-8aAa3-DL$3eUC0D4!4@V9Vh3 +iLr1KGf&Z)8S@iIZhA)ST'8iBY+'RL`(2C'(LF+[+NYkD%%8#[j-$T4C-MX3k"XN +MS(JJj!#i*%G54hXLLB+bD`@*(@pL`$[Pq8&NM$H`[*JX$B$250%D6*0ca'ZJ@4h +)2N9C*`HK58E+TH-D4$V+bI$JR!J3"fr5q(A$jMapaip-rm'ka1Y0e&(Z112`2Zq +lUpCH`LMNKUTS)1PjN!"(FrlB,TCG*"GG$$"+HRhX(3kr#35[4FZ#6JN)*2rpVS* +$f))*@rrSJl'rkZ$flrIS0C2cdG(BH3MSk!"-@!RF5S'AQ$ZB*D$NfP0dH*ir(`h ++Qi)Nr""fRk3%rRD3!&,iPT!!8&Yai-41FH$$FH#$SdMI42[YJMS42SIZJNKDZMK +ji#A+K%Nk$%')B*YA#h)#Fq13!"(!KJ4c3Bqd"2Sk1jKimhm%h"0mQ#$Z2r`##I) +#Gap((JQq1J)a2VV(3Ga$$ajb##f!6EJ*X+,r'BeY$'T0C4IpI*Fd2ZdNI3m$-4i +-!*%MjcSrSMjbq!*0rE(cN[,4mjf1k!c2amjJZE(cRj`3kAEamjHF((cNV64mjG, +4Ta"(i[qARaq,bppB%G0,aq,r0ikM!RPbLJ!*p!#ID!R0!6RY'%"(!KmL$r3JIlP +K#0r9)4V5k`Cm#*S#0D!PX"RjT'$M35-(-Je)5bUfjLA'%%MMUU[UY,6`3ES'1JI +FBiT)CIS-3G2!3a1$!QS)5c`3ZYjJMf2V4fIXUQcJNC(&f96RkbU$Ukq@Shd(6`8 +5aEAAM#TFZ#al(,99R%Xmr940(98i@40(Cf9CAaBP4U)PRU,&!UXVe(l+UUE1RVi +YE94,1`B)eNA2fF''F3fcJjFGBhfIVl1UXRh3p8&V0(%Tl+U'(N)k#$"X1IlM!Ir +38Pmbe9Ajk*SY*9@@SLDDXXmr%Vl#bVUHYL@0P@@&P@@HSJXA#qP#rBCep&pC8e6 +SYLAm6kbdST)*f&69D24e@MD@dp@L`CmAX"f#E6DX#39k*RV#[UZUJ`lLAl35rMp +6P&+Xr6k1*9D@UViPEBDB2h5AfHITkp9#JXR$IfB2rSk#Qb`A@3L99SkrUE0a6'T +[T+qcV+f*6eYE%X"epNl6dAl5D1UL9GKC0H%&C%LXe)Dq`XiKTZf&N!$jPRe6(LX +`a0IP)@[l`CZHFJ3G+rB9EdqL3-k1UV5!e(ed5pSr8'CeB9qML9&8-p""L@)Vr@1 +[8(0MV2UXC@eP6SBJY#`Ik0fpm"c*%EAXi*eKcdjIApA(6R@)Tc5V8@+RY66M29P +H)*SkbcdSFD5SE$,A8pR8jq#HBJ10%"c%G5GDrC!!&Kr@#!9@RTkQcBH0D5#SBJI +D#"edGRmSqb"f99&dPE6f3H@0N!$kGCB9m4ad$([X[4BqPL9YCS8MiI*ASqUJR'* +$JK)CZ1TX%rKC(hD0(pU&L"bF(2J[-G5BKm@`bS3rZr@f5eJi*U#dJh@FaF6*8p6 +@9pRBD22Z2Y90E@99ICa+Q`XG3YYV%kc%BM#B'*M-rC&XPNUQLUUbYQBQ@cj)Jdb +5*)PrdG994-A8@'NXiP4BDGBLXp9@G2@9Sh6PYaX"ZqpMVrHiP&T+kS)j4@``dC% +[RN@j((%T+"am[`![hmGKk0fA9'SXb0NQV94!,RP5@TdPPC)Y+[&c-6+e@M4bYK% +l@UXV"YYe8f&GBeY9CKL`PC*#a698MX1+T@c$Y*@Z"DTcL3eZS5h3EE(Z([J"l[i +kaH(Vj@+bX+jlaf6-48q3!"%"'h"FR"J5b,lPpc",953cAZN4@i#DJ4+4&+5J'Z! +((Npd[%%3#FZc52&jl2*)bRXM4BlSF[28F5NV+kUbHNXjl-j@H[,YCU#XXbC"B$V +V25@9HJk)6d8R2@&6%T!!N!!V"'1k5$S1PapITDHYV-p%cpKSl1[TkiBE89pR6kI +SFC6Nf5*MDI59YRq@L4#G'"6(2jl5@99LJ8BAXZ9+NR@e#@m'N!#B+MqkaEf098e +PA@$Td4iP#SYX3@lUN424k3M6ceKA8ipZL&hbLGSJbGbNjJDdfA8KrQh`QBq*B@@ +HFMr@5il6&a3iSr0AX6rTCkLbU*kKPA94[dkL*9@9PB@8U5@k6'8E!dG2,`GC"63 +E@1jF#AZ58L,6SQ[HjCNik#$md&rJ[m'qMV0d5DY-6L4BrEkX'YJq+$Pb%INmJJI +eCK+qR(C2BIYDJcN)Q$QF4%aMU9qp5Z@faQC*p9Q,q1KT-r@9qKLB`YadP%iZaXF +P6k%F*Ie[)kHaX5H96fD)UPqVC8pRB@A9G%iZ`LlZ@4IF0-i2"a-[PSP@2eD-Pa* +2f)DX6d6dS246T,MkcVZYk,*9QHca6Hbe28k(5ePD"9&1a-C6ep2RUISTr*iZ*K* +r"ShYd-&M!3GKaimQfZT`ZEJldYarib%L'&699U#FV"33C'$qZ`r9PV#bXY4JBL@ +VPKlX,%DFh'04%T*qPT)PA@9Y9SjP*)ECV,pd-k&U'Cc"jcV%-UYMiQE+SpM"p%K +)j9+9k5P!6QJ6eVp%&Q@%b1*VNKX5A!Xa24dk5jNL54jdKkq,1B2pNf0,NAZV,B+ +h%3`$iD%Tdf!JZQ)%8Zh+c4V2qGY1fmIIZdpmIC%LQBA$&1U$UJeQCDSCdXG+`9X +G55%KPKI9%5Yh@`Fpk4HP,FkYJdmK+6eKArYXb#"K9+PAR!`B1f5EdSI23C'1TGK +qC##*8P4++Q"aB0F-R[1JZL&2B%kV*ae!l62X)0l"Ni2l25ChF9kq`ClB16LQ5MF +5`Ecm&pMXfQ0V)0Z-DQ$C`DD$fRT!Ib`Bq$,`IAX2b*,*RdYVSRBN'r4-JiE2bl1 +$bS,#$rPk11NJLM`IcE$TX[Ak'[X00AY21LGS'L!9V'+c4S'edGf$dlh[4eAr6jG +9+3AH$Ui-+ikVS4A-K(BVBISk+)T'p1YDf&(C99ASiLZfRT,Mp(p&kXEcBhN")2S +MZ2G,55JNS%")'"$qT!DKFmQPj03BVjT,jlTmrFahX#mDSMK,6cm#Xp"p%(d"mJ- +!M%6ZejZej!6$bAfh4J`rS3#ASQNR0#*``HaDH[r[MrlqMYY5iQMl#Yf5$+"CLDA +$fX!6Z9[61mrR(4m&eJcX%%TmFTmD#F3L2r*(`bUD`54LG"%EaDb9X(&l)'dl+5N +qkY&laU"B88!88$+8-FDbS%kMcqHKa*YfU8XKab)YbqA"(S%H"i"UTT-SUi*"!MV +HYJZV0jQ!h"ZAbc9,0@rPS*'bAbq@'"XfF[PKJE-(,jBB'rN)FCrX-2JH!'(4)%! +PGJ)3i0C2`2!$!h82!m!-2b)%"KdN-0A9KKq9!J-,ZJ3$AjJ)3i[##!BG+J3'&jK +KkhV3`kC!J-1R3)$$mk"!4AS#%11S33$#pVXl``Aa!J-)L"!BIS3)$#A3)#Vp+l2 +0e[SeU(rkNE8,lmJ3&r8S%"IId#![kTA+`3G@MP3+`!%5-'"31#kB3)#kC3)#l"+ +lXV*SlX,ZX3)%H`J%)0$%Ujh#S%"Keb[4Q&5MdBBGHJ3''(3)"V%!3KaL8%!`l"A +bi)*T(b``l&!J--8J3'%fJ3%8i"#(',9r1##G4r---BJ3!NmJ3'%qJ3''03)#V(! +31GS"I82mHM#JR3S%"IN%#![b+"!Aj*@PJJSND8#XQ"#(&'JJ''83)$$+S%"KPPF +E""5)id--ZJ3#@B!L4Jc+"`A8U"!ACTAC`3GNMX`Zl0!J,XfJ3)pfJ%)4Ca"!--k +VcF%&-McBB8k"!B9#"!B9+"!4Ci#%1+TA`a`#2KKK&3)$$2S%!*@)%"KS%#!Ud)% +$RDd8e$qZ493[Vd#!EX%#![X8#![d5VV""C)ZS&D-#%1,0"!-0)J3''P3)$$6+cX +%'R4R3`e#"!*GU"#((E))"KU8#!`lGA#`3DT(#KKh#"!B@L"#,@"%M"V%$JZlPA9 +`3De(9KGh5"!ADj!!)#lAS%#2E!#%+YLVbF%'b4j--0QJ3''d3)$$DS%!*YN#!UY +3)(1lF4e$rZd58,p`J3&rH)%"(hU"!ApmUL`3GqLLJ9Z3!#%10dJJ'#[p"KZd#!` +m&9YJJm*&Y$$H)%!P[3)3im0"!-,C!J-2%9PB)0mM+KKiU"!BH-J3$@r!K$Mad%! +`mK@pJJYdEd-)b"!BH5J3'(P)%"&jB%5-(!9dF%(Q)k-,Z#J3&h#3!#!Zme!J,Z' +J3!R%!3Fla9RTb%(R)DKIjk"!AqJJ3&rSS%"Ak61B5#i4&3+p-#%11-JJ'(U)%"K +kU"!BHXUH`3('%VRIA3)",N!3K`GqGA1qbJ3'(Y+XX%(YSXSB()NVRIF3)"Vh3)3 +ij5#!BHmV'L5SaSBHqJ3'(`)%"KqY!J)ZB"#((`UfX"P$XH0rBJ3'#APb2'rYA'V +Ui2N3)#VphfIBZeIr,q5!rlr6p0!Iq(Nq5J2raX0JJ2r(6DC!Iq@Abk!rc6bAaYe +qHAPd"rSr*q4!IqF%!K%%(p))"#B)$QN%+6M,J%,JJrj1BVB!4rD#!3f!ffS"$S) +2TJJ%2JJrk-hkA!MkS)"%B)2rk+m)PpD"!LAq%#"%N@b3!"%[mS%#*IDJ3)PrfJ3 +)Ppbe*Ck$ra!J4,ld#"%[rIX5([m2j)$IrHQJ0cI*3'rdRm+3!(1db!hqmZJ0cjj +!EmCG!Djr)J-[R@C6f@Rl"*I6"(G4e(2Jk,r-%Ie(83FrU)k$U2aJk2lS,RU)2PZ +3!$S2a"$T2r&(VRU$@,!rmHS08Ml`2ZX!,G4"rpe(5rq`A8#i1SN`i"NM9"Q'#lr +qL2JKq)-&AIU$!4kL$m[rS*Fq6%5"Dk,mbi1Kqp&)rmNdLa$@#'jNcakU#rlNim& +HN!!e!RMmF"Mkimi+J6JK%)2Tjcj1$jIa"1lrr3IM$)YqYGb#[q`9kEr4Jq`h0"( +3r+L"SA0qY)0#"8&d6fiA-R),pD3f4,qF$A1S!ZNlQ(r5LGfB*`3rHaCR4&mU*m! +MXhMSC2R#S#E(REF0r`9NS1MBQJ'IJ'Ii`5c9Hr%5G22C"H"k'%HjZBC"IA,rYA# +`ALl,,1Gr@5jJrh$rU#@(d`H3!$im&Iqi2bai1h2eb#r@1j4((3S)S(hiS+IG"q9 +%Hq[k`hI!T!d8jk#RrN(5G!)3hkbrlB*p%JQe5rrm%LLi%HYXBc+6EZMbc1#R,-l +V'*6bNa+)eSkp0Y3a-6-e8K6YLTiriQ2VkZ`3CapHC-&K&6DE3fk1GAERbVGZG"1 +4aH9aP"Mcfm3G&1cp*LdY$6+@J`4kJYL9m@-"lV$()6ZD'`[)Xm9i(rR#&I&'Smi +3amJ[JIJJ[32Vi8hX2h5kS2TXh)N#q$al%%K)S3D1c8KEcTY)6*QN@08YJG[0Zm9 +i3$S(A)!#AkS'mQca)Sq#3ZchjPPlEVHF0l&-Id,cQ`"3VJahr-(c4a*Q#22!P,! +)Q8()2h'lp!hRFHb1A6Shac@U-*GpbJ$$`aSF)()'A8#1UBi!NJIlMV[d616&QJ& +lUpeQB3HXPd0JPr(dj$'QYrG++Udal!i&(T!!ZZ-VE$4e8'C%9A4[bd%%QZLVLp' +l353k'MTiUDSeRT,&4D4Sdl#$`KN-TT+bcJbLGZ(-VTZUUXK2jkXXj$,eqHX)1bF +6'kBc5@C$$")*Z(`B`LCSkI4fG8HF@!8`J*3PP-X[4[%aGE@`BY%9aBf$IliP%9m +iRY(Lp(d&*9($h59@RAM)NXPPSQC1#G!b60qP0e008#6T&f,&2EUZSeq4lGKH*-c ++l+I4+h#)d0l%Jr2GB1Nbbm8P&B@ChDQEZU)6daZ!p2(GE(Ej(c9l"6[TQr4"-35 +-GddGcR19UkZE!M10FJ6MqVJkCG+K[8$X(e,,'aEdS,mA241h6c)kcY'Gq6ZA,B+ +4GbYGDj+eNA*9(G15U*&XTX8rA15R!kC+25q2&&jmG)04h@30pSf`H663lelNVD3 +GbVGJj+YNANU!,0Nj*iNAY*V"V@14l5,kMT!!Hf,PXc)[Qf-&RPLRcB[(#0p'q`H +mkGhk"fm-(G#c,jU0JqCfq[JEjNpJqVJ%HcNikYJPBl8UPl[bXZ"lI*@i(fJVR#G ++jVB01+jX)k*X'h1DB(!Sq&JmZ$Ll"hFYl%B4I*6X(YFbpHZ#",,%CRV#TdPFRS4 +TdQ&G(GNDQXUTQRVp(-ep8P`E+Nilp-(iafUJMP`PC8QcDFl5@IJMh`)*8MHK#4I +!K*2J3Ne%,Y"R)+1$j)lL`A@HRZ&+2BLP'Q8i#('"$S9%,lM0"NMp-`4f0bXrM9R +-fL5BmIM+,p,X1!LF4h00dIdAcQhcQrNjNaZZ`cq#j[jjETG[HF(+dedY%l5c4fq +IE0mfEjXf"&mqfqIEdId+1h@FKjpT+@R3@R4fNGh1VerVkrqIG8q[pIAH[h1VY)k +dMV4,p,R`h*,a[625Td8HQ'Cd-I(bmZ[q#!4,T@r!ZAMjFI&Me`lC'2Piq*%-3P* +YXM,`B'AL5m523bNSN[JHAb!dB8!EbjIN5r,6%TNSp0Kq4r@JAcqA$bremrPm[pD +BXdMbrekEPmRZ1@"k"`,mm"*T3kk``qa0!H@QN!!q3+J-d`I8lN2YJJjrkqAq[f2 +BB2p'N!"rbi3JHK"UE-$[BjI,!0i)GDZIBp&ee9(,U)iQhTG99B6PL,UQjJA`rEp +TQfX1BC'QKJqhl6"!AD&$RSi1Mk0,J2Sj'VN6),3A8-UrYJk0%#NZMNDD#QG"TkA +30B6rK65++5SBU-MkkSaGSm869kb94CNIQ%aD%KJ`*%Vk-9U(lBHM4cU"h4`ID+Q +JH$X!9S2rEdF24p(pSYi)$%!ZcZb5###-LTq*5#!R+JdNX,Pe8-ZT#`l$T#2)5j! +!334!&%*HA`6(i'#'"j%ZX"c!q'(pI2Drq`3kdJPH#(2QiHYQhJKdFd3h1cmIcQR +S2(ef2EUV39XIq31NB9N3[''3!"KiFF!1NDd8!eeeBeD*Nq`q2cMQ%H!F%"hhfZ% +#SU2XhC!!359YGeG8@C4dK+BBjf!Mr4bX%HX6UBfDZ'*%K))@-K9l5-"5$SfP$M3 +5$M0+bPfY"-T*FqDkrD38Uf6"pMD)VbD()%4m[JP#$N%@4PdF)mmJ40RUf3)jjAT +3`"pN55(c!C!!'%U,05Ad[9hLm*--[#*f#S%*Kc5)%*QJ)&AL6Nl`!UKUB")-,QZ ++V2br+"b@6P$j-$J6!C5d&`V8FNJF3mD'`bDRc-+j#0G(KNUhTSj0Me-`e44-`TJ +5Q8QJ5bhP1FG%d&TAf(U(5#"c9D9k"000NYe3D&LY1#(bJJm,62jGKi$-B9EDKJ- +d-eHX6@fNXA4dH43LNXAPD0+'!JI6APISc@9+I6aep,FaeNcJ`abF'hTLL4G$,1R +RhqdNkIp2-[fqeA4*pUTQ*8ee6AJG19`9901PGcS-RPQqZJ$TQB2V0-@&A-*m+ci +ZTqA$kl@@S5UfHU)%J26p%Xk6$+e[MHVC2Sb[j-6qZP2l26'%)K*INCQd6blhS#T +4ANi*-b#SQDX,,3VLj0G4!Hd*Pe)krE&,"(8Fp@D1aVDI8(XP%KErilVjf0rF91B +YQMGIIkaTp3Y2bX-!3a*eH&6meYaDdaGX`a+ZK9*VF5C-Q!r10IT1Lk,,P8*@R32 +4Z8Cr!a+P-Qr!VpE-#UBXqE6Q"9Sf#SAk)b8CPq84IC%4cprJMVjN`l1[L*AM`,B +4Y&T+Sr8fQV$+YAEm4Np""(ATFb"MYkZbX+qcAlk-*jQIId(HL,'m5RdY2@9Y28$ +#e&98dqN'$Vl"T#Rq@)`D+T(9m%GlL9Ff)BX*6UVkIpflrpT'+IK,iQ2UiQSX0*% +ckBI0H*fcqMd,(5&9&83!SkH*RUbRVE#,%U$rHcV5-F,4TepDE2eKMP)Je2Sp(@4 +Dp(4*%Be0(GBmH5%f58h9"V9%0`4SQ-3HNhVrqa,qEZ(5%YGe%)MRJqjpKeF&893 +39e2RRd[U2ArA"(9cU5LpR'[C`UIZjrqF66MAf1S6V((*kCrK,P59EBGlS'pQ"Im +1K4V%M)jX%G82m+&SfDR0M6f*-4dGCfT$GB@9B)SX`&NSf`&2XQ5U%J*X,&"[4c1 +eIP)hqU4[rEGaeiJMY%rmUVBe96@9HS9kTY`H2F$i&B5%N!#A68iMT!kbDqrGC2# +IP-Rr+C2r6PNl9K#PZS)lETfXf@dj-$F[D*Q)rDD5j+H3!'h*6&2AZSRRY,U,R9@ +"V+fY&1*3QK%"*,kVqp-fXFl8D4A,V*IfCG*bCThad'"Hl-ejFD[kA)mG4`4hM*h +-hq9()lCYJLJ@85Y1jT%,6Lb-3DVUH[V,%Y)NXHc1iHNeU,C8pL2iM')Y,)Y%DSD +#X*G&5@qk0@MJ5#PVG1VUl4jm9[6CqRXrfK%bQ[M+fXXDL`Tl,26,mV+r+b[m,+2 +)B'#1m"0rjN'lf9%ZX+q*&5V46eV),NM84pT@0UE#Z&Z9*E+U**e58aKH,)NS1j! +!l8R&H-*8T`E%-)&UAeeJ$Ml&eLRGRB6(EVcdcXRl+e%V%ZFb9KTE#Y@,R5@D5EN +[kK+&#N3Y3PL'J@qC3Me)VI53!)e55@#0T(l+m`i@5PSk8JMUc+U`$*6$(d8[KR` +rHc"T4bj5i(mUUZXE#b&GVG3,`NTQ*Sl-%6Nd(0&%HRVDeY-afr"ZRj5Tr`P6ph1 +$L-qPZ@3CZ+'Ycd3pGUC!b6LhqD[[pe&L8L6CL`Y@9j!!V-4&(c5(#RV$%0C5q5$ +R4c-Cq8lIpTfrq1XcF%GTFIAk1UXQccRUfeHbNa+GNYfYX'jUM5%8328%E'`'9`, +C@DeCAQ6FlANNa%rZCZRmRj6Grp6Gph4e9BY&Yae5"SN'MG1cI0ZkN!!3PhkkA4C +N5%HQ-8m8!Q4,E,FZ#1SApj0'Q&$6e!*#HVm`2[Qi6e$mS@rlP+$'Hj!!4f&Ck@' ++#qp#4q-K(D2qM9r#`2iX&2d3p#JQp@HS9LBkaC6PN!"FCfCJM[e0pPl0+PeIXQ9 +DHR*G8SR%*jC,VRi)krVi@h`14(AY+Gi)X(AiaN3C1XHjH1"C89IXFTmEBlUAi5K +[ZNGP[43GFrXNlk1))+Yr**'qrai@iCrXNMl(#2AG)ipGHbZNI)4c8b29c9NUL[+ +,EPCHAJMZRH%4,J6TJA9p09jRejMVfZZUr$pMAjj$`S)l(,dl*V*@HILD0HSJZ++ +plkekpSD[V0'RDM[lNc)D5cdPPAT,QUk[US-Nrj3NQdY(JB-MQSTkR3aE*$[UQIf +a"rjlN!""p`#5Ai3Cc2Hc*r%RjDNHeJkZHaG*L`Ll,XTr+j-#+ZHbXrN3)XXCNjk +IJZNGUXYMqb2Aj(HCSa4J)Z-XHKN#2EV+QY`jrHRa-p&%Gp@CV+NpF%I(jmNJ!4G +XrC+)G1cd[4pqbdpNmC!!4dIK+6*'lr(4p$PU6+rT"LSRXMNmF#&I2BqNb-%T(kl +'CI+jD#kA58TacKZlBP2Em"'0SmIM$mVh6+dNr5dN%PG-jM+*$#kHVLmPN!$+QKT +1j+GaH9JMT#Lb8r4CH#3N+[-iqLRJ3hfCV,-qH%KF#B4!3p[&j(+dN!"*b(c6Y&2 +$8A@K,ImB#kjJC!X!Tmqp'J4VJ)'JZZpCl&VVjp+R$M"GIJ6F#!Mq%rCC,4`4per +X0[8(rJ#i+%AM2eeIT$Vq1A#''rT#eR+Qf3-Ni)rfalTHDqr`4rpS-j8qc"(``iH +#2qX$1C!!A4!bIZb5p$f(AU$4HBcHJ[m'MqK[H9&"d[p3YN&k(C!!d[h!CRi,40m +6c2J!bQD')-8N'V3-iIi-q1"jV22j`,dV"Id,PU833HP(J[C`-$2U!`pq+"Pa)JC +4Li(HfpEc`-mCL2HYkB'CYL$qYkl%H)@[@j),eTm+[e33FIS8&pA"eB&hS&lFA$V +S)2A`J'((iKekiT)S*pHi2Ad3,kNYXjf#$NGXZk9!2YmK2eEGC'!Jfj(iVCUJl1# +$f%qq0eNi+`#r33,ZX!qIl#m[GSI&L$f9hM1KJlJ#rI3,P$kF3HdRJQZUTel@28X +8,p)6V`Q+MlDrR[@+&U4GbSAhESYp[pi@pka`RYrpJC20$2a!bJBJ[`rY!bF2l8h +)'I5k3EiIr8#pDJAm5H!5kpdS@X&Q[8,[DrI43[V%#pM!3kr&f$T![Lb)M-e!a!k +jfJHd3,ebKIPZd19Z')GpLSFJAqcT%#pNS@U-l03ZRG1CrCUA6J[fEP*%&drZSCk +j&ZBld%B$%JP5m-iB'IYC!&aJ,rN#qk"IN33I'RQ)ZYdJj)&VpHEUI[+$irq'3-I +ZJJrD[Z[MS2j!AT`i`SFI5"RI-&ccmrYZ!A`m(+Jrh""qlk3-`F&T((RirFX)mFG +Q@$jCB&m$"(RA("mUSM)4eq!["V$T(',0mUrI#5ML4amY'X1NGM!,TP911b3&f+" +I34a-qqA@,$6(8`&lKB-Bl3!A[K*,qb#AjH8"PpC",qpAq&&rhj8&a2d$2q-`k&r +jGN#jiGe$2QG#rc9!,hPJ[mp@a+0&""p'J"Hl`DZ1dS'D4ca+r4D!Y,-YLrShJ'% +X*3cl3-JJkP3aCBh@)&rc9ZP,[jdN'FU1H`krRUJ-0me3cC!!'IHNh3$1FVmb"Id +NbSFQJApZ+9iT![r[KT!!KG#cV!@l%N%p$PfbHQ08&,c`dBkQUN%R[5#8'j5HSXU +ccTk14bbdKEVLkJV*p"Q8aRk3!-Ck5aq68JNFV9!pCp&M$Y*C-#Y-P-(S%$U01j2 +)*I`Y32S&4A+jA*jASX[Ak%`dUpL4bG%HH@[UY(Sj0ce&5H5-aM*'`Kd&"@99NJ6 +SlULi98JPph)*XI5L)c2@&6SmASlV4Pq6Sj4$6-VKh5@9C60H#FUKILp(4f9JBJh +40T1[bc3LA4CHLb&&Nmc4-CGfd-M1MdBY5,UaA`!!3J!!UU#RN!!'!!S!N!G+!+! +)H!#B8)CiL)QBF!!)U)HALCF!U)Q+KRHR#`#3!`4e9'CNPe9&De9&KSB!N!-)N!! +0!!%c4&9@U)Q!!*!$#L)c4&@3!eC9CPCRCQCRGhGiHAH)N!4iL*LDUCUUU3#J!!U +(hrQ(ZqR9qhCe`rp,,1H0)HHcf3`M650qV9fljj`!(KbKYRPR@&ZPB4!(5(ZbYhc +P#fqFU9KYabKAI)(0YN1bU$61XlliH%UaKi!fl)A5YRG+k&FBC5[P(18*K,cKfH6 +kbK[MFKhj!FrrdPRA05T1YQV9UlpiG!TY1RYKUD#J+-3(cCbbqXXSCmXkb`%,4*E +lmH1F1@1L(-+ZA+%BA4V(`3q@idV'G*dh3#$P16$PYRH!U2eM1q2KI+(eR%@r'R, +$(61(`lIRBiIH)RB4ECbqSUdDA3YbP'U!bX2MEqU,rh8Q)[R1[)8M[hLpD8'0UPZ +F2EUkY-XJrAmR3T(+6ir"+4Uqh&&-4+lmEBe(6jp1V8#a%*XbdVZ"hC+l5%)DqMm +l2ACVr1cAkKlhpHIk-$cj#r+k1Y+AU0[[r2iDqMf@Hcd@Dl0IT8Epd-GX2P,`bMR +iaK1N2q6TEMI4iHjkC4XT+S,qC$VVpIj@G(Up0Q[m[C!!jpRGp2FJFB,'Umm2)dc +D1r`eqN'r4kJpG#RRhI,BrmE)PAq0ISpPQ[dHHcdfHYJadcVP'qC*9r$(ES'@cE0 +a)qM@$@cAjr1-Sjq[6,(K*dE)XR`R5mH5m3E-,G`mLbf)3rlFrG4rR0NJDc`Pj4a +V*6F-XDiM+)ABN4f`Ud)hqeb'k5*50Vk4HQD2EKeAcfNJlKZqK-[bC`qH@1I#@@, +TAXKp(*[T#RH*EH4am%XDH8H+'A3$'f1HmKEC$hb#(,J$4E31-5R@h,(#'%kD9%1 +!V[ad)6T-5*D,R`)bb*EGbSka251V9'5fDB*SI'0[EeI0#"i&U&-kP0`bPj*6R*+ +SljdNY9Gj2(`P+N!iT1I'KC`#PSNc5EUfS0Z'r)2bi"0[PB3%@&'SX5Qh(6J10*@ +B&b'mBZ@NCbPJUTJZ%44ebB"Jr&hIZ$C4j+BJ%TM$GT(+0+bPQTkN334p)8ZZi(@ +%U&3d&Qf-mNYdU"b)l(2%f34`#*@'l&&$$lG21h6-3MI,"T3qH8YSc-*(53aDd[B +VZ1P4#c+C)TVK`-4FL)J2c(4hSVl+V0ILjXGXGc[33N%mc+DfVc[QQT9)'&$BY+A +)3A8D30@!RBB'MCicid9Y5"`LGpCQ+3`B'UB*$dAk-5qXHTcl&3C4UK!Y[ac(rS6 +eK#JQ*rl)QSRkBfNp$BhlRjRfa5'iNjB*6N#U$&!Q5&d[*S#-[EPrqUa'$f6kaXl +C%DZfAfVq+5hlmJpUplil)Gk8iIQAPN2KTA3#5il%c8-6QRD4!AE!rb54F5)&LUr +E[aRDP"pQ)ff(baV2E0QJI6Ul%DB1`rIJJ3BlT#1mdY654@RYj+DZ1mRqYcj[05E +@1"Cq+12[iAaj)qdU8KX+Cl9NLk9&*$6kJp"TY[5X30CQmT@5f3jd5DA5r%XEECE +DM8Ff)1pb%,8NF9i4YmGf5(cb`1@b@)2qFI$[R5l(L-,GNamTF@B$Upa+@V*a9f- +h%@ZJ)hf2A)$U%BDP$Y4Zie9V%#LI0cHCP!R*al**S6$YjF*3IXdheKJr-eq5Xh0 +UjZD!HPia@3lLqI`4mi`(I+rJMkGSIiBPjf'+3Zm%"B4391$I8%Ac-1DjQCX33h5 +Uji(j2eP@(%J-(UKNji0m"`KFaBb4rT!!mC(,&5RhTRYcMhX**@)Y[ERkm%Pd%mV +RL(%`0aZJH'd9+3Rr!5pah,qGXcU)C$KACEEaRAI$&-C')Q5ZTZ4BQ3Lrq**@Va" +"cJ@M66-amr3hd@+*VXDH40!8YdFfrVS!akM'X6c'&5!`PiG,Q@'*!!3X1J862PR +A[pLR30Hb(M3"8f2)EIaZ,0$eaB@[DlZb0G$[&r3h9TTQTQCTk-TSH3E0Te+*#!F +BD[F9h@EjDQlJ'E@e-LE6mdJ[(E94dlDN*e9QGUjfC5YNH(%0@[@5!4eU0`HXeB8 +,),Rh@9plGQbIBamULEqfpbLhVYl5M&NB89'*p2ZhGBq)1m6cZ'L2-$Fp*&*801$ +`a4@ca8iXe1`FJiBUJ5DSPa(b0i9NkD,h480MCbicKH0![51qecM%Q,DU,r"i[&b +`AAh'aqr0-GmMjpEMNNAR2R"d`#KTHFr6JJLCZ,RLD&Q$lFY('1SKk003j-Y&5+D +rL[+CmX"#Sc1p(ijk&T)fIpBT3P')XXjdShI#PBQ1HIFL&1,RNQ55*BL5j3,dp%P +Uh)Ya19meNc9iijH,'c#MHp1K6GXpN!!hq[Q1-QD[6fL*CHkZ#Ce#a)dYVi0fQ6H +N,F&J&&U5HND4E($PB9RcJN)92LS5A`pk8q[RR9+20QZ46iZ"G@F055'Y$jXdhEQ +H4*Nb#YRJJJ5-!p@Vc3rC,Vi`iBm%MBT&HiKXk'+c4[$aCU,YD'XVR)VAAi-%+km +h9IdA*VdBHj`S[I'MqjcXjaZIdhQT&dVLMqE64rP#q1P"rff93$*JDS*62Y[$YGc +LSiTdKUJd1*P,YV`FYS5'kLbK%CLT2G&ISa"hGi,LPZ+12C(dZR5TdTAh5E0i9&( +Q$460VK(F0Fc4#A*N@SqJa28YIZbAL&V0MU&kKYJGer%kbN$eTB+U[(&elUGYfrp +&FP1epQlQHbkqN4mCR%Y2SjRV@986Xr&)#3MahM!9h"V@kk4h%h(Imbp-@-G-R+- +N@C6mP58eR,#e"3Q($KMNhm[(mFlXJrTeJCeI#,-9AH(lL[`BI&kYi,&&qrVjEqa +LY2&*+h+8@ipB*GUYUSS0Z)Llf0`IYMTQrekl$qpZlC!!2m6Z%Zf*[c(D%lZVIN# +[ifr+8lpA[aqd0IUp'VicZ2de$BD@r83182PliG8D4ZMUkrhpd1MVmieKQ$r%qXh +Z(eZ2![,r&Hc"23VaDJ2*)YicbK,"(I)ZI&[R%Y`UmaPf4Ph`X(B[*aAQ(YZ2,6r +bfMa,TVF,D#Crl`V%rF'V9edrM(P$r1Vlrcr6[MNRmNmQrS"a`UD-M5cJFDh,p9I +L[10,lN`('9*lhJ*hL&%HjICHYDDh(qXRV@$T2a11((e%%QI[TGp11fUYUm$1SHL +Q)XmdaNAdd@q@C5mK*BL4`!,rF!!!lYNCK!!$!)C"FQ0SD@8!!JC"FQ0SD@8"!*! +$#%&38%a$DNe!Td[h1+G,q-FK3%aP$(J!!J!!qli!N!D6%`#3"!T"FQ0SD@8J4'p +M!3!!NaYdG(*[G(4iG+G,i&@R66bd!3!0A+L5!!3!N!B6#!#3"JP@`5X!!!%!N!- +ZI!!!,A`!!!*q!!%#LJ!!!H8!N!F"!T)!!!(L)NGPF`#3!`%#QJT"FQ0SD@8ZFf9 +K!!)!N!0"8&"-49K88L!!N!P"8&"-49K88L!!N"HR68*$!!#Fl3!!-2S"l3!"!XS +!!!(l8%`!!!'U!!%#dJ!!!Gm!N!--#NF!!3,D!!!#03!!")S!!3!"!Z)!!!)R8f9 +KFQ0S!!%#kJ!!!IF!#!G(CA-!!3,b!!!#(NBJ!!!"XJ!"![S!!!(bE@9[GA3J!!% +$!J!!!Mi%BJ!"!*!$!3-+!!!#-3!-#de[FJ!"!!!"V!9*BfpZ$3!!)N&eG'p&H(4 +bB@0dEh+U)+NJ-6Nj-L"#D@aX)%G[Ef4YB@i!3N&eG'p&H(4bB@0dEh)JFQ9aG@P +bCA-JG'KP)%KTCA*KFQ0SD@0KE#"'D@aP)&0jFh4PE5!S5%C6+5"cEfCdGf&bC3! +N9'KPFQ8JDA-JEQpd)'9ZEh9RD#"YC@e[FRNJBACKD@aKBQaP!%K8D'9bC5"TFb" +ZEh3JC@j[G@GS)(0`B@0P)'&fB@PXB@*XC5"[EL"dD'Pc)(C[E(9YC5"dEb"PH(" +KEQ3JG'KP)'&bBfKTGQ8!*L"`BA0cGfpbC#"cGA"`E'PPC#"TFb"TEQ0[FR*PBh3 +JEh)JG'KP!!TdD'8J4NP138`J!!)J)`!$G'KP#f%JC'PQCQ9bC@jd#d9iG(*KBh4 +TEQFk)%CTE'9c)(*PE@&TEQPZCb"dEb"LC5"PH(4bB@0dC@3k!"P$Efe`B@0dC@3 +JBRNJ3fpYF'&MG#"3FQqU!*!$,`!b8%&$9!!!#30"45"8C@e`!`#3!e!!8!#S!D3 +!N!-(!&m!&`&9!%Arr`")!9B!(3!+!#8"5`#3"3`!'Jd+!!S!"J*+!-i!N!BHL!" +3!!919[k851F$##KZ!!K#,I"U+dc`9%kk'P33,I"LX#`!)@F3'f`!)I"L6VS8)%S +!CJ!$hN*R2bh`C$mm!!%[,!!L6VSEDMYIm)a+EI#-CJ!$9N*R2bh`E#mYm'i[,I" +8,b`!+LmX!#C1ZKc'1er`M!aYrp$`M'B!!,![,I"85'lrP%kk'&Jl32#-5N"3MfB +!!cS),J!%rl*R'#mYm&3r2!$c6VSBD&0!A)pR!!,%B!!$B%SYlL4Q0#mYm&3r2!$ +a6VSB5NT!A)pR!!0'D`!$3PG!CaKU#P*!DJ!$0Q!!!T*93'S!!b`EI!!"lL4#Ccm +Ym'`[,I"Z,bh`9%kk(3JlAr#-5Qh`M'B!!X*#CcmYm'`[,I"Z,bh`9#mX!#S[,!! +Q6VSF$MYIm)a+EI#-CJ!#R#mYm&4)E[q86VSASMY!m)a+3CJ!#K$em3!$r[#e +X!#lrh#eYm'lra%(Zrj4`#U*J1d$`M%T!CJ!#B!JX!*!$2@F5'h`!!HiP'h`!!Hi +D6VS*BQ!%3LhZ*A$r+d$`MLYX!%EZ%LYX!$lZ&NUYlK*RE%*R2bh`E#mYm'i[,I" +8(c`!!dKYm(*1ZKXD1er`M%TYm)aQ!!)%'h`!!I"UF!,!,!!p(`"1ZJ*Q-#hZ%&5 +2Ca*V!!)X98"R!!(JDJ!#)Q!!!E4#,I"U3QFr,I"b6VSC,$YIm)a+EI#-CJ!"[LY +X!%VZ%LYX!%,Z&NUYlK*RE%*R2bh`E#mYm'i[,I"8(c`!!dKYm(*1ZKT#1er`M%T +Ym)aQ!!'''h`!!I"UF!6!,!!p(`"1ZJ(S-#hZ%&52Ca*V!!'Z98"R!!&LDJ!"T'! +!!6C#,I"U3QFr,I"b6VSBVMYIm)a+EI#-CJ!"3#!Ym)k`V!!iCJ!"4#mYm&4)E[q +86VS@1MY!m)a+3CJ!"(#eX!$,ri$!X!$B#32lq28$r[#eYm'lra%(Zrj4`#U* +J1d$`M%T!CJ!!mJJX!!-!2@FH3QFr,I"X,bh`ELmYm&41ZKY51er`M%TYm)aQ!!$ +-)'h`9(`!(""`!"!YlJL`4QB!!)*q!@!8)'h`9#*0dXF3-(!!X#RZ#'B)8NG64NT +'E1B-4[rrCP`YEI"Zrm4"l[k8,8MrTMemrj!$X%(Zrj4`#D*J1d$`M%T!CMJ!EJ3 +!rla#,[k83HlrP(!+SQ"J*%SYm'TR(N*R2bh`FNkk&kj#9cmYm'`[,I"Z,bh`9%k +k'R48Mdkk&`a6EHiQ6VS@hR!!B!!!NNTYm)aRC!aYrpR`M'B'1h`!C2#-)'h`CNK +S!""1ZJqb@)pJ4LmYm&41ZJqQ5J"BMfDBB$B[,I"85LhZ*@F)3Hh[!L!)B!C"lHi +T)!J[!%KYlLP)EHiTUBY#Ccmm!2*#TkQ)$&m!!@F!rf*+,I"UCaj#CcmYm(*1ZKF +13PFr,I"X,bh`ELmYm&41ZKR89)p`!8cI%-"1ANje6PEq3%MR(`K#EHi33QhZ)Nk +k!mK+EHi3CJ!#!#YYm(6`H#YYljc[T%SZ!!KR-'!i)#h`K,#Ym)KQ$%kk!jj+EHi +3CJ!"eL"Ym)45VI#%(a"1ZJ5q5QhZ%&52CJ!"[NUYlKCQc'!!!E!JEHqF3LJIr5" +Ylja#+"rq)'h[R%)S(rmr2!%!,bh[U%KZr`"1ZJ'85QhZ%%r[!!TQ!!'!2c`!3#m +Ylka)E[l!6VS"H%TYlK"2l`!+CJ!"C$mm!)![,Hq`5'lq3%kk!9a+EHi36qm!#QB +!!8Kq!%*YlL!I2!!36VS#GNTYlK"8MfB!!6"J!!%30LhZ(%T$DNB`!`*!Irpb!$) +!dUh[U#""(""`!"!')%l4`(!"d#Mr!"m!6VS#1NTYlK"8MfB!!23I"Nkk!q4+EHi +39)pQ!!$N9)GJ!!$#-!-#3(rrFJ!b!0+Ylk`J3AJ!'"!J6Y$%F!(3+2l!(`"1ZJ( +f5QhZ%&52CJ!!X$!YlKcL5()!-J$5VHq`)%&k!"S3)%l3a4mSrN"1ZJ(-5QhZ%&5 +2CJ!!KZe0-#hZ(()+iQL+3"mm!!C1ZJ'Z5QhZ%&52CQJ`45!Ylk53!)JS3,RYlja +N)%RX)!"J'Km86VS$4%TYlK"8MfC%8SbjlHqJCJ3SEHqF8d4+4'cJ5UhZ&Q`11h` +!!Hi31hcrfI#-B"j@K`b(!!(rm'`)5UhZ&QB!rZ4+VHi@CJ$qE%kk"%4-ha$i6Pj +1G8j@rJ")jamB2Li!%#KZ!!`JEI#%XHh`L'B36VS"R%TYlK"Q!!%))'h`K(S!'KJ +V52#%-!A33,"(EJ!!jLCZ!!Ki!(B!B(`JEI#%XHh`L'B36VS"CNTYlK"Q!!$5)'h +`K")B+dM`K"!"k!J@`'FL'!""l[i!d-23`d2S!!)d!f!)-##i!'`'-`"4b[rf-`4 +53`C%!3!#!3!2&X&R)KJ"3Hlq!0$$d-0$k!!#0!0J#$!JZ!"X"M-!8FVrpM-%8N- +'4!%!8FhrJLJ,Q+i!#*j%B!*#'e(2rr`q!h`!GJ$H4d2ZrJ"J0"Ja-!!5-6!"+M` +!!)!!iUdJ"G#'$)!!!)!!EL""p'!!B!)3a&(0rr`J2!!!J!$LU0b!9%1f4fd!rmK +J$$YmrpR`M$Ym!!(Z%%cI'2K1ANje6PB!!#m((Li!#(!!%!H`EHiJEeJJ,HiF%Lh +Z)H1S+d$Z(*iYlL%L,I#%XUh`L'B+6VS!8NTYlK"Q4#"Ym)45VI#%'e$Z(L!Ym)5 +`VI#)CJT1ZJ!b5QhZ%'BN)'h`K&+Ym)3E81iI1h`!%1iJ)#hZ(1qS+d$Z(()!%JH +6EHiJ,Kp1ANje6PErr%MR!`K+VHi5C`!"$%kk%3K+!'B!!4!YI!!!)!$rr#!Zrrb +`VHi5E`BYEHi5rra#CcmYm'4)E[rm,bh`J%kk%Z`lAr#-5Qh`M'FN$'hrfI#-CJ! +!bP)Ym')3,I"LX#h[Qf)!!,41ZJ[+5J"Q!!#i5Ulrr'HL,blrr%kk%N)J,[rmNDh +Z%Y#Ym)!V32#)+fh`J2#%5LhZ*9L2C`!!N!!SEI#!,Llrr'"3)#hdPZ#)("5a"KM +'%#hdQE%')#hdNR)BikJL,I5@i)Q!JA)!%JBJ6H@*dF%L+2LDXi!V325@)LhdNZ# +*G!!8"L"0jBV4`L3Sp*UeJ5Y"p**6KdU(E+T+,HiDCbK#,HiDF!M3VI#!+d$`K,# +Ym)KM&$YmrpR`M$Ym!!(Z%'!'1h`!!qi360m3`%jH6R919J!!,`FH,J!))'h[T"# +(8Uh[T#!Ylk5`VHqJCJBVEHqFlk4+EHiLCL!-"`#"CK*`!E#YlKCR#MYm!!(Z)Q! +!!3BE4qi1B!!!i!aY!!(Z)QCD$!F!JQB+1h`!!ZiLB!!!jKYm!)(Z$L"Ym(J3[!# +"8Uh`H#!Ym(L`VI"mCJa1ZJ$-5QhZ%'B!!,j6VHi@C`!!YJ`(!)&Q#R!"X+hZ&QB +!!+C#EHiL'dIZ$Q"m3QhZ)NS(CdK6"h!!%!H4VHi@5UhZ&Q`Z1h`!!Hi31hcrfI# +-B(3JEI"i8Uh`H"#YlJiJ,I"iX+h`I'B+6VS!BNTYlK"Q9"!(8`G+!'EBB%SJEI" +i%,`!J9+Ym(JJ,I"iX+h`I'B+6VS!1%TYlK"Q+P1YlKCR*"Ym!),Z$L"Ym(J3VHi +18Uh`H#!Ym(L`VI"mCJ41ZJ!-8khZ&LiI6Pj1G8j@rr`J,I"iN!#Ym(3Y32rm2`! +[,I"d6VS0q%*A2bh`FNKZrr`[,I"d6VS3KMYIm)a+EI#-@)pR#$Ym!!,Z%'!'+fh +`G2"i6Pj1G8MR!aJVI!%M4@IdNLYmLD[0lr5@5Hh[Nhi!(Lh[NQ"#("`3,I5CX3C +`!"!'jBJQ3#!Yp**b'11S)LhdPZ#*J)&"lILDdFXL%,1!+d$dPL)Yp*,JL8(Yp*V +4bb33YB%V3I558dG+4fbi60mB`%je6PErH%MR!aK1ZJB`6VS"k%SYr04R2NKYr04 +)EHiT5'hZ+8KYlLQTLd+R2c`"pd+R5(MrrkPm,9rrr%KY!)T)E[rkUC%[,[rmUB- +-EJ!"rrTQ!!'B3UF[2%&8@%8r2!2SU"mQAb!,CcBlEIh8m'`VEIh@m'iJ5k!T3QG +"lI"X,`K"lI"Z,`JJ5b"36T!!-"rJ5"i!,`ZTSdS(C`!"8'"%3Lhm[5mYr*j)EHi +T5'd!FMmmrrp#TdKY!)*)EIl%2c`"pNKY!(Sr2!!%UHT+,IbpC`!"'M!i!K4%3$Y +!m'`VH!1Bm'ipEI"XrjC#E[qF3UlrNN(Zri#L"dT!CJ!!m#mZrl"`!$!Zrli[!%k +Y!%+`VIc!E"*)EHki2c`!dNkk$*jFMf!!!-J-EY,Arm"Q'"Ym!!(m[N*R2c`!m%+ +RUBJ-A`!"CJ!!U%SYr,aR"%kk!`*"lHiT+dM`9%*Ym&J[,HqdU491ZJdQ)'h[Y#e +S!"$rH#eS!"6rI%KZrhLT+KYm!!(r$Q!Z+'hmcQ!@,`a1ZJ0@@)mm!%T'Ce4`6X( +'d)`S3("1`HhmdY#Yr-k`M',F8Lhr$K!Yr`k`,HqEBmK1ZJXq3QG#TcmYm'a1ZJj +d9)p#Tbmm38a59$mm!qLS(dUIC`a#Ccmm!qK#TkQ&9)p1ZJ3i60mB`%jH6R919[r +Z51F"#%KYrH4)E[rZ5'lrm+Re+hJ$Q2h@-$J#&%4!1d$pe%(YrG3V52"Q'h`!!I" +L3QFr%#mS!!*)D!!3(c`!!8KYm'41ZJlS1er`M%TYm)aQ!!(D'h`!!HiSF!JY32r +m3QFr,I"N5'lrr%KYra"1ZJf+1er`M%TYm)aQ!!'`$#d!!Im3C`S-,3!#ra"Q!!' +B$#d!!Im4CJ!"MMYYra,mc%UYra4Q$N)Ym'*1ZJC85J"Q!!'@'fhr%HqEF2mV32# +13QFr,I"N2c`!!5mYra41ZJf51er`M%TYm)aQ!!&3F!FY32rm3QFr,I"N5'lrr%K +Zrr41ZJd'1er`M%TYm)aQ!!%X2c`!!dKZrrK1ZJT51flrq2c5$'d&h2c5A)pZ!!% +)'flrq[c85'hmeA!!%#lrqLm!6VS+!%TYm)a3MfB!!1jq!#KYr-jJ!!#S,`a)H!! +"6VS*iNTYm)a3MfB!!0"+&'S%F!&J!R!!'8!!)!)8!(m-&!!IBJ!!X%KX!!&`!"! +8,`"1ZJQ`5Qh`MCJ!!RJJX!*!$)'FB5'`!0NKi!!*1ZJQ55Qh`MCJ!!J'! +m5'`!)8Ki!#e1ZJPk5Qh`MCQJ),!#3!ceR"KYm!!(m[&*YlLBJ,!"'d+`!5Yk +!)#`!2Y#X!%,4VIc!5H`!6P0ZrrK+E[riE!$r8#!Zrr5`VI#1CL")H!%r,`G1V3" +D+d$`@NU!CJC`!5Y!m&SVEI"Dm&jJ*MYmrpR`M!aYrpR`M'B'1h`!C2#-)'h`CNK +S!""1ZJ2Q@)p1ZJ(J60m3J%jH6R919[l`51F$#%+R2c`"p%+R5(MrrkPm+&p)E3# ++5'lrm+Q4$'i!![r`CJ41ZJ'U,``r2!!$5'lrrNKZrrT)E[rbUBd[,[rk5'lqm+Q +3!(i"B"amrpa(!NB!"e*')%l3aa!Sr[!J6G$'d5M[NP*(F!!3,[l`X%GXfK!Zr[! +E31q583"M"KYm!!M[NLm-UB0-ha$!6Pj1G8j@rj4)j`-i+'i!##iYm'i),!#3!b" +Q(K!X!#'`,Im1CJi[$%kklkK+!&L2CJ!""R!"B!!""JJX!!-!)'B!!0j+,IbqCJ! +!S#m-5'lrP%kk#&Jl32#-5N"3MfCN##i!"2qbC`JVE[r%m'jJHNSYlL4Q-Lm-2c` +!m8kk#&j+3&b2C`!!XQX!!+jA3'FBDJT53'S!!+*J!!#!98"U!!#B'h`!!HiN3QF +r,I"X,bh`ELm-6VS0(MYIm)a+EI#-CQTJ#!aYrpA`M'CJ3QFr,I"X,bh`ELm-5'h +`ENkk$+JlAr#-5Qh`M'C#F%l!l!!f4r3)6NAX!%jJ&Lm+6VVr"M`!5NCBMfF`F%l +"aY#+*%#hbQEQ6VS("Q!'!#`!#!!J+dI`ER!"d'`!0Q!5,`a1ZJ)@5J"BMfEL+dI +`ER!!60mF`%jH6R9+,HiSC`a#CcmYm'41ZJQS9)qTp%je6PErr%MR(cLJBdKYrrb +SEUMq,c`!!2rr)"qJ-UN5U6#Tc%+RUAZS8+!fS$B-H2rr!rCQ%%KYlNir2!$56VS +(3URdA)mJ2!!!)!#K(LY)m)!J2!!"b3LK(LY)r-iJ2!!!3!#K(LY)m(3J2!!!)!# +K(LY)lj`J2!!!J!#K(LY)lkJJ2!!!J!#K(LY)lk`J2!!!J!#K(LY)ll"+VIc1Cbj ++VI"dCbK+VI#!Cb*+VHqFCaa+VHqSCaC+VHqXCa"+VHq`C`UJB3b!!!"!!'`F5Uh +`J'F')'h`J+!I5'hZNMmm!0*1ZJDHUI4FMb"Ylja"k#!!+dM[S#*Ym(4$k8!!+dR +`I%+R5'h[Z%KYr-4)EHiT,c`!!3!!5(Mrrd)R3UHT%bYIll4+VHqdCJ+Tp#mYll5 +SFd*RU)G#CkL+3UFr2!$),bh[Y+Qq5TpQ!URd3QlrrNRYm**(lILD4HhdQQ"mIJ" +m!(S!1#lrrRB)B&K`!F"%28$rr()"`SC)`,'"CacLMJJ(!!"R"!M'!"rLM`U(lEL +$)!U'lEL$)'!1iSi)"`!!C`3)aJ!IiSp`!F#&-Llrr%M"Xi"R#Z+0#SAYZ)-JB!, +LMH*%8d0+3fbL*)FQKLL&8QlrrPL-@)YBLJaZ!3$rrQd!rha-haci6Pj1G8j@rBC +)j`-B*Qi!#$"Ym)`[#%KZrSC1ZJMD5HhZ+6!Ym)aU0!4!rp0REQS8"%$rpfGQDJC +H3'GJB("43'SbB'S%3!!+Cf4U#P*!DP*H3'TDB"j93'T8B%`%3!"NC`*J5NSYlL9 +R"%RYl`)q2!%%B$j(l[f'2@h`E2qF3HlpKLe)rjK#E[qL3HlrKU)(1d$`M%T!C`4 +(lHiT2M`"$Q!32M`"$f!+2M`"%Q!%2M`"%5m,5'lqKLm-5'hZ+DQ,3QFr"d+RUBJ +m(`a'!!&A`%3!60mB`%jH6R919[li5LhZ+'F33LhZ+%*R2bh`C%kk"XT8Md(YrL3 +V52"Q5Lh`BQFq)'h`CM!34%!a`!)8)'h`CL(S!!)$Q!`Y!!(`BQB-3Hhpe#Y)m'C +J!!#S%#h`BV!YljYR!!#F3HhqG#Y)m'Br2!!8UFK+,I"LCK4)EHmU5'hZ+8KYlLP +)EHiTUBYJ)R!!%#h`BLm!5'lr!%kk"iK)EHiT5'h[0NKZr`")EHiTUBX[,IbH5'h +Z+8+R2c`!!8KYr+*#Tb"Ym'C)D!!'2c`"p8KY!)Sr2!!%UHSJEI"Q5LJ!"QB'F!& +J!!%X)'h`CL&i!jJ!!M!i!K4%3#"Ym'B`J%*R)'h`CMm3,bJ!!NKS!"!I2!!"5'h +`C%kk"a`lAr#-5Qh`M'B!!-j`##e!r[a#CcmYm'4)E[lm5'hr%%kk"F3lAr#-5Qh +`M'B!!*i-,3!"ra"R%J`Y!!,r%'F+1hcrfI#-B!!!K$!Yra+`EIc-CKa+,I"LC`S +3,Im4X#h`BQB-5Lh`BQCB5Uhr&'C5F!!3,Im4,`")E[m!6VS'LNKZr`!`,Im5X'h +mc'B)3Hh[1L!)B!C"lHmq)!J[!%KYlLP)EHiTUBY#Ccmm!0C#TkQ)3PFr,I"N6VS +&%P52B!$qQ"Ym!!(Z+(!!B#a#CcmYm'41ZJ6i9)m-EIrCm)aQ"MYm!'6`M#"Ym'C +)D!!36VVp*PL2B!$qBNjH6R919[rU,``SEJ!3,``r2!!,5'lrlNKZrra)E[r`UBd +[$$mm!!&)E[rZ5'lrq%KZrr#TM5"Zrr`J8#*ZrrJL84!S!"'`+3!4Ca3[,[rm)'l +rq#"3F!!3+!!42`#TA5"Z!!`-8!!$CM!JEJ!-##J!N!-1Cb3JEJ!-)#J!!J+!!*! +$rh*PXS"Q%#"Z!!J`[!!-(A`!!3!8B!4#,J!8+&p1AL"I6qm!$%l36PEriLm(2Li +!$!a(!!aQ#KYm!!(m[Ai$B%S-4`!,CN3[,J!)2c`!!8KZrr*)E[rm5'lrp+Q0)'l +rr#"35LJ!%@BL5LhqcQB%IQGJ'%(Zrq*`!+!`8N!),J!$rr"R"(jUB!*qD$e(!!i +Z(djH)&pFMdl36PB!!"em!!%!$%jH,Tp1G8j@rqj)j`%B+'i!%#CZ!!`q%`a(!!C +Q6VRV!!*Q!!#B5'lrlUKd,``r2!!"5'lrqNKZrra)E[rbUBd[$+Kc,c`!!`!$U*Y +)E[rb,ccrr2rmU+P)E[rb,c`!%!!3U,![,[rZU(0J8!a(!!0Q5JJV!*!$$QC#I[r +1+`!&$!F!$@F'$!F!!fB`,``r2!!"5'lrqNKZrra)E[rbUBdJE[rm)&"++!!4CK! +JEJ!)-,`!!4em!!%!&'!%3Li!&%cI')"1AL"I6qm!$%l33QFr,I"X,bh`ENKYr,) +[2$q3"#mm9%9B9%kk"-K#9cmYm'`[,I"Z5'hmXNkk"BT8Mdje6PB!!%*R2bh`C%K +Z!!J[,J!-6VS#XMYIm)`r,J!+,bi!$%kk!!C1ANje6PB!!#"Z!!Jd,J!-)Lh`MN2 +Ym**J%(!!%"Lc!19))$%!!1#*XB&4b[rZ+d(`MNjH6R919J!!,``SEJ!)1@h`E!! +@+@h`EJ!`+@i!$!!53L`!'N*X!"`J6(!*SQ!SAdjH6R919J!!,bi!#NKYlLP)EHi +T5'hZ+DQ,3QFr,J!)3UHTL$!I6Pj1G8j@rqLTY%)R2ccrrdKZrr#TF$!Zrr"8MfF +!!)4VjPe!Ce4Ui&K!DYa#CbmZrrT)E[rXU5`-A`!$CXSJ,[rXX+h[Y'E!5'lrqUK +a3QF[,[rk,bh[Y%KZrqLTE!aI!!TQT%*R,blrk#mZrrT#TkPS5PpRNR!"B#iJ,[r +bX+h[Y'D%,bh[Y+NL)'h[Y%KS!"#SSdkk!"B[,HqdU50J!2pSF!"J!R!!6Pj1GDL +H5'hr)+LK,c`!%`!+U*0)EHp+U)41ZJ"k5'hr++LK,c`!"J!"U*X[2!!H!!USNcm +Ym&K#CkL5,c`!1!!+U*0)EHp@U)4#CdKYleDSM(!9d&ml32m`6VS!5Mmm!!1SKcm +m!!QSLLmm!&8!!kL65'h[H+L%,c`!93#PU*0)EHiUU)4#CkL(3QHSLLmYll5TD8j +e,c`!%`"IU*-[,I"8U)41G8j@r`!r,Im`2c`!1+L6-'hZ*Lm)5'lr!%kk!G*)E[m +!U)41ANje6PErq%(YlLNV52"85'hr'+LM5'lrq$mYrc!r2!!XF#E3EIm`2`!r2!! +mU+G)E[riU+01ANje6PB!!#m(IJ!J,J!)NDh`AQ!+)#h`@Y'Ym&j54dUYm&jYm$! +Ym&M34`a!!8"[#$im!8#HEI"BF!V3EI"B2`!r2!!HU*-r"d*RU*,IEI"B,Kp1ANj +e6PErcL"2-@i!#!!BS!%p3!!+6PiJAe526Y"4`@!#8-&19[r1)%mKEJ!)!#!aEJ! +3!"JLEJ!-)9%!*%*S!#a#U!!Z5J&Q"+!#B!+J!ce!!")LEJ!-)UJ!+%jH)Pp2l`! ++6Y&19[r!)%maEJ!)!"BKEJ!+!"+J%ce!!!j1AL*IA)p1d8j@rmiJ6c&Z!!i!'$& +Z!!`!,#&Z!!J!,U"%28!!%%jH)Pp3Mdl4)Pm3(b"ICJC`"U*JB!4`"UCJ2S"1d5* +I%"mJAfB%SJ"J!UB!2S"1d5*I%"mJAfB%SJTJ!UB+2S"1d5*I%"mJAfB%SJKJ!UB +)2S"1d5*I%"mJAfB%SJPJ!UB*2S"1d5*I%"mJAfB%SN&J!UC"2S"1d5*I%"mJAfB +%SJaJ!UB-2S"1d5*I%"mJAfB%SJeJ!UB02S"1d5"[!!3J,`!)3QHTlL"I8%p1d%j +@riB["ceZ!"ErR#eZ!",rYLeZ!!lrQ%)Zrk!GEJ!-rk&`!#e!rk*9MdKZriC`!"m +!6VVr2$iI)'i!#$#Zrjip4`!B,LlrJNjH)&p2l`!36Y#&5%p348i!!%j@riB["ce +Z!"ErR#eZ!",rYLeZ!!lrQ%)Zrk!GEJ!-rk&`!#e!rk*9MdKZriC`!"m!6VVqp$i +I)'i!#$#Zrjip4`!B,LlrJNjH)&p2l`!36Y#(5%p348j54J!!6PErKNMR!`!X,J! +82@i!'2qF,8ErYLeZ!"$rQ%)Zrk"9MdKZriC`!"m!6VVqXMiICMC#E[qL9Bp)E[q +'F!!I!%kkrY)q(fBJ,@i!$2qU,@i!#2qQ,8ErYP@25'lrKR!!(`"1Z[l#2Kmp4`! +D61i!`2pq6PiJAdr[!"*1d)G)3e*&394&!!"19[q',`FpEJ!8rj`YEJ!3rlBYEJ! +-rjK9MdKZriC`!"m!6VVpqMiI)'i!###ZrlBp4`!@,LlrJNjH)&p2l`!16Y#*4%P +53e*&394&!!"19[q'2@i!%2qF,@i!$2qf,@i!#2qB3LlrS&@25'lrKR!!(`"1Z[h +f29m!%NjH)&p2l`!+6Y#(5%4&6%9843!!6PErKMeZ!"$rR#eZ!!crYLeZ!!MrQ%) +Zrk"9MdKZriC`!"m!6VVpb$eI!"*1AL"I6qm!#Nl3L8K6494'6%p$5`#3"!)Z!*! +$#J#3!j*#H!T+RFj1ZJ!N3QG)H3!!rrp)E`!%5&G)H!!")MVrhNke%!!JE3"X6T! +!UI4CMbmm@N956d*RUD!N9eQ2,ca%394"3QHTS#"A)&!LH!N)*&*J$M,BCJSb'Q! +#3KP4bIrmZmPQlUQMUD0CMbmm4&*&6%*RUD!J9k!P)&$L3#30B!Bb'0@e%!"4b2r +iUD01G5"I-KJd',"B9mRrqNT#Crj1m#$m)&mb'$3BX*KAbIrk5N*RrNl`)2SJAc) +B0"L`3Qi+N!""E3E33%(`!!)`%'Iq6[!!!#![!!3[33!%)Lm!##pI!!4)jc`!*!! +Q!8K#a--S!#S"5%A)aG4%5%+3!m$"d)*-h`!m)Kp1G5![!!3[33!%)Lm!##pI!!4 +)jc%!6VS!R%cI!)`L(dje)#m!"#p"!!3L,`!),em!"%MR-3"1ZJ"m)!&-h`#-)Kp +1G5![!!3[33!%)Lm!##pI!!4)jc%!6VS!,%cI!)`L(dje)#m!"#p"!!3L,`!),em +!"%MR-3"1ZJ!-)!&-h`#-)Kp1G8U!DKa+J@S-4)"%J8kk!#"%J8je4)"1ZJ!@4)" +%J8je5S&U#N5"6VS!"N5!6R8Z2!!!rrqbJ'-')J"`!%jeX)GL$)$"5%!b!%*!5%" +1GE+(BKSZ!%*!5%#!`8K!5%Fq!%K(MX%`"dK(-JG1G53!*J(LL1+*XSGLq)$"`)F +b!m,!,J0)4ml!5%I5Kf8)NS*L"%5"6R963'$N6R8!N!1)!*!$Q!!!%IJ!N!0i!*! +$)!!%2c`!!DR`!*)r2!!"UI!!TMmm!!'Tm!#k2c`!!DR`!0Br2!!"UI!"$$mm!!' +Tm!%X2c`!!DR`!8ir2!!"UI!"EMmm!!'Tm!)S2c`!!DR`&h)r2!!#UI!@@Mmm!!+ +Tm"F!2c`!!UR`&i)r2!!#UI!,8$mm!!+Tm!#3!`T)J!!%R!!!"*`!N!3R*N&eG'p +&H(4bB@0dEh)J-5ic-b#T)$%j16)J3QPXE#"(EfpNE@&Z!*!$(%9B9&)!N!-"580 +1)`#3"B"'8N9'!*!&J!#3!aX!+`%C!$`"5`!!!3!!C!#3#!46G'p`!*!$"d&38%` +!N!8"!"rrrr!3!!!3&m!(d"H!!p!A`!I3&q!2d"A!"e!3Rr)3N!-B%"!6Q"#3!aJ +3%"ri%*!$'"!3%jJ3N!-B%"!Iq"#3!aJ3%"1B%*!$'"!3(rJ3N!-B%"!6Q"#3!aJ +3%"ri%"#2qK!9`!G3&q!2d"I!"p!AJ!23&m!(d"!!!"!Irrr`(rrrm"rrrr!Irrr +`(rrrm"rrrr!Irrr`(rrrm"rrrr!Irrr`(rrrm"rrrr!Irrr`(rrrm"rrrr!Irrr +`(rrrm"rrrr!Irrr`(rrrm"rrrr!Irrr`(rrrm"rrrr!Irrr`(rrrm"rrrr!Irrr +`(rrrm"rrrr!Irrr`(rrrm"rrrr!!N!-9!&!!8!#E!5)!!3%!N!F"p!#3""8!N!A +3!C!!!!%!N!J"p3#3""8!2!!3!2B"m!!$!3#3"`(h!*!%'!#3"F`"L`!"!*!)!IB +!N!06!*!$$!"3!&!!Y!&b!0*993#3!``!8!"'!-3"QJ$@998!N!--!&!!8!$b!CS +!m999!*!$$!"3!&!!j!'Z!20993#3!``!8!"3!13"QJ%%998!N!--!&!!8!#d!A) +"$P99!*!$$!"3!%B!a!'Z!4*993#3!``!8!"3!13"L`$b998!N!-1!&!!8!$%!@J +"%999JJ#3"!i!8!"3!-3"Z!$`99@$!*!%$J"3!&!!a!&S!3p99B)!N!3N!!%!N!9 +'!0)!@J%B"!*25`#3"3S!4J!k!4L)!ei`,[m!N!0`!!%!N!9@!33!DJ&+"!*25`# +3"3S!4J"+!8U)8&4SDA-JDA-JEQpd)(4SC5"bCA&eCA0dC@3JFf9RE@9ZG#"QD@a +P,Jd09'KTFb"QD@aP)'Pc)(0PCfePER3J)ei`)'pQ)&ia)'&bBfKTGQ8Z!*!$cJ! +%!*!&K!$k!*J"3!3%8fYTF!#3"@B!qJ"k!8!%"&0dEh!!N!9Q!%B!HJ$Q""&5CA" +XB@0P)&4SDA-J4QPXC3)!N!@%!%B!Q!$Q""C5CA"XB@0P)%&-6#"%GA"XD@0KG'9 +c!*!&#J"'!&S"3)K@dPi`db"KE(*PB@4j)'9iDA0dFbi0$84[)(P[G5"hDA0S)(4 +[)(*PF'aKBf8JDA3JGfPdD#"dD'8JCQPXC5pQEfaNCA)JCR*[E5"dD'8JBA*MD'P +fC6m!N!1S!!)!N!9f!3i!LJ&8"!46DfP`!*!&GJ#l!)S"!33%8h4[F!#3"3S!4J" +U!95)G&4SC5"'58a&)0*H-0-JBf&ZEQpd)'*P)'9iG(*KBh4PC#i0$8%J4Np-4%9 +5)(GTG'JJG'KKG#"ZB@eP)'&XFQ9KC(NJCAKTFh4c)#KjEh8JBf&ZeA3JFQ9`E'& +MC5"K)%C26%4&8L"hDA4S)'%J4NP-45NZ!*!$6!!"!*!&GJ$k!)S"3!3#6dX!N!8 ++!%B!DJ&!L#a$B@jZEh3JFQ9KC#$5AM$6,Jd09'KPAM)JBA*MD'PfC5"TFb"NB@e +KCf9N,J#3!eS!!J#3"8B!dJ"D!4J%"&0VDA!!N!9'!(m!@J$&"!46G'p`!*!&#J" +'!$S"')JQdPi`db"TFb"XEf0VC@3JB@jN)'0KEQj[G#"LC5"YEf4TCQPPC#i!N!0 +N!!)!N!9@!4J!DJ&H"!46DfP`!*!&9J$&!'S"#`3%8h4[F!#3"3S!4J"+!9k)-&4 +SDA-JGQpXG@eP)'Pc)'CeE'`Z$3h5AM$6)'0[G@aN)'j[G#"LC5"hFQPdG'9Z,J# +3!dS!!`#3"5d!JJ""!-J%!Np,!*!&,3![!%%!G33%8A9TG!#3"3N!@!!C!-L3!!# +3"JN!#J!C!&#)#9"KFh0hEh*N1J#3"1)!#J#3"Dd"0!#r!B3%"%a[B@3!N!B%Z`" +3"-d%"NKTC'4PEJ#3"C3"0!#Q!B3%"N0KEQ0PE!#3"6%"(!"&!Bq!!*!'6J%d!'! +"K!3&4@TPBh3#!*!&C`%d!(N"K!3&4(*TGQ8#!*!&-3!-!--"'J#3"c%"'3$$!5S +!N!H'!6!!K`'0J!#3"`58!'8%p)J!N!B'!!`!&`''L#P3E'9KFf8JE'pKC#"H-(0 +PCfePER4H-9ib)'pQ)(4SC5"KFQ0SDACPb3#3"(3!!J#3"AB!k`#+!6%%"&0VDA! +!N!9f!*J!LJ$H"!46G'p`!*!&#J"'!'S"-BK!dPi`db"MEh9XC#"ZEh3JBQ8JCAK +dFQ&MG'9N)("bEh"PFQaj,Jd09'KPAM%JBA*MD'PfC5"TFb"NB@eKCf9N,J#3!c3 +!!J#3"CN"M3#Y!G-%!Np,!*!&Q3%k!+d"J!3%8A9TG!#3"3d!$3#0!G1)!Pi`!!! +",!!1!*!&NJ'U!+3"qJ3)6faN)%p`C@i!N!3%J!!l"0!!633'5'PNC'9Z!*!&G`% +V!)N"H`3'3f&ZBf9X!*!&)J"!!$B"#i!!N!BK!5X!-`&l"!9&DQ9MG!)!N!8m!5X +!6J&l"!9%FQPfC3)!N!90!$N![`%6!*!(63%5!,m")`#3"f%"*`"L!Aq!!*!&""3 +!&!4j!(5)!*!'NJ%V!+3"H`3%6h"PEJ#3"Dd"+`#r!AX%#N9iG(*KBh3J%88!N!8 +'!!B!&J$(L"T6C@aPBh3J4'9cG'PZBA4TEfiJ4QpXC'9bb3#3"5)!"J!b!$f)"eC +[E(9YC6S#!*!&1!!'!%J!0iJ(4QpXC'9b1J)!N!0Q!!)!N!9@!-J!DJ%1"!46DfP +`!*!&9J"e!'S!Z`3%8h4[F!#3"3S!4J"+!3k)-8%JCQPXC5"PFR*[FL!SAM%T)'p +MBh9bFQ9N)(GSD@aP)'&MBf9cFfPZCb$5AM$6,L!J!*!$Y!!#!*!&9J%B!'S"AJ3 +(4AKdFQ&MG!)!N!9@!--!DJ%*"!44G@Pd!*!&#J"'!%S"ASKm9'KTFb"TFb"KEL" +04P-JGQpXG@eP,L""GA4[4AKdFQ&MG'pb)(GTE'`JEQpd)'*P)'&LE'8JG'mJF(9 +d)(4SC5"QD@aPFb"TEL"QEfaNCA*c,Jd04'mJH@pe)(GTFfJJG'mJCAKdFQ&MG#" +dD'8JCQPXCA-JB@jjGf&j2`#3!f!!!J#3"9B!b!"U!3i%"&0VDA!!N!9@!(8!DJ# +l"!46G'p`!*!&#J"'!%S"$SJV35"NDA0V)'9bFQpb)'pMBh9bFQ9N)(GSD@aP)'& +MBf9cFfPZCb$5AM$6,L!!!!%!N!-ZI!!!,A`!!!*q!'a(S!J@!*!$(!*q!!a%394 +"!*!$DPT&8Nm!N!0f4&*&6!#3!i*$6d4&!!)!MP0*@N8!N!1b49K88J#3!lj#6N4 +-!*!$bN019%`!N!2@4P*&4J#3!q**3diM!*!$lN4-6dF!!`$k38a59!!+!5T%594 +-!!i"VJ!!rrmS!*!%E%F%!!$rr`J!!E!!E%D`!!$rrbJ!!F!!E%Dd!!,rrcJ!!F3 +!E%Di!!(rra`!)&!!N!ErrbJ!)S)!N!6rN!3!!#-1!'a'[!!!rrm)!#-F!'a'U!# +!rrm)!#0(!'a'T!$)rrmS!#0R!'a'S!#!rrm)!#1'!'a'R!#!rrm)!#14!'a'Q!( +drrm-!#59!'a'a!(errm-!#5Z!*!%!IIrr``!*-F!N!3"p[rr$!!Ni!#3"G,rr`` +!*2`!E%D8!0ErrbJ!*3`!N!AarrmS!#8F!*!&mrrr+!!P,!#3"!%%rrmS!#8m!*! +%!3lrrbJ!*8`!N!3"%[rr+!!PA!#3"I,rrbJ!*@`!N!3"%Irr+!!PI!#3"I$rrbJ +!*Bi!N!3"$rrr+!!PS!#3"G,rr``!*E)!E%GJ!0ErrbJ!*GS!N!AarrmS!#C1!*! +&mrrr+!!R)!#3"!%%rrmS!#I-!*!%!3lrrbJ!+"`!N!3"%[rr+!!SHJ#3"!(drrm +-!#ML!*!%!IArr``!+6!!N!AbrrmS!#S@!*!%!IIrr``!+Si!N!3"p[rr$!!UaJ# +3"!%4rrmS!#[f!*!&m2rr+!!XB!#3"!%2rrmS!#dB!*!%fk!: diff --git a/release/base/contrib/perl-archie-3.8.tar.gz b/release/base/contrib/perl-archie-3.8.tar.gz new file mode 100644 index 0000000..9446b44 Binary files /dev/null and b/release/base/contrib/perl-archie-3.8.tar.gz differ diff --git a/release/base/contrib/xarchie-2.0.8.tar.gz b/release/base/contrib/xarchie-2.0.8.tar.gz new file mode 100644 index 0000000..62a2b6c Binary files /dev/null and b/release/base/contrib/xarchie-2.0.8.tar.gz differ diff --git a/release/base/doc/manual-3.5.ps.gz b/release/base/doc/manual-3.5.ps.gz new file mode 100644 index 0000000..9271170 Binary files /dev/null and b/release/base/doc/manual-3.5.ps.gz differ diff --git a/release/base/etc/ardomains.cf b/release/base/etc/ardomains.cf new file mode 100644 index 0000000..c33f9f3 --- /dev/null +++ b/release/base/etc/ardomains.cf @@ -0,0 +1,18 @@ +# +westeurope1 de:ie:pt:es:uk:at:fr:it:be:nl +westeurope2 ch:cy:gr:li:lu:tr +westeurope westeurope1:westeurope2 Western Europe +easteurope bg:cs:cz:hr:hu:pl:ro:sk:si Eastern Europe +scandinavia no:dk:se:fi:ee:is Scandinavia +europe westeurope:easteurope:scandinavia Europe +usa edu:com:mil:gov:us:org:net United States +northamerica usa:ca:mx North America +southamerica ar:bo:br:cl:co:cr:cu:ec:pe:ve South American +centralamerica sv:gt:hn Central America +asia kr:hk:sg:jp:cn:my:tw:in Asia +mideast eg:.il:kw:sa Middle East +africa za Africa +anzac au:nz OZ & New Zealand +world1 europe:scandinavia:northamerica +world2 centralamerica:southamerica:mideast:africa:anzac:as +world world1:world2 The World diff --git a/release/base/etc/arretdefs.cf b/release/base/etc/arretdefs.cf new file mode 100644 index 0000000..fdb8490 --- /dev/null +++ b/release/base/etc/arretdefs.cf @@ -0,0 +1,3 @@ +anonftp:unix_bsd:image:.Z:anonymous:::-R:*?:ls-lR +anonftp:novell:image:.Z:anonymous:::-R:*?:ls-lR +anonftp:vms_std:image:.Z:anonymous:::[...]:*?:ls-lR diff --git a/release/base/etc/arretrieve.cf b/release/base/etc/arretrieve.cf new file mode 100644 index 0000000..5545b79 --- /dev/null +++ b/release/base/etc/arretrieve.cf @@ -0,0 +1,2 @@ +localhost anonftp * 0 rw 1d 19940124155459 0 +localhost webindex * 10 rw 1 19940816041633 0 diff --git a/release/base/etc/arupdate.cf b/release/base/etc/arupdate.cf new file mode 100644 index 0000000..4f1cc3d --- /dev/null +++ b/release/base/etc/arupdate.cf @@ -0,0 +1,3 @@ +archie.bunyip.com anonftp * 10 rw 0 19941228054741 0 +archie.bunyip.com gopherindex * 5 rw 0 19950105211457 0 + diff --git a/release/base/etc/catalogs.cf b/release/base/etc/catalogs.cf new file mode 100644 index 0000000..907116c --- /dev/null +++ b/release/base/etc/catalogs.cf @@ -0,0 +1,7 @@ +# +#database type access method location +# name +# +anonftp archie anonftp anonftp_db +gopherindex archie gopherindex gopherindex_db + diff --git a/release/base/etc/domain.order b/release/base/etc/domain.order new file mode 100644 index 0000000..cd89905 --- /dev/null +++ b/release/base/etc/domain.order @@ -0,0 +1,4 @@ +# +# Colon separated list of domains... example: ca:edu +# + diff --git a/release/base/etc/email.help b/release/base/etc/email.help new file mode 100644 index 0000000..d97bbf3 --- /dev/null +++ b/release/base/etc/email.help @@ -0,0 +1,366 @@ + Archie Email Help (Version 3.2) + +HELP for this archie email server, as of 11 April, 1994. + +To perform an archie search via email, send mail to + + archie@ + +where is the name of an archie host, some of which are listed +below. + +The "Subject:" header in mail sent to archie is treated as part of the +message body. + +Command lines begin in the first column. All lines that do not match a valid +commands are ignored. + +Empty messages are treated as "help" requests (this file). If no command +in a particular message can be recognized, the message is treated as +"empty" and this file will be returned. + +The current (and complete) list of archie servers can be found with the +"servers" command (described below). A sample list is: + + archie.au 139.130.4.6 Australia + archie.edvz.uni-linz.ac.at 140.78.3.8 Austria + archie.univie.ac.at 131.130.1.23 Austria + archie.cs.mcgill.ca 132.206.51.250 Canada + archie.uqam.ca 132.208.250.10 Canada + archie.funet.fi 128.214.6.102 Finland + archie.univ-rennes1.fr 129.20.128.38 France + archie.th-darmstadt.de 130.83.128.118 Germany + archie.ac.il 132.65.16.18 Israel + archie.unipi.it 131.114.21.10 Italy + archie.wide.ad.jp 133.4.3.6 Japan + archie.hama.nm.kr 128.134.1.1 Korea + archie.sogang.ac.kr 163.239.1.11 Korea + archie.uninett.no 128.39.2.20 Norway + archie.rediris.es 130.206.1.2 Spain + archie.luth.se 130.240.12.30 Sweden + archie.switch.ch 130.59.1.40 Switzerland + archie.nctuccca.edu.tw Taiwan + archie.ncu.edu.tw 192.83.166.12 Taiwan + archie.doc.ic.ac.uk 146.169.11.3 United Kingdom + archie.hensa.ac.uk 129.12.21.25 United Kingdom + archie.unl.edu 129.93.1.14 USA (NE) + archie.internic.net 198.49.45.10 USA (NJ) + archie.rutgers.edu 128.6.18.15 USA (NJ) + archie.ans.net 147.225.1.10 USA (NY) + archie.sura.net 128.167.254.179 USA (MD) + + +If you do not get mail back within 1 day or so, try using the "path" +command described below. + + +Mail destined for the ADMINISTRATION of individual servers should be +addressed to: + + archie-admin@ + +where is one of the hosts listed above. If you are having +a problem with a particular server, try sending mail to its administrator +first before contacting the general archie contact address below. They +may already be aware of the problem. + +To request the ADDITION or DELETION of a site from the archie database, +send mail to: + + archie-admin@bunyip.com + + +To contact the IMPLEMENTORS of archie, send mail to: + + archie-group@bunyip.com + + +For your information anonymous FTP may be performed through the mail by +various ftp-mail servers. Send a message with the word 'help' in it to: + +For BITNET/EARN sites ONLY: + + bitftp@pucc.princeton.edu + +or (general access): + + ftpmail@decwrl.dec.com + +for an explanations on how to use them. + +Under version 3.2 the email client implements all the non-interactive +commands and variables of the telnet client. However, interactive +commands like "pager" are not supported as they don't make much sense in +the email environment. + +For a complete explanation of the the archie system use the "manpage" +command to request a copy of the manual page, what follows is a short +summary of the valid email commands and variables. + +NOTE: The "site" command of earlier versions of archie has been disabled + under version 3.2 until it can be reimplemented with the new + architecture of the system. + +"Quick and dirty" summary +------------------------- + +For those of you who want to get something done now and read the rest of +this later, send the email to an archie server with the line: + + find + +(where is the name of the file you are looking for). You should get +a message back with results of your search. If you want to be a bit more +sophisticated, read on.... + + +Commands +-------- +In the commands that follow, parameters between '[' and ']' are optional. +The ellipsis ("...") signifies that the previous parameter can be repeated +multiple times. A '|' character means "or". + + +help [ [[ ] ...]] + + The "help" command by itself produces this message. + + An optional topic and subtopic(s) may also be given. A + list of words is considered to be one topic, not a list + of individual topics. Thus, + + help set maxhits + + requests help on the subtopic 'maxhits' of topic 'set', + not on two separate topics. + + +find This command produces a list of files matching the pattern + . The may be interpreted as a simple + substring, a case sensitive substring, an exact string or + a regular expression, depending on the value of the + variable search. + +prog This is identical to "find" and is included for backward + compatibility with older versions of the system. + + +list [ ] + + Produce a list of sites whose contents are contained in + the archie database. With no argument all the sites are + listed. If given, the argument is interpreted + as a regular expression (see the archie manual page for + an explanation of regular expressons) against which to + match site names: only those names matching are printed. + The format of the output can be selected through the + output_format variable (described below). + + Note that the numerical (IP) address associated with a + site name is valid at the time the site was last updated + in the archie database, but may have changed subsequently. + +mail
Mail the results generated up until this command to +
. This must be a vaid email address. + +manpage [ roff | ascii ] + + Return the archie manual page. The optional arguments + specify the format of the returned document. "roff" + specifies UNIX troff (or nroff) format, while ascii + specifies plain, preformatted ASCII output. With no + arguments it defaults to ascii. + +motd Re-display the "message of the day", which is normally + printed at the start of the returned message. + +path
Set the return email address to
. This overrides + the default path which the system automatically generates + by looking at the incoming mail header. This is actually + an alias for "set mailto
" (see "Variables" + below), and is included for backwards compatability. + +servers Display a list of all publicly accessible archie servers + worldwide. The names of the hosts, their IP addresses and + geographical locations are listed. IP addresses were valid + at the time that this document was last updated. + +domains Give a list of the archie pseudo-domains that the archie + server supports. See the manual page for an explanation + of archie pseudo-domains. + +set + + Set the specified to . See "Variables" + below. + +show [ ...] + + Without any parameters, display the status of all the + user-settable variables, including such information as + its type (boolean, numeric, string), whether or not it is + set and its current value (if its type requires a + value). Otherwise show the status of each of the + specified arguments. Useful for finding out what the + default settings at a server are. + +unset + Unset the specified . The subsequent value of + the variable is defined on a -specific basis. + +version + Print the current version of the email interface. + +whatis + + Search the Software Description Database for the given + substring, ignoring case. This database consists of + names and short descriptions of many software packages, + documents (like RFCs and educational material), and data + files stored on the Internet. + + Note that this database is currently maintained by hand + and is certain to be outdated (the net changes on a daily + basis). + +Variables +--------- + +The archie email system has 3 types of variables. + +1) Numeric +---------- + +Numeric variables may have preset internal ranges in which the value of +the variable must lie. + + +maxhits Allow the "find" command to generate at most the + specified number of matches (hits) (permissible range: + 0-1000). Default 100. + +maxhitspm Maximum number of files (hits) per filename located in + the find command. See the manual page for more + information. Range 0-1000. Default 100. + +maxmatch Maximum number of filenames to return with the find + command. This is NOT the same as maxhits which limits the + total number of files returned. See the manual page for + more information. Range 0-1000. Default 100. + +max_split_size Approximate maximum size, in bytes, of a file to be mailed + to the user. Any output larger than this limit will be + split in pieces of about this size. This can be set by + the user in the range 1024 to ~2Gb with a default of + 51200 bytes. Some mail gateways will not allow results of + over 100Kb and so care should be taken when setting this + limit. + +2) String +--------- + +String variables may have a predefined range of values. + + +compress The kind of data compression the user can specify when + mailing back output. Currently allowed values are + "none" and "compress" (standard UNIX compress program) + with a default of "none" + +encode The type of post-compression encoding the user can + specify when mailing back output. Currently allowed + values are "none" and "uuencode", with a default + of "none". Note that this variable is ignored unless + compression is enabled (via the compress variable). + +language Allows the user to specify the language in which the + help, etc. is presented. Individual servers may be + configured for a range of languages. + +mailto A valid address to mail the results back to. This overrides + the address automatically generated by the archie system + from the incoming mail header. Setting this variable is + equivalent to using the "path" command. + +match_domain Restrict the returned files to sites in the + colon-separated list of domains and pseudo-domains. See + the manual page for further information. + +match_path Restrict the files returned in the 'find' command to + contain the colon-separated list of pathname components. + See the manual page for further information. + +output_format Affects the way the output of "find" and "list" is + displayed. User settable, with valid values of "machine" + (machine readable format), "terse" and "verbose", with a + default of "verbose". + +search The type of search done by the "find" (or "prog") command. + The list of valid values is given below in order of + increasing search times. The given search string may + match a directory or filename in the database. + + exact String has to match exactly (including case) + subcase Substring match. Case sensitive. + sub Substring match. Case insensitive. + regex Regular expression (see ed(1)) search. + Case sensitive. The archie manual page + gives examples of regular expressions. + + + There are also compound searches made up of combinations + of the above search methods in sequence: + + exact_sub Try "exact". If no matches found use + "sub". + exact_subcase Try "exact". If no matches found use + "subcase" + exact_regex Try "exact". If no matches found use + regex. + + + Note: unless specifically anchored to the beginning + (with ^) or end (with $) of a line, regular expressions + (effectively) have ``.*'' prepended and appended to them. + For example, it is not necessary to type + + find .*xnlock.* + + because + + find xnlock + + In this instance, the regex match is equivalent a simple + substring match which should be used instead. + +server The archie/Prospero server to which the email interface + connects when "find" or "list" commands are used. Usually + defaults to "localhost" on most archie systems. + +sortby Set the method of sorting to be applied to output from + the "find" command. + + The five permitted methods (and their associated reverse + orders) are: + + none Unsorted (default; no reverse order, though + 'rnone' is accepted) + + filename Sort files/directories by name, using lexical + order (reverse order: 'rfilename') + + hostname Sort on the archive hostname, in lexical order + (reverse order: 'rhostname') + + size Sort by size, largest files/directories first + (reverse order: 'rsize') + + time Sort by modification time, with the most recent + file/directory names first (reverse order: 'rtime') + + +3) Boolean +---------- + +Currently the email interface to the archie system has no variables of +type "boolean". diff --git a/release/base/etc/find_files.cf b/release/base/etc/find_files.cf new file mode 100644 index 0000000..38b3de2 --- /dev/null +++ b/release/base/etc/find_files.cf @@ -0,0 +1 @@ +readme [Rr][Ee][Aa][Dd][Mm.][EeMm][Ee]* diff --git a/release/base/etc/hm_db.cf b/release/base/etc/hm_db.cf new file mode 100644 index 0000000..748fa1e --- /dev/null +++ b/release/base/etc/hm_db.cf @@ -0,0 +1,5 @@ +anonftp {Filename,40,,W:User,15:Password,15,,W:Account,15:Path,30,,W} +gopherindex {Port,5,,W:Path,30,,W} +webindex {Port,5,,W:Path,30,,W} + + diff --git a/release/base/etc/inform_web b/release/base/etc/inform_web new file mode 100644 index 0000000..03f1881 --- /dev/null +++ b/release/base/etc/inform_web @@ -0,0 +1,29 @@ +Subject: Archie indexes your Web server + + Dear Web Administrator, + + Archie has started indexing your site for the collective use of + all Archie servers around the world. Indexing your site and all + other web sites is merely for archieving purposes. If you wish + at any time to stop having Archie index your web site then + please reply to this email or send email stating so at + archie-group@bunyip.com + + Archie complies to the ``robots.txt'' exclusion standard and + performs partial retrievals of only new material. + + If you have any questions regarding the procedure or any + inquiries about Archie, then please feel free to contact the Archie + team at the email address (archie-group@bunyip.com). + You can also browse our web site at + http://www.bunyip.com/products/archie + + We also would like to remind you that this message will only be + sent out once. So please save it for future references. + + + Archie Group + Bunyip Information Systems Inc + archie-goup@bunyip.com + + diff --git a/release/base/etc/manpage.ascii b/release/base/etc/manpage.ascii new file mode 100644 index 0000000..e86775f --- /dev/null +++ b/release/base/etc/manpage.ascii @@ -0,0 +1,1107 @@ + + + +ARCHIE(1L) MISC. REFERENCE MANUAL PAGES ARCHIE(1L) + + + +NAME + archie(tm) - Internet archive server listing service + +SYNOPSIS + archie + +DESCRIPTION + This manual page describes Version 3 of the archie system. + This Internet information service allows the user to query a + catalog containing a list of files which are available on + hosts connected to the Internet. Software located through + this service can be obtained by means of ftp(1); for hosts + with access to BITNET/NetNorth/EARN, it can be obtained by + electronic mail through the Princeton bitftp (1L) service. + Send mail to + + bitftp@pucc.princeton.edu + + Other Internet users who are not directly connected may use + the services of various ftp-by-mail servers including + + ftpmail@decwrl.dec.com + + Some archie systems track archive sites globally, others + only track the archive sites in their country, region or + continent in order to reduce the load on trans-oceanic + links. There are a number of archie hosts serving different + continental user communities. The servers command will list + the most up-to-date information on archie servers worldwide. + + archie.au Australia + archie.edvz.uni-linz.ac.at Austria + archie.univie.ac.at Austria + archie.uqam.ca Canada + archie.cs.mcgill.ca Canada + archie.funet.fi Finland + archie.univ-rennes1.fr France + archie.th-darmstadt.de Germany + archie.ac.il Israel + archie.unipi.it Italy + archie.wide.ad.jp Japan + archie.hana.nm.kr Korea + archie.sogang.ac.kr Korea + archie.uninett.no Norway + archie.rediris.es Spain + archie.luth.se Sweden + archie.switch.ch Switzerland + archie.ncu.edu.tw Taiwan + archie.doc.ic.ac.uk United Kingdom + archie.hensa.ac.uk United Kingdom + archie.unl.edu USA (NE) + archie.internic.net USA (NJ) + archie.rutgers.edu USA (NJ) + archie.ans.net USA (NY) + archie.sura.net USA (MD) + + archie can be accessed interactively, via electronic mail or + through archie client programs available widely on the + Internet. + + + Using the Interactive (telnet) Interface + In order to use the interactive system you should use the + following procedure: + + 1) telnet to the archie system closest to you. Do not use + ftp for this, it will not work. + + 2) Login as user archie no capitals, no password is + required. The system should print a banner message and + status report before presenting you with the command + prompt. Some newer operating systems will prompt for a + password. Just hit the return key and continue. + + 3) Type help for complete information on the system. + + For full details, refer to the section entitled ARCHIE COM- + MANDS which appears below. + + + Using the Electronic Mail Interface + In order to use the email interface, send requests to: + + archie@ + + where is one of the hosts listed above, or + one returned by the servers command. Send the word help in + a message to obtain a list of available commands and + features. This is a completely automated interface, acting + without human intervention. + + For full details, refer to the section entitled ARCHIE COM- + MANDS which appears below. + + Using the archie clients + The source code as well as machine executables for a variety + of archie client programs can be obtained via anonymous + ftp(1) from many of the archie server hosts listed above. + They are usually stored in the archie/clients or + pub/archie/clients directories. These clients communicate + via the Prospero + + distributed file system protocol with archie servers, which + perform the specified queries and return the results to the + user. Currently there are Unix and VMS command line, curses + and X window clients as well as Mac and PC Windows versions. + For more information on Prospero send your queries to info- + prospero-request@isi.edu + + + Communicating with the Database Administrators + Mail to archie administrators at a particular archie server + should be sent to the address + + archie-admin@ + + where is one of the hosts listed above. + + To send mail to the implementors of the archie system, + please send mail to + + archie-group@bunyip.com + + The archie server system is a product of Bunyip Information + Systems. + + Requests for additions to the set of hosts surveyed for the + catalog, modifications to the Software Description Catalog, + or other administrative matters, should be sent to: + + archie-admin@bunyip.com + +ARCHIE COMMANDS + In the archie system version 3 the telnet and email clients + accept a common set of commands. Additionally, there are + specialized commands specfic to the particular interfaces. + See THE INTERACTIVE INTERFACE and THE EMAIL INTERFACE sec- + tions below for a list of these commands. + + Note that some archie server sites may disable some of the + commands for reasons particular to their site. As well some + sites limit the number of concurrent interactive (telnet) + sessions to better utilize limited resources. + + Commands + Arguments to commands shown in square brackets '[]' are + optional; all others are mandatory. + + find + + prog + This command produces a list of files matching the pat- + tern . The may be interpreted as a + simple substring, a case sensitive substring, an exact + string or a regular expression, depending on the value + of the search variable. The output normally contains + such information as the file name that was matched, the + directory path leading to it, the site containing it + and the time at which that site was last updated. The + format of the output can be selected through the + output_format variable. The results are sorted accord- + ing to the value of the sortby variable, and are lim- + ited in number by the maxhits variable. + + prog is identical to find. It is included for backward + compatibility with older versions of the system. + + help [ [] ...] + Invokes the help system and presents help on the speci- + fied topic. A list of words is considered to be one + topic, not a list of individual topics. Thus, + + help set maxhits + + requests help on the subtopic maxhits of topic set, not + on two separate topics. After help is presented the + user is placed in the help system at the deepest level + containing subtopics. + + For example, after typing + + help set maxhits + + and being shown the information for that topic the user + is placed at the level set in the help hierarchy. + + list [] + Produce a list of sites whose contents are contained in + the archie catalog. With no argument all the sites are + listed. If given, the argument is interpreted + as a regular expression (See "REGULAR EXPRESSIONS" + below) against which to match site names: only those + names matching are printed. The format of the output + can be selected through the output_format variable. + + Note that the numerical (IP) address associated with a + site name was valid at the last time the site was + updated in the archie catalog but may have been changed + subsequently. Furthermore, the listed IP address is + the primary address as listed in the Domain Name System + (secondary addresses are not stored). + + Example: + + list + + lists all sites in the catalog, while + + list .de$ + + lists all German sites. + + mail
+ Mail the result of the last command that produced out- + put (eg. find, whatis, list) to
. This must be + a vaid email address. + + manpage [ roff | ascii ] + Display the archie manual page (this file). The + optional arguments specify the format of the returned + document. roff specifies UNIX troff(1) format while + ascii specifies plain, preformatted ASCII output. With + no arguments it defaults to ascii. + + domains + Asks the current server for the list of the archie + pseudo-domains that it supports. See the entry for the + match_domain variable below. This command takes no + arguments. + + Example: + + domains + + requests the list of pseudo-domains from the server. + The result looks (in part) something like this: + + africa Africa za + anzac OZ & New Zealand au:nz + asia Asia kr:hk:sg:jp:cn:my:tw:in + centralamerica Central America sv:gt:hn + easteurope Eastern Europe bg:hu:pl:cs:ro:si:hr + mideast Middle East eg:.il:kw:sa + northamerica North America usa:ca:mx + scandinavia Scandinavia no:dk:se:fi:ee:is + southamerica South American ar:bo:br:cl:co:cr:cu:ec:pe + usa United States edu:com:mil:gov:us + westeurope Western Europe westeurope1:westeurope2 + world The World world1:world2 + + + The first column gives the names of pseduo-domains sup- + ported by the server. The second gives the "natural + language" description of the pseudo-domain and the + third column is the actual definitions of those + domains. Thus here the "asia" domain is comprised of + the Domain Name System country codes for Korea ("kr"), + Hong Kong ("hk"), Singapore ("sg") etc. Pseudo-domains + may also be constructed from other pseudo-domains: thus + one component of the the "northamerica" domain is + itself constructed from the "usa" pseudo-domain. + + motd Re-display the "message of the day", which is normally + printed when the user initially logs on to the client + (in the case of the interactive interface) or at the + start of the returned message (in the email interface). + + servers + Display a list of all publicly accessible archie + servers worldwide. The names of the hosts, their IP + addresses and geographical locations are listed. + + set [] + Set the specified variable. Variables are used to con- + trol various aspects of the way archie operates; the + interpretation of arguments, the format of + output from various commands, etc. See the section + below on variables for a description of each one as + well as the entries for unset and show. + + show [ ...] + Without any argument, display the status of all the + user-settable variables, including such information as + its type (boolean, numeric, string), whether or not it + is set and its current value (if its type requires a + value). Otherwise show the status of each of the + specified arguments. + + Example: + + show maxhits + + site + This command is currently unimplemented under version 3 + of the archie system. + + unset variable + Remove any value associated with the specified vari- + able. This may cause counter-intuitive behavior in + some cases; for example, if maxhits is not defined by + the user, the find command will print the internal + default number of matches rather than an unlimited + number of matches. + + version + Print the current version of the client. + + whatis + Search the Software Description Catalog for the given + substring, ignoring case. This catalog consists of + names and short descriptions of many software packages, + documents (like RFCs and educational material), and + data files stored on the Internet. + + Example: + + whatis uucp + + in part gives as a result: + + findpath.sh UUCP Pathfinder + logfile-stats UUCP LOGFILE analyzer + mapstats UUCP map statistics pro- + gram + + Variable Types + The behavior of archie can be modified by certain variables, + the values of which may be changed using the set command, or + removed entirely by the unset command. There are three + variable types: + + boolean (Set or unset) + + numeric (Integer within a defined range) + + string (String of characters which may or may not be + restricted). + + If the value of a string variable should con- + tain leading or trailing spaces then it + should be quoted. Two ways of quoting text + are to surround it with a pair of double + quotes (`"'), or to precede individual char- + acters with a backslash (`\'). (A double + quote, or a backslash may itself be quoted by + preceding it by a backslash.) The resulting + value is that of the string with the quotes + stripped off. + + + Numeric Variables + maxhits + Allow the find command to generate at most the speci- + fied number of matches (permissible range: 0-1000; + default: 100). + + Example: + + set maxhits 100 + + halts prog after 100 matches have been found in total. + + maxhitspm + Across all the anonymous FTP archives on the Internet + (and even on one single anonymous FTP archive) many + files will have the same name. For example, if you + + + +Sun Release 4.1 Last change: 12 Apr 1994 7 + + + + + + +ARCHIE(1L) MISC. REFERENCE MANUAL PAGES ARCHIE(1L) + + + + search for a very common filename like "README" you can + get hundreds even thousands of matches. You can limit + the number of files with the same name through this + variable. For example, + + set maxhitspm 100 + + tells the system only 100 files with the same name. + Note that the overall maximum number of files returned + is still controlled with the 'maxhits' variable. + + maxmatch + This variable will limit the number filenames returned. + For example, if maxmatch is set to 2 and you perform a + substring search for the string "etc", and the catalog + contains filenames "etca", "betc" and "detc" only the + filenames "etca" and "betc" will be returned. However, + depending on the values of maxhitspm and maxhits you + will get back a number of actual files with those + names. Example: + + set maxmatch 20 + + + + max_split_size + Approximate maximum size, in bytes, of a file to be + mailed to the user. Any output larger than this will + be split in pieces of about this size. This can be set + by the user in the range 1024 to ~2Gb with a default of + 51200 bytes. + + String Variables + compress + The kind of data compression the user can specify when + mailing back output. Currently allowed values are none + and compress (standard UNIX compress(1),withadefaultof + + encode + The type of post-compression encoding the user can + specify when mailing back output. Currently allowed + values are none and uuencode, with a default of none. + Note that this variable is ignored unless compression + is enabled (via the compress) variable. + + language + Allows the user to specify the language in which the + help, etc. is presented. Currently the default value + is english. + + mailto + If the mail command is issued with no arguments, mail + the output of the last command to the address specified + by this string variable. Initially this variable is + unset. + + Example: + + set mailto user@frobozz.com + + Conventional Internet addressing styles are understood. + BITNET sites should use the convention: + + user@sitename.bitnet + + UUCP addresses can be specified as + + user@sitename.uucp + + match_domain + This variable allows users to restrict the scope of + their search based upon the Fully Qualified Domain + Names (FQDN) of the anonymous FTP sites being searched. + In this way, the user can specify a colon-separated + list of domain names to which all returned sites must + match. Each component in the list is taken as the + rightmost part of the FQDN. For example, + + set match_domain ca:internic.net:harvard.edu + + means that the names of all returned sites must end in + "ca" (Canada), "internic.net" (sites in the Internet + NIC) or "harvard.edu" (sites at Harvard University). + + While these are all real domain names, listing all pos- + sible combinations for say, the USA, would quickly + become tedious (and if you think that is bad, try list- + ing all the countries on the Internet in Europe). To + aid in this problem, the archie system has the concept + of pseudo-domains to allow users to use a shorthand + notation when using this facility. These pseudo-domains + are defined on a server-by-server basis and you can use + the domains command to query your current server for + its list of predefined pseudo-domains. + + A pseudo-domain is a list of real DNS domain names + and/or a list of other pseudo-domains. For example, the + archie administrator on the server could define the + pseudo-domain + + "usa" + + to be + + "edu:mil:com:gov:us" + + If this definition existed on the server, then you + could + + set match_domain usa + + which would be the same as saying + + set match_domain edu:mil:com:gov:us + + In addition, the server administrator may define + + "northamerica" + + to be + + "usa:ca:mx" + + meaning that "northamerica" is composed of the pseudo- + domain "usa" and the real domains "ca" (Canada) and + "mx" (Mexico). This process can be repeated for 20 lev- + els (more than sufficient for any naming scheme). By + using the domains command you can determine what + pseudo-domains your current server supports. + + match_path + Sometimes you only would like your search (using the + find command) to look for files or directories with a + certain set of names in their full path. + + For example, many anonymous FTP site administrators + will put software packages for the MacIntosh in a path + containing the name "mac" or "macintosh". Another exam- + ple is when a document exists in several formats and + you are only looking for the PostScript version. You + can guess that the file may end in ".ps" or it maybe in + a directory called "ps" or "PostScript". + + This is usually guesswork, but is is useful to have the + archie system only look for files or directories with + particular components in their path name. + + This variable allows you to do this. The arguments are + a colon-separated list of possible path name com- + ponents. In the last example above, saying + + set match_path ps:postscript + + will restrict the search only to match those files or + directories which have the strings "ps" or "postscript" + in their path. + + The comparison is always case-insensitive (regardless + of the value of the match variable) and there is a log- + ical OR connecting the components so that the above + statement says: "find only files which have 'ps' OR + 'postscript' in their path". If either component + matches then the condition is satisfied. + + output_format + Affects the way the output of find and list is + displayed. User settable, with valid values of machine + (machine readable format), terse and verbose, with a + default of verbose. + + search + The type of search done by the find (or prog) command. + User settable with a range of exact, regex, sub, sub- + case, exact_regex, exact_sub and exact_subcase with a + default of sub. (The exact_ types cause it to try + exact first, then fall back to type if no matches + are found). The values have the following meanings: + + exact + Exact match (the fastest method). A match occurs + if the file (or directory) name in the catalog + corresponds exactly to the user-given substring + (including case). + + For example, this type of search could be used to + locate all files called xlock.tar.Z + + regex + Allow user-specified (search) strings to take the + form of ed(1) regular expressions. + + Note: unless specifically anchored to the begin- + ning (with ^) or end (with $) of a line, ed(1) + regular expressions (effectively) have ``.*'' + prepended and appended to them. For example, it + is not necessary to type + + find .*xnlock.* + + because + + find xnlock + + suffices. In this instance, the regex match is + equivalent a simple substring match. Those unfam- + iliar with regular expressions should refer to the + section entitled REGULAR EXPRESSIONS which appears + below. + + sub Substring (case insensitive). A match occurs if + the file (or directory) name in the catalog con- + tains the user-given substring, without regard to + case. + + Example: + + The pattern: + + is + + matches any of the following: + + islington + this + poison + + subcase + Substring (case sensitive). As above, but taking + case as significant. + + Example: + + The pattern: + + TeX + + will match: + + LaTeX + + but neither of the following: + + Latex + TExTroff + + server + the Prospero server to which the client connects when + find or list commands are invoked. User settable, with + a default value of localhost. + + sortby + Set the method of sorting to be applied to output from + the find command. Typing the keyboard interrupt char- + acter (generally Cntl-C on UNIX hosts) aborts a search. + This will also dequeue the request from the server. + Unlike previous versions of the archie system, version + 3 does not allow partial results. The output phase may + be aborted by typing the abort character a second time. + The five permitted methods (and their associated + reverse orders) are: + + none Unsorted (default; no reverse order, though rnone + is accepted) + + filename + Sort files/directories by name, using lexical + order (reverse order: rfilename) + + hostname + Sort on the archive hostname, in lexical order + (reverse order: rhostname) + + size Sort by size, largest files/directories first + (reverse order: rsize) + + time Sort by modification time, with the most recent + file/directory names first (reverse order: rtime) + +THE INTERACTIVE (TELNET) INTERFACE + The interactive interface accepts the following commands and + variables in addtion to those listed above. + + Commands + stty [[