home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / UNIX / ARCHIE / CLIENTS / C_ARCHI2.COM < prev    next >
Encoding:
Text File  |  1992-04-14  |  255.7 KB  |  9,451 lines

  1. $ write sys$output "Unpacking..."
  2. $ if f$search("archie.dir") .eqs. "" then create/dir [.ARCHIE]
  3. $ if f$search("[.ARCHIE]vms.dir") .eqs. "" then create/dir [.ARCHIE.VMS]
  4. $ if f$search("[.ARCHIE]msdos.dir") .eqs. "" then create/dir [.ARCHIE.MSDOS]
  5. $ set noverify
  6. $! This is a DCL shar-type archive created by Unix dclshar.
  7. $!
  8. $CREATE [.archie]INSTALL
  9. $DECK
  10. [Last changed: 04/14/92 v1.3.2]
  11.  
  12.  This is the minimal set of things you need to build an Archie client
  13. that takes advantage of the Prospero system.  It is derived from the
  14. 4.2beta version of Prospero, currently available as the file prospero.tar.Z
  15. on the host cs.washington.edu.
  16.  
  17.  * To make the client under Unix:
  18.    * edit the Makefile, changing CC, OPTIONS, LDFLAGS, and RM if
  19.      necessary (odds are you won't have to do this..see below)
  20.    * edit the DEFINEs as necessary
  21.    * if archie.ans.net isn't "close" to you netwise, please edit
  22.      ARCHIE in the Makefile appropriately.  This is particularly important
  23.      if you're not in the US.  You don't need to touch archie.h anymore.
  24.    * type `make'
  25.  
  26.  I've tried to make this as portable as possible.  I'd encourage you
  27. to try doing a "make" without any changes to the Makefile, and see how
  28. it goes.  If it pukes, and you have to define something, please drop
  29. me a line---my goal is for anybody to just type "make" and not have to
  30. worry about things like what functions their system supports.
  31.  
  32.  * To make the client under VMS, just type @MAKE and it'll ask you
  33.    which of the available Archie servers is closest.  That's it!
  34.  
  35.  * To make the client under MSDOS or OS/2:
  36.    * with FTP Software's PC/TCP for MSDOS (version 2.1 or higher) and
  37.      OS/2 (version 1.1 and higher), use makefile.os2 or makefile.dos
  38.    * with CUTCP (NCSA telnet), use makefile.cut
  39.  
  40. -- Brendan Kehoe (brendan@cs.widener.edu)
  41. $EOD
  42. $!
  43. $CREATE [.archie]Makefile
  44. $DECK
  45. #
  46. # Last changed: 4/14/92, v1.3.2
  47. #
  48. # Makefile for the minimal build for an archie Prospero client.
  49.  
  50. # Your C compiler:
  51. CC=cc
  52.  
  53. # For most systems, these OPTIONS will suffice.  Exceptions:
  54. #
  55. #    * If you're on a Stardent, add  -43
  56. #    * If you're running EP/IX, you may need to add  -systype bsd43
  57. #      but try it without it first.
  58. OPTIONS= -O -I. -I/usr/netinclude -I/usr/ucbinclude
  59.  
  60. # For this, DEFINES is usually ok as-is.  Try it without any of these
  61. # first; if some stuff fails or shows up undefined, then come back and
  62. # add 'em.  Also please drop me a line if you had to add anything...ideally
  63. # things will reach a point where this whole section will be unnecessary.
  64. #
  65. #     * if you want to include the debugging code (so you
  66. #       can help with problem-solving if any crop up), add    -DDEBUG
  67. #     * if you're running Interactive Unix, add              -DISC
  68. #     * if you're running System V, add                  -DSYSV
  69. #     * if you're running a USG (System V.2) system, add      -DUSG
  70. #     * if you're running UTS, add                  -DUTS
  71. #     * if your system doesn't have the functions index(),
  72. #       rindex(), bcopy(), or bzero(), add                    -DFUNCS
  73. #     * if your system is missing the getenv(3) routine, add  -DGETENV
  74. #     * if your system doesn't have the re_comp/regcmp or re_exec/regex
  75. #       routines (no regex(3)/regcmp(3X) library), then add   -DNOREGEX
  76. #     * if your system is lacking strspn(), add               -DSTRSPN
  77. DEFINES= -DDEBUG
  78.  
  79. # The default Archie server; choose one of:
  80. #    archie.ans.net        (USA [NY])
  81. #    archie.rutgers.edu        (USA [NJ])
  82. #    archie.sura.net        (USA [MD])
  83. #    archie.unl.edu        (USA [NE])
  84. #    archie.mcgill.ca        (Canada)
  85. #    archie.funet.fi        (Finland/Mainland Europe)
  86. #    archie.au            (Australia)
  87. #    archie.doc.ic.ac.uk    (Great Britain/Ireland)
  88. #
  89. ARCHIE= archie.sura.net
  90.  
  91. #    Usually LDFLAGS is empty; if, after you build this, archie
  92. #     complains that it can't resolve ARCHIE.ANS.NET (or whatever
  93. #     you defined ARCHIE_HOST as), you need to add `-lresolv'.
  94. #    * If you need the PW library (e.g. A/UX), add -lPW
  95. #    * If you're using ISC, add -linet
  96. #    * If you're using Wollongong TCP/IP on an AT&T box, use the
  97. #      arguments -lnet -lnsl_s .
  98. #    * If you're using UTS, add -lsocket
  99. #    * If you're using System V Release 4, add -L/usr/ucblib etc.
  100. LDFLAGS=
  101. #LDFLAGS= -lresolv
  102. #LDFLAGS= -lnet -lnsl_s
  103. #LDFLAGS= -lsocket
  104. #LDFLAGS= -L/usr/ucblib -lucb -lsockdns -lnsl
  105.  
  106. # Change this if necessary.
  107. RM=/bin/rm
  108.  
  109. # =========================
  110. # Yer' done....make archie.
  111. # =========================
  112. #
  113. CFLAGS=$(OPTIONS) $(DEFINES) -DARCHIE_HOST=\"$(ARCHIE)\"
  114.  
  115. VERSION=1.3.2
  116. VMS_VERSION=`echo $(VERSION) | sed -e 's,\\.,_,g'`
  117.  
  118. OBJS=    aquery.o archie.o atalloc.o dirsend.o get_pauth.o get_vdir.o \
  119.     perrmesg.o procquery.o ptalloc.o regex.o stcopy.o support.o \
  120.     vlalloc.o vl_comp.o
  121.  
  122. all: archie
  123.  
  124. archie: $(OBJS)
  125.     $(CC) $(CFLAGS) -o $@ $(OBJS) $(LDFLAGS)
  126.  
  127. $(OBJS): archie.h pmachine.h pcompat.h Makefile
  128.  
  129. procquery.o: copyright.h
  130.  
  131. clean:
  132.     $(RM) -f *.o archie archie.doc
  133.  
  134. gclean: clean
  135.     $(RM) -f *~ archie.0* archie$(VMS_VERSION).com archie.tar* gmon.out archie.doc
  136.  
  137. unx-deadly:
  138.     unifdef -UXARCHIE xprocquery.c > procquery.c
  139.  
  140. udp: udp.o
  141.     $(CC) -o $@ udp.o
  142.  
  143. udptest: udp
  144.     @echo "This should print the date, if UDP's enabled, or hang if not:"
  145.     @./udp
  146.  
  147. FILES=    INSTALL Makefile Prospero README README.dos archie.c archie.h \
  148.     archie.lnk archie.doc archie.man aquery.c atalloc.c dirsend.c \
  149.     get_pauth.c get_vdir.c make.com makefile.cut makefile.dos makefile.os2 \
  150.     msdos/cutcp.h msdos/hostform.h msdos/netevent.h \
  151.     perrmesg.c patchlevel.h pauthent.h pcompat.h perrno.h pfs.h pmachine.h \
  152.     pprot.h procquery.c ptalloc.c rdgram.h regex.c regex.h stcopy.c \
  153.     support.c copyright.h udp.c vl_comp.c vlalloc.c vms.h vms_support.c \
  154.     vms/fd.h vms/in.h vms/pseudos.h vms/signal.h vms/socket.h vms/time.h \
  155.     vms/types.h vms/network.h vms/multi.opt vms/ucx.opt vms/woll.opt
  156.  
  157. BFILES= $(FILES) xprocquery.c
  158.  
  159. dist: tar shar dcl
  160.  
  161. shar: archie.doc
  162.     makekit -narchie-$(VERSION). archie-$(VERSION) `echo $(FILES) | \
  163.         tr ' ' '\012' | sed -e "s/^/archie-$(VERSION)\//g"` \
  164.         vms msdos > Manifest
  165.  
  166. archie.doc: archie.man
  167.     nroff -man archie.man | tr '\010' _ | sed -e s/__//g > archie.doc
  168.  
  169. dcl: archie.doc
  170.     if [ ! -d archie$(VMS_VERSION)/ ]; then ln -s . archie$(VMS_VERSION); fi
  171.     echo '$$ write sys$$output "Unpacking..."' > archie$(VMS_VERSION).com
  172.     echo '$$ if f$$search("archie.dir") .eqs. "" then create/dir [.ARCHIE]' >> archie$(VMS_VERSION).com
  173.     echo '$$ if f$$search("[.ARCHIE]vms.dir") .eqs. "" then create/dir [.ARCHIE.VMS]' >> archie$(VMS_VERSION).com
  174.     echo '$$ if f$$search("[.ARCHIE]msdos.dir") .eqs. "" then create/dir [.ARCHIE.MSDOS]' >> archie$(VMS_VERSION).com
  175.     echo '$$ set noverify' >> archie$(VMS_VERSION).com
  176.     dclshar `echo "$(FILES)" | tr ' ' '\012' | \
  177.         sed -e "s/^/archie\//g"` >> archie$(VMS_VERSION).com
  178.     echo '$$ write sys$$output "Ok, now enter the ARCHIE directory, look at MAKE.COM, then type @MAKE ."' >> archie$(VMS_VERSION).com
  179.  
  180. tar: archie.doc
  181.     if [ ! -d archie-$(VERSION)/ ]; then ln -s . archie-$(VERSION); fi
  182.     tar cvf archie-$(VERSION).tar `echo $(FILES) |\
  183.      tr ' ' '\012' | sed -e "s/^/archie-$(VERSION)\//g"`
  184.     compress -f archie-$(VERSION).tar
  185. $EOD
  186. $!
  187. $CREATE [.archie]Prospero
  188. $DECK
  189. Prospero also allows users to access Archie as if it were part of a
  190. file system.  Here is an example of how Prospero can be used to access
  191. Archie in this manner.
  192.  
  193.   Script started on Mon Jul  1 22:36:42 1991
  194.   % source /home/ftp/archie/pfs/bin/vfsetup.source
  195.   % vfsetup guest
  196.   % venable
  197.   % cd /archive-sites/archie/regex
  198.   % cd prospero (This command specifies the query)
  199.   % ls -l
  200.   total 0
  201.   -r--r--r--   0 -               0 -            info-prospero.arc
  202.   dr-xr-xr-x   0 -               0 -            prospero
  203.   dr-xr-xr-x   0 -               0 -            prospero-papers
  204.   -r--r--r--   0 -               0 -            prospero.arc
  205.   -r--r--r--   0 -               0 -            prospero.tar.Z
  206.   (Note that the "vls" command could have been used)
  207.   (to show where the files were actually stored    )
  208.   % ls prospero (list a result if it is a directory)
  209.   prog.tar.Z      prospero.tar.Z
  210.   % cat info-prospero.arc  (The file is automatically retrieved and displayed)
  211.   >From bcn@n1dmm  Tue Dec  4 02:33:36 1990
  212.   Received: from n1dmm.cs.washington.edu by june.cs.washington.edu (5.64/7.0jh)
  213.           id AA24763; Tue, 4 Dec 90 02:33:36 -0800
  214.   Received: by n1dmm.cs.washington.edu (5.64/7.0h)
  215.           id AA08497; Tue, 4 Dec 90 02:33:31 -0800
  216.   Date: Tue, 4 Dec 90 02:33:31 -0800
  217.   From: bcn@cs.washington.edu (Clifford Neuman)
  218.   ...
  219.   % vdisable
  220.   % exit
  221.   script done on Mon Jul  1 22:39:33 1991
  222. $EOD
  223. $!
  224. $CREATE [.archie]README
  225. $DECK
  226. [Last changed 04/14/92 v1.3.2]
  227.  
  228.  Enclosed you'll find a Prospero client for the archie service.  It'll
  229. let you query the archie databases without actually using an
  230. interactive process on the remote server's machine (e.g., archie.ans.net),
  231. resulting in a MUCH better response time.  It also helps lessen the
  232. load on the archie server itself.
  233.  
  234.  What's Archie?  It's a system that will let you check a database containing
  235. thousands of entries for the files that're available at FTP sites around
  236. the world.
  237.  
  238.  This is a third child of Clifford Neuman's Prospero project.  It's really
  239. the Archie client that's included in the prospero stuff, but I've taken out
  240. everything that's unnecessary for this client to work.  (Aka, you don't
  241. have to build all of Prospero to get the Archie client.)  Khun Yee Fung
  242. wrote an archie client in Perl, George Ferguson has written a client
  243. for use with XWindows, based in part upon this code.  Also, Scott
  244. Stark wrote a NeXT-Step client for the NeXT.
  245.  
  246.  Using the Archie Prospero interface in its true form will probably be of
  247. interest---check out the file `Prospero' for an example of its interface.
  248. If you find it intriguing, you should probably get the full prospero kit
  249. from the University of Washington on cs.washington.edu in pub/prospero.tar.Z.
  250.  
  251.  Suffice to say, there are now a number of ways to query Archie without
  252. bogging a server down with your logins.
  253.  
  254.  Check out the man page (or archie.doc, if you're using VMS or DOS)
  255. for instructions on how to use this archie client.  VMS users please
  256. note that you have to put quotes around args that are capital letters;
  257. for example,  $ ARCHIE "-L"  to list the available servers.
  258.  
  259.  Please check to make sure you don't have "archie" aliased or modified
  260. in some way to do a telnet or rlogin (which you may've done before
  261. this command-line ability came into being).
  262.  
  263.  If Archie consistently hangs (at different times of day with
  264. different queries), it's possible that your site has UDP traffic on
  265. ports > 1000 blocked, for security reasons.  Type `make udptest' to
  266. check---if it prints out the date, the Archie server is probably down;
  267. if it doesn't print out the date, either Widener's computer is down
  268. (God forbid ;-) ) or you do indeed have UDP blocked.  See your system
  269. administrator in this case.  If the problem persists and haven't the
  270. vaguest, then write me describing the situation and what machine/OS
  271. you're using.
  272.  
  273.  Write to archie-group@cs.mcgill.ca with questions about Archie itself.
  274.  Write to info-prospero@isi.edu about the Prospero protocol.
  275.  Write to brendan@cs.widener.edu with questions about this specific package.
  276. $EOD
  277. $!
  278. $CREATE [.archie]README.dos
  279. $DECK
  280. 11/22/91  Readme.dos -- Readme file for CUTCP DOS version of Archie.
  281.  
  282. --
  283. This version requires the use of a `standard' NCSA or CUTCP compatible
  284. CONFIG.TEL file.  If you are running NCSA telnet or CUTCP/CUTE telnet,
  285. you should be able to run this program without modification.
  286.  
  287. As with all CUTCP programs, you may set a DOS environment variable to
  288. point to the location of your config.tel file.
  289.  
  290.     set CONFIGTEL=C:\net\config.tel
  291.  
  292. You may also set the $CUTCPnn dos environment variables to include other
  293. 'local' information (such as client IP address on a Novell lan).
  294.  
  295. This version has been compiled with the US (archie.sura.net) Prospero/Archie
  296. server as the default. This may not be appropriate for your location. Here's
  297. how to change it.
  298.  
  299.  
  300.     1. Run the archie program with the -L argument to list known
  301.        archie/prospero servers.
  302.  
  303.     2. Select the server name that is closest to your site. For this example
  304.        we'll pick archie.funet.fi
  305.  
  306.     3. Edit your config.tel file and add the following lines at the end
  307.        of the file.
  308.  
  309.             name=archie
  310.             host=archie.funet.fi    # actually substitute your select
  311.                         # server name here
  312.  
  313.     4. If you happen to know the IP address of the server, you may also
  314.        add the appropriate
  315.  
  316.             hostip=<insert IP address here>
  317.  
  318.     5. If you don't enter an IP address, archie will perform a DNS lookup
  319.        use the domain nameserver information that is in your config.tel 
  320.        file.
  321.  
  322.  
  323. An additional command line option (-H) has been added (vs -h) to allow the
  324. user to specify the config.tel file location on the command line. 
  325.  
  326.     archie -H c:\net\config.tel emacs
  327.  
  328. During a search, you may press the <ESCAPE> key to abort the query.
  329.  
  330.  
  331.  
  332. If you have problems, try running archie with the -D9 option (debug).
  333.  
  334. As usual, bugs/comments to:
  335.  
  336.         cutcp-bugs@omnigate.clarkson.edu
  337.  
  338. Brad Clements, Sr. Network Engineer
  339. Educational Resources Center
  340. Clarkson University 
  341. Potsdam, NY 13699
  342.  
  343. bkc@draco.erc.clarkson.edu
  344.  
  345. -----------
  346. Sample Config.tel file 
  347. ------------------------------
  348. #  Example host file for ARCHIE/ CUTCP version
  349. #  11/21/91
  350. #
  351. #      Bugs to  cutcp-bugs@omnigate.clarkson.edu
  352.  
  353. #---------------------------------------------------------------------------#
  354. #                                        #
  355. #** ATTENTION ATTENTION ATTENTION ATTENTION ATTENTION ATTENTION ATTENTION **#
  356. #                                        #
  357. #   This sample config.tel file contains every single option that you could #
  358. #   possibly use. Its meant as an example only. Please Please PLEASE don't  #
  359. #   use all these options in your working config.tel file, just the ones    #
  360. #   that you actually need. Many options can be left out, the default action#
  361. #   (if defined) is shown in parens () next to the option.             #
  362. #                                        #
  363. #                         Thank you for your support                #
  364. #---------------------------------------------------------------------------#
  365.  
  366. #
  367. #  This example file is for my=bootp, in which case the following items are
  368. #  determined from the bootp server: (and are thus commented out in this file)
  369. #       1. This machine's IP Address
  370. #       2. The network NETMASK
  371. #       3. The default gateway (one or more)
  372. #       4. Nameservers (one or more)
  373. #       5. The domain search list (if this clients hostname is in the bootp packet)
  374. #
  375. #  Your BOOTP server needs to be RFC 1048 compliant for this to work
  376. #  
  377. #  If you have nameservers, gateways or a domainslist already specified
  378. #  in this file, then the file's entry takes precedence.
  379. #  Extra gateways and nameservers will be added by BOOTP if found, however.
  380. #----------------------------------------------------------------------------
  381. #  You can set a DOS environment variable  CONFIGTEL to point to this file
  382. #  then you don't need batch files or the -h option.
  383. #
  384. #       C> set CONFIGTEL=C:\net\myconfig.tel
  385. #
  386. #  You may also use environment variables to include config.tel options,
  387. #  such as:
  388. #    C> set $CUTCP1=myip~197.001.42.98;netmask~255.255.252.0
  389. #    C> set $CUTCP2=name~x;hostip~128.163.298.2
  390. #
  391. #  and so on up to $CUTCP99. Note that you use a tilde (~) instead of (=)
  392. #  in the dos set command because two ='s are not allowed by Dos.
  393. #
  394. #  Additionally, there is a new config.tel option called include= which
  395. #  allows the nesting (up to 3) configuration files deep.
  396. #
  397. #
  398. #  You can use these new options on networks to make your configuration job
  399. #  easier. CUTCP always opens config.tel files as read-only, so you can mark
  400. #  your files as sharable, read only. Also, you can use the include= command
  401. #  in a $CUTCP environment variable, and on the command line.
  402.  
  403. #  *Note* that you can not include a machine specific parameter before
  404. #  name=default... This used to work in old versions, but is strictly
  405. #  enforced in this version.
  406. # --------------------------------------------------------------------------  
  407. #  This file is free form
  408. #  Separators are any char <33 and :;=
  409. #
  410. #  The form is keyword=value for each parameter.
  411. #  The first set of parameters refer to the whole program's defaults.
  412. #  These parameter values can be in any order.
  413. #  Following this are the individual machine specs.
  414. #
  415.  
  416. myip=128.153.28.65                      #  (bootp)
  417.                 #  myip types are:
  418.                                 #  bootp        - sends out a BOOTP request for your IP
  419.                                 #  rarp         - Uses reverse ARp to get your IP
  420.                                 #  xx.yy.zz.qq  - your IP address
  421.  
  422. vjc=no                # (no)
  423.                 # set  vjc=yes if you're running slip and
  424.                 # you want to use Van Jacobson TCP header
  425.                 # compression
  426.  
  427. splayc=no            # (no) ack. splay compression w/ vjc.. don't
  428.                 # use it, not standard, development option only
  429.  
  430. myname=userid            # put your userid here, used for Rlogin
  431.                 # PC-NFS version ignores this value and uses the name
  432.                 # that you specified to your pcnfsd.
  433.  
  434. netmask=255.255.252.0           #  needed if not using BOOTP. 
  435.                                 #  otherwise not needed because Bootp gets your netmask
  436.                 #  for you
  437.  
  438. hardware=packet            # (packet)
  439.                                 # harware choices
  440.                                 #  3com         - 3com 3c501
  441.                                 #  3c523        - 3com 3c523
  442.                                 #  wd800        - Western Digitial 800E
  443.                                 #  nicpc        - 
  444.                                 #  nicps        -
  445.                                 #  ni5210       - Micom Interlan NI5210 card
  446.                                 #  packet       - FTP packet Driver spec 
  447.                                 # (currently only Ethernet and Slip class devices are supported)
  448.  
  449. interrupt=2                     # hardware IRQ interrupt
  450. address=0                       # (0)
  451.                 # base memory address or packet driver class
  452.                                 # if using packet driver (0 == default == ethernet)
  453.                                 # or class=6 for slip
  454.  
  455. ioaddr=0                        # (0)
  456.                 # I/O address  or packet int vector if using packet driver
  457.                                 # If = 0 and packet driver, telbin looks for first
  458.                                 # packet driver found between 60H and 7FH
  459.  
  460. noarpme=yes            # Don't arp for myself before running? (no)
  461.                 # if yes, inhibits the initial arp request
  462.                 # for this IP address. However, if yes, won't
  463.                 # warn you if another user is using this IP
  464.                 # address. For some token ring systems, you'll
  465.                 # need noarpme=yes.
  466.  
  467. include="nul"            # if you want to include another file as part
  468.                 # of this one (you can nest up to three includes)
  469.                 # otherwise, don't use this option
  470.  
  471. domaintime=4            # domain name lookup timeout (first retry)
  472. domainretry=4            # domain name max number of retries 
  473. domainslist="clarkson.edu,aux.clarkson.edu" # domain name search path
  474.                                 # domain name lookup will attach each of these
  475.                                 # comma seperated suffixes to
  476.                                 # the end of the name you are looking for to
  477.                                 # discover the full name and IP address.
  478.                                 # so, looking for x tries x.clarkson.edu and x.aux.clarkson.edu then just x
  479.                                 # unless you use  x.  which ONLY looks for x
  480.  
  481.     ## Also, the fewer suffixes in the domainslist
  482.     ## the less time you will have to wait if you mis-type an entry.
  483.     ## Finally, try not to use a suffix like   .  or .edu or .com this will
  484.     ## waste a lot of time looking for a bogus host name if you mis-type an entry.
  485.  
  486. ## ----------------------------------------------------------------- ##
  487. ##   BEGIN MACHINE SPECIFIC PARAMETERS...                 ##
  488. ## ----------------------------------------------------------------- ##
  489.  
  490. name=default            # default entry sets defaults for all following
  491.                 # machines.
  492.  
  493. arptime=10            # arp timeout in seconds
  494.                 #
  495.  
  496. retrans=1                       # starting retransmit time out in ticks
  497.                 #   1/18ths of sec MAX 100, min 1
  498.  
  499. mtu=1024                        # maximum transmit unit in bytes
  500.                 #   outgoing packet size, MAX=1500
  501.  
  502. maxseg=1024            # largest segment we can receive
  503.                 #   whatever the hardware can take, MAX=4096
  504. rwin=2048                       # most bytes we can receive without ACK
  505.                 #   =TCP window size, MAX=4096
  506.  
  507. contime=20                      # timeout in seconds to try connection
  508.                 #   before returning error to user
  509.  
  510. #  Following are individual machine specifications
  511. #  Gateways are used in order that they appear in the file
  512. #  Nameservers rotate, #1, #2, #3, #1, #2 when a request fails
  513. #
  514.  
  515. # ********************************************************************* ###
  516. # Note: If you are using BOOTP above for myip=, then you do not need
  517. #       to enter a default gateway, nameserver, netmask etc (unless you want to)
  518. #       only IF your BOOTP server is rfc_1048 compliant. (Ask your Net Manager)
  519. #       You can use both bootp and entries here, in which case the entries in
  520. #       this file over-ride what BOOTP discovers. (however, bootp nameservers
  521. #       and gateways are ADDED to this file's list of entries
  522. # ********************************************************************* ####
  523.  
  524. #  Below this line, most of the communication parameters are obtained
  525. #  from the "default" host entry.  Those parameters listed for a host 
  526. #  override the default host values.
  527. #
  528. #  These are examples, replace them with the correct values for your site.
  529. #name=mynameserver
  530. #host=omnigate.clarkson.edu
  531. #hostip=197.001.4.2
  532. #nameserver=1
  533.  
  534. #name=backupserver
  535. #host=clutx.clarkson.edu
  536. #hostip=197.001.4.3
  537. #nameserver=2
  538.  
  539. #name=lastserver
  540. #host=n2ngw.nyser.net
  541. #hostip=128.145.198.2
  542. #nameserver=3
  543.  
  544. #name=mygateway
  545. #host=nysernet.clarkson.edu
  546. #hostip=197.001.4.1
  547. #gateway=1
  548.  
  549.  
  550. name=archie
  551. host=archie.funet.fi
  552. $EOD
  553. $!
  554. $CREATE [.archie]archie.c
  555. $DECK
  556. /*
  557.  * Copyright (c) 1991 by the University of Washington
  558.  *
  559.  * For copying and distribution information, please see the file
  560.  * <copyright.h>.
  561.  */
  562.  
  563. #include <copyright.h>
  564.  
  565. /*
  566.  * Archie client using the Prospero protocol.
  567.  *
  568.  * Suggestions and improvements to Brendan Kehoe (brendan@cs.widener.edu).
  569.  */
  570.  
  571. #include <stdio.h>
  572. #if defined(OS2)
  573. # include <pctcp.h>
  574. #endif
  575. #ifdef MSDOS
  576. # include <string.h>
  577. # include <stdlib.h>
  578. # ifdef CUTCP
  579. #  include <msdos/cutcp.h>
  580. #  include <msdos/hostform.h>
  581. /* The default stack size for a BC program is 4k; jack it up to 16 and add the
  582.    Check for Stack Overflow option to the compiler.  */
  583. extern unsigned _stklen = 16 * 1024;
  584. # endif
  585. #endif
  586.  
  587. #include <pfs.h>
  588. #include <rdgram.h>
  589. #include <archie.h>
  590. #include <pmachine.h>
  591.  
  592. int        listflag = 0;
  593. int        sortflag = 0;   /* 1 = by date                    */
  594. char        *progname;
  595. #ifdef DEBUG
  596. extern int    pfs_debug;
  597. #endif
  598. extern int    rdgram_priority;
  599.  
  600. /* To keep the code clean.. */
  601. #ifdef VMS
  602. # define NFLAG    "\"N\""
  603. # define LFLAG    "\"L\""
  604. # define A_EXIT    SS$_NORMAL
  605. #else
  606. # define NFLAG    "N"
  607. # define LFLAG    "L"
  608. # define A_EXIT    1
  609. #endif
  610. #ifdef CUTCP
  611. # define HFLAG    "[H config.tel]]"
  612. #else
  613. # define HFLAG    "]"
  614. #endif
  615.  
  616. main(argc,argv)
  617.     int        argc;
  618.     char    *argv[];
  619.     {
  620.     char        *cur_arg;
  621.     char        qtype = '=';    /* Default to exact string match  */
  622.     char        etype = '=';    /* Type if only -e is specified   */
  623.     int        eflag = 0;    /* Exact flag specified          */
  624.     int        max_hits = MAX_HITS;
  625.     int        offset = 0;
  626.     int        exitflag = 0;    /* Display release identifier     */
  627.     int        tmp;
  628.     char        *host = ARCHIE_HOST;
  629.     char        *p;
  630.     static char *archies[] = { ARCHIES };
  631. #ifdef CUTCP
  632.     int        hostset = 0;
  633. #endif
  634.     char        *getenv();
  635.  
  636.     progname = *argv;
  637.     argc--; argv++;
  638.  
  639. #ifdef    CUTCP
  640.     if(getenv("CONFIGTEL"))
  641.         if(Shostfile(getenv("CONFIGTEL")) < 0) {
  642.             fprintf(stderr,"Error, couldn't open configtel file %s\n",
  643.                 getenv("CONFIGTEL"));
  644.             exit(1);
  645.         }
  646. #endif
  647.  
  648.     if ((p = getenv("ARCHIE_HOST")) != (char *)NULL)
  649.       host = p;
  650.         
  651.     while (argc > 0 && **argv == '-') {
  652.         cur_arg = argv[0]+1;
  653.  
  654.         /* If a - by itself, or --, then no more arguments */
  655.         if(!*cur_arg || ((*cur_arg == '-') && (!*(cur_arg+1)))) {
  656.             argc--, argv++;
  657.         goto scandone;
  658.         }
  659.  
  660.         while (*cur_arg) {
  661.         switch (*cur_arg++) {
  662. #ifdef DEBUG        
  663.         case 'D':  /* Debug level */
  664.             pfs_debug = 1; /* Default debug level */
  665.             if(*cur_arg && index("0123456789",*cur_arg)) {
  666.             sscanf(cur_arg,"%d",&pfs_debug);
  667.             cur_arg += strspn(cur_arg,"0123456789");
  668.             }
  669.             else if(argc > 2) {
  670.                 tmp = sscanf(argv[1],"%d",&pfs_debug);
  671.             if (tmp == 1) {argc--;argv++;}
  672.             }
  673.             break;
  674. #endif
  675. #ifdef    CUTCP
  676.         case 'H' :
  677.             if(Shostfile(argv[1]) < 0) {
  678.                 fprintf(stderr,"Error, couldn't open configtel file %s\n",argv[1]);
  679.                 exit(1);
  680.             }
  681.              argc--;argv++;
  682.             break;
  683. #endif
  684. #ifndef XARCHIE
  685.         case 'L':
  686.             printf("Known archie servers:\n");
  687.             for (tmp = 0; tmp < NARCHIES; tmp++)
  688.             printf("\t%s\n", archies[tmp]);
  689.             printf(" * %s is the default Archie server.\n", ARCHIE_HOST);
  690.             printf(" * For the most up-to-date list, write to an Archie server and give it\n   the command `servers'.\n");
  691.             exitflag = 1;
  692.             break;
  693. #endif
  694.  
  695.         case 'N':  /* Priority (nice) */
  696.             rdgram_priority = RDGRAM_MAX_PRI; /* Use this if no # */
  697.             if(*cur_arg && index("-0123456789",*cur_arg)) {
  698.             sscanf(cur_arg,"%d",&rdgram_priority);
  699.             cur_arg += strspn(cur_arg,"-0123456789");
  700.             }
  701.             else if(argc > 2) {
  702.                 tmp = sscanf(argv[1],"%d",&rdgram_priority);
  703.             if (tmp == 1) {argc--;argv++;}
  704.             }
  705.             if(rdgram_priority > RDGRAM_MAX_SPRI) 
  706.             rdgram_priority = RDGRAM_MAX_PRI;
  707.             if(rdgram_priority < RDGRAM_MIN_PRI) 
  708.             rdgram_priority = RDGRAM_MIN_PRI;
  709.               break;
  710.  
  711.         case 'c':  /* substring (case sensitive) */
  712.             qtype = 'C';
  713.             etype = 'c';
  714.             break;
  715.  
  716.         case 'e':  /* Exact match */
  717.             /* If -e specified by itself, then we use the  */
  718.             /* default value of etype which must be '='    */
  719.             eflag++;
  720.             break;
  721.  
  722.         case 'h':  /* Host */
  723.             host = argv[1];
  724. #ifdef CUTCP
  725.             hostset++;
  726. #endif
  727.             argc--; argv++;
  728.             break;
  729.  
  730.         case 'l':  /* List one match per line */
  731.             listflag++;
  732.             break;
  733.  
  734.         case '0': case '1': case '2': case '3': case '4':
  735.         case '5': case '6': case '7': case '8': case '9':
  736.             cur_arg--;
  737.         case 'm':  /* Max hits */
  738.             max_hits = -1;  
  739.             if(*cur_arg && index("0123456789",*cur_arg)) {
  740.             sscanf(cur_arg,"%d",&max_hits);
  741.             cur_arg += strspn(cur_arg,"0123456789");
  742.             }
  743.             else if(argc > 1) {
  744.                 tmp = sscanf(argv[1],"%d",&max_hits);
  745.             if (tmp == 1) {argc--;argv++;}
  746.             }
  747.             if (max_hits < 1) {
  748.             fprintf(stderr, "%s: -m option requires a value for max hits (>= 1)\n",
  749.                 progname);
  750.             exit(A_EXIT);
  751.             }
  752.             break;
  753.  
  754.         case 'o':  /* Offset */
  755.             if(argc > 1) {
  756.               tmp = sscanf(argv[1],"%d",&offset);
  757.               if (tmp != 1)
  758.             argc = -1;
  759.               else {
  760.             argc--; argv++;
  761.               }
  762.             }
  763.             break;
  764.  
  765.         case 'r':  /* Regular expression search */
  766.             qtype = 'R';
  767.             etype = 'r';
  768.             break;
  769.  
  770.         case 's':  /* substring (case insensitive) */
  771.             qtype = 'S';
  772.             etype = 's';
  773.             break;
  774.  
  775.         case 't':  /* Sort inverted by date */
  776.             sortflag = 1;
  777.             break;
  778.  
  779.         case 'v':  /* Display version */
  780.             fprintf(stderr,
  781.             "Client version %s based upon Prospero version %s\n",
  782.                 CLIENT_VERSION, PFS_RELEASE);
  783.             exitflag++;
  784.             break;
  785.  
  786.         default:
  787.             fprintf(stderr,"Usage: %s [-[cers][l][t][m#][h host][%s][%s#]%s string\n", progname, LFLAG, NFLAG, HFLAG);
  788.             exit(A_EXIT);
  789.         }
  790.         }
  791.         argc--; argv++;
  792.     }
  793.  
  794.       scandone:
  795.  
  796.     if (eflag) qtype = etype;
  797.  
  798.     if ((argc != 1) && exitflag) exit(0);
  799.  
  800.     if (argc != 1) {
  801.         fprintf(stderr, "Usage: %s [-[cers][l][t][m#][h host][%s][%s#]%s string\n", progname, LFLAG, NFLAG, HFLAG);
  802.         fprintf(stderr,"       -c : case sensitive substring search\n");
  803.         fprintf(stderr,"       -e : exact string match (default)\n");
  804.         fprintf(stderr,"       -r : regular expression search\n");
  805.         fprintf(stderr,"       -s : case insensitive substring search\n");
  806.         fprintf(stderr,"       -l : list one match per line\n");
  807.         fprintf(stderr,"       -t : sort inverted by date\n");
  808.         fprintf(stderr,"      -m# : specifies maximum number of hits to return (default %d)\n", max_hits);
  809.         fprintf(stderr,"  -h host : specifies server host\n");
  810.         fprintf(stderr,"       -%s : list known servers and current default\n", LFLAG);
  811.         fprintf(stderr,"      -%s# : specifies query niceness level (0-35765)\n", NFLAG);
  812. #ifdef CUTCP
  813.         fprintf(stderr,"-H config.tel: specify location of config.tel file\n");
  814. #endif
  815.         exit(A_EXIT);
  816.     }
  817.  
  818. #ifdef    CUTCP
  819.     if(argc = Snetinit()) {
  820.                fprintf(stderr,"Error %d from SNetinit (bad or missing config.tel ?)\n",argc);
  821.         if(argc == -2)
  822.                    netshut();    /* rarp lookup failure */
  823.         exit(1);
  824.     }
  825.     if(!hostset) {        /* if no host on command line, look in config.tel file
  826.                           for name=archie */
  827.         struct machinfo *mp;
  828.  
  829.          mp = Shostlook("archie");
  830.         if(mp) {
  831.                    host = mp->hname ? mp->hname : mp->sname;
  832.         }
  833.        }
  834. #endif
  835.  
  836.     procquery(host, argv[0], max_hits, offset, qtype, sortflag, listflag);
  837.  
  838. #ifdef CUTCP
  839.     netshut();
  840. #endif
  841.     exit(0);
  842.     }
  843. $EOD
  844. $!
  845. $CREATE [.archie]archie.h
  846. $DECK
  847. /*
  848.  * archie.h : Definitions for the programmatic Prospero interface to Archie
  849.  *
  850.  *     Written by Brendan Kehoe (brendan@cs.widener.edu), 
  851.  *                George Ferguson (ferguson@cs.rochester.edu), and
  852.  *                Clifford Neuman (bcn@isi.edu).
  853.  */
  854.  
  855. /* You can't touch this.  */
  856. #ifndef XARCHIE
  857. # 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)"
  858. # define NARCHIES    8
  859. #endif
  860.  
  861. /*
  862.  * Default value for max hits.  Note that this is normally different
  863.  * for different client implementations.  Doing so makes it easier to
  864.  * collect statistics on the use of the various clients.
  865.  */
  866. #ifdef VMS
  867. # define    MAX_HITS    98    /* VMS Client */
  868. #else
  869. # ifdef XARCHIE
  870. #  define    MAX_HITS    99    /* X Client */
  871. # else
  872. #  define    MAX_HITS    95    /* Normal client */
  873. # endif
  874. #endif
  875.  
  876. /*
  877.  * CLIENT_VERSION may be used to identify the version of the client if 
  878.  * distributed separately from the Prospero distribution.  The version
  879.  * command should then identify both the client version and the Prospero
  880.  * version identifiers.   
  881.  */
  882. #ifdef XARCHIE
  883. # define CLIENT_VERSION    "1.3-X"
  884. #else
  885. # define CLIENT_VERSION "1.3.2"
  886. #endif
  887.  
  888. /* Procedures from user/aquery.c */
  889.  
  890. /* archie_query(host,string,max_hits,offset,query_type,cmp_proc,flags) */
  891. extern VLINK archie_query(); 
  892.  
  893. /* defcmplink(p,q) and invdatecmplink(p,q)                             */
  894. extern int defcmplink();    /* Compare by host then by filename    */
  895. extern int invdatecmplink();    /* Compare links inverted by date      */
  896.  
  897. /* Definitions for the comparison procedures                           */
  898. #define AQ_DEFCMP    defcmplink
  899. #define AQ_INVDATECMP    invdatecmplink
  900.  
  901. /* Flags                                                               */
  902. #define AQ_NOSORT    0x01    /* Don't sort                          */
  903. #define AQ_NOTRANS    0x02    /* Don't translate Archie responses    */
  904. $EOD
  905. $!
  906. $CREATE [.archie]archie.lnk
  907. $DECK
  908. aquery.lo archie.lo atalloc.lo dirsend.lo+
  909. Get_pauth.lo get_vdir.lo perrmesg.lo procquery.lo+
  910. ptalloc.lo regex.lo stcopy.lo support.lo+
  911. vlalloc.lo vl_comp.lo
  912. archie.unp
  913. archie/map/noi/co/li/stack:45000
  914. lsocket lnetlib lconfig lpc llibce
  915. $EOD
  916. $!
  917. $CREATE [.archie]archie.doc
  918. $DECK
  919.  
  920.  
  921.  
  922. ARCHIE(1)                USER COMMANDS                  ARCHIE(1)
  923.  
  924.  
  925.  
  926. NAME
  927.      archie - query the  Archie  anonymous  FTP  databases  using
  928.      Prospero
  929.  
  930. SYNOPSIS
  931.      archie [ -cers ] [ -l ] [ -t ] [ -m# ] [ -N# ] [ -h hostname ]
  932.             [ -L ] string
  933.  
  934. DESCRIPTION
  935.      archie queries an archie anonymous FTP database looking  for
  936.      the  specified  string  using  the  Prospero protocol.  This
  937.      client is based on Prospero version Beta.4.2 and is provided
  938.      to  encourage non-interactive use of the Archie servers (and
  939.      subsequently better performance on both  sides).   This  man
  940.      page describes version 1.3 of the client.
  941.  
  942.      The general method of use is of the form
  943.  
  944.           % archie string
  945.  
  946.      This will go to the archie server and ask it to look for all
  947.      known  systems  that have a file named `string' in their FTP
  948.      area.  archie will wait, and print out any matches.
  949.  
  950.      For example,
  951.  
  952.           % archie emacs
  953.  
  954.      will find all anonymous FTP sites  in  the  archie  database
  955.      that  have  files  named  emacs somewhere in their FTP area.
  956.      (This particular query would probably return a lot of direc-
  957.      tories.)  If you want a list of every filename that contains
  958.      emacs anywhere in it, you'd use
  959.  
  960.           % archie -c emacs
  961.  
  962.      Regular expressions, such as
  963.  
  964.           % archie -r '[xX][lL]isp'
  965.  
  966.      may also be used for searches.  (See the manual of a reason-
  967.      ably good editor, like GNU Emacs or vi, for more information
  968.      on using regular expressions.)
  969.  
  970.  
  971. OPTIONS
  972.      The options currently available to this archie client are:
  973.  
  974.      -c          Search substrings paying attention  to  upper  &
  975.                  lower case.
  976.      -e          Exact string match.  (This is the default.)
  977.      -r          Search using a regular expression.
  978.  
  979.  
  980.  
  981. Archie (Prospero)  Last change: 9 January 1992                  1
  982.  
  983.  
  984.  
  985.  
  986.  
  987.  
  988. ARCHIE(1)                USER COMMANDS                  ARCHIE(1)
  989.  
  990.  
  991.  
  992.      -s          Search  substrings  ignoring  the  case  of  the
  993.                  letters.
  994.      -l          Output results in a form suitable for parsing by
  995.                  programs.
  996.      -t          Sort the results inverted by date.
  997.      -m#         Specifies the maximum number of  hits  (matches)
  998.                  to return (default of 95).
  999.      -N#         Sets the niceness of a query; by  default,  it's
  1000.                  set  to 0.  Without an argument, ``-N'' defaults
  1001.                  to 35765.   If  you  use  -N  with  an  argument
  1002.                  between 0 and 35765, it'll adjust itself accord-
  1003.                  ingly.  (Note: VMS users will have to put quotes
  1004.                  around  this  argument, and -L, like "-N45"; VMS
  1005.                  will otherwise convert it to lowercase.)
  1006.      -h hostname Tells the client  to  query  the  Archie  server
  1007.                  hostname.
  1008.      -L          Lists the Archie servers known  to  the  program
  1009.                  when it was compiled, as well as the name of the
  1010.                  default Archie server.  For an up-to-date  list,
  1011.                  write  to  ``archie@archie.mcgill.ca''  (or  any
  1012.                  Archie  server)  with  the  single  command   of
  1013.                  servers.
  1014.  
  1015.      The three search-modifying arguments  (``-c'',  ``-r'',  and
  1016.      ``-s'')  are  all  mutually  exclusive;  only  the  last one
  1017.      counts.  If you specify -e with any of  ``-c'',  ``-r'',  or
  1018.      ``-s'', the server will first check for an exact match, then
  1019.      fall back to the case-sensitive, case-insensitive, or  regu-
  1020.      lar expression search.  This is so if there are matches that
  1021.      are particularly obvious, it will take a minimal  amount  of
  1022.      time to satisfy your request.
  1023.  
  1024.      If you list a single `-' by itself,  any  further  arguments
  1025.      will  be  taken  as  part  of  the  search  string.  This is
  1026.      intended to enable searching for strings that begin  with  a
  1027.      `-'; for example:
  1028.  
  1029.           % archie -s - -old
  1030.  
  1031.      will search for all filenames that contain the string `-old'
  1032.      in them.
  1033.  
  1034. RESPONSE
  1035.      Archie servers are set up to respond to a number of requests
  1036.      in  a  queued fashion.  That is, smaller requests get served
  1037.      much more quickly than do large requests.  As a result,  the
  1038.      more  often  you query the Archie server, or the larger your
  1039.      requests, the longer the queue will become, resulting  in  a
  1040.      longer  waiting  period  for everyone's requests.  Please be
  1041.      frugal when possible, for your benefit as well  as  for  the
  1042.      other users.
  1043.  
  1044.  
  1045.  
  1046.  
  1047. Archie (Prospero)  Last change: 9 January 1992                  2
  1048.  
  1049.  
  1050.  
  1051.  
  1052.  
  1053.  
  1054. ARCHIE(1)                USER COMMANDS                  ARCHIE(1)
  1055.  
  1056.  
  1057.  
  1058. QUERY PRIORITY
  1059.      Please use the  ``-N''  option  whenever  you  don't  demand
  1060.      immediacy,  or when you're requesting things that could gen-
  1061.      erate large responses.  Even when using the nice option, you
  1062.      should  still  try  to  avoid  big jobs during busy periods.
  1063.      Here is a list of what we consider to be  nice  values  that
  1064.      accurately reflect the priority of a job to the server.
  1065.  
  1066.           Normal              0
  1067.           Nice                500
  1068.           Nicer               1000
  1069.           Very Nice           5000
  1070.           Extremely Nice      10000
  1071.           Nicest              32765
  1072.  
  1073.      The last priority, Nicest, would be used when a  job  should
  1074.      wait  until  the  queue is essentially empty before running.
  1075.      You should pick one of these values to use, possibly modify-
  1076.      ing  it  slightly depending on where you think your priority
  1077.      should land.  For example, 32760 would mean wait  until  the
  1078.      queue  is  empty,  but  jump  ahead  of other jobs that have
  1079.      selected Nicest.
  1080.  
  1081.      There are certain types of  things  that  we  suggest  using
  1082.      Nicest  for,  irregardless.  In particular, any searches for
  1083.      which you would have a hard time justifying the use of  any-
  1084.      thing but extra resources.  (We all know what those searches
  1085.      would be for.)
  1086.  
  1087. ENVIRONMENT
  1088.      ARCHIE_HOST
  1089.              This will change the host archie will  consult  when
  1090.              making  queries.   (The default value is what's been
  1091.              compiled in.)  The ``-h'' option will override this.
  1092.              If  you're  running  VMS,  create  a  symbol  called
  1093.              ARCHIE_HOST.
  1094.  
  1095. SEE ALSO
  1096.      For more information on regular expressions, see the  manual
  1097.      pages on:
  1098.  
  1099.      regex(3), ed(1)
  1100.  
  1101.      Also   read    the    file    archie/doc/whatis.archie    on
  1102.      archie.mcgill.ca for a detailed paper on Archie as a whole.
  1103.  
  1104. AUTHORS
  1105.      The archie service was conceived  and  implemented  by  Alan
  1106.      Emtage       (bajan@cs.mcgill.ca),       Peter       Deutsch
  1107.      (peterd@cs.mcgill.ca),        and        Bill         Heelan
  1108.      (wheelan@cs.mcgill.ca).   The  entire  Internet  is in their
  1109.      debt.
  1110.  
  1111.  
  1112.  
  1113. Archie (Prospero)  Last change: 9 January 1992                  3
  1114.  
  1115.  
  1116.  
  1117.  
  1118.  
  1119.  
  1120. ARCHIE(1)                USER COMMANDS                  ARCHIE(1)
  1121.  
  1122.  
  1123.  
  1124.      The  Prospero  system  was  created   by   Clifford   Neuman
  1125.      (bcn@isi.edu);   write  to  info-prospero@isi.edu  for  more
  1126.      information on the protocol and its use.
  1127.  
  1128.      This stripped client  was  put  together  by  Brendan  Kehoe
  1129.      (brendan@cs.widener.edu),  with  modifications  by  Clifford
  1130.      Neuman and George Ferguson (ferguson@cs.rochester.edu).
  1131.  
  1132. BUGS
  1133.      There are none; only a few unexpected features.
  1134.  
  1135.  
  1136.  
  1137.  
  1138.  
  1139.  
  1140.  
  1141.  
  1142.  
  1143.  
  1144.  
  1145.  
  1146.  
  1147.  
  1148.  
  1149.  
  1150.  
  1151.  
  1152.  
  1153.  
  1154.  
  1155.  
  1156.  
  1157.  
  1158.  
  1159.  
  1160.  
  1161.  
  1162.  
  1163.  
  1164.  
  1165.  
  1166.  
  1167.  
  1168.  
  1169.  
  1170.  
  1171.  
  1172.  
  1173.  
  1174.  
  1175.  
  1176.  
  1177.  
  1178.  
  1179. Archie (Prospero)  Last change: 9 January 1992                  4
  1180.  
  1181.  
  1182.  
  1183. $EOD
  1184. $!
  1185. $CREATE [.archie]archie.man
  1186. $DECK
  1187. .\" Originally by Jeff Kellem (composer@chem.bu.edu).
  1188. .\"
  1189. .\" This is from rn (1):
  1190. .de Ip
  1191. .br
  1192. .ie \\n.$>=3 .ne \\$3
  1193. .el .ne 3
  1194. .IP "\\$1" \\$2
  1195. ..
  1196. .\"
  1197. .TH ARCHIE 1 "9 January 1992" "Archie (Prospero)"
  1198. .SH NAME
  1199. archie \- query the Archie anonymous FTP databases using Prospero
  1200. .SH SYNOPSIS
  1201. .in +\w'\fBarchie \fR'u
  1202. .ti -\w'\fBarchie \fR'u
  1203. .B archie\
  1204. \ [\ \fB\-cers\fR\ ]\
  1205. \ [\ \fB\-l\fR\ ]\ [\ \fB\-t\fR\ ]\
  1206. \ [\ \fB\-m#\fR\ ]\ [\ \fB\-N#\fR\ ]\
  1207. \ [\ \fB\-h\fR\ \fIhostname\fR\ ]
  1208. [\ \fB\-L\fR\ ]\ \fIstring\fR
  1209. .SH DESCRIPTION
  1210. .B archie
  1211. queries an archie anonymous FTP database looking for the specified
  1212. .I string
  1213. using the
  1214. .B Prospero
  1215. protocol.  This client is based on
  1216. .B Prospero
  1217. version Beta.4.2 and is provided to encourage non-interactive use of
  1218. the Archie servers (and subsequently better performance on both
  1219. sides).  This man page describes version 1.3 of the client.
  1220.  
  1221. The general method of use is of the form
  1222.  
  1223. .RS
  1224. %
  1225. .B archie string
  1226. .RE
  1227. .PP
  1228.  
  1229. This will go to the archie server and ask it to look for all known
  1230. systems that have a file named `string' in their FTP area.  \fBarchie\fP
  1231. will wait, and print out any matches.
  1232.  
  1233. For example,
  1234.  
  1235. .RS
  1236. %
  1237. .B archie emacs
  1238. .RE
  1239. .PP
  1240.  
  1241. will find all anonymous FTP sites in the archie database that have files
  1242. named
  1243. .B emacs
  1244. somewhere in their FTP area.  (This particular query would probably
  1245. return a lot of directories.)  If you want a list of every filename
  1246. that contains \fBemacs\fR \fIanywhere\fR in it, you'd use
  1247.  
  1248. .RS
  1249. %
  1250. .B archie -c emacs
  1251. .RE
  1252. .PP
  1253.  
  1254. Regular expressions, such as
  1255.  
  1256. .RS
  1257. %
  1258. .B archie -r '[xX][lL]isp'
  1259. .RE
  1260. .PP
  1261.  
  1262. may also be used for searches.  (See the manual of a reasonably good
  1263. editor, like GNU Emacs or vi, for more information on using regular
  1264. expressions.)
  1265.  
  1266. .SH OPTIONS
  1267. The options currently available to this
  1268. .B archie
  1269. client are:
  1270.  
  1271. .PD 0
  1272. .TP 12
  1273. .BR \-c
  1274. Search substrings paying attention to upper & lower case.
  1275. .TP
  1276. .BR \-e
  1277. Exact string match.  (This is the default.)
  1278. .TP
  1279. .BR \-r
  1280. Search using a regular expression.
  1281. .TP
  1282. .BR \-s
  1283. Search substrings ignoring the case of the letters.
  1284. .TP
  1285. .BR \-l
  1286. Output results in a form suitable for parsing by programs.
  1287. .TP
  1288. .BR \-t
  1289. Sort the results inverted by date.
  1290. .TP
  1291. .BI \-m#
  1292. Specifies the maximum number of hits (matches) to return (default of 
  1293. \fB95\fR).
  1294. .TP
  1295. .BI \-N#
  1296. Sets the \fIniceness\fR of a query; by default, it's set to 0.
  1297. Without an argument, ``\-N'' defaults to \fB35765\fR.  If you use
  1298. \fB\-N\fR with an argument between 0 and 35765, it'll adjust itself
  1299. accordingly.  (\fBNote\fR: VMS users will have to put quotes around
  1300. this argument, and \fB\-L\fR, like "\fB\-N45\fR"; VMS will otherwise convert
  1301. it to lowercase.)
  1302. .TP
  1303. .BI \-h\ \fIhostname\fR
  1304. Tells the client to query the Archie server \fIhostname\fR.
  1305. .TP
  1306. .BI \-L
  1307. Lists the Archie servers known to the program when it was compiled, as
  1308. well as the name of the default Archie server.  For an up-to-date
  1309. list, write to ``archie@archie.mcgill.ca'' (or any Archie server) with
  1310. the single command of \fIservers\fR.
  1311.  
  1312. .PP
  1313. The three search-modifying arguments (``\-c'', ``\-r'', and ``\-s'')
  1314. are all mutually exclusive; only the last one counts.  If you specify
  1315. \fB\-e\fR with any of ``\-c'', ``\-r'', or ``\-s'',
  1316. the server will first check for an exact match, then fall back to the
  1317. case-sensitive, case-insensitive, or regular expression search.  This is
  1318. so if there are matches that are particularly obvious, it will take a
  1319. minimal amount of time to satisfy your request.
  1320.  
  1321. If you list a single `\-' by itself, any further arguments will be
  1322. taken as part of the search string.  This is intended to enable
  1323. searching for strings that begin with a `\-'; for example:
  1324.  
  1325. .RS
  1326. %
  1327. .B archie \-s \- \-old
  1328. .RE
  1329.  
  1330. will search for all filenames that contain the string `\-old' in them.
  1331.  
  1332. .SH RESPONSE
  1333. Archie servers are set up to respond to a number of requests in a
  1334. queued fashion.  That is, smaller requests get served much more
  1335. quickly than do large requests.  As a result, the more often you query
  1336. the Archie server, or the larger your requests, the longer the queue
  1337. will become, resulting in a longer waiting period for everyone's
  1338. requests.  Please be frugal when possible, for your benefit as well as
  1339. for the other users.
  1340.  
  1341. .SH QUERY PRIORITY
  1342. Please use the ``-N'' option whenever you don't demand immediacy, or
  1343. when you're requesting things that could generate large responses.
  1344. Even when using the nice option, you should still try to avoid big
  1345. jobs during busy periods.  Here is a list of what we consider to be
  1346. nice values that accurately reflect the priority of a job to the server.
  1347.  
  1348. .RS
  1349. .TP 20
  1350. .B Normal
  1351. 0
  1352. .TP
  1353. .B Nice
  1354. 500
  1355. .TP
  1356. .B Nicer
  1357. 1000
  1358. .TP
  1359. .B Very Nice
  1360. 5000
  1361. .TP
  1362. .B Extremely Nice
  1363. 10000
  1364. .TP
  1365. .B Nicest
  1366. 32765
  1367. .RE
  1368.  
  1369. The last priority, \fBNicest\fR, would be used when a job should wait until
  1370. the queue is essentially empty before running.  You should pick one of
  1371. these values to use, possibly modifying it slightly depending on where
  1372. you think your priority should land.  For example, 32760 would mean
  1373. wait until the queue is empty, but jump ahead of other jobs that have
  1374. selected \fBNicest\fR.
  1375.  
  1376. There are certain types of things that we suggest using \fBNicest\fR
  1377. for, irregardless.  In particular, any searches for which you would
  1378. have a hard time justifying the use of anything but extra resources.
  1379. (We all know what those searches would be for.)
  1380.  
  1381. .SH ENVIRONMENT
  1382. .Ip "ARCHIE_HOST" 8
  1383. This will change the host
  1384. .IR archie
  1385. will consult when making queries.  (The default value is what's been
  1386. compiled in.)  The ``\-h'' option will override this.  If you're
  1387. running VMS, create a symbol called ARCHIE_HOST.
  1388.  
  1389. .SH SEE ALSO
  1390. For more information on regular expressions, see the manual pages on:
  1391.  
  1392. .BR regex (3) ,
  1393. .BR ed (1)
  1394.  
  1395. Also read the file \fBarchie/doc/whatis.archie\fR on
  1396. \fBarchie.mcgill.ca\fR for a detailed paper on Archie as a whole.
  1397.  
  1398. .SH AUTHORS
  1399. The 
  1400. .B archie
  1401. service was conceived and implemented by Alan Emtage (\fBbajan@cs.mcgill.ca\fR),
  1402. Peter Deutsch (\fBpeterd@cs.mcgill.ca\fR), and Bill Heelan
  1403. (\fBwheelan@cs.mcgill.ca\fR).  The entire Internet is in their debt.
  1404.  
  1405. The \fBProspero\fR system was created by Clifford Neuman
  1406. (\fBbcn@isi.edu\fR); write to \fBinfo\-prospero@isi.edu\fR for more
  1407. information on the protocol and its use.
  1408.  
  1409. This stripped client was put together by Brendan Kehoe
  1410. (\fBbrendan@cs.widener.edu\fR), with modifications by
  1411. Clifford Neuman and George Ferguson (\fBferguson@cs.rochester.edu\fR).
  1412.  
  1413. .SH BUGS
  1414. There are none; only a few unexpected features.
  1415.  
  1416. $EOD
  1417. $!
  1418. $CREATE [.archie]aquery.c
  1419. $DECK
  1420. /*
  1421.  * aquery.c : Programmatic Prospero interface to Archie
  1422.  *
  1423.  * Copyright (c) 1991 by the University of Washington
  1424.  *
  1425.  * For copying and distribution information, please see the file
  1426.  * <copyright.h>.
  1427.  *
  1428.  * Originally part of the Prospero Archie client by Clifford 
  1429.  * Neuman (bcn@isi.edu).  Modifications, addition of programmatic interface,
  1430.  * and new sorting code by George Ferguson (ferguson@cs.rochester.edu) 
  1431.  * and Brendan Kehoe (brendan@cs.widener.edu).  MSDOS and OS2 modifications
  1432.  * to use with PC/TCP by Mark Towfiq (towfiq@FTP.COM).
  1433.  */
  1434.  
  1435. #include <copyright.h>
  1436.  
  1437. #include <stdio.h>
  1438.  
  1439. #include <pfs.h>
  1440. #include <perrno.h>
  1441. #include <archie.h>
  1442.  
  1443. #include <pmachine.h>
  1444. #ifdef NEED_STRING_H
  1445. # include <string.h>            /* for char *index() */
  1446. #else
  1447. # include <strings.h>            /* for char *index() */
  1448. #endif
  1449.  
  1450. static void translateArchieResponse();
  1451.  
  1452. extern int pwarn;
  1453. extern char p_warn_string[];
  1454.  
  1455. /*
  1456.  * archie_query : Sends a request to _host_, telling it to search for
  1457.  *                _string_ using _query_type_ as the search method.
  1458.  *                No more than _max_hits_ matches are to be returned
  1459.  *                skipping over _offset_ matches.
  1460.  *
  1461.  *          archie_query returns a linked list of virtual links. 
  1462.  *                If _flags_ does not include AQ_NOTRANS, then the Archie
  1463.  *                responses will be translated. If _flags_ does not include 
  1464.  *                AQ_NOSORT, then the list will be sorted using _cmp_proc_ to
  1465.  *                compare pairs of links.  If _cmp_proc_ is NULL or AQ_DEFCMP,
  1466.  *                then the default comparison procedure, defcmplink(), is used
  1467.  *                sorting by host, then filename. If cmp_proc is AQ_INVDATECMP
  1468.  *                then invdatecmplink() is used, sorting inverted by date.
  1469.  *                otherwise a user-defined comparison procedure is called.
  1470.  *
  1471.  *                archie_query returns NULL and sets perrno if the query
  1472.  *                failed. Note that it can return NULL with perrno == PSUCCESS
  1473.  *                if the query didn't fail but there were simply no matches.
  1474.  *
  1475.  *   query_type:  S  Substring search ignoring case   
  1476.  *                C  Substring search with case significant
  1477.  *                R  Regular expression search
  1478.  *                =  Exact String Match
  1479.  *            s,c,e  Tries exact match first and falls back to S, C, or R 
  1480.  *                   if not found.
  1481.  *
  1482.  *     cmp_proc:  AQ_DEFCMP      Sort by host, then filename
  1483.  *                AQ_INVDATECMP  Sort inverted by date
  1484.  *
  1485.  *        flags:  AQ_NOSORT      Don't sort results
  1486.  *                AQ_NOTRANS     Don't translate results
  1487.  */
  1488. VLINK 
  1489. archie_query(host,string,max_hits,offset,query_type,cmp_proc,flags)
  1490.     char    *host,*string;
  1491.     int        max_hits,offset;
  1492.     char    query_type;
  1493.     int        (*cmp_proc)();
  1494.     int        flags;
  1495.     {
  1496.     char qstring[MAX_VPATH];    /* For construting the query  */
  1497.     VLINK    links;        /* Matches returned by server */
  1498.     VDIR_ST    dir_st;         /* Filled in by get_vdir      */
  1499.     PVDIR    dir= &dir_st;
  1500.     
  1501.     VLINK    p,q,r,lowest,nextp,pnext,pprev;
  1502.     int    tmp;
  1503.  
  1504.     /* Set the cmp_proc if not given */
  1505.     if (cmp_proc == NULL) cmp_proc = defcmplink;
  1506.  
  1507.     /* Make the query string */
  1508.     sprintf(qstring,"ARCHIE/MATCH(%d,%d,%c)/%s",
  1509.         max_hits,offset,query_type,string);
  1510.  
  1511.     /* Initialize Prospero structures */
  1512.     perrno = PSUCCESS; *p_err_string = '\0';
  1513.     pwarn = PNOWARN; *p_warn_string = '\0';
  1514.     vdir_init(dir);
  1515.     
  1516.     /* Retrieve the list of matches, return error if there was one */
  1517. #if defined(MSDOS)
  1518.     if(tmp = get_vdir(host, qstring, "", dir, (long)GVD_ATTRIB|GVD_NOSORT,
  1519.         NULL, NULL)) {
  1520. #else
  1521.     if(tmp = get_vdir(host,qstring,"",dir,GVD_ATTRIB|GVD_NOSORT,NULL,NULL)) {
  1522. # endif
  1523.         perrno = tmp;
  1524.         return(NULL);
  1525.     }
  1526.  
  1527.     /* Save the links, and clear in dir in case it's used again   */
  1528.     links = dir->links; dir->links = NULL;
  1529.  
  1530.     /* As returned, list is sorted by suffix, and conflicting     */
  1531.     /* suffixes appear on a list of "replicas".  We want to       */
  1532.     /* create a one-dimensional list sorted by host then filename */
  1533.     /* and maybe by some other parameter                          */
  1534.  
  1535.     /* First flatten the doubly-linked list */
  1536.     for (p = links; p != NULL; p = nextp) {
  1537.         nextp = p->next;
  1538.         if (p->replicas != NULL) {
  1539.         p->next = p->replicas;
  1540.         p->next->previous = p;
  1541.         for (r = p->replicas; r->next != NULL; r = r->next)
  1542.             /*EMPTY*/ ;
  1543.         r->next = nextp;
  1544.         nextp->previous = r;
  1545.         p->replicas = NULL;
  1546.         }
  1547.     }
  1548.  
  1549.     /* Translate the filenames unless NOTRANS was given */
  1550.     if (!(flags & AQ_NOTRANS))
  1551.         for (p = links; p != NULL; p = p->next)
  1552.         translateArchieResponse(p);
  1553.  
  1554.     /* If NOSORT given, then just hand it back */
  1555.     if (flags & AQ_NOSORT) {
  1556.         perrno = PSUCCESS;
  1557.         return(links);
  1558.     }
  1559.  
  1560.     /* Otherwise sort it using a selection sort and the given cmp_proc */
  1561.     for (p = links; p != NULL; p = nextp) {
  1562.         nextp = p->next;
  1563.         lowest = p;
  1564.         for (q = p->next; q != NULL; q = q->next)
  1565.         if ((*cmp_proc)(q,lowest) < 0)
  1566.             lowest = q;
  1567.         if (p != lowest) {
  1568.         /* swap the two links */
  1569.         pnext = p->next;
  1570.         pprev = p->previous;
  1571.         if (lowest->next != NULL)
  1572.             lowest->next->previous = p;
  1573.         p->next = lowest->next;
  1574.         if (nextp == lowest) {
  1575.             p->previous = lowest;
  1576.         } else {
  1577.             lowest->previous->next = p;
  1578.             p->previous = lowest->previous;
  1579.         }
  1580.         if (nextp == lowest) {
  1581.             lowest->next = p;
  1582.         } else {
  1583.             pnext->previous = lowest;
  1584.             lowest->next = pnext;
  1585.         }
  1586.         if (pprev != NULL)
  1587.             pprev->next = lowest;
  1588.         lowest->previous = pprev;
  1589.         /* keep the head of the list in the right place */
  1590.         if (links == p)
  1591.             links = lowest;
  1592.         }
  1593.     }
  1594.  
  1595.     /* Return the links */
  1596.     perrno = PSUCCESS;
  1597.     return(links);
  1598.     }
  1599.  
  1600. /*
  1601.  * translateArchieResponse: 
  1602.  *
  1603.  *   If the given link is for an archie-pseudo directory, fix it. 
  1604.  *   This is called unless AQ_NOTRANS was given to archie_query().
  1605.  */
  1606. static void
  1607. translateArchieResponse(l)
  1608.     VLINK l;
  1609.     {
  1610.     char *slash;
  1611.  
  1612.     if (strcmp(l->type,"DIRECTORY") == 0) {
  1613.         if (strncmp(l->filename,"ARCHIE/HOST",11) == 0) {
  1614.         l->type = stcopyr("EXTERNAL(AFTP,DIRECTORY)",l->type);
  1615.         l->host = stcopyr(l->filename+12,l->host);
  1616.         slash = (char *)index(l->host,'/');
  1617.         if (slash) {
  1618.             l->filename = stcopyr(slash,l->filename);
  1619.             *slash++ = '\0';
  1620.         } else
  1621.             l->filename = stcopyr("",l->filename);
  1622.         }
  1623.     }
  1624.     }
  1625.  
  1626. /*
  1627.  * defcmplink: The default link comparison function for sorting. Compares
  1628.  *           links p and q first by host then by filename. Returns < 0 if p
  1629.  *             belongs before q, > 0 if p belongs after q, and == 0 if their
  1630.  *             host and filename fields are identical.
  1631.  */
  1632. int
  1633. defcmplink(p,q)
  1634.     VLINK p,q;
  1635.     {
  1636.     int result;
  1637.  
  1638.     if ((result=strcmp(p->host,q->host)) != 0)
  1639.         return(result);
  1640.     else
  1641.         return(strcmp(p->filename,q->filename));
  1642.     }
  1643.  
  1644. /*
  1645.  * invdatecmplink: An alternative comparison function for sorting that
  1646.  *               compares links p and q first by LAST-MODIFIED date,
  1647.  *                 if they both have that attribute. If both links
  1648.  *                 don't have that attribute or the dates are the
  1649.  *                 same, it then calls defcmplink() and returns its 
  1650.  *           value.
  1651.  */
  1652. int
  1653. invdatecmplink(p,q)
  1654.     VLINK p,q;
  1655.     {
  1656.     PATTRIB pat,qat;
  1657.     char *pdate,*qdate;
  1658.     int result;
  1659.     
  1660.     pdate = qdate = NULL;
  1661.     for (pat = p->lattrib; pat; pat = pat->next)
  1662.         if(strcmp(pat->aname,"LAST-MODIFIED") == 0)
  1663.         pdate = pat->value.ascii;
  1664.     for (qat = q->lattrib; qat; qat = qat->next)
  1665.         if(strcmp(qat->aname,"LAST-MODIFIED") == 0)
  1666.         qdate = qat->value.ascii;
  1667.     if(!pdate && !qdate) return(defcmplink(p,q));
  1668.     if(!pdate) return(1); 
  1669.     if(!qdate) return(-1);
  1670.     if((result=strcmp(qdate,pdate)) == 0) return(defcmplink(p,q));
  1671.     else return(result);
  1672.     }
  1673. $EOD
  1674. $!
  1675. $CREATE [.archie]atalloc.c
  1676. $DECK
  1677. /*
  1678.  * Copyright (c) 1989, 1990 by the University of Washington
  1679.  *
  1680.  * For copying and distribution information, please see the file
  1681.  * <copyright.h>.
  1682.  */
  1683.  
  1684. #include <copyright.h>
  1685. #include <stdio.h>
  1686.  
  1687. #include <pfs.h>
  1688. #include <pmachine.h> /* for correct definition of ZERO */
  1689.  
  1690. static PATTRIB    lfree = NULL;
  1691. int        pattrib_count = 0;
  1692. int        pattrib_max = 0;
  1693.  
  1694. /*
  1695.  * atalloc - allocate and initialize vlink structure
  1696.  *
  1697.  *    ATALLOC returns a pointer to an initialized structure of type
  1698.  *    PATTRIB.  If it is unable to allocate such a structure, it
  1699.  *    returns NULL.
  1700.  */
  1701. PATTRIB
  1702. atalloc()
  1703.     {
  1704.     PATTRIB    at;
  1705.     if(lfree) {
  1706.         at = lfree;
  1707.         lfree = lfree->next;
  1708.     }
  1709.     else {
  1710.         at = (PATTRIB) malloc(sizeof(PATTRIB_ST));
  1711.         if (!at) return(NULL);
  1712.         pattrib_max++;
  1713.     }
  1714.  
  1715.     pattrib_count++;
  1716.  
  1717.     ZERO(at);
  1718.     /* Initialize and fill in default values; all items are
  1719.        0 [or NULL] save precedence */
  1720.     at->precedence = ATR_PREC_OBJECT;
  1721.  
  1722.     return(at);
  1723.     }
  1724.  
  1725. /*
  1726.  * atfree - free a PATTRIB structure
  1727.  *
  1728.  *    ATFREE takes a pointer to a PATTRRIB structure and adds it to
  1729.  *    the free list for later reuse.
  1730.  */
  1731. void
  1732. atfree(at)
  1733.     PATTRIB    at;
  1734.     {
  1735.     if(at->aname) stfree(at->aname);
  1736.  
  1737.     if((strcmp(at->avtype,"ASCII") == 0) && at->value.ascii) 
  1738.         stfree(at->value.ascii);
  1739.     if((strcmp(at->avtype,"LINK") == 0) && at->value.link) 
  1740.         vlfree(at->value.link);
  1741.     
  1742.     if(at->avtype) stfree(at->avtype);
  1743.  
  1744.     at->next = lfree;
  1745.     at->previous = NULL;
  1746.     lfree = at;
  1747.     pattrib_count--;
  1748.     }
  1749.  
  1750. /*
  1751.  * atlfree - free a PATTRIB structure
  1752.  *
  1753.  *    ATLFREE takes a pointer to a PATTRIB structure frees it and any linked
  1754.  *    PATTRIB structures.  It is used to free an entrie list of PATTRIB
  1755.  *    structures.
  1756.  */
  1757. void
  1758. atlfree(at)
  1759.     PATTRIB    at;
  1760.     {
  1761.     PATTRIB    nxt;
  1762.  
  1763.     while(at != NULL) {
  1764.         nxt = at->next;
  1765.         atfree(at);
  1766.         at = nxt;
  1767.     }
  1768.     }
  1769.  
  1770. $EOD
  1771. $!
  1772. $CREATE [.archie]dirsend.c
  1773. $DECK
  1774. /*
  1775.  * Copyright (c) 1989, 1990, 1991 by the University of Washington
  1776.  *
  1777.  * For copying and distribution information, please see the file
  1778.  * <copyright.h>.
  1779.  */
  1780.  
  1781. /* If you're going to hack on this, I'd suggest using unifdef with -UCUTCP
  1782.    and possibly -UVMS, for your working copy.  When you've got your changes
  1783.    done, come back and add them into this main file.  It's getting pretty
  1784.    nasty down there.  */
  1785.  
  1786. #include <copyright.h>
  1787. #include <stdio.h>
  1788. #include <errno.h>
  1789.  
  1790. #ifdef VMS
  1791. # ifdef WOLLONGONG
  1792. #  include "twg$tcp:[netdist.include]netdb.h"
  1793. # else /* not Wollongong */
  1794. #  ifdef UCX
  1795. #   include netdb
  1796. #  else /* Multinet */
  1797. #   include "multinet_root:[multinet.include]netdb.h"
  1798. #  endif
  1799. # endif
  1800. # include <vms.h>
  1801. #else /* not VMS */
  1802. # include <sys/types.h> /* this may/will define FD_SET etc */
  1803. # ifdef u3b2
  1804. #  include <sys/inet.h> /* THIS does FD_SET etc on AT&T 3b2s.  */
  1805. # endif /* u3b2 */
  1806. # include <pmachine.h>
  1807. # if defined(NEED_TIME_H) && !defined(AUX)
  1808. #  include <time.h>
  1809. # else
  1810. #  include <sys/time.h>
  1811. # endif
  1812. # ifdef WANT_BOTH_TIME
  1813. #  include <sys/time.h>
  1814. # endif
  1815. # ifdef NEED_STRING_H
  1816. #  include <string.h>
  1817. # else
  1818. #  include <strings.h>
  1819. # endif
  1820. # ifdef CUTCP
  1821. #  include <msdos/cutcp.h>
  1822. #  include <msdos/netevent.h>
  1823. #  include <msdos/hostform.h>
  1824. # else /* not CUTCP */
  1825. #  include <netdb.h>
  1826. #  include <sys/socket.h>
  1827. # endif
  1828. # ifdef NEED_SELECT_H
  1829. #  include <sys/select.h>
  1830. # endif /* NEED_SELECT_H */
  1831. # ifndef IN_H
  1832. #  include <netinet/in.h>
  1833. #  define IN_H
  1834. # endif
  1835. # ifndef hpux
  1836. #  include <arpa/inet.h>
  1837. # endif
  1838. #endif /* !VMS */
  1839.  
  1840. /* Interactive UNIX keeps some of the socket definitions in funny places.  */
  1841. #ifdef ISC
  1842. # include <net/errno.h>
  1843. #endif /* ISC */
  1844.  
  1845. #include <pfs.h>
  1846. #include <pprot.h>
  1847. #include <pcompat.h>
  1848. #include <perrno.h>
  1849.  
  1850. /* Gnu C currently fails to pass structures on Sparcs properly.  This directly
  1851.    effects the calling of inet_ntoa().  To get around it, we use this hack;
  1852.    take the address of what's being called to inet_ntoa, so it gets it
  1853.    properly.  This won't be necessary with gcc 2.0.  */
  1854. #if defined(sun) && defined(__GNUC__) && !defined(__GNU_LIBRARY__)
  1855. # define SUN_GNU_FIX &
  1856. #else
  1857. # define SUN_GNU_FIX
  1858. #endif
  1859.  
  1860. static int notprived = 0;
  1861. #ifndef MSDOS
  1862. extern int errno;
  1863. #endif
  1864. extern int perrno;
  1865. extern int rdgram_priority;
  1866. #ifdef DEBUG
  1867. extern int pfs_debug;
  1868. #endif
  1869. extern int pfs_disable_flag;
  1870.  
  1871. char    *nlsindex();
  1872.  
  1873. #define max(X, Y)  ((X) > (Y) ? (X) : (Y))
  1874.  
  1875. static int        dir_udp_port = 0;    /* Remote UDP port number */
  1876.  
  1877. #ifdef CUTCP
  1878. # define    NS_TIMEOUT    15
  1879. #endif
  1880.  
  1881. static unsigned short    next_conn_id = 0;
  1882.  
  1883. static int client_dirsrv_timeout = CLIENT_DIRSRV_TIMEOUT;
  1884. static int client_dirsrv_retry = CLIENT_DIRSRV_RETRY; 
  1885.  
  1886. /* These were parameters to dirsend() */
  1887. static PTEXT pkt;
  1888. static char *hostname;
  1889. static struct sockaddr_in *hostaddr;
  1890.  
  1891. /* These were locals in dirsend(). Note that the initializations here
  1892.  * are really meaningless since we have to redo them for each call to
  1893.  * dirsend() since they were formerly automatically initialized.
  1894.  */
  1895. static PTEXT        first = NULL;    /* First returned packet     */
  1896. static PTEXT        next;        /* The one we are waiting for      */
  1897. static PTEXT        vtmp;           /* For reorganizing linked list  */
  1898. static PTEXT        comp_thru;    /* We have all packets though    */
  1899. static int        lp = -1;    /* Opened UDP port             */
  1900. static int        hdr_len;    /* Header Length                 */
  1901. static int        nd_pkts;    /* Number of packets we want     */
  1902. static int        no_pkts;    /* Number of packets we have     */
  1903. static int        pkt_cid;        /* Packet connection identifier  */
  1904. static unsigned short    this_conn_id;    /* Connection ID we are using    */
  1905. static unsigned short    recvd_thru;    /* Received through              */
  1906. static short        priority;    /* Priority for request          */
  1907. static short        one = 0;    /* Pointer to value 1            */
  1908. static short        zero = 0;    /* Pointer to value 0         */
  1909. static char        *seqtxt;    /* Pointer to text w/ sequence # */
  1910. static struct sockaddr_in  us;        /* Our address                   */
  1911. static struct sockaddr_in  to;        /* Address to send query     */
  1912. static struct sockaddr_in  from;    /* Reply received from         */
  1913. static int        from_sz;    /* Size of from structure     */
  1914. static struct hostent    *host;        /* Host info from gethostbyname  */
  1915. static long        newhostaddr;    /* New host address from *host   */
  1916. static int        req_udp_port=0; /* Requested port (optional)     */
  1917. static char        *openparen;    /* Delimits port in name         */
  1918. static char        hostnoport[500];/* Host name without port        */
  1919. static int        ns;        /* Number of bytes actually sent */
  1920. static int        nr;        /* Number of bytes received      */
  1921. static SELECTARG    readfds;    /* Used for select         */
  1922. static int        tmp;
  1923. static char        *ctlptr;    /* Pointer to control field      */
  1924. static short        stmp;        /* Temp short for conversions    */
  1925. static int        backoff;    /* Server requested backoff      */
  1926. static unsigned char    rdflag11;    /* First byte of flags (bit vect)*/
  1927. static unsigned char    rdflag12;    /* Second byte of flags (int)    */
  1928. static int        scpflag = 0;    /* Set if any sequencd cont pkts */
  1929. static int        ackpend = 0;    /* Acknowledgement pending      */
  1930. static int        gaps = 0;    /* Gaps present in recvd pkts   */
  1931. static struct timeval    timeout;    /* Time to wait for response    */
  1932. static struct timeval    ackwait;    /* Time to wait before acking   */
  1933. static struct timeval    gapwait;    /* Time to wait b4 filling gaps */
  1934. static struct timeval    *selwait;    /* Time to wait for select      */
  1935. static int        retries;    /* was = client_dirsrv_retry    */
  1936. char   to_hostname[512];        /* lmjm: saves inet_ntoa() str  */
  1937.  
  1938. /* These are added so dirsend() "blocks" properly */
  1939. static PTEXT dirsendReturn;
  1940. static int dirsendDone;
  1941.  
  1942. /* And here are the values for dirsendDone */
  1943. #define DSRET_DONE        1
  1944. #define DSRET_SEND_ERROR    -1
  1945. #define DSRET_RECV_ERROR    -2
  1946. #define DSRET_SELECT_ERROR    -3
  1947. #define DSRET_TIMEOUT        -4
  1948. #define DSRET_ABORTED        -5
  1949.  
  1950. /* New procedures to break up dirsend() */
  1951. static int initDirsend();
  1952. static void retryDirsend(), keepWaitingDirsend();
  1953. static void timeoutProc();
  1954. static void readProc();
  1955.  
  1956. /* Wrappers around X calls to allow non-X usage */
  1957. static void processEvent();
  1958.  
  1959. /* Extra stuff for the asynchronous X version of dirsend() */
  1960. typedef char *XtPointer;
  1961. typedef char *XtInputId;
  1962. typedef char *XtIntervalId;
  1963.  
  1964. static XtInputId inputId;
  1965. static XtIntervalId timerId = (XtIntervalId)0;
  1966.  
  1967. /*
  1968.  * dirsend - send packet and receive response
  1969.  *
  1970.  *   DIRSEND takes a pointer to a structure of type PTEXT, a hostname,
  1971.  *   and a pointer to a host address.  It then sends the supplied
  1972.  *   packet off to the directory server on the specified host.  If
  1973.  *   hostaddr points to a valid address, that address is used.  Otherwise,
  1974.  *   the hostname is looked up to obtain the address.  If hostaddr is a
  1975.  *   non-null pointer to a 0 address, then the address will be replaced
  1976.  *   with that found in the hostname lookup.
  1977.  *
  1978.  *   DIRSEND will wait for a response and retry an appropriate
  1979.  *   number of times as defined by timeout and retries (both static
  1980.  *   variables).  It will collect however many packets form the reply, and
  1981.  *   return them in a structure (or structures) of type PTEXT.
  1982.  *
  1983.  *   DIRSEND will free the packet that it is presented as an argument.
  1984.  *   The packet is freed even if dirsend fails.
  1985.  */
  1986. PTEXT
  1987. dirsend(pkt_p,hostname_p,hostaddr_p)
  1988.     PTEXT pkt_p;
  1989.     char *hostname_p;
  1990.     struct sockaddr_in    *hostaddr_p;
  1991. {
  1992.     /* copy parameters to globals since other routines use them */
  1993.     pkt = pkt_p;
  1994.     hostname = hostname_p;
  1995.     hostaddr = hostaddr_p;
  1996.     /* Do the initializations of formerly auto variables */
  1997.     first = NULL;
  1998.     lp = -1;
  1999.     one = 0;
  2000.     zero = 0;
  2001.     req_udp_port=0;
  2002.     scpflag = 0;
  2003.     ackpend = 0;
  2004.     gaps = 0;
  2005.     retries = client_dirsrv_retry;
  2006.  
  2007.     if (initDirsend() < 0)
  2008.     return(NULL);
  2009.  
  2010.     /* set the first timeout */
  2011.     retryDirsend();
  2012.  
  2013.     dirsendReturn = NULL;
  2014.     dirsendDone = 0;
  2015.     /* Until one of the callbacks says to return, keep processing events */
  2016.     while (!dirsendDone)
  2017.     processEvent();
  2018.  
  2019.     /* Return whatever we're supposed to */
  2020.     return(dirsendReturn);
  2021. }
  2022.  
  2023.  
  2024. /*    -    -    -    -    -    -    -    -    */
  2025. /* This function does all the initialization that used to be done at the
  2026.  * start of dirsend(), including opening the socket descriptor "lp". It
  2027.  * returns the descriptor if successful, otherwise -1 to indicate that
  2028.  * dirsend() should return NULL immediately.
  2029.  */
  2030. static int
  2031. initDirsend()
  2032. {
  2033.     if(one == 0) one = htons((short) 1);
  2034.  
  2035.     priority = htons(rdgram_priority);
  2036.  
  2037.     timeout.tv_sec = client_dirsrv_timeout;
  2038.     timeout.tv_usec = 0;
  2039.  
  2040.     ackwait.tv_sec = 0;
  2041.     ackwait.tv_usec = 500000;
  2042.  
  2043.     gapwait.tv_sec = (client_dirsrv_timeout < 5 ? client_dirsrv_timeout : 5);
  2044.     gapwait.tv_usec = 0;
  2045.  
  2046.     comp_thru = NULL;
  2047.     perrno = 0;
  2048.     nd_pkts = 0;
  2049.     no_pkts = 0;
  2050.     pkt_cid = 0;
  2051.  
  2052.     /* Find first connection ID */
  2053.     if(next_conn_id == 0) {
  2054.     srand(getpid()+time(0)); /* XXX: arg ok, but not right type. */
  2055.     next_conn_id = rand();
  2056.     }
  2057.  
  2058.  
  2059.     /* If necessary, find out what udp port to send to */
  2060.     if (dir_udp_port == 0) {
  2061.         register struct servent *sp;
  2062.     tmp = pfs_enable; pfs_enable = PMAP_DISABLE;
  2063. #ifdef USE_ASSIGNED_PORT
  2064.     /* UCX needs 0 & -1 */
  2065.         if ((sp = getservbyname("prospero","udp")) <= 0) {
  2066. #ifdef DEBUG
  2067.         if (pfs_debug)
  2068.         fprintf(stderr, "dirsrv: udp/prospero unknown service - using %d\n", 
  2069.             PROSPERO_PORT);
  2070. #endif
  2071.         dir_udp_port = htons((u_short) PROSPERO_PORT);
  2072.         }
  2073. #else
  2074.     /* UCX needs 0 & -1 */
  2075.         sp = getservbyname("dirsrv","udp");
  2076.     if (sp == (struct servent *)0 || sp == (struct servent *)-1) {
  2077. #ifdef DEBUG
  2078.         if (pfs_debug)
  2079.         fprintf(stderr, "dirsrv: udp/dirsrv unknown service - using %d\n", 
  2080.             DIRSRV_PORT);
  2081. #endif
  2082.         dir_udp_port = htons((u_short) DIRSRV_PORT);
  2083.         }
  2084. #endif
  2085.     else dir_udp_port = sp->s_port;
  2086.     pfs_enable = tmp;
  2087. #ifdef DEBUG
  2088.         if (pfs_debug > 3)
  2089.             fprintf(stderr,"dir_udp_port is %d\n", ntohs(dir_udp_port));
  2090. #endif
  2091.     }
  2092.  
  2093.     /* If we were given the host address, then use it.  Otherwise  */
  2094.     /* lookup the hostname.  If we were passed a host address of   */
  2095.     /* 0, we must lookup the host name, then replace the old value */
  2096.     if(!hostaddr || (hostaddr->sin_addr.s_addr == 0)) {
  2097.     /* I we have a null host name, return an error */
  2098.     if((hostname == NULL) || (*hostname == '\0')) {
  2099. #ifdef DEBUG
  2100.             if (pfs_debug)
  2101.                 fprintf(stderr, "dirsrv: Null hostname specified\n");
  2102. #endif
  2103.         perrno = DIRSEND_BAD_HOSTNAME;
  2104.         ptlfree(pkt);
  2105.             /* return(NULL); */
  2106.         return(-1);
  2107.     }
  2108.     /* If a port is included, save it away */
  2109.     if(openparen = index(hostname,'(')) {
  2110.         sscanf(openparen+1,"%d",&req_udp_port);
  2111.         strncpy(hostnoport,hostname,400);
  2112.         if((openparen - hostname) < 400) {
  2113.         *(hostnoport + (openparen - hostname)) = '\0';
  2114.         hostname = hostnoport;
  2115.         }
  2116.     }
  2117.     tmp = pfs_enable; pfs_enable = PMAP_DISABLE;
  2118.     if((host = gethostbyname(hostname)) == NULL) {
  2119.         pfs_enable = tmp;
  2120.         /* Check if a numeric address */
  2121.         newhostaddr = inet_addr(hostname);
  2122.         if(newhostaddr == -1) {
  2123. #ifdef DEBUG
  2124.         if (pfs_debug)
  2125.           fprintf(stderr, "dirsrv: Can't resolve host %s\n",hostname);
  2126. #endif
  2127.         perrno = DIRSEND_BAD_HOSTNAME;
  2128.         ptlfree(pkt);
  2129.         /* return(NULL); */
  2130.         return(-1);
  2131.         }
  2132.         bzero((char *)&to, S_AD_SZ);
  2133.         to.sin_family = AF_INET;
  2134.         bcopy((char *) &newhostaddr, (char *)&to.sin_addr, 4);
  2135.         if(hostaddr) bcopy(&to,hostaddr, S_AD_SZ);
  2136.     }
  2137.     else {
  2138.         pfs_enable = tmp;
  2139.         bzero((char *)&to, S_AD_SZ);
  2140.         to.sin_family = host->h_addrtype;
  2141. #ifdef CUTCP
  2142.         bcopy((char *) &host->h_addr, (char *)&to.sin_addr, host->h_length);
  2143. #else
  2144.         bcopy(host->h_addr, (char *)&to.sin_addr, host->h_length);
  2145. #endif
  2146.         if(hostaddr) bcopy(&to,hostaddr, S_AD_SZ);
  2147.     }
  2148.     }
  2149.     else bcopy(hostaddr,&to, S_AD_SZ);
  2150.     /* lmjm: Save away the hostname */
  2151.     strncpy(to_hostname,
  2152.         inet_ntoa(SUN_GNU_FIX *(struct in_addr *)&to.sin_addr),
  2153.         sizeof(to_hostname)-1);
  2154.  
  2155.     if(req_udp_port) to.sin_port = htons(req_udp_port);
  2156.     else to.sin_port = dir_udp_port;
  2157.  
  2158.     /* If a port was specified in hostaddr, use it, otherwise fill it in */
  2159.     if(hostaddr) {
  2160.     if(hostaddr->sin_port) to.sin_port = hostaddr->sin_port;
  2161.     else hostaddr->sin_port = to.sin_port;
  2162.     }
  2163.  
  2164. #ifndef CUTCP
  2165.     /* Must open a new port each time. we do not want to see old */
  2166.     /* responses to messages we are done with                    */
  2167.     if ((lp = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  2168. #ifdef DEBUG
  2169.         if (pfs_debug)
  2170.             fprintf(stderr,"dirsrv: Can't open socket\n");
  2171. #endif
  2172.     perrno = DIRSEND_UDP_CANT;
  2173.     ptlfree(pkt);
  2174.         /* return(NULL); */
  2175.     return(-1);
  2176.     }
  2177. #endif /* not CUTCP */
  2178.  
  2179.     /* Try to bind it to a privileged port - loop through candidate */
  2180.     /* ports trying to bind.  If failed, that's OK, we will let the */
  2181.     /* system assign a non-privileged port later                    */
  2182. #ifndef CUTCP
  2183.     if(!notprived) {
  2184.     for(tmp = PROS_FIRST_PRIVP; tmp < PROS_FIRST_PRIVP+PROS_NUM_PRIVP; 
  2185.         tmp++) {
  2186. #endif
  2187.         bzero((char *)&us, sizeof(us));
  2188.         us.sin_family = AF_INET;
  2189. #ifndef CUTCP
  2190.         us.sin_port = htons((u_short) tmp);
  2191.         if (bind(lp, (struct sockaddr *)&us, sizeof(us))) {
  2192.         if(errno != EADDRINUSE) {
  2193.             notprived++;
  2194.             break;
  2195.         }
  2196.         }
  2197.         else break;
  2198.     }
  2199.     }
  2200. #else
  2201.     us.sin_port = htons(PROS_FIRST_PRIVP);
  2202.     netulisten(PROS_FIRST_PRIVP);
  2203. #endif
  2204.  
  2205. #ifndef USE_V3_PROT
  2206.     /* Add header */
  2207.     if(rdgram_priority) {
  2208.     pkt->start -= 15;
  2209.     pkt->length += 15;
  2210.     *(pkt->start) = (char) 15;
  2211.     bzero(pkt->start+9,4);
  2212.     *(pkt->start+11) = 0x02;
  2213.     bcopy(&priority,pkt->start+13,2);
  2214.     }
  2215.     else {
  2216.     pkt->start -= 9;
  2217.     pkt->length += 9;
  2218.     *(pkt->start) = (char) 9;
  2219.     }
  2220.     this_conn_id = htons(next_conn_id++);
  2221.     if(next_conn_id == 0) next_conn_id++;
  2222.     bcopy(&this_conn_id,pkt->start+1,2);
  2223.     bcopy(&one,pkt->start+3,2);
  2224.     bcopy(&one,pkt->start+5,2);
  2225.     bzero(pkt->start+7,2);
  2226. #endif
  2227.  
  2228. #ifdef DEBUG
  2229.     if (pfs_debug > 2) {
  2230. #ifndef USE_V3_PROT
  2231.         if (to.sin_family == AF_INET) {
  2232.         if(req_udp_port) 
  2233.         fprintf(stderr,"Sending message to %s+%d(%d)...",
  2234.             to_hostname, req_udp_port, ntohs(this_conn_id));
  2235.         else fprintf(stderr,"Sending message to %s(%d)...",
  2236.              to_hostname, ntohs(this_conn_id));
  2237.     }
  2238. #else
  2239.         if (to.sin_family == AF_INET) 
  2240.         fprintf(stderr,"Sending message to %s...", to_hostname);
  2241. #endif /* USE_V3_PROT */
  2242.         else
  2243.             fprintf(stderr,"Sending message...");
  2244.         (void) fflush(stderr);
  2245.     }
  2246. #endif /* DEBUG */
  2247.  
  2248.     first = ptalloc();
  2249.     next = first;
  2250.  
  2251. #ifndef CUTCP
  2252.     return(lp);
  2253. #else
  2254.     return(1);
  2255. #endif /* CUTCP */
  2256. }
  2257.  
  2258. /*    -    -    -    -    -    -    -    -    */
  2259. /*
  2260.  * This used to be a label to goto to retry the last packet. Now we resend
  2261.  * the packet and call keepWaitingDirsend() to wait for a reply. (We
  2262.  * call keepWaitingDirsend() because formerly the code dropped through
  2263.  * the keep_waiting label.)
  2264.  */
  2265. static void
  2266. retryDirsend()
  2267. {
  2268. #ifdef CUTCP
  2269.     int lretry = 3;
  2270. #endif
  2271.     gaps = ackpend = 0;
  2272.  
  2273. #ifndef CUTCP
  2274.     ns = sendto(lp,(char *)(pkt->start), pkt->length, 0, (struct sockaddr *)&to, S_AD_SZ);
  2275. #else
  2276.     while(--lretry) {
  2277.         ns = netusend(&to.sin_addr,ntohs(to.sin_port),ntohs(us.sin_port),
  2278.               (char *) pkt->start, pkt->length);
  2279.         if(!ns)
  2280.         break;
  2281.         Stask();
  2282.         Stask();
  2283.         Stask();
  2284.     }
  2285. #endif /* CUTCP */
  2286.  
  2287. #ifndef CUTCP
  2288.     if(ns != pkt->length) {
  2289. #else
  2290.     if(ns != 0) {
  2291. #endif
  2292. #ifdef DEBUG
  2293.     if (pfs_debug) {
  2294.     fprintf(stderr,"\nsent only %d/%d: ",ns, pkt->length);
  2295.         perror("");
  2296.     }
  2297. #endif
  2298.     close(lp);
  2299.     perrno = DIRSEND_NOT_ALL_SENT;
  2300.     ptlfree(first);
  2301.     ptlfree(pkt);
  2302.     /* return(NULL); */
  2303.     dirsendReturn = NULL;
  2304.     dirsendDone = DSRET_SEND_ERROR;
  2305.     }
  2306. #ifdef DEBUG
  2307.     if (pfs_debug > 2) fprintf(stderr,"Sent.\n");
  2308. #endif
  2309.     keepWaitingDirsend();
  2310. }
  2311.  
  2312. /*    -    -    -    -    -    -    -    -    */
  2313. /*
  2314.  * This used to be a label to goto to set the appropriate timeout value
  2315.  * and blocked in select(). Now we set selwait and the SELECTARGs to the
  2316.  * appropriate values, and in X register a new timeout, then return to
  2317.  * allow event processing.
  2318.  */
  2319. static void
  2320. keepWaitingDirsend()
  2321. {
  2322.     /* We come back to this point (by a goto) if the packet */
  2323.     /* received is only part of the response, or if the     */
  2324.     /* response came from the wrong host            */
  2325.  
  2326. #ifdef DEBUG
  2327.     if (pfs_debug > 2) fprintf(stderr,"Waiting for reply...");
  2328. #endif
  2329.  
  2330. #ifndef CUTCP
  2331.     FD_ZERO(&readfds);
  2332.     FD_SET(lp, &readfds);
  2333. #endif
  2334.  
  2335.     if(ackpend) selwait = &ackwait;
  2336.     else if(gaps) selwait = &gapwait;
  2337.     else selwait = &timeout;
  2338. }
  2339.  
  2340. /*    -    -    -    -    -    -    -    -    */
  2341. /*
  2342.  * This routine is called when a timeout occurs. It includes the code that
  2343.  * was formerly used when select() returned 0 (indicating a timeout).
  2344.  */
  2345. /*ARGSUSED*/
  2346. static void
  2347. timeoutProc(client_data,id)
  2348. XtPointer client_data;
  2349. XtIntervalId *id;
  2350. {
  2351.     if (gaps || ackpend) { /* Send acknowledgment */
  2352.     /* Acks are piggybacked on retries - If we have received */
  2353.     /* an ack from the server, then the packet sent is only  */
  2354.     /* an ack and the rest of the message will be empty      */
  2355. #ifdef DEBUG
  2356.     if (pfs_debug > 2) {
  2357.             fprintf(stderr,"Acknowledging (%s).\n",
  2358.             (ackpend ? "requested" : "gaps"));
  2359.     }    
  2360. #endif
  2361.     retryDirsend();
  2362.     return;
  2363.     }
  2364.  
  2365.     if (retries-- > 0) {
  2366.     timeout.tv_sec = CLIENT_DIRSRV_BACKOFF(timeout.tv_sec);
  2367. #ifdef DEBUG
  2368.     if (pfs_debug > 2) {
  2369.             fprintf(stderr,"Timed out.  Setting timeout to %d seconds.\n",
  2370.             timeout.tv_sec);
  2371.     }
  2372. #endif
  2373.     retryDirsend();
  2374.     return;
  2375.     }
  2376.  
  2377. #ifdef DEBUG
  2378.     if (pfs_debug) {
  2379.     fprintf(stderr, "select failed(timeoutProc): readfds=%x ",
  2380.         readfds);
  2381.     perror("");
  2382.     }
  2383. #endif
  2384. #ifndef CUTCP
  2385.     close(lp);
  2386. #endif
  2387.     perrno = DIRSEND_SELECT_FAILED;
  2388.     ptlfree(first);
  2389.     ptlfree(pkt);
  2390.     /* return(NULL); */
  2391.     dirsendReturn = NULL;
  2392.     dirsendDone = DSRET_TIMEOUT;
  2393. }
  2394.  
  2395. /*    -    -    -    -    -    -    -    -    */
  2396. /*
  2397.  * This function is called whenever there's something to read on the
  2398.  * connection. It includes the code that was run when select() returned
  2399.  * greater than 0 (indicating read ready).
  2400.  */
  2401. /*ARGSUSED*/
  2402. static void
  2403. readProc(client_data,source,id)
  2404. XtPointer client_data;
  2405. int *source;
  2406. XtInputId *id;
  2407. {
  2408. #ifdef CUTCP
  2409.     int lretry = 3;
  2410. #endif
  2411.  
  2412.     from_sz = sizeof(from);
  2413.     next->start = next->dat;
  2414.  
  2415. #ifndef CUTCP
  2416.     if ((nr = recvfrom(lp, next->start, sizeof(next->dat), 0, (struct sockaddr *)&from, &from_sz)) < 0) {
  2417. #else
  2418.     nr = neturead(next->start);
  2419.     if (nr < 1) {
  2420. #endif
  2421. #ifdef DEBUG
  2422.         if (pfs_debug) perror("recvfrom");
  2423. #endif
  2424. #ifndef CUTCP
  2425.     close(lp);
  2426. #endif
  2427.     perrno = DIRSEND_BAD_RECV;
  2428.     ptlfree(first);
  2429.     ptlfree(pkt);
  2430.     /* return(NULL) */
  2431.     dirsendReturn = NULL;
  2432.     dirsendDone = DSRET_RECV_ERROR;
  2433.         return;
  2434.     }
  2435.  
  2436.     next->length = nr;
  2437.     next->start[next->length] = 0;
  2438.  
  2439. #ifdef DEBUG
  2440.     if (pfs_debug > 2)
  2441.         fprintf(stderr,"Received packet from %s\n",
  2442.         inet_ntoa(SUN_GNU_FIX *(struct in_addr *)&from.sin_addr));
  2443. #endif
  2444.  
  2445.  
  2446.     /* For the current format, if the first byte is less than             */
  2447.     /* 20, then the first two bits are a version number and the next six  */
  2448.     /* are the header length (including the first byte).                  */
  2449.     if((hdr_len = (unsigned char) *(next->start)) < 20) {
  2450.     ctlptr = next->start + 1;
  2451.     next->seq = 0;
  2452.     if(hdr_len >= 3) {     /* Connection ID */
  2453.         bcopy(ctlptr,&stmp,2);
  2454.         if(stmp) pkt_cid = ntohs(stmp);
  2455.         ctlptr += 2;
  2456.     }
  2457.     if(pkt_cid && this_conn_id && (pkt_cid != ntohs(this_conn_id))) {
  2458.         /* The packet is not for us */
  2459.         /* goto keep_waiting; */
  2460.         keepWaitingDirsend();
  2461.         return;
  2462.     }
  2463.     if(hdr_len >= 5) {    /* Packet number */
  2464.         bcopy(ctlptr,&stmp,2);
  2465.         next->seq = ntohs(stmp);
  2466.         ctlptr += 2;
  2467.     }
  2468.     else { /* No packet number specified, so this is the only one */
  2469.         next->seq = 1;
  2470.         nd_pkts = 1;
  2471.     }
  2472.     if(hdr_len >= 7) {        /* Total number of packets */
  2473.         bcopy(ctlptr,&stmp,2);  /* 0 means don't know      */
  2474.         if(stmp) nd_pkts = ntohs(stmp);
  2475.         ctlptr += 2;
  2476.     }
  2477.     if(hdr_len >= 9) {    /* Receievd through */
  2478.         bcopy(ctlptr,&stmp,2);  /* 1 means received request */
  2479. #ifndef USE_V3_PROT
  2480.         if((stmp) && (ntohs(stmp) == 1)) {
  2481.         /* Future retries will be acks only */
  2482.         pkt->length = 9;
  2483.         bcopy(&zero,pkt->start+3,2);
  2484. #ifdef DEBUG
  2485.         if(pfs_debug > 2) 
  2486.             fprintf(stderr,"Server acked request - retries will be acks only\n");
  2487. #endif
  2488.         }
  2489. #endif
  2490.         ctlptr += 2;
  2491.     }
  2492.     if(hdr_len >= 11) {    /* Backoff */
  2493.         bcopy(ctlptr,&stmp,2);
  2494.         if(stmp) {
  2495.         backoff = ntohs(stmp);
  2496. #ifdef DEBUG
  2497.         if(pfs_debug > 2) 
  2498.             fprintf(stderr,"Backing off to %d seconds\n", backoff);
  2499. #endif
  2500.         timeout.tv_sec = backoff;
  2501.         if ((backoff > 60) && (first == next) && (no_pkts == 0)) {
  2502.             /* Probably a long queue on the server - don't give up */
  2503.             retries = client_dirsrv_retry;
  2504.         }
  2505.         }
  2506.         ctlptr += 2;
  2507.     }
  2508.     if(hdr_len >= 12) {    /* Flags (1st byte) */
  2509.         bcopy(ctlptr,&rdflag11,1);
  2510.         if(rdflag11 & 0x80) {
  2511. #ifdef DEBUG
  2512.         if(pfs_debug > 2) 
  2513.             fprintf(stderr,"Ack requested\n");
  2514. #endif
  2515.         ackpend++;
  2516.         }
  2517.         if(rdflag11 & 0x40) {
  2518. #ifdef DEBUG
  2519.         if(pfs_debug > 2) 
  2520.             fprintf(stderr,"Sequenced control packet\n");
  2521. #endif
  2522.         next->length = -1;
  2523.         scpflag++;
  2524.         }
  2525.         ctlptr += 1;
  2526.     }
  2527.     if(hdr_len >= 13) {    /* Flags (2nd byte) */
  2528.         /* Reserved for future use */
  2529.         bcopy(ctlptr,&rdflag12,1);
  2530.         ctlptr += 1;
  2531.     }
  2532.     if(next->seq == 0) {
  2533.         /* goto keep_waiting; */
  2534.         keepWaitingDirsend();
  2535.         return;
  2536.     }
  2537.     if(next->length >= 0) next->length -= hdr_len;
  2538.     next->start += hdr_len;
  2539.     goto done_old;
  2540.     }
  2541.  
  2542.     pkt_cid = 0;
  2543.  
  2544.     /* if intermediate format (between old and new), then process */
  2545.     /* and go to done_old                                         */
  2546.     ctlptr = next->start + max(0,next->length-20);
  2547.     while(*ctlptr) ctlptr++;
  2548.     /* Control fields start after the terminating null */
  2549.     ctlptr++;
  2550.     /* Until old version are gone, must be 4 extra bytes minimum */
  2551.     /* When no version 3 servers, can remove the -4              */
  2552.     if(ctlptr < (next->start + next->length - 4)) {
  2553.     /* Connection ID */
  2554.     bcopy(ctlptr,&stmp,2);
  2555.     if(stmp) pkt_cid = ntohs(stmp);
  2556.     ctlptr += 2;
  2557.     if(pkt_cid && this_conn_id && (pkt_cid != ntohs(this_conn_id))) {
  2558.         /* The packet is not for us */
  2559.         /* goto keep_waiting; */
  2560.         keepWaitingDirsend();
  2561.         return;
  2562.     }
  2563.     /* Packet number */
  2564.     if(ctlptr < (next->start + next->length)) {
  2565.         bcopy(ctlptr,&stmp,2);
  2566.         next->seq = ntohs(stmp);
  2567.         ctlptr += 2;
  2568.     }
  2569.     /* Total number of packets */
  2570.     if(ctlptr < (next->start + next->length)) {
  2571.         bcopy(ctlptr,&stmp,2);
  2572.         if(stmp) nd_pkts = ntohs(stmp);
  2573.         ctlptr += 2;
  2574.     }
  2575.     /* Receievd through */
  2576.     if(ctlptr < (next->start + next->length)) {
  2577.         /* Not supported by clients */
  2578.         ctlptr += 2;
  2579.     }
  2580.     /* Backoff */
  2581.     if(ctlptr < (next->start + next->length)) {
  2582.         bcopy(ctlptr,&stmp,2);
  2583.         backoff = ntohs(stmp);
  2584. #ifdef DEBUG
  2585.         if(pfs_debug > 2) 
  2586.         fprintf(stderr,"Backing off to %d seconds\n", backoff);
  2587. #endif
  2588.         if(backoff) timeout.tv_sec = backoff;
  2589.         ctlptr += 2;
  2590.     }
  2591.     if(next->seq == 0) {
  2592.         /* goto keep_waiting; */
  2593.         keepWaitingDirsend();
  2594.         return;
  2595.     }
  2596.     goto done_old;
  2597.  
  2598.     }
  2599.  
  2600.     /* Notes that we have to start searching 11 bytes before the    */
  2601.     /* expected start of the MULTI-PACKET line because the message  */
  2602.     /* might include up to 10 bytes of data after the trailing null */
  2603.     /* The order of those bytes is two bytes each for Connection ID */
  2604.     /* Packet-no, of, Received-through, Backoff                     */
  2605.     seqtxt = nlsindex(next->start + max(0,next->length - 40),"MULTI-PACKET"); 
  2606.     if(seqtxt) seqtxt+= 13;
  2607.  
  2608.     if((nd_pkts == 0) && (no_pkts == 0) && (seqtxt == NULL)) goto all_done;
  2609.  
  2610.     tmp = sscanf(seqtxt,"%d OF %d", &(next->seq), &nd_pkts);
  2611. #ifdef DEBUG    
  2612.     if (pfs_debug && (tmp == 0)) 
  2613.     fprintf(stderr,"Cant read packet sequence number: %s", seqtxt);    
  2614. #endif
  2615.  done_old:
  2616. #ifdef DEBUG
  2617.     if(pfs_debug > 2) fprintf(stderr,"Packet %d of %d\n",next->seq,nd_pkts);
  2618. #endif
  2619.     if ((first == next) && (no_pkts == 0)) {
  2620.     if(first->seq == 1) {
  2621.         comp_thru = first;
  2622.         /* If only one packet, then return it */
  2623.         if(nd_pkts == 1) goto all_done;
  2624.     }
  2625.     else gaps++;
  2626.     no_pkts = 1;
  2627.     next = ptalloc();
  2628.     /* goto keep_waiting; */
  2629.     keepWaitingDirsend();
  2630.     return;
  2631.     }
  2632.     
  2633.     if(comp_thru && (next->seq <= comp_thru->seq))
  2634.     ptfree(next);
  2635.     else if (next->seq < first->seq) {
  2636.     vtmp = first;
  2637.     first = next;
  2638.     first->next = vtmp;
  2639.     first->previous = NULL;
  2640.     vtmp->previous = first;
  2641.     if(first->seq == 1) comp_thru = first;
  2642.     no_pkts++;
  2643.     }
  2644.     else {
  2645.     vtmp = (comp_thru ? comp_thru : first);
  2646.     while (vtmp->seq < next->seq) {
  2647.         if(vtmp->next == NULL) {
  2648.         vtmp->next = next;
  2649.         next->previous = vtmp;
  2650.         next->next = NULL;
  2651.         no_pkts++;
  2652.         goto ins_done;
  2653.         }
  2654.         vtmp = vtmp->next;
  2655.     }
  2656.     if(vtmp->seq == next->seq)
  2657.         ptfree(next);
  2658.     else {
  2659.         vtmp->previous->next = next;
  2660.         next->previous = vtmp->previous;
  2661.         next->next = vtmp;
  2662.         vtmp->previous = next;
  2663.         no_pkts++;
  2664.     }
  2665.     }   
  2666.  
  2667. ins_done:
  2668.     
  2669.     while(comp_thru && comp_thru->next && 
  2670.       (comp_thru->next->seq == (comp_thru->seq + 1))) {
  2671.     comp_thru = comp_thru->next;
  2672. #ifndef USE_V3_PROT
  2673.     recvd_thru = htons(comp_thru->seq);
  2674.     bcopy(&recvd_thru,pkt->start+7,2); /* Let server know we got it */
  2675. #endif
  2676.     /* We've made progress, so reset retry count */
  2677.     retries = client_dirsrv_retry;
  2678.     /* Also, next retry will be only an acknowledgement */
  2679.     /* but for now, we can't fill in the ack field      */
  2680. #ifdef DEBUG
  2681.     if(pfs_debug > 2) 
  2682.         fprintf(stderr,"Packets now received through %d\n",comp_thru->seq);
  2683. #endif
  2684.     }
  2685.  
  2686.     /* See if there are any gaps */
  2687.     if(!comp_thru || comp_thru->next) gaps++;
  2688.     else gaps = 0;
  2689.  
  2690.     if ((nd_pkts == 0) || (no_pkts < nd_pkts)) {
  2691.     next = ptalloc();
  2692.     /* goto keep_waiting; */
  2693.     keepWaitingDirsend();
  2694.     return;
  2695.     }
  2696.  
  2697.  all_done:
  2698.     if(ackpend) { /* Send acknowledgement if requested */
  2699. #ifdef DEBUG
  2700.     if (pfs_debug > 2) {
  2701.         if (to.sin_family == AF_INET)
  2702.         fprintf(stderr,"Acknowledging final packet to %s(%d)\n",
  2703.             to_hostname, ntohs(this_conn_id));
  2704.             else
  2705.                 fprintf(stderr,"Acknowledging final packet\n");
  2706.         (void) fflush(stderr);
  2707.     }
  2708. #endif
  2709. #ifndef CUTCP
  2710.     ns = sendto(lp,(char *)(pkt->start), pkt->length, 0, (struct sockaddr *)&to, S_AD_SZ);
  2711. #else
  2712.     while(--lretry) {
  2713.         ns = netusend(&to.sin_addr, ntohs(to.sin_port), ntohs(us.sin_port),(char *) pkt->start, pkt->length);
  2714.         if(!ns)
  2715.             break;
  2716.         Stask();
  2717.         Stask();
  2718.     }
  2719. #endif
  2720.  
  2721. #ifndef CUTCP
  2722.     if(ns != pkt->length) {
  2723. #else
  2724.     if(ns != 0) {
  2725. #endif
  2726.  
  2727. #ifdef DEBUG
  2728.         if (pfs_debug) {
  2729.         fprintf(stderr,"\nsent only %d/%d: ",ns, pkt->length);
  2730.         perror("");
  2731.         }
  2732. #endif
  2733.     }
  2734.  
  2735.     }
  2736. #ifndef CUTCP
  2737.     close(lp);
  2738. #endif
  2739.     ptlfree(pkt);
  2740.  
  2741.     /* Get rid of any sequenced control packets */
  2742.     if(scpflag) {
  2743.     while(first && (first->length < 0)) {
  2744.         vtmp = first;
  2745.         first = first->next;
  2746.         if(first) first->previous = NULL;
  2747.         ptfree(vtmp);
  2748.     }
  2749.     vtmp = first;
  2750.     while(vtmp && vtmp->next) {
  2751.         if(vtmp->next->length < 0) {
  2752.         if(vtmp->next->next) {
  2753.             vtmp->next = vtmp->next->next;
  2754.             ptfree(vtmp->next->previous);
  2755.             vtmp->next->previous = vtmp;
  2756.         }
  2757.         else {
  2758.             ptfree(vtmp->next);
  2759.             vtmp->next = NULL;
  2760.         }
  2761.         }
  2762.         vtmp = vtmp->next;
  2763.     }
  2764.     }
  2765.  
  2766.     /* return(first); */
  2767.     dirsendReturn = first;
  2768.     dirsendDone = DSRET_DONE;
  2769.  
  2770. }
  2771.  
  2772. static void
  2773. processEvent()
  2774. {
  2775. #ifdef CUTCP
  2776.     unsigned long now;
  2777. #endif
  2778.     /* select - either recv is ready, or timeout */
  2779.     /* see if timeout or error or wrong descriptor */
  2780. #ifndef CUTCP
  2781.     tmp = select(lp + 1, &readfds, (SELECTARG *)0, (SELECTARG *)0, selwait);
  2782.     if (tmp == 0) {
  2783.     timeoutProc(NULL,&timerId);
  2784.     } else if ((tmp < 0) || !FD_ISSET(lp,&readfds)) {
  2785. #ifdef DEBUG
  2786.     if (pfs_debug) {
  2787.         fprintf(stderr, "select failed(processEvent): readfds=%x ",
  2788.             readfds);
  2789.         perror("");
  2790.     }
  2791. #endif
  2792.     close(lp);
  2793. #else /* CUTCP's flood. */
  2794.     /* while not timeout in selwait loop, stask looking for uevents */
  2795.     now = time(NULL) + selwait->tv_sec;
  2796. #ifdef    DEBUG
  2797.      if(pfs_debug) {
  2798.         fprintf(stderr,"Waiting %d seconds\n",selwait->tv_sec);
  2799.     }
  2800.  
  2801. #endif
  2802.     while(now > time(NULL)) {
  2803.         int    i, cl, dat;
  2804.  
  2805.         Stask();
  2806.         if (0 < (i = Sgetevent(USERCLASS, &cl, &dat))) {
  2807.             /* got a user class event */
  2808.             if(cl == USERCLASS &&
  2809.                 i == UDPDATA) {
  2810.                     readProc(NULL,&lp,&inputId);
  2811.                     return;
  2812.             }
  2813.         }
  2814.         if(kbhit()) {
  2815.             int c = getch();
  2816.             if(c == 27 || c == 3)
  2817.                 break;
  2818.             fprintf(stderr,"Press <ESCAPE> to abort\n");
  2819.         }
  2820.     }
  2821.     if(now <= time(NULL)) {    /* timeout */
  2822.         timeoutProc(NULL,&timerId);
  2823.          return;
  2824.     }
  2825.  
  2826. #endif /* CUTCP */
  2827.     perrno = DIRSEND_SELECT_FAILED;
  2828.     ptlfree(first);
  2829.     ptlfree(pkt);
  2830.     /* return(NULL); */
  2831.     dirsendReturn = NULL;
  2832.     dirsendDone = DSRET_SELECT_ERROR;
  2833. #ifndef CUTCP
  2834.     } else {
  2835.     readProc(NULL,&lp,&inputId);
  2836.     }
  2837. #endif /* CUTCP */
  2838. }
  2839.  
  2840. void
  2841. abortDirsend()
  2842. {
  2843.     if (!dirsendDone) {
  2844. #ifndef CUTCP
  2845.     close(lp);
  2846. #endif
  2847.     ptlfree(first);
  2848.     ptlfree(pkt);
  2849.     dirsendReturn = NULL;
  2850.     dirsendDone = DSRET_ABORTED;
  2851.     }
  2852.     return;
  2853. }
  2854. $EOD
  2855. $!
  2856. $CREATE [.archie]get_pauth.c
  2857. $DECK
  2858. /*
  2859.  * Copyright (c) 1989, 1990 by the University of Washington
  2860.  *
  2861.  * For copying and distribution information, please see the file
  2862.  * <copyright.h>.
  2863.  */
  2864.  
  2865. #include <copyright.h>
  2866. #include <stdio.h>
  2867. #ifndef VMS
  2868. # include <sys/types.h> /* this may/will define FD_SET etc */
  2869. # include <pmachine.h>
  2870. #endif
  2871.  
  2872. #ifdef NEED_STRING_H
  2873. # include <string.h>
  2874. #else
  2875. # include <strings.h>
  2876. #endif
  2877.  
  2878. #ifndef VMS
  2879. # if defined(MSDOS) && !defined(OS2)
  2880. #  ifndef CUTCP
  2881. #   include <rwconf.h>
  2882. #  endif
  2883. # else
  2884. #  include <pwd.h>
  2885. # endif
  2886. #else
  2887. # include <jpidef.h>
  2888. # include <vms.h>
  2889. #endif
  2890.  
  2891. #include <pcompat.h>
  2892. #include <pauthent.h>
  2893.  
  2894. PAUTH
  2895. get_pauth(type)
  2896.     int        type;
  2897.     {
  2898.     static PAUTH_ST   no_auth_st;
  2899.     static PAUTH          no_auth = NULL;
  2900. #if !defined(VMS) && !defined(MSDOS) || defined(OS2)
  2901.     struct passwd *whoiampw;
  2902. #else
  2903.     char username[13];
  2904.     unsigned short usernamelen;
  2905.     struct {
  2906.         unsigned short buflen;
  2907.         unsigned short itmcod;
  2908.         char *bufadr;
  2909.         unsigned short *retlenadr;
  2910.         unsigned long null;
  2911.     } jpi_itemlist;
  2912. #endif
  2913.  
  2914.     if(no_auth == NULL) {
  2915.         no_auth = &no_auth_st;
  2916.         strcpy(no_auth->auth_type,"UNAUTHENTICATED");
  2917.  
  2918.         /* find out who we are */
  2919. #ifndef VMS
  2920. #if defined(MSDOS) && !defined(OS2)
  2921. #ifndef CUTCP
  2922.         if (!getconf("general", "user", no_auth->authenticator, 250)
  2923.         || (strlen (no_auth->authenticator) == 0))
  2924. #endif
  2925.           strcpy(no_auth->authenticator,"nobody");
  2926. #else /* not MSDOS */
  2927.         DISABLE_PFS(whoiampw = getpwuid(getuid()));
  2928.         if (whoiampw == 0) strcpy(no_auth->authenticator,"nobody");
  2929.         else strcpy(no_auth->authenticator, whoiampw->pw_name);
  2930. #endif /* not MSDOS */
  2931. #else
  2932.         jpi_itemlist.buflen = sizeof(username);
  2933.         jpi_itemlist.itmcod = JPI$_USERNAME;
  2934.         jpi_itemlist.bufadr = &username;
  2935.         jpi_itemlist.retlenadr = &usernamelen;
  2936.         jpi_itemlist.null = 0;
  2937.         if (SYS$GETJPI(0, 0, 0, &jpi_itemlist, 0, 0, 0) & 0x1)
  2938.         {
  2939.         username[usernamelen] = 0;
  2940.         strcpy(no_auth->authenticator, username);
  2941.         } else
  2942.         strcpy(no_auth->authenticator, "nobody");
  2943. #endif
  2944.     }
  2945.     return(no_auth);
  2946.     }
  2947. $EOD
  2948. $!
  2949. $CREATE [.archie]get_vdir.c
  2950. $DECK
  2951. /*
  2952.  * Copyright (c) 1989, 1990, 1991 by the University of Washington
  2953.  *
  2954.  * For copying and distribution information, please see the file
  2955.  * <copyright.h>.
  2956.  */
  2957.  
  2958. #include <copyright.h>
  2959. #include <stdio.h>
  2960.  
  2961. #include <pfs.h>
  2962. #include <pprot.h>
  2963. #include <perrno.h>
  2964. #include <pcompat.h>
  2965. #include <pauthent.h>
  2966. #include <pmachine.h>
  2967.  
  2968. #ifdef NEED_STRING_H
  2969. # include <string.h>
  2970. #else
  2971. # include <strings.h>
  2972. #endif
  2973.  
  2974. #ifdef DEBUG
  2975. extern int    pfs_debug;
  2976. #endif
  2977.  
  2978. extern int    pwarn;
  2979. extern char    p_warn_string[];
  2980. extern int    perrno;
  2981. extern char    p_err_string[];
  2982.  
  2983. /*
  2984.  * get_vdir - Get contents of a directory given its location
  2985.  *
  2986.  *          GET_VDIR takes a directory location, a list of desired
  2987.  *          components, a pointer to a directory structure to be 
  2988.  *          filled in, and flags.  It then queries the appropriate 
  2989.  *          directory server and retrieves the desired information.
  2990.  *
  2991.  *      ARGS:   dhost       - Host on which directory resides
  2992.  *              dfile       - Directory on that host
  2993.  *              components  - The names from the directory we want
  2994.  *        dir        - Structure to be filled in
  2995.  *            flags       - Options.  See FLAGS
  2996.  *        filters     - filters to be applied to result 
  2997.  *              acomp       - Pointer to remaining components
  2998.  *
  2999.  *     FLAGS:    GVD_UNION   - Do not expand union links
  3000.  *        GVD_EXPAND  - Expand union links locally
  3001.  *        GVD_REMEXP  - Request remote expansion (& local if refused)
  3002.  *        GVD_LREMEXP - Request remote expansion of local union links
  3003.  *        GVD_VERIFY  - Only verify that args are for a directory
  3004.  *              GVD_ATTRIB  - Request attributes from directory server
  3005.  *              GVD_NOSORT  - Do not sort links when adding to directory
  3006.  *
  3007.  *   RETURNS:   PSUCCESS (0) or error code
  3008.  *        On some codes addition information in p_err_string
  3009.  *
  3010.  *     NOTES:   If acomp is non-null the string it points to might be modified
  3011.  *
  3012.  *              If the directory passed as an argument already has
  3013.  *        links or union links, then those lists will be freed
  3014.  *              before the new contents are filled in.
  3015.  *
  3016.  *              If a filter is passed to the procedure, and application of
  3017.  *              the filter results in additional union link, then those links
  3018.  *              will (or will not) be expanded as specified in the FLAGS field.
  3019.  *
  3020.  *              If the list of components in NULL, or the null string, then
  3021.  *              get_vdir will return all links in the requested directory.
  3022.  *
  3023.  *      BUGS:   Doesn't process union links yet
  3024.  *              Doesn't process errors returned from server
  3025.  *        Doesn't expand union links if requested to
  3026.  */
  3027. int
  3028. get_vdir(dhost,dfile,components,dir,flags,filters,acomp)
  3029.     char    *dhost;        /* Host on which directory resides           */
  3030.     char    *dfile;        /* Name of file on that host                 */
  3031.     char    *components;    /* Component name (wildcards allowed)        */
  3032.     PVDIR    dir;        /* Structure to be filled in             */
  3033.     long    flags;        /* Flags                         */
  3034.     VLINK    filters;    /* Filters to be applied to result           */
  3035.     char    *acomp;        /* Components left to be resolved            */
  3036.     {
  3037.         PTEXT    request;    /* Text of request to dir server             */
  3038.     PTEXT    resp;            /* Response from dir server                 */
  3039.  
  3040.     char    ulcomp[MAX_VPATH];/* Work space for new current component    */
  3041.     char    *comp = components;
  3042.  
  3043.     VLINK    cur_link = NULL;/* Current link being filled in              */
  3044.     VLINK     exp = NULL;     /* The current ulink being expanded         */
  3045.     VLINK    pul = NULL;     /* Prev union link (insert new one after it) */
  3046.     VLINK    l;        /* Temp link pointer                  */
  3047.     int    mcomp;        /* Flag - check multiple components          */
  3048.     int    unresp;        /* Flag - received unresolved response       */
  3049.     int    getattrib = 0;  /* Get attributes from server                */
  3050.     int    vl_insert_flag; /* Flags to vl_insert                        */
  3051.  
  3052.     int    fwdcnt = MAX_FWD_DEPTH;
  3053.  
  3054.     int    no_links = 0;   /* Count of number of links found         */
  3055.  
  3056.     char    options[40];    /* LIST option                               */
  3057.     char    *opt;           /* After leading +                           */
  3058.  
  3059.     PAUTH    authinfo;
  3060.  
  3061.     /* Treat null string like NULL (return entire directory) */
  3062.     if(!components || !*components) comp = NULL;
  3063.  
  3064.     if(acomp && !filters) mcomp = 1;
  3065.     else mcomp = 0;
  3066.  
  3067.     if(flags&GVD_ATTRIB) {
  3068.         getattrib++;
  3069.         flags &= (~GVD_ATTRIB);
  3070.     }
  3071.  
  3072.     if(flags&GVD_NOSORT) vl_insert_flag = VLI_NOSORT;
  3073.     else vl_insert_flag = VLI_ALLOW_CONF;
  3074.     flags &= (~GVD_NOSORT);
  3075.  
  3076.     if(filters) comp = NULL;
  3077.  
  3078.     perrno = 0;
  3079.  
  3080.     authinfo = get_pauth(PFSA_UNAUTHENTICATED);
  3081.  
  3082.     *options = '\0';
  3083.  
  3084.     if(getattrib) {
  3085.         strcat(options,"+ATTRIBUTES");
  3086.         flags &= (~GVD_ATTRIB);
  3087.     }
  3088.  
  3089.     if(!filters) { /* Can't do remote expansion if filters to be applied */
  3090.         if(flags == GVD_REMEXP) strcat(options,"+EXPAND");
  3091.         if(flags == GVD_LREMEXP) strcat(options,"+LEXPAND");
  3092.     }
  3093.  
  3094.     /* If all we are doing is verifying that dfile is a directory */
  3095.     /* then we do not want a big response from the directory      */
  3096.     /* server.  A NOT-FOUND is sufficient.                  */
  3097.     if(flags == GVD_VERIFY)
  3098. #ifdef NEWVERIFYOPT
  3099.         strcat(options,"+VERIFY");
  3100. #else
  3101.     comp = "%#$PRobably_nOn_existaNT$#%";
  3102. #endif
  3103.  
  3104.     if(*options) opt = options+1;
  3105.     else opt = "''";
  3106.  
  3107.     startover:
  3108.     request = ptalloc();
  3109.  
  3110.     sprintf(request->start,
  3111.         "VERSION %d %s\nAUTHENTICATOR %s %s\nDIRECTORY ASCII %s\nLIST %s COMPONENTS %s%s%s\n",
  3112.         VFPROT_VNO, PFS_SW_ID, authinfo->auth_type,
  3113.         authinfo->authenticator, dfile, opt,
  3114.         (comp ? comp : ""), (mcomp ? "/" : ""),
  3115.         (mcomp ? acomp : ""));
  3116.  
  3117.     request->length = strlen(request->start);
  3118.  
  3119. #ifdef DEBUG
  3120.     if(pfs_debug > 2)
  3121.         fprintf(stderr,"Sending message to dirsrv:\n%s",request->start);
  3122. #endif
  3123.  
  3124. #if defined(MSDOS)
  3125.     resp = dirsend(request,dhost,0L);
  3126. #else
  3127.     resp = dirsend(request,dhost,0);
  3128. #endif
  3129.  
  3130. #ifdef DEBUG
  3131.     if(pfs_debug && (resp == NULL)) {
  3132.         fprintf(stderr,"Dirsend failed: %d\n",perrno);
  3133.     }
  3134. #endif
  3135.  
  3136.     /* If we don't get a response, then if the requested       */
  3137.     /* directory, return error, if a ulink, mark it unexpanded */
  3138.     if(resp == NULL) {
  3139.         if(exp) exp->expanded = FAILED;
  3140.         else return(perrno);
  3141.     }
  3142.  
  3143.     unresp = 0;
  3144.  
  3145.     /* Here we must parse reponse and put in directory */
  3146.     /* While looking at each packet            */
  3147.     while(resp) {
  3148.         PTEXT        vtmp;
  3149.         char        *line;
  3150.  
  3151.         vtmp = resp;
  3152. #ifdef DEBUG
  3153.         if(pfs_debug > 3) fprintf(stderr,"%s\n",resp->start);
  3154. #endif
  3155.         /* Look at each line in packet */
  3156.         for(line = resp->start;line != NULL;line = nxtline(line)) {
  3157.         switch (*line) {
  3158.             
  3159.             /* Temporary variables to hold link info */
  3160.             char    l_linktype;
  3161.             char     l_name[MAX_DIR_LINESIZE];
  3162.             char    l_type[MAX_DIR_LINESIZE];
  3163.             char     l_htype[MAX_DIR_LINESIZE];
  3164.             char     l_host[MAX_DIR_LINESIZE];
  3165.             char     l_ntype[MAX_DIR_LINESIZE];
  3166.             char     l_fname[MAX_DIR_LINESIZE];
  3167.             int        l_version;
  3168.             char     t_unresolved[MAX_DIR_LINESIZE];
  3169.             int        l_magic;
  3170.             int        tmp;
  3171.  
  3172.         case 'L': /* LINK or LINK-INFO */
  3173.             if(strncmp(line,"LINK-INFO",9) == 0) {
  3174.             PATTRIB        at;
  3175.             PATTRIB        last_at;
  3176.             at = parse_attribute(line);
  3177.             if(!at) break;
  3178.  
  3179.             /* Cant have link info without a link */
  3180.             if(!cur_link) {
  3181.                 perrno = DIRSRV_BAD_FORMAT;
  3182.                 atfree(at);
  3183.                 break;
  3184.             }
  3185.             
  3186.             if(cur_link->lattrib) {
  3187.                 last_at = cur_link->lattrib;
  3188.                 while(last_at->next) last_at = last_at->next;
  3189.                 at->previous = last_at;
  3190.                 last_at->next = at;
  3191.             }
  3192.             else {
  3193.                 cur_link->lattrib = at;
  3194.                 at->previous = NULL;
  3195.             }
  3196.             break;
  3197.             }
  3198.  
  3199.             /* Not LINK-INFO, must be LINK - if not check for error */
  3200.             if(strncmp(line,"LINK",4) != 0) goto scanerr;
  3201.  
  3202.             /* If only verifying, don't want to change dir */
  3203.             if(flags == GVD_VERIFY) {
  3204.             break;
  3205.             }
  3206.             /* If first link and some links in dir, free them */
  3207.             if(!no_links++) {
  3208.             if(dir->links) vllfree(dir->links); dir->links=NULL;
  3209.             if(dir->ulinks) vllfree(dir->ulinks); dir->ulinks=NULL;
  3210.             }
  3211.             
  3212.             cur_link = vlalloc();
  3213.  
  3214.             /* parse and insert file info */
  3215.             tmp = sscanf(line,"LINK %c %s %s %s %s %s %s %d %d", &l_linktype,
  3216.                  l_type, l_name, l_htype, l_host, 
  3217.                  l_ntype, l_fname, &(cur_link->version),
  3218.                  &(cur_link->f_magic_no));
  3219.  
  3220.             if(tmp != 9) {
  3221.             perrno = DIRSRV_BAD_FORMAT;
  3222.             vlfree(cur_link);
  3223.             break;
  3224.             }
  3225.  
  3226.             cur_link->linktype = l_linktype;
  3227.             cur_link->type = stcopyr(l_type,cur_link->type);
  3228.             cur_link->name = stcopyr(unquote(l_name),cur_link->name);
  3229.             cur_link->hosttype = stcopyr(l_htype,cur_link->hosttype);
  3230.             cur_link->host = stcopyr(l_host,cur_link->host);
  3231.             cur_link->nametype = stcopyr(l_ntype,cur_link->nametype);
  3232.             cur_link->filename = stcopyr(l_fname,cur_link->filename);
  3233.  
  3234.             /* Double check to make sure we don't get */
  3235.             /* back unwanted components              */
  3236.             /* OK to keep if special (URP) links      */
  3237.             /* or if mcomp specified                  */
  3238.             if(!mcomp && (cur_link->linktype == 'L') && 
  3239.                (!wcmatch(cur_link->name,comp))) {
  3240.             vlfree(cur_link);
  3241.             break;
  3242.             }
  3243.  
  3244.             /* If other optional info was sent back, it must */
  3245.             /* also be parsed before inserting link     ***  */
  3246.             
  3247.             
  3248.             if(cur_link->linktype == 'L') 
  3249.             vl_insert(cur_link,dir,vl_insert_flag);
  3250.             else {
  3251.             tmp = ul_insert(cur_link,dir,pul);
  3252.  
  3253.             /* If inserted after pul, next one after cur_link */
  3254.             if(pul && (!tmp || (tmp == UL_INSERT_SUPERSEDING)))
  3255.                 pul = cur_link;
  3256.             }
  3257.             
  3258.             break;
  3259.  
  3260.         case 'F': /* FILTER, FAILURE or FORWARDED */
  3261.             /* FORWARDED */
  3262.             if(strncmp(line,"FORWARDED",9) == 0) {
  3263.             if(fwdcnt-- <= 0) {
  3264.                 ptlfree(resp);
  3265.                 perrno = PFS_MAX_FWD_DEPTH;
  3266.                 return(perrno);
  3267.             }
  3268.             /* parse and start over */
  3269.  
  3270.             tmp = sscanf(line,"FORWARDED %s %s %s %s %d %d", 
  3271.                      l_htype,l_host,l_ntype,l_fname,
  3272.                      &l_version, &l_magic);
  3273.  
  3274.             dhost = stcopy(l_host);
  3275.             dfile = stcopy(l_fname);
  3276.  
  3277.             if(tmp < 4) {
  3278.                 perrno = DIRSRV_BAD_FORMAT;
  3279.                 break;
  3280.             }
  3281.  
  3282.             ptlfree(resp);
  3283.             goto startover;
  3284.             }
  3285.             if(strncmp(line,"FILTER",6) != 0) goto scanerr;
  3286.             break;
  3287.  
  3288.  
  3289.         case 'M': /* MULTI-PACKET (processed by dirsend) */
  3290.         case 'P': /* PACKET (processed by dirsend) */
  3291.             break;
  3292.  
  3293.         case 'N': /* NOT-A-DIRECTORY or NONE-FOUND */
  3294.             /* NONE-FOUND, we just have no links to insert */
  3295.             /* It is not an error, but we must clear any   */
  3296.             /* old links in the directory arg              */
  3297.             if(strncmp(line,"NONE-FOUND",10) == 0) {
  3298.             /* If only verifying, don't want to change dir */
  3299.             if(flags == GVD_VERIFY) {
  3300.                 break;
  3301.             }
  3302.  
  3303.             /* If first link and some links in dir, free them */
  3304.             if(!no_links++) {
  3305.                 if(dir->links) vllfree(dir->links);
  3306.                 if(dir->ulinks) vllfree(dir->ulinks);
  3307.                 dir->links = NULL;
  3308.                 dir->ulinks = NULL;
  3309.             }
  3310.             break;
  3311.             }
  3312.             /* If NOT-A-DIRECTORY or anything else, scan error */
  3313.             goto scanerr;
  3314.  
  3315.         case 'U': /* UNRESOLVED */
  3316.             if(strncmp(line,"UNRESOLVED",10) != 0) {
  3317.             goto scanerr;
  3318.             }
  3319.             tmp = sscanf(line,"UNRESOLVED %s", t_unresolved);
  3320.             if(tmp < 1) {
  3321.             perrno = DIRSRV_BAD_FORMAT;
  3322.             break;
  3323.             }
  3324.             /* If multiple components were resolved */
  3325.             if(strlen(t_unresolved) < strlen(acomp)) {
  3326.             strcpy(ulcomp,acomp);
  3327.             /* ulcomp is the components that were resolved */
  3328.             *(ulcomp+strlen(acomp)-strlen(t_unresolved)-1) = '\0';
  3329.             /* Comp gets the last component resolved */
  3330.             comp = (char *) rindex(ulcomp,'/');
  3331.             if(comp) comp++;
  3332.             else comp = ulcomp;
  3333.             /* Let rd_vdir know what remains */
  3334.             strcpy(acomp,t_unresolved);
  3335.             }
  3336.             unresp = 1;
  3337.             break;
  3338.  
  3339.         case 'V': /* VERSION-NOT-SUPPORTED */
  3340.             if(strncmp(line,"VERSION-NOT-SUPPORTED",21) == 0) {
  3341.             perrno = DIRSRV_BAD_VERS;
  3342.             return(perrno);
  3343.             }
  3344.             goto scanerr;
  3345.  
  3346.         scanerr:
  3347.         default:
  3348.             if(*line && (tmp = scan_error(line))) {
  3349.             ptlfree(resp);
  3350.             return(tmp);
  3351.             }
  3352.             break;
  3353.         }
  3354.         }
  3355.  
  3356.         resp = resp->next;
  3357.  
  3358.         ptfree(vtmp);
  3359.     }
  3360.  
  3361.     /* We sent multiple components and weren't told any */
  3362.     /* were unresolved                                  */
  3363.     if(mcomp && !unresp) {
  3364.         /* ulcomp is the components that were resolved */
  3365.         strcpy(ulcomp,acomp);
  3366.         /* Comp gets the last component resolved */
  3367.         comp = (char *) rindex(ulcomp,'/');
  3368.         if(comp) comp++;
  3369.         else comp = ulcomp;
  3370.         /* If we have union links to resolve, only one component remains */
  3371.         mcomp = 0;
  3372.         /* Let rd_vdir know what remains */
  3373.         *acomp = '\0';
  3374.     }
  3375.  
  3376.     /* If only verifying, we already know it is a directory */
  3377.     if(flags == GVD_VERIFY) return(PSUCCESS);
  3378.  
  3379.     /* Don't return if matching was delayed by the need to filter    */
  3380.     /* if FIND specified, and dir->links is non null, then we have   */
  3381.     /* found a match, and should return.                             */
  3382.     if((flags & GVD_FIND) && dir->links && (!filters))
  3383.         return(PSUCCESS);
  3384.  
  3385.     /* If expand specified, and ulinks must be expanded, making sure */
  3386.         /* that the order of the links is maintained properly            */
  3387.  
  3388. expand_ulinks:
  3389.  
  3390.     if((flags != GVD_UNION) && (flags != GVD_VERIFY)) {
  3391.  
  3392.         l = dir->ulinks;
  3393.  
  3394.         /* Find first unexpanded ulink */
  3395.         while(l && l->expanded && (l->linktype == 'U')) l = l->next;
  3396.         
  3397.         /* Only expand if a FILE or DIRECTORY -  Mark as  */
  3398.             /* failed otherwise                               */
  3399.         /* We must still add support for symbolic ulinks */
  3400.         if(l) {
  3401.         if ((strcmp(l->type,"DIRECTORY") == 0) || 
  3402.             (strcmp(l->type,"FILE") == 0)) {
  3403.             l->expanded = TRUE;
  3404.             exp = l;
  3405.             pul = l;
  3406.             dhost = l->host;
  3407.             dfile = l->filename;
  3408.             goto startover; /* was get_contents; */
  3409.         }
  3410.         else l->expanded = FAILED;
  3411.         }
  3412.     }
  3413.  
  3414.     /* Double check to make sure we don't get */
  3415.     /* back unwanted components          */
  3416.     /* OK to keep if special (URP) links      */
  3417.     if(components && *components) {
  3418.         l = dir->links;
  3419.         while(l) {
  3420.         VLINK    ol;
  3421.         if((l->linktype == 'L') && (!wcmatch(l->name,components))) {
  3422.             if(l == dir->links)
  3423.             dir->links = l->next;
  3424.             else l->previous->next = l->next;
  3425.             if(l->next) l->next->previous = l->previous;
  3426.             ol = l;
  3427.             l = l->next;
  3428.             vlfree(ol);
  3429.         }
  3430.         else l = l->next;
  3431.         }
  3432.     }
  3433.  
  3434.     return(PSUCCESS);
  3435.     }
  3436. $EOD
  3437. $!
  3438. $CREATE [.archie]make.com
  3439. $DECK
  3440. $! --- MAKE.COM ---                        !x='f$verify(0)'
  3441. $! Description:
  3442. $!  build the Archie client for VAX/VMS
  3443. $!
  3444. $! Written by Luke Brennan <brennan@coco.cchs.su.oz.au>
  3445. $!
  3446. $! Modifications:
  3447. $!    Date    Programmer    Reason for modification.
  3448. $! 20-Jan-92       ldcb        Initial coding.
  3449. $!
  3450. $!
  3451. $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3452. $ Archie_EXECUTABLE := "archie.exe"
  3453. $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3454. $! add a new call here with the appropriate new Archie server host(s)
  3455. $!
  3456. $ arg == 1
  3457. $ Call AddHost "archie.ans.net"        "(USA [NY])"
  3458. $ Call AddHost "archie.rutgers.edu"    "(USA [NJ])"
  3459. $ Call AddHost "archie.sura.net"    "(USA [MD])"
  3460. $ Call AddHost "archie.unl.edu"        "(USA [NE])"
  3461. $ Call AddHost "archie.mcgill.ca"    "(Canada)"
  3462. $ Call AddHost "archie.funet.fi"    "(Finland/Mainland Europe)"
  3463. $ Call AddHost "archie.au"        "(Australia)"
  3464. $ Call AddHost "archie.doc.ic.ac.uk"    "(Great Britain/Ireland)"
  3465. $ MAXHOSTS = arg - 1
  3466. $!
  3467. $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3468. $! add a new call here with any new source file(s)
  3469. $! (P2 should be "SUPPORT" if intended for supporting an unknown TCPIP)
  3470. $!
  3471. $ arg == 1
  3472. $ Call AddSource "AQUERY"
  3473. $ Call AddSource "ARCHIE"
  3474. $ Call AddSource "ATALLOC"
  3475. $ Call AddSource "DIRSEND"
  3476. $ Call AddSource "GET_PAUTH"
  3477. $ Call AddSource "GET_VDIR"
  3478. $ Call AddSource "PERRMESG"
  3479. $ Call AddSource "PROCQUERY"
  3480. $ Call AddSource "PTALLOC"
  3481. $ Call AddSource "REGEX"
  3482. $ Call AddSource "STCOPY"
  3483. $ Call AddSource "SUPPORT"
  3484. $ Call AddSource "VLALLOC"
  3485. $ Call AddSource "VL_COMP"
  3486. $ Call AddSource "VMS_SUPPORT" "SUPPORT"
  3487. $ MAXSOURCEFILES = arg - 1
  3488. $!
  3489. $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3490. $! add a call here with any supported TCP/IP implementations
  3491. $!  P1 = name of TCP/IP product, P2 = cc/define to set,
  3492. $!  P3 = logical to look for,    P4 = location of link/OPT,
  3493. $!  P5 = MINIMUM VERSION of TCP/IP to support
  3494. $!
  3495. $!  Multinet should be last, as it can 'fake' a UCX if you want it to, so
  3496. $!  UCX would come up as the 'real' net even though Multinet is used.
  3497. $!
  3498. $ arg == 1
  3499. $ Call AddTCPIP "UCX"        "UCX"         "UCX$DEVICE" "[.vms]ucx.opt"
  3500. $ Call AddTCPIP "WOLLONGONG" "WOLLONGONG"  "TWG$TCP"    "[.vms]woll.opt"
  3501. $ Call AddTCPIP "MULTINET"   "MULTINET_30" "MULTINET"   "[.vms]multi.opt" "V3.0"
  3502. $ MAXTCPIPTYPES = arg - 1
  3503. $!
  3504. $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3505. $!
  3506. $ YES = (1.eq.1)
  3507. $ NO  = (1.eq.0)
  3508. $!
  3509. $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3510. $!
  3511. $ GoSub get_command_line_args
  3512. $ GoSub check_for_GNU_cc
  3513. $ GoSub check_which_TCPIP
  3514. $ GoSub ask_nearest_ARCHIE_HOST
  3515. $ GoSub check_for_strings_H
  3516. $ GoSub set_cc_defines
  3517. $ GoSub do_compiles
  3518. $ If (LINKAGE_REQUIRED)
  3519. $ Then GoSub do_link
  3520. $ Else Write Sys$OutPut "ARCHIE is up to date."
  3521. $ EndIF
  3522. $ Exit
  3523. $!
  3524. $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3525. $!
  3526. $get_command_line_args:
  3527. $ cmdline = P1 + P2 + P3 + P4 + P5 + P6 + P7 + P8
  3528. $ If ((f$locate("DEBUG",cmdline) .ne. f$length(cmdline)) -
  3529.  .or. (f$locate("DBG",cmdline)   .ne. f$length(cmdline)))
  3530. $ Then debug := "/DeBug"
  3531. $ Else debug := "/NOdebug"
  3532. $ EndIF
  3533. $ If (f$locate("FORCE",cmdline) .ne. f$length(cmdline))
  3534. $ Then FORCEBUILD = YES
  3535. $ Else FORCEBUILD = NO
  3536. $ EndIF
  3537. $ If (f$locate("LINK",cmdline) .ne. f$length(cmdline))
  3538. $ Then FORCELINK = YES
  3539. $ Else FORCELINK = NO
  3540. $ EndIF
  3541. $ If ((f$locate("?",cmdline) .ne. f$length(cmdline)) -
  3542.  .or. (f$locate("H",cmdline) .ne. f$length(cmdline)))
  3543. $ Then
  3544. $   Write Sys$Output "Usage:"
  3545. $   Write Sys$OutPut "     @MAKE [<debug>|<force>|<link>|<help>]
  3546. $   EXIT
  3547. $ EndIF
  3548. $ RETURN
  3549. $!
  3550. $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3551. $!
  3552. $CHECK_FOR_GNU_CC:
  3553. $ If (f$trnlnm("GNU_CC") .nes. "")
  3554. $ Then
  3555. $   cc := "GCC/Optimize/Include=([])"
  3556. $   gnu_cc = YES
  3557. $ Else
  3558. $   cc := "CC/Optimize=NOinline/Include=([])"
  3559. $   gnu_cc = NO
  3560. $ EndIF
  3561. $!
  3562. $ RETURN
  3563. $!
  3564. $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3565. $! for product P1, cc/define=P2 if logical P3 present on system.
  3566. $! Libs/option = P4 if present. ALL get disregarded if less than version P5
  3567. $!
  3568. $CHECK_WHICH_TCPIP:
  3569. $ tcpip_flag :=
  3570. $ tcpip_libs :=
  3571. $ NO_TCPIP_SUPPORT = YES
  3572. $ i = 1
  3573. $tcp_loop:
  3574. $ If (i .gt. MAXTCPIPTYPES) Then GoTo tcp_check_done
  3575. $ If (f$type(tcpip_P2_'i') .eqs. "") Then GoTo tcp_check_done
  3576. $ If (f$type(tcpip_P3_'i') .nes. "")
  3577. $ Then
  3578. $   tcpip_logical = tcpip_P3_'i'
  3579. $   If (tcpip_logical .nes. "")
  3580. $   Then                    ! logical to look for
  3581. $     If (f$logical(tcpip_logical) .nes. "")
  3582. $     Then
  3583. $       tcpip_flag = tcpip_P2_'i'
  3584. $       tcpip_flag = f$fao(",!AS=1",tcpip_flag)
  3585. $       NO_TCPIP_SUPPORT = NO
  3586. $       If (f$type(tcpip_P4_'i') .nes. "")
  3587. $       Then                    ! link/OPT file location
  3588. $        tcpip_linkOPTs = tcpip_P4_'i'
  3589. $         If (tcpip_linkOPTs .nes. "")
  3590. $         Then
  3591. $           If (f$search(tcpip_linkOPTs) .nes. "")
  3592. $           Then
  3593. $             tcpip_libs = tcpip_P4_'i'
  3594. $             tcpip_libs = f$fao("!AS/Option",tcpip_libs)
  3595. $           EndIF
  3596. $         EndIF
  3597. $       EndIF
  3598. $       If (f$type(tcpip_P5_'i') .nes. "")
  3599. $       Then                    ! minimum version specified
  3600. $         If (tcpip_P5_'i' .nes. "")
  3601. $         Then
  3602. $           GoSub CheckIfVersionOK
  3603. $           If VERSION_TOO_EARLY
  3604. $           Then                ! too early.. use SUPPORT files
  3605. $             tcpip_flag :=
  3606. $             tcpip_libs :=
  3607. $             NO_TCPIP_SUPPORT = YES
  3608. $          tcp_ver = tcpip_P5_'i'
  3609. $             tcp_name = tcpip_P1_'i'
  3610. $             Write Sys$OutPut f$fao( -
  3611.            "Your version of !AS is earlier than !AS.",tcp_name,tcp_ver)
  3612.           Write Sys$OutPut "MAKE will use STD support files instead."
  3613. $           EndIF
  3614. $         EndIF
  3615. $       EndIF
  3616. $     EndIF
  3617. $   EndIF
  3618. $ EndIF
  3619. $ i = i + 1
  3620. $ Goto tcp_loop
  3621. $tcp_check_done:
  3622. $ RETURN
  3623. $!
  3624. $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3625. $!
  3626. $ASK_NEAREST_ARCHIE_HOST:
  3627. $GoSub CLRSCN
  3628. $ Write Sys$OutPut f$fao("!AS!/!/", -
  3629.     "           Enter the number of the ARCHIE HOST nearest you.")
  3630. $!
  3631. $ i = 1
  3632. $_display_loop:
  3633. $ If (i .gt. MAXHOSTS) Then GoTo _display_done
  3634. $  Write Sys$OutPut f$fao("!2SL) !25AS  !AS",i,host_P1_'i',host_P2_'i')
  3635. $  i = i + 1
  3636. $ GoTo _display_loop
  3637. $_display_done:
  3638. $!
  3639. $ Assign/User_Mode/NOlog Sys$Command Sys$InPut
  3640. $_select_loop:                ! get their selection
  3641. $ Read     Sys$Command selection    -
  3642.     /End=_selection_made    -
  3643.     /Prompt="Enter number of your selection: "
  3644. $ If (selection .gt. MAXHOSTS)
  3645. $ Then
  3646. $   Write Sys$OutPut f$fao("!AS !2SL", "error: Options only go to", MAXHOSTS)
  3647. $   GoTo _select_loop
  3648. $ EndIF
  3649. $ ascii_string = f$edit(selection,"COLLAPSE,UPCASE")
  3650. $ ascii_char = f$extract(0,1,ascii_string)
  3651. $ If (.NOT. ("0" .les. ascii_char) .and. (ascii_char .les. "9"))
  3652. $ Then
  3653. $   Write Sys$OutPut -
  3654.     f$fao("error: Enter option NUMBER (up to !2SL)", MAXHOSTS)
  3655. $   Goto _select_loop
  3656. $ EndIF
  3657. $!
  3658. $ local_archie = host_P1_'selection'
  3659. $!
  3660. $ RETURN
  3661. $!
  3662. $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3663. $! If we're using VAXC then we need to grab STRINGS.H from SYS$LIBRARY.
  3664. $CHECK_FOR_STRINGS_H:
  3665. $ delete := delete
  3666. $ copy   := copy
  3667. $ If (f$search("strings.h") .nes. "") Then delete/nolog/noconfirm []strings.h;*
  3668. $ If .NOT. (GNU_CC) Then copy/noconfirm sys$library:string.h []strings.h
  3669. $!
  3670. $ RETURN
  3671. $!
  3672. $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3673. $! **NOTE** use of global symbol!!!
  3674. $! **NOTE** this is the only way I could pass it to the compile subroutine
  3675. $! **NOTE** without DCL and/or CC stripping off too many layers of quotes..
  3676. $! **NOTE** yeah.. I know.. It's ugly...  you work it out!! :-)
  3677. $SET_CC_DEFINES:
  3678. $ archie_host = " """"""ARCHIE_HOST=""""""""''local_archie'"""""""" """""" "
  3679. $ cflags :== /define=(debug=1,funcs=1,noregex=1'tcpip_flag','archie_host')
  3680. $!
  3681. $RETURN
  3682. $!
  3683. $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3684. $!
  3685. $DO_COMPILES:
  3686. $ GoSub CLRSCN
  3687. $ LINKAGE_REQUIRED == NO
  3688. $ If ("''f$type(Archie_EXECUTABLE)'" .nes. "")
  3689. $ Then
  3690. $   If (Archie_EXECUTABLE .nes. "")
  3691. $   Then If (f$search(Archie_EXECUTABLE) .eqs. "") Then LINKAGE_REQUIRED == YES
  3692. $   Else If (f$search("Archie.exe") .eqs. "") Then LINKAGE_REQUIRED == YES
  3693. $   EndIF
  3694. $ Else
  3695. $   If (f$search("Archie.exe") .nes. "") Then LINKAGE_REQUIRED == YES
  3696. $ EndIF
  3697. $ i = 1
  3698. $cc_loop:
  3699. $ If (i .gt. MAXSOURCEFILES) Then GoTo cc_done
  3700. $ source_file = source_P1_'i'
  3701. $ If ((f$type(source_P2_'i') .eqs. "") .or. (source_P2_'i' .eqs. ""))
  3702. $ Then Call Compile "''cc'" "''source_file'" "''debug'" 'FORCEBUILD'
  3703. $ Else
  3704. $   If ((NO_TCPIP_SUPPORT) .and. (source_P2_'i' .eqs. "SUPPORT"))
  3705. $   Then Call Compile "''cc'" "''source_file'" "''debug'" 'FORCEBUILD'
  3706. $   EndIF
  3707. $ EndIF
  3708. $ i = i + 1
  3709. $ GoTo cc_loop
  3710. $cc_done:
  3711. $ If (FORCELINK) Then LINKAGE_REQUIRED == YES
  3712. $!
  3713. $ RETURN
  3714. $!
  3715. $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3716. $!
  3717. $DO_LINK:
  3718. $ If (f$type(Archie_EXECUTABLE) .nes. "")
  3719. $ Then
  3720. $   If (Archie_EXECUTABLE .nes. "")
  3721. $   Then executable := /Exec='Archie_EXECUTABLE'
  3722. $   Else executable := /Exec=Archie.exe
  3723. $   EndIF
  3724. $ Else
  3725. $   executable := /Exec=Archie.exe
  3726. $ EndIF
  3727. $ i = 1
  3728. $ object_files :=
  3729. $object_files_loop:
  3730. $ If (i .gt. MAXSOURCEFILES) Then GoTo object_files_done
  3731. $ object_file = source_P1_'i'
  3732. $ If ((f$type(source_P2_'i') .eqs. "") .or. (source_P2_'i' .eqs. ""))
  3733. $ Then object_files := 'object_files'+'object_file'
  3734. $ Else
  3735. $   If ((NO_TCPIP_SUPPORT) .and. (source_P2_'i' .eqs. "SUPPORT"))
  3736. $   Then object_files := 'object_files'+'object_file'
  3737. $   EndIF
  3738. $ EndIF
  3739. $ i = i + 1
  3740. $ GoTo object_files_loop
  3741. $object_files_done:
  3742. $ If (f$extract(0,1,object_files) .eqs. "+")
  3743. $ Then object_files = f$extract(1,f$length(object_files),object_files)
  3744. $ EndIF
  3745. $ If (tcpip_libs .nes. "")
  3746. $ Then object_files = object_files + ","
  3747. $ EndIF
  3748. $!
  3749. $ Set Verify
  3750. $ Link'debug''executable' 'object_files''tcpip_libs'
  3751. $ x='f$verify(0)'
  3752. $!
  3753. $ Write Sys$OutPut " "
  3754. $ Write Sys$OutPut " "
  3755. $ Write Sys$OutPut "Done! Define the symbol ARCHIE & fire away."
  3756. $!
  3757. $ RETURN
  3758. $!
  3759. $! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3760. $!
  3761. $CLRSCN:
  3762. $If (f$GetDVI("TT:","TT_ANSICRT"))            ! ANSI compatible?
  3763. $Then
  3764. $  CSI = "x["
  3765. $  CSI[0,8] = 27
  3766. $  CLS = CSI + "H" + CSI +"2J"
  3767. $  Write Sys$OutPut CLS
  3768. $Else
  3769. $  Write Sys$Output "''f$fao("!/!/!/!/!/!/!/!/!/!/!/")
  3770. $  Write Sys$Output "''f$fao("!/!/!/!/!/!/!/!/!/!/!/!/")
  3771. $EndIF
  3772. $Return
  3773. $!
  3774. $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3775. $!
  3776. $AddHOST: SUBROUTINE
  3777. $ host_P1_'arg' :== "''P1'"
  3778. $ host_P2_'arg' :== "''P2'"
  3779. $ arg == arg + 1    ! *NOTE* global symbols used...
  3780. $ENDSUBROUTINE
  3781. $!
  3782. $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3783. $!
  3784. $AddSOURCE: SUBROUTINE
  3785. $ source_P1_'arg' :== "''P1'"
  3786. $ source_P2_'arg' :== "''P2'"
  3787. $ arg == arg + 1    ! *NOTE* global symbols used...
  3788. $ENDSUBROUTINE
  3789. $!
  3790. $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3791. $!
  3792. $AddTCPIP: SUBROUTINE
  3793. $ tcpip_P1_'arg' :== "''P1'"
  3794. $ tcpip_P2_'arg' :== "''P2'"
  3795. $ tcpip_P3_'arg' :== "''P3'"
  3796. $ tcpip_P4_'arg' :== "''P4'"
  3797. $ tcpip_P5_'arg' :== "''P5'"
  3798. $ arg == arg + 1    ! *NOTE* global symbols used...
  3799. $ENDSUBROUTINE
  3800. $!
  3801. $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3802. $! **NOTE** cflags is a GLOBAL symbol due to problems with quoted /Defines
  3803. $! **NOTE** not passing down correctly.. (I gave up!)
  3804. $Compile: SUBROUTINE
  3805. $ YES = (1.eq.1)
  3806. $! --- do a Make of only that source which has been modified since its
  3807. $!     object code was generated or that is missing its object code.
  3808. $ cc       = "''P1'"
  3809. $ source   = "''P2'"
  3810. $ dbg      = "''P3'"
  3811. $ FORCED   = P4
  3812. $!
  3813. $source = source - ".C" + ".C"
  3814. $ t1 = f$search("''source'")                ! source exists?
  3815. $  If (t1 .eqs. "") Then GoTo _error_source_missing    ! YIPE!
  3816. $   source = source - ".C"
  3817. $    if (FORCED) Then GoTo _compile_the_source        ! forced to compile
  3818. $     t1 = f$search("''source'.OBJ")            ! object exist?
  3819. $     If (t1 .eqs. "") Then GoTo _compile_the_source    ! object missing
  3820. $     t1 = f$file_attributes("''source'.OBJ","RDT")    ! when was the OBJECT
  3821. $    t1 = f$cvtime(t1)                    ! produced? (rev date)
  3822. $   t2 = f$file_attributes("''source'.C","RDT")        ! when was source last
  3823. $  t2 = f$cvtime(t2)                    ! modified?
  3824. $ If (t1 .ges. t2) Then GoTo _bypass_compile        ! object still current
  3825. $_compile_the_source:
  3826. $ set verify
  3827. $ 'cc -
  3828.   'cflags -
  3829.   'dbg 'source
  3830. $ x='f$verify(0)'
  3831. $ LINKAGE_REQUIRED == YES
  3832. $  GoTo _cc_done
  3833. $_bypass_compile:                    ! didn't need to
  3834. $  GoTo _cc_done                    ! generate new OBJ file
  3835. $_error_source_missing:
  3836. $ Write Sys$OutPut "ERROR: unable to locate source file ''source'.C"
  3837. $_cc_done:
  3838. $ENDSUBROUTINE
  3839. $!
  3840. $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3841. $!
  3842. $CHECKIFVERSIONOK:
  3843. $ required_version = tcpip_P5_'i'
  3844. $ tcpip_type = tcpip_P1_'i'
  3845. $ If ("MULTINET" .eqs. tcpip_type)
  3846. $ Then                        ! I know how to check MULTINET
  3847. $   If (f$search("MULTINET:MULTINET_VERSION.;") .nes. "")
  3848. $   Then
  3849. $     Open/share=READ fd MULTINET:MULTINET_VERSION.;
  3850. $     Read fd buffer
  3851. $     Close fd
  3852. $     v = buffer - "VERSION"
  3853. $     v = f$edit(V,"TRIM,COMPRESS")
  3854. $     If (v .ges. required_version)
  3855. $     Then VERSION_TOO_EARLY = NO
  3856. $     Else VERSION_TOO_EARLY = YES
  3857. $     EndIF
  3858. $   Else
  3859. $     VERSION_TOO_EARLY = YES
  3860. $   EndIF
  3861. $ Else                        ! don't know, so assume current
  3862. $   VERSION_TOO_EARLY = NO
  3863. $ EndIF
  3864. $!
  3865. $ RETURN
  3866. $!
  3867. $!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3868.  
  3869.  
  3870. $EOD
  3871. $!
  3872. $CREATE [.archie]makefile.cut
  3873. $DECK
  3874. #
  3875. # CUTCP/CUTE BC++ version 11/22/91 bkc@omnigate.clarkson.edu
  3876. # Last changed: 12/03/91 1.2.1
  3877. #
  3878. # Makefile for the minimal build for an archie Prospero client.
  3879. #.INCLUDE ../../../builtins
  3880.  
  3881. OBJS    = aquery.obj    archie.obj    atalloc.obj \ 
  3882.       get_pauth.obj    get_vdir.obj    perrmesg.obj    procquery.obj    \
  3883.       ptalloc.obj    regex.obj    stcopy.obj    support.obj\
  3884.       vlalloc.obj    vl_comp.obj     dirsend.obj    misc.obj
  3885.  
  3886. # dirsend.obj
  3887.  
  3888. HDRS    = archie.h    pmachine.h    pcompat.h
  3889.  
  3890. DEFINES    = -DDEBUG -DCUTCP
  3891.  
  3892. CFLAGS= -k -N -ml -r -v $(DEFINES) -I.
  3893. LFLAGS= /P/m/s
  3894. CC = bccx
  3895.  
  3896. EXE    = archie.exe
  3897.  
  3898. all: $(EXE)
  3899.  
  3900. $(OBJS): $(HDRS)
  3901.  
  3902. .c.obj:
  3903.     $(CC)  $(CFLAGS) -c $<
  3904.  
  3905. $(EXE): $(OBJS) Makefile 
  3906.     tlink $(LFLAGS) @&&!
  3907. c0l $(OBJS)
  3908. !,archie,archie,@&&!
  3909. lib\tcp lib\sess lib\enet lib\vjc lib\over cl
  3910. !
  3911.  
  3912. clean:
  3913.     +-del *.obj
  3914. $EOD
  3915. $!
  3916. $CREATE [.archie]makefile.dos
  3917. $DECK
  3918. #
  3919. # Last changed: 11/20/91, v1.2
  3920. #
  3921. # Makefile for the minimal build for an archie Prospero client.
  3922. #.INCLUDE ../../../builtins
  3923.  
  3924. OBJS    = aquery.lo    archie.lo    atalloc.lo    dirsend.lo    \
  3925.       get_pauth.lo    get_vdir.lo    perrmesg.lo    procquery.lo    \
  3926.       ptalloc.lo    regex.lo    stcopy.lo    support.lo    \
  3927.       vlalloc.lo    vl_comp.lo
  3928. HDRS    = archie.h    pmachine.h    pcompat.h
  3929.  
  3930. DEFINES    = -DDEBUG -DNOREGEX -DUSG
  3931.  
  3932. CFLAGS    = -Oeclgsz -Gs -Zi -W4 -I. $(DEFINES)
  3933.  
  3934. EXE    = archie.exe
  3935.  
  3936. all: $(EXE)
  3937.  
  3938. $(OBJS): $(HDRS)
  3939.  
  3940. $(EXE): $(OBJS) Makefile archie.lnk
  3941.     link @archie.lnk
  3942.     exepack archie.unp archie.exe
  3943.  
  3944. clean:
  3945.     +-del *.lo
  3946.     +-del *.exe
  3947.  
  3948. $EOD
  3949. $!
  3950. $CREATE [.archie]makefile.os2
  3951. $DECK
  3952. #
  3953. # Last changed: 11/20/91, v1.2
  3954. #
  3955. # Makefile for the minimal build for an archie Prospero client.
  3956. .INCLUDE ../../../builtins
  3957.  
  3958. OBJS    = aquery.obj    archie.obj    atalloc.obj    dirsend.obj    \
  3959.       get_pauth.obj    get_vdir.obj    perrmesg.obj    procquery.obj    \
  3960.       ptalloc.obj    regex.obj    stcopy.obj    support.obj    \
  3961.       vlalloc.obj    vl_comp.obj
  3962. HDRS    = archie.h    pmachine.h    pcompat.h
  3963.  
  3964. DEFINES    = -DDEBUG -DNOREGEX
  3965.  
  3966. IFLAGS    = -I. -I../../../include $(DEFINES)
  3967.  
  3968. LFLAGS     = /stack:30000/nod/noe/noi/map/CO
  3969. LIBS    = pctcp bsd ftpcrt socket os2
  3970. EXE    = archie.exe
  3971.  
  3972. all: $(EXE)
  3973.  
  3974. install: $(EXE)
  3975.     cp $[m,*.exe,$**] ..\..\..\bin
  3976.     @touch install
  3977.  
  3978. $(OBJS): $(HDRS)
  3979.  
  3980. $(EXE): $(OBJS) Makefile
  3981.     $(LD) $(LFLAGS) $(L_DEBUG) <@<
  3982. $[s,"+ \n",$[m,*.obj,$**]]
  3983. $*
  3984. $*
  3985. $(LIBS)
  3986.  
  3987. <
  3988.     +markexe lfns $@
  3989.     +markexe windowcompat $@
  3990.  
  3991. clean:
  3992.     +-del *.obj
  3993.     +-del *.exe
  3994.  
  3995. $EOD
  3996. $!
  3997. $CREATE [.archie.msdos]cutcp.h
  3998. $DECK
  3999. /* cutcp.h -- defs for cutcp code */
  4000.  
  4001.  
  4002. int         netlisten(unsigned int port);
  4003. struct machinfo *Shostlook(char *name);
  4004. int         Sdomain(char *name);
  4005. struct machinfo *Sgethost(char *name);
  4006. struct machinfo *Slookip(unsigned long *address);
  4007. void        netgetftp(unsigned int array[], unsigned int port);
  4008. int         netopen(unsigned long *address, unsigned int port);
  4009. int         Snetopen(struct machinfo *m, unsigned int port);
  4010. int        netqlen(int handle);
  4011. int        netroom(int handle);
  4012. int        netread(int pnum, unsigned char *buffer, unsigned int n);
  4013. int        netwrite(int pnum, unsigned char *buffer, unsigned int n);
  4014. int        netest(int pnum);
  4015. int        netpush(int pnum);
  4016. void        netulisten(unsigned int portnum);
  4017. int        netusend(unsigned long *address, unsigned destport, 
  4018.             unsigned sourceport, unsigned char *buffer, int count);
  4019. int        neturead(unsigned char    *buffer);
  4020. struct machinfo *Slooknum(int pnum);
  4021. int        Snetinit();
  4022. int        Shostfile(char *name);
  4023. int        netshut();
  4024. int        Sgetevent(int classes, int *clss, int *data);
  4025. int        netclose(int pnum);
  4026. unsigned int    intswap(unsigned int val);
  4027. unsigned long    n_clicks(void *p);
  4028. void        Stask();
  4029.  
  4030. #define    ntohs(a)    (intswap(a))
  4031. #define    htons(a)    (intswap(a))
  4032. $EOD
  4033. $!
  4034. $CREATE [.archie.msdos]hostform.h
  4035. $DECK
  4036. /* hfile.inc - placed into all .h files to set up for PVCS 
  4037.    $Header:   E:/pcdirs/vcs/hostform.h_v   1.0   15 Jan 1990 19:30:22   bkc  $
  4038.    Revision History ----------------------------------------------------
  4039.    $Log:   E:/pcdirs/vcs/hostform.h_v  $
  4040.  * 
  4041.  *    Rev 1.0   15 Jan 1990 19:30:22   bkc
  4042. */
  4043.  
  4044.  
  4045. /*
  4046. *  Host and local machine configuration information.
  4047. *
  4048. ****************************************************************************
  4049. *                                                                          *
  4050. *      NCSA Telnet for the PC                                              *
  4051. *      by Tim Krauskopf, VT100 by Gaige Paulsen, Tek by Aaron Contorer     *
  4052. *                                                                          *
  4053. *      National Center for Supercomputing Applications                     *
  4054. *      152 Computing Applications Building                                 *
  4055. *      605 E. Springfield Ave.                                             *
  4056. *      Champaign, IL  61820                                                *
  4057. *                                                                          *
  4058. *      This program is in the public domain.                               *
  4059. *                                                                          *
  4060. ****************************************************************************
  4061. */
  4062.  
  4063. /*
  4064. *  Linked list of structures which describe other machines.
  4065. *  Arranged one per session with unique session names.
  4066. */
  4067.  
  4068. struct machinfo {
  4069.     unsigned char 
  4070.         *sname,                    /* pointer to name of session */
  4071.         *hname,                 /* pointer to name of that machine */
  4072.         *font,                    /* font name, if we can do it */
  4073.         *keymap,                /* pointer to keymap file name */
  4074.         hostip[4],                /* IP number of this machine */
  4075.         gateway,                /* gateway preference, start with 1 */
  4076.         nameserv,                /* nameserver preference, start with 1 */
  4077.         bksp,                    /* backspace value */
  4078.         halfdup,                /* half duplex required */
  4079.         crmap,                    /* Strange Berkeley 4.3 CR mode needed */
  4080.         vtwrap,                    /* flag on when need wrap mode */
  4081.         vtmargin;                /* col to ring bell at */
  4082.     int
  4083.         clearsave,                /* whether to save cleared lines */
  4084.         fsize,                    /* font size in points */
  4085.         nfcolor[3],                /* normal foreground */
  4086.         nbcolor[3],                /* normal background */
  4087.         bfcolor[3],                /* blink             */
  4088.         bbcolor[3],
  4089.         ufcolor[3],             /* underline */
  4090.         ubcolor[3],
  4091.         mno,                    /* machine number for reference */
  4092.         mstat,                    /* status of this machine entry */
  4093.         bkscroll,                /* how many lines to save */
  4094.         retrans,                /* initial retrans timeout */
  4095.         conto,                    /* time out in seconds to wait for connect */
  4096.         window,                    /* window, will be checked against buffers */
  4097.         maxseg,                    /* maximum receivable segment size */
  4098.         mtu,                    /* maximum transfer unit MTU (out) */
  4099.                 domainsremaining,                       /* how many domain search list entries remain */
  4100.                 destport,                               /* yepper, you can telnet to a different port than 23 */
  4101.         flags;                    /* general flags holder */        
  4102. #define    MFLAGS_SCRIPT    0x80
  4103.     struct machinfo *next;        /* surprise, its a linked list! */
  4104. };
  4105.  
  4106. struct machinfo *Sgethost(),*Shostlook(),*Slooknum(),*Slookip(),*Smadd();
  4107.  
  4108. /*
  4109. *  status fields for mstat, what do we know about that machine?
  4110. */
  4111. #define NOIP 1                    /* we don't have IP number */
  4112. #define UDPDOM 3                /* there is a UDP request pending on it */
  4113. /*  The next 20 numbers are reserved for UDPDOM */
  4114. #define HAVEIP 50                /* at least we have the # */
  4115. #define HFILE 70                /* we have IP number from host file */
  4116. #define DOM 71                    /* we have an IP number from DOMAIN */
  4117. #define FROMKIP 72                /* have IP# from KIP server */
  4118.  
  4119.  
  4120.  
  4121. /*
  4122. *   Configuration information which 
  4123. *   the calling program may want to obtain from the hosts file.
  4124. *   The calling program should include hostform.h and call
  4125. *   Sgetconfig(cp)
  4126. *     struct config *cp;
  4127. *   which will copy the information to the user's data structure.
  4128. */
  4129. struct config {
  4130.     unsigned char
  4131.         netmask[4],                /* subnetting mask being used */
  4132.         havemask,                /* do we have a netmask? */
  4133.         irqnum,                    /* which hardware interrupt */
  4134.         myipnum[4],                /* what is my IP #? */
  4135.         me[32],                    /* my name description (first 30 chars) */
  4136.         color[3],                /* default colors to use */
  4137.         hw[10],                    /* hardware type for network */
  4138.         video[10],                /* video graphics hardware available */
  4139.         bios,                    /* flag, do we want to use BIOS for screen access */
  4140.         tek,                    /* flag, enable tektronix graphics */
  4141.         ftp,                    /* flag, enable ftp server */
  4142.         rcp,                    /* flag, enable rcp server */
  4143.         comkeys,                /* flag, commandkeys=yes */
  4144.         *termtype,                /* terminal type specification */
  4145.         *zone,                    /* AppleTalk zone for KIP NBP */
  4146.         *defdom,                /* default domain */
  4147.         *capture,                /* pointer to where the capture file name is */
  4148.         *pass,                    /* pointer to where the password file name is */
  4149.         *hpfile,                /* HP file name */
  4150.         *psfile,                /* PS file name */
  4151.         *tekfile;                /* tek file name */
  4152. int
  4153.         nstype,                    /* nameserver = 1-domain 2-IEN116  */
  4154.         domto,                    /* time out for UDP domain request */
  4155.         ndom,                    /* number of retries for domain requests */
  4156.         timesl,                    /* time slice */
  4157.         address,                /* segment address */
  4158.         ioaddr;                    /* I/O address */
  4159. char            *domainpath;                               /* domain name search path */
  4160. char            *map3270;                               /* path to 3270 map */
  4161. char            tnmode;                                 /* how we decide to connect to 3270 streams */
  4162. long        sys_flags;
  4163. #define    SYS_FLAGS_VISUAL_BELL    0x1        /* use visual bell */
  4164.  
  4165. };
  4166.  
  4167.  
  4168. #define TNMODE_FLAGGED  0
  4169. #define TNMODE_AUTO     1
  4170. #define TNMODE_NOTFLAGGED 2
  4171. #define TNMODE_OFF      3
  4172. $EOD
  4173. $!
  4174. $CREATE [.archie.msdos]netevent.h
  4175. $DECK
  4176. /* hfile.inc - placed into all .h files to set up for PVCS 
  4177.    $Header:   E:/pcdirs/vcs/netevent.h_v   1.0   15 Jan 1990 19:29:26   bkc  $
  4178.    Revision History ----------------------------------------------------
  4179.    $Log:   E:/pcdirs/vcs/netevent.h_v  $
  4180.  * 
  4181.  *    Rev 1.0   15 Jan 1990 19:29:26   bkc
  4182. */
  4183.  
  4184.  
  4185. /*
  4186. *  Events for event processing in NCSA Telnet.
  4187. *  Used for netgetevent().
  4188. */
  4189.  
  4190.  
  4191. #define USERCLASS    1    /* the user program will accept these events */
  4192. #define ICMPCLASS    2    /* ICMP in netsleep will look for these */
  4193. #define ERRCLASS    4    /* the user may or may not read these error messages */
  4194. #define SCLASS        8    /* the background server will take these */
  4195. #define CONCLASS    0x10    /* the application manages connections with these */
  4196.  
  4197. #define ERR1    1        /* an error message is waiting, ERRCLASS */
  4198.  
  4199. #define IREDIR    1        /* ICMP redirect, ICMPCLASS */
  4200.  
  4201. #define CONOPEN 1        /* connection has opened, CONCLASS */
  4202. #define CONDATA 2       /* there is data available on this connection */
  4203. #define CONCLOSE 3        /* the other side has closed its side of the connection */
  4204. #define CONFAIL 4        /* connection open attempt has failed */
  4205.  
  4206. #define UDPDATA 1        /* UDP data has arrived on listening port, USERCLASS */
  4207. #define DOMOK    2        /* domain name ready */
  4208. #define DOMFAIL 3        /* domain name lookup failed */
  4209. #define FTPCOPEN 20     /* FTP command connection has opened */
  4210. #define FTPCLOSE 21     /* FTP command connection has closed */
  4211. #define FTPBEGIN 22     /* FTP transfer beginning, dat =1 for get, 0 for put */
  4212. #define FTPEND   23     /* FTP transfer ending */
  4213. #define FTPLIST  24     /* FTP file listing taking place */
  4214. #define FTPUSER  25     /* FTP user name has been entered */
  4215. #define FTPPWOK    26        /* FTP password verified */
  4216. #define FTPPWNO 27        /* FTP password failed */
  4217. #define RCPBEGIN 30        /* RCP beginning */
  4218. #define RCPEND 31        /* RCP ending */
  4219.  
  4220. #define UDPTO 1            /* UDP request from DOMAIN timed out, SCLASS */
  4221. #define FTPACT 2        /* FTP transfer is active, keep sending */
  4222. #define TCPTO  3        /* TCP for DOMAIN timed out */
  4223. #define RCPACT 4        /* rcp is active, needs CPU time */
  4224. #define RETRYCON 5        /* retry connection packet, might be lost */
  4225. #define DOMNEXT 6               /* search next domain list entry */
  4226. #define E_CLOCK 7
  4227. #ifdef    SCRIPT
  4228. #define    SCRIPT_EVENT    1    /* script next step */
  4229. #define    SCRIPT_DATA    2    /* received some data */
  4230. #define    SCRIPT_PROC    3    /* just process stuff */
  4231. #define    SCRIPT_CLOSE    4    /* connection was closed */
  4232. #define    SCRIPT_FORCE    5    /* user forced connection closed */
  4233. #define    SCRIPT_DOMAIN    6    /* domain name lookup ok */
  4234. #define    SCRIPT_FUNC    8
  4235. /* int Script_Event(int type, void *twin, unsigned int data); */
  4236. #endif
  4237. $EOD
  4238. $!
  4239. $CREATE [.archie]perrmesg.c
  4240. $DECK
  4241. /*
  4242.  * Copyright (c) 1989, 1990, 1991 by the University of Washington
  4243.  *
  4244.  * For copying and distribution information, please see the file
  4245.  * <copyright.h>.
  4246.  */
  4247.  
  4248. #include <copyright.h>
  4249. #include <perrno.h>
  4250. #include <stdio.h>
  4251.  
  4252. /* This file and perrno.h should always be updated simultaneously */
  4253.  
  4254. int    perrno = 0;
  4255. int    pwarn = 0;
  4256. char    p_err_string[P_ERR_STRING_SZ];
  4257. char    p_warn_string[P_ERR_STRING_SZ];
  4258.  
  4259. char    *p_err_text[256] = {
  4260.     /*   0 */ "Success (prospero)",
  4261.     /*   1 */ "Port unknown (dirsend)",
  4262.     /*   2 */ "Can't open local UDP port (dirsend)",
  4263.     /*   3 */ "Can't resolve hostname (dirsend)",
  4264.     /*   4 */ "Unable to send entire message (dirsend)",
  4265.     /*   5 */ "Timed out (dirsend)",
  4266.     /*   6 */ "Recvfrom failed (dirsend)",
  4267.     /*   7 */ "",    /*   8 */ "",    /*   9 */ "",    /*  10 */ "",
  4268.     /*  11 */ "Sendto failed (reply)",
  4269.     /*  12 */ "",    /*  13 */ "",    /*  14 */ "",    /*  15 */ "",
  4270.     /*  16 */ "",    /*  17 */ "",    /*  18 */ "",    /*  19 */ "",
  4271.     /*  20 */ "",
  4272.     /*  21 */ "Link already exists (vl_insert)",
  4273.     /*  22 */ "Link with same name already exists (vl_insert)",
  4274.     /*  23 */ "",    /*  24 */ "",
  4275.     /*  25 */ "Link already exists (ul_insert)",
  4276.     /*  26 */ "Replacing existing link (ul_insert)",
  4277.     /*  27 */ "Previous entry not found in dir->ulinks (ul_insert)",
  4278.     /*  28 */ "",    /*  29 */ "",    /*  30 */ "",    /*  31 */ "",
  4279.     /*  32 */ "",    /*  33 */ "",    /*  34 */ "",    /*  35 */ "",
  4280.     /*  36 */ "",    /*  37 */ "",    /*  38 */ "",    /*  39 */ "",
  4281.     /*  40 */ "",
  4282.     /*  41 */ "Temporary not found (rd_vdir)",
  4283.     /*  42 */ "Namespace not closed with object (rd_vdir)",
  4284.     /*  43 */ "Alias for namespace not defined (rd_vdir)",
  4285.     /*  44 */ "Specified namespace not found (rd_vdir)",
  4286.     /*  45 */ "",    /*  46 */ "",    /*  47 */ "",    /*  48 */ "",
  4287.     /*  49 */ "",    /*  50 */ "",
  4288.     /*  51 */ "File access method not supported (pfs_access)",
  4289.     /*  52 */ "",    /*  53 */ "",    /*  54 */ "",
  4290.     /*  55 */ "Pointer to cached copy - delete on close (pmap_cache)",
  4291.     /*  56 */ "Unable to retrieve file (pmap_cache)",
  4292.     /*  57 */ "",    /*  58 */ "",    /*  59 */ "",    /*  60 */ "",
  4293.     /*  61 */ "Directory already exists (mk_vdir)",
  4294.     /*  62 */ "Link with same name already exists (mk_vdir)",
  4295.     /*  63 */ "",    /*  64 */ "",
  4296.     /*  65 */ "Not a virtual system (vfsetenv)",
  4297.     /*  66 */ "Can't find directory (vfsetenv)",
  4298.     /*  67 */ "",    /*  68 */ "",    /*  69 */ "",    /*  70 */ "",
  4299.     /*  71 */ "Link already exists (add_vlink)",
  4300.     /*  72 */ "Link with same name already exists (add_vlink)",
  4301.     /*  73 */ "",    /*  74 */ "",    /*  75 */ "",    /*  76 */ "",
  4302.     /*  77 */ "",    /*  78 */ "",    /*  79 */ "",    /*  80 */ "",
  4303.     /*  81 */ "",    /*  82 */ "",    /*  83 */ "",    /*  84 */ "",
  4304.     /*  85 */ "",    /*  86 */ "",    /*  87 */ "",    /*  88 */ "",
  4305.     /*  89 */ "",    /*  90 */ "",    /*  91 */ "",    /*  92 */ "",
  4306.     /*  93 */ "",    /*  94 */ "",    /*  95 */ "",    /*  96 */ "",
  4307.     /*  97 */ "",    /*  98 */ "",    /*  99 */ "",    /* 100 */ "",
  4308.     /* 101 */ "",    /* 102 */ "",    /* 103 */ "",    /* 104 */ "",
  4309.     /* 105 */ "",    /* 106 */ "",    /* 107 */ "",    /* 108 */ "",
  4310.     /* 109 */ "",    /* 110 */ "",    /* 111 */ "",    /* 112 */ "",
  4311.     /* 113 */ "",    /* 114 */ "",    /* 115 */ "",    /* 116 */ "",
  4312.     /* 117 */ "",    /* 118 */ "",    /* 119 */ "",    /* 120 */ "",
  4313.     /* 121 */ "",    /* 122 */ "",    /* 123 */ "",    /* 124 */ "",
  4314.     /* 125 */ "",    /* 126 */ "",    /* 127 */ "",    /* 128 */ "",
  4315.     /* 129 */ "",    /* 130 */ "",    /* 131 */ "",    /* 132 */ "",
  4316.     /* 133 */ "",    /* 134 */ "",    /* 135 */ "",    /* 136 */ "",
  4317.     /* 137 */ "",    /* 138 */ "",    /* 139 */ "",    /* 140 */ "",
  4318.     /* 141 */ "",    /* 142 */ "",    /* 143 */ "",    /* 144 */ "",
  4319.     /* 145 */ "",    /* 146 */ "",    /* 147 */ "",    /* 148 */ "",
  4320.     /* 149 */ "",    /* 150 */ "",    /* 151 */ "",    /* 152 */ "",
  4321.     /* 153 */ "",    /* 154 */ "",    /* 155 */ "",    /* 156 */ "",
  4322.     /* 157 */ "",    /* 158 */ "",    /* 159 */ "",    /* 160 */ "",
  4323.     /* 161 */ "",    /* 162 */ "",    /* 163 */ "",    /* 164 */ "",
  4324.     /* 165 */ "",    /* 166 */ "",    /* 167 */ "",    /* 168 */ "",
  4325.     /* 169 */ "",    /* 170 */ "",    /* 171 */ "",    /* 172 */ "",
  4326.     /* 173 */ "",    /* 174 */ "",    /* 175 */ "",    /* 176 */ "",
  4327.     /* 177 */ "",    /* 178 */ "",    /* 179 */ "",    /* 180 */ "",
  4328.     /* 181 */ "",    /* 182 */ "",    /* 183 */ "",    /* 184 */ "",
  4329.     /* 185 */ "",    /* 186 */ "",    /* 187 */ "",    /* 188 */ "",
  4330.     /* 189 */ "",    /* 190 */ "",    /* 191 */ "",    /* 192 */ "",
  4331.     /* 193 */ "",    /* 194 */ "",    /* 195 */ "",    /* 196 */ "",
  4332.     /* 197 */ "",    /* 198 */ "",    /* 199 */ "",    /* 200 */ "",
  4333.     /* 201 */ "",    /* 202 */ "",    /* 203 */ "",    /* 204 */ "",
  4334.     /* 205 */ "",    /* 206 */ "",    /* 207 */ "",    /* 208 */ "",
  4335.     /* 209 */ "",    /* 210 */ "",    /* 211 */ "",    /* 212 */ "",
  4336.     /* 213 */ "",    /* 214 */ "",    /* 215 */ "",    /* 216 */ "",
  4337.     /* 217 */ "",    /* 218 */ "",    /* 219 */ "",    /* 220 */ "",
  4338.     /* 221 */ "",    /* 222 */ "",    /* 223 */ "",    /* 224 */ "",
  4339.     /* 225 */ "",    /* 226 */ "",    /* 227 */ "",    /* 228 */ "",
  4340.     /* 229 */ "",
  4341.     /* 230 */ "File not found (prospero)",
  4342.     /* 231 */ "Directory not found (prospero)",
  4343.     /* 232 */ "Symbolic links nested too deep (prospero)",
  4344.     /* 233 */ "Environment not initialized - source vfsetup.source then run vfsetup",
  4345.     /* 234 */ "Can't traverse an external file (prospero)",
  4346.     /* 235 */ "Forwarding chain is too long (prospero)",
  4347.     /* 236 */ "",    /* 237 */ "",    /* 238 */ "",    /* 239 */ "",
  4348.     /* 240 */ "",    /* 241 */ "",
  4349.     /* 242 */ "Authentication required (prospero server)",
  4350.     /* 243 */ "Not authorized (prospero server)",
  4351.     /* 244 */ "Not found (prospero server)",
  4352.     /* 245 */ "Bad version number (prospero server)",
  4353.     /* 246 */ "Not a directory (prospero server)",
  4354.     /* 247 */ "Already exists (prospero server)",
  4355.     /* 248 */ "Link with same name already exists (prospero server)",
  4356.     /* 249 */ "",    /* 250 */ "",
  4357.     /* 251 */ "Command not implemented on server (dirsrv)",
  4358.     /* 252 */ "Bad format for response (dirsrv)",
  4359.     /* 253 */ "Protocol error (prospero server)",
  4360.     /* 254 */ "Unspecified server failure (prospero server)",
  4361.     /* 255 */ "Generic Failure (prospero)"};
  4362.  
  4363. char    *p_warn_text[256] = {
  4364.     /*   0 */ "No warning",
  4365.     /*   1 */ "You are using an old version of this program",
  4366.     /*   2 */ "From server",
  4367.     /*   3 */ "Unrecognized line in response from server",
  4368.   /* 4-254 */ "", "", "", "", "", "", "", "", "", "", "", "", "",
  4369.   "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
  4370.   "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
  4371.   "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
  4372.   "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
  4373.   "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
  4374.   "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
  4375.   "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
  4376.   "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
  4377.   "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
  4378.   "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
  4379.   "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
  4380.   "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
  4381.   "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
  4382.   "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
  4383.     /* 255 */ ""};
  4384.  
  4385. #ifndef ARCHIE
  4386. perrmesg(prefix,no,text)
  4387.     char    *prefix;
  4388.     int        no;
  4389.     char    *text;
  4390.     {
  4391.     fprintf(stderr,"%s%s%s%s\n", (prefix ? prefix : ""),
  4392.         (no ? p_err_text[no] : p_err_text[perrno]),
  4393.         ((text ? (*text ? " - " : "") : 
  4394.           (!no && *p_err_string ? " - " : ""))),
  4395.         (text ? text : (no ? "" : p_err_string)));
  4396.     }
  4397.  
  4398. sperrmesg(buf,prefix,no,text)
  4399.     char    *buf;
  4400.     char    *prefix;
  4401.     int        no;
  4402.     char    *text;
  4403.     {
  4404.     sprintf(buf,"%s%s%s%s\n", (prefix ? prefix : ""),
  4405.         (no ? p_err_text[no] : p_err_text[perrno]),
  4406.         ((text ? (*text ? " - " : "") : 
  4407.           (!no && *p_err_string ? " - " : ""))),
  4408.         (text ? text : (no ? "" : p_err_string)));
  4409.     }
  4410.  
  4411. pwarnmesg(prefix,no,text)
  4412.     char    *prefix;
  4413.     int        no;
  4414.     char    *text;
  4415.     {
  4416.     fprintf(stderr,"%s%s%s%s\n", (prefix ? prefix : ""),
  4417.         (no ? p_warn_text[no] : p_warn_text[pwarn]),
  4418.         ((text ? (*text ? " - " : "") : 
  4419.           (!no && *p_warn_string ? " - " : ""))),
  4420.         (text ? text : (no ? "" : p_warn_string)));
  4421.     }
  4422.  
  4423. spwarnmesg(buf,prefix,no,text)
  4424.     char    *buf;
  4425.     char    *prefix;
  4426.     int        no;
  4427.     char    *text;
  4428.     {
  4429.     sprintf(buf,"%s%s%s%s\n", (prefix ? prefix : ""),
  4430.         (no ? p_warn_text[no] : p_warn_text[pwarn]),
  4431.         ((text ? (*text ? " - " : "") : 
  4432.           (!no && *p_warn_string ? " - " : ""))),
  4433.         (text ? text : (no ? "" : p_warn_string)));
  4434.     }
  4435. #endif
  4436. $EOD
  4437. $!
  4438. $CREATE [.archie]patchlevel.h
  4439. $DECK
  4440. /*
  4441.  * Archie v1.3
  4442.  *
  4443.  * History:
  4444.  *
  4445.  * 04/14/92 v1.3.2 - Release.
  4446.  * 01/10/92 v1.3.1 - Release.
  4447.  * 01/09/92 v1.3 - Release.
  4448.  * 12/13/91      - added UCX support
  4449.  * 12/03/91      - added CUTCP support
  4450.  * 11/20/91 v1.2 - Release.
  4451.  * 11/18/91      - ported to DOS & OS/2
  4452.  * 11/12/91      - finally got to test under Multinet 3.0
  4453.  * 10/03/91      - replaced regex.c for oz
  4454.  * 09/25/91     - added Wollongong support
  4455.  * 08/30/91      - ported to VMS
  4456.  * 08/20/91 v1.1 - Major revisions
  4457.  * 07/31/91 v1.0 - Original
  4458.  */
  4459. $EOD
  4460. $!
  4461. $CREATE [.archie]pauthent.h
  4462. $DECK
  4463. /*
  4464.  * Copyright (c) 1989, 1990, 1991 by the University of Washington
  4465.  *
  4466.  * For copying and distribution information, please see the file
  4467.  * <copyright.h>.
  4468.  */
  4469.  
  4470. #include <copyright.h>
  4471.  
  4472. #define PFSA_UNAUTHENTICATED        1
  4473.  
  4474. struct pfs_auth_info {
  4475.     char            auth_type[100];
  4476.     char            authenticator[250];
  4477. };
  4478.  
  4479. typedef struct pfs_auth_info *PAUTH;
  4480. typedef struct pfs_auth_info PAUTH_ST;
  4481.  
  4482. PAUTH get_pauth();
  4483.  
  4484. #ifndef VMS
  4485. # ifndef IN_H
  4486. #  include <netinet/in.h>
  4487. #  define IN_H
  4488. # endif
  4489. #else
  4490. # ifndef _ARCHIE_VMS
  4491. #  include <vms.h>
  4492. # endif
  4493. #endif
  4494.  
  4495. struct client_info {
  4496.     int                ainfo_type;
  4497.     char            *auth_type;
  4498.     char            *authenticator;
  4499.     char            *userid;
  4500.     short            port;
  4501.     struct in_addr        haddr;
  4502.     struct pfs_auth_info    *previous;
  4503.     struct pfs_auth_info    *next;
  4504. };
  4505.  
  4506. typedef struct client_info *CINFO;
  4507. typedef struct client_info CINFO_ST;
  4508. $EOD
  4509. $!
  4510. $CREATE [.archie]pcompat.h
  4511. $DECK
  4512. /*
  4513.  * Copyright (c) 1989, 1990 by the University of Washington
  4514.  *
  4515.  * For copying and distribution information, please see the file
  4516.  * <copyright.h>.
  4517.  */
  4518.  
  4519. #include <copyright.h>
  4520.  
  4521. /* 
  4522.  * pcompat.h - Definitions for compatability library
  4523.  *
  4524.  * This file contains the defintions used by the compatability
  4525.  * library.  Among the definitions are the possible values for
  4526.  * pfs_disable_flag.  This file also contains the external 
  4527.  * declaration of that variable.  Note, however that the 
  4528.  * the module pfs_disable_flag.o is included in libpfs.a
  4529.  * because some of the routines in that library set it.
  4530.  * The only place it is checked, however, is in pfs_access, 
  4531.  * found in libpcompat.a
  4532.  *
  4533.  */
  4534.  
  4535. extern    int        pfs_default;
  4536. extern    int        pfs_enable;
  4537.  
  4538. /* Definitions for values of pfs_enable */
  4539. #define PMAP_DISABLE      0
  4540. #define PMAP_ENABLE       1
  4541. #define PMAP_COLON      2
  4542. #define PMAP_ATSIGN_NF      3
  4543. #define PMAP_ATSIGN      4
  4544.  
  4545. #define DISABLE_PFS(stmt) do {int DpfStmp; DpfStmp = pfs_enable;\
  4546.                pfs_enable = PMAP_DISABLE; \
  4547.                stmt; \
  4548.                pfs_enable = DpfStmp;} while (0)
  4549.  
  4550. /* Definitions for PFS_ACCESS */
  4551. #define PFA_MAP           0  /* Map the file name only                       */
  4552. #define PFA_CREATE        1  /* Create file if not found                     */
  4553. #define PFA_CRMAP         2  /* Map file name.  Map to new name if not found */
  4554. #define PFA_RO            4  /* Access to file is read only                  */
  4555.  
  4556. #define check_pfs_default() \
  4557.     do { if (pfs_default == -1) get_pfs_default(); } while (0)
  4558. $EOD
  4559. $!
  4560. $CREATE [.archie]perrno.h
  4561. $DECK
  4562. /*
  4563.  * Copyright (c) 1989, 1990 by the University of Washington
  4564.  *
  4565.  * For copying and distribution information, please see the file
  4566.  * <copyright.h>.
  4567.  */
  4568.  
  4569. #include <copyright.h>
  4570.  
  4571. /* This file and perrmesg.c should be updated simultaneously.  */
  4572.  
  4573. /*
  4574.  * perrno.h - definitions for perrno
  4575.  *
  4576.  * This file contains the declarations and defintions of of the external
  4577.  * error values in which errors are returned by the pfs and psrv
  4578.  * libraries.
  4579.  */
  4580.  
  4581. #define        P_ERR_STRING_SZ 100     /* Size of error string        */
  4582.  
  4583. extern int    perrno;
  4584. extern char    p_err_string[];
  4585. extern char    *p_err_text[];
  4586.  
  4587. extern int    pwarn;
  4588. extern char    p_warn_string[];
  4589. extern char    *p_warn_text[];
  4590.  
  4591. /* Error codes returned or found in verrno */
  4592.  
  4593. #ifndef PSUCCESS
  4594. #define    PSUCCESS        0
  4595. #endif
  4596.  
  4597. /* dirsend (perrno) */
  4598. #define DIRSEND_PORT_UNKN    1    /* DIRSRV UDP port unknown      */
  4599. #define DIRSEND_UDP_CANT    2    /* Can't open local UDP port    */
  4600. #define DIRSEND_BAD_HOSTNAME    3    /* Can't resolve hostname       */
  4601. #define DIRSEND_NOT_ALL_SENT    4    /* Didn't send entire message   */
  4602. #define DIRSEND_SELECT_FAILED    5    /* Select failed            */
  4603. #define DIRSEND_BAD_RECV    6    /* Recvfrom failed             */
  4604.  
  4605. /* reply */
  4606. #define REPLY_NOTSENT        11    /* Reply: sendto failed            */
  4607.  
  4608. /* vl_insert */
  4609. #define VL_INSERT_ALREADY_THERE    21    /* Link already exists            */
  4610. #define VL_INSERT_CONFLICT    22    /* Link exists with same name   */
  4611.  
  4612. /* ul_insert */
  4613. #define UL_INSERT_ALREADY_THERE 25    /* Link already exists        */
  4614. #define UL_INSERT_SUPERSEDING   26    /* Replacing existing link    */
  4615. #define UL_INSERT_POS_NOTFOUND  27    /* Prv entry not in dir->ulinks */
  4616.  
  4617. /* rd_vdir */
  4618. #define RVD_DIR_NOT_THERE    41    /* Temporary NOT_FOUND            */
  4619. #define RVD_NO_CLOSED_NS    42    /* Namespace not closed w/ object:: */
  4620. #define RVD_NO_NS_ALIAS        43    /* No alias for namespace NS#:      */
  4621. #define RVD_NS_NOT_FOUND    44    /* Specified namespace not found    */
  4622.  
  4623. /* pfs_access */
  4624. #define PFSA_AM_NOT_SUPPORTED   51      /* Access method not supported  */
  4625.  
  4626. /* pmap_cache */
  4627. #define PMC_DELETE_ON_CLOSE     55    /* Delete cached copy on close   */
  4628. #define PMC_RETRIEVE_FAILED     56      /* Unable to retrieve file       */
  4629.  
  4630. /* mk_vdir */
  4631. /* #define MKVD_ALREADY_EXISTS     61    /* Directory already exists      */
  4632. /* #define MKVD_NAME_CONFLICT    62    /* Link with name already exists */
  4633.  
  4634. /* vfsetenv */
  4635. #define VFSN_NOT_A_VS        65    /* Not a virtual system          */
  4636. #define VFSN_CANT_FIND_DIR    66    /* Not a virtual system          */
  4637.  
  4638. /* add_vlink */
  4639. /* #define ADDVL_ALREADY_EXISTS    71    /* Directory already exists      */
  4640. /* #define ADDVL_NAME_CONFLICT    72    /* Link with name already exists */
  4641.  
  4642. /* Local error codes on server */
  4643.  
  4644. /* dsrdir */
  4645. #define DSRDIR_NOT_A_DIRECTORY 111    /* Not a directory name        */
  4646. /* dsrfinfo */
  4647. #define DSRFINFO_NOT_A_FILE    121      /* Object not found             */
  4648. #define DSRFINFO_FORWARDED     122      /* Object has moved             */
  4649.  
  4650. /* Error codes that may be returned by various procedures               */
  4651. #define PFS_FILE_NOT_FOUND     230      /* File not found               */
  4652. #define PFS_DIR_NOT_FOUND      231      /* Directory in path not found  */
  4653. #define PFS_SYMLINK_DEPTH      232    /* Max sym-link depth exceeded  */
  4654. #define PFS_ENV_NOT_INITIALIZED    233    /* Can't read environment    */
  4655. #define PFS_EXT_USED_AS_DIR    234    /* Can't use externals as dirs  */
  4656. #define PFS_MAX_FWD_DEPTH      235    /* Exceeded max forward depth   */
  4657.  
  4658. /* Error codes returned by directory server                    */
  4659. /* some of these duplicate errors from individual routines     */
  4660. /* some of those error codes should be eliminated              */
  4661. #define DIRSRV_AUTHENT_REQ     242      /* Authentication required       */
  4662. #define DIRSRV_NOT_AUTHORIZED  243      /* Not authorized                */
  4663. #define DIRSRV_NOT_FOUND       244      /* Not found                     */
  4664. #define DIRSRV_BAD_VERS        245
  4665. #define DIRSRV_NOT_DIRECTORY   246
  4666. #define DIRSRV_ALREADY_EXISTS  247    /* Identical link already exists */
  4667. #define DIRSRV_NAME_CONFLICT   248    /* Link with name already exists */
  4668.  
  4669. #define DIRSRV_UNIMPLEMENTED   251      /* Unimplemented command         */
  4670. #define DIRSRV_BAD_FORMAT      252
  4671. #define DIRSRV_ERROR           253
  4672. #define DIRSRV_SERVER_FAILED   254      /* Unspecified server failure    */
  4673.  
  4674. #ifndef PFAILURE
  4675. #define    PFAILURE            255
  4676. #endif
  4677.  
  4678. /* Warning codes */
  4679.  
  4680. #define PNOWARN             0    /* No warning indicated         */
  4681. #define PWARN_OUT_OF_DATE     1    /* Software is out of date       */
  4682. #define PWARN_MSG_FROM_SERVER     2      /* Warning in p_warn_string      */
  4683. #define PWARN_UNRECOGNIZED_RESP  3    /* Unrecognized line in response */
  4684. #define PWARNING           255    /* Warning in p_warn_string      */
  4685. $EOD
  4686. $!
  4687. $CREATE [.archie]pfs.h
  4688. $DECK
  4689. /*
  4690.  * Copyright (c) 1989, 1990, 1991 by the University of Washington
  4691.  *
  4692.  * For copying and distribution information, please see the file
  4693.  * <copyright.h>.
  4694.  */
  4695.  
  4696. #include <copyright.h>
  4697.  
  4698. #ifdef VMS
  4699. # include <vms.h>
  4700. #else /* not VMS */
  4701. # ifndef _TYPES_
  4702. #  include <sys/types.h>
  4703. # endif /* _TYPES_ */
  4704. # ifndef IN_H
  4705. #  include <netinet/in.h> 
  4706. #  define IN_H
  4707. # endif
  4708. #endif /* VMS */
  4709.  
  4710. #ifndef NULL
  4711. # ifdef MSDOS
  4712. #  include <stdio.h>
  4713. # else
  4714. #  define NULL 0
  4715. # endif /* MSDOS */
  4716. #endif /* NULL */
  4717.  
  4718. #define        PFS_RELEASE    "Beta.4.2E"
  4719. #define        PFS_SW_ID    "B42E"
  4720.  
  4721. /* moved up for vdir_init */
  4722. #define ZERO(p)        bzero((char *)(p), sizeof(*(p)))
  4723.  
  4724. /* General Definitions */
  4725.  
  4726. #define        MAX_PTXT_LEN    1250     /* Max length of PTEXT structure   */
  4727. #define        MAX_PTXT_HDR    32       /* Max offset for start            */
  4728. #define        P_ERR_STRING_SZ 100     /* Size of error string        */
  4729. #define        MAX_VPATH    1024     /* Max length of virtual pathname  */
  4730.  
  4731. /* Definition of text structure used to pass text around */
  4732.  
  4733. struct ptext {
  4734.     int            length;          /* Length of text (from start)    */
  4735.     char        *start;          /* Start of text            */
  4736.     char        dat[MAX_PTXT_LEN+2*MAX_PTXT_HDR];/* The data itself */
  4737.     unsigned long     mbz;          /* ZERO to catch runaway strings  */
  4738.     struct ptext    *previous;        /* Previous element in list       */
  4739.     struct ptext    *next;          /* Next element in linked list    */
  4740.     int            seq;          /* Sequence Number            */
  4741. };
  4742.  
  4743. typedef struct ptext *PTEXT;
  4744. typedef struct ptext PTEXT_ST;
  4745.  
  4746. /* Request structure: maintains information about server requests */
  4747. struct preq {
  4748.     int            cid;          /* Connection ID                  */
  4749.     short        priority;      /* Connection priority            */
  4750.     int            pf_priority;      /* Priority assigned by pri_func  */
  4751.     int            recv_tot;      /* Total # of packets received    */
  4752.     int            trns_tot;      /* Total # of packets to transmit */
  4753.     struct ptext    *cpkt;          /* Current packet being filled in */
  4754.     struct ptext    *recv;          /* Received packets               */
  4755.     struct ptext    *trns;          /* Transmitted packets            */
  4756.     int            rcvd_thru;      /* Received all packets through # */
  4757.     struct preq        *previous;        /* Previous element in list       */
  4758.     struct preq        *next;          /* Next element in linked list    */
  4759.     struct sockaddr_in    fromto;       /* Sender/Destination            */
  4760. };
  4761.  
  4762. typedef struct preq *PREQ;
  4763. typedef struct preq PREQ_ST;
  4764.  
  4765.  
  4766. /* Definition of structure containing information on virtual link */
  4767.  
  4768. struct vlink {
  4769.     int            dontfree;      /* Flag: don't free this link     */
  4770.     char        *name;          /* Component of path name        */
  4771.     char        linktype;      /* L = Link, U = Union, N= Native */
  4772.     int            expanded;      /* Has a union link been expanded */
  4773.     char        *type;            /* Type of object pointed to      */
  4774.     struct vlink    *filters;      /* Filters associated with link   */
  4775.     struct vlink    *replicas;      /* Replicas (* see comment below) */
  4776.     char        *hosttype;      /* Type of hostname            */
  4777.     char        *host;          /* Files physical location        */
  4778.     char        *nametype;      /* Type of filename            */
  4779.     char        *filename;      /* System level filename        */
  4780.     long        version;      /* Version number of destination  */
  4781.     long        f_magic_no;      /* File's magic number        */
  4782.     struct acl        *acl;          /* ACL for link            */
  4783.     long        dest_exp;      /* Expiration for dest of link    */
  4784.     long        link_exp;      /* Expiration of link itself      */
  4785.     char        *args;          /* Arguments if this is a filter  */
  4786.     struct pattrib    *lattrib;      /* Attributes associated w/ link  */
  4787.     struct pfile    *f_info;      /* Info to be assoicated w/ file  */
  4788.     struct vlink    *previous;        /* Previous elt in linked list    */
  4789.     struct vlink    *next;          /* Next element in linked list    */
  4790. };
  4791.  
  4792. typedef struct vlink *VLINK;
  4793. typedef struct vlink VLINK_ST;
  4794.  
  4795. /* * Note that vlink->replicas is not really a list of replicas of the  */
  4796. /*   object.  Instead, it is a list of the objects returned during name */
  4797. /*   resolution that share the same name as the current object.  Such   */
  4798. /*   an object should only be considered a replica if it also shares    */
  4799. /*   the same non-zero magic number.                                    */
  4800.  
  4801. /* Definition of structure continiaing virtual directory information    */
  4802.  
  4803. struct vdir {
  4804.     int            version;      /* Version of local directory fmt  */
  4805.     int            inc_native;      /* Include the native directory    */
  4806.     long        magic_no;      /* Magic number of current file    */
  4807.     struct acl        *dacl;            /* Default acl for links in dir    */
  4808.     struct pfile    *f_info;      /* Directory file info             */
  4809.     struct vlink    *links;          /* The directory entries         */
  4810.     struct vlink    *lastlink;      /* Last directory entry            */
  4811.     struct vlink    *ulinks;      /* The entries for union links     */
  4812.     struct vdir        *previous;        /* Previous element in linked list */
  4813.     struct vdir        *next;          /* Next element in linked list     */
  4814. };
  4815.  
  4816. typedef struct vdir *PVDIR;
  4817. typedef struct vdir VDIR_ST;
  4818.  
  4819. /* Initialize directory */
  4820. #define vdir_init(dir)  ZERO(dir)
  4821. /* XXX: was
  4822.  
  4823.   dir->version = 0;     dir->inc_native = 0; \
  4824.   dir->magic_no = 0;    dir->f_info = NULL; \
  4825.   dir->links = NULL;    dir->lastlink = NULL; \
  4826.   dir->ulinks = NULL;   dir->dacl = NULL; \
  4827.   dir->previous = NULL; dir->next = NULL;
  4828. */
  4829.  
  4830. #define vdir_copy(d1,d2) d2->version = d1->version; \
  4831.                          d2->inc_native = d1->inc_native; \
  4832.                          d2->magic_no = d1->magic_no; \
  4833.                  d2->f_info = d1->f_info; \
  4834.                          d2->links = d1->links; \
  4835.                          d2->lastlink = d1->lastlink; \
  4836.                          d2->ulinks = d1->ulinks; \
  4837.                          d2->dacl = d1->dacl; \
  4838.                          d2->previous = d1->previous; \
  4839.                          d2->next = d1->next; 
  4840.                          
  4841. /* Values of ->inc_native in vdir structure */
  4842. #define VDIN_REALONLY    -1   /* Include native files, but not . and ..       */
  4843. #define VDIN_NONATIVE     0   /* Do not include files from native directory   */
  4844. #define VDIN_INCLNATIVE     1   /* Include files from native directory          */
  4845. #define VDIN_NATIVEONLY  2   /* All entries in directory are from native dir */
  4846. #define VDIN_PSEUDO      3   /* Directory is not real                        */
  4847.  
  4848.  
  4849. /* Definition of structure containing information on a specific file */
  4850.  
  4851. union avalue {
  4852.     char        *ascii;        /* Character string                */
  4853.     struct vlink    *link;        /* A link               */
  4854. };
  4855.  
  4856.  
  4857. struct pattrib {
  4858.     char        precedence;    /* Precedence for link attribute   */
  4859.     char        *aname;        /* Name of the attribute           */
  4860.     char        *avtype;    /* Type of the attribute value     */
  4861.     union avalue    value;        /* Attribute Value                 */
  4862.     struct pattrib    *previous;      /* Previous element in linked list */
  4863.     struct pattrib    *next;        /* Next element in linked list     */
  4864. };
  4865.  
  4866. typedef struct pattrib *PATTRIB;
  4867. typedef struct pattrib PATTRIB_ST;
  4868.  
  4869. #define     ATR_PREC_OBJECT  'O'   /* Authoritative answer for object */
  4870. #define     ATR_PREC_LINK    'L'   /* Authoritative answer for link   */
  4871. #define     ATR_PREC_CACHED  'C'   /* Object info cached w/ link      */
  4872. #define     ATR_PREC_REPLACE 'R'   /* From link (replaces O)          */
  4873. #define     ATR_PREC_ADD     'A'   /* From link (additional value)    */
  4874.  
  4875. /* **** Incomplete **** */
  4876. struct pfile {
  4877.     int            version;      /* Version of local finfo format   */
  4878.     long        f_magic_no;      /* Magic number of current file    */
  4879.     long        exp;          /* Expiration date of timeout      */
  4880.     long        ttl;          /* Time to live after reference    */
  4881.     long        last_ref;      /* Time of last reference          */
  4882.     struct vlink    *forward;      /* List of forwarding pointers     */
  4883.     struct vlink    *backlinks;      /* Partial list of back links      */
  4884.     struct pattrib    *attributes;      /* List of file attributes         */
  4885.     struct pfile    *previous;        /* Previous element in linked list */
  4886.     struct pfile    *next;          /* Next element in linked list     */
  4887. };
  4888.  
  4889. typedef struct pfile *PFILE;
  4890. typedef struct pfile PFILE_ST;
  4891.  
  4892. /* Definition of structure contining an access control list entry */
  4893.  
  4894. struct acl {
  4895.     int            acetype;      /* Access Contol Entry type       */
  4896.     char        *atype;           /* Authentication type            */
  4897.     char        *rights;          /* Rights                         */
  4898.     char        *principals;      /* Authorized principals          */
  4899.     struct restrict     *restrictions;    /* Restrictions on use            */
  4900.     struct acl        *previous;        /* Previous elt in linked list    */
  4901.     struct acl        *next;          /* Next element in linked list    */
  4902. };
  4903. typedef struct acl *ACL;
  4904. typedef struct acl ACL_ST;
  4905.  
  4906. #define ACL_NONE        0         /* Nobody authorized by ths entry */
  4907. #define ACL_DEFAULT        1         /* System default                 */
  4908. #define ACL_SYSTEM        2         /* System administrator           */
  4909. #define ACL_OWNER               3         /* Directory owner                */
  4910. #define ACL_DIRECTORY           4         /* Same as directory              */
  4911. #define ACL_ANY                 5         /* Any user                       */
  4912. #define ACL_AUTHENT             6         /* Authenticated principal        */
  4913. #define ACL_LGROUP              7         /* Local group                    */
  4914. #define ACL_GROUP               8         /* External group                 */
  4915. #define ACL_ASRTHOST            10        /* Check host and asserted userid */
  4916. #define ACL_TRSTHOST            11        /* ASRTHOST from privileged port  */
  4917.  
  4918.  
  4919. /* Definition of structure contining access restrictions */
  4920. /* for future extensions                                 */
  4921. struct restrict {
  4922.     struct acl        *previous;        /* Previous elt in linked list    */
  4923.     struct acl        *next;          /* Next element in linked list    */
  4924. };
  4925.  
  4926. /* Definitions for send_to_dirsrv */
  4927. #define    CLIENT_DIRSRV_TIMEOUT        4    /* time between retries      */
  4928. #define CLIENT_DIRSRV_BACKOFF(x)  (2 * x)    /* Backoff algorithm         */
  4929. #define CLIENT_DIRSRV_RETRY        3    /* retry this many times     */
  4930.  
  4931. /* Definitions for rd_vlink and rd_vdir */
  4932. #define        SYMLINK_NESTING 10       /* Max nesting depth for sym links */
  4933.  
  4934. /* Definition fo check_acl */
  4935. #define        ACL_NESTING     10       /* Max depth for ACL group nesting */
  4936.  
  4937. /* Flags for mk_vdir */
  4938. #define         MKVD_LPRIV     1   /* Minimize privs for creator in new ACL    */
  4939.  
  4940. /* Flags for get_vdir */
  4941. #define         GVD_UNION      0    /* Do not expand union links              */
  4942. #define      GVD_EXPAND     1   /* Expand union links locally             */
  4943. #define         GVD_LREMEXP    3   /* Request remote expansion of local links   */
  4944. #define         GVD_REMEXP     7   /* Request remote expansion of all links     */
  4945. #define         GVD_VERIFY     8    /* Only verify args are for a directory      */
  4946. #define      GVD_FIND       16   /* Stop expanding when match is found        */
  4947. #define         GVD_ATTRIB    32   /* Request attributes from remote server     */
  4948. #define         GVD_NOSORT       64   /* Do not sort links when adding to dir      */
  4949.  
  4950. /* Flags for rd_vdir */
  4951. #define         RVD_UNION      GVD_UNION
  4952. #define         RVD_EXPAND     GVD_EXPAND 
  4953. #define         RVD_LREMEXP    GVD_LREMEXP
  4954. #define         RVD_REMEXP     GVD_REMEXP
  4955. #define         RVD_DFILE_ONLY GVD_VERIFY /* Only return ptr to dir file        */
  4956. #define      RVD_FIND       GVD_FIND   
  4957. #define      RVD_ATTRIB     GVD_ATTRIB
  4958. #define         RVD_NOSORT        GVD_NOSORT
  4959. #define         RVD_NOCACHE    128
  4960.  
  4961. /* Flags for add_vlink */
  4962. #define         AVL_UNION      1   /* Link is a union link                      */
  4963.  
  4964. /* Flags for vl_insert */
  4965. #define         VLI_NOCONFLICT 0   /* Do not insert links w/ conflicting names  */
  4966. #define      VLI_ALLOW_CONF 1   /* Allow links with conflicting names        */
  4967. #define         VLI_NOSORT     2   /* Allow conflicts and don't sort            */
  4968.  
  4969. /* Flags for mapname */
  4970. #define      MAP_READWRITE  0   /* Named file to be read and written         */
  4971. #define         MAP_READONLY   1   /* Named file to be read only                */
  4972.  
  4973. /* Flags for modify_acl */
  4974. #define         MACL_NOSYSTEM   0x01
  4975. #define      MACL_NOSELF     0x02
  4976. #define      MACL_DEFAULT    0x08
  4977. #define      MACL_SET        0x0C
  4978. #define      MACL_INSERT     0x14
  4979. #define      MACL_DELETE     0x10
  4980. #define      MACL_ADD        0x1C
  4981. #define      MACL_SUBTRACT   0x18
  4982. #define      MACL_LINK       0x00
  4983. #define      MACL_DIRECTORY  0x20
  4984. #define      MACL_OBJECT     0x60
  4985. #define      MACL_INCLUDE    0x40
  4986.  
  4987. #define      MACL_OP    (MACL_DEFAULT|MACL_SET|MACL_INSERT|\
  4988.              MACL_DELETE|MACL_ADD|MACL_SUBTRACT)
  4989.  
  4990. #define      MACL_OTYPE (MACL_LINK|MACL_DIRECTORY|MACL_OBJECT|MACL_INCLUDE)
  4991.  
  4992. /* Flags for dsrdir */
  4993. #define DSRD_ATTRIBUTES                      0x1 /* Fill in attributes for links */
  4994.  
  4995. /* Access methods returned by Pget_am */
  4996. #define P_AM_ERROR            0
  4997. #define P_AM_FTP            1
  4998. #define P_AM_AFTP            2  /* Anonymous FTP  */
  4999. #define P_AM_NFS            4
  5000. #define P_AM_KNFS            8  /* Kerberized NFS */
  5001. #define P_AM_AFS               16
  5002.  
  5003. /* Return codes */
  5004.  
  5005. #define        PSUCCESS    0
  5006. #define        PFAILURE    255
  5007.  
  5008. /* Hush up warnings.  */
  5009. void vllfree();
  5010.  
  5011. /* Procedures in libpfs.a */
  5012.  
  5013. char *pget_wdhost(), *pget_wdfile(), *pget_wd(), *pget_hdhost();
  5014. char *pget_hdfile(), *pget_hd(), *pget_rdhost(), *pget_rdfile();
  5015. char *pget_dhost(), *pget_dfile(), *pget_vsname(), *nlsindex();
  5016. char *sindex(), *strtok(), *nxtline(), *unquote(), *stcopy();
  5017. char *stcopyr(), *readheader(), *month_sname();
  5018.  
  5019. long        asntotime();
  5020. void        procquery();
  5021.  
  5022. PTEXT        ptalloc();
  5023. PTEXT        dirsend();
  5024. void        ptfree();
  5025. void        ptlfree();
  5026.  
  5027. PREQ        pralloc();
  5028. PREQ        get_next_request();
  5029.  
  5030. VLINK        rd_slink();
  5031. VLINK        rd_vlink();
  5032. VLINK        vl_delete();
  5033. VLINK        vlalloc();
  5034. VLINK        vlcopy();
  5035. void        vlfree();
  5036.  
  5037. PFILE        pfalloc();
  5038.  
  5039. PATTRIB         parse_attribute();
  5040. PATTRIB         atalloc();
  5041. PATTRIB     pget_at();
  5042. void        atfree();
  5043. void        atlfree();
  5044.  
  5045. ACL             acalloc();
  5046. ACL             get_acl();
  5047.  
  5048. void        stfree();
  5049.  
  5050. /* Miscellaneous useful definitions */
  5051. #ifndef TRUE
  5052. #define TRUE        1
  5053. #define FALSE        0
  5054. #endif
  5055.  
  5056. #define AUTHORIZED      1
  5057. #define NOT_AUTHORIZED  0
  5058. #define NEG_AUTHORIZED  -1
  5059.  
  5060. #ifndef NULL
  5061. #define NULL        0
  5062. #endif
  5063.  
  5064. #define FAILED        -1
  5065. $EOD
  5066. $!
  5067. $CREATE [.archie]pmachine.h
  5068. $DECK
  5069. /*
  5070.  * Miscellaneous system dependencies.
  5071.  *
  5072.  * I kept the name pmachine.h because it was already in all of the files...this
  5073.  * barely resembles the pmachine.h that comes with the real Prospero, tho.
  5074.  */
  5075.  
  5076. #ifdef u3b2
  5077. # define USG
  5078. # define NOREGEX
  5079. # define MAXPATHLEN 1024    /* There's no maxpathlen in any 3b2 .h file.  */
  5080. #endif
  5081.  
  5082. #ifdef hpux
  5083. # ifndef bcopy
  5084. #  define FUNCS            /* HP/UX 8.0 has the fns.  */
  5085. # endif
  5086. # define NOREGEX
  5087. # define NEED_STRING_H
  5088. #endif
  5089.  
  5090. #if defined(USG) || defined(SYSV)
  5091. # define FUNCS
  5092. #endif
  5093.  
  5094. #ifdef ISC
  5095. # define FUNCS
  5096. # define STRSPN
  5097. # define NOREGEX
  5098. #endif
  5099.  
  5100. #ifdef CUTCP
  5101. # define FUNCS
  5102. # define NOREGEX
  5103. # define NEED_STRING_H
  5104. # define SELECTARG int
  5105. # define MSDOS
  5106. #endif
  5107.  
  5108. #ifdef _AUX_SOURCE
  5109. # define AUX
  5110. # define NOREGEX
  5111. # define NBBY 8    /* Number of bits in a byte.  */
  5112. # define long Fd_mask;
  5113. # define NFDBITS (sizeof(Fd_mask) * NBBY)    /* bits per mask */
  5114. #endif
  5115.  
  5116. #ifdef OS2
  5117. # define NOREGEX
  5118. # include <pctcp.h>
  5119. #endif
  5120. #ifdef MSDOS
  5121. # define USG
  5122. # define NOREGEX
  5123. # include <string.h>
  5124. # include <stdlib.h>
  5125. #endif
  5126.  
  5127. #ifdef _AIX
  5128. # ifdef u370
  5129. #  define FUNCS
  5130. # endif /* AIX/370 */
  5131. # define _NONSTD_TYPES
  5132. # define _BSD_INCLUDES
  5133. # define NEED_STRING_H
  5134. # define NEED_SELECT_H
  5135. # define NEED_TIME_H
  5136. #endif
  5137.  
  5138. /* ==== */
  5139. #ifdef FUNCS
  5140. # define index        strchr
  5141. /* According to mycroft. */
  5142. # ifdef _IBMR2
  5143. char *strchr();
  5144. # endif
  5145. # define rindex        strrchr
  5146. # ifndef _AUX_SOURCE
  5147. #  define bcopy(a,b,n)    memcpy(b,a,n)
  5148. #  define bzero(a,n)    memset(a,0,n)
  5149. # ifdef _IBMR2
  5150. char *memset();
  5151. # endif
  5152. # endif
  5153. #endif
  5154.  
  5155. #if defined(_IBMR2) || defined(_BULL_SOURCE)
  5156. # define NEED_SELECT_H
  5157. #endif
  5158. #if defined(USG) || defined(UTS)
  5159. # define NEED_STRING_H
  5160. #endif
  5161. #if defined(USG) || defined(UTS) || defined(_AUX_SOURCE)
  5162. # define NEED_TIME_H
  5163. # ifdef UTS
  5164. #  define WANT_BOTH_TIME
  5165. # endif
  5166. #endif
  5167.  
  5168. #ifdef VMS
  5169. /* Get the system status stuff.  */
  5170. # include <ssdef.h>
  5171. #endif /* VMS */
  5172.  
  5173. /*
  5174.  * FD_SET: lib/pfs/dirsend.c, user/vget/ftp.c
  5175.  */
  5176. #ifndef CUTCP
  5177.  
  5178. #define SELECTARG fd_set
  5179. #if !defined(FD_SET) && !defined(VMS) && !defined(NEED_SELECT_H)
  5180. #define    FD_SETSIZE    32
  5181. #define    FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
  5182. #define    FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
  5183. #define    FD_ISSET(n, p)    ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
  5184. #define FD_ZERO(p)    bzero((char *)(p), sizeof(*(p)))
  5185. #endif
  5186.  
  5187. #endif /* not CUTCP */
  5188. $EOD
  5189. $!
  5190. $CREATE [.archie]pprot.h
  5191. $DECK
  5192. /*
  5193.  * Copyright (c) 1989, 1990, 1991 by the University of Washington
  5194.  *
  5195.  * For copying and distribution information, please see the file
  5196.  * <copyright.h>.
  5197.  */
  5198.  
  5199. #include <copyright.h>
  5200.  
  5201. #ifndef MAXPATHLEN
  5202. # ifdef VMS
  5203. #  define MAXPATHLEN 32
  5204. # else /* not VMS */
  5205. #  if defined(MSDOS) && !defined(OS2)
  5206. #   define MAXPATHLEN 255
  5207. #  else /* not MSDOS */
  5208. #   ifdef ISC
  5209. #    define MAXPATHLEN 512
  5210. #   else /* not Interactive..normal! (gasp) */
  5211. #    include <sys/param.h>
  5212. #   endif /* ISC */
  5213. #  endif /* MSDOS && !OS2 */
  5214. # endif /* VMS */
  5215. #endif
  5216.  
  5217. /* Protocol Definitions */
  5218.  
  5219. #define           VFPROT_VNO    1      /* Protocol Version Number           */
  5220.  
  5221. #define           DIRSRV_PORT      1525   /* Server port used if not in srvtab */
  5222. #define        PROSPERO_PORT    191    /* Officially assigned prived port   */
  5223. #define           PROS_FIRST_PRIVP 901    /* First privileged port to try      */
  5224. #define        PROS_NUM_PRIVP   20     /* Number of privileged ports to try */
  5225.  
  5226. #define           MAXPKT            1024   /* Max size of response from server  */
  5227. #define           SEQ_SIZE        32     /* Max size of sequence text in resp */ 
  5228. #define           MAX_DIR_LINESIZE 160+MAXPATHLEN /* Max linesize in directory */
  5229.  
  5230. #define           MAX_FWD_DEPTH    20     /* Max fwd pointers to follow        */
  5231.  
  5232. #define S_AD_SZ        sizeof(struct sockaddr_in)
  5233.  
  5234. /* Replacement for strtok that doesn't keep state.  Both the variable  */
  5235. /* S and the variable S_next must be defined.  To initialize, assign   */
  5236. /* the string to be stepped through to S_next, then call get_token on  */
  5237. /* S.  The first token will be in S, and S_next will point to the next */
  5238. /* token.  Like strtok, this macro does modify the string passed to it */
  5239. #ifdef __GNUC__
  5240. #define get_token(S,C) \
  5241.   do { \
  5242.     S = S##_next; \
  5243.     if(S) { \
  5244.      while(*S == C) S++; \
  5245.      S##_next = index(S,C); \
  5246.      if(S##_next) *(S##_next++) = '\0'; \
  5247.      if(!*S) S = NULL; \
  5248.     } \
  5249.   } while (0)
  5250. #else
  5251. #define get_token(S,C) \
  5252.     S = S/**/_next; \
  5253.   do { \
  5254.     if(S) { \
  5255.      while(*S == C) S++; \
  5256.      S/**/_next = index(S,C); \
  5257.      if(S/**/_next) *(S/**/_next++) = '\0'; \
  5258.      if(!*S) S = NULL; \
  5259.     } \
  5260.   } while (0)
  5261. #endif /* __GNUC__ */
  5262. $EOD
  5263. $!
  5264. $CREATE [.archie]procquery.c
  5265. $DECK
  5266. /*
  5267.  * procquery.c : Routines for processing results from Archie
  5268.  *
  5269.  * Originally part of the Prospero Archie client by Cliff Neuman (bcn@isi.edu).
  5270.  * Modified by Brendan Kehoe (brendan@cs.widener.edu).
  5271.  * Re-modified by George Ferguson (ferguson@cs.rochester.edu).
  5272.  *
  5273.  * Copyright (c) 1991 by the University of Washington
  5274.  *
  5275.  * For copying and distribution information, please see the file
  5276.  * <copyright.h>.
  5277.  *
  5278.  */
  5279.  
  5280. #include <copyright.h>
  5281. #include <stdio.h>
  5282. #include <pfs.h>
  5283. #include <perrno.h>
  5284. #include <pmachine.h>
  5285. #include <archie.h>
  5286.  
  5287. #ifdef NEED_TIME_H
  5288. # include <time.h>
  5289. #else
  5290. # ifndef VMS
  5291. #  include <sys/time.h>
  5292. # endif
  5293. #endif
  5294.  
  5295. extern int client_dirsrv_timeout,client_dirsrv_retry;    /* dirsend.c */
  5296. extern char *progname;
  5297.  
  5298.  
  5299. /*
  5300.  * Functions defined here
  5301.  */
  5302. void display_link(), procquery();
  5303.  
  5304. /*
  5305.  * Data defined here
  5306.  */
  5307. extern int pwarn, perrno;
  5308. #ifdef DEBUG
  5309. int pfs_debug;
  5310. #endif
  5311. static struct tm *presenttime;
  5312. static char lastpath[MAX_VPATH] = "\001";
  5313. static char lasthost[MAX_VPATH] = "\001";
  5314.  
  5315. /*    -    -    -    -    -    -    -    -    */
  5316. /*
  5317.  * display_link : Prints the contents of the given virtual link. If
  5318.  *    listflag is 0, then this uses last{host,path} to save state
  5319.  *    between calls for a less verbose output. If listflag is non-zero
  5320.  *    then all information is printed every time.
  5321.  */
  5322. void
  5323. display_link(l,listflag)
  5324. VLINK l;
  5325. int listflag;
  5326. {
  5327.     PATTRIB     ap;
  5328.     char    linkpath[MAX_VPATH];
  5329.     int        dirflag = 0;
  5330. #ifdef MSDOS
  5331.     unsigned long size = 0L;
  5332. #else
  5333.     int        size = 0;
  5334. #endif
  5335.     char    *modes = "";
  5336.     char    archie_date[20];
  5337.     char    *gt_date = "";
  5338.     int        gt_year = 0;
  5339.     int        gt_mon = 0;
  5340.     int        gt_day = 0;
  5341.     int        gt_hour = 0;
  5342.     int        gt_min = 0;
  5343.     
  5344.     /* Initialize local buffers */
  5345.     *archie_date = '\0';
  5346.  
  5347.     /* Remember if we're looking at a directory */
  5348.     if (sindex(l->type,"DIRECTORY"))
  5349.     dirflag = 1;
  5350.     else
  5351.     dirflag = 0;
  5352.     
  5353.     /* Extract the linkpath from the filename */
  5354.     strcpy(linkpath,l->filename);
  5355.     *(linkpath + (strlen(linkpath) - strlen(l->name) - 1)) = '\0';
  5356.     
  5357.     /* Is this a new host? */
  5358.     if (strcmp(l->host,lasthost) != 0) {
  5359.     if (!listflag)
  5360.         printf("\nHost %s\n\n",l->host);
  5361.     strcpy(lasthost,l->host);
  5362.     *lastpath = '\001';
  5363.     }
  5364.     
  5365.     /* Is this a new linkpath (location)? */
  5366.     if(strcmp(linkpath,lastpath) != 0) {
  5367.     if (!listflag)
  5368.         printf("    Location: %s\n",(*linkpath ? linkpath : "/"));
  5369.     strcpy(lastpath,linkpath);
  5370.     }
  5371.     
  5372.     /* Parse the attibutes of this link */
  5373.     for (ap = l->lattrib; ap; ap = ap->next) {
  5374.     if (strcmp(ap->aname,"SIZE") == 0) {
  5375. #ifdef MSDOS
  5376.         sscanf(ap->value.ascii,"%lu",&size);
  5377. #else
  5378.         sscanf(ap->value.ascii,"%d",&size);
  5379. #endif
  5380.     } else if(strcmp(ap->aname,"UNIX-MODES") == 0) {
  5381.         modes = ap->value.ascii;
  5382.     } else if(strcmp(ap->aname,"LAST-MODIFIED") == 0) {
  5383.         gt_date = ap->value.ascii;
  5384.         sscanf(gt_date,"%4d%2d%2d%2d%2d",>_year,
  5385.            >_mon, >_day, >_hour, >_min);
  5386.         if ((12 * (presenttime->tm_year + 1900 - gt_year) + 
  5387.                     presenttime->tm_mon - gt_mon) > 6) 
  5388.         sprintf(archie_date,"%s %2d %4d",month_sname(gt_mon),
  5389.             gt_day, gt_year);
  5390.         else
  5391.         sprintf(archie_date,"%s %2d %02d:%02d",month_sname(gt_mon),
  5392.              gt_day, gt_hour, gt_min);
  5393.     }
  5394.     }
  5395.     
  5396.     /* Print this link's information */
  5397.     if (listflag)
  5398. #if defined(MSDOS)
  5399.     printf("%s %6lu %s %s%s\n",gt_date,size,l->host,l->filename,
  5400.            (dirflag ? "/" : ""));
  5401. #else
  5402.     printf("%s %6d %s %s%s\n",gt_date,size,l->host,l->filename,
  5403.            (dirflag ? "/" : ""));
  5404. #endif
  5405.     else
  5406. #ifdef MSDOS
  5407.     printf("      %9s %s %10lu  %s  %s\n",(dirflag ? "DIRECTORY" : "FILE"),
  5408.                     modes,size,archie_date,l->name);
  5409. #else
  5410.     printf("      %9s %s %10d  %s  %s\n",(dirflag ? "DIRECTORY" : "FILE"),
  5411.                     modes,size,archie_date,l->name);
  5412. #endif /* MSDOS */
  5413.  
  5414.  
  5415.     /* Free the attibutes */
  5416.     atlfree(l->lattrib);
  5417.     l->lattrib = NULL;
  5418. }
  5419.  
  5420. /*    -    -    -    -    -    -    -    -    */
  5421. /*
  5422.  * procquery : Process the given query and display the results. If
  5423.  *    sortflag is non-zero, then the results are sorted by increasing
  5424.  *    date, else by host/filename. If listflag is non-zero then each
  5425.  *    entry is printed on a separate, complete line. Note that listflag
  5426.  *    is ignored by xarchie.
  5427.  */
  5428. void
  5429. procquery(host,str,max_hits,offset,query_type,sortflag,listflag)
  5430. char *host,*str;
  5431. int max_hits,offset;
  5432. char query_type;
  5433. int sortflag,listflag;
  5434. {
  5435.     VLINK l;
  5436.     long now;
  5437.     extern int rdgram_priority;
  5438.  
  5439.     /* initialize data structures for this query */
  5440.     (void)time(&now);
  5441.     presenttime = localtime(&now);
  5442.  
  5443.     /* Do the query */
  5444.     if (sortflag == 1)
  5445.     l = archie_query(host,str,max_hits,offset,query_type,AQ_INVDATECMP,0);
  5446.     else
  5447.     l = archie_query(host,str,max_hits,offset,query_type,NULL,0);
  5448.  
  5449.     /* Error? */
  5450.     if (perrno != PSUCCESS) {
  5451.     if (p_err_text[perrno]) {
  5452.         if (*p_err_string)
  5453.         fprintf(stderr, "%s: failed: %s - %s\n", progname,
  5454.                 p_err_text[perrno], p_err_string);
  5455.         else
  5456.             fprintf(stderr, "%s failed: %s\n", progname, p_err_text[perrno]);
  5457.     } else
  5458.         fprintf(stderr, "%s failed: Undefined error %d (prospero)", perrno);
  5459.     }
  5460.  
  5461.     /* Warning? */
  5462.     if (pwarn != PNOWARN) {
  5463.     if (*p_warn_string)
  5464.         fprintf(stderr, "%s: Warning! %s - %s\n", progname,
  5465.         p_warn_text[pwarn], p_warn_string);
  5466.     else
  5467.         fprintf(stderr, "%s: Warning! %s\n", progname, p_warn_text[pwarn]);
  5468.     }
  5469.  
  5470.  
  5471.     /* Display the results */
  5472.  
  5473.     if (l == (VLINK)NULL && pwarn == PNOWARN && perrno == PSUCCESS) {
  5474.     if (! listflag) puts ("No matches.");
  5475. #ifdef CUTCP
  5476.     netshut();
  5477. #endif
  5478.     exit (1);
  5479.     }
  5480.  
  5481.     *lasthost = '\001';
  5482.     *lastpath = '\001';
  5483.     while (l != NULL) {
  5484.     display_link(l,listflag);
  5485.     l = l->next;
  5486.     }
  5487. }
  5488. $EOD
  5489. $!
  5490. $CREATE [.archie]ptalloc.c
  5491. $DECK
  5492. /*
  5493.  * Copyright (c) 1989, 1990, 1991 by the University of Washington
  5494.  *
  5495.  * For copying and distribution information, please see the file
  5496.  * <copyright.h>.
  5497.  */
  5498.  
  5499. #include <copyright.h>
  5500. #include <stdio.h>
  5501.  
  5502. #include <pfs.h>
  5503. #include <pmachine.h> /* for correct definition of ZERO */
  5504. #ifdef MSDOS
  5505. # define free _pfree   /* otherwise we get conflicts with free() */
  5506. #endif
  5507.  
  5508. static PTEXT    free = NULL;
  5509. int         ptext_count = 0;
  5510. int        ptext_max = 0;
  5511.  
  5512. /*
  5513.  * ptalloc - allocate and initialize ptext structure
  5514.  *
  5515.  *    PTALLOC returns a pointer to an initialized structure of type
  5516.  *    PTEXT.  If it is unable to allocate such a structure, it
  5517.  *    returns NULL.
  5518.  */
  5519. PTEXT
  5520. ptalloc()
  5521.     {
  5522.     PTEXT    vt;
  5523.     if(free) {
  5524.         vt = free;
  5525.         free = free->next;
  5526.     }
  5527.     else {
  5528.         vt = (PTEXT) malloc(sizeof(PTEXT_ST));
  5529.         if (!vt) return(NULL);
  5530.         ptext_max++;
  5531.     }
  5532.     ptext_count++;
  5533.  
  5534.     /* nearly all parts are 0 [or NULL] */
  5535.     ZERO(vt);
  5536.     /* The offset is to leave room for additional headers */
  5537.     vt->start = vt->dat + MAX_PTXT_HDR;
  5538.  
  5539.     return(vt);
  5540.     }
  5541.  
  5542. /*
  5543.  * ptfree - free a VTEXT structure
  5544.  *
  5545.  *    VTFREE takes a pointer to a VTEXT structure and adds it to
  5546.  *    the free list for later reuse.
  5547.  */
  5548. void
  5549. ptfree(vt)
  5550.     PTEXT    vt;
  5551.     {
  5552.     vt->next = free;
  5553.     vt->previous = NULL;
  5554.     free = vt;
  5555.     ptext_count--;
  5556.     }
  5557.  
  5558. /*
  5559.  * ptlfree - free a VTEXT structure
  5560.  *
  5561.  *    VTLFREE takes a pointer to a VTEXT structure frees it and any linked
  5562.  *    VTEXT structures.  It is used to free an entrie list of VTEXT
  5563.  *    structures.
  5564.  */
  5565. void
  5566. ptlfree(vt)
  5567.     PTEXT    vt;
  5568.     {
  5569.     PTEXT    nxt;
  5570.  
  5571.     while(vt != NULL) {
  5572.         nxt = vt->next;
  5573.         ptfree(vt);
  5574.         vt = nxt;
  5575.     }
  5576.     }
  5577.  
  5578. $EOD
  5579. $!
  5580. $CREATE [.archie]rdgram.h
  5581. $DECK
  5582. /*
  5583.  * Copyright (c) 1991 by the University of Washington
  5584.  *
  5585.  * For copying and distribution information, please see the file
  5586.  * <copyright.h>.
  5587.  */
  5588.  
  5589. #include <copyright.h>
  5590.  
  5591. /* Queuing priorities for datagrams */
  5592. #define           RDGRAM_MAX_PRI   32765  /* Maximum user proiority          */
  5593. #define           RDGRAM_MAX_SPRI  32767  /* Maximum priority for system use */
  5594. #define           RDGRAM_MIN_PRI  -32765  /* Maximum user proiority          */
  5595. #define           RDGRAM_MIN_SPRI -32768  /* Maximum priority for system use */
  5596.  
  5597. int    rdgram_priority = 0;
  5598. $EOD
  5599. $!
  5600. $CREATE [.archie]regex.c
  5601. $DECK
  5602. #include <pmachine.h>
  5603.  
  5604. #ifdef NOREGEX
  5605. /*
  5606.  * These routines are BSD regex(3)/ed(1) compatible regular-expression
  5607.  * routines written by Ozan S. Yigit, Computer Science, York University.
  5608.  * Parts of the code that are not needed by Prospero have been removed,
  5609.  * but most of the accompanying information has been left intact. 
  5610.  * This file is to be included on those operating systems that do not
  5611.  * support re_comp and re_exec.
  5612.  */
  5613.  
  5614. /*
  5615.  * regex - Regular expression pattern matching
  5616.  *         and replacement
  5617.  *
  5618.  * by:  Ozan S. Yigit (oz@nexus.yorku.ca)
  5619.  *    Dept. of Computing Services
  5620.  *      York University
  5621.  *
  5622.  * These routines are the PUBLIC DOMAIN equivalents 
  5623.  * of regex routines as found in 4.nBSD UN*X, with minor
  5624.  * extensions.
  5625.  *
  5626.  * Modification history:
  5627.  *
  5628.  * $Log:    regex.c,v $
  5629.  * Revision 1.3  89/04/01  14:18:09  oz
  5630.  * Change all references to a dfa: this is actually an nfa.
  5631.  * 
  5632.  * Revision 1.2  88/08/28  15:36:04  oz
  5633.  * Use a complement bitmap to represent NCL.
  5634.  * This removes the need to have seperate 
  5635.  * code in the pmatch case block - it is 
  5636.  * just CCL code now.
  5637.  * 
  5638.  * Use the actual CCL code in the CLO
  5639.  * section of pmatch. No need for a recursive
  5640.  * pmatch call.
  5641.  * 
  5642.  * Use a bitmap table to set char bits in an
  5643.  * 8-bit chunk.
  5644.  * 
  5645.  * Routines:
  5646.  *      re_comp:        compile a regular expression into
  5647.  *                      a NFA.
  5648.  *
  5649.  *            char *re_comp(s)
  5650.  *            char *s;
  5651.  *
  5652.  *      re_exec:        execute the NFA to match a pattern.
  5653.  *
  5654.  *            int re_exec(s)
  5655.  *            char *s;
  5656.  *
  5657.  * Regular Expressions:
  5658.  *
  5659.  *      [1]     char    matches itself, unless it is a special
  5660.  *                      character (metachar): . \ [ ] * + ^ $
  5661.  *
  5662.  *      [2]     .       matches any character.
  5663.  *
  5664.  *      [3]     \       matches the character following it, except
  5665.  *            when followed by a left or right round bracket,
  5666.  *            a digit 1 to 9 or a left or right angle bracket. 
  5667.  *            (see [7], [8] and [9])
  5668.  *            It is used as an escape character for all 
  5669.  *            other meta-characters, and itself. When used
  5670.  *            in a set ([4]), it is treated as an ordinary
  5671.  *            character.
  5672.  *
  5673.  *      [4]     [set]   matches one of the characters in the set.
  5674.  *                      If the first character in the set is "^",
  5675.  *                      it matches a character NOT in the set, i.e. 
  5676.  *            complements the set. A shorthand S-E is 
  5677.  *            used to specify a set of characters S upto 
  5678.  *            E, inclusive. The special characters "]" and 
  5679.  *            "-" have no special meaning if they appear 
  5680.  *            as the first chars in the set.
  5681.  *                      examples:        match:
  5682.  *
  5683.  *                              [a-z]    any lowercase alpha
  5684.  *
  5685.  *                              [^]-]    any char except ] and -
  5686.  *
  5687.  *                              [^A-Z]   any char except uppercase
  5688.  *                                       alpha
  5689.  *
  5690.  *                              [a-zA-Z] any alpha
  5691.  *
  5692.  *      [5]     *       any regular expression form [1] to [4], followed by
  5693.  *                      closure char (*) matches zero or more matches of
  5694.  *                      that form.
  5695.  *
  5696.  *      [6]     +       same as [5], except it matches one or more.
  5697.  *
  5698.  *      [7]             a regular expression in the form [1] to [10], enclosed
  5699.  *                      as \(form\) matches what form matches. The enclosure
  5700.  *                      creates a set of tags, used for [8] and for
  5701.  *                      pattern substution. The tagged forms are numbered
  5702.  *            starting from 1.
  5703.  *
  5704.  *      [8]             a \ followed by a digit 1 to 9 matches whatever a
  5705.  *                      previously tagged regular expression ([7]) matched.
  5706.  *
  5707.  *    [9]    \<    a regular expression starting with a \< construct
  5708.  *        \>    and/or ending with a \> construct, restricts the
  5709.  *            pattern matching to the beginning of a word, and/or
  5710.  *            the end of a word. A word is defined to be a character
  5711.  *            string beginning and/or ending with the characters
  5712.  *            A-Z a-z 0-9 and _. It must also be preceded and/or
  5713.  *            followed by any character outside those mentioned.
  5714.  *
  5715.  *      [10]            a composite regular expression xy where x and y
  5716.  *                      are in the form [1] to [10] matches the longest
  5717.  *                      match of x followed by a match for y.
  5718.  *
  5719.  *      [11]    ^    a regular expression starting with a ^ character
  5720.  *        $    and/or ending with a $ character, restricts the
  5721.  *                      pattern matching to the beginning of the line,
  5722.  *                      or the end of line. [anchors] Elsewhere in the
  5723.  *            pattern, ^ and $ are treated as ordinary characters.
  5724.  *
  5725.  *
  5726.  * Acknowledgements:
  5727.  *
  5728.  *    HCR's Hugh Redelmeier has been most helpful in various
  5729.  *    stages of development. He convinced me to include BOW
  5730.  *    and EOW constructs, originally invented by Rob Pike at
  5731.  *    the University of Toronto.
  5732.  *
  5733.  * References:
  5734.  *              Software tools            Kernighan & Plauger
  5735.  *              Software tools in Pascal        Kernighan & Plauger
  5736.  *              Grep [rsx-11 C dist]            David Conroy
  5737.  *        ed - text editor        Un*x Programmer's Manual
  5738.  *        Advanced editing on Un*x    B. W. Kernighan
  5739.  *        regexp routines            Henry Spencer
  5740.  *
  5741.  * Notes:
  5742.  *
  5743.  *    This implementation uses a bit-set representation for character
  5744.  *    classes for speed and compactness. Each character is represented 
  5745.  *    by one bit in a 128-bit block. Thus, CCL always takes a 
  5746.  *    constant 16 bytes in the internal nfa, and re_exec does a single
  5747.  *    bit comparison to locate the character in the set.
  5748.  *
  5749.  * Examples:
  5750.  *
  5751.  *    pattern:    foo*.*
  5752.  *    compile:    CHR f CHR o CLO CHR o END CLO ANY END END
  5753.  *    matches:    fo foo fooo foobar fobar foxx ...
  5754.  *
  5755.  *    pattern:    fo[ob]a[rz]    
  5756.  *    compile:    CHR f CHR o CCL bitset CHR a CCL bitset END
  5757.  *    matches:    fobar fooar fobaz fooaz
  5758.  *
  5759.  *    pattern:    foo\\+
  5760.  *    compile:    CHR f CHR o CHR o CHR \ CLO CHR \ END END
  5761.  *    matches:    foo\ foo\\ foo\\\  ...
  5762.  *
  5763.  *    pattern:    \(foo\)[1-3]\1    (same as foo[1-3]foo)
  5764.  *    compile:    BOT 1 CHR f CHR o CHR o EOT 1 CCL bitset REF 1 END
  5765.  *    matches:    foo1foo foo2foo foo3foo
  5766.  *
  5767.  *    pattern:    \(fo.*\)-\1
  5768.  *    compile:    BOT 1 CHR f CHR o CLO ANY END EOT 1 CHR - REF 1 END
  5769.  *    matches:    foo-foo fo-fo fob-fob foobar-foobar ...
  5770.  * 
  5771.  */
  5772.  
  5773. #define MAXNFA  1024
  5774. #define MAXTAG  10
  5775.  
  5776. #define OKP     1
  5777. #define NOP     0
  5778.  
  5779. #define CHR     1
  5780. #define ANY     2
  5781. #define CCL     3
  5782. #define BOL     4
  5783. #define EOL     5
  5784. #define BOT     6
  5785. #define EOT     7
  5786. #define BOW    8
  5787. #define EOW    9
  5788. #define REF     10
  5789. #define CLO     11
  5790.  
  5791. #define END     0
  5792.  
  5793. /*
  5794.  * The following defines are not meant
  5795.  * to be changeable. They are for readability
  5796.  * only.
  5797.  *
  5798.  */
  5799. #define MAXCHR    128
  5800. #define CHRBIT    8
  5801. #define BITBLK    MAXCHR/CHRBIT
  5802. #define BLKIND    0170
  5803. #define BITIND    07
  5804.  
  5805. #define ASCIIB    0177
  5806.  
  5807. typedef /*unsigned*/ char CHAR;
  5808.  
  5809. static int  tagstk[MAXTAG];             /* subpat tag stack..*/
  5810. static CHAR nfa[MAXNFA];        /* automaton..       */
  5811. static int  sta = NOP;                   /* status of lastpat */
  5812.  
  5813. static CHAR bittab[BITBLK];        /* bit table for CCL */
  5814.                     /* pre-set bits...   */
  5815. static CHAR bitarr[] = {1,2,4,8,16,32,64,128};
  5816.  
  5817. static int internal_error;
  5818.  
  5819. static void
  5820. chset(c)
  5821. register CHAR c;
  5822. {
  5823.     bittab[((c) & BLKIND) >> 3] |= bitarr[(c) & BITIND];
  5824. }
  5825.  
  5826. #define badpat(x)    return (*nfa = END, x)
  5827. #define store(x)    *mp++ = x
  5828.  
  5829. char *     
  5830. re_comp(pat)
  5831. char *pat;
  5832. {
  5833.     register char *p;               /* pattern pointer   */
  5834.     register CHAR *mp = nfa;        /* nfa pointer       */
  5835.     register CHAR *lp;              /* saved pointer..   */
  5836.     register CHAR *sp = nfa;        /* another one..     */
  5837.  
  5838.     register int tagi = 0;          /* tag stack index   */
  5839.     register int tagc = 1;          /* actual tag count  */
  5840.  
  5841.     register int n;
  5842.     register CHAR mask;        /* xor mask -CCL/NCL */
  5843.     int c1, c2;
  5844.         
  5845.     if (!pat || !*pat)
  5846.         if (sta)
  5847.             return 0;
  5848.         else
  5849.             badpat("No previous regular expression");
  5850.     sta = NOP;
  5851.  
  5852.     for (p = pat; *p; p++) {
  5853.         lp = mp;
  5854.         switch(*p) {
  5855.  
  5856.         case '.':               /* match any char..  */
  5857.             store(ANY);
  5858.             break;
  5859.  
  5860.         case '^':               /* match beginning.. */
  5861.             if (p == pat)
  5862.                 store(BOL);
  5863.             else {
  5864.                 store(CHR);
  5865.                 store(*p);
  5866.             }
  5867.             break;
  5868.  
  5869.         case '$':               /* match endofline.. */
  5870.             if (!*(p+1))
  5871.                 store(EOL);
  5872.             else {
  5873.                 store(CHR);
  5874.                 store(*p);
  5875.             }
  5876.             break;
  5877.  
  5878.         case '[':               /* match char class..*/
  5879.             store(CCL);
  5880.  
  5881.             if (*++p == '^') {
  5882.                 mask = 0377;    
  5883.                 p++;
  5884.             }
  5885.             else
  5886.                 mask = 0;
  5887.  
  5888.             if (*p == '-')        /* real dash */
  5889.                 chset(*p++);
  5890.             if (*p == ']')        /* real brac */
  5891.                 chset(*p++);
  5892.             while (*p && *p != ']') {
  5893.                 if (*p == '-' && *(p+1) && *(p+1) != ']') {
  5894.                     p++;
  5895.                     c1 = *(p-2) + 1;
  5896.                     c2 = *p++;
  5897.                     while (c1 <= c2)
  5898.                         chset(c1++);
  5899.                 }
  5900. #ifdef EXTEND
  5901.                 else if (*p == '\\' && *(p+1)) {
  5902.                     p++;
  5903.                     chset(*p++);
  5904.                 }
  5905. #endif
  5906.                 else
  5907.                     chset(*p++);
  5908.             }
  5909.             if (!*p)
  5910.                 badpat("Missing ]");
  5911.  
  5912.             for (n = 0; n < BITBLK; bittab[n++] = (char) 0)
  5913.                 store(mask ^ bittab[n]);
  5914.     
  5915.             break;
  5916.  
  5917.         case '*':               /* match 0 or more.. */
  5918.         case '+':               /* match 1 or more.. */
  5919.             if (p == pat)
  5920.                 badpat("Empty closure");
  5921.             lp = sp;        /* previous opcode */
  5922.             if (*lp == CLO)        /* equivalence..   */
  5923.                 break;
  5924.             switch(*lp) {
  5925.  
  5926.             case BOL:
  5927.             case BOT:
  5928.             case EOT:
  5929.             case BOW:
  5930.             case EOW:
  5931.             case REF:
  5932.                 badpat("Illegal closure");
  5933.             default:
  5934.                 break;
  5935.             }
  5936.  
  5937.             if (*p == '+')
  5938.                 for (sp = mp; lp < sp; lp++)
  5939.                     store(*lp);
  5940.  
  5941.             store(END);
  5942.             store(END);
  5943.             sp = mp;
  5944.             while (--mp > lp)
  5945.                 *mp = mp[-1];
  5946.             store(CLO);
  5947.             mp = sp;
  5948.             break;
  5949.  
  5950.         case '\\':              /* tags, backrefs .. */
  5951.             switch(*++p) {
  5952.  
  5953.             case '(':
  5954.                 if (tagc < MAXTAG) {
  5955.                     tagstk[++tagi] = tagc;
  5956.                     store(BOT);
  5957.                     store(tagc++);
  5958.                 }
  5959.                 else
  5960.                     badpat("Too many \\(\\) pairs");
  5961.                 break;
  5962.             case ')':
  5963.                 if (*sp == BOT)
  5964.                     badpat("Null pattern inside \\(\\)");
  5965.                 if (tagi > 0) {
  5966.                     store(EOT);
  5967.                     store(tagstk[tagi--]);
  5968.                 }
  5969.                 else
  5970.                     badpat("Unmatched \\)");
  5971.                 break;
  5972.             case '<':
  5973.                 store(BOW);
  5974.                 break;
  5975.             case '>':
  5976.                 if (*sp == BOW)
  5977.                     badpat("Null pattern inside \\<\\>");
  5978.                 store(EOW);
  5979.                 break;
  5980.             case '1':
  5981.             case '2':
  5982.             case '3':
  5983.             case '4':
  5984.             case '5':
  5985.             case '6':
  5986.             case '7':
  5987.             case '8':
  5988.             case '9':
  5989.                 n = *p-'0';
  5990.                 if (tagi > 0 && tagstk[tagi] == n)
  5991.                     badpat("Cyclical reference");
  5992.                 if (tagc > n) {
  5993.                     store(REF);
  5994.                     store(n);
  5995.                 }
  5996.                 else
  5997.                     badpat("Undetermined reference");
  5998.                 break;
  5999. #ifdef EXTEND
  6000.             case 'b':
  6001.                 store(CHR);
  6002.                 store('\b');
  6003.                 break;
  6004.             case 'n':
  6005.                 store(CHR);
  6006.                 store('\n');
  6007.                 break;
  6008.             case 'f':
  6009.                 store(CHR);
  6010.                 store('\f');
  6011.                 break;
  6012.             case 'r':
  6013.                 store(CHR);
  6014.                 store('\r');
  6015.                 break;
  6016.             case 't':
  6017.                 store(CHR);
  6018.                 store('\t');
  6019.                 break;
  6020. #endif
  6021.             default:
  6022.                 store(CHR);
  6023.                 store(*p);
  6024.             }
  6025.             break;
  6026.  
  6027.         default :               /* an ordinary char  */
  6028.             store(CHR);
  6029.             store(*p);
  6030.             break;
  6031.         }
  6032.         sp = lp;
  6033.     }
  6034.     if (tagi > 0)
  6035.         badpat("Unmatched \\(");
  6036.     store(END);
  6037.     sta = OKP;
  6038.     return 0;
  6039. }
  6040.  
  6041.  
  6042. static char *bol;
  6043. static char *bopat[MAXTAG];
  6044. static char *eopat[MAXTAG];
  6045. char *pmatch();
  6046.  
  6047. /*
  6048.  * re_exec:
  6049.  *     execute nfa to find a match.
  6050.  *
  6051.  *    special cases: (nfa[0])    
  6052.  *        BOL
  6053.  *            Match only once, starting from the
  6054.  *            beginning.
  6055.  *        CHR
  6056.  *            First locate the character without
  6057.  *            calling pmatch, and if found, call
  6058.  *            pmatch for the remaining string.
  6059.  *        END
  6060.  *            re_comp failed, poor luser did not
  6061.  *            check for it. Fail fast.
  6062.  *
  6063.  *    If a match is found, bopat[0] and eopat[0] are set
  6064.  *    to the beginning and the end of the matched fragment,
  6065.  *    respectively.
  6066.  *
  6067.  */
  6068.  
  6069. int
  6070. re_exec(lp)
  6071. register char *lp;
  6072. {
  6073.     register char c;
  6074.     register char *ep = 0;
  6075.     register CHAR *ap = nfa;
  6076.  
  6077.     bol = lp;
  6078.  
  6079.     bopat[0] = 0;
  6080.     bopat[1] = 0;
  6081.     bopat[2] = 0;
  6082.     bopat[3] = 0;
  6083.     bopat[4] = 0;
  6084.     bopat[5] = 0;
  6085.     bopat[6] = 0;
  6086.     bopat[7] = 0;
  6087.     bopat[8] = 0;
  6088.     bopat[9] = 0;
  6089.  
  6090.     switch(*ap) {
  6091.  
  6092.     case BOL:            /* anchored: match from BOL only */
  6093.         ep = pmatch(lp,ap);
  6094.         break;
  6095.     case CHR:            /* ordinary char: locate it fast */
  6096.         c = *(ap+1);
  6097.         while (*lp && *lp != c)
  6098.             lp++;
  6099.         if (!*lp)        /* if EOS, fail, else fall thru. */
  6100.             return 0;
  6101.     default:            /* regular matching all the way. */
  6102.         while (*lp) {
  6103.             if ((ep = pmatch(lp,ap)))
  6104.                 break;
  6105.             lp++;
  6106.         }
  6107.         break;
  6108.     case END:            /* munged automaton. fail always */
  6109.         return 0;
  6110.     }
  6111.     if (!ep)
  6112.         return 0;
  6113.  
  6114.     if (internal_error)
  6115.         return -1;
  6116.  
  6117.     bopat[0] = lp;
  6118.     eopat[0] = ep;
  6119.     return 1;
  6120. }
  6121.  
  6122. /* 
  6123.  * pmatch: 
  6124.  *    internal routine for the hard part
  6125.  *
  6126.  *     This code is mostly snarfed from an early
  6127.  *     grep written by David Conroy. The backref and
  6128.  *     tag stuff, and various other mods are by oZ.
  6129.  *
  6130.  *    special cases: (nfa[n], nfa[n+1])
  6131.  *        CLO ANY
  6132.  *            We KNOW ".*" will match ANYTHING
  6133.  *            upto the end of line. Thus, go to
  6134.  *            the end of line straight, without
  6135.  *            calling pmatch recursively. As in
  6136.  *            the other closure cases, the remaining
  6137.  *            pattern must be matched by moving
  6138.  *            backwards on the string recursively,
  6139.  *            to find a match for xy (x is ".*" and 
  6140.  *            y is the remaining pattern) where
  6141.  *            the match satisfies the LONGEST match
  6142.  *            for x followed by a match for y.
  6143.  *        CLO CHR
  6144.  *            We can again scan the string forward
  6145.  *            for the single char without recursion, 
  6146.  *            and at the point of failure, we execute 
  6147.  *            the remaining nfa recursively, as
  6148.  *            described above.
  6149.  *
  6150.  *    At the end of a successful match, bopat[n] and eopat[n]
  6151.  *    are set to the beginning and end of subpatterns matched
  6152.  *    by tagged expressions (n = 1 to 9).    
  6153.  *
  6154.  */
  6155.  
  6156. /*
  6157.  * character classification table for word boundary
  6158.  * operators BOW and EOW. the reason for not using 
  6159.  * ctype macros is that we can let the user add into 
  6160.  * our own table. see re_modw. This table is not in
  6161.  * the bitset form, since we may wish to extend it
  6162.  * in the future for other character classifications. 
  6163.  *
  6164.  *    TRUE for 0-9 A-Z a-z _
  6165.  */
  6166. static char chrtyp[MAXCHR] = {
  6167.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  6168.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  6169.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  6170.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  6171.     0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 
  6172.     1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 
  6173.     0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 
  6174.     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  6175.     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  6176.     1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 
  6177.     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  6178.     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  6179.     1, 1, 1, 0, 0, 0, 0, 0
  6180.     };
  6181.  
  6182. #define inascii(x)    (0177&(x))
  6183. #define iswordc(x)     chrtyp[inascii(x)]
  6184. #define isinset(x,y)     ((x)[((y)&BLKIND)>>3] & bitarr[(y)&BITIND])
  6185.  
  6186. /*
  6187.  * skip values for CLO XXX to skip past the closure
  6188.  *
  6189.  */
  6190.  
  6191. #define ANYSKIP    2     /* [CLO] ANY END ...         */
  6192. #define CHRSKIP    3    /* [CLO] CHR chr END ...     */
  6193. #define CCLSKIP 18    /* [CLO] CCL 16bytes END ... */
  6194.  
  6195. static char *
  6196. pmatch(lp, ap)
  6197. register char *lp;
  6198. register CHAR *ap;
  6199. {
  6200.     register int op, c, n;
  6201.     register char *e;        /* extra pointer for CLO */
  6202.     register char *bp;        /* beginning of subpat.. */
  6203.     register char *ep;        /* ending of subpat..     */
  6204.     char *are;            /* to save the line ptr. */
  6205.  
  6206.     while ((op = *ap++) != END)
  6207.         switch(op) {
  6208.  
  6209.         case CHR:
  6210.             if (*lp++ != *ap++)
  6211.                 return 0;
  6212.             break;
  6213.         case ANY:
  6214.             if (!*lp++)
  6215.                 return 0;
  6216.             break;
  6217.         case CCL:
  6218.             c = *lp++;
  6219.             if (!isinset(ap,c))
  6220.                 return 0;
  6221.             ap += BITBLK;
  6222.             break;
  6223.         case BOL:
  6224.             if (lp != bol)
  6225.                 return 0;
  6226.             break;
  6227.         case EOL:
  6228.             if (*lp)
  6229.                 return 0;
  6230.             break;
  6231.         case BOT:
  6232.             bopat[*ap++] = lp;
  6233.             break;
  6234.         case EOT:
  6235.             eopat[*ap++] = lp;
  6236.             break;
  6237.          case BOW:
  6238.             if (lp!=bol && iswordc(lp[-1]) || !iswordc(*lp))
  6239.                 return 0;
  6240.             break;
  6241.         case EOW:
  6242.             if (lp==bol || !iswordc(lp[-1]) || iswordc(*lp))
  6243.                 return 0;
  6244.             break;
  6245.         case REF:
  6246.             n = *ap++;
  6247.             bp = bopat[n];
  6248.             ep = eopat[n];
  6249.             while (bp < ep)
  6250.                 if (*bp++ != *lp++)
  6251.                     return 0;
  6252.             break;
  6253.         case CLO:
  6254.             are = lp;
  6255.             switch(*ap) {
  6256.  
  6257.             case ANY:
  6258.                 while (*lp)
  6259.                     lp++;
  6260.                 n = ANYSKIP;
  6261.                 break;
  6262.             case CHR:
  6263.                 c = *(ap+1);
  6264.                 while (*lp && c == *lp)
  6265.                     lp++;
  6266.                 n = CHRSKIP;
  6267.                 break;
  6268.             case CCL:
  6269.                 while ((c = *lp) && isinset(ap+1,c))
  6270.                     lp++;
  6271.                 n = CCLSKIP;
  6272.                 break;
  6273.             default:
  6274.                 internal_error++;
  6275.                 return 0;
  6276.             }
  6277.  
  6278.             ap += n;
  6279.  
  6280.             while (lp >= are) {
  6281.                 if (e = pmatch(lp, ap))
  6282.                     return e;
  6283.                 --lp;
  6284.             }
  6285.             return 0;
  6286.         default:
  6287.             internal_error++;
  6288.             return 0;
  6289.         }
  6290.     return lp;
  6291. }
  6292. #endif /* Need regex libraries? Compile to nothing if not.  */
  6293. $EOD
  6294. $!
  6295. $CREATE [.archie]regex.h
  6296. $DECK
  6297. /*
  6298.  * regex.h : External defs for Ozan Yigit's regex functions, for systems
  6299.  *    that don't have them builtin. See regex.c for copyright and other
  6300.  *    details.
  6301.  *
  6302.  * Note that this file can be included even if we're linking against the
  6303.  * system routines, since the interface is (deliberately) identical.
  6304.  *
  6305.  * George Ferguson, ferguson@cs.rochester.edu, 11 Sep 1991.
  6306.  */
  6307.  
  6308. #if defined(_AUX_SOURCE) || defined(USG)
  6309. /* Let them use ours if they wish.  */
  6310. # ifndef NOREGEX
  6311. extern char *regcmp();
  6312. extern char *regex();
  6313. #define re_comp regcmp
  6314. #define re_exec regex
  6315. # endif
  6316. #else
  6317. extern char *re_comp();
  6318. extern int re_exec();
  6319. #endif
  6320. $EOD
  6321. $!
  6322. $CREATE [.archie]stcopy.c
  6323. $DECK
  6324. /*
  6325.  * Copyright (c) 1989, 1990, 1991 by the University of Washington
  6326.  *
  6327.  * For copying and distribution information, please see the file
  6328.  * <copyright.h>.
  6329.  */
  6330.  
  6331. #include <copyright.h>
  6332. #include <stdio.h>
  6333. #include <pmachine.h>
  6334.  
  6335. #ifdef NEED_STRING_H
  6336. # include <string.h>
  6337. #else
  6338. # include <strings.h>
  6339. #endif
  6340.  
  6341. #if defined(MSDOS)
  6342. # include <stdlib.h>
  6343. #endif
  6344.  
  6345. char    *stcopyr();
  6346.  
  6347. int    string_count = 0;
  6348. int    string_max = 0;
  6349.  
  6350. /*
  6351.  * stcopy - allocate space for and copy a string
  6352.  *
  6353.  *     STCOPY takes a string as an argument, allocates space for
  6354.  *     a copy of the string, copies the string to the allocated space,
  6355.  *     and returns a pointer to the copy.
  6356.  */
  6357.  
  6358. char *
  6359. stcopy(st)
  6360.     char    *st;
  6361.     {
  6362.       if (!st) return(NULL);
  6363.       if (string_max < ++string_count) string_max = string_count;
  6364.  
  6365.       return strcpy((char *)malloc(strlen(st) + 1), st);
  6366.     }
  6367.  
  6368. /*
  6369.  * stcopyr - copy a string allocating space if necessary
  6370.  *
  6371.  *     STCOPYR takes a string, S, as an argument, and a pointer to a second
  6372.  *     string, R, which is to be replaced by S.  If R is long enough to
  6373.  *     hold S, S is copied.  Otherwise, new space is allocated, and R is
  6374.  *     freed.  S is then copied to the newly allocated space.  If S is
  6375.  *     NULL, then R is freed and NULL is returned.
  6376.  *
  6377.  *     In any event, STCOPYR returns a pointer to the new copy of S,
  6378.  *     or a NULL pointer.
  6379.  */
  6380. char *
  6381. stcopyr(s,r)
  6382.     char    *s;
  6383.     char    *r;
  6384.     {
  6385.     int    sl;
  6386.  
  6387.     if(!s && r) {
  6388.         free(r);
  6389.         string_count--;
  6390.         return(NULL);
  6391.     }
  6392.     else if (!s) return(NULL);
  6393.  
  6394.     sl = strlen(s) + 1;
  6395.  
  6396.     if(r) {
  6397.         if ((strlen(r) + 1) < sl) {
  6398.         free(r);
  6399.         r = (char *) malloc(sl);
  6400.         }
  6401.     }
  6402.     else {
  6403.         r = (char *) malloc(sl);
  6404.         string_count++;
  6405.         if(string_max < string_count) string_max = string_count;
  6406.     }
  6407.         
  6408.     return strcpy(r,s);
  6409.     }
  6410.  
  6411. /*
  6412.  * stfree - free space allocated by stcopy or stalloc
  6413.  *
  6414.  *     STFREE takes a string that was returned by stcopy or stalloc 
  6415.  *     and frees the space that was allocated for the string.
  6416.  */
  6417. void
  6418. stfree(st)
  6419.     char *st;
  6420.     {
  6421.     if(st) {
  6422.         free(st);
  6423.         string_count--;
  6424.     }
  6425.     }
  6426.  
  6427.  
  6428. $EOD
  6429. $!
  6430. $CREATE [.archie]support.c
  6431. $DECK
  6432. /*
  6433.  * Copyright (c) 1989, 1990, 1991 by the University of Washington
  6434.  *
  6435.  * For copying and distribution information, please see the file
  6436.  * <copyright.h>.
  6437.  */
  6438.  
  6439. /*
  6440.  * Miscellaneous routines pulled from ~beta/lib/pfs and ~beta/lib/filters
  6441.  */
  6442.  
  6443. #include <copyright.h>
  6444. #include <stdio.h>
  6445.  
  6446. #include <errno.h>
  6447.  
  6448. #ifdef VMS
  6449. # ifdef WOLLONGONG
  6450. #  include "twg$tcp:[netdist.include]netdb.h"
  6451. # else /* not Wollongong */
  6452. #  ifdef UCX
  6453. #   include netdb
  6454. #  else /* Multinet */
  6455. #   include "multinet_root:[multinet.include]netdb.h"
  6456. #  endif
  6457. # endif
  6458. # include <vms.h>
  6459. #else /* not VMS */
  6460. # include <sys/types.h>
  6461. # include <pmachine.h>
  6462. # ifdef NEED_STRING_H
  6463. #  include <string.h>
  6464. # else
  6465. #  include <strings.h>
  6466. # endif
  6467. # ifndef CUTCP
  6468. #  include <netdb.h>
  6469. # endif
  6470. # if !defined(MSDOS) || defined(OS2)
  6471. #  include <sys/file.h>
  6472. #  include <sys/param.h>
  6473. # endif
  6474. #endif /* VMS */
  6475.  
  6476. #include <pfs.h>
  6477. #include <pprot.h>
  6478. #include <perrno.h>
  6479. #include <pcompat.h>
  6480. #include <pauthent.h>
  6481.  
  6482. #include "regex.h"
  6483.  
  6484. int    pfs_enable = PMAP_ATSIGN;
  6485.  
  6486. #ifndef FALSE
  6487. # define TRUE     1
  6488. # define FALSE   0
  6489. #endif
  6490.  
  6491. /* 
  6492.  * wcmatch - Match string s against template containing widlcards
  6493.  *
  6494.  *         WCMATCH takes a string and a template, and returns
  6495.  *         true if the string matches the template, and 
  6496.  *         FALSE otherwise.
  6497.  *
  6498.  *    ARGS:  s        - string to be tested
  6499.  *           template - Template containing optional wildcards
  6500.  *
  6501.  * RETURNS:  TRUE (non-zero) on match.  FALSE (0) otherwise.
  6502.  *
  6503.  *    NOTE:  If template is NULL, will return TRUE.
  6504.  *
  6505.  */
  6506. int
  6507. wcmatch(s,template)
  6508.     char    *s;
  6509.     char    *template;
  6510.     {
  6511.     char    temp[200];
  6512.     char    *p = temp;
  6513.  
  6514.     if(!template) return(TRUE);
  6515.     *p++ = '^';
  6516.  
  6517.     while(*template) {
  6518.         if(*template == '*') {*(p++)='.'; *(p++) = *(template++);}
  6519.         else if(*template == '?') {*(p++)='.';template++;}
  6520.         else if(*template == '.') {*(p++)='\\';*(p++)='.';template++;}
  6521.         else if(*template == '[') {*(p++)='\\';*(p++)='[';template++;}
  6522.         else if(*template == '$') {*(p++)='\\';*(p++)='$';template++;}
  6523.         else if(*template == '^') {*(p++)='\\';*(p++)='^';template++;}
  6524.         else if(*template == '\\') {*(p++)='\\';*(p++)='\\';template++;}
  6525.         else *(p++) = *(template++);
  6526.     }
  6527.         
  6528.     *p++ = '$';
  6529.     *p++ = '\0';
  6530.  
  6531.     if(re_comp(temp)) return(FALSE);
  6532.  
  6533. #ifdef AUX
  6534.     if (re_exec(s) == (char *)NULL)
  6535.       return 0;
  6536.     return 1;
  6537. #else
  6538.     return(re_exec(s));
  6539. #endif
  6540.     }
  6541.  
  6542. /*
  6543.  * ul_insert - Insert a union link at the right location
  6544.  *
  6545.  *             UL_INSERT takes a directory and a union link to be added
  6546.  *             to a the list of union links in the directory.  It then
  6547.  *             inserts the union link in the right spot in the linked
  6548.  *             list of union links associated with that directory.
  6549.  *
  6550.  *           If an identical link already exists, then the link which
  6551.  *             would be evaluated earlier (closer to the front of the list)
  6552.  *             wins and the other one is freed.  If this happens, an error
  6553.  *             will also be returned.
  6554.  *        
  6555.  *    ARGS:    ul    - link to be inserted
  6556.  *           vd    - directory to get link
  6557.  *             p     - vl that this link will apper after
  6558.  *                     NULL - This vl will go at end of list
  6559.  *                     vd   - This vl will go at head of list
  6560.  *
  6561.  * RETURNS:    Success, or UL_INSERT_ALREADY_THERE or UL_INSERT_SUPERSEDING
  6562.  */
  6563. int
  6564. ul_insert(ul,vd,p)
  6565.     VLINK    ul;        /* Link to be inserted                   */
  6566.     PVDIR    vd;        /* Directory to receive link             */
  6567.     VLINK    p;        /* Union link to appear prior to new one */
  6568.     {
  6569.     VLINK    current;
  6570.  
  6571.     /* This is the first ul in the directory */
  6572.     if(vd->ulinks == NULL) {
  6573.         vd->ulinks = ul;
  6574.         ul->previous = NULL;
  6575.         ul->next = NULL;
  6576.         return(PSUCCESS);
  6577.     }
  6578.  
  6579.     /* This ul will go at the head of the list */
  6580.     if(p == (VLINK) vd) {
  6581.         ul->next = vd->ulinks;
  6582.         ul->next->previous = ul;
  6583.         vd->ulinks = ul;
  6584.         ul->previous = NULL;
  6585.     }
  6586.     /* Otherwise, decide if it must be inserted at all  */
  6587.     /* If an identical link appears before the position */
  6588.     /* at which the new one is to be inserted, we can   */
  6589.     /* return without inserting it                 */
  6590.     else {
  6591.         current = vd->ulinks;
  6592.  
  6593.         while(current) {
  6594.         /* p == NULL means we insert after last link */
  6595.         if(!p && (current->next == NULL))
  6596.             p = current;
  6597.  
  6598.         if(vl_comp(current,ul) == 0) {
  6599.             vlfree(ul);
  6600.             return(UL_INSERT_ALREADY_THERE);
  6601.         }
  6602.  
  6603.         if(current == p) break;
  6604.         current = current->next;
  6605.         }
  6606.  
  6607.         /* If current is null, p was not found */
  6608.         if(current == NULL)
  6609.         return(UL_INSERT_POS_NOTFOUND);
  6610.  
  6611.         /* Insert ul */
  6612.         ul->next = p->next;
  6613.         p->next = ul;
  6614.         ul->previous = p;
  6615.         if(ul->next) ul->next->previous = ul;
  6616.     }
  6617.  
  6618.     /* Check for identical links after ul */
  6619.     current = ul->next;
  6620.  
  6621.     while(current) {
  6622.         if(vl_comp(current,ul) == 0) {
  6623.         current->previous->next = current->next;
  6624.         if(current->next)
  6625.             current->next->previous = current->previous;
  6626.         vlfree(current);
  6627.         return(UL_INSERT_SUPERSEDING);
  6628.         }
  6629.         current = current->next;
  6630.     }
  6631.     
  6632.     return(PSUCCESS);
  6633.     }
  6634.  
  6635. /*
  6636.  * vl_insert - Insert a directory link at the right location
  6637.  *
  6638.  *             VL_INSERT takes a directory and a link to be added to a 
  6639.  *             directory and inserts it in the linked list of links for
  6640.  *             that directory.  
  6641.  *
  6642.  *             If a link already exists with the same name, and if the
  6643.  *             information associated with the new link matches that in
  6644.  *             the existing link, an error is returned.  If the information
  6645.  *             associated with the new link is different, but the magic numbers
  6646.  *             match, then the new link will be added as a replica of the
  6647.  *             existing link.  If the magic numbers do not match, the new
  6648.  *             link will only be added to the list of "replicas" if the
  6649.  *             allow_conflict flag has been set.
  6650.  * 
  6651.  *             If the link is not added, an error is returned and the link
  6652.  *             is freed.  Ordering for the list of links is by the link name.  
  6653.  *        
  6654.  *             If vl is a union link, then VL_INSERT calls ul_insert with an
  6655.  *           added argument indicating the link is to be included at the
  6656.  *             end of the union link list.
  6657.  * 
  6658.  *    ARGS:    vl - Link to be inserted, vd - directory to get link
  6659.  *             allow_conflict - insert links with conflicting names
  6660.  *
  6661.  * RETURNS:    Success, or VL_INSERT_ALREADY_THERE
  6662.  */
  6663. int
  6664. vl_insert(vl,vd,allow_conflict)
  6665.     VLINK    vl;        /* Link to be inserted               */
  6666.     PVDIR    vd;        /* Directory to receive link         */
  6667.     int        allow_conflict;    /* Allow duplicate names             */
  6668.     {
  6669.     VLINK    current;    /* To step through list             */
  6670.     VLINK    crep;        /* To step through list of replicas  */
  6671.     int    retval;        /* Temp for checking returned values */
  6672.  
  6673.     /* This can also be used to insert union links at end of list */
  6674.     if(vl->linktype == 'U') return(ul_insert(vl,vd,NULL));
  6675.  
  6676.     /* If this is the first link in the directory */
  6677.     if(vd->links == NULL) {
  6678.         vd->links = vl;
  6679.         vl->previous = NULL;
  6680.         vl->next = NULL;
  6681.         vd->lastlink = vl;
  6682.         return(PSUCCESS);
  6683.     }
  6684.  
  6685.     /* If no sorting is to be done, just insert at end of list */
  6686.     if(allow_conflict == VLI_NOSORT) {
  6687.         vd->lastlink->next = vl;
  6688.         vl->previous = vd->lastlink;
  6689.         vl->next = NULL;
  6690.         vd->lastlink = vl;
  6691.         return(PSUCCESS);
  6692.     }
  6693.  
  6694.     /* If it is to be inserted at start of list */
  6695.     if(vl_comp(vl,vd->links) < 0) {
  6696.         vl->next = vd->links;
  6697.         vl->previous = NULL;
  6698.         vl->next->previous = vl;
  6699.         vd->links = vl;
  6700.         return(PSUCCESS);
  6701.     }
  6702.  
  6703.     current = vd->links;
  6704.  
  6705.     /* Otherwise, we must find the right spot to insert it */
  6706.     while((retval = vl_comp(vl,current)) > 0) {
  6707.         if(!current->next) {
  6708.         /* insert at end */
  6709.         vl->previous = current;
  6710.         vl->next = NULL;
  6711.         current->next = vl;
  6712.         vd->lastlink = vl;
  6713.         return(PSUCCESS);
  6714.         }
  6715.         current = current->next;
  6716.     }
  6717.  
  6718.     /* If we found an equivilant entry already in list */
  6719.     if(!retval) {
  6720.         if(vl_equal(vl,current)) {
  6721.         vlfree(vl);
  6722.         return(VL_INSERT_ALREADY_THERE);
  6723.         }
  6724.         if((allow_conflict == VLI_NOCONFLICT) &&
  6725.            ((vl->f_magic_no != current->f_magic_no) ||
  6726.         (vl->f_magic_no==0)))
  6727.         return(VL_INSERT_CONFLICT);
  6728.         /* Insert the link into the list of "replicas" */
  6729.         /* If magic is 0, then create a pseudo magic number */
  6730.         if(vl->f_magic_no == 0) vl->f_magic_no = -1;
  6731.         crep = current->replicas;
  6732.         if(!crep) {
  6733.         current->replicas = vl;
  6734.         vl->next = NULL;
  6735.         vl->previous = NULL;
  6736.         }
  6737.         else {
  6738.         while(crep->next) {
  6739.             /* If magic was 0, then we need a unique magic number */
  6740.             if((crep->f_magic_no < 0) && (vl->f_magic_no < 1))
  6741.             (vl->f_magic_no)--;
  6742.             crep = crep->next;
  6743.         }
  6744.         /* If magic was 0, then we need a unique magic number */
  6745.         if((crep->f_magic_no < 0) && (vl->f_magic_no < 1))
  6746.             (vl->f_magic_no)--;
  6747.         crep->next = vl;
  6748.         vl->previous = crep;
  6749.         vl->next = NULL;
  6750.         }
  6751.         return(PSUCCESS);
  6752.     }
  6753.  
  6754.     /* We found the spot where vl is to be inserted */
  6755.     vl->next = current;
  6756.     vl->previous = current->previous;
  6757.     current->previous = vl;
  6758.     vl->previous->next = vl;
  6759.     return(PSUCCESS);
  6760.     }
  6761.  
  6762. /*
  6763.  * nlsindex - Find first instance of string 2 in string 1 following newline
  6764.  *
  6765.  *          NLSINDEX scans string 1 for the first instance of string
  6766.  *          2 that immediately follows a newline.  If found, NLSINDEX
  6767.  *          returns a pointer to the first character of that instance.
  6768.  *          If no instance is found, NLSINDEX returns NULL (0).
  6769.  *
  6770.  *    NOTE:   This function is only useful for searching strings that
  6771.  *            consist of multiple lines.  s1 is assumed to be preceeded
  6772.  *           by a newline.  Thus, if s2 is at the start of s1, it will
  6773.  *          be found.
  6774.  *    ARGS:   s1 - string to be searched
  6775.  *            s2 - string to be found
  6776.  * RETURNS:   First instance of s2 in s1, or NULL (0) if not found
  6777.  */
  6778. char *
  6779. nlsindex(s1,s2)
  6780.     char    *s1;        /* String to be searched */
  6781.     char    *s2;        /* String to be found    */
  6782.     {
  6783.     register int s2len = strlen(s2);
  6784.     char    *curline = s1;    /* Pointer to start of current line */
  6785.  
  6786.     /* In case s2 appears at start of s1 */
  6787.     if(strncmp(curline,s2,s2len) == 0)
  6788.         return(curline);
  6789.  
  6790.     /* Check remaining lines of s1 */
  6791.     while((curline = (char *) index(curline,'\n')) != NULL) {
  6792.         curline++;
  6793.         if(strncmp(curline,s2,s2len) == 0)
  6794.         return(curline);
  6795.     }
  6796.  
  6797.     /* We didn't find it */
  6798.     return(NULL);
  6799.     }
  6800.  
  6801. /*
  6802.  * month_sname - Return a month name from it's number
  6803.  *
  6804.  *               MONTH_SNAME takes a number in the range 0
  6805.  *               to 12 and returns a pointer to a string
  6806.  *               representing the three letter abbreviation
  6807.  *             for that month.  If the argument is out of 
  6808.  *         range, MONTH_SNAME returns a pointer to "Unk".
  6809.  *
  6810.  *       ARGS:   n - Number of the month
  6811.  *    RETURNS:   Abbreviation for selected month
  6812.  */
  6813. char *month_sname(n)
  6814.     int n;        /* Month number */
  6815. {
  6816.     static char *name[] = { "Unk",
  6817.         "Jan","Feb","Mar","Apr","May","Jun",
  6818.         "Jul","Aug","Sep","Oct","Nov","Dec"
  6819.     };
  6820.     return((n < 1 || n > 12) ? name[0] : name[n]);
  6821. }
  6822.  
  6823. /*
  6824.  * sindex - Find first instance of string 2 in string 1 
  6825.  *
  6826.  *          SINDEX scans string 1 for the first instance of string
  6827.  *          2.  If found, SINDEX returns a pointer to the first
  6828.  *          character of that instance.  If no instance is found, 
  6829.  *          SINDEX returns NULL (0).
  6830.  *
  6831.  *    ARGS:   s1 - string to be searched
  6832.  *            s2 - string to be found
  6833.  * RETURNS:   First instance of s2 in s1, or NULL (0) if not found
  6834.  */
  6835. char *
  6836. sindex(s1,s2)
  6837.     char    *s1;        /* String to be searched   */
  6838.     char    *s2;        /* String to be found      */
  6839.     {
  6840.     register int s2len = strlen(s2);
  6841.     char    *s = s1;    /* Temp pointer to string  */
  6842.  
  6843.     /* Check for first character of s2 */
  6844.     while((s = (char *) index(s,*s2)) != NULL) {
  6845.         if(strncmp(s,s2,s2len) == 0)
  6846.         return(s);
  6847.         s++;
  6848.     }
  6849.  
  6850.     /* We didn't find it */
  6851.     return(NULL);
  6852.     }
  6853.  
  6854. int
  6855. scan_error(erst)
  6856.     char    *erst;
  6857.     {
  6858.     *p_err_string = '\0';
  6859.  
  6860.     if(strncmp(erst,"NOT-A-DIRECTORY",15) == 0) 
  6861.         return(DIRSRV_NOT_DIRECTORY);
  6862.  
  6863.     if(strncmp(erst,"UNIMPLEMENTED",13) == 0) {
  6864.         perrno = DIRSRV_UNIMPLEMENTED;
  6865.         sscanf(erst+13,"%*[^\n \t\r]%*[ \t]%[^\n]",p_err_string);
  6866.         return(perrno);
  6867.     }
  6868.  
  6869.     if(strncmp(erst,"WARNING ",8) == 0) {
  6870.         erst += 8;
  6871.         *p_warn_string = '\0';
  6872.         sscanf(erst,"%*[^\n \t\r]%*[ \t]%[^\n]",p_warn_string);
  6873.         /* Return values for warnings are negative */
  6874.         if(strncmp(erst,"OUT-OF-DATE",11) == 0) {
  6875.         pwarn = PWARN_OUT_OF_DATE;
  6876.         return(PSUCCESS);
  6877.         }
  6878.         if(strncmp(erst,"MESSAGE",7) == 0) {
  6879.         pwarn = PWARN_MSG_FROM_SERVER;
  6880.         return(PSUCCESS);
  6881.         }
  6882.         pwarn = PWARNING;
  6883.         sscanf(erst,"%[^\n]",p_warn_string);
  6884.         return(PSUCCESS);
  6885.     }
  6886.     else if(strncmp(erst,"ERROR",5) == 0) {
  6887.         if(*(erst+5)) sscanf(erst+6,"%[^\n]",p_err_string);
  6888.         perrno = DIRSRV_ERROR;
  6889.         return(perrno);
  6890.     }
  6891.     /* The rest start with "FAILURE" */
  6892.     else if(strncmp(erst,"FAILURE",7) != 0) {
  6893.         /* Unrecognized - Give warning, but return PSUCCESS */
  6894.         if(pwarn == 0) {
  6895.         *p_warn_string = '\0';
  6896.         pwarn = PWARN_UNRECOGNIZED_RESP;
  6897.         sscanf(erst,"%[^\n]",p_warn_string);
  6898.         }
  6899.         return(PSUCCESS);
  6900.     }
  6901.  
  6902.     if(strncmp(erst,"FAILURE ",8) != 0) {
  6903.         perrno = PFAILURE;
  6904.         return(perrno);
  6905.     }    
  6906.     erst += 8;
  6907.     
  6908.     sscanf(erst,"%*[^\n \t\r]%*[ \t]%[^\n]",p_err_string);
  6909.  
  6910.     /* Still to add               */
  6911.     /* DIRSRV_AUTHENT_REQ     242 */
  6912.     /* DIRSRV_BAD_VERS        245 */
  6913.  
  6914.     if(strncmp(erst,"NOT-FOUND",9) == 0) 
  6915.         perrno = DIRSRV_NOT_FOUND;
  6916.     else if(strncmp(erst,"NOT-AUTHORIZED",13) == 0) 
  6917.         perrno = DIRSRV_NOT_AUTHORIZED;
  6918.     else if(strncmp(erst,"ALREADY-EXISTS",14) == 0) 
  6919.         perrno = DIRSRV_ALREADY_EXISTS;
  6920.     else if(strncmp(erst,"NAME-CONFLICT",13) == 0) 
  6921.         perrno = DIRSRV_NAME_CONFLICT;
  6922.     else if(strncmp(erst,"SERVER-FAILED",13) == 0) 
  6923.         perrno = DIRSRV_SERVER_FAILED;
  6924.      /* Use it whether it starts with FAILURE or not */
  6925.     else if(strncmp(erst,"NOT-A-DIRECTORY",15) == 0) 
  6926.         perrno = DIRSRV_NOT_DIRECTORY;
  6927.     else perrno = PFAILURE;
  6928.  
  6929.     return(perrno);
  6930.     }
  6931.  
  6932. PATTRIB 
  6933. parse_attribute(line)
  6934.     char    *line;
  6935.     {
  6936.     char    l_precedence[MAX_DIR_LINESIZE];
  6937.     char    l_name[MAX_DIR_LINESIZE];
  6938.     char    l_type[MAX_DIR_LINESIZE];
  6939.     char    l_value[MAX_DIR_LINESIZE];
  6940.     PATTRIB    at;
  6941.     int    tmp;
  6942.  
  6943.     tmp = sscanf(line,"OBJECT-INFO %s %s %[^\n]", l_name, l_type, l_value);
  6944.     
  6945.     if(tmp < 3) {
  6946.         tmp = sscanf(line,"LINK-INFO %s %s %s %[^\n]", l_precedence,
  6947.              l_name, l_type, l_value);
  6948.         if(tmp < 4) {
  6949.         perrno = DIRSRV_BAD_FORMAT;
  6950.         return(NULL);
  6951.         }
  6952.     }
  6953.  
  6954.     at = atalloc();
  6955.  
  6956.     if(tmp == 4) {
  6957.         if(strcmp(l_precedence,"CACHED") == 0) 
  6958.         at->precedence = ATR_PREC_CACHED;
  6959.         else if(strcmp(l_precedence,"LINK") == 0) 
  6960.         at->precedence = ATR_PREC_LINK;
  6961.         else if(strcmp(l_precedence,"REPLACEMENT") == 0) 
  6962.         at->precedence = ATR_PREC_REPLACE;
  6963.         else if(strcmp(l_precedence,"ADDITIONAL") == 0) 
  6964.         at->precedence = ATR_PREC_ADD;
  6965.     }
  6966.  
  6967.     at->aname = stcopy(l_name);
  6968.     at->avtype = stcopy(l_type);
  6969.     if(strcmp(l_type,"ASCII") == 0) 
  6970.         at->value.ascii = stcopy(l_value);
  6971.     else if(strcmp(l_type,"LINK") == 0) {
  6972.         char        ftype[MAX_DIR_LINESIZE];
  6973.         char        lname[MAX_DIR_LINESIZE];
  6974.         char        htype[MAX_DIR_LINESIZE];
  6975.         char        host[MAX_DIR_LINESIZE];
  6976.         char        ntype[MAX_DIR_LINESIZE];
  6977.         char        fname[MAX_DIR_LINESIZE];
  6978.         VLINK        al;
  6979.  
  6980.         al = vlalloc();
  6981.         at->value.link = al;
  6982.  
  6983.         tmp = sscanf(l_value,"%c %s %s %s %s %s %s %d %d",
  6984.              &(al->linktype),
  6985.              ftype,lname,htype,host,ntype,fname,
  6986.              &(al->version),
  6987.              &(al->f_magic_no));
  6988.         if(tmp == 9) {
  6989.         al->type = stcopyr(ftype,al->type);
  6990.         al->name = stcopyr(unquote(lname),al->name);
  6991.         al->hosttype = stcopyr(htype,al->hosttype);
  6992.         al->host = stcopyr(host,al->host);
  6993.         al->nametype = stcopyr(ntype,al->nametype);
  6994.         al->filename = stcopyr(fname,al->filename);
  6995.         }
  6996.         else {
  6997.         perrno = DIRSRV_BAD_FORMAT;
  6998.         return(NULL);
  6999.         }
  7000.         
  7001.     }
  7002.  
  7003.     return(at);
  7004.     }
  7005.  
  7006. /*
  7007.  * nxtline - Find the next line in the string
  7008.  *
  7009.  *          NXTLINE takes a string and returns a pointer to
  7010.  *          the character immediately following the next newline.
  7011.  *
  7012.  *    ARGS:   s - string to be searched
  7013.  *
  7014.  * RETURNS:   Next line or NULL (0) on failure
  7015.  */
  7016. char *
  7017. nxtline(s)
  7018.     char    *s;        /* String to be searched */
  7019.  {
  7020.     s = (char *) index(s,'\n');
  7021.     if(s) return(++s);
  7022.     else return(NULL);
  7023.     }
  7024.  
  7025.  
  7026. /*
  7027.  * unquote - unquote string if necessary
  7028.  *
  7029.  *          UNQUOTE takes a string and unquotes it if it has been quoted.
  7030.  *
  7031.  *    ARGS:   s - string to be unquoted
  7032.  *            
  7033.  * RETURNS:   The original string.  If the string has been quoted, then the
  7034.  *            result appears in static storage, and must be copied if 
  7035.  *            it is to last beyond the next call to quote.
  7036.  *
  7037.  */
  7038. char *
  7039. unquote(s)
  7040.     char    *s;        /* String to be quoted */
  7041.     {
  7042.     static char    unquoted[200];
  7043.     char        *c = unquoted;
  7044.  
  7045.     if(*s != '\'') return(s);
  7046.  
  7047.     s++;
  7048.  
  7049.     /* This should really treat a quote followed by other */
  7050.     /* than a quote or a null as an error                 */
  7051.     while(*s) {
  7052.         if(*s == '\'') s++;
  7053.         if(*s) *c++ = *s++;
  7054.     }
  7055.  
  7056.     *c++ = '\0';
  7057.  
  7058.     return(unquoted);
  7059.     }
  7060.  
  7061. #if defined(DEBUG) && defined(STRSPN)
  7062. /* needed for -D option parsing */
  7063. /*
  7064.  * strspn - Count initial characters from chrs in s
  7065.  *
  7066.  *          STRSPN counts the occurances of chacters from chrs
  7067.  *            in the string s preceeding the first occurance of
  7068.  *            a character not in s.
  7069.  *
  7070.  *    ARGS:   s    - string to be checked
  7071.  *            chrs - string of characters we are looking for
  7072.  *
  7073.  * RETURNS:   Count of initial characters from chrs in s
  7074.  */
  7075. strspn(s,chrs)
  7076.     char    *s;    /* String to search                         */
  7077.     char    *chrs; /* String of characters we are looking for  */
  7078.     {
  7079.     char    *cp;   /* Pointer to the current character in chrs */
  7080.     int    count; /* Count of characters seen so far          */
  7081.     
  7082.     count = 0;
  7083.  
  7084.     while(*s) {
  7085.         for(cp = chrs;*cp;cp++)
  7086.         if(*cp == *s) {
  7087.             s++;
  7088.             count++;
  7089.             goto done;
  7090.         }
  7091.         return(count);
  7092.     done:
  7093.         ;
  7094.     }
  7095.     return(count);
  7096.     }
  7097. #endif
  7098.  
  7099. #ifdef CUTCP
  7100. char
  7101. *inet_ntoa(struct in_addr in)
  7102. {
  7103.     static    char    buff[36];
  7104.  
  7105.     unsigned char    *c = (char *) &in.address;
  7106.     sprintf(buff,"%d.%d.%d.%d",*c,*(c+1),*(c+2),*(c+3));
  7107.     return(buff);
  7108. }
  7109.  
  7110. long
  7111. inet_addr(char *cp)
  7112. {
  7113.     long    value = 0;
  7114.     unsigned    v1,v2,v3,v4;
  7115.  
  7116.     v1 = v2 = v3 = v4 = 0xff;
  7117.     sscanf(cp,"%d.%d.%d.%d",&v1,&v2,&v3,&v4);
  7118.     value = (v1 << 24) | (v2 << 16) | (v3 << 8) | v4;
  7119.     return(value);
  7120. }
  7121.  
  7122. struct    hostent
  7123. *gethostbyname(char *name)
  7124. {
  7125.     struct machinfo    *mp;
  7126.     int    mnum;
  7127.     unsigned long    now;
  7128.     static    struct hostent    ht;
  7129.     extern int pfs_debug;
  7130.  
  7131.     mp = Shostlook(name);
  7132.     if(!mp || (!mp->hostip[0])) {    /* DNS lookup */
  7133. #ifdef DEBUG
  7134.         if (pfs_debug)
  7135.         fprintf(stderr, "Domain name lookup of %s\n", name);
  7136. #endif
  7137.         mnum = Sdomain(name);        /* start a DNS lookup */
  7138.         now = time(NULL) + NS_TIMEOUT;
  7139.         while(now > time(NULL)) {
  7140.             int    i, class, dat;
  7141.  
  7142.             Stask();
  7143.             i = Sgetevent(USERCLASS, &class, &dat);
  7144.             if(i == DOMOK) {    /* domain lookup ok */
  7145.                 mp = Slooknum(mnum);
  7146. #ifdef DEBUG
  7147.         if (pfs_debug)
  7148.         fprintf(stderr, "Domain name lookup of %s Completed OK\n", name);
  7149. #endif
  7150.                 break;
  7151.             }
  7152.         }
  7153.         if(!mp)    {    /* get here if timeout */
  7154. #ifdef DEBUG
  7155.         if (pfs_debug)
  7156.         fprintf(stderr, "Domain name lookup of %s Failed\n", name);
  7157. #endif
  7158.             return(NULL);
  7159.         }
  7160.     }
  7161.     ht.h_addr = *((unsigned long *) mp->hostip);
  7162.     ht.h_length = 4;
  7163.     ht.h_addrtype = AF_INET;
  7164.     return(&ht);
  7165.  
  7166. }
  7167. #endif /* CUTCP */
  7168.  
  7169. #ifdef GETENV
  7170. /*
  7171.  * Copyright (c) 1987 Regents of the University of California.
  7172.  * All rights reserved.
  7173.  *
  7174.  * Redistribution and use in source and binary forms are permitted
  7175.  * provided that: (1) source distributions retain this entire copyright
  7176.  * notice and comment, and (2) distributions including binaries display
  7177.  * the following acknowledgement:  ``This product includes software
  7178.  * developed by the University of California, Berkeley and its contributors''
  7179.  * in the documentation or other materials provided with the distribution
  7180.  * and in all advertising materials mentioning features or use of this
  7181.  * software. Neither the name of the University nor the names of its
  7182.  * contributors may be used to endorse or promote products derived
  7183.  * from this software without specific prior written permission.
  7184.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  7185.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  7186.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  7187.  */
  7188.  
  7189. #if defined(LIBC_SCCS) && !defined(lint)
  7190. static char sccsid[] = "@(#)getenv.c    5.7 (Berkeley) 6/1/90";
  7191. #endif /* LIBC_SCCS and not lint */
  7192.  
  7193. #include <stdlib.h>
  7194. #include <stddef.h>
  7195.  
  7196. /*
  7197.  * getenv --
  7198.  *    Returns ptr to value associated with name, if any, else NULL.
  7199.  */
  7200. char *
  7201. getenv(name)
  7202.     char *name;
  7203. {
  7204.     int offset;
  7205.     char *_findenv();
  7206.  
  7207.     return(_findenv(name, &offset));
  7208. }
  7209.  
  7210. /*
  7211.  * _findenv --
  7212.  *    Returns pointer to value associated with name, if any, else NULL.
  7213.  *    Sets offset to be the offset of the name/value combination in the
  7214.  *    environmental array, for use by setenv(3) and unsetenv(3).
  7215.  *    Explicitly removes '=' in argument name.
  7216.  *
  7217.  *    This routine *should* be a static; don't use it.
  7218.  */
  7219. char *
  7220. _findenv(name, offset)
  7221.     register char *name;
  7222.     int *offset;
  7223. {
  7224.     extern char **environ;
  7225.     register int len;
  7226.     register char **P, *C;
  7227.  
  7228.     for (C = name, len = 0; *C && *C != '='; ++C, ++len);
  7229.     for (P = environ; *P; ++P)
  7230.         if (!strncmp(*P, name, len))
  7231.             if (*(C = *P + len) == '=') {
  7232.                 *offset = P - environ;
  7233.                 return(++C);
  7234.             }
  7235.     return(NULL);
  7236. }
  7237. #endif
  7238. $EOD
  7239. $!
  7240. $CREATE [.archie]copyright.h
  7241. $DECK
  7242. /* These are the uw-copyright.h and usc-copyright.h files that appear in
  7243.    the Prospero distribution.  */
  7244.  
  7245. /* 
  7246.   Copyright (c) 1989, 1990, 1991 by the University of Washington
  7247.  
  7248.   Permission to use, copy, modify, and distribute this software and its
  7249.   documentation for non-commercial purposes and without fee is hereby
  7250.   granted, provided that the above copyright notice appear in all copies
  7251.   and that both the copyright notice and this permission notice appear in
  7252.   supporting documentation, and that the name of the University of
  7253.   Washington not be used in advertising or publicity pertaining to
  7254.   distribution of the software without specific, written prior
  7255.   permission.  The University of Washington makes no representations
  7256.   about the suitability of this software for any purpose.  It is
  7257.   provided "as is" without express or implied warranty.
  7258.  
  7259.   Prospero was written by Clifford Neuman (bcn@isi.edu).
  7260.  
  7261.   Questions concerning this software should be directed to 
  7262.   info-prospero@isi.edu.
  7263.  
  7264.   */
  7265.  
  7266. /* 
  7267.   Copyright (c) 1991, 1992 by the University of Southern California
  7268.   All rights reserved.
  7269.  
  7270.   Permission to use, copy, modify, and distribute this software and its
  7271.   documentation in source and binary forms for non-commercial purposes
  7272.   and without fee is hereby granted, provided that the above copyright
  7273.   notice appear in all copies and that both the copyright notice and
  7274.   this permission notice appear in supporting documentation. and that
  7275.   any documentation, advertising materials, and other materials related
  7276.   to such distribution and use acknowledge that the software was
  7277.   developed by the University of Southern California, Information
  7278.   Sciences Institute.  The name of the University may not be used to
  7279.   endorse or promote products derived from this software without
  7280.   specific prior written permission.
  7281.  
  7282.   THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about
  7283.   the suitability of this software for any purpose.  THIS SOFTWARE IS
  7284.   PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
  7285.   INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  7286.   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  7287.  
  7288.   Other copyrights might apply to parts of the Prospero distribution
  7289.   and are so noted when applicable.
  7290.  
  7291.   Prospero was originally written by Clifford Neuman (bcn@isi.edu).
  7292.   Contributors include Benjamin Britt (britt@isi.edu)
  7293.   and others identified in individual modules.
  7294.  
  7295.   Questions concerning this software should be directed to 
  7296.   info-prospero@isi.edu.
  7297.  
  7298.   */
  7299. $EOD
  7300. $!
  7301. $CREATE [.archie]udp.c
  7302. $DECK
  7303. /*
  7304.  * udp - Check if UDP traffic is allowed on this host; we open port 1527 on
  7305.  *       a system (default of cs.widener.edu), which is expecting it; the
  7306.  *       date is output (e.g. very similar to the daytime service).  This
  7307.  *       will conclusively tell us if UDP traffic on ports > 1000 is allowed.
  7308.  *
  7309.  *    It should print out the date if UDP traffic's not blocked on your
  7310.  *    system.  If it just hangs, try these tests too:
  7311.  *      a. run it with -d  (e.g. "udp -d"); that goes to the normal UDP port
  7312.  *         to print the date.  If it works, then you can be sure that any
  7313.  *         UDP traffic > port 1000 is blocked on your system.
  7314.  *      b. if it hangs too, try "telnet 147.31.254.130 13" and see if
  7315.  *         _that_ prints the date; if it doesn't, it's another problem (your
  7316.  *         network can't get to me, e.g.).
  7317.  *
  7318.  * Compile by: cc -o udp udp.c
  7319.  *
  7320.  * Brendan Kehoe, brendan@cs.widener.edu, Oct 1991.
  7321.  */
  7322.  
  7323. #include <stdio.h>
  7324. #include <sys/types.h>
  7325. #include <sys/socket.h>
  7326. #include <netinet/in.h>
  7327. #ifndef hpux
  7328. # include <arpa/inet.h>
  7329. #endif
  7330.  
  7331. #define    SIZE    2048
  7332. #define    HOST    "147.31.254.130"    /* cs.widener.edu */
  7333. #define PORT    1527
  7334.  
  7335. main (argc, argv)
  7336.      int argc;
  7337.      char **argv;
  7338. {
  7339.   int s, len;
  7340.   struct sockaddr_in server, sa;
  7341.   char buf[SIZE];
  7342.  
  7343.   if ((s = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
  7344.     {
  7345.       perror ("socket()");
  7346.       exit (1);
  7347.     }
  7348.  
  7349.   bzero ((char *) &sa, sizeof (sa));
  7350.   sa.sin_family = AF_INET;
  7351.   sa.sin_addr.s_addr = htonl (INADDR_ANY);
  7352.   sa.sin_port = htons (0);
  7353.  
  7354.   if (bind (s, (struct sockaddr *) &sa, sizeof (sa)) < 0)
  7355.     {
  7356.       perror ("bind()");
  7357.       exit (1);
  7358.     }
  7359.  
  7360.   bzero ((char *) &server, sizeof (server));
  7361.   server.sin_family = AF_INET;
  7362.   server.sin_addr.s_addr = inet_addr (HOST);
  7363.   if (argc > 1 && strcmp(*(argv + 1), "-d") == 0)
  7364.     server.sin_port = htons ((unsigned short) 13);
  7365.   else
  7366.     server.sin_port = htons ((unsigned short) PORT);
  7367.  
  7368.   /* yoo hoo, we're here .. */
  7369.   if (sendto (s, "\n", 1, 0, &server, sizeof (server)) < 0)
  7370.     {
  7371.       perror ("sendto()");
  7372.       exit (1);
  7373.     }
  7374.  
  7375.   /* slurp */
  7376.   len = sizeof (server);
  7377.   if (recvfrom (s, buf, sizeof (buf), 0, &server, &len) < 0)
  7378.     {
  7379.       perror ("recvfrom");
  7380.       exit (1);
  7381.     }
  7382.  
  7383.   printf ("%s", buf);
  7384.   close (s);
  7385. }
  7386. $EOD
  7387. $!
  7388. $CREATE [.archie]vl_comp.c
  7389. $DECK
  7390. /*
  7391.  * Copyright (c) 1989, 1990, 1991 by the University of Washington
  7392.  *
  7393.  * For copying and distribution information, please see the file
  7394.  * <copyright.h>.
  7395.  */
  7396.  
  7397. #include <copyright.h>
  7398. #include <pfs.h>
  7399.  
  7400. /*
  7401.  * vl_comp - compare the names of two virtual links
  7402.  *
  7403.  *           VL_COMP compares the names of two links.  It returns
  7404.  *           0 if they are equal, negative if vl1 < vl2, and positive if
  7405.  *           vl1 > vl2.
  7406.  *
  7407.  *    ARGS:  vl1,vl2 - Virtual links to be compared
  7408.  * 
  7409.  * RETURNS:  0 if equal, + is vl1 > vl2, - if vl1 < vl2
  7410.  *
  7411.  *   NOTES:  Order of significance is as follows.  Existence,
  7412.  *           name.  If names do not exist, then hosttype, host,
  7413.  *           native filenametype, native filename.  The only time
  7414.  *           the name will not exist if if the link is a union link.
  7415.  */
  7416. int
  7417. vl_comp(vl1,vl2)
  7418.     VLINK    vl1;
  7419.     VLINK    vl2;
  7420.     {
  7421.     int    retval;
  7422.  
  7423.     if(vl1->name && !vl2->name) return(1);
  7424.     if(!vl1->name && vl2->name) return(-1);
  7425.     if(vl1->name && vl2->name && (*(vl1->name) || *(vl2->name)))
  7426.         return(strcmp(vl1->name,vl2->name));
  7427.  
  7428.     retval = strcmp(vl1->hosttype,vl2->hosttype);
  7429.     if(!retval) retval = strcmp(vl1->host,vl2->host);
  7430.     if(!retval) retval = strcmp(vl1->nametype,vl2->nametype);
  7431.     if(!retval) retval = strcmp(vl1->filename,vl2->filename);
  7432.     return(retval);
  7433.     }
  7434.  
  7435. /*
  7436.  * vl_equal - compare the values of two virtual links
  7437.  *
  7438.  *           VL_EQUAL compares the values of two links.  It returns
  7439.  *           1 if all important fields are the same, and 0 otherwise.
  7440.  *
  7441.  *    ARGS:  vl1,vl2 - Virtual links to be compared
  7442.  * 
  7443.  * RETURNS:  1 if equal, 0 if not equal
  7444.  *
  7445.  */
  7446. int
  7447. vl_equal(vl1,vl2)
  7448.     VLINK    vl1;
  7449.     VLINK    vl2;
  7450.     {
  7451.       return strcmp(vl1->name, vl2->name) == 0         &&
  7452.          vl1->linktype == vl2->linktype            &&
  7453.          strcmp(vl1->type, vl2->type) == 0         &&
  7454.          strcmp(vl1->hosttype, vl2->hosttype) == 0 &&
  7455.          strcmp(vl1->host, vl2->host) == 0         &&
  7456.          strcmp(vl1->nametype, vl2->nametype) == 0 &&
  7457.          strcmp(vl1->filename, vl2->filename) == 0 &&
  7458.          vl1->version == vl2->version              &&
  7459.          vl1->f_magic_no == vl2->f_magic_no        ;
  7460.  
  7461.     }
  7462.  
  7463. $EOD
  7464. $!
  7465. $CREATE [.archie]vlalloc.c
  7466. $DECK
  7467. /*
  7468.  * Copyright (c) 1989, 1990, 1991 by the University of Washington
  7469.  *
  7470.  * For copying and distribution information, please see the file
  7471.  * <copyright.h>.
  7472.  */
  7473.  
  7474. #include <copyright.h>
  7475. #include <stdio.h>
  7476.  
  7477. #include <pfs.h>
  7478. #include <pmachine.h>
  7479.  
  7480. static VLINK    lfree = NULL;
  7481. int        vlink_count = 0;
  7482. int        vlink_max = 0;
  7483.  
  7484. /*
  7485.  * vlalloc - allocate and initialize vlink structure
  7486.  *
  7487.  *    VLALLOC returns a pointer to an initialized structure of type
  7488.  *    VLINK.  If it is unable to allocate such a structure, it
  7489.  *    returns NULL.
  7490.  */
  7491. VLINK
  7492. vlalloc()
  7493.     {
  7494.     VLINK    vl;
  7495.     if(lfree) {
  7496.         vl = lfree;
  7497.         lfree = lfree->next;
  7498.     }
  7499.     else {
  7500.         vl = (VLINK) malloc(sizeof(VLINK_ST));
  7501.         if (!vl) return(NULL);
  7502.         vlink_max++;
  7503.     }
  7504.  
  7505.     vlink_count++;
  7506.  
  7507.     /* Initialize and fill in default values */
  7508.     /* Since all but four are set to a zero-value,
  7509.        why not just wipe it clean?  */
  7510.     ZERO(vl);
  7511.  
  7512.     vl->linktype = 'L';
  7513.     vl->type = stcopy("FILE");
  7514.     vl->hosttype = stcopy("INTERNET-D");
  7515.     vl->nametype = stcopy("ASCII");
  7516.  
  7517.     return(vl);
  7518.     }
  7519.  
  7520. /*
  7521.  * vlfree - free a VLINK structure
  7522.  *
  7523.  *    VLFREE takes a pointer to a VLINK structure and adds it to
  7524.  *    the free list for later reuse.
  7525.  */
  7526. void
  7527. vlfree(vl)
  7528.     VLINK    vl;
  7529.     {
  7530.         extern int string_count;
  7531.  
  7532.     if(vl->dontfree) return;
  7533.     /* many of these don't need to call stfree(); since a check
  7534.        for pointer validity's already done before even calling
  7535.        it, we can just call free() here then do one big decrement
  7536.        of string_count at the end.  */
  7537.     if(vl->name) free(vl->name);
  7538.     stfree(vl->type);
  7539.     if(vl->replicas) vllfree(vl->replicas);
  7540.     stfree(vl->hosttype);
  7541.     if(vl->host) free(vl->host);
  7542.     stfree(vl->nametype);
  7543.     if(vl->filename) free(vl->filename);
  7544.     if(vl->args) free(vl->args);
  7545.     if(vl->lattrib) atlfree(vl->lattrib);
  7546.     /* No allocation routines for f_info yet */
  7547.     vl->f_info = NULL;
  7548.     vl->next = lfree;
  7549.     vl->previous = NULL;
  7550.     lfree = vl;
  7551.     vlink_count--;
  7552.     string_count -= 4; /* freed name, host, filename, and args */
  7553.     }
  7554.  
  7555. /*
  7556.  * vllfree - free a VLINK structure
  7557.  *
  7558.  *    VLLFREE takes a pointer to a VLINK structure frees it and any linked
  7559.  *    VLINK structures.  It is used to free an entrie list of VLINK
  7560.  *    structures.
  7561.  */
  7562. void
  7563. vllfree(vl)
  7564.     VLINK    vl;
  7565.     {
  7566.     VLINK    nxt;
  7567.  
  7568.     while((vl != NULL) && !vl->dontfree) {
  7569.         nxt = vl->next;
  7570.         vlfree(vl);
  7571.         vl = nxt;
  7572.     }
  7573.     }
  7574.  
  7575. $EOD
  7576. $!
  7577. $CREATE [.archie]vms.h
  7578. $DECK
  7579. #ifndef _ARCHIE_VMS
  7580. #define _ARCHIE_VMS
  7581. #include <pmachine.h>
  7582.  
  7583. #if !defined(MULTINET_30) && !defined(WOLLONGONG) && !defined(UCX)
  7584. #include "[.vms]pseudos.h"
  7585. #include "[.vms]types.h"
  7586. #include "[.vms]in.h"
  7587. #include "[.vms]signal.h"
  7588. #include "[.vms]socket.h"
  7589. #include "[.vms]time.h"
  7590.  
  7591. #else
  7592.  
  7593. /* time_t gets multiply defined <ekup> */
  7594. #ifndef __TYPES
  7595. #define __TYPES
  7596. #endif
  7597. #ifdef MULTINET_30
  7598. # include "multinet_root:[multinet.include.sys]types.h"
  7599. # include "multinet_root:[multinet.include.netinet]in.h"
  7600. # include "multinet_root:[multinet.include.sys]socket.h"
  7601. # include "multinet_root:[multinet.include.sys]time.h"
  7602. #endif /* MULTINET_30 */
  7603.  
  7604. #ifdef WOLLONGONG
  7605. /* We don't want size_t defined.  */
  7606. # ifndef __STDDEF
  7607. #  define __STDDEF
  7608. # endif
  7609. # include "twg$tcp:[netdist.include.sys]types.h"
  7610. # include "twg$tcp:[netdist.include.netinet]in.h"
  7611. # include "twg$tcp:[netdist.include.sys]socket.h"
  7612. # include "twg$tcp:[netdist.include.sys]time.h"
  7613. #endif /* WOLLONGONG */
  7614.  
  7615. #ifdef UCX
  7616. # include <types.h>
  7617. # include <in.h>
  7618. # include <socket.h>
  7619. # include <time.h>
  7620. # include "[.vms]fd.h"
  7621. #endif /* UCX */
  7622.  
  7623. #endif /* Multinet or Wallongong or UCX */
  7624.  
  7625. #endif /* _ARCHIE_VMS */
  7626. $EOD
  7627. $!
  7628. $CREATE [.archie]vms_support.c
  7629. $DECK
  7630. /* Emulation of 4.2 UNIX socket interface routines includes drivers for
  7631.    Wollongong, CMU-TEK, UCX tcp/ip interface and also emulates the SUN
  7632.    version of X.25 sockets.  The TWG will also work for MultiNet.  */
  7633.  
  7634. /* This is from unixlib, by P.Kay@massey.ac.nz; wonderful implementation.
  7635.    You can get the real thing on 130.123.1.4 as unixlib_tar.z.  */
  7636.  
  7637. #include <stdio.h>
  7638. #include <errno.h>
  7639. #include <ssdef.h>
  7640. #include <dvidef.h>
  7641. #include <signal.h>
  7642. #include <sys$library:msgdef.h>
  7643. #include <iodef.h>
  7644. #include <ctype.h>
  7645. #include <vms.h>
  7646. #include "[.vms]network.h"
  7647.  
  7648. #define QIO_FAILED (st != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL)
  7649. #define QIO_ST_FAILED (st != SS$_NORMAL)
  7650.  
  7651. /* Socket routine.  */
  7652. int
  7653. VMSsocket (domain, type, protocol)
  7654.      int domain, type, protocol;
  7655. {
  7656.   struct descriptor inetdesc, x25desc, mbxdesc;
  7657.   int i, st, s, p_initialise ();
  7658.   long ucx_sock_def;
  7659.   char *getenv ();
  7660.  
  7661.   if (!tcp_make)
  7662.     set_tcp_make ();
  7663.  
  7664.   if (p_initialised == 0)
  7665.     {
  7666.       for (i = 0; i < 32; i++)
  7667.     p_initialise (i);
  7668.  
  7669.       p_initialised = 1;
  7670.     }
  7671.  
  7672.   /* First of all, get a file descriptor and file ptr we can associate with
  7673.      the socket, allocate a buffer, and remember the socket details.  */
  7674.   s = dup (0);
  7675.   if (s > 31)
  7676.     {
  7677.       errno = EMFILE;
  7678.       close (s);
  7679.       return -1;
  7680.     }
  7681.  
  7682.   p[s].fptr = fdopen (s, "r");
  7683.   p[s].fd_buff = (unsigned char *) malloc (BUF_SIZE);
  7684.   p[s].domain = domain;
  7685.   p[s].type = type;
  7686.   p[s].protocol = protocol;
  7687.  
  7688.   /* Handle the case of INET and X.25 separately.  */
  7689.   if (domain == AF_INET)
  7690.     {
  7691.       if (tcp_make == NONE)
  7692.     {
  7693.       printf ("Trying to obtain a TCP socket when we don't have TCP!\n");
  7694.       exit (1);
  7695.     }
  7696.       if (tcp_make == CMU)
  7697.     {
  7698.       /* For CMU we need only assign a channel.  */
  7699.       inetdesc.size = 3;
  7700.       inetdesc.ptr = "IP:";
  7701.       if (sys$assign (&inetdesc, &p[s].channel, 0, 0) != SS$_NORMAL)
  7702.         return -1;
  7703.     }
  7704.       else if (tcp_make == UCX)
  7705.     {
  7706.       /* For UCX assign channel and associate a socket with it.  */
  7707.       inetdesc.size = 3;
  7708.       inetdesc.ptr = "BG:";
  7709.       if (sys$assign (&inetdesc, &p[s].channel, 0, 0) != SS$_NORMAL)
  7710.         return -1;
  7711.  
  7712.       ucx_sock_def = (domain << 24) + (type << 16) + protocol;
  7713.       st = sys$qiow (0, p[s].channel, IO$_SETMODE, p[s].iosb, 0, 0,
  7714.              &ucx_sock_def, 0, 0, 0, 0, 0);
  7715.       if (QIO_FAILED)
  7716.         return -1;
  7717.     }
  7718.       else
  7719.     {
  7720.       /* For TWG we assign the channel and associate a socket with it.  */
  7721.       inetdesc.size = 7;
  7722.       inetdesc.ptr = "_INET0:";
  7723.  
  7724.       if (sys$assign (&inetdesc, &p[s].channel, 0, 0) != SS$_NORMAL)
  7725.         return -1;
  7726.  
  7727.       st = sys$qiow (0, p[s].channel, IO$_SOCKET, p[s].iosb, 0, 0,
  7728.              domain, type, 0, 0, 0, 0);
  7729.       if (QIO_FAILED)
  7730.         return -1;
  7731.     }
  7732.     }
  7733.   else
  7734.     /* We don't handle any other domains yet.  */
  7735.     return -1;
  7736.  
  7737.   /* For each case if we are successful we return the descriptor.  */
  7738.   return s;
  7739. }
  7740.  
  7741. /* Bind routine.  */
  7742. VMSbind (s, name, namelen)
  7743.      int s;
  7744.      union socket_addr *name;
  7745.      int namelen;
  7746. {
  7747.   char infobuff[1024], lhost[32];
  7748.   int st;
  7749.  
  7750.   if (!tcp_make)
  7751.     set_tcp_make ();
  7752.  
  7753.   if (p[s].domain == AF_INET)
  7754.     {
  7755.       /* One main problem with bind is that if we're given a port number
  7756.      of 0, then we're expected to return a unique port number.  Since
  7757.      we don't KNOW, we return 1050+s and look to Lady Luck.  */
  7758.       if (tcp_make == CMU)
  7759.     {
  7760.       if (name->in.sin_port == 0 && p[s].type != SOCK_DGRAM)
  7761.         name->in.sin_port = 1050 + s;
  7762.       p[s].namelen = namelen;
  7763.       bcopy (name, &(p[s].name), namelen);
  7764.  
  7765.       if (p[s].type == SOCK_DGRAM)
  7766.         {
  7767.           /* Another problem is that CMU still needs an OPEN request
  7768.          even if it's a datagram socket.  */
  7769.           st = sys$qiow (0, p[s].channel, TCP$OPEN, p[s].iosb,
  7770.                  0, 0, 0, 0, ntohs (p[s].name.in.sin_port),
  7771.                  0, 1, 0);
  7772.           if (QIO_ST_FAILED)
  7773.         return -1;
  7774.  
  7775.           p[s].cmu_open = 1;
  7776.           sys$qiow (0, p[s].channel, TCP$INFO, p[s].iosb,
  7777.             0, 0, &infobuff, 1024, 0, 0, 0, 0);
  7778.           bcopy (infobuff + 264, &(p[s].name.in.sin_port), 2);
  7779.           p[s].name.in.sin_port = htons (p[s].name.in.sin_port);
  7780.  
  7781.           /* So get it another way.  */
  7782.           bcopy (infobuff + 136, lhost, infobuff[1]);
  7783.           lhost[infobuff[1]] = '\0';
  7784.           sys$qiow (0, p[s].channel, GTHST, p[s].iosb,
  7785.             0, 0, &infobuff, 1024, 1, lhost, 0, 0);
  7786.           bcopy (infobuff + 4, &(p[s].name.in.sin_addr), 4);
  7787.  
  7788.           /* Be prepared to receive a message.  */
  7789.           hang_a_read (s);
  7790.         }
  7791.     }
  7792.       else if (tcp_make == UCX)
  7793.     {
  7794.       /* UCX will select a prot for you.  If the port's number is 0,
  7795.          translate "name" into an item_2 list.  */
  7796.       struct itemlist lhost;
  7797.       lhost.length = namelen;
  7798.       lhost.code = 0;
  7799.       lhost.dataptr = (char *) name;
  7800.  
  7801.       st = sys$qiow (0, p[s].channel, IO$_SETMODE, p[s].iosb, 0, 0,
  7802.              0, 0, &lhost, 0, 0, 0);
  7803.       if (QIO_FAILED)
  7804.         return -1;
  7805.  
  7806.       if (p[s].type == SOCK_DGRAM)
  7807.         hang_a_read (s);
  7808.  
  7809.     }
  7810.       else
  7811.     {
  7812.       /* WG is more straightforward */
  7813.       st = sys$qiow (0, p[s].channel, IO$_BIND, p[s].iosb,
  7814.              0, 0, name, namelen, 0, 0, 0, 0);
  7815.       if (QIO_FAILED)
  7816.         return -1;
  7817.  
  7818.       /* If it's a datagram, get ready for the message.  */
  7819.       if (p[s].type == SOCK_DGRAM)
  7820.         hang_a_read (s);
  7821.     }
  7822.     }
  7823.   else
  7824.     /* We don't handle any other domain yet.  */
  7825.     return -1;
  7826.  
  7827.   return 0;
  7828. }
  7829.  
  7830. /* Connect routine.  */
  7831. VMSconnect (s, name, namelen)
  7832.      int s;
  7833.      union socket_addr *name;
  7834.      int namelen;
  7835. {
  7836.   int pr, fl, st;
  7837.   char *inet_ntoa ();
  7838.   static struct
  7839.   {
  7840.     int len;
  7841.     char name[128];
  7842.   } gethostbuf;
  7843.   extern int connect_ast ();
  7844.  
  7845.   if (!tcp_make)
  7846.     set_tcp_make ();
  7847.  
  7848.   /* For datagrams we need to remember who the name was so we can send all
  7849.      messages to that address without having to specify it all the time.  */
  7850.   if (p[s].connected)
  7851.     {
  7852.       if (p[s].connected == 1)
  7853.     errno = EISCONN;
  7854.       else
  7855.     {
  7856.       errno = ECONNREFUSED;
  7857.       p[s].connected = 0;
  7858.     }
  7859.       return -1;
  7860.     }
  7861.  
  7862.   if (p[s].connect_pending)
  7863.     {
  7864.       errno = EALREADY;
  7865.       return -1;
  7866.     }
  7867.  
  7868.   p[s].passive = 0;
  7869.   p[s].tolen = namelen;
  7870.   bcopy (name, &(p[s].to), namelen);
  7871.  
  7872.   if (p[s].domain == AF_INET)
  7873.     {
  7874.       if (tcp_make == CMU)
  7875.     {
  7876.  
  7877.       /* Get the info about the remote host  and open up a connection.  */
  7878.       st = sys$qiow (0, p[s].channel, GTHST, p[s].iosb, 0, 0, &gethostbuf,
  7879.              132, 2, name->in.sin_addr.s_addr, 0, 0);
  7880.       if (QIO_FAILED)
  7881.         {
  7882.           strcpy (gethostbuf.name, inet_ntoa (name->in.sin_addr.s_addr));
  7883.           gethostbuf.len = strlen (gethostbuf.name);
  7884.         }
  7885.       gethostbuf.name[gethostbuf.len] = 0;
  7886.  
  7887.       /* TCP */
  7888.       pr = 0;
  7889.       /* Active */
  7890.       fl = 1;
  7891.  
  7892.       /* Nothing else for datagrams.  */
  7893.       if (p[s].type == SOCK_DGRAM)
  7894.         return (0);
  7895.       st = sys$qio (s, p[s].channel, TCP$OPEN, p[s].iosb, connect_ast,
  7896.             &p[s], &(gethostbuf.name), ntohs (name->in.sin_port),
  7897.             ntohs (p[s].name.in.sin_port), fl, pr, 0);
  7898.       if (QIO_ST_FAILED)
  7899.         return -1;
  7900.     }
  7901.       else if (tcp_make == UCX)
  7902.     {
  7903.       /* Both UDP and TCP can use a connect - IO$_ACCESS */
  7904.       p[s].rhost.length = namelen;
  7905.       p[s].rhost.code = 0;
  7906.       p[s].rhost.dataptr = (char *) name;
  7907.  
  7908.       st = sys$qio (s, p[s].channel, IO$_ACCESS, p[s].iosb, connect_ast,
  7909.             &p[s], 0, 0, &p[s].rhost, 0, 0, 0);
  7910.       if (QIO_ST_FAILED)
  7911.         return -1;
  7912.     }
  7913.       else
  7914.     {
  7915.       /* TWG */
  7916.       if (p[s].type == SOCK_DGRAM)
  7917.         return (0);
  7918.       st = sys$qio (s, p[s].channel, IO$_CONNECT, p[s].iosb, connect_ast,
  7919.             &p[s], name, namelen, 0, 0, 0, 0);
  7920.       if (QIO_ST_FAILED)
  7921.         return -1;
  7922.     }
  7923.     }
  7924.   else
  7925.     /* We don't handle any other domain yet.  */
  7926.     return -1;
  7927.  
  7928.   if (p[s].non_blocking)
  7929.     {
  7930.       if (p[s].connected)
  7931.     {
  7932.       if (p[s].connected == 1)
  7933.         return 0;
  7934.       else
  7935.         {
  7936.           p[s].connected = 0;
  7937.           errno = ECONNREFUSED;
  7938.           return -1;
  7939.         }
  7940.     }
  7941.       else
  7942.     {
  7943.       p[s].connect_pending = 1;
  7944.       errno = EINPROGRESS;
  7945.       return -1;
  7946.     }
  7947.     }
  7948.   else
  7949.     {
  7950.       /* wait for the connection to occur */
  7951.       if (p[s].connected)
  7952.     {
  7953.       if (p[s].connected == 1)
  7954.         return 0;
  7955.       else
  7956.         {
  7957.           p[s].connected = 0;
  7958.           errno = ECONNREFUSED;
  7959.           return -1;
  7960.         }
  7961.     }
  7962.  
  7963.       /* Timed out? */
  7964.       if (wait_efn (s) == -1)
  7965.     return -1;
  7966.  
  7967.       if (p[s].connected != SS$_NORMAL)
  7968.     {
  7969.       errno = ECONNREFUSED;
  7970.       return -1;
  7971.     }
  7972.  
  7973.       return 0;
  7974.     }
  7975. }
  7976.  
  7977. /* Listen routine.  */
  7978. VMSlisten (s, backlog)
  7979.      int s;
  7980.      int backlog;
  7981. {
  7982.   int st;
  7983.  
  7984.   if (!tcp_make)
  7985.     set_tcp_make ();
  7986.  
  7987.   p[s].passive = 1;
  7988.   p[s].backlog = backlog;
  7989.   if (p[s].domain == AF_INET)
  7990.     {
  7991.       if (tcp_make == CMU)
  7992.     {
  7993.       /* For the CMU sockets we can't do the open call in listen;
  7994.          we have to do it in hang_an_accept, because when we close
  7995.          off the connection we have to be ready to accept another
  7996.          one.  accept() also calls hang_an_accept on the old
  7997.          descriptor.  */
  7998.  
  7999.       /* Nothing */
  8000.     }
  8001.       else if (tcp_make == UCX)
  8002.     {
  8003.  
  8004.       /* Doc Verbage sez backlog is descriptor of byte.  Doc examples
  8005.          and common sense say backlog is value.  Value doesn't work,
  8006.          so let's try descriptor of byte after all.  */
  8007.       struct descriptor bl;
  8008.       unsigned char ucx_backlog;
  8009.  
  8010.       ucx_backlog = (unsigned char) backlog;
  8011.       bl.size = sizeof (ucx_backlog);
  8012.       bl.ptr = (char *) &ucx_backlog;
  8013.  
  8014.       st = sys$qiow (0, p[s].channel, IO$_SETMODE, p[s].iosb, 0, 0,
  8015.              0, 0, 0, &bl, 0, 0);
  8016.       if (QIO_FAILED)
  8017.         return -1;
  8018.     }
  8019.       else
  8020.     {
  8021.       /* TWG */
  8022.       st = sys$qiow (0, p[s].channel, IO$_LISTEN, p[s].iosb, 0, 0,
  8023.              backlog, 0, 0, 0, 0, 0);
  8024.       if (QIO_FAILED)
  8025.         return -1;
  8026.     }
  8027.     }
  8028.   else
  8029.     /* We don't handle any other domain yet.  */
  8030.     return -1;
  8031.  
  8032.   p[s].status = LISTENING;
  8033.   hang_an_accept (s);
  8034.   return 0;
  8035. }
  8036.  
  8037. /* Accept routine.  */
  8038. int
  8039. VMSaccept (s, addr, addrlen)
  8040.      int s;
  8041.      union socket_addr *addr;
  8042.      int *addrlen;
  8043. {
  8044.   int news, st;
  8045.   struct descriptor inetdesc;
  8046.  
  8047.   if (!tcp_make)
  8048.     set_tcp_make ();
  8049.  
  8050.   if (p[s].non_blocking && !p[s].accept_pending)
  8051.     {
  8052.       errno = EWOULDBLOCK;
  8053.       return -1;
  8054.     }
  8055.  
  8056.   /* hang_an_accept set up an incoming connection request so we have first
  8057.      to hang around until one appears or we time out.  */
  8058.   if (p[s].domain == AF_INET)
  8059.     {
  8060.       if (tcp_make == CMU)
  8061.     {
  8062.       char infobuff[1024];
  8063.  
  8064.       /* Timed out?  */
  8065.       if (wait_efn (s) == -1)
  8066.         return -1;
  8067.  
  8068.       /* Ok, get a new descriptor ...  */
  8069.       news = dup (0);
  8070.       if (news > 31)
  8071.         {
  8072.           errno = EMFILE;
  8073.           close (news);
  8074.           return -1;
  8075.         }
  8076.  
  8077.       /* ... and copy all of our data across.  */
  8078.       bcopy (&p[s], &p[news], sizeof (p[0]));
  8079.  
  8080.       /* But not this field, of course! */
  8081.       p[news].s = news;
  8082.  
  8083.       sys$qiow (0, p[news].channel, TCP$INFO, p[news].iosb,
  8084.             0, 0, &infobuff, 1024, 0, 0, 0, 0);
  8085.  
  8086.       /* Copy across the connection info if necessary.  */
  8087.       if (addr != 0)
  8088.         {
  8089.           *addrlen = sizeof (struct sockaddr_in);
  8090.           bcopy (infobuff + 132, &(addr->in.sin_port), 2);
  8091.           addr->in.sin_port = htons (addr->in.sin_port);
  8092.           addr->in.sin_family = AF_INET;
  8093.           bcopy (infobuff + 272, &(addr->in.sin_addr), 4);
  8094.           p[news].fromlen = *addrlen;
  8095.           bcopy (addr, &(p[news].from), *addrlen);
  8096.         }
  8097.       p[news].status = PASSIVE_CONNECTION;
  8098.  
  8099.       /* Get a new file ptr for the socket.  */
  8100.       p[news].fptr = fdopen (news, "r");
  8101.  
  8102.       /* Reset this field.  */
  8103.       p[news].accept_pending = 0;
  8104.  
  8105.       /* Allocate a buffer.  */
  8106.       p[news].fd_buff = (unsigned char *) malloc (BUF_SIZE);
  8107.       p[news].fd_leftover = 0;
  8108.  
  8109.       /* Be prepared to get msgs.  */
  8110.       hang_a_read (news);
  8111.  
  8112.       /* Now fix up our previous socket so it's again listening
  8113.          for connections.  */
  8114.       inetdesc.size = 3;
  8115.       inetdesc.ptr = "IP:";
  8116.       if (sys$assign (&inetdesc, &p[s].channel, 0, 0) != SS$_NORMAL)
  8117.         return -1;
  8118.       p[s].status = LISTENING;
  8119.       hang_an_accept (s);
  8120.  
  8121.       /* Return the new socket descriptor.  */
  8122.       return news;
  8123.     }
  8124.       else if (tcp_make == UCX)
  8125.     {
  8126.       /* UCX does the actual accept from hang_an_accept.  The accept info
  8127.         is put into the data structure for the "listening" socket.
  8128.         These just need to be copied into a newly allocated socket for
  8129.         the connect and the listening socket re-started.  */
  8130.  
  8131.       /* Wait for event flag from accept being received inside
  8132.          of hang_an_accept().  */
  8133.  
  8134.       if (wait_efn (s) == -1)
  8135.         /* Timed out.  */
  8136.         return -1;
  8137.  
  8138.       /* Ok, get a new descriptor ...  */
  8139.       news = dup (0);
  8140.       if (news > 31)
  8141.         {
  8142.           errno = EMFILE;
  8143.           close (news);
  8144.           return -1;
  8145.         }
  8146.       /* ... and copy all of our data across.  */
  8147.       bcopy (&p[s], &p[news], sizeof (p[0]));
  8148.       p[news].s = news;    /* but not this field */
  8149.       p[news].channel = p[s].ucx_accept_chan;
  8150.  
  8151.       /* Initialize the remote host address item_list_3 struct.  */
  8152.       p[news].rhost.length = sizeof (struct sockaddr_in);
  8153.       p[news].rhost.code = 0;
  8154.       p[news].rhost.dataptr = (char *) &p[news].from;
  8155.       p[news].rhost.retlenptr = &p[news].fromdummy;
  8156.  
  8157.       if (addr != 0)
  8158.         {
  8159.           /* Return the caller's info, if requested.  */
  8160.           *addrlen = p[news].fromdummy;
  8161.           bcopy (&p[news].from, addr, p[news].fromdummy);
  8162.         }
  8163.  
  8164.       /* Finish fleshing out the new structure.  */
  8165.       p[news].status = PASSIVE_CONNECTION;
  8166.  
  8167.       /* Get a new file pointer for the socket.  */
  8168.       p[news].fptr = fdopen (news, "r");
  8169.  
  8170.       /* Reset this field.  */
  8171.       p[news].accept_pending = 0;
  8172.  
  8173.       /* Allocate a buffer.  */
  8174.       p[news].fd_buff = (unsigned char *) malloc (BUF_SIZE);
  8175.       p[news].fd_leftover = 0;
  8176.  
  8177.       /* Get it started reading.  */
  8178.       hang_a_read (news);
  8179.  
  8180.       p[s].status = LISTENING;
  8181.       hang_an_accept (s);
  8182.  
  8183.       return news;
  8184.     }
  8185.       else
  8186.     {
  8187.       /* TWG */
  8188.       struct descriptor inetdesc;
  8189.       int size;
  8190.  
  8191.       /* Time out?  */
  8192.       if (wait_efn (s) == -1)
  8193.         return -1;
  8194.  
  8195.       /* Ok, get a new descriptor ...  */
  8196.       news = dup (0);
  8197.       if (news > 31)
  8198.         {
  8199.           errno = EMFILE;
  8200.           close (news);
  8201.           return -1;
  8202.         }
  8203.  
  8204.       /* Assign a new channel.  */
  8205.       inetdesc.size = 7;
  8206.       inetdesc.ptr = "_INET0:";
  8207.       st = sys$assign (&inetdesc, &p[news].channel, 0, 0);
  8208.       if (QIO_ST_FAILED)
  8209.         {
  8210.           p[s].accept_pending = 0;
  8211.           sys$clref (s);
  8212.           return -1;
  8213.         }
  8214.  
  8215.       /* From info needs an int length field! */
  8216.       size = sizeof (p[s].from) + 4;
  8217.       st = sys$qiow (0, p[news].channel, IO$_ACCEPT, p[news].iosb, 0, 0,
  8218.              &p[s].fromdummy, size, p[s].channel, 0, 0, 0);
  8219.  
  8220.       if (QIO_ST_FAILED || p[news].iosb[0] != SS$_NORMAL)
  8221.         {
  8222.           p[s].accept_pending = 0;
  8223.           sys$clref (s);
  8224.           return -1;
  8225.         }
  8226.  
  8227.       if (addr != 0)
  8228.         {
  8229.           /* Return the caller's info if requested.  */
  8230.           *addrlen = p[s].fromdummy;
  8231.           bcopy (&p[s].from, addr, *addrlen);
  8232.         }
  8233.  
  8234.       /* Fix up our new data structure.  */
  8235.       p[news].status = PASSIVE_CONNECTION;
  8236.       p[news].domain = AF_INET;
  8237.       p[news].passive = 1;
  8238.       p[news].fptr = fdopen (news, "r");
  8239.       /* Allocate a buffer.  */
  8240.       p[news].fd_buff = (unsigned char *) malloc (BUF_SIZE);
  8241.  
  8242.       /* Be prepared to accept msgs.  */
  8243.       hang_a_read (news);
  8244.  
  8245.       /* Get the old descriptor back onto accepting.  */
  8246.       hang_an_accept (s);
  8247.       return news;
  8248.     }
  8249.     }
  8250.   else
  8251.     /* We don't handle any other domain yet.  */
  8252.     return -1;
  8253. }
  8254.  
  8255. /* Recv routine.  */
  8256. int
  8257. VMSrecv (s, buf, len, flags)
  8258.      int s;
  8259.      char *buf;
  8260.      int len, flags;
  8261. {
  8262.   return recvfrom (s, buf, len, flags, 0, 0);
  8263. }
  8264.  
  8265. /* Revfrom routine.  */
  8266. int
  8267. VMSrecvfrom (s, buf, len, flags, from, fromlen)
  8268.      int s;
  8269.      char *buf;
  8270.      int len, flags;
  8271.      union socket_addr *from;
  8272.      int *fromlen;
  8273. {
  8274.   int number;
  8275.  
  8276.   if (!tcp_make)
  8277.     set_tcp_make ();
  8278.  
  8279.   if (p[s].domain != AF_INET && p[s].domain != AF_X25)
  8280.     return -1;
  8281.  
  8282.   /* If we're not onto datagrams, then it's possible that a previous
  8283.      call to recvfrom didn't read all the data, and left some behind.
  8284.      So first of all, look in our data buffer for any leftovers that
  8285.      will satisfy this read.  */
  8286.  
  8287.   /* We couldn't satisfy the request from previous calls so we must now
  8288.      wait for a message to come through.  */
  8289.   if (wait_efn (s) == -1)
  8290.     /* Timed out.  */
  8291.     return -1;
  8292.  
  8293.   if (p[s].closed_by_remote == 1)
  8294.     {
  8295.       /* This could have happened! */
  8296.       errno = ECONNRESET;
  8297.       return -1;
  8298.     }
  8299.  
  8300.   if (from != NULL)
  8301.     {
  8302.       if (tcp_make == CMU)
  8303.     {
  8304.       if (p[s].type == SOCK_DGRAM)
  8305.         {
  8306.           /* Not documented but we get the from data from the beginning of
  8307.          the data buffer.  */
  8308.           *fromlen = sizeof (p[s].from.in);
  8309.           from->in.sin_family = AF_INET;
  8310.           bcopy (&p[s].fd_buff[8], &(from->in.sin_port), 2);
  8311.           from->in.sin_port = htons (from->in.sin_port);
  8312.           bcopy (&p[s].fd_buff[0], &(from->in.sin_addr), 4);
  8313.  
  8314.           /* Remove the address data from front of data buffer.  */
  8315.           bcopy (p[s].fd_buff + 12, p[s].fd_buff, p[s].fd_buff_size);
  8316.         }
  8317.       else
  8318.         {
  8319.           *fromlen = p[s].fromlen;
  8320.           bcopy (&p[s].from, from, p[s].fromlen);
  8321.         }
  8322.     }
  8323.       else if (tcp_make == UCX)
  8324.     {
  8325.       *fromlen = p[s].fromdummy;
  8326.       bcopy (&p[s].from, from, p[s].fromdummy);
  8327.     }
  8328.       else
  8329.     {
  8330.       *fromlen = p[s].fromlen;
  8331.       bcopy (&p[s].from, from, p[s].fromlen);
  8332.     }
  8333.     }
  8334.  
  8335.   /* We may've received too much.  */
  8336.   number = p[s].fd_buff_size;
  8337.   if (number <= len)
  8338.     {
  8339.       /* If we haven't give back all the data available.  */
  8340.       bcopy (p[s].fd_buff, buf, number);
  8341.       p[s].fd_leftover = 0;
  8342.       hang_a_read (s);
  8343.       return (number);
  8344.     }
  8345.   else
  8346.     {
  8347.       /* If we have too much data then split it up.  */
  8348.       p[s].fd_leftover = p[s].fd_buff;
  8349.       bcopy (p[s].fd_leftover, buf, len);
  8350.       /* And change the pointers.  */
  8351.       p[s].fd_leftover += len;
  8352.       p[s].fd_buff_size -= len;
  8353.       return (len);
  8354.     }
  8355. }
  8356.  
  8357. /* Send routine.  */
  8358. int
  8359. VMSsend (s, msg, len, flags)
  8360.      int s;
  8361.      char *msg;
  8362.      int len, flags;
  8363. {
  8364.   return sendto (s, msg, len, flags, 0, 0);
  8365. }
  8366.  
  8367. /* Sendto routine.  */
  8368. int
  8369. VMSsendto (s, msg, len, flags, to, tolen)
  8370.      int s;
  8371.      unsigned char *msg;
  8372.      int len, flags;
  8373.      union socket_addr *to;
  8374.      int tolen;
  8375. {
  8376.   int i, j, st, size;
  8377.   unsigned char udpbuf[BUF_SIZE + 12];
  8378.   char infobuff[1024], lhost[32];
  8379.   unsigned short int temp;
  8380.  
  8381.   if (!tcp_make)
  8382.     set_tcp_make ();
  8383.  
  8384.   /* First remember who we sent it to and set the value of size.  */
  8385.   if (to != 0)
  8386.     {
  8387.       p[s].tolen = tolen;
  8388.       bcopy (to, &(p[s].to), tolen);
  8389.       size = tolen;
  8390.     }
  8391.   else
  8392.     size = 0;
  8393.  
  8394.   if (p[s].domain == AF_INET)
  8395.     {
  8396.       /* We might never have started a read for udp (socket/sendto) so
  8397.      put one here.  */
  8398.       if (p[s].type == SOCK_DGRAM)
  8399.     hang_a_read (s);
  8400.  
  8401.       if (tcp_make == CMU)
  8402.     {
  8403.       if (p[s].type == SOCK_DGRAM)
  8404.         {
  8405.           /* We might never have opened up a udp connection yet,
  8406.          so check.  */
  8407.           if (p[s].cmu_open != 1)
  8408.         {
  8409.           st = sys$qiow (0, p[s].channel, TCP$OPEN, p[s].iosb, 0, 0,
  8410.                  0, 0, 0, 0, 1, 0);
  8411.           if (QIO_ST_FAILED)
  8412.             return -1;
  8413.  
  8414.           p[s].cmu_open = 1;
  8415.           sys$qiow (0, p[s].channel, TCP$INFO, p[s].iosb,
  8416.                 0, 0, &infobuff, 1024, 0, 0, 0, 0);
  8417.           bcopy (infobuff + 264, &(p[s].name.in.sin_port), 2);
  8418.           p[s].name.in.sin_port = htons (p[s].name.in.sin_port);
  8419.           bcopy (infobuff + 136, lhost, infobuff[1]);
  8420.           lhost[infobuff[1]] = '\0';
  8421.           sys$qiow (0, p[s].channel, GTHST, p[s].iosb,
  8422.                 0, 0, &infobuff, 1024, 1, lhost, 0, 0);
  8423.           bcopy (infobuff + 4, &(p[s].name.in.sin_addr), 4);
  8424.         }
  8425.  
  8426.           /* This isn't well documented.  To send to a UDP socket, we
  8427.          need to put the address info at the beginning of the
  8428.          buffer.  */
  8429.           bcopy (msg, udpbuf + 12, len);
  8430.           bcopy (&p[s].to.in.sin_addr, udpbuf + 4, 4);
  8431.           temp = ntohs (p[s].to.in.sin_port);
  8432.           bcopy (&temp, udpbuf + 10, 2);
  8433.           bcopy (&p[s].name.in.sin_addr, udpbuf, 4);
  8434.           temp = ntohs (p[s].name.in.sin_port);
  8435.           bcopy (&temp, udpbuf + 8, 2);
  8436.           temp = len + 12;
  8437.           st = sys$qiow (0, p[s].channel, TCP$SEND, p[s].iosb, 0, 0,
  8438.                  udpbuf, temp, 0, 0, 0, 0);
  8439.           if (QIO_FAILED)
  8440.         return -1;
  8441.         }
  8442.       else
  8443.         {
  8444.           /* TCP (! UDP)  */
  8445.           st = sys$qiow (0, p[s].channel, TCP$SEND, p[s].iosb, 0, 0,
  8446.                  msg, len, 0, 0, 0, 0);
  8447.           if (QIO_FAILED)
  8448.         return -1;
  8449.         }
  8450.       return len;
  8451.     }
  8452.       else if (tcp_make == UCX)
  8453.     {
  8454.       struct itemlist rhost;
  8455.       rhost.length = sizeof (struct sockaddr_in);
  8456.       rhost.code = 0;
  8457.       rhost.dataptr = (char *) &p[s].to;
  8458.  
  8459.       st = sys$qiow (0, p[s].channel, IO$_WRITEVBLK, p[s].iosb, 0, 0,
  8460.              msg, len, &rhost, 0, 0, 0);
  8461.       if (QIO_FAILED)
  8462.         return -1;
  8463.  
  8464.       return len;
  8465.     }
  8466.       else
  8467.     {
  8468.       /* TWG */
  8469.       st = sys$qiow (0, p[s].channel, IO$_WRITEVBLK, p[s].iosb,
  8470.              0, 0, msg, len, 0, &p[s].to, size, 0);
  8471.       if (QIO_FAILED)
  8472.         return -1;
  8473.  
  8474.       return len;
  8475.     }
  8476.     }
  8477.   else
  8478.     /* We don't handle any other domain yet.  */
  8479.     return -1;
  8480. }
  8481.  
  8482. /* Getsockname routine.  */
  8483. int
  8484. VMSgetsockname (s, name, namelen)
  8485.      int s;
  8486.      union socket_addr *name;
  8487.      int *namelen;
  8488. {
  8489.   int st;
  8490.  
  8491.   if (!tcp_make)
  8492.     set_tcp_make ();
  8493.  
  8494.   if (p[s].domain == AF_INET)
  8495.     {
  8496.       if (tcp_make == CMU)
  8497.     {
  8498.       /* For CMU we just return values held in our data structure.  */
  8499.       *namelen = p[s].namelen;
  8500.       bcopy (&(p[s].name), name, *namelen);
  8501.       return (0);
  8502.     }
  8503.       else if (tcp_make == UCX)
  8504.     {
  8505.       /* An item_list_3 descriptor.  */
  8506.       struct itemlist lhost;
  8507.  
  8508.       lhost.length = *namelen;
  8509.       lhost.code = 0;
  8510.       lhost.dataptr = (char *) name;
  8511.  
  8512.       /* Fill in namelen with actual ret len value.  */
  8513.       lhost.retlenptr = (short int *) namelen;
  8514.  
  8515.       st = sys$qiow (0, p[s].channel, IO$_SENSEMODE, p[s].iosb, 0, 0,
  8516.              0, 0, &lhost, 0, 0, 0);
  8517.       if (QIO_FAILED)
  8518.         return -1;
  8519.  
  8520.       return 0;
  8521.     }
  8522.       else
  8523.     {
  8524.       /* TWG gives us the information. */
  8525.       st = sys$qiow (0, p[s].channel, IO$_GETSOCKNAME, p[s].iosb,
  8526.              0, 0, name, namelen, 0, 0, 0, 0);
  8527.       if (QIO_FAILED)
  8528.         return -1;
  8529.  
  8530.       return 0;
  8531.     }
  8532.     }
  8533.   else
  8534.     /* We don't handle any other domain yet.  */
  8535.     return -1;
  8536. }
  8537.  
  8538. /* Select routine.  */
  8539. int
  8540. VMSselect (nfds, readfds, writefds, exceptfds, timeout)
  8541.      int nfds;
  8542.      fd_set *readfds, *writefds, *exceptfds;
  8543.      struct timeval *timeout;
  8544. {
  8545.   int timer, fd, alarm_set, total, end;
  8546.   long mask, cluster;
  8547.   struct descriptor termdesc;
  8548.   static fd_set new_readfds, new_writefds, new_exceptfds;
  8549.  
  8550.   FD_ZERO (&new_readfds);
  8551.   FD_ZERO (&new_writefds);
  8552.   FD_ZERO (&new_exceptfds);
  8553.   total = 0;
  8554.  
  8555.   /* Assign a terminal channel if we haven't already.  */
  8556.   if (terminal.chan == -1)
  8557.     {
  8558.       termdesc.size = 10;
  8559.       termdesc.ptr = "SYS$INPUT:";
  8560.       sys$assign (&termdesc, &terminal.chan, 0, 0);
  8561.     }
  8562.   alarm_set = 0;
  8563.   if (timeout != NULL)
  8564.     {
  8565.       /* If a timeout is given then set the alarm.  */
  8566.       end = timeout->tv_sec;
  8567.       if (timer != 0)
  8568.     {
  8569.       /* We need to reset the alarm if it didn't fire, but we set it.  */
  8570.       alarm_set = 1;
  8571.       si_alarm (end);
  8572.     }
  8573.     }
  8574.   else
  8575.     end = 1;
  8576.  
  8577.   do
  8578.     {
  8579.       if (exceptfds)
  8580.     {
  8581.        /* Nothing */ ;
  8582.     }
  8583.  
  8584.       if (writefds)
  8585.     {
  8586.       for (fd = 0; fd < nfds; fd++)
  8587.         if (FD_ISSET (fd, writefds))
  8588.           {
  8589.         if (p[fd].connect_pending)
  8590.            /* Nothing */ ;
  8591.         else if ((p[fd].status == ACTIVE_CONNECTION)
  8592.              || (p[fd].status == PASSIVE_CONNECTION))
  8593.           {
  8594.             FD_SET (fd, &new_writefds);
  8595.             total++;
  8596.           }
  8597.           }
  8598.     }
  8599.  
  8600.       if (readfds)
  8601.     {
  8602.       /* True if data pending or an accept.  */
  8603.       for (fd = 3; fd < nfds; fd++)
  8604.         if (FD_ISSET (fd, readfds) &&
  8605.         ((p[fd].fd_buff_size != -1) || (p[fd].accept_pending == 1)))
  8606.           {
  8607.         FD_SET (fd, &new_readfds);
  8608.         total++;
  8609.           }
  8610.     }
  8611.  
  8612.       if (total || (end == 0))
  8613.     break;
  8614.  
  8615.       /* Otherwise, wait on an event flag.  It's possible that the wait can
  8616.      be stopped by a spurious event flag being set -- i.e. one that's
  8617.      got a status not normal.  So we've got to be prepared to loop
  8618.      around the wait until a valid reason happens.  */
  8619.  
  8620.       /* Set up the wait mask.  */
  8621.       cluster = 0;
  8622.       mask = 0;
  8623.       for (fd = 3; fd < nfds; fd++)
  8624.     {
  8625.       sys$clref (fd);
  8626.       if (readfds)
  8627.         if FD_ISSET
  8628.           (fd, readfds) mask |= (1 << fd);
  8629.       if (writefds)
  8630.         if FD_ISSET
  8631.           (fd, writefds) mask |= (1 << fd);
  8632.       if (exceptfds)
  8633.         if FD_ISSET
  8634.           (fd, exceptfds) mask |= (1 << fd);
  8635.     }
  8636.  
  8637.       mask |= (1 << TIMER_EFN);
  8638.  
  8639.       /* Clear it off just in case.  */
  8640.       sys$clref (TIMER_EFN);
  8641.  
  8642.       /* Wait around.  */
  8643.       sys$wflor (cluster, mask);
  8644.  
  8645.       mask = 0;
  8646.       if (read_efn (TIMER_EFN))
  8647.     {
  8648.       errno = EINTR;
  8649.       break;
  8650.     }
  8651.   } while (1);
  8652.   /*NOTREACHED*/
  8653.  
  8654.   /* Unset the alarm if we set it.  */
  8655.   if (alarm_set == 1)
  8656.     alarm (0);
  8657.  
  8658.   if (readfds)
  8659.     *readfds = new_readfds;
  8660.  
  8661.   if (writefds)
  8662.     *writefds = new_writefds;
  8663.  
  8664.   if (exceptfds)
  8665.     *exceptfds = new_exceptfds;
  8666.  
  8667.   return total;
  8668. }
  8669.  
  8670. /* Shutdown routine.  */
  8671. VMSshutdown (s, how)
  8672.      int s, how;
  8673. {
  8674.   int st;
  8675.   int ucx_how;
  8676.  
  8677.   if (!tcp_make)
  8678.     set_tcp_make ();
  8679.  
  8680.   if (p[s].domain == AF_INET)
  8681.     {
  8682.       if (tcp_make == CMU)
  8683.     {
  8684.       /* For CMU we just close off.  */
  8685.       si_close (s);
  8686.       return 0;
  8687.     }
  8688.       else if (tcp_make == UCX)
  8689.     {
  8690.       st = sys$qiow (0, p[s].channel, IO$_DEACCESS | IO$M_SHUTDOWN,
  8691.              p[s].iosb, 0, 0, 0, 0, 0, how, 0, 0);
  8692.       if (QIO_FAILED)
  8693.         return -1;
  8694.  
  8695.       return 0;
  8696.     }
  8697.       else
  8698.     {
  8699.       /* TWG lets us do it.  */
  8700.       st = sys$qiow (0, p[s].channel, IO$_SHUTDOWN, p[s].iosb, 0, 0, how,
  8701.              0, 0, 0, 0, 0);
  8702.       if (QIO_FAILED)
  8703.         return -1;
  8704.  
  8705.       return 0;
  8706.     }
  8707.     }
  8708.   else                /* it wasn't a socket */
  8709.     return -1;
  8710. }
  8711.  
  8712. /*   */
  8713.  
  8714. /* The following routines are used by the above socket calls.  */
  8715.  
  8716. /* hang_a_read sets up a read to be finished at some later time.  */
  8717. hang_a_read (s)
  8718.      int s;
  8719. {
  8720.   extern int read_ast ();
  8721.   int size, st;
  8722.  
  8723.   /* Don't bother if we already did it.  */
  8724.   if (p[s].read_outstanding == 1)
  8725.     return;
  8726.  
  8727.   /* Have a read outstanding.  */
  8728.   p[s].read_outstanding = 1;
  8729.   size = sizeof (p[s].from) + 4;
  8730.   sys$clref (s);
  8731.  
  8732.   /* Clear off the event flag just in case, and reset the buf size.  */
  8733.   p[s].fd_buff_size = -1;
  8734.   if (p[s].domain == AF_INET)
  8735.     {
  8736.       if (tcp_make == CMU)
  8737.     {
  8738.       st = sys$qio (s, p[s].channel, TCP$RECEIVE, p[s].iosb, read_ast,
  8739.             &p[s], p[s].fd_buff, BUF_SIZE, 0, 0, 0, 0);
  8740.       if (QIO_ST_FAILED)
  8741.         return -1;
  8742.     }
  8743.       else if (tcp_make == UCX)
  8744.     {
  8745.  
  8746.       p[s].rhost.length = sizeof (struct sockaddr_in);
  8747.       p[s].rhost.code = 0;
  8748.       p[s].rhost.dataptr = (char *) &p[s].from;
  8749.       p[s].rhost.retlenptr = &p[s].fromdummy;
  8750.  
  8751.       st = sys$qio (s, p[s].channel, IO$_READVBLK, p[s].iosb, read_ast,
  8752.             &p[s], p[s].fd_buff, BUF_SIZE, &p[s].rhost, 0, 0, 0);
  8753.       if (QIO_ST_FAILED)
  8754.         return -1;
  8755.     }
  8756.       else
  8757.     {
  8758.       /* TWG */
  8759.       st = sys$qio (s, p[s].channel, IO$_READVBLK, p[s].iosb, read_ast,
  8760.             &p[s], p[s].fd_buff, BUF_SIZE, 0, &p[s].fromlen,
  8761.             size, 0);
  8762.       if (QIO_ST_FAILED)
  8763.         return -1;
  8764.     }
  8765.     }
  8766.   else
  8767.     /* We don't handle any other domain yet.  */
  8768.     return -1;
  8769. }
  8770.  
  8771. /* hang_an_accept waits for a connection request to come in.  */
  8772. hang_an_accept (s)
  8773.      int s;
  8774. {
  8775.   extern int accept_ast ();
  8776.   int st;
  8777.  
  8778.   /* Clear the event flag just in case.  */
  8779.   sys$clref (s);
  8780.  
  8781.   /* Reset our flag & buf size.  */
  8782.   p[s].accept_pending = 0;
  8783.   p[s].fd_buff_size = -1;
  8784.   if (p[s].domain == AF_INET)
  8785.     {
  8786.       if (tcp_make == CMU)
  8787.     {
  8788.       st = sys$qio (s, p[s].channel, TCP$OPEN, p[s].iosb, accept_ast,
  8789.             &p[s], 0, 0, ntohs (p[s].name.in.sin_port), 0, 0, 0);
  8790.       if (QIO_ST_FAILED)
  8791.         return -1;
  8792.     }
  8793.       else if (tcp_make == UCX)
  8794.     {
  8795.       struct descriptor inetdesc;
  8796.  
  8797.       /* Assign channel for actual connection off listener.  */
  8798.       inetdesc.size = 3;
  8799.       inetdesc.ptr = "BG:";
  8800.       if (sys$assign (&inetdesc, &p[s].ucx_accept_chan, 0,
  8801.               0) != SS$_NORMAL)
  8802.         return -1;
  8803.  
  8804.       /* UCX's accept returns remote host info and the channel for a new
  8805.          socket to perform reads/writes on, so a sys$assign isn't
  8806.          really necessary.  */
  8807.       p[s].rhost.length = sizeof (struct sockaddr_in);
  8808.       p[s].rhost.dataptr = (char *) &p[s].from;
  8809.       p[s].fromdummy = 0;
  8810.       p[s].rhost.retlenptr = &p[s].fromdummy;
  8811.  
  8812.       st = sys$qio (s, p[s].channel, IO$_ACCESS | IO$M_ACCEPT, p[s].iosb,
  8813.             accept_ast, &p[s], 0, 0, &p[s].rhost,
  8814.             &p[s].ucx_accept_chan, 0, 0);
  8815.       if (QIO_ST_FAILED)
  8816.         return -1;
  8817.     }
  8818.       else
  8819.     {
  8820.       st = sys$qio (s, p[s].channel, IO$_ACCEPT_WAIT, p[s].iosb,
  8821.             accept_ast, &p[s], 0, 0, 0, 0, 0, 0);
  8822.       if (QIO_ST_FAILED)
  8823.         return -1;
  8824.     }
  8825.     }
  8826.   else
  8827.     /* We don't handle any other domain yet.  */
  8828.     return -1;
  8829. }
  8830.  
  8831. /* wait_efn just sets up a wait on either an event or the timer.  */
  8832. wait_efn (s)
  8833.      int s;
  8834. {
  8835.   long mask, cluster;
  8836.  
  8837.   cluster = 0;
  8838.   sys$clref (TIMER_EFN);
  8839.   mask = (1 << s) | (1 << TIMER_EFN);
  8840.   sys$wflor (cluster, mask);
  8841.  
  8842.   if (read_efn (TIMER_EFN))
  8843.     {
  8844.       errno = EINTR;
  8845.       return -1;
  8846.     }
  8847.  
  8848.   return 0;
  8849. }
  8850.  
  8851. /* read_ast is called by the system whenever a read is done.  */
  8852. read_ast (p)
  8853.      struct fd_entry *p;
  8854. {
  8855.   int i, j;
  8856.   unsigned char *v, *w;
  8857.  
  8858.   /* Reset the outstanding flag.  */
  8859.   p->read_outstanding = 0;
  8860.   if (p->iosb[0] == SS$_NORMAL)
  8861.     {
  8862.       /* Check no errors.  */
  8863.       p->fd_buff_size = p->iosb[1];
  8864.       if (tcp_make == CMU)
  8865.     {
  8866.       /* fiddle for DGRMs */
  8867.       if (p->type == SOCK_DGRAM)
  8868.         p->fd_buff_size -= 12;
  8869.     }
  8870.       if (p->sig_req == 1)
  8871.     gsignal (SIGIO);
  8872.     }
  8873.   else if (p->iosb[0] == SS$_CLEARED)
  8874.     p->closed_by_remote = 1;
  8875.   else if (tcp_make == UCX)
  8876.     {
  8877.       if (p->iosb[0] == SS$_LINKDISCON)
  8878.     p->closed_by_remote = 1;
  8879.     }
  8880. }
  8881.  
  8882. /* accept_ast is called whenever an incoming call is detected.  */
  8883. accept_ast (p)
  8884.      struct fd_entry *p;
  8885. {
  8886.   if (p->iosb[0] == SS$_NORMAL)
  8887.     p->accept_pending = 1;
  8888.   else
  8889.     /* If it failed set up another listen.  */
  8890.     listen (p->s, p[p->s].backlog);
  8891. }
  8892.  
  8893. /* connect_ast is called whenever an async connect is made.  */
  8894. connect_ast (p)
  8895.      struct fd_entry *p;
  8896. {
  8897.   p->connect_pending = 0;
  8898.   if ((p->connected = p->iosb[0]) == SS$_NORMAL)
  8899.     {
  8900.       /* We made the connection.  */
  8901.       p->status = ACTIVE_CONNECTION;
  8902.  
  8903.       /* Be prepared to accept a msg.  */
  8904.       hang_a_read (p->s);
  8905.     }
  8906. }
  8907.  
  8908. /*   */
  8909. /* These routines handle stream I/O.  */
  8910.  
  8911. /* si_close -- must close off any connection in progress.  */
  8912. si_close (s)
  8913.      int s;
  8914. {
  8915.   if (!tcp_make)
  8916.     set_tcp_make ();
  8917.  
  8918.   if ((s < 0) || (s > 31))
  8919.     return -1;
  8920.  
  8921.   if (p[s].channel != 0)
  8922.     {
  8923.       /* Was it one of our descriptors? */
  8924.       if (p[s].domain == AF_INET)
  8925.     {
  8926.       if (tcp_make == CMU)
  8927.         sys$qiow (0, p[s].channel, TCP$CLOSE, p[s].iosb,
  8928.               0, 0, 0, 0, 0, 0, 0, 0);
  8929.       if (p[s].status != HANDED_OFF)
  8930.         sys$dassgn (p[s].channel);
  8931.       close (s);
  8932.       free (p[s].fd_buff);
  8933.       p_initialise (s);
  8934.     }
  8935.       return 0;
  8936.     }
  8937.   else
  8938.     {
  8939.       /* Re-initialise data structure just in case.  */
  8940.       p[s].fd_buff_size = -1;
  8941.       p[s].accept_pending = 0;
  8942.       p[s].status = INITIALISED;
  8943.       return close (s);
  8944.     }
  8945. }
  8946.  
  8947. /* si_alarm -- insert a call to our own alarm function.  */
  8948. si_alarm (i)
  8949.      int i;
  8950. {
  8951.   extern int pre_alarm ();
  8952.  
  8953.   /* Make the call to pre_alarm instead of what the user wants;
  8954.      pre_alarm will call his routine when it finishes.  */
  8955.   /* VAX needs this call each time! */
  8956.   signal (SIGALRM, pre_alarm);
  8957.   alarm (i);
  8958. }
  8959.  
  8960. /* pre_alarm -- gets called first on an alarm signal.  */
  8961. pre_alarm ()
  8962. {
  8963.   /* Come here first so we can set our timer event flag.  */
  8964.   sys$setef (TIMER_EFN);
  8965.   (*alarm_function) ();
  8966. }
  8967.  
  8968. /* p_initialise - initialise our data array.  */
  8969. p_initialise (s)
  8970.      int s;
  8971. {
  8972.   int j;
  8973.   for (j = 0; j < 4; j++)
  8974.     p[s].iosb[j] = 0;
  8975.   p[s].channel = 0;
  8976.   p[s].fd_buff_size = -1;
  8977.   p[s].accept_pending = 0;
  8978.   p[s].connect_pending = 0;
  8979.   p[s].connected = 0;
  8980.   p[s].fd_buff = NULL;
  8981.   p[s].fd_leftover = NULL;
  8982.   p[s].fptr = NULL;
  8983.   p[s].s = s;
  8984.   p[s].name.in.sin_port = 0;
  8985.   p[s].masklen = 4;
  8986.   for (j = 0; j < 16; j++)
  8987.     p[s].mask[j] = 0xff;
  8988.   p[s].need_header = 0;
  8989.   p[s].status = INITIALISED;
  8990.   p[s].read_outstanding = 0;
  8991.   p[s].cmu_open = 0;
  8992.   p[s].x25_listener = 0;
  8993.   p[s].mother = s;
  8994.   p[s].child = 0;
  8995.   p[s].no_more_accepts = 0;
  8996.   p[s].closed_by_remote = 0;
  8997.   p[s].non_blocking = 0;
  8998.   p[s].sig_req = 0;
  8999.   sys$clref (s);
  9000. }
  9001.  
  9002. /* read_efn -- see whether an event flag is set.  */
  9003. read_efn (i)
  9004.      int i;
  9005. {
  9006.   int j;
  9007.   sys$readef (i, &j);
  9008.   j &= (1 << i);
  9009.  
  9010.   return j;
  9011. }
  9012.  
  9013. static
  9014. set_tcp_make ()
  9015. {
  9016.   struct descriptor inetdesc;
  9017.   int channel;
  9018.   /* first try CMU */
  9019.   inetdesc.size = 3;
  9020.   inetdesc.ptr = "IP:";
  9021.   if (sys$assign (&inetdesc, &channel, 0, 0) == SS$_NORMAL)
  9022.     {
  9023.       sys$dassgn (channel);
  9024.       tcp_make = CMU;
  9025.       return;
  9026.     }
  9027.  
  9028.   /* next try TWG */
  9029.   inetdesc.size = 7;
  9030.   inetdesc.ptr = "_INET0:";
  9031.   if (sys$assign (&inetdesc, &channel, 0, 0) == SS$_NORMAL)
  9032.     {
  9033.       sys$dassgn (channel);
  9034.       tcp_make = WG;
  9035.       return;
  9036.     }
  9037.  
  9038.   /* next try UCX */
  9039.   inetdesc.size = 4;
  9040.   inetdesc.ptr = "BG0:";
  9041.   if (sys$assign (&inetdesc, &channel, 0, 0) == SS$_NORMAL)
  9042.     {
  9043.       sys$dassgn (channel);
  9044.       tcp_make = UCX;
  9045.       return;
  9046.     }
  9047.  
  9048.   /* nothing there oh dear!*/
  9049.   tcp_make = NONE;
  9050.   return;
  9051. }
  9052.  
  9053. static char *
  9054. getdevicename (channel)
  9055.      unsigned short int channel;
  9056. {
  9057.   int st;
  9058.   struct
  9059.   {
  9060.     struct itemlist id;
  9061.     int eol;
  9062.   } itmlst;
  9063.   static char name[64];
  9064.   short int lgth;
  9065.  
  9066.   name[0] = '\0';
  9067.   itmlst.id.code = DVI$_DEVNAM;
  9068.   itmlst.id.length = 64;
  9069.   itmlst.id.dataptr = name;
  9070.   itmlst.id.retlenptr = &lgth;
  9071.   itmlst.eol = 0;
  9072.   st = sys$getdvi (0, channel, 0, &itmlst, 0, 0, 0, 0);
  9073.   if (QIO_ST_FAILED)
  9074.     fprintf (stderr, "error getting device name %d\n", st);
  9075.  
  9076.   return (name);
  9077. }
  9078. $EOD
  9079. $!
  9080. $CREATE [.archie.vms]fd.h
  9081. $DECK
  9082. #ifndef _VMS_FD
  9083. #define _VMS_FD
  9084.  
  9085. typedef struct fd_set
  9086. {
  9087.   int fds_bits[1];
  9088. } fd_set;
  9089.  
  9090. #define FD_SETSIZE          (sizeof (fd_set) * 8)
  9091. #define FD_SET(f,s)         ((s)->fds_bits[0] |= (1 << (f)))
  9092. #define FD_CLR(f,s)         ((s)->fds_bits[0] &= ~(1 << (f)))
  9093. #define FD_ISSET(f,s)       ((s)->fds_bits[0] & (1 << (f)))
  9094. #define FD_ZERO(s)          ((s)->fds_bits[0] = 0)
  9095.  
  9096. #endif /* _VMS_FD */
  9097. $EOD
  9098. $!
  9099. $CREATE [.archie.vms]in.h
  9100. $DECK
  9101. /* netinet/in.h */
  9102. struct in_addr
  9103. {
  9104.   union
  9105.   {
  9106.     struct
  9107.     {
  9108.       unsigned char s_b1, s_b2, s_b3, s_b4;
  9109.     } S_un_b;
  9110.     struct
  9111.     {
  9112.       unsigned short s_w1, s_w2;
  9113.     } S_un_w;
  9114.     unsigned long S_addr;
  9115.   } S_un;
  9116. #define   s_addr S_un.S_addr
  9117. #define   s_host S_un.S_un_b.s_b2
  9118. #define   s_net  S_un.S_un_b.s_b1
  9119. #define   s_imp  S_un.S_un_w.s_w2
  9120. #define   s_impno S_un.S_un_b.s_b4
  9121. #define   s_lh   S_un.S_un_b.s_b3
  9122. };
  9123.  
  9124. #define INADDR_ANY 0x00000000
  9125. #define INADDR_BROADCAST 0xffffffff
  9126. #define INADDR_LOOPBACK 0x7f000001
  9127.  
  9128. struct sockaddr_in
  9129. {
  9130.   short sin_family;
  9131.   unsigned short sin_port;
  9132.   struct in_addr sin_addr;
  9133.   char sin_zero[8];
  9134. };
  9135.  
  9136. #define ntohl(x) (( (((unsigned long) x) >> 24)& 0x000000ff ) |\
  9137.                   ( (((unsigned long) x) >> 8) & 0x0000ff00 ) |\
  9138.                   ( (((unsigned long) x) << 8) & 0x00ff0000 ) |\
  9139.                   ( (((unsigned long) x) << 24)& 0xff000000 ))
  9140. #define ntohs(x) (( (((unsigned short) x) >> 8) |\
  9141.                   ( (((unsigned short) x) << 8)) & 0xffff ))
  9142. #define htonl(x) (( (((unsigned long) x) >> 24)& 0x000000ff ) |\
  9143.                   ( (((unsigned long) x) >> 8) & 0x0000ff00 ) |\
  9144.                   ( (((unsigned long) x) << 8) & 0x00ff0000 ) |\
  9145.                   ( (((unsigned long) x) << 24)& 0xff000000 ))
  9146. #define htons(x) (( (((unsigned short) x) >> 8) |\
  9147.                   ( (((unsigned short) x) << 8)) & 0xffff ))
  9148.  
  9149. #define IPPORT_RESERVED 1024
  9150. $EOD
  9151. $!
  9152. $CREATE [.archie.vms]pseudos.h
  9153. $DECK
  9154. /* These are so we don't end up using the MultiNet versions.  */
  9155. #define socket    VMSsocket
  9156. #define bind    VMSbind
  9157. #define connect    VMSconnect
  9158. #define listen    VMSlisten
  9159. #define accept    VMSaccept
  9160. #define select    VMSselect
  9161. #define recv    VMSrecv
  9162. #define recvfrom    VMSrecvfrom
  9163. #define send    VMSsend
  9164. #define sendto    VMSsendto
  9165. #define getsockname    VMSgetsockname
  9166. #define shutdown    VMSshutdown
  9167. #define getsockopt    VMSgetsockopt
  9168. #define setsockopt    VMSsetsockopt
  9169. $EOD
  9170. $!
  9171. $CREATE [.archie.vms]signal.h
  9172. $DECK
  9173. /* signal.h */
  9174. #define SIGURG  16
  9175. #define SIGTSTP 18
  9176. #define SIGCHLD 20
  9177. #define SIGIO   23
  9178. #define sigmask(m) (1 << ((m)-1))
  9179.  
  9180. #ifndef __GNUC__
  9181. # include <sys$library:signal.h>
  9182. #else /* Gnu C */
  9183. # include <gnu_cc_include:[000000]signal.h>
  9184. #endif /* not Gnu C */
  9185. $EOD
  9186. $!
  9187. $CREATE [.archie.vms]socket.h
  9188. $DECK
  9189. /* sys/socket.h */
  9190. #define SOCK_STREAM     1
  9191. #define SOCK_DGRAM      2
  9192.  
  9193. #define SO_DEBUG        0x01
  9194. #define SO_ACCEPTCONN   0x02
  9195. #define SO_REUSEADDR    0x04
  9196. #define SO_KEEPALIVE    0x08
  9197. #define SO_LINGER       0x80
  9198. #define SO_DONTLINGER   (~SO_LINGER)
  9199.  
  9200. #define AF_UNSPEC       0
  9201. #define AF_ERROR        0
  9202. #define AF_INET         2
  9203. #define AF_CCITT        10
  9204. #define AF_X25          10
  9205.  
  9206. struct sockaddr
  9207. {
  9208.   unsigned short sa_family;
  9209.   char sa_data[14];
  9210. };
  9211.  
  9212. #define SOL_SOCKET      0xffff
  9213.  
  9214. #define MSG_OOB 1
  9215. #define MSG_PEEK 2
  9216. $EOD
  9217. $!
  9218. $CREATE [.archie.vms]time.h
  9219. $DECK
  9220. #ifndef __PKTIME
  9221. #define __PKTIME
  9222.  
  9223. struct timeval
  9224. {
  9225.   long tv_sec;
  9226.   long tv_usec;
  9227. };
  9228.  
  9229. struct timezone
  9230. {
  9231.   int tz_minuteswest;
  9232.   int tz_dsttime;
  9233. };
  9234.  
  9235. struct itimerval
  9236. {
  9237.   struct timeval it_interval;
  9238.   struct timeval it_value;
  9239. };
  9240.  
  9241. #define ITIMER_REAL 0
  9242. #define timerclear(x) (x)->tv_sec = (x)->tv_usec = 0
  9243.  
  9244. #ifndef __GNUC__
  9245. # include <sys$library:time.h>
  9246. #else /* not Gnu C */
  9247. # include <gnu_cc_include:[000000]time.h>
  9248. #endif /* Gnu C */
  9249.  
  9250. #endif /* __PKTIME */
  9251. $EOD
  9252. $!
  9253. $CREATE [.archie.vms]types.h
  9254. $DECK
  9255. /* sys/types.h */
  9256. #ifndef _types_
  9257. #define _types_
  9258.  
  9259. #ifndef __GNUC__
  9260. # include <sys$library:stddef.h>
  9261. #endif /* not Gnu C */
  9262.  
  9263. typedef unsigned char u_char;
  9264. typedef unsigned short u_short;
  9265. typedef unsigned int u_int;
  9266. typedef unsigned long u_long;
  9267.  
  9268. typedef long daddr_t;
  9269. typedef char *caddr_t;
  9270.  
  9271. #include <sys$library:types.h>
  9272.  
  9273. typedef unsigned short ino_t;
  9274. typedef char *dev_t;
  9275. typedef unsigned int off_t;
  9276. typedef long key_t;
  9277.  
  9278. #include "[.vms]fd.h"
  9279.  
  9280. #endif /* _types */
  9281. $EOD
  9282. $!
  9283. $CREATE [.archie.vms]network.h
  9284. $DECK
  9285. /* Miscellaneous things for the networking library.  */
  9286.  
  9287. /* Actually an itemlist_3, but can be used for itemlist_2's.  */
  9288. struct itemlist
  9289. {
  9290.   short length;
  9291.   short code;
  9292.   char *dataptr;
  9293.   short *retlenptr;
  9294. };
  9295.  
  9296. union socket_addr
  9297. {
  9298.   struct sockaddr_in in;
  9299. };
  9300.  
  9301. #define   TCP$SEND        (IO$_WRITEVBLK)
  9302. #define   TCP$RECEIVE     (IO$_READVBLK)
  9303. #define   TCP$OPEN        (IO$_CREATE)
  9304. #define   TCP$CLOSE       (IO$_DELETE)
  9305. #define   TCP$ABORT       (IO$_DEACCESS)
  9306. #define   TCP$STATUS      (IO$_ACPCONTROL)
  9307. #define   TCP$INFO        (IO$_MODIFY)
  9308. #define   GTHST           (IO$_SKIPFILE)
  9309.  
  9310. #define   IO$_SEND        (IO$_WRITEVBLK)
  9311. #define   IO$_RECEIVE     (IO$_READVBLK)
  9312. #ifndef IO$S_FCODE
  9313. #define IO$S_FCODE 0x0006
  9314. #endif
  9315. #define   IO$_SOCKET      (IO$_ACCESS | (0 << IO$S_FCODE))
  9316. #define   IO$_BIND        (IO$_ACCESS | (1 << IO$S_FCODE))
  9317. #define   IO$_LISTEN      (IO$_ACCESS | (2 << IO$S_FCODE))
  9318. #define   IO$_ACCEPT      (IO$_ACCESS | (3 << IO$S_FCODE))
  9319. #define   IO$_CONNECT     (IO$_ACCESS | (4 << IO$S_FCODE))
  9320. #define   IO$_SETSOCKOPT  (IO$_ACCESS | (5 << IO$S_FCODE))
  9321. #define   IO$_GETSOCKOPT  (IO$_ACCESS | (6 << IO$S_FCODE))
  9322. #define   IO$_IOCTL       (IO$_ACCESS | (8 << IO$S_FCODE))
  9323. #define   IO$_ACCEPT_WAIT (IO$_ACCESS | (10 << IO$S_FCODE))
  9324. #define   IO$_NETWORK_PTY (IO$_ACCESS | (11 << IO$S_FCODE))
  9325. #define   IO$_SHUTDOWN    (IO$_ACCESS | (12 << IO$S_FCODE))
  9326. #define   IO$_GETSOCKNAME (IO$_ACCESS | (13 << IO$S_FCODE))
  9327. #define      SETCHAR_HANDOFF (1<<2)
  9328.  
  9329. #define   NFB$C_DECLNAME   0x15
  9330.  
  9331. #define TIMER_EFN 1
  9332. #define TERM_EFN  2
  9333. #define BUF_SIZE 2000
  9334.  
  9335. #define INITIALISED 0
  9336. #define ACTIVE_CONNECTION 1
  9337. #define PASSIVE_CONNECTION 2
  9338. #define LISTENING 3
  9339. #define HANDED_OFF 4
  9340.  
  9341. static struct fd_entry
  9342. {
  9343.   unsigned short int channel;    /* vms channel assigned to this socket */
  9344.   unsigned short int iosb[4];    /* returned status block */
  9345.   int fd_buff_size;        /* number of chrs in buffer still to be read */
  9346.   int accept_pending;        /* a call is waiting to be accepted */
  9347.   int connect_pending;        /* a connect is outstanding*/
  9348.   int connected;        /* this descriptor is connected */
  9349.   unsigned char *fd_buff;    /* pointer to buffer dyn assigned */
  9350.   unsigned char *fd_leftover;    /* pointer to any chrs still to be read */
  9351.   FILE *fptr;            /* we need to assgn a file ptr for stream io */
  9352.   int s;            /* socket number - needed in the ast's */
  9353.   int namelen;            /* our socket address name */
  9354.   union socket_addr name;
  9355.   short int fromdummy;        /* wg - accept wants an int - recvfrom wants a short!!*/
  9356.   short int fromlen;        /* the from socket address name */
  9357.   union socket_addr from;
  9358.   int tolen;            /* wg - sendto wants an int*/
  9359.   union socket_addr to;        /* the to socket address name */
  9360.   int passive;            /* still needed because of x25 close ambig */
  9361.   int backlog;            /* backlog - not handled well! */
  9362.   int domain;            /* domain of socket AF_INET or AF_X25 */
  9363.   int type;            /* type of socket stream or datagram */
  9364.   int protocol;            /* protocol of socket - ignored */
  9365.   int mbx_channel;        /* mailbox channel - needed for x25 */
  9366.   unsigned char mbx_buff[255];    /* mailbox buffer */
  9367.   unsigned short int miosb[4];    /* mailbox status block */
  9368.   int ncb_size;            /* x25 connection information */
  9369.   unsigned char ncb[128];
  9370.   unsigned char masklen;    /* x25 user data mask */
  9371.   unsigned char mask[16];
  9372.   int need_header;        /* x25 header field gives data status if req*/
  9373.   int send_type;        /* x25 data packet type eg more bit set etc */
  9374.   int status;            /* status of socket */
  9375.   int closed_by_remote;        /* flag for remote dropouts */
  9376.   int read_outstanding;        /* flag so we don't hang two reads */
  9377.   int cmu_open;            /* flag to say whether a cmu open was hung */
  9378.   int x25_listener;        /* flag to say we are an x25 listener */
  9379.   int oob_type;            /* handles interrupt messages */
  9380.   int mother;            /* mother socket for X25 accepts */
  9381.   int child;            /* child socket for X25 accepts */
  9382.   int no_more_accepts;        /* don't accept anymore calls */
  9383.   char int_data;        /* interrupt data - only 1 char supported */
  9384.   int non_blocking;        /* don't block on a read if no data */
  9385.   int sig_req;            /* generate SIGIO on data ready */
  9386.   struct itemlist rhost;    /* descriptor pointing to "p[].from" info for UCX */
  9387.   unsigned short ucx_accept_chan;    /* Channel returned by a UCX accept via hang_an_accept */
  9388. } p[32];
  9389.  
  9390. /* So we can handle select on terminal input.  */
  9391. static struct term_entry
  9392. {
  9393.   int chan;
  9394.   short int iosb[4];
  9395.   short int char_available;
  9396.   short int read_outstanding;
  9397.   char c[1];
  9398. } terminal =
  9399.  
  9400. {
  9401.   -1, 0, 0, 0, 0, 0, 0
  9402. };
  9403.  
  9404. #define CMU 1
  9405. #define WG  2
  9406. #define NONE 3
  9407. #define TGV 4
  9408. #define UCX 5
  9409. static int tcp_make = 0;
  9410.  
  9411. struct descriptor
  9412. {
  9413.   int size;
  9414.   char *ptr;
  9415. };
  9416.  
  9417. /* Initialize certain things 1st time thru.  */
  9418. static int p_initialised = 0;
  9419.  
  9420. /* A routine to point SIGALRM and SIGURG at.  */
  9421. static int 
  9422. si_dummy ()
  9423. {
  9424. }
  9425. static int (*alarm_function) () = si_dummy;
  9426. static int (*sigurg_function) () = si_dummy;
  9427.  
  9428. FILE *fdopen ();
  9429. static set_tcp_make ();
  9430. static char *getdevicename ();
  9431. $EOD
  9432. $!
  9433. $CREATE [.archie.vms]multi.opt
  9434. $DECK
  9435. sys$library:vaxcrtl.exe/share
  9436. multinet:multinet_socket_library.exe/share
  9437. $EOD
  9438. $!
  9439. $CREATE [.archie.vms]ucx.opt
  9440. $DECK
  9441. sys$library:vaxcrtl.exe/share
  9442. sys$library:ucx$ipc/lib
  9443. $EOD
  9444. $!
  9445. $CREATE [.archie.vms]woll.opt
  9446. $DECK
  9447. sys$library:vaxcrtl.exe/share
  9448. twg$tcp:[netdist.lib]twglib.olb/lib
  9449. $EOD
  9450. $ write sys$output "Ok, now enter the ARCHIE directory, look at MAKE.COM, then type @MAKE ."
  9451.