home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume33 / archie / part01 < prev    next >
Encoding:
Text File  |  1992-11-10  |  54.7 KB  |  2,001 lines

  1. Newsgroups: comp.sources.misc
  2. From: brendan@cygnus.com (Brendan Kehoe)
  3. Subject:  v33i050:  archie - A client to query the Archie FTP databases, v1.4.1, Part01/07
  4. Message-ID: <csm-v33i050=archie.145604@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: f72fa1a60a8684951e575c05203ad538
  6. Date: Thu, 5 Nov 1992 20:59:05 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: brendan@cygnus.com (Brendan Kehoe)
  10. Posting-number: Volume 33, Issue 50
  11. Archive-name: archie/part01
  12. Environment: UNIX, VMS, DOS
  13. Supersedes: archie: Volume 27, Issue 79-84
  14.  
  15. [ Version 1.4.1 ]
  16.  
  17.  Enclosed you'll find a Prospero client for the archie service.  It'll
  18. let you query the archie databases without actually using an
  19. interactive process on the remote server's machine (e.g., archie.ans.net),
  20. resulting in a MUCH better response time.  It also helps lessen the
  21. load on the archie server itself.
  22.  
  23.  What's Archie?  It's a system that will let you check a database containing
  24. thousands of entries for the files that're available at FTP sites around
  25. the world.
  26.  
  27.  This is a third child of Clifford Neuman's Prospero project.  It's really
  28. the Archie client that's included in the prospero stuff, but I've taken out
  29. everything that's unnecessary for this client to work.  (Aka, you don't
  30. have to build all of Prospero to get the Archie client.)  Khun Yee Fung
  31. wrote an archie client in Perl, George Ferguson has written a client
  32. for use with XWindows, based in part upon this code.  Also, Scott
  33. Stark wrote a NeXT-Step client for the NeXT.
  34.  
  35.  Also included in this release is a GNU Emacs Lisp front-end to the
  36. archie client.  Note that it requires the Ange FTP package to work
  37. properly.  You can retrieve it from archive.cis.ohio-state.edu in the
  38. directory /pub/gnu/emacs/elisp-archive/packages as ange-ftp.tar.Z.
  39.  
  40.  Using the Archie Prospero interface in its true form will probably be of
  41. interest---check out the file `Prospero' for an example of its interface.
  42. If you find it intriguing, you should probably get the full prospero kit
  43. from the University of Washington on cs.washington.edu in pub/prospero.tar.Z.
  44.  
  45.  Suffice to say, there are now a number of ways to query Archie without
  46. bogging a server down with your logins.
  47.  
  48.  Check out the man page (or archie.doc, if you're using VMS or DOS)
  49. for instructions on how to use this archie client.  VMS users please
  50. note that you have to put quotes around args that are capital letters;
  51. for example,  `$ ARCHIE "-L"'  to list the available servers.
  52.  
  53.  Please check to make sure you don't have "archie" aliased or modified
  54. in some way to do a telnet or rlogin (which you may've done before
  55. this command-line ability came into being).
  56.  
  57.  If Archie consistently hangs (at different times of day with
  58. different queries), it's possible that your site has UDP traffic on
  59. ports > 1000 blocked, for security reasons.  Contact your local
  60. system administrator.
  61.  
  62.  Write to archie-group@cc.mcgill.ca with questions about Archie itself.
  63.  Write to info-prospero@isi.edu about the Prospero protocol.
  64.  Write to brendan@cygnus.com with questions about this specific package.
  65. -----------
  66. #! /bin/sh
  67. # This is a shell archive.  Remove anything before this line, then feed it
  68. # into a shell via "sh file" or similar.  To overwrite existing files,
  69. # type "sh file -c".
  70. # Contents:  README README.ALEX README.dos msdos vms vms/in.h
  71. #   vms_support.c
  72. # Wrapped by kent@sparky on Thu Nov  5 12:53:07 1992
  73. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  74. echo If this archive is complete, you will see the following message:
  75. echo '          "shar: End of archive 1 (of 7)."'
  76. if test -f 'README' -a "${1}" != "-c" ; then 
  77.   echo shar: Will not clobber existing file \"'README'\"
  78. else
  79.   echo shar: Extracting \"'README'\" \(2529 characters\)
  80.   sed "s/^X//" >'README' <<'END_OF_FILE'
  81. X[ Version 1.4 ]
  82. X
  83. X Enclosed you'll find a Prospero client for the archie service.  It'll
  84. Xlet you query the archie databases without actually using an
  85. Xinteractive process on the remote server's machine (e.g., archie.ans.net),
  86. Xresulting in a MUCH better response time.  It also helps lessen the
  87. Xload on the archie server itself.
  88. X
  89. X What's Archie?  It's a system that will let you check a database containing
  90. Xthousands of entries for the files that're available at FTP sites around
  91. Xthe world.
  92. X
  93. X This is a third child of Clifford Neuman's Prospero project.  It's really
  94. Xthe Archie client that's included in the prospero stuff, but I've taken out
  95. Xeverything that's unnecessary for this client to work.  (Aka, you don't
  96. Xhave to build all of Prospero to get the Archie client.)  Khun Yee Fung
  97. Xwrote an archie client in Perl, George Ferguson has written a client
  98. Xfor use with XWindows, based in part upon this code.  Also, Scott
  99. XStark wrote a NeXT-Step client for the NeXT.
  100. X
  101. X Also included in this release is a GNU Emacs Lisp front-end to the
  102. Xarchie client.  Note that it requires the Ange FTP package to work
  103. Xproperly.  You can retrieve it from archive.cis.ohio-state.edu in the
  104. Xdirectory /pub/gnu/emacs/elisp-archive/packages as ange-ftp.tar.Z.
  105. X
  106. X Using the Archie Prospero interface in its true form will probably be of
  107. Xinterest---check out the file `Prospero' for an example of its interface.
  108. XIf you find it intriguing, you should probably get the full prospero kit
  109. Xfrom the University of Washington on cs.washington.edu in pub/prospero.tar.Z.
  110. X
  111. X Suffice to say, there are now a number of ways to query Archie without
  112. Xbogging a server down with your logins.
  113. X
  114. X Check out the man page (or archie.doc, if you're using VMS or DOS)
  115. Xfor instructions on how to use this archie client.  VMS users please
  116. Xnote that you have to put quotes around args that are capital letters;
  117. Xfor example,  `$ ARCHIE "-L"'  to list the available servers.
  118. X
  119. X Please check to make sure you don't have "archie" aliased or modified
  120. Xin some way to do a telnet or rlogin (which you may've done before
  121. Xthis command-line ability came into being).
  122. X
  123. X If Archie consistently hangs (at different times of day with
  124. Xdifferent queries), it's possible that your site has UDP traffic on
  125. Xports > 1000 blocked, for security reasons.  Contact your local
  126. Xsystem administrator.
  127. X
  128. X
  129. X Write to archie-group@cc.mcgill.ca with questions about Archie itself.
  130. X Write to info-prospero@isi.edu about the Prospero protocol.
  131. X Write to brendan@cygnus.com with questions about this specific package.
  132. END_OF_FILE
  133.   if test 2529 -ne `wc -c <'README'`; then
  134.     echo shar: \"'README'\" unpacked with wrong size!
  135.   fi
  136.   # end of 'README'
  137. fi
  138. if test -f 'README.ALEX' -a "${1}" != "-c" ; then 
  139.   echo shar: Will not clobber existing file \"'README.ALEX'\"
  140. else
  141.   echo shar: Extracting \"'README.ALEX'\" \(780 characters\)
  142.   sed "s/^X//" >'README.ALEX' <<'END_OF_FILE'
  143. XAlex is a filesystem that lets users access files in FTP sites around
  144. Xthe world just like they access local files.  The name Alex comes from 
  145. Xthe ancient Library of Alexandria. Alexandria gathered information from 
  146. Xaround the world into one easy to access location. Alex does an analogous 
  147. Xthing in a very modern way.
  148. X
  149. XSource to Alex is now available on alex.sp.cs.cmu.edu in the `src'
  150. Xsubdirectory.
  151. X
  152. Xusenix.wofs92.ps - paper on Alex as published in Usenix Workshop on File Systems 
  153. X                   May of 1992.
  154. X
  155. Xintro.ps         -  same as above paper but with updates
  156. X
  157. X
  158. Xnsf.poster.ps    -  6 slides used for a poster session
  159. X
  160. X
  161. XKeywords:     Alexandria, Alex, technical papers, techreport
  162. XMaster copy:  /alex/edu/cmu/cs/sp/alex/doc/README
  163. X
  164. X
  165. X   Vincent Cate
  166. X   vac@cs.cmu.edu
  167. X
  168. END_OF_FILE
  169.   if test 780 -ne `wc -c <'README.ALEX'`; then
  170.     echo shar: \"'README.ALEX'\" unpacked with wrong size!
  171.   fi
  172.   # end of 'README.ALEX'
  173. fi
  174. if test -f 'README.dos' -a "${1}" != "-c" ; then 
  175.   echo shar: Will not clobber existing file \"'README.dos'\"
  176. else
  177.   echo shar: Extracting \"'README.dos'\" \(10680 characters\)
  178.   sed "s/^X//" >'README.dos' <<'END_OF_FILE'
  179. X11/22/91  Readme.dos -- Readme file for CUTCP DOS version of Archie.
  180. X
  181. X--
  182. XThis version requires the use of a `standard' NCSA or CUTCP compatible
  183. XCONFIG.TEL file.  If you are running NCSA telnet or CUTCP/CUTE telnet,
  184. Xyou should be able to run this program without modification.
  185. X
  186. XAs with all CUTCP programs, you may set a DOS environment variable to
  187. Xpoint to the location of your config.tel file.
  188. X
  189. X    set CONFIGTEL=C:\net\config.tel
  190. X
  191. XYou may also set the $CUTCPnn dos environment variables to include other
  192. X'local' information (such as client IP address on a Novell lan).
  193. X
  194. XThis version has been compiled with the US (archie.sura.net) Prospero/Archie
  195. Xserver as the default. This may not be appropriate for your location. Here's
  196. Xhow to change it.
  197. X
  198. X
  199. X    1. Run the archie program with the -L argument to list known
  200. X       archie/prospero servers.
  201. X
  202. X    2. Select the server name that is closest to your site. For this example
  203. X       we'll pick archie.funet.fi
  204. X
  205. X    3. Edit your config.tel file and add the following lines at the end
  206. X       of the file.
  207. X
  208. X            name=archie
  209. X            host=archie.funet.fi    # actually substitute your select
  210. X                        # server name here
  211. X
  212. X    4. If you happen to know the IP address of the server, you may also
  213. X       add the appropriate
  214. X
  215. X            hostip=<insert IP address here>
  216. X
  217. X    5. If you don't enter an IP address, archie will perform a DNS lookup
  218. X       use the domain nameserver information that is in your config.tel 
  219. X       file.
  220. X
  221. X
  222. XAn additional command line option (-H) has been added (vs -h) to allow the
  223. Xuser to specify the config.tel file location on the command line. 
  224. X
  225. X    archie -H c:\net\config.tel emacs
  226. X
  227. XDuring a search, you may press the <ESCAPE> key to abort the query.
  228. X
  229. X
  230. X
  231. XIf you have problems, try running archie with the -D9 option (debug).
  232. X
  233. XAs usual, bugs/comments to:
  234. X
  235. X        cutcp-bugs@omnigate.clarkson.edu
  236. X
  237. XBrad Clements, Sr. Network Engineer
  238. XEducational Resources Center
  239. XClarkson University 
  240. XPotsdam, NY 13699
  241. X
  242. Xbkc@draco.erc.clarkson.edu
  243. X
  244. X-----------
  245. XSample Config.tel file 
  246. X------------------------------
  247. X#  Example host file for ARCHIE/ CUTCP version
  248. X#  11/21/91
  249. X#
  250. X#      Bugs to  cutcp-bugs@omnigate.clarkson.edu
  251. X
  252. X#---------------------------------------------------------------------------#
  253. X#                                        #
  254. X#** ATTENTION ATTENTION ATTENTION ATTENTION ATTENTION ATTENTION ATTENTION **#
  255. X#                                        #
  256. X#   This sample config.tel file contains every single option that you could #
  257. X#   possibly use. Its meant as an example only. Please Please PLEASE don't  #
  258. X#   use all these options in your working config.tel file, just the ones    #
  259. X#   that you actually need. Many options can be left out, the default action#
  260. X#   (if defined) is shown in parens () next to the option.             #
  261. X#                                        #
  262. X#                         Thank you for your support                #
  263. X#---------------------------------------------------------------------------#
  264. X
  265. X#
  266. X#  This example file is for my=bootp, in which case the following items are
  267. X#  determined from the bootp server: (and are thus commented out in this file)
  268. X#       1. This machine's IP Address
  269. X#       2. The network NETMASK
  270. X#       3. The default gateway (one or more)
  271. X#       4. Nameservers (one or more)
  272. X#       5. The domain search list (if this clients hostname is in the bootp packet)
  273. X#
  274. X#  Your BOOTP server needs to be RFC 1048 compliant for this to work
  275. X#  
  276. X#  If you have nameservers, gateways or a domainslist already specified
  277. X#  in this file, then the file's entry takes precedence.
  278. X#  Extra gateways and nameservers will be added by BOOTP if found, however.
  279. X#----------------------------------------------------------------------------
  280. X#  You can set a DOS environment variable  CONFIGTEL to point to this file
  281. X#  then you don't need batch files or the -h option.
  282. X#
  283. X#       C> set CONFIGTEL=C:\net\myconfig.tel
  284. X#
  285. X#  You may also use environment variables to include config.tel options,
  286. X#  such as:
  287. X#    C> set $CUTCP1=myip~197.001.42.98;netmask~255.255.252.0
  288. X#    C> set $CUTCP2=name~x;hostip~128.163.298.2
  289. X#
  290. X#  and so on up to $CUTCP99. Note that you use a tilde (~) instead of (=)
  291. X#  in the dos set command because two ='s are not allowed by Dos.
  292. X#
  293. X#  Additionally, there is a new config.tel option called include= which
  294. X#  allows the nesting (up to 3) configuration files deep.
  295. X#
  296. X#
  297. X#  You can use these new options on networks to make your configuration job
  298. X#  easier. CUTCP always opens config.tel files as read-only, so you can mark
  299. X#  your files as sharable, read only. Also, you can use the include= command
  300. X#  in a $CUTCP environment variable, and on the command line.
  301. X
  302. X#  *Note* that you can not include a machine specific parameter before
  303. X#  name=default... This used to work in old versions, but is strictly
  304. X#  enforced in this version.
  305. X# --------------------------------------------------------------------------  
  306. X#  This file is free form
  307. X#  Separators are any char <33 and :;=
  308. X#
  309. X#  The form is keyword=value for each parameter.
  310. X#  The first set of parameters refer to the whole program's defaults.
  311. X#  These parameter values can be in any order.
  312. X#  Following this are the individual machine specs.
  313. X#
  314. X
  315. Xmyip=128.153.28.65                      #  (bootp)
  316. X                #  myip types are:
  317. X                                #  bootp        - sends out a BOOTP request for your IP
  318. X                                #  rarp         - Uses reverse ARp to get your IP
  319. X                                #  xx.yy.zz.qq  - your IP address
  320. X
  321. Xvjc=no                # (no)
  322. X                # set  vjc=yes if you're running slip and
  323. X                # you want to use Van Jacobson TCP header
  324. X                # compression
  325. X
  326. Xsplayc=no            # (no) ack. splay compression w/ vjc.. don't
  327. X                # use it, not standard, development option only
  328. X
  329. Xmyname=userid            # put your userid here, used for Rlogin
  330. X                # PC-NFS version ignores this value and uses the name
  331. X                # that you specified to your pcnfsd.
  332. X
  333. Xnetmask=255.255.252.0           #  needed if not using BOOTP. 
  334. X                                #  otherwise not needed because Bootp gets your netmask
  335. X                #  for you
  336. X
  337. Xhardware=packet            # (packet)
  338. X                                # harware choices
  339. X                                #  3com         - 3com 3c501
  340. X                                #  3c523        - 3com 3c523
  341. X                                #  wd800        - Western Digitial 800E
  342. X                                #  nicpc        - 
  343. X                                #  nicps        -
  344. X                                #  ni5210       - Micom Interlan NI5210 card
  345. X                                #  packet       - FTP packet Driver spec 
  346. X                                # (currently only Ethernet and Slip class devices are supported)
  347. X
  348. Xinterrupt=2                     # hardware IRQ interrupt
  349. Xaddress=0                       # (0)
  350. X                # base memory address or packet driver class
  351. X                                # if using packet driver (0 == default == ethernet)
  352. X                                # or class=6 for slip
  353. X
  354. Xioaddr=0                        # (0)
  355. X                # I/O address  or packet int vector if using packet driver
  356. X                                # If = 0 and packet driver, telbin looks for first
  357. X                                # packet driver found between 60H and 7FH
  358. X
  359. Xnoarpme=yes            # Don't arp for myself before running? (no)
  360. X                # if yes, inhibits the initial arp request
  361. X                # for this IP address. However, if yes, won't
  362. X                # warn you if another user is using this IP
  363. X                # address. For some token ring systems, you'll
  364. X                # need noarpme=yes.
  365. X
  366. Xinclude="nul"            # if you want to include another file as part
  367. X                # of this one (you can nest up to three includes)
  368. X                # otherwise, don't use this option
  369. X
  370. Xdomaintime=4            # domain name lookup timeout (first retry)
  371. Xdomainretry=4            # domain name max number of retries 
  372. Xdomainslist="clarkson.edu,aux.clarkson.edu" # domain name search path
  373. X                                # domain name lookup will attach each of these
  374. X                                # comma seperated suffixes to
  375. X                                # the end of the name you are looking for to
  376. X                                # discover the full name and IP address.
  377. X                                # so, looking for x tries x.clarkson.edu and x.aux.clarkson.edu then just x
  378. X                                # unless you use  x.  which ONLY looks for x
  379. X
  380. X    ## Also, the fewer suffixes in the domainslist
  381. X    ## the less time you will have to wait if you mis-type an entry.
  382. X    ## Finally, try not to use a suffix like   .  or .edu or .com this will
  383. X    ## waste a lot of time looking for a bogus host name if you mis-type an entry.
  384. X
  385. X## ----------------------------------------------------------------- ##
  386. X##   BEGIN MACHINE SPECIFIC PARAMETERS...                 ##
  387. X## ----------------------------------------------------------------- ##
  388. Xname=default            # default entry sets defaults for all following
  389. X                # machines.
  390. X
  391. Xarptime=10            # arp timeout in seconds
  392. X                #
  393. X
  394. Xretrans=1                       # starting retransmit time out in ticks
  395. X                #   1/18ths of sec MAX 100, min 1
  396. X
  397. Xmtu=1024                        # maximum transmit unit in bytes
  398. X                #   outgoing packet size, MAX=1500
  399. X
  400. Xmaxseg=1024            # largest segment we can receive
  401. X                #   whatever the hardware can take, MAX=4096
  402. Xrwin=2048                       # most bytes we can receive without ACK
  403. X                #   =TCP window size, MAX=4096
  404. X
  405. Xcontime=20                      # timeout in seconds to try connection
  406. X                #   before returning error to user
  407. X
  408. X#  Following are individual machine specifications
  409. X#  Gateways are used in order that they appear in the file
  410. X#  Nameservers rotate, #1, #2, #3, #1, #2 when a request fails
  411. X#
  412. X
  413. X# ********************************************************************* ###
  414. X# Note: If you are using BOOTP above for myip=, then you do not need
  415. X#       to enter a default gateway, nameserver, netmask etc (unless you want to)
  416. X#       only IF your BOOTP server is rfc_1048 compliant. (Ask your Net Manager)
  417. X#       You can use both bootp and entries here, in which case the entries in
  418. X#       this file over-ride what BOOTP discovers. (however, bootp nameservers
  419. X#       and gateways are ADDED to this file's list of entries
  420. X# ********************************************************************* ####
  421. X
  422. X#  Below this line, most of the communication parameters are obtained
  423. X#  from the "default" host entry.  Those parameters listed for a host 
  424. X#  override the default host values.
  425. X#
  426. X#  These are examples, replace them with the correct values for your site.
  427. X#name=mynameserver
  428. X#host=omnigate.clarkson.edu
  429. X#hostip=197.001.4.2
  430. X#nameserver=1
  431. X
  432. X#name=backupserver
  433. X#host=clutx.clarkson.edu
  434. X#hostip=197.001.4.3
  435. X#nameserver=2
  436. X
  437. X#name=lastserver
  438. X#host=n2ngw.nyser.net
  439. X#hostip=128.145.198.2
  440. X#nameserver=3
  441. X
  442. X#name=mygateway
  443. X#host=nysernet.clarkson.edu
  444. X#hostip=197.001.4.1
  445. X#gateway=1
  446. X
  447. X
  448. Xname=archie
  449. Xhost=archie.funet.fi
  450. END_OF_FILE
  451.   if test 10680 -ne `wc -c <'README.dos'`; then
  452.     echo shar: \"'README.dos'\" unpacked with wrong size!
  453.   fi
  454.   # end of 'README.dos'
  455. fi
  456. if test ! -d 'msdos' ; then
  457.     echo shar: Creating directory \"'msdos'\"
  458.     mkdir 'msdos'
  459. fi
  460. if test ! -d 'vms' ; then
  461.     echo shar: Creating directory \"'vms'\"
  462.     mkdir 'vms'
  463. fi
  464. if test -f 'vms/in.h' -a "${1}" != "-c" ; then 
  465.   echo shar: Will not clobber existing file \"'vms/in.h'\"
  466. else
  467.   echo shar: Extracting \"'vms/in.h'\" \(1418 characters\)
  468.   sed "s/^X//" >'vms/in.h' <<'END_OF_FILE'
  469. X/* netinet/in.h */
  470. Xstruct in_addr
  471. X{
  472. X  union
  473. X  {
  474. X    struct
  475. X    {
  476. X      unsigned char s_b1, s_b2, s_b3, s_b4;
  477. X    } S_un_b;
  478. X    struct
  479. X    {
  480. X      unsigned short s_w1, s_w2;
  481. X    } S_un_w;
  482. X    unsigned long S_addr;
  483. X  } S_un;
  484. X#define   s_addr S_un.S_addr
  485. X#define   s_host S_un.S_un_b.s_b2
  486. X#define   s_net  S_un.S_un_b.s_b1
  487. X#define   s_imp  S_un.S_un_w.s_w2
  488. X#define   s_impno S_un.S_un_b.s_b4
  489. X#define   s_lh   S_un.S_un_b.s_b3
  490. X};
  491. X
  492. X#define INADDR_ANY 0x00000000
  493. X#define INADDR_BROADCAST 0xffffffff
  494. X#define INADDR_LOOPBACK 0x7f000001
  495. X
  496. Xstruct sockaddr_in
  497. X{
  498. X  short sin_family;
  499. X  unsigned short sin_port;
  500. X  struct in_addr sin_addr;
  501. X  char sin_zero[8];
  502. X};
  503. X
  504. X#define ntohl(x) (( (((unsigned long) x) >> 24)& 0x000000ff ) |\
  505. X                  ( (((unsigned long) x) >> 8) & 0x0000ff00 ) |\
  506. X                  ( (((unsigned long) x) << 8) & 0x00ff0000 ) |\
  507. X                  ( (((unsigned long) x) << 24)& 0xff000000 ))
  508. X#define ntohs(x) (( (((unsigned short) x) >> 8) |\
  509. X                  ( (((unsigned short) x) << 8)) & 0xffff ))
  510. X#define htonl(x) (( (((unsigned long) x) >> 24)& 0x000000ff ) |\
  511. X                  ( (((unsigned long) x) >> 8) & 0x0000ff00 ) |\
  512. X                  ( (((unsigned long) x) << 8) & 0x00ff0000 ) |\
  513. X                  ( (((unsigned long) x) << 24)& 0xff000000 ))
  514. X#define htons(x) (( (((unsigned short) x) >> 8) |\
  515. X                  ( (((unsigned short) x) << 8)) & 0xffff ))
  516. X
  517. X#define IPPORT_RESERVED 1024
  518. END_OF_FILE
  519.   if test 1418 -ne `wc -c <'vms/in.h'`; then
  520.     echo shar: \"'vms/in.h'\" unpacked with wrong size!
  521.   fi
  522.   # end of 'vms/in.h'
  523. fi
  524. if test -f 'vms_support.c' -a "${1}" != "-c" ; then 
  525.   echo shar: Will not clobber existing file \"'vms_support.c'\"
  526. else
  527.   echo shar: Extracting \"'vms_support.c'\" \(32780 characters\)
  528.   sed "s/^X//" >'vms_support.c' <<'END_OF_FILE'
  529. X/* Emulation of 4.2 UNIX socket interface routines includes drivers for
  530. X   Wollongong, CMU-TEK, UCX tcp/ip interface and also emulates the SUN
  531. X   version of X.25 sockets.  The TWG will also work for MultiNet.  */
  532. X
  533. X/* This is from unixlib, by P.Kay@massey.ac.nz; wonderful implementation.
  534. X   You can get the real thing on 130.123.1.4 as unixlib_tar.z.  */
  535. X
  536. X#include <stdio.h>
  537. X#include <errno.h>
  538. X#include <ssdef.h>
  539. X#include <dvidef.h>
  540. X#include <signal.h>
  541. X#include <sys$library:msgdef.h>
  542. X#include <iodef.h>
  543. X#include <ctype.h>
  544. X#include <vms.h>
  545. X#include "[.vms]network.h"
  546. X
  547. X#define QIO_FAILED (st != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL)
  548. X#define QIO_ST_FAILED (st != SS$_NORMAL)
  549. X
  550. X/* Socket routine.  */
  551. Xint
  552. XVMSsocket (domain, type, protocol)
  553. X     int domain, type, protocol;
  554. X{
  555. X  struct descriptor inetdesc, x25desc, mbxdesc;
  556. X  int i, st, s, p_initialise ();
  557. X  long ucx_sock_def;
  558. X  char *getenv ();
  559. X
  560. X  if (!tcp_make)
  561. X    set_tcp_make ();
  562. X
  563. X  if (p_initialised == 0)
  564. X    {
  565. X      for (i = 0; i < 32; i++)
  566. X    p_initialise (i);
  567. X
  568. X      p_initialised = 1;
  569. X    }
  570. X
  571. X  /* First of all, get a file descriptor and file ptr we can associate with
  572. X     the socket, allocate a buffer, and remember the socket details.  */
  573. X  s = dup (0);
  574. X  if (s > 31)
  575. X    {
  576. X      errno = EMFILE;
  577. X      close (s);
  578. X      return -1;
  579. X    }
  580. X
  581. X  p[s].fptr = fdopen (s, "r");
  582. X  p[s].fd_buff = (unsigned char *) malloc (BUF_SIZE);
  583. X  p[s].domain = domain;
  584. X  p[s].type = type;
  585. X  p[s].protocol = protocol;
  586. X
  587. X  /* Handle the case of INET and X.25 separately.  */
  588. X  if (domain == AF_INET)
  589. X    {
  590. X      if (tcp_make == NONE)
  591. X    {
  592. X      printf ("Trying to obtain a TCP socket when we don't have TCP!\n");
  593. X      exit (1);
  594. X    }
  595. X      if (tcp_make == CMU)
  596. X    {
  597. X      /* For CMU we need only assign a channel.  */
  598. X      inetdesc.size = 3;
  599. X      inetdesc.ptr = "IP:";
  600. X      if (sys$assign (&inetdesc, &p[s].channel, 0, 0) != SS$_NORMAL)
  601. X        return -1;
  602. X    }
  603. X      else if (tcp_make == UCX)
  604. X    {
  605. X      /* For UCX assign channel and associate a socket with it.  */
  606. X      inetdesc.size = 3;
  607. X      inetdesc.ptr = "BG:";
  608. X      if (sys$assign (&inetdesc, &p[s].channel, 0, 0) != SS$_NORMAL)
  609. X        return -1;
  610. X
  611. X      ucx_sock_def = (domain << 24) + (type << 16) + protocol;
  612. X      st = sys$qiow (0, p[s].channel, IO$_SETMODE, p[s].iosb, 0, 0,
  613. X             &ucx_sock_def, 0, 0, 0, 0, 0);
  614. X      if (QIO_FAILED)
  615. X        return -1;
  616. X    }
  617. X      else
  618. X    {
  619. X      /* For TWG we assign the channel and associate a socket with it.  */
  620. X      inetdesc.size = 7;
  621. X      inetdesc.ptr = "_INET0:";
  622. X
  623. X      if (sys$assign (&inetdesc, &p[s].channel, 0, 0) != SS$_NORMAL)
  624. X        return -1;
  625. X
  626. X      st = sys$qiow (0, p[s].channel, IO$_SOCKET, p[s].iosb, 0, 0,
  627. X             domain, type, 0, 0, 0, 0);
  628. X      if (QIO_FAILED)
  629. X        return -1;
  630. X    }
  631. X    }
  632. X  else
  633. X    /* We don't handle any other domains yet.  */
  634. X    return -1;
  635. X
  636. X  /* For each case if we are successful we return the descriptor.  */
  637. X  return s;
  638. X}
  639. X
  640. X/* Bind routine.  */
  641. XVMSbind (s, name, namelen)
  642. X     int s;
  643. X     union socket_addr *name;
  644. X     int namelen;
  645. X{
  646. X  char infobuff[1024], lhost[32];
  647. X  int st;
  648. X
  649. X  if (!tcp_make)
  650. X    set_tcp_make ();
  651. X
  652. X  if (p[s].domain == AF_INET)
  653. X    {
  654. X      /* One main problem with bind is that if we're given a port number
  655. X     of 0, then we're expected to return a unique port number.  Since
  656. X     we don't KNOW, we return 1050+s and look to Lady Luck.  */
  657. X      if (tcp_make == CMU)
  658. X    {
  659. X      if (name->in.sin_port == 0 && p[s].type != SOCK_DGRAM)
  660. X        name->in.sin_port = 1050 + s;
  661. X      p[s].namelen = namelen;
  662. X      bcopy (name, &(p[s].name), namelen);
  663. X
  664. X      if (p[s].type == SOCK_DGRAM)
  665. X        {
  666. X          /* Another problem is that CMU still needs an OPEN request
  667. X         even if it's a datagram socket.  */
  668. X          st = sys$qiow (0, p[s].channel, TCP$OPEN, p[s].iosb,
  669. X                 0, 0, 0, 0, ntohs (p[s].name.in.sin_port),
  670. X                 0, 1, 0);
  671. X          if (QIO_ST_FAILED)
  672. X        return -1;
  673. X
  674. X          p[s].cmu_open = 1;
  675. X          sys$qiow (0, p[s].channel, TCP$INFO, p[s].iosb,
  676. X            0, 0, &infobuff, 1024, 0, 0, 0, 0);
  677. X          bcopy (infobuff + 264, &(p[s].name.in.sin_port), 2);
  678. X          p[s].name.in.sin_port = htons (p[s].name.in.sin_port);
  679. X
  680. X          /* So get it another way.  */
  681. X          bcopy (infobuff + 136, lhost, infobuff[1]);
  682. X          lhost[infobuff[1]] = '\0';
  683. X          sys$qiow (0, p[s].channel, GTHST, p[s].iosb,
  684. X            0, 0, &infobuff, 1024, 1, lhost, 0, 0);
  685. X          bcopy (infobuff + 4, &(p[s].name.in.sin_addr), 4);
  686. X
  687. X          /* Be prepared to receive a message.  */
  688. X          hang_a_read (s);
  689. X        }
  690. X    }
  691. X      else if (tcp_make == UCX)
  692. X    {
  693. X      /* UCX will select a prot for you.  If the port's number is 0,
  694. X         translate "name" into an item_2 list.  */
  695. X      struct itemlist lhost;
  696. X      lhost.length = namelen;
  697. X      lhost.code = 0;
  698. X      lhost.dataptr = (char *) name;
  699. X
  700. X      st = sys$qiow (0, p[s].channel, IO$_SETMODE, p[s].iosb, 0, 0,
  701. X             0, 0, &lhost, 0, 0, 0);
  702. X      if (QIO_FAILED)
  703. X        return -1;
  704. X
  705. X      if (p[s].type == SOCK_DGRAM)
  706. X        hang_a_read (s);
  707. X
  708. X    }
  709. X      else
  710. X    {
  711. X      /* WG is more straightforward */
  712. X      st = sys$qiow (0, p[s].channel, IO$_BIND, p[s].iosb,
  713. X             0, 0, name, namelen, 0, 0, 0, 0);
  714. X      if (QIO_FAILED)
  715. X        return -1;
  716. X
  717. X      /* If it's a datagram, get ready for the message.  */
  718. X      if (p[s].type == SOCK_DGRAM)
  719. X        hang_a_read (s);
  720. X    }
  721. X    }
  722. X  else
  723. X    /* We don't handle any other domain yet.  */
  724. X    return -1;
  725. X
  726. X  return 0;
  727. X}
  728. X
  729. X/* Connect routine.  */
  730. XVMSconnect (s, name, namelen)
  731. X     int s;
  732. X     union socket_addr *name;
  733. X     int namelen;
  734. X{
  735. X  int pr, fl, st;
  736. X  char *inet_ntoa ();
  737. X  static struct
  738. X  {
  739. X    int len;
  740. X    char name[128];
  741. X  } gethostbuf;
  742. X  extern int connect_ast ();
  743. X
  744. X  if (!tcp_make)
  745. X    set_tcp_make ();
  746. X
  747. X  /* For datagrams we need to remember who the name was so we can send all
  748. X     messages to that address without having to specify it all the time.  */
  749. X  if (p[s].connected)
  750. X    {
  751. X      if (p[s].connected == 1)
  752. X    errno = EISCONN;
  753. X      else
  754. X    {
  755. X      errno = ECONNREFUSED;
  756. X      p[s].connected = 0;
  757. X    }
  758. X      return -1;
  759. X    }
  760. X
  761. X  if (p[s].connect_pending)
  762. X    {
  763. X      errno = EALREADY;
  764. X      return -1;
  765. X    }
  766. X
  767. X  p[s].passive = 0;
  768. X  p[s].tolen = namelen;
  769. X  bcopy (name, &(p[s].to), namelen);
  770. X
  771. X  if (p[s].domain == AF_INET)
  772. X    {
  773. X      if (tcp_make == CMU)
  774. X    {
  775. X
  776. X      /* Get the info about the remote host  and open up a connection.  */
  777. X      st = sys$qiow (0, p[s].channel, GTHST, p[s].iosb, 0, 0, &gethostbuf,
  778. X             132, 2, name->in.sin_addr.s_addr, 0, 0);
  779. X      if (QIO_FAILED)
  780. X        {
  781. X          strcpy (gethostbuf.name, inet_ntoa (name->in.sin_addr.s_addr));
  782. X          gethostbuf.len = strlen (gethostbuf.name);
  783. X        }
  784. X      gethostbuf.name[gethostbuf.len] = 0;
  785. X
  786. X      /* TCP */
  787. X      pr = 0;
  788. X      /* Active */
  789. X      fl = 1;
  790. X
  791. X      /* Nothing else for datagrams.  */
  792. X      if (p[s].type == SOCK_DGRAM)
  793. X        return (0);
  794. X      st = sys$qio (s, p[s].channel, TCP$OPEN, p[s].iosb, connect_ast,
  795. X            &p[s], &(gethostbuf.name), ntohs (name->in.sin_port),
  796. X            ntohs (p[s].name.in.sin_port), fl, pr, 0);
  797. X      if (QIO_ST_FAILED)
  798. X        return -1;
  799. X    }
  800. X      else if (tcp_make == UCX)
  801. X    {
  802. X      /* Both UDP and TCP can use a connect - IO$_ACCESS */
  803. X      p[s].rhost.length = namelen;
  804. X      p[s].rhost.code = 0;
  805. X      p[s].rhost.dataptr = (char *) name;
  806. X
  807. X      st = sys$qio (s, p[s].channel, IO$_ACCESS, p[s].iosb, connect_ast,
  808. X            &p[s], 0, 0, &p[s].rhost, 0, 0, 0);
  809. X      if (QIO_ST_FAILED)
  810. X        return -1;
  811. X    }
  812. X      else
  813. X    {
  814. X      /* TWG */
  815. X      if (p[s].type == SOCK_DGRAM)
  816. X        return (0);
  817. X      st = sys$qio (s, p[s].channel, IO$_CONNECT, p[s].iosb, connect_ast,
  818. X            &p[s], name, namelen, 0, 0, 0, 0);
  819. X      if (QIO_ST_FAILED)
  820. X        return -1;
  821. X    }
  822. X    }
  823. X  else
  824. X    /* We don't handle any other domain yet.  */
  825. X    return -1;
  826. X
  827. X  if (p[s].non_blocking)
  828. X    {
  829. X      if (p[s].connected)
  830. X    {
  831. X      if (p[s].connected == 1)
  832. X        return 0;
  833. X      else
  834. X        {
  835. X          p[s].connected = 0;
  836. X          errno = ECONNREFUSED;
  837. X          return -1;
  838. X        }
  839. X    }
  840. X      else
  841. X    {
  842. X      p[s].connect_pending = 1;
  843. X      errno = EINPROGRESS;
  844. X      return -1;
  845. X    }
  846. X    }
  847. X  else
  848. X    {
  849. X      /* wait for the connection to occur */
  850. X      if (p[s].connected)
  851. X    {
  852. X      if (p[s].connected == 1)
  853. X        return 0;
  854. X      else
  855. X        {
  856. X          p[s].connected = 0;
  857. X          errno = ECONNREFUSED;
  858. X          return -1;
  859. X        }
  860. X    }
  861. X
  862. X      /* Timed out? */
  863. X      if (wait_efn (s) == -1)
  864. X    return -1;
  865. X
  866. X      if (p[s].connected != SS$_NORMAL)
  867. X    {
  868. X      errno = ECONNREFUSED;
  869. X      return -1;
  870. X    }
  871. X
  872. X      return 0;
  873. X    }
  874. X}
  875. X
  876. X/* Listen routine.  */
  877. XVMSlisten (s, backlog)
  878. X     int s;
  879. X     int backlog;
  880. X{
  881. X  int st;
  882. X
  883. X  if (!tcp_make)
  884. X    set_tcp_make ();
  885. X
  886. X  p[s].passive = 1;
  887. X  p[s].backlog = backlog;
  888. X  if (p[s].domain == AF_INET)
  889. X    {
  890. X      if (tcp_make == CMU)
  891. X    {
  892. X      /* For the CMU sockets we can't do the open call in listen;
  893. X         we have to do it in hang_an_accept, because when we close
  894. X         off the connection we have to be ready to accept another
  895. X         one.  accept() also calls hang_an_accept on the old
  896. X         descriptor.  */
  897. X
  898. X      /* Nothing */
  899. X    }
  900. X      else if (tcp_make == UCX)
  901. X    {
  902. X
  903. X      /* Doc Verbage sez backlog is descriptor of byte.  Doc examples
  904. X         and common sense say backlog is value.  Value doesn't work,
  905. X         so let's try descriptor of byte after all.  */
  906. X      struct descriptor bl;
  907. X      unsigned char ucx_backlog;
  908. X
  909. X      ucx_backlog = (unsigned char) backlog;
  910. X      bl.size = sizeof (ucx_backlog);
  911. X      bl.ptr = (char *) &ucx_backlog;
  912. X
  913. X      st = sys$qiow (0, p[s].channel, IO$_SETMODE, p[s].iosb, 0, 0,
  914. X             0, 0, 0, &bl, 0, 0);
  915. X      if (QIO_FAILED)
  916. X        return -1;
  917. X    }
  918. X      else
  919. X    {
  920. X      /* TWG */
  921. X      st = sys$qiow (0, p[s].channel, IO$_LISTEN, p[s].iosb, 0, 0,
  922. X             backlog, 0, 0, 0, 0, 0);
  923. X      if (QIO_FAILED)
  924. X        return -1;
  925. X    }
  926. X    }
  927. X  else
  928. X    /* We don't handle any other domain yet.  */
  929. X    return -1;
  930. X
  931. X  p[s].status = LISTENING;
  932. X  hang_an_accept (s);
  933. X  return 0;
  934. X}
  935. X
  936. X/* Accept routine.  */
  937. Xint
  938. XVMSaccept (s, addr, addrlen)
  939. X     int s;
  940. X     union socket_addr *addr;
  941. X     int *addrlen;
  942. X{
  943. X  int news, st;
  944. X  struct descriptor inetdesc;
  945. X
  946. X  if (!tcp_make)
  947. X    set_tcp_make ();
  948. X
  949. X  if (p[s].non_blocking && !p[s].accept_pending)
  950. X    {
  951. X      errno = EWOULDBLOCK;
  952. X      return -1;
  953. X    }
  954. X
  955. X  /* hang_an_accept set up an incoming connection request so we have first
  956. X     to hang around until one appears or we time out.  */
  957. X  if (p[s].domain == AF_INET)
  958. X    {
  959. X      if (tcp_make == CMU)
  960. X    {
  961. X      char infobuff[1024];
  962. X
  963. X      /* Timed out?  */
  964. X      if (wait_efn (s) == -1)
  965. X        return -1;
  966. X
  967. X      /* Ok, get a new descriptor ...  */
  968. X      news = dup (0);
  969. X      if (news > 31)
  970. X        {
  971. X          errno = EMFILE;
  972. X          close (news);
  973. X          return -1;
  974. X        }
  975. X
  976. X      /* ... and copy all of our data across.  */
  977. X      bcopy (&p[s], &p[news], sizeof (p[0]));
  978. X
  979. X      /* But not this field, of course! */
  980. X      p[news].s = news;
  981. X
  982. X      sys$qiow (0, p[news].channel, TCP$INFO, p[news].iosb,
  983. X            0, 0, &infobuff, 1024, 0, 0, 0, 0);
  984. X
  985. X      /* Copy across the connection info if necessary.  */
  986. X      if (addr != 0)
  987. X        {
  988. X          *addrlen = sizeof (struct sockaddr_in);
  989. X          bcopy (infobuff + 132, &(addr->in.sin_port), 2);
  990. X          addr->in.sin_port = htons (addr->in.sin_port);
  991. X          addr->in.sin_family = AF_INET;
  992. X          bcopy (infobuff + 272, &(addr->in.sin_addr), 4);
  993. X          p[news].fromlen = *addrlen;
  994. X          bcopy (addr, &(p[news].from), *addrlen);
  995. X        }
  996. X      p[news].status = PASSIVE_CONNECTION;
  997. X
  998. X      /* Get a new file ptr for the socket.  */
  999. X      p[news].fptr = fdopen (news, "r");
  1000. X
  1001. X      /* Reset this field.  */
  1002. X      p[news].accept_pending = 0;
  1003. X
  1004. X      /* Allocate a buffer.  */
  1005. X      p[news].fd_buff = (unsigned char *) malloc (BUF_SIZE);
  1006. X      p[news].fd_leftover = 0;
  1007. X
  1008. X      /* Be prepared to get msgs.  */
  1009. X      hang_a_read (news);
  1010. X
  1011. X      /* Now fix up our previous socket so it's again listening
  1012. X         for connections.  */
  1013. X      inetdesc.size = 3;
  1014. X      inetdesc.ptr = "IP:";
  1015. X      if (sys$assign (&inetdesc, &p[s].channel, 0, 0) != SS$_NORMAL)
  1016. X        return -1;
  1017. X      p[s].status = LISTENING;
  1018. X      hang_an_accept (s);
  1019. X
  1020. X      /* Return the new socket descriptor.  */
  1021. X      return news;
  1022. X    }
  1023. X      else if (tcp_make == UCX)
  1024. X    {
  1025. X      /* UCX does the actual accept from hang_an_accept.  The accept info
  1026. X        is put into the data structure for the "listening" socket.
  1027. X        These just need to be copied into a newly allocated socket for
  1028. X        the connect and the listening socket re-started.  */
  1029. X
  1030. X      /* Wait for event flag from accept being received inside
  1031. X         of hang_an_accept().  */
  1032. X
  1033. X      if (wait_efn (s) == -1)
  1034. X        /* Timed out.  */
  1035. X        return -1;
  1036. X
  1037. X      /* Ok, get a new descriptor ...  */
  1038. X      news = dup (0);
  1039. X      if (news > 31)
  1040. X        {
  1041. X          errno = EMFILE;
  1042. X          close (news);
  1043. X          return -1;
  1044. X        }
  1045. X      /* ... and copy all of our data across.  */
  1046. X      bcopy (&p[s], &p[news], sizeof (p[0]));
  1047. X      p[news].s = news;    /* but not this field */
  1048. X      p[news].channel = p[s].ucx_accept_chan;
  1049. X
  1050. X      /* Initialize the remote host address item_list_3 struct.  */
  1051. X      p[news].rhost.length = sizeof (struct sockaddr_in);
  1052. X      p[news].rhost.code = 0;
  1053. X      p[news].rhost.dataptr = (char *) &p[news].from;
  1054. X      p[news].rhost.retlenptr = &p[news].fromdummy;
  1055. X
  1056. X      if (addr != 0)
  1057. X        {
  1058. X          /* Return the caller's info, if requested.  */
  1059. X          *addrlen = p[news].fromdummy;
  1060. X          bcopy (&p[news].from, addr, p[news].fromdummy);
  1061. X        }
  1062. X
  1063. X      /* Finish fleshing out the new structure.  */
  1064. X      p[news].status = PASSIVE_CONNECTION;
  1065. X
  1066. X      /* Get a new file pointer for the socket.  */
  1067. X      p[news].fptr = fdopen (news, "r");
  1068. X
  1069. X      /* Reset this field.  */
  1070. X      p[news].accept_pending = 0;
  1071. X
  1072. X      /* Allocate a buffer.  */
  1073. X      p[news].fd_buff = (unsigned char *) malloc (BUF_SIZE);
  1074. X      p[news].fd_leftover = 0;
  1075. X
  1076. X      /* Get it started reading.  */
  1077. X      hang_a_read (news);
  1078. X
  1079. X      p[s].status = LISTENING;
  1080. X      hang_an_accept (s);
  1081. X
  1082. X      return news;
  1083. X    }
  1084. X      else
  1085. X    {
  1086. X      /* TWG */
  1087. X      struct descriptor inetdesc;
  1088. X      int size;
  1089. X
  1090. X      /* Time out?  */
  1091. X      if (wait_efn (s) == -1)
  1092. X        return -1;
  1093. X
  1094. X      /* Ok, get a new descriptor ...  */
  1095. X      news = dup (0);
  1096. X      if (news > 31)
  1097. X        {
  1098. X          errno = EMFILE;
  1099. X          close (news);
  1100. X          return -1;
  1101. X        }
  1102. X
  1103. X      /* Assign a new channel.  */
  1104. X      inetdesc.size = 7;
  1105. X      inetdesc.ptr = "_INET0:";
  1106. X      st = sys$assign (&inetdesc, &p[news].channel, 0, 0);
  1107. X      if (QIO_ST_FAILED)
  1108. X        {
  1109. X          p[s].accept_pending = 0;
  1110. X          sys$clref (s);
  1111. X          return -1;
  1112. X        }
  1113. X
  1114. X      /* From info needs an int length field! */
  1115. X      size = sizeof (p[s].from) + 4;
  1116. X      st = sys$qiow (0, p[news].channel, IO$_ACCEPT, p[news].iosb, 0, 0,
  1117. X             &p[s].fromdummy, size, p[s].channel, 0, 0, 0);
  1118. X
  1119. X      if (QIO_ST_FAILED || p[news].iosb[0] != SS$_NORMAL)
  1120. X        {
  1121. X          p[s].accept_pending = 0;
  1122. X          sys$clref (s);
  1123. X          return -1;
  1124. X        }
  1125. X
  1126. X      if (addr != 0)
  1127. X        {
  1128. X          /* Return the caller's info if requested.  */
  1129. X          *addrlen = p[s].fromdummy;
  1130. X          bcopy (&p[s].from, addr, *addrlen);
  1131. X        }
  1132. X
  1133. X      /* Fix up our new data structure.  */
  1134. X      p[news].status = PASSIVE_CONNECTION;
  1135. X      p[news].domain = AF_INET;
  1136. X      p[news].passive = 1;
  1137. X      p[news].fptr = fdopen (news, "r");
  1138. X      /* Allocate a buffer.  */
  1139. X      p[news].fd_buff = (unsigned char *) malloc (BUF_SIZE);
  1140. X
  1141. X      /* Be prepared to accept msgs.  */
  1142. X      hang_a_read (news);
  1143. X
  1144. X      /* Get the old descriptor back onto accepting.  */
  1145. X      hang_an_accept (s);
  1146. X      return news;
  1147. X    }
  1148. X    }
  1149. X  else
  1150. X    /* We don't handle any other domain yet.  */
  1151. X    return -1;
  1152. X}
  1153. X
  1154. X/* Recv routine.  */
  1155. Xint
  1156. XVMSrecv (s, buf, len, flags)
  1157. X     int s;
  1158. X     char *buf;
  1159. X     int len, flags;
  1160. X{
  1161. X  return recvfrom (s, buf, len, flags, 0, 0);
  1162. X}
  1163. X
  1164. X/* Revfrom routine.  */
  1165. Xint
  1166. XVMSrecvfrom (s, buf, len, flags, from, fromlen)
  1167. X     int s;
  1168. X     char *buf;
  1169. X     int len, flags;
  1170. X     union socket_addr *from;
  1171. X     int *fromlen;
  1172. X{
  1173. X  int number;
  1174. X
  1175. X  if (!tcp_make)
  1176. X    set_tcp_make ();
  1177. X
  1178. X  if (p[s].domain != AF_INET && p[s].domain != AF_X25)
  1179. X    return -1;
  1180. X
  1181. X  /* If we're not onto datagrams, then it's possible that a previous
  1182. X     call to recvfrom didn't read all the data, and left some behind.
  1183. X     So first of all, look in our data buffer for any leftovers that
  1184. X     will satisfy this read.  */
  1185. X
  1186. X  /* We couldn't satisfy the request from previous calls so we must now
  1187. X     wait for a message to come through.  */
  1188. X  if (wait_efn (s) == -1)
  1189. X    /* Timed out.  */
  1190. X    return -1;
  1191. X
  1192. X  if (p[s].closed_by_remote == 1)
  1193. X    {
  1194. X      /* This could have happened! */
  1195. X      errno = ECONNRESET;
  1196. X      return -1;
  1197. X    }
  1198. X
  1199. X  if (from != NULL)
  1200. X    {
  1201. X      if (tcp_make == CMU)
  1202. X    {
  1203. X      if (p[s].type == SOCK_DGRAM)
  1204. X        {
  1205. X          /* Not documented but we get the from data from the beginning of
  1206. X         the data buffer.  */
  1207. X          *fromlen = sizeof (p[s].from.in);
  1208. X          from->in.sin_family = AF_INET;
  1209. X          bcopy (&p[s].fd_buff[8], &(from->in.sin_port), 2);
  1210. X          from->in.sin_port = htons (from->in.sin_port);
  1211. X          bcopy (&p[s].fd_buff[0], &(from->in.sin_addr), 4);
  1212. X
  1213. X          /* Remove the address data from front of data buffer.  */
  1214. X          bcopy (p[s].fd_buff + 12, p[s].fd_buff, p[s].fd_buff_size);
  1215. X        }
  1216. X      else
  1217. X        {
  1218. X          *fromlen = p[s].fromlen;
  1219. X          bcopy (&p[s].from, from, p[s].fromlen);
  1220. X        }
  1221. X    }
  1222. X      else if (tcp_make == UCX)
  1223. X    {
  1224. X      *fromlen = p[s].fromdummy;
  1225. X      bcopy (&p[s].from, from, p[s].fromdummy);
  1226. X    }
  1227. X      else
  1228. X    {
  1229. X      *fromlen = p[s].fromlen;
  1230. X      bcopy (&p[s].from, from, p[s].fromlen);
  1231. X    }
  1232. X    }
  1233. X
  1234. X  /* We may've received too much.  */
  1235. X  number = p[s].fd_buff_size;
  1236. X  if (number <= len)
  1237. X    {
  1238. X      /* If we haven't give back all the data available.  */
  1239. X      bcopy (p[s].fd_buff, buf, number);
  1240. X      p[s].fd_leftover = 0;
  1241. X      hang_a_read (s);
  1242. X      return (number);
  1243. X    }
  1244. X  else
  1245. X    {
  1246. X      /* If we have too much data then split it up.  */
  1247. X      p[s].fd_leftover = p[s].fd_buff;
  1248. X      bcopy (p[s].fd_leftover, buf, len);
  1249. X      /* And change the pointers.  */
  1250. X      p[s].fd_leftover += len;
  1251. X      p[s].fd_buff_size -= len;
  1252. X      return (len);
  1253. X    }
  1254. X}
  1255. X
  1256. X/* Send routine.  */
  1257. Xint
  1258. XVMSsend (s, msg, len, flags)
  1259. X     int s;
  1260. X     char *msg;
  1261. X     int len, flags;
  1262. X{
  1263. X  return sendto (s, msg, len, flags, 0, 0);
  1264. X}
  1265. X
  1266. X/* Sendto routine.  */
  1267. Xint
  1268. XVMSsendto (s, msg, len, flags, to, tolen)
  1269. X     int s;
  1270. X     unsigned char *msg;
  1271. X     int len, flags;
  1272. X     union socket_addr *to;
  1273. X     int tolen;
  1274. X{
  1275. X  int i, j, st, size;
  1276. X  unsigned char udpbuf[BUF_SIZE + 12];
  1277. X  char infobuff[1024], lhost[32];
  1278. X  unsigned short int temp;
  1279. X
  1280. X  if (!tcp_make)
  1281. X    set_tcp_make ();
  1282. X
  1283. X  /* First remember who we sent it to and set the value of size.  */
  1284. X  if (to != 0)
  1285. X    {
  1286. X      p[s].tolen = tolen;
  1287. X      bcopy (to, &(p[s].to), tolen);
  1288. X      size = tolen;
  1289. X    }
  1290. X  else
  1291. X    size = 0;
  1292. X
  1293. X  if (p[s].domain == AF_INET)
  1294. X    {
  1295. X      /* We might never have started a read for udp (socket/sendto) so
  1296. X     put one here.  */
  1297. X      if (p[s].type == SOCK_DGRAM)
  1298. X    hang_a_read (s);
  1299. X
  1300. X      if (tcp_make == CMU)
  1301. X    {
  1302. X      if (p[s].type == SOCK_DGRAM)
  1303. X        {
  1304. X          /* We might never have opened up a udp connection yet,
  1305. X         so check.  */
  1306. X          if (p[s].cmu_open != 1)
  1307. X        {
  1308. X          st = sys$qiow (0, p[s].channel, TCP$OPEN, p[s].iosb, 0, 0,
  1309. X                 0, 0, 0, 0, 1, 0);
  1310. X          if (QIO_ST_FAILED)
  1311. X            return -1;
  1312. X
  1313. X          p[s].cmu_open = 1;
  1314. X          sys$qiow (0, p[s].channel, TCP$INFO, p[s].iosb,
  1315. X                0, 0, &infobuff, 1024, 0, 0, 0, 0);
  1316. X          bcopy (infobuff + 264, &(p[s].name.in.sin_port), 2);
  1317. X          p[s].name.in.sin_port = htons (p[s].name.in.sin_port);
  1318. X          bcopy (infobuff + 136, lhost, infobuff[1]);
  1319. X          lhost[infobuff[1]] = '\0';
  1320. X          sys$qiow (0, p[s].channel, GTHST, p[s].iosb,
  1321. X                0, 0, &infobuff, 1024, 1, lhost, 0, 0);
  1322. X          bcopy (infobuff + 4, &(p[s].name.in.sin_addr), 4);
  1323. X        }
  1324. X
  1325. X          /* This isn't well documented.  To send to a UDP socket, we
  1326. X         need to put the address info at the beginning of the
  1327. X         buffer.  */
  1328. X          bcopy (msg, udpbuf + 12, len);
  1329. X          bcopy (&p[s].to.in.sin_addr, udpbuf + 4, 4);
  1330. X          temp = ntohs (p[s].to.in.sin_port);
  1331. X          bcopy (&temp, udpbuf + 10, 2);
  1332. X          bcopy (&p[s].name.in.sin_addr, udpbuf, 4);
  1333. X          temp = ntohs (p[s].name.in.sin_port);
  1334. X          bcopy (&temp, udpbuf + 8, 2);
  1335. X          temp = len + 12;
  1336. X          st = sys$qiow (0, p[s].channel, TCP$SEND, p[s].iosb, 0, 0,
  1337. X                 udpbuf, temp, 0, 0, 0, 0);
  1338. X          if (QIO_FAILED)
  1339. X        return -1;
  1340. X        }
  1341. X      else
  1342. X        {
  1343. X          /* TCP (! UDP)  */
  1344. X          st = sys$qiow (0, p[s].channel, TCP$SEND, p[s].iosb, 0, 0,
  1345. X                 msg, len, 0, 0, 0, 0);
  1346. X          if (QIO_FAILED)
  1347. X        return -1;
  1348. X        }
  1349. X      return len;
  1350. X    }
  1351. X      else if (tcp_make == UCX)
  1352. X    {
  1353. X      struct itemlist rhost;
  1354. X      rhost.length = sizeof (struct sockaddr_in);
  1355. X      rhost.code = 0;
  1356. X      rhost.dataptr = (char *) &p[s].to;
  1357. X
  1358. X      st = sys$qiow (0, p[s].channel, IO$_WRITEVBLK, p[s].iosb, 0, 0,
  1359. X             msg, len, &rhost, 0, 0, 0);
  1360. X      if (QIO_FAILED)
  1361. X        return -1;
  1362. X
  1363. X      return len;
  1364. X    }
  1365. X      else
  1366. X    {
  1367. X      /* TWG */
  1368. X      st = sys$qiow (0, p[s].channel, IO$_WRITEVBLK, p[s].iosb,
  1369. X             0, 0, msg, len, 0, &p[s].to, size, 0);
  1370. X      if (QIO_FAILED)
  1371. X        return -1;
  1372. X
  1373. X      return len;
  1374. X    }
  1375. X    }
  1376. X  else
  1377. X    /* We don't handle any other domain yet.  */
  1378. X    return -1;
  1379. X}
  1380. X
  1381. X/* Getsockname routine.  */
  1382. Xint
  1383. XVMSgetsockname (s, name, namelen)
  1384. X     int s;
  1385. X     union socket_addr *name;
  1386. X     int *namelen;
  1387. X{
  1388. X  int st;
  1389. X
  1390. X  if (!tcp_make)
  1391. X    set_tcp_make ();
  1392. X
  1393. X  if (p[s].domain == AF_INET)
  1394. X    {
  1395. X      if (tcp_make == CMU)
  1396. X    {
  1397. X      /* For CMU we just return values held in our data structure.  */
  1398. X      *namelen = p[s].namelen;
  1399. X      bcopy (&(p[s].name), name, *namelen);
  1400. X      return (0);
  1401. X    }
  1402. X      else if (tcp_make == UCX)
  1403. X    {
  1404. X      /* An item_list_3 descriptor.  */
  1405. X      struct itemlist lhost;
  1406. X
  1407. X      lhost.length = *namelen;
  1408. X      lhost.code = 0;
  1409. X      lhost.dataptr = (char *) name;
  1410. X
  1411. X      /* Fill in namelen with actual ret len value.  */
  1412. X      lhost.retlenptr = (short int *) namelen;
  1413. X
  1414. X      st = sys$qiow (0, p[s].channel, IO$_SENSEMODE, p[s].iosb, 0, 0,
  1415. X             0, 0, &lhost, 0, 0, 0);
  1416. X      if (QIO_FAILED)
  1417. X        return -1;
  1418. X
  1419. X      return 0;
  1420. X    }
  1421. X      else
  1422. X    {
  1423. X      /* TWG gives us the information. */
  1424. X      st = sys$qiow (0, p[s].channel, IO$_GETSOCKNAME, p[s].iosb,
  1425. X             0, 0, name, namelen, 0, 0, 0, 0);
  1426. X      if (QIO_FAILED)
  1427. X        return -1;
  1428. X
  1429. X      return 0;
  1430. X    }
  1431. X    }
  1432. X  else
  1433. X    /* We don't handle any other domain yet.  */
  1434. X    return -1;
  1435. X}
  1436. X
  1437. X/* Select routine.  */
  1438. Xint
  1439. XVMSselect (nfds, readfds, writefds, exceptfds, timeout)
  1440. X     int nfds;
  1441. X     fd_set *readfds, *writefds, *exceptfds;
  1442. X     struct timeval *timeout;
  1443. X{
  1444. X  int timer, fd, alarm_set, total, end;
  1445. X  long mask, cluster;
  1446. X  struct descriptor termdesc;
  1447. X  static fd_set new_readfds, new_writefds, new_exceptfds;
  1448. X
  1449. X  FD_ZERO (&new_readfds);
  1450. X  FD_ZERO (&new_writefds);
  1451. X  FD_ZERO (&new_exceptfds);
  1452. X  total = 0;
  1453. X
  1454. X  /* Assign a terminal channel if we haven't already.  */
  1455. X  if (terminal.chan == -1)
  1456. X    {
  1457. X      termdesc.size = 10;
  1458. X      termdesc.ptr = "SYS$INPUT:";
  1459. X      sys$assign (&termdesc, &terminal.chan, 0, 0);
  1460. X    }
  1461. X  alarm_set = 0;
  1462. X  if (timeout != NULL)
  1463. X    {
  1464. X      /* If a timeout is given then set the alarm.  */
  1465. X      end = timeout->tv_sec;
  1466. X      if (timer != 0)
  1467. X    {
  1468. X      /* We need to reset the alarm if it didn't fire, but we set it.  */
  1469. X      alarm_set = 1;
  1470. X      si_alarm (end);
  1471. X    }
  1472. X    }
  1473. X  else
  1474. X    end = 1;
  1475. X
  1476. X  do
  1477. X    {
  1478. X      if (exceptfds)
  1479. X    {
  1480. X       /* Nothing */ ;
  1481. X    }
  1482. X
  1483. X      if (writefds)
  1484. X    {
  1485. X      for (fd = 0; fd < nfds; fd++)
  1486. X        if (FD_ISSET (fd, writefds))
  1487. X          {
  1488. X        if (p[fd].connect_pending)
  1489. X           /* Nothing */ ;
  1490. X        else if ((p[fd].status == ACTIVE_CONNECTION)
  1491. X             || (p[fd].status == PASSIVE_CONNECTION))
  1492. X          {
  1493. X            FD_SET (fd, &new_writefds);
  1494. X            total++;
  1495. X          }
  1496. X          }
  1497. X    }
  1498. X
  1499. X      if (readfds)
  1500. X    {
  1501. X      /* True if data pending or an accept.  */
  1502. X      for (fd = 3; fd < nfds; fd++)
  1503. X        if (FD_ISSET (fd, readfds) &&
  1504. X        ((p[fd].fd_buff_size != -1) || (p[fd].accept_pending == 1)))
  1505. X          {
  1506. X        FD_SET (fd, &new_readfds);
  1507. X        total++;
  1508. X          }
  1509. X    }
  1510. X
  1511. X      if (total || (end == 0))
  1512. X    break;
  1513. X
  1514. X      /* Otherwise, wait on an event flag.  It's possible that the wait can
  1515. X     be stopped by a spurious event flag being set -- i.e. one that's
  1516. X     got a status not normal.  So we've got to be prepared to loop
  1517. X     around the wait until a valid reason happens.  */
  1518. X
  1519. X      /* Set up the wait mask.  */
  1520. X      cluster = 0;
  1521. X      mask = 0;
  1522. X      for (fd = 3; fd < nfds; fd++)
  1523. X    {
  1524. X      sys$clref (fd);
  1525. X      if (readfds)
  1526. X        if FD_ISSET
  1527. X          (fd, readfds) mask |= (1 << fd);
  1528. X      if (writefds)
  1529. X        if FD_ISSET
  1530. X          (fd, writefds) mask |= (1 << fd);
  1531. X      if (exceptfds)
  1532. X        if FD_ISSET
  1533. X          (fd, exceptfds) mask |= (1 << fd);
  1534. X    }
  1535. X
  1536. X      mask |= (1 << TIMER_EFN);
  1537. X
  1538. X      /* Clear it off just in case.  */
  1539. X      sys$clref (TIMER_EFN);
  1540. X
  1541. X      /* Wait around.  */
  1542. X      sys$wflor (cluster, mask);
  1543. X
  1544. X      mask = 0;
  1545. X      if (read_efn (TIMER_EFN))
  1546. X    {
  1547. X      errno = EINTR;
  1548. X      break;
  1549. X    }
  1550. X  } while (1);
  1551. X  /*NOTREACHED*/
  1552. X
  1553. X  /* Unset the alarm if we set it.  */
  1554. X  if (alarm_set == 1)
  1555. X    alarm (0);
  1556. X
  1557. X  if (readfds)
  1558. X    *readfds = new_readfds;
  1559. X
  1560. X  if (writefds)
  1561. X    *writefds = new_writefds;
  1562. X
  1563. X  if (exceptfds)
  1564. X    *exceptfds = new_exceptfds;
  1565. X
  1566. X  return total;
  1567. X}
  1568. X
  1569. X/* Shutdown routine.  */
  1570. XVMSshutdown (s, how)
  1571. X     int s, how;
  1572. X{
  1573. X  int st;
  1574. X  int ucx_how;
  1575. X
  1576. X  if (!tcp_make)
  1577. X    set_tcp_make ();
  1578. X
  1579. X  if (p[s].domain == AF_INET)
  1580. X    {
  1581. X      if (tcp_make == CMU)
  1582. X    {
  1583. X      /* For CMU we just close off.  */
  1584. X      si_close (s);
  1585. X      return 0;
  1586. X    }
  1587. X      else if (tcp_make == UCX)
  1588. X    {
  1589. X      st = sys$qiow (0, p[s].channel, IO$_DEACCESS | IO$M_SHUTDOWN,
  1590. X             p[s].iosb, 0, 0, 0, 0, 0, how, 0, 0);
  1591. X      if (QIO_FAILED)
  1592. X        return -1;
  1593. X
  1594. X      return 0;
  1595. X    }
  1596. X      else
  1597. X    {
  1598. X      /* TWG lets us do it.  */
  1599. X      st = sys$qiow (0, p[s].channel, IO$_SHUTDOWN, p[s].iosb, 0, 0, how,
  1600. X             0, 0, 0, 0, 0);
  1601. X      if (QIO_FAILED)
  1602. X        return -1;
  1603. X
  1604. X      return 0;
  1605. X    }
  1606. X    }
  1607. X  else                /* it wasn't a socket */
  1608. X    return -1;
  1609. X}
  1610. X
  1611. X/*   */
  1612. X
  1613. X/* The following routines are used by the above socket calls.  */
  1614. X
  1615. X/* hang_a_read sets up a read to be finished at some later time.  */
  1616. Xhang_a_read (s)
  1617. X     int s;
  1618. X{
  1619. X  extern int read_ast ();
  1620. X  int size, st;
  1621. X
  1622. X  /* Don't bother if we already did it.  */
  1623. X  if (p[s].read_outstanding == 1)
  1624. X    return;
  1625. X
  1626. X  /* Have a read outstanding.  */
  1627. X  p[s].read_outstanding = 1;
  1628. X  size = sizeof (p[s].from) + 4;
  1629. X  sys$clref (s);
  1630. X
  1631. X  /* Clear off the event flag just in case, and reset the buf size.  */
  1632. X  p[s].fd_buff_size = -1;
  1633. X  if (p[s].domain == AF_INET)
  1634. X    {
  1635. X      if (tcp_make == CMU)
  1636. X    {
  1637. X      st = sys$qio (s, p[s].channel, TCP$RECEIVE, p[s].iosb, read_ast,
  1638. X            &p[s], p[s].fd_buff, BUF_SIZE, 0, 0, 0, 0);
  1639. X      if (QIO_ST_FAILED)
  1640. X        return -1;
  1641. X    }
  1642. X      else if (tcp_make == UCX)
  1643. X    {
  1644. X
  1645. X      p[s].rhost.length = sizeof (struct sockaddr_in);
  1646. X      p[s].rhost.code = 0;
  1647. X      p[s].rhost.dataptr = (char *) &p[s].from;
  1648. X      p[s].rhost.retlenptr = &p[s].fromdummy;
  1649. X
  1650. X      st = sys$qio (s, p[s].channel, IO$_READVBLK, p[s].iosb, read_ast,
  1651. X            &p[s], p[s].fd_buff, BUF_SIZE, &p[s].rhost, 0, 0, 0);
  1652. X      if (QIO_ST_FAILED)
  1653. X        return -1;
  1654. X    }
  1655. X      else
  1656. X    {
  1657. X      /* TWG */
  1658. X      st = sys$qio (s, p[s].channel, IO$_READVBLK, p[s].iosb, read_ast,
  1659. X            &p[s], p[s].fd_buff, BUF_SIZE, 0, &p[s].fromlen,
  1660. X            size, 0);
  1661. X      if (QIO_ST_FAILED)
  1662. X        return -1;
  1663. X    }
  1664. X    }
  1665. X  else
  1666. X    /* We don't handle any other domain yet.  */
  1667. X    return -1;
  1668. X}
  1669. X
  1670. X/* hang_an_accept waits for a connection request to come in.  */
  1671. Xhang_an_accept (s)
  1672. X     int s;
  1673. X{
  1674. X  extern int accept_ast ();
  1675. X  int st;
  1676. X
  1677. X  /* Clear the event flag just in case.  */
  1678. X  sys$clref (s);
  1679. X
  1680. X  /* Reset our flag & buf size.  */
  1681. X  p[s].accept_pending = 0;
  1682. X  p[s].fd_buff_size = -1;
  1683. X  if (p[s].domain == AF_INET)
  1684. X    {
  1685. X      if (tcp_make == CMU)
  1686. X    {
  1687. X      st = sys$qio (s, p[s].channel, TCP$OPEN, p[s].iosb, accept_ast,
  1688. X            &p[s], 0, 0, ntohs (p[s].name.in.sin_port), 0, 0, 0);
  1689. X      if (QIO_ST_FAILED)
  1690. X        return -1;
  1691. X    }
  1692. X      else if (tcp_make == UCX)
  1693. X    {
  1694. X      struct descriptor inetdesc;
  1695. X
  1696. X      /* Assign channel for actual connection off listener.  */
  1697. X      inetdesc.size = 3;
  1698. X      inetdesc.ptr = "BG:";
  1699. X      if (sys$assign (&inetdesc, &p[s].ucx_accept_chan, 0,
  1700. X              0) != SS$_NORMAL)
  1701. X        return -1;
  1702. X
  1703. X      /* UCX's accept returns remote host info and the channel for a new
  1704. X         socket to perform reads/writes on, so a sys$assign isn't
  1705. X         really necessary.  */
  1706. X      p[s].rhost.length = sizeof (struct sockaddr_in);
  1707. X      p[s].rhost.dataptr = (char *) &p[s].from;
  1708. X      p[s].fromdummy = 0;
  1709. X      p[s].rhost.retlenptr = &p[s].fromdummy;
  1710. X
  1711. X      st = sys$qio (s, p[s].channel, IO$_ACCESS | IO$M_ACCEPT, p[s].iosb,
  1712. X            accept_ast, &p[s], 0, 0, &p[s].rhost,
  1713. X            &p[s].ucx_accept_chan, 0, 0);
  1714. X      if (QIO_ST_FAILED)
  1715. X        return -1;
  1716. X    }
  1717. X      else
  1718. X    {
  1719. X      st = sys$qio (s, p[s].channel, IO$_ACCEPT_WAIT, p[s].iosb,
  1720. X            accept_ast, &p[s], 0, 0, 0, 0, 0, 0);
  1721. X      if (QIO_ST_FAILED)
  1722. X        return -1;
  1723. X    }
  1724. X    }
  1725. X  else
  1726. X    /* We don't handle any other domain yet.  */
  1727. X    return -1;
  1728. X}
  1729. X
  1730. X/* wait_efn just sets up a wait on either an event or the timer.  */
  1731. Xwait_efn (s)
  1732. X     int s;
  1733. X{
  1734. X  long mask, cluster;
  1735. X
  1736. X  cluster = 0;
  1737. X  sys$clref (TIMER_EFN);
  1738. X  mask = (1 << s) | (1 << TIMER_EFN);
  1739. X  sys$wflor (cluster, mask);
  1740. X
  1741. X  if (read_efn (TIMER_EFN))
  1742. X    {
  1743. X      errno = EINTR;
  1744. X      return -1;
  1745. X    }
  1746. X
  1747. X  return 0;
  1748. X}
  1749. X
  1750. X/* read_ast is called by the system whenever a read is done.  */
  1751. Xread_ast (p)
  1752. X     struct fd_entry *p;
  1753. X{
  1754. X  int i, j;
  1755. X  unsigned char *v, *w;
  1756. X
  1757. X  /* Reset the outstanding flag.  */
  1758. X  p->read_outstanding = 0;
  1759. X  if (p->iosb[0] == SS$_NORMAL)
  1760. X    {
  1761. X      /* Check no errors.  */
  1762. X      p->fd_buff_size = p->iosb[1];
  1763. X      if (tcp_make == CMU)
  1764. X    {
  1765. X      /* fiddle for DGRMs */
  1766. X      if (p->type == SOCK_DGRAM)
  1767. X        p->fd_buff_size -= 12;
  1768. X    }
  1769. X      if (p->sig_req == 1)
  1770. X    gsignal (SIGIO);
  1771. X    }
  1772. X  else if (p->iosb[0] == SS$_CLEARED)
  1773. X    p->closed_by_remote = 1;
  1774. X  else if (tcp_make == UCX)
  1775. X    {
  1776. X      if (p->iosb[0] == SS$_LINKDISCON)
  1777. X    p->closed_by_remote = 1;
  1778. X    }
  1779. X}
  1780. X
  1781. X/* accept_ast is called whenever an incoming call is detected.  */
  1782. Xaccept_ast (p)
  1783. X     struct fd_entry *p;
  1784. X{
  1785. X  if (p->iosb[0] == SS$_NORMAL)
  1786. X    p->accept_pending = 1;
  1787. X  else
  1788. X    /* If it failed set up another listen.  */
  1789. X    listen (p->s, p[p->s].backlog);
  1790. X}
  1791. X
  1792. X/* connect_ast is called whenever an async connect is made.  */
  1793. Xconnect_ast (p)
  1794. X     struct fd_entry *p;
  1795. X{
  1796. X  p->connect_pending = 0;
  1797. X  if ((p->connected = p->iosb[0]) == SS$_NORMAL)
  1798. X    {
  1799. X      /* We made the connection.  */
  1800. X      p->status = ACTIVE_CONNECTION;
  1801. X
  1802. X      /* Be prepared to accept a msg.  */
  1803. X      hang_a_read (p->s);
  1804. X    }
  1805. X}
  1806. X
  1807. X/*   */
  1808. X/* These routines handle stream I/O.  */
  1809. X
  1810. X/* si_close -- must close off any connection in progress.  */
  1811. Xsi_close (s)
  1812. X     int s;
  1813. X{
  1814. X  if (!tcp_make)
  1815. X    set_tcp_make ();
  1816. X
  1817. X  if ((s < 0) || (s > 31))
  1818. X    return -1;
  1819. X
  1820. X  if (p[s].channel != 0)
  1821. X    {
  1822. X      /* Was it one of our descriptors? */
  1823. X      if (p[s].domain == AF_INET)
  1824. X    {
  1825. X      if (tcp_make == CMU)
  1826. X        sys$qiow (0, p[s].channel, TCP$CLOSE, p[s].iosb,
  1827. X              0, 0, 0, 0, 0, 0, 0, 0);
  1828. X      if (p[s].status != HANDED_OFF)
  1829. X        sys$dassgn (p[s].channel);
  1830. X      close (s);
  1831. X      free (p[s].fd_buff);
  1832. X      p_initialise (s);
  1833. X    }
  1834. X      return 0;
  1835. X    }
  1836. X  else
  1837. X    {
  1838. X      /* Re-initialise data structure just in case.  */
  1839. X      p[s].fd_buff_size = -1;
  1840. X      p[s].accept_pending = 0;
  1841. X      p[s].status = INITIALISED;
  1842. X      return close (s);
  1843. X    }
  1844. X}
  1845. X
  1846. X/* si_alarm -- insert a call to our own alarm function.  */
  1847. Xsi_alarm (i)
  1848. X     int i;
  1849. X{
  1850. X  extern int pre_alarm ();
  1851. X
  1852. X  /* Make the call to pre_alarm instead of what the user wants;
  1853. X     pre_alarm will call his routine when it finishes.  */
  1854. X  /* VAX needs this call each time! */
  1855. X  signal (SIGALRM, pre_alarm);
  1856. X  alarm (i);
  1857. X}
  1858. X
  1859. X/* pre_alarm -- gets called first on an alarm signal.  */
  1860. Xpre_alarm ()
  1861. X{
  1862. X  /* Come here first so we can set our timer event flag.  */
  1863. X  sys$setef (TIMER_EFN);
  1864. X  (*alarm_function) ();
  1865. X}
  1866. X
  1867. X/* p_initialise - initialise our data array.  */
  1868. Xp_initialise (s)
  1869. X     int s;
  1870. X{
  1871. X  int j;
  1872. X  for (j = 0; j < 4; j++)
  1873. X    p[s].iosb[j] = 0;
  1874. X  p[s].channel = 0;
  1875. X  p[s].fd_buff_size = -1;
  1876. X  p[s].accept_pending = 0;
  1877. X  p[s].connect_pending = 0;
  1878. X  p[s].connected = 0;
  1879. X  p[s].fd_buff = NULL;
  1880. X  p[s].fd_leftover = NULL;
  1881. X  p[s].fptr = NULL;
  1882. X  p[s].s = s;
  1883. X  p[s].name.in.sin_port = 0;
  1884. X  p[s].masklen = 4;
  1885. X  for (j = 0; j < 16; j++)
  1886. X    p[s].mask[j] = 0xff;
  1887. X  p[s].need_header = 0;
  1888. X  p[s].status = INITIALISED;
  1889. X  p[s].read_outstanding = 0;
  1890. X  p[s].cmu_open = 0;
  1891. X  p[s].x25_listener = 0;
  1892. X  p[s].mother = s;
  1893. X  p[s].child = 0;
  1894. X  p[s].no_more_accepts = 0;
  1895. X  p[s].closed_by_remote = 0;
  1896. X  p[s].non_blocking = 0;
  1897. X  p[s].sig_req = 0;
  1898. X  sys$clref (s);
  1899. X}
  1900. X
  1901. X/* read_efn -- see whether an event flag is set.  */
  1902. Xread_efn (i)
  1903. X     int i;
  1904. X{
  1905. X  int j;
  1906. X  sys$readef (i, &j);
  1907. X  j &= (1 << i);
  1908. X
  1909. X  return j;
  1910. X}
  1911. X
  1912. Xstatic
  1913. Xset_tcp_make ()
  1914. X{
  1915. X  struct descriptor inetdesc;
  1916. X  int channel;
  1917. X  /* first try CMU */
  1918. X  inetdesc.size = 3;
  1919. X  inetdesc.ptr = "IP:";
  1920. X  if (sys$assign (&inetdesc, &channel, 0, 0) == SS$_NORMAL)
  1921. X    {
  1922. X      sys$dassgn (channel);
  1923. X      tcp_make = CMU;
  1924. X      return;
  1925. X    }
  1926. X
  1927. X  /* next try TWG */
  1928. X  inetdesc.size = 7;
  1929. X  inetdesc.ptr = "_INET0:";
  1930. X  if (sys$assign (&inetdesc, &channel, 0, 0) == SS$_NORMAL)
  1931. X    {
  1932. X      sys$dassgn (channel);
  1933. X      tcp_make = WG;
  1934. X      return;
  1935. X    }
  1936. X
  1937. X  /* next try UCX */
  1938. X  inetdesc.size = 4;
  1939. X  inetdesc.ptr = "BG0:";
  1940. X  if (sys$assign (&inetdesc, &channel, 0, 0) == SS$_NORMAL)
  1941. X    {
  1942. X      sys$dassgn (channel);
  1943. X      tcp_make = UCX;
  1944. X      return;
  1945. X    }
  1946. X
  1947. X  /* nothing there oh dear!*/
  1948. X  tcp_make = NONE;
  1949. X  return;
  1950. X}
  1951. X
  1952. Xstatic char *
  1953. Xgetdevicename (channel)
  1954. X     unsigned short int channel;
  1955. X{
  1956. X  int st;
  1957. X  struct
  1958. X  {
  1959. X    struct itemlist id;
  1960. X    int eol;
  1961. X  } itmlst;
  1962. X  static char name[64];
  1963. X  short int lgth;
  1964. X
  1965. X  name[0] = '\0';
  1966. X  itmlst.id.code = DVI$_DEVNAM;
  1967. X  itmlst.id.length = 64;
  1968. X  itmlst.id.dataptr = name;
  1969. X  itmlst.id.retlenptr = &lgth;
  1970. X  itmlst.eol = 0;
  1971. X  st = sys$getdvi (0, channel, 0, &itmlst, 0, 0, 0, 0);
  1972. X  if (QIO_ST_FAILED)
  1973. X    fprintf (stderr, "error getting device name %d\n", st);
  1974. X
  1975. X  return (name);
  1976. X}
  1977. END_OF_FILE
  1978.   if test 32780 -ne `wc -c <'vms_support.c'`; then
  1979.     echo shar: \"'vms_support.c'\" unpacked with wrong size!
  1980.   fi
  1981.   # end of 'vms_support.c'
  1982. fi
  1983. echo shar: End of archive 1 \(of 7\).
  1984. cp /dev/null ark1isdone
  1985. MISSING=""
  1986. for I in 1 2 3 4 5 6 7 ; do
  1987.     if test ! -f ark${I}isdone ; then
  1988.     MISSING="${MISSING} ${I}"
  1989.     fi
  1990. done
  1991. if test "${MISSING}" = "" ; then
  1992.     echo You have unpacked all 7 archives.
  1993.     rm -f ark[1-9]isdone
  1994. else
  1995.     echo You still must unpack the following archives:
  1996.     echo "        " ${MISSING}
  1997. fi
  1998. exit 0
  1999. exit 0 # Just in case...
  2000.