home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #26 / NN_1992_26.iso / spool / comp / sources / misc / 4055 < prev    next >
Encoding:
Text File  |  1992-11-05  |  54.9 KB  |  2,006 lines

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