home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume26 / archie / part01 next >
Encoding:
Text File  |  1991-11-23  |  53.8 KB  |  2,250 lines

  1. Newsgroups: comp.sources.misc
  2. From: brendan@cs.widener.edu (Brendan Kehoe)
  3. Subject:  v26i046:  archie - A Prospero client for Archie, v1.2, Part01/05
  4. Message-ID: <csm-v26i046=archie.225243@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: d74fd4bb34930ed88f5866ee64664f9d
  6. Date: Sun, 24 Nov 1991 04:53:48 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: brendan@cs.widener.edu (Brendan Kehoe)
  10. Posting-number: Volume 26, Issue 46
  11. Archive-name: archie/part01
  12. Environment: UNIX, VMS
  13. Supersedes: archie: Volume 22, Issue 35-39
  14.  
  15. This is the official release of Archie 1.2, a stand-alone client to
  16. access the Archie FTP database.  It's intended to help reduce the
  17. interactive use of the archie server by providing a comfortable,
  18. accessible, and faster method of query.
  19.  
  20.  Changes since version 1.1 include:
  21.  
  22.     * much more portable; now runs under VMS (with Multinet & Wallongong
  23.       TCP/IP), MSDOS and OS/2 (with PC/TCP), and countless versions of Unix
  24.     * faster and cleaner code (those in the US will notice a marked
  25.       difference in response time by using the default of ARCHIE.SURA.NET
  26.       for their server; 1.1 used quiche)
  27.     * dirsend.c totally rewritten by George Ferguson
  28.     * bug fixes
  29.     * (hopefully) clearer man page
  30.     * handles Prospero warnings
  31.     * builds with gcc on sparcs properly
  32.     * mentions available servers
  33.  
  34.  There are now a goodly number of servers available, so no one system
  35. will get hit with the world's use.  They are (as of 11/20/91):
  36.  
  37.         archie.sura.net (USA, Mexico, etc)
  38.         archie.mcgill.ca (Canada)
  39.         archie.funet.fi (Finland/Mainland Europe)
  40.         archie.au (Australia/New Zealand)
  41.         archie.doc.ic.ac.uk (Great Britain/Ireland)
  42.  
  43.  The package is available in the comp.sources.misc and vmsnet.sources
  44. newsgroups (and, later, their archives), or via anonymous FTP from:
  45.  
  46.     * ftp.cs.widener.edu [147.31.254.132] as pub/archie.tar.Z (unix)
  47.       or archie-vms.com (VMS DCL .com file)
  48.     * cs.rochester.edu [192.5.53.209] as pub/archie-1.2.tar.Z
  49.     * ftp.huji.ac.il [132.65.6.5] as pub/archie-clients/c-archie.tar.Z
  50.       (for Israeli sites mainly)
  51.  
  52.  Please report any comments, suggestions, fixes, (whether positive or negative)
  53. to brendan@cs.widener.edu.  Enjoy!
  54.  
  55. Brendan Kehoe, Widener University, Chester, PA
  56. --
  57. #! /bin/sh
  58. # This is a shell archive.  Remove anything before this line, then feed it
  59. # into a shell via "sh file" or similar.  To overwrite existing files,
  60. # type "sh file -c".
  61. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  62. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  63. # Contents:  . ./regex.c ./vms ./vms_support.c
  64. # Wrapped by kent@sparky on Wed Nov 20 18:23:43 1991
  65. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  66. echo If this archive is complete, you will see the following message:
  67. echo '          "shar: End of archive 1 (of 5)."'
  68. if test -f './regex.c' -a "${1}" != "-c" ; then 
  69.   echo shar: Will not clobber existing file \"'./regex.c'\"
  70. else
  71.   echo shar: Extracting \"'./regex.c'\" \(16057 characters\)
  72.   sed "s/^X//" >'./regex.c' <<'END_OF_FILE'
  73. X#include <pmachine.h>
  74. X
  75. X#ifdef NOREGEX
  76. X/*
  77. X * These routines are BSD regex(3)/ed(1) compatible regular-expression
  78. X * routines written by Ozan S. Yigit, Computer Science, York University.
  79. X * Parts of the code that are not needed by Prospero have been removed,
  80. X * but most of the accompanying information has been left intact. 
  81. X * This file is to be included on those operating systems that do not
  82. X * support re_comp and re_exec.
  83. X */
  84. X
  85. X/*
  86. X * regex - Regular expression pattern matching
  87. X *         and replacement
  88. X *
  89. X * by:  Ozan S. Yigit (oz@nexus.yorku.ca)
  90. X *    Dept. of Computing Services
  91. X *      York University
  92. X *
  93. X * These routines are the PUBLIC DOMAIN equivalents 
  94. X * of regex routines as found in 4.nBSD UN*X, with minor
  95. X * extensions.
  96. X *
  97. X * Modification history:
  98. X *
  99. X * $Log:    regex.c,v $
  100. X * Revision 1.3  89/04/01  14:18:09  oz
  101. X * Change all references to a dfa: this is actually an nfa.
  102. X * 
  103. X * Revision 1.2  88/08/28  15:36:04  oz
  104. X * Use a complement bitmap to represent NCL.
  105. X * This removes the need to have seperate 
  106. X * code in the pmatch case block - it is 
  107. X * just CCL code now.
  108. X * 
  109. X * Use the actual CCL code in the CLO
  110. X * section of pmatch. No need for a recursive
  111. X * pmatch call.
  112. X * 
  113. X * Use a bitmap table to set char bits in an
  114. X * 8-bit chunk.
  115. X * 
  116. X * Routines:
  117. X *      re_comp:        compile a regular expression into
  118. X *                      a NFA.
  119. X *
  120. X *            char *re_comp(s)
  121. X *            char *s;
  122. X *
  123. X *      re_exec:        execute the NFA to match a pattern.
  124. X *
  125. X *            int re_exec(s)
  126. X *            char *s;
  127. X *
  128. X * Regular Expressions:
  129. X *
  130. X *      [1]     char    matches itself, unless it is a special
  131. X *                      character (metachar): . \ [ ] * + ^ $
  132. X *
  133. X *      [2]     .       matches any character.
  134. X *
  135. X *      [3]     \       matches the character following it, except
  136. X *            when followed by a left or right round bracket,
  137. X *            a digit 1 to 9 or a left or right angle bracket. 
  138. X *            (see [7], [8] and [9])
  139. X *            It is used as an escape character for all 
  140. X *            other meta-characters, and itself. When used
  141. X *            in a set ([4]), it is treated as an ordinary
  142. X *            character.
  143. X *
  144. X *      [4]     [set]   matches one of the characters in the set.
  145. X *                      If the first character in the set is "^",
  146. X *                      it matches a character NOT in the set, i.e. 
  147. X *            complements the set. A shorthand S-E is 
  148. X *            used to specify a set of characters S upto 
  149. X *            E, inclusive. The special characters "]" and 
  150. X *            "-" have no special meaning if they appear 
  151. X *            as the first chars in the set.
  152. X *                      examples:        match:
  153. X *
  154. X *                              [a-z]    any lowercase alpha
  155. X *
  156. X *                              [^]-]    any char except ] and -
  157. X *
  158. X *                              [^A-Z]   any char except uppercase
  159. X *                                       alpha
  160. X *
  161. X *                              [a-zA-Z] any alpha
  162. X *
  163. X *      [5]     *       any regular expression form [1] to [4], followed by
  164. X *                      closure char (*) matches zero or more matches of
  165. X *                      that form.
  166. X *
  167. X *      [6]     +       same as [5], except it matches one or more.
  168. X *
  169. X *      [7]             a regular expression in the form [1] to [10], enclosed
  170. X *                      as \(form\) matches what form matches. The enclosure
  171. X *                      creates a set of tags, used for [8] and for
  172. X *                      pattern substution. The tagged forms are numbered
  173. X *            starting from 1.
  174. X *
  175. X *      [8]             a \ followed by a digit 1 to 9 matches whatever a
  176. X *                      previously tagged regular expression ([7]) matched.
  177. X *
  178. X *    [9]    \<    a regular expression starting with a \< construct
  179. X *        \>    and/or ending with a \> construct, restricts the
  180. X *            pattern matching to the beginning of a word, and/or
  181. X *            the end of a word. A word is defined to be a character
  182. X *            string beginning and/or ending with the characters
  183. X *            A-Z a-z 0-9 and _. It must also be preceded and/or
  184. X *            followed by any character outside those mentioned.
  185. X *
  186. X *      [10]            a composite regular expression xy where x and y
  187. X *                      are in the form [1] to [10] matches the longest
  188. X *                      match of x followed by a match for y.
  189. X *
  190. X *      [11]    ^    a regular expression starting with a ^ character
  191. X *        $    and/or ending with a $ character, restricts the
  192. X *                      pattern matching to the beginning of the line,
  193. X *                      or the end of line. [anchors] Elsewhere in the
  194. X *            pattern, ^ and $ are treated as ordinary characters.
  195. X *
  196. X *
  197. X * Acknowledgements:
  198. X *
  199. X *    HCR's Hugh Redelmeier has been most helpful in various
  200. X *    stages of development. He convinced me to include BOW
  201. X *    and EOW constructs, originally invented by Rob Pike at
  202. X *    the University of Toronto.
  203. X *
  204. X * References:
  205. X *              Software tools            Kernighan & Plauger
  206. X *              Software tools in Pascal        Kernighan & Plauger
  207. X *              Grep [rsx-11 C dist]            David Conroy
  208. X *        ed - text editor        Un*x Programmer's Manual
  209. X *        Advanced editing on Un*x    B. W. Kernighan
  210. X *        regexp routines            Henry Spencer
  211. X *
  212. X * Notes:
  213. X *
  214. X *    This implementation uses a bit-set representation for character
  215. X *    classes for speed and compactness. Each character is represented 
  216. X *    by one bit in a 128-bit block. Thus, CCL always takes a 
  217. X *    constant 16 bytes in the internal nfa, and re_exec does a single
  218. X *    bit comparison to locate the character in the set.
  219. X *
  220. X * Examples:
  221. X *
  222. X *    pattern:    foo*.*
  223. X *    compile:    CHR f CHR o CLO CHR o END CLO ANY END END
  224. X *    matches:    fo foo fooo foobar fobar foxx ...
  225. X *
  226. X *    pattern:    fo[ob]a[rz]    
  227. X *    compile:    CHR f CHR o CCL bitset CHR a CCL bitset END
  228. X *    matches:    fobar fooar fobaz fooaz
  229. X *
  230. X *    pattern:    foo\\+
  231. X *    compile:    CHR f CHR o CHR o CHR \ CLO CHR \ END END
  232. X *    matches:    foo\ foo\\ foo\\\  ...
  233. X *
  234. X *    pattern:    \(foo\)[1-3]\1    (same as foo[1-3]foo)
  235. X *    compile:    BOT 1 CHR f CHR o CHR o EOT 1 CCL bitset REF 1 END
  236. X *    matches:    foo1foo foo2foo foo3foo
  237. X *
  238. X *    pattern:    \(fo.*\)-\1
  239. X *    compile:    BOT 1 CHR f CHR o CLO ANY END EOT 1 CHR - REF 1 END
  240. X *    matches:    foo-foo fo-fo fob-fob foobar-foobar ...
  241. X * 
  242. X */
  243. X
  244. X#define MAXNFA  1024
  245. X#define MAXTAG  10
  246. X
  247. X#define OKP     1
  248. X#define NOP     0
  249. X
  250. X#define CHR     1
  251. X#define ANY     2
  252. X#define CCL     3
  253. X#define BOL     4
  254. X#define EOL     5
  255. X#define BOT     6
  256. X#define EOT     7
  257. X#define BOW    8
  258. X#define EOW    9
  259. X#define REF     10
  260. X#define CLO     11
  261. X
  262. X#define END     0
  263. X
  264. X/*
  265. X * The following defines are not meant
  266. X * to be changeable. They are for readability
  267. X * only.
  268. X *
  269. X */
  270. X#define MAXCHR    128
  271. X#define CHRBIT    8
  272. X#define BITBLK    MAXCHR/CHRBIT
  273. X#define BLKIND    0170
  274. X#define BITIND    07
  275. X
  276. X#define ASCIIB    0177
  277. X
  278. Xtypedef /*unsigned*/ char CHAR;
  279. X
  280. Xstatic int  tagstk[MAXTAG];             /* subpat tag stack..*/
  281. Xstatic CHAR nfa[MAXNFA];        /* automaton..       */
  282. Xstatic int  sta = NOP;                   /* status of lastpat */
  283. X
  284. Xstatic CHAR bittab[BITBLK];        /* bit table for CCL */
  285. X                    /* pre-set bits...   */
  286. Xstatic CHAR bitarr[] = {1,2,4,8,16,32,64,128};
  287. X
  288. Xstatic int internal_error;
  289. X
  290. Xstatic void
  291. Xchset(c)
  292. Xregister CHAR c;
  293. X{
  294. X    bittab[((c) & BLKIND) >> 3] |= bitarr[(c) & BITIND];
  295. X}
  296. X
  297. X#define badpat(x)    return (*nfa = END, x)
  298. X#define store(x)    *mp++ = x
  299. Xchar *     
  300. Xre_comp(pat)
  301. Xchar *pat;
  302. X{
  303. X    register char *p;               /* pattern pointer   */
  304. X    register CHAR *mp = nfa;        /* nfa pointer       */
  305. X    register CHAR *lp;              /* saved pointer..   */
  306. X    register CHAR *sp = nfa;        /* another one..     */
  307. X
  308. X    register int tagi = 0;          /* tag stack index   */
  309. X    register int tagc = 1;          /* actual tag count  */
  310. X
  311. X    register int n;
  312. X    register CHAR mask;        /* xor mask -CCL/NCL */
  313. X    int c1, c2;
  314. X        
  315. X    if (!pat || !*pat)
  316. X        if (sta)
  317. X            return 0;
  318. X        else
  319. X            badpat("No previous regular expression");
  320. X    sta = NOP;
  321. X
  322. X    for (p = pat; *p; p++) {
  323. X        lp = mp;
  324. X        switch(*p) {
  325. X
  326. X        case '.':               /* match any char..  */
  327. X            store(ANY);
  328. X            break;
  329. X
  330. X        case '^':               /* match beginning.. */
  331. X            if (p == pat)
  332. X                store(BOL);
  333. X            else {
  334. X                store(CHR);
  335. X                store(*p);
  336. X            }
  337. X            break;
  338. X
  339. X        case '$':               /* match endofline.. */
  340. X            if (!*(p+1))
  341. X                store(EOL);
  342. X            else {
  343. X                store(CHR);
  344. X                store(*p);
  345. X            }
  346. X            break;
  347. X
  348. X        case '[':               /* match char class..*/
  349. X            store(CCL);
  350. X
  351. X            if (*++p == '^') {
  352. X                mask = 0377;    
  353. X                p++;
  354. X            }
  355. X            else
  356. X                mask = 0;
  357. X
  358. X            if (*p == '-')        /* real dash */
  359. X                chset(*p++);
  360. X            if (*p == ']')        /* real brac */
  361. X                chset(*p++);
  362. X            while (*p && *p != ']') {
  363. X                if (*p == '-' && *(p+1) && *(p+1) != ']') {
  364. X                    p++;
  365. X                    c1 = *(p-2) + 1;
  366. X                    c2 = *p++;
  367. X                    while (c1 <= c2)
  368. X                        chset(c1++);
  369. X                }
  370. X#ifdef EXTEND
  371. X                else if (*p == '\\' && *(p+1)) {
  372. X                    p++;
  373. X                    chset(*p++);
  374. X                }
  375. X#endif
  376. X                else
  377. X                    chset(*p++);
  378. X            }
  379. X            if (!*p)
  380. X                badpat("Missing ]");
  381. X
  382. X            for (n = 0; n < BITBLK; bittab[n++] = (char) 0)
  383. X                store(mask ^ bittab[n]);
  384. X    
  385. X            break;
  386. X
  387. X        case '*':               /* match 0 or more.. */
  388. X        case '+':               /* match 1 or more.. */
  389. X            if (p == pat)
  390. X                badpat("Empty closure");
  391. X            lp = sp;        /* previous opcode */
  392. X            if (*lp == CLO)        /* equivalence..   */
  393. X                break;
  394. X            switch(*lp) {
  395. X
  396. X            case BOL:
  397. X            case BOT:
  398. X            case EOT:
  399. X            case BOW:
  400. X            case EOW:
  401. X            case REF:
  402. X                badpat("Illegal closure");
  403. X            default:
  404. X                break;
  405. X            }
  406. X
  407. X            if (*p == '+')
  408. X                for (sp = mp; lp < sp; lp++)
  409. X                    store(*lp);
  410. X
  411. X            store(END);
  412. X            store(END);
  413. X            sp = mp;
  414. X            while (--mp > lp)
  415. X                *mp = mp[-1];
  416. X            store(CLO);
  417. X            mp = sp;
  418. X            break;
  419. X
  420. X        case '\\':              /* tags, backrefs .. */
  421. X            switch(*++p) {
  422. X
  423. X            case '(':
  424. X                if (tagc < MAXTAG) {
  425. X                    tagstk[++tagi] = tagc;
  426. X                    store(BOT);
  427. X                    store(tagc++);
  428. X                }
  429. X                else
  430. X                    badpat("Too many \\(\\) pairs");
  431. X                break;
  432. X            case ')':
  433. X                if (*sp == BOT)
  434. X                    badpat("Null pattern inside \\(\\)");
  435. X                if (tagi > 0) {
  436. X                    store(EOT);
  437. X                    store(tagstk[tagi--]);
  438. X                }
  439. X                else
  440. X                    badpat("Unmatched \\)");
  441. X                break;
  442. X            case '<':
  443. X                store(BOW);
  444. X                break;
  445. X            case '>':
  446. X                if (*sp == BOW)
  447. X                    badpat("Null pattern inside \\<\\>");
  448. X                store(EOW);
  449. X                break;
  450. X            case '1':
  451. X            case '2':
  452. X            case '3':
  453. X            case '4':
  454. X            case '5':
  455. X            case '6':
  456. X            case '7':
  457. X            case '8':
  458. X            case '9':
  459. X                n = *p-'0';
  460. X                if (tagi > 0 && tagstk[tagi] == n)
  461. X                    badpat("Cyclical reference");
  462. X                if (tagc > n) {
  463. X                    store(REF);
  464. X                    store(n);
  465. X                }
  466. X                else
  467. X                    badpat("Undetermined reference");
  468. X                break;
  469. X#ifdef EXTEND
  470. X            case 'b':
  471. X                store(CHR);
  472. X                store('\b');
  473. X                break;
  474. X            case 'n':
  475. X                store(CHR);
  476. X                store('\n');
  477. X                break;
  478. X            case 'f':
  479. X                store(CHR);
  480. X                store('\f');
  481. X                break;
  482. X            case 'r':
  483. X                store(CHR);
  484. X                store('\r');
  485. X                break;
  486. X            case 't':
  487. X                store(CHR);
  488. X                store('\t');
  489. X                break;
  490. X#endif
  491. X            default:
  492. X                store(CHR);
  493. X                store(*p);
  494. X            }
  495. X            break;
  496. X
  497. X        default :               /* an ordinary char  */
  498. X            store(CHR);
  499. X            store(*p);
  500. X            break;
  501. X        }
  502. X        sp = lp;
  503. X    }
  504. X    if (tagi > 0)
  505. X        badpat("Unmatched \\(");
  506. X    store(END);
  507. X    sta = OKP;
  508. X    return 0;
  509. X}
  510. X
  511. X
  512. Xstatic char *bol;
  513. Xstatic char *bopat[MAXTAG];
  514. Xstatic char *eopat[MAXTAG];
  515. Xchar *pmatch();
  516. X
  517. X/*
  518. X * re_exec:
  519. X *     execute nfa to find a match.
  520. X *
  521. X *    special cases: (nfa[0])    
  522. X *        BOL
  523. X *            Match only once, starting from the
  524. X *            beginning.
  525. X *        CHR
  526. X *            First locate the character without
  527. X *            calling pmatch, and if found, call
  528. X *            pmatch for the remaining string.
  529. X *        END
  530. X *            re_comp failed, poor luser did not
  531. X *            check for it. Fail fast.
  532. X *
  533. X *    If a match is found, bopat[0] and eopat[0] are set
  534. X *    to the beginning and the end of the matched fragment,
  535. X *    respectively.
  536. X *
  537. X */
  538. X
  539. Xint
  540. Xre_exec(lp)
  541. Xregister char *lp;
  542. X{
  543. X    register char c;
  544. X    register char *ep = 0;
  545. X    register CHAR *ap = nfa;
  546. X
  547. X    bol = lp;
  548. X
  549. X    bopat[0] = 0;
  550. X    bopat[1] = 0;
  551. X    bopat[2] = 0;
  552. X    bopat[3] = 0;
  553. X    bopat[4] = 0;
  554. X    bopat[5] = 0;
  555. X    bopat[6] = 0;
  556. X    bopat[7] = 0;
  557. X    bopat[8] = 0;
  558. X    bopat[9] = 0;
  559. X
  560. X    switch(*ap) {
  561. X
  562. X    case BOL:            /* anchored: match from BOL only */
  563. X        ep = pmatch(lp,ap);
  564. X        break;
  565. X    case CHR:            /* ordinary char: locate it fast */
  566. X        c = *(ap+1);
  567. X        while (*lp && *lp != c)
  568. X            lp++;
  569. X        if (!*lp)        /* if EOS, fail, else fall thru. */
  570. X            return 0;
  571. X    default:            /* regular matching all the way. */
  572. X        while (*lp) {
  573. X            if ((ep = pmatch(lp,ap)))
  574. X                break;
  575. X            lp++;
  576. X        }
  577. X        break;
  578. X    case END:            /* munged automaton. fail always */
  579. X        return 0;
  580. X    }
  581. X    if (!ep)
  582. X        return 0;
  583. X
  584. X    if (internal_error)
  585. X        return -1;
  586. X
  587. X    bopat[0] = lp;
  588. X    eopat[0] = ep;
  589. X    return 1;
  590. X}
  591. X
  592. X/* 
  593. X * pmatch: 
  594. X *    internal routine for the hard part
  595. X *
  596. X *     This code is mostly snarfed from an early
  597. X *     grep written by David Conroy. The backref and
  598. X *     tag stuff, and various other mods are by oZ.
  599. X *
  600. X *    special cases: (nfa[n], nfa[n+1])
  601. X *        CLO ANY
  602. X *            We KNOW ".*" will match ANYTHING
  603. X *            upto the end of line. Thus, go to
  604. X *            the end of line straight, without
  605. X *            calling pmatch recursively. As in
  606. X *            the other closure cases, the remaining
  607. X *            pattern must be matched by moving
  608. X *            backwards on the string recursively,
  609. X *            to find a match for xy (x is ".*" and 
  610. X *            y is the remaining pattern) where
  611. X *            the match satisfies the LONGEST match
  612. X *            for x followed by a match for y.
  613. X *        CLO CHR
  614. X *            We can again scan the string forward
  615. X *            for the single char without recursion, 
  616. X *            and at the point of failure, we execute 
  617. X *            the remaining nfa recursively, as
  618. X *            described above.
  619. X *
  620. X *    At the end of a successful match, bopat[n] and eopat[n]
  621. X *    are set to the beginning and end of subpatterns matched
  622. X *    by tagged expressions (n = 1 to 9).    
  623. X *
  624. X */
  625. X
  626. X/*
  627. X * character classification table for word boundary
  628. X * operators BOW and EOW. the reason for not using 
  629. X * ctype macros is that we can let the user add into 
  630. X * our own table. see re_modw. This table is not in
  631. X * the bitset form, since we may wish to extend it
  632. X * in the future for other character classifications. 
  633. X *
  634. X *    TRUE for 0-9 A-Z a-z _
  635. X */
  636. Xstatic char chrtyp[MAXCHR] = {
  637. X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  638. X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  639. X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  640. X    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  641. X    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 
  642. X    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 
  643. X    0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 
  644. X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  645. X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  646. X    1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 
  647. X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  648. X    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  649. X    1, 1, 1, 0, 0, 0, 0, 0
  650. X    };
  651. X
  652. X#define inascii(x)    (0177&(x))
  653. X#define iswordc(x)     chrtyp[inascii(x)]
  654. X#define isinset(x,y)     ((x)[((y)&BLKIND)>>3] & bitarr[(y)&BITIND])
  655. X
  656. X/*
  657. X * skip values for CLO XXX to skip past the closure
  658. X *
  659. X */
  660. X
  661. X#define ANYSKIP    2     /* [CLO] ANY END ...         */
  662. X#define CHRSKIP    3    /* [CLO] CHR chr END ...     */
  663. X#define CCLSKIP 18    /* [CLO] CCL 16bytes END ... */
  664. X
  665. Xstatic char *
  666. Xpmatch(lp, ap)
  667. Xregister char *lp;
  668. Xregister CHAR *ap;
  669. X{
  670. X    register int op, c, n;
  671. X    register char *e;        /* extra pointer for CLO */
  672. X    register char *bp;        /* beginning of subpat.. */
  673. X    register char *ep;        /* ending of subpat..     */
  674. X    char *are;            /* to save the line ptr. */
  675. X
  676. X    while ((op = *ap++) != END)
  677. X        switch(op) {
  678. X
  679. X        case CHR:
  680. X            if (*lp++ != *ap++)
  681. X                return 0;
  682. X            break;
  683. X        case ANY:
  684. X            if (!*lp++)
  685. X                return 0;
  686. X            break;
  687. X        case CCL:
  688. X            c = *lp++;
  689. X            if (!isinset(ap,c))
  690. X                return 0;
  691. X            ap += BITBLK;
  692. X            break;
  693. X        case BOL:
  694. X            if (lp != bol)
  695. X                return 0;
  696. X            break;
  697. X        case EOL:
  698. X            if (*lp)
  699. X                return 0;
  700. X            break;
  701. X        case BOT:
  702. X            bopat[*ap++] = lp;
  703. X            break;
  704. X        case EOT:
  705. X            eopat[*ap++] = lp;
  706. X            break;
  707. X         case BOW:
  708. X            if (lp!=bol && iswordc(lp[-1]) || !iswordc(*lp))
  709. X                return 0;
  710. X            break;
  711. X        case EOW:
  712. X            if (lp==bol || !iswordc(lp[-1]) || iswordc(*lp))
  713. X                return 0;
  714. X            break;
  715. X        case REF:
  716. X            n = *ap++;
  717. X            bp = bopat[n];
  718. X            ep = eopat[n];
  719. X            while (bp < ep)
  720. X                if (*bp++ != *lp++)
  721. X                    return 0;
  722. X            break;
  723. X        case CLO:
  724. X            are = lp;
  725. X            switch(*ap) {
  726. X
  727. X            case ANY:
  728. X                while (*lp)
  729. X                    lp++;
  730. X                n = ANYSKIP;
  731. X                break;
  732. X            case CHR:
  733. X                c = *(ap+1);
  734. X                while (*lp && c == *lp)
  735. X                    lp++;
  736. X                n = CHRSKIP;
  737. X                break;
  738. X            case CCL:
  739. X                while ((c = *lp) && isinset(ap+1,c))
  740. X                    lp++;
  741. X                n = CCLSKIP;
  742. X                break;
  743. X            default:
  744. X                internal_error++;
  745. X                return 0;
  746. X            }
  747. X
  748. X            ap += n;
  749. X
  750. X            while (lp >= are) {
  751. X                if (e = pmatch(lp, ap))
  752. X                    return e;
  753. X                --lp;
  754. X            }
  755. X            return 0;
  756. X        default:
  757. X            internal_error++;
  758. X            return 0;
  759. X        }
  760. X    return lp;
  761. X}
  762. X#endif /* Need regex libraries? Compile to nothing if not.  */
  763. END_OF_FILE
  764.   if test 16057 -ne `wc -c <'./regex.c'`; then
  765.     echo shar: \"'./regex.c'\" unpacked with wrong size!
  766.   fi
  767.   # end of './regex.c'
  768. fi
  769. if test ! -d './vms' ; then
  770.     echo shar: Creating directory \"'./vms'\"
  771.     mkdir './vms'
  772. fi
  773. if test -f './vms_support.c' -a "${1}" != "-c" ; then 
  774.   echo shar: Will not clobber existing file \"'./vms_support.c'\"
  775. else
  776.   echo shar: Extracting \"'./vms_support.c'\" \(32780 characters\)
  777.   sed "s/^X//" >'./vms_support.c' <<'END_OF_FILE'
  778. X/* Emulation of 4.2 UNIX socket interface routines includes drivers for
  779. X   Wollongong, CMU-TEK, UCX tcp/ip interface and also emulates the SUN
  780. X   version of X.25 sockets.  The TWG will also work for MultiNet.  */
  781. X
  782. X/* This is from unixlib, by P.Kay@massey.ac.nz; wonderful implementation.
  783. X   You can get the real thing on 130.123.1.4 as unixlib_tar.z.  */
  784. X
  785. X#include <stdio.h>
  786. X#include <errno.h>
  787. X#include <ssdef.h>
  788. X#include <dvidef.h>
  789. X#include <signal.h>
  790. X#include <sys$library:msgdef.h>
  791. X#include <iodef.h>
  792. X#include <ctype.h>
  793. X#include <vms.h>
  794. X#include "[.vms]network.h"
  795. X
  796. X#define QIO_FAILED (st != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL)
  797. X#define QIO_ST_FAILED (st != SS$_NORMAL)
  798. X
  799. X/* Socket routine.  */
  800. Xint
  801. XVMSsocket (domain, type, protocol)
  802. X     int domain, type, protocol;
  803. X{
  804. X  struct descriptor inetdesc, x25desc, mbxdesc;
  805. X  int i, st, s, p_initialise ();
  806. X  long ucx_sock_def;
  807. X  char *getenv ();
  808. X
  809. X  if (!tcp_make)
  810. X    set_tcp_make ();
  811. X
  812. X  if (p_initialised == 0)
  813. X    {
  814. X      for (i = 0; i < 32; i++)
  815. X    p_initialise (i);
  816. X
  817. X      p_initialised = 1;
  818. X    }
  819. X
  820. X  /* First of all, get a file descriptor and file ptr we can associate with
  821. X     the socket, allocate a buffer, and remember the socket details.  */
  822. X  s = dup (0);
  823. X  if (s > 31)
  824. X    {
  825. X      errno = EMFILE;
  826. X      close (s);
  827. X      return -1;
  828. X    }
  829. X
  830. X  p[s].fptr = fdopen (s, "r");
  831. X  p[s].fd_buff = (unsigned char *) malloc (BUF_SIZE);
  832. X  p[s].domain = domain;
  833. X  p[s].type = type;
  834. X  p[s].protocol = protocol;
  835. X
  836. X  /* Handle the case of INET and X.25 separately.  */
  837. X  if (domain == AF_INET)
  838. X    {
  839. X      if (tcp_make == NONE)
  840. X    {
  841. X      printf ("Trying to obtain a TCP socket when we don't have TCP!\n");
  842. X      exit (1);
  843. X    }
  844. X      if (tcp_make == CMU)
  845. X    {
  846. X      /* For CMU we need only assign a channel.  */
  847. X      inetdesc.size = 3;
  848. X      inetdesc.ptr = "IP:";
  849. X      if (sys$assign (&inetdesc, &p[s].channel, 0, 0) != SS$_NORMAL)
  850. X        return -1;
  851. X    }
  852. X      else if (tcp_make == UCX)
  853. X    {
  854. X      /* For UCX assign channel and associate a socket with it.  */
  855. X      inetdesc.size = 3;
  856. X      inetdesc.ptr = "BG:";
  857. X      if (sys$assign (&inetdesc, &p[s].channel, 0, 0) != SS$_NORMAL)
  858. X        return -1;
  859. X
  860. X      ucx_sock_def = (domain << 24) + (type << 16) + protocol;
  861. X      st = sys$qiow (0, p[s].channel, IO$_SETMODE, p[s].iosb, 0, 0,
  862. X             &ucx_sock_def, 0, 0, 0, 0, 0);
  863. X      if (QIO_FAILED)
  864. X        return -1;
  865. X    }
  866. X      else
  867. X    {
  868. X      /* For TWG we assign the channel and associate a socket with it.  */
  869. X      inetdesc.size = 7;
  870. X      inetdesc.ptr = "_INET0:";
  871. X
  872. X      if (sys$assign (&inetdesc, &p[s].channel, 0, 0) != SS$_NORMAL)
  873. X        return -1;
  874. X
  875. X      st = sys$qiow (0, p[s].channel, IO$_SOCKET, p[s].iosb, 0, 0,
  876. X             domain, type, 0, 0, 0, 0);
  877. X      if (QIO_FAILED)
  878. X        return -1;
  879. X    }
  880. X    }
  881. X  else
  882. X    /* We don't handle any other domains yet.  */
  883. X    return -1;
  884. X
  885. X  /* For each case if we are successful we return the descriptor.  */
  886. X  return s;
  887. X}
  888. X
  889. X/* Bind routine.  */
  890. XVMSbind (s, name, namelen)
  891. X     int s;
  892. X     union socket_addr *name;
  893. X     int namelen;
  894. X{
  895. X  char infobuff[1024], lhost[32];
  896. X  int st;
  897. X
  898. X  if (!tcp_make)
  899. X    set_tcp_make ();
  900. X
  901. X  if (p[s].domain == AF_INET)
  902. X    {
  903. X      /* One main problem with bind is that if we're given a port number
  904. X     of 0, then we're expected to return a unique port number.  Since
  905. X     we don't KNOW, we return 1050+s and look to Lady Luck.  */
  906. X      if (tcp_make == CMU)
  907. X    {
  908. X      if (name->in.sin_port == 0 && p[s].type != SOCK_DGRAM)
  909. X        name->in.sin_port = 1050 + s;
  910. X      p[s].namelen = namelen;
  911. X      bcopy (name, &(p[s].name), namelen);
  912. X
  913. X      if (p[s].type == SOCK_DGRAM)
  914. X        {
  915. X          /* Another problem is that CMU still needs an OPEN request
  916. X         even if it's a datagram socket.  */
  917. X          st = sys$qiow (0, p[s].channel, TCP$OPEN, p[s].iosb,
  918. X                 0, 0, 0, 0, ntohs (p[s].name.in.sin_port),
  919. X                 0, 1, 0);
  920. X          if (QIO_ST_FAILED)
  921. X        return -1;
  922. X
  923. X          p[s].cmu_open = 1;
  924. X          sys$qiow (0, p[s].channel, TCP$INFO, p[s].iosb,
  925. X            0, 0, &infobuff, 1024, 0, 0, 0, 0);
  926. X          bcopy (infobuff + 264, &(p[s].name.in.sin_port), 2);
  927. X          p[s].name.in.sin_port = htons (p[s].name.in.sin_port);
  928. X
  929. X          /* So get it another way.  */
  930. X          bcopy (infobuff + 136, lhost, infobuff[1]);
  931. X          lhost[infobuff[1]] = '\0';
  932. X          sys$qiow (0, p[s].channel, GTHST, p[s].iosb,
  933. X            0, 0, &infobuff, 1024, 1, lhost, 0, 0);
  934. X          bcopy (infobuff + 4, &(p[s].name.in.sin_addr), 4);
  935. X
  936. X          /* Be prepared to receive a message.  */
  937. X          hang_a_read (s);
  938. X        }
  939. X    }
  940. X      else if (tcp_make == UCX)
  941. X    {
  942. X      /* UCX will select a prot for you.  If the port's number is 0,
  943. X         translate "name" into an item_2 list.  */
  944. X      struct itemlist lhost;
  945. X      lhost.length = namelen;
  946. X      lhost.code = 0;
  947. X      lhost.dataptr = (char *) name;
  948. X
  949. X      st = sys$qiow (0, p[s].channel, IO$_SETMODE, p[s].iosb, 0, 0,
  950. X             0, 0, &lhost, 0, 0, 0);
  951. X      if (QIO_FAILED)
  952. X        return -1;
  953. X
  954. X      if (p[s].type == SOCK_DGRAM)
  955. X        hang_a_read (s);
  956. X
  957. X    }
  958. X      else
  959. X    {
  960. X      /* WG is more straightforward */
  961. X      st = sys$qiow (0, p[s].channel, IO$_BIND, p[s].iosb,
  962. X             0, 0, name, namelen, 0, 0, 0, 0);
  963. X      if (QIO_FAILED)
  964. X        return -1;
  965. X
  966. X      /* If it's a datagram, get ready for the message.  */
  967. X      if (p[s].type == SOCK_DGRAM)
  968. X        hang_a_read (s);
  969. X    }
  970. X    }
  971. X  else
  972. X    /* We don't handle any other domain yet.  */
  973. X    return -1;
  974. X
  975. X  return 0;
  976. X}
  977. X
  978. X/* Connect routine.  */
  979. XVMSconnect (s, name, namelen)
  980. X     int s;
  981. X     union socket_addr *name;
  982. X     int namelen;
  983. X{
  984. X  int pr, fl, st;
  985. X  char *inet_ntoa ();
  986. X  static struct
  987. X  {
  988. X    int len;
  989. X    char name[128];
  990. X  } gethostbuf;
  991. X  extern int connect_ast ();
  992. X
  993. X  if (!tcp_make)
  994. X    set_tcp_make ();
  995. X
  996. X  /* For datagrams we need to remember who the name was so we can send all
  997. X     messages to that address without having to specify it all the time.  */
  998. X  if (p[s].connected)
  999. X    {
  1000. X      if (p[s].connected == 1)
  1001. X    errno = EISCONN;
  1002. X      else
  1003. X    {
  1004. X      errno = ECONNREFUSED;
  1005. X      p[s].connected = 0;
  1006. X    }
  1007. X      return -1;
  1008. X    }
  1009. X
  1010. X  if (p[s].connect_pending)
  1011. X    {
  1012. X      errno = EALREADY;
  1013. X      return -1;
  1014. X    }
  1015. X
  1016. X  p[s].passive = 0;
  1017. X  p[s].tolen = namelen;
  1018. X  bcopy (name, &(p[s].to), namelen);
  1019. X
  1020. X  if (p[s].domain == AF_INET)
  1021. X    {
  1022. X      if (tcp_make == CMU)
  1023. X    {
  1024. X
  1025. X      /* Get the info about the remote host  and open up a connection.  */
  1026. X      st = sys$qiow (0, p[s].channel, GTHST, p[s].iosb, 0, 0, &gethostbuf,
  1027. X             132, 2, name->in.sin_addr.s_addr, 0, 0);
  1028. X      if (QIO_FAILED)
  1029. X        {
  1030. X          strcpy (gethostbuf.name, inet_ntoa (name->in.sin_addr.s_addr));
  1031. X          gethostbuf.len = strlen (gethostbuf.name);
  1032. X        }
  1033. X      gethostbuf.name[gethostbuf.len] = 0;
  1034. X
  1035. X      /* TCP */
  1036. X      pr = 0;
  1037. X      /* Active */
  1038. X      fl = 1;
  1039. X
  1040. X      /* Nothing else for datagrams.  */
  1041. X      if (p[s].type == SOCK_DGRAM)
  1042. X        return (0);
  1043. X      st = sys$qio (s, p[s].channel, TCP$OPEN, p[s].iosb, connect_ast,
  1044. X            &p[s], &(gethostbuf.name), ntohs (name->in.sin_port),
  1045. X            ntohs (p[s].name.in.sin_port), fl, pr, 0);
  1046. X      if (QIO_ST_FAILED)
  1047. X        return -1;
  1048. X    }
  1049. X      else if (tcp_make == UCX)
  1050. X    {
  1051. X      /* Both UDP and TCP can use a connect - IO$_ACCESS */
  1052. X      p[s].rhost.length = namelen;
  1053. X      p[s].rhost.code = 0;
  1054. X      p[s].rhost.dataptr = (char *) name;
  1055. X
  1056. X      st = sys$qio (s, p[s].channel, IO$_ACCESS, p[s].iosb, connect_ast,
  1057. X            &p[s], 0, 0, &p[s].rhost, 0, 0, 0);
  1058. X      if (QIO_ST_FAILED)
  1059. X        return -1;
  1060. X    }
  1061. X      else
  1062. X    {
  1063. X      /* TWG */
  1064. X      if (p[s].type == SOCK_DGRAM)
  1065. X        return (0);
  1066. X      st = sys$qio (s, p[s].channel, IO$_CONNECT, p[s].iosb, connect_ast,
  1067. X            &p[s], name, namelen, 0, 0, 0, 0);
  1068. X      if (QIO_ST_FAILED)
  1069. X        return -1;
  1070. X    }
  1071. X    }
  1072. X  else
  1073. X    /* We don't handle any other domain yet.  */
  1074. X    return -1;
  1075. X
  1076. X  if (p[s].non_blocking)
  1077. X    {
  1078. X      if (p[s].connected)
  1079. X    {
  1080. X      if (p[s].connected == 1)
  1081. X        return 0;
  1082. X      else
  1083. X        {
  1084. X          p[s].connected = 0;
  1085. X          errno = ECONNREFUSED;
  1086. X          return -1;
  1087. X        }
  1088. X    }
  1089. X      else
  1090. X    {
  1091. X      p[s].connect_pending = 1;
  1092. X      errno = EINPROGRESS;
  1093. X      return -1;
  1094. X    }
  1095. X    }
  1096. X  else
  1097. X    {
  1098. X      /* wait for the connection to occur */
  1099. X      if (p[s].connected)
  1100. X    {
  1101. X      if (p[s].connected == 1)
  1102. X        return 0;
  1103. X      else
  1104. X        {
  1105. X          p[s].connected = 0;
  1106. X          errno = ECONNREFUSED;
  1107. X          return -1;
  1108. X        }
  1109. X    }
  1110. X
  1111. X      /* Timed out? */
  1112. X      if (wait_efn (s) == -1)
  1113. X    return -1;
  1114. X
  1115. X      if (p[s].connected != SS$_NORMAL)
  1116. X    {
  1117. X      errno = ECONNREFUSED;
  1118. X      return -1;
  1119. X    }
  1120. X
  1121. X      return 0;
  1122. X    }
  1123. X}
  1124. X
  1125. X/* Listen routine.  */
  1126. XVMSlisten (s, backlog)
  1127. X     int s;
  1128. X     int backlog;
  1129. X{
  1130. X  int st;
  1131. X
  1132. X  if (!tcp_make)
  1133. X    set_tcp_make ();
  1134. X
  1135. X  p[s].passive = 1;
  1136. X  p[s].backlog = backlog;
  1137. X  if (p[s].domain == AF_INET)
  1138. X    {
  1139. X      if (tcp_make == CMU)
  1140. X    {
  1141. X      /* For the CMU sockets we can't do the open call in listen;
  1142. X         we have to do it in hang_an_accept, because when we close
  1143. X         off the connection we have to be ready to accept another
  1144. X         one.  accept() also calls hang_an_accept on the old
  1145. X         descriptor.  */
  1146. X
  1147. X      /* Nothing */
  1148. X    }
  1149. X      else if (tcp_make == UCX)
  1150. X    {
  1151. X
  1152. X      /* Doc Verbage sez backlog is descriptor of byte.  Doc examples
  1153. X         and common sense say backlog is value.  Value doesn't work,
  1154. X         so let's try descriptor of byte after all.  */
  1155. X      struct descriptor bl;
  1156. X      unsigned char ucx_backlog;
  1157. X
  1158. X      ucx_backlog = (unsigned char) backlog;
  1159. X      bl.size = sizeof (ucx_backlog);
  1160. X      bl.ptr = (char *) &ucx_backlog;
  1161. X
  1162. X      st = sys$qiow (0, p[s].channel, IO$_SETMODE, p[s].iosb, 0, 0,
  1163. X             0, 0, 0, &bl, 0, 0);
  1164. X      if (QIO_FAILED)
  1165. X        return -1;
  1166. X    }
  1167. X      else
  1168. X    {
  1169. X      /* TWG */
  1170. X      st = sys$qiow (0, p[s].channel, IO$_LISTEN, p[s].iosb, 0, 0,
  1171. X             backlog, 0, 0, 0, 0, 0);
  1172. X      if (QIO_FAILED)
  1173. X        return -1;
  1174. X    }
  1175. X    }
  1176. X  else
  1177. X    /* We don't handle any other domain yet.  */
  1178. X    return -1;
  1179. X
  1180. X  p[s].status = LISTENING;
  1181. X  hang_an_accept (s);
  1182. X  return 0;
  1183. X}
  1184. X
  1185. X/* Accept routine.  */
  1186. Xint
  1187. XVMSaccept (s, addr, addrlen)
  1188. X     int s;
  1189. X     union socket_addr *addr;
  1190. X     int *addrlen;
  1191. X{
  1192. X  int news, st;
  1193. X  struct descriptor inetdesc;
  1194. X
  1195. X  if (!tcp_make)
  1196. X    set_tcp_make ();
  1197. X
  1198. X  if (p[s].non_blocking && !p[s].accept_pending)
  1199. X    {
  1200. X      errno = EWOULDBLOCK;
  1201. X      return -1;
  1202. X    }
  1203. X
  1204. X  /* hang_an_accept set up an incoming connection request so we have first
  1205. X     to hang around until one appears or we time out.  */
  1206. X  if (p[s].domain == AF_INET)
  1207. X    {
  1208. X      if (tcp_make == CMU)
  1209. X    {
  1210. X      char infobuff[1024];
  1211. X
  1212. X      /* Timed out?  */
  1213. X      if (wait_efn (s) == -1)
  1214. X        return -1;
  1215. X
  1216. X      /* Ok, get a new descriptor ...  */
  1217. X      news = dup (0);
  1218. X      if (news > 31)
  1219. X        {
  1220. X          errno = EMFILE;
  1221. X          close (news);
  1222. X          return -1;
  1223. X        }
  1224. X
  1225. X      /* ... and copy all of our data across.  */
  1226. X      bcopy (&p[s], &p[news], sizeof (p[0]));
  1227. X
  1228. X      /* But not this field, of course! */
  1229. X      p[news].s = news;
  1230. X
  1231. X      sys$qiow (0, p[news].channel, TCP$INFO, p[news].iosb,
  1232. X            0, 0, &infobuff, 1024, 0, 0, 0, 0);
  1233. X
  1234. X      /* Copy across the connection info if necessary.  */
  1235. X      if (addr != 0)
  1236. X        {
  1237. X          *addrlen = sizeof (struct sockaddr_in);
  1238. X          bcopy (infobuff + 132, &(addr->in.sin_port), 2);
  1239. X          addr->in.sin_port = htons (addr->in.sin_port);
  1240. X          addr->in.sin_family = AF_INET;
  1241. X          bcopy (infobuff + 272, &(addr->in.sin_addr), 4);
  1242. X          p[news].fromlen = *addrlen;
  1243. X          bcopy (addr, &(p[news].from), *addrlen);
  1244. X        }
  1245. X      p[news].status = PASSIVE_CONNECTION;
  1246. X
  1247. X      /* Get a new file ptr for the socket.  */
  1248. X      p[news].fptr = fdopen (news, "r");
  1249. X
  1250. X      /* Reset this field.  */
  1251. X      p[news].accept_pending = 0;
  1252. X
  1253. X      /* Allocate a buffer.  */
  1254. X      p[news].fd_buff = (unsigned char *) malloc (BUF_SIZE);
  1255. X      p[news].fd_leftover = 0;
  1256. X
  1257. X      /* Be prepared to get msgs.  */
  1258. X      hang_a_read (news);
  1259. X
  1260. X      /* Now fix up our previous socket so it's again listening
  1261. X         for connections.  */
  1262. X      inetdesc.size = 3;
  1263. X      inetdesc.ptr = "IP:";
  1264. X      if (sys$assign (&inetdesc, &p[s].channel, 0, 0) != SS$_NORMAL)
  1265. X        return -1;
  1266. X      p[s].status = LISTENING;
  1267. X      hang_an_accept (s);
  1268. X
  1269. X      /* Return the new socket descriptor.  */
  1270. X      return news;
  1271. X    }
  1272. X      else if (tcp_make == UCX)
  1273. X    {
  1274. X      /* UCX does the actual accept from hang_an_accept.  The accept info
  1275. X        is put into the data structure for the "listening" socket.
  1276. X        These just need to be copied into a newly allocated socket for
  1277. X        the connect and the listening socket re-started.  */
  1278. X
  1279. X      /* Wait for event flag from accept being received inside
  1280. X         of hang_an_accept().  */
  1281. X
  1282. X      if (wait_efn (s) == -1)
  1283. X        /* Timed out.  */
  1284. X        return -1;
  1285. X
  1286. X      /* Ok, get a new descriptor ...  */
  1287. X      news = dup (0);
  1288. X      if (news > 31)
  1289. X        {
  1290. X          errno = EMFILE;
  1291. X          close (news);
  1292. X          return -1;
  1293. X        }
  1294. X      /* ... and copy all of our data across.  */
  1295. X      bcopy (&p[s], &p[news], sizeof (p[0]));
  1296. X      p[news].s = news;    /* but not this field */
  1297. X      p[news].channel = p[s].ucx_accept_chan;
  1298. X
  1299. X      /* Initialize the remote host address item_list_3 struct.  */
  1300. X      p[news].rhost.length = sizeof (struct sockaddr_in);
  1301. X      p[news].rhost.code = 0;
  1302. X      p[news].rhost.dataptr = (char *) &p[news].from;
  1303. X      p[news].rhost.retlenptr = &p[news].fromdummy;
  1304. X
  1305. X      if (addr != 0)
  1306. X        {
  1307. X          /* Return the caller's info, if requested.  */
  1308. X          *addrlen = p[news].fromdummy;
  1309. X          bcopy (&p[news].from, addr, p[news].fromdummy);
  1310. X        }
  1311. X
  1312. X      /* Finish fleshing out the new structure.  */
  1313. X      p[news].status = PASSIVE_CONNECTION;
  1314. X
  1315. X      /* Get a new file pointer for the socket.  */
  1316. X      p[news].fptr = fdopen (news, "r");
  1317. X
  1318. X      /* Reset this field.  */
  1319. X      p[news].accept_pending = 0;
  1320. X
  1321. X      /* Allocate a buffer.  */
  1322. X      p[news].fd_buff = (unsigned char *) malloc (BUF_SIZE);
  1323. X      p[news].fd_leftover = 0;
  1324. X
  1325. X      /* Get it started reading.  */
  1326. X      hang_a_read (news);
  1327. X
  1328. X      p[s].status = LISTENING;
  1329. X      hang_an_accept (s);
  1330. X
  1331. X      return news;
  1332. X    }
  1333. X      else
  1334. X    {
  1335. X      /* TWG */
  1336. X      struct descriptor inetdesc;
  1337. X      int size;
  1338. X
  1339. X      /* Time out?  */
  1340. X      if (wait_efn (s) == -1)
  1341. X        return -1;
  1342. X
  1343. X      /* Ok, get a new descriptor ...  */
  1344. X      news = dup (0);
  1345. X      if (news > 31)
  1346. X        {
  1347. X          errno = EMFILE;
  1348. X          close (news);
  1349. X          return -1;
  1350. X        }
  1351. X
  1352. X      /* Assign a new channel.  */
  1353. X      inetdesc.size = 7;
  1354. X      inetdesc.ptr = "_INET0:";
  1355. X      st = sys$assign (&inetdesc, &p[news].channel, 0, 0);
  1356. X      if (QIO_ST_FAILED)
  1357. X        {
  1358. X          p[s].accept_pending = 0;
  1359. X          sys$clref (s);
  1360. X          return -1;
  1361. X        }
  1362. X
  1363. X      /* From info needs an int length field! */
  1364. X      size = sizeof (p[s].from) + 4;
  1365. X      st = sys$qiow (0, p[news].channel, IO$_ACCEPT, p[news].iosb, 0, 0,
  1366. X             &p[s].fromdummy, size, p[s].channel, 0, 0, 0);
  1367. X
  1368. X      if (QIO_ST_FAILED || p[news].iosb[0] != SS$_NORMAL)
  1369. X        {
  1370. X          p[s].accept_pending = 0;
  1371. X          sys$clref (s);
  1372. X          return -1;
  1373. X        }
  1374. X
  1375. X      if (addr != 0)
  1376. X        {
  1377. X          /* Return the caller's info if requested.  */
  1378. X          *addrlen = p[s].fromdummy;
  1379. X          bcopy (&p[s].from, addr, *addrlen);
  1380. X        }
  1381. X
  1382. X      /* Fix up our new data structure.  */
  1383. X      p[news].status = PASSIVE_CONNECTION;
  1384. X      p[news].domain = AF_INET;
  1385. X      p[news].passive = 1;
  1386. X      p[news].fptr = fdopen (news, "r");
  1387. X      /* Allocate a buffer.  */
  1388. X      p[news].fd_buff = (unsigned char *) malloc (BUF_SIZE);
  1389. X
  1390. X      /* Be prepared to accept msgs.  */
  1391. X      hang_a_read (news);
  1392. X
  1393. X      /* Get the old descriptor back onto accepting.  */
  1394. X      hang_an_accept (s);
  1395. X      return news;
  1396. X    }
  1397. X    }
  1398. X  else
  1399. X    /* We don't handle any other domain yet.  */
  1400. X    return -1;
  1401. X}
  1402. X
  1403. X/* Recv routine.  */
  1404. Xint
  1405. XVMSrecv (s, buf, len, flags)
  1406. X     int s;
  1407. X     char *buf;
  1408. X     int len, flags;
  1409. X{
  1410. X  return recvfrom (s, buf, len, flags, 0, 0);
  1411. X}
  1412. X
  1413. X/* Revfrom routine.  */
  1414. Xint
  1415. XVMSrecvfrom (s, buf, len, flags, from, fromlen)
  1416. X     int s;
  1417. X     char *buf;
  1418. X     int len, flags;
  1419. X     union socket_addr *from;
  1420. X     int *fromlen;
  1421. X{
  1422. X  int number;
  1423. X
  1424. X  if (!tcp_make)
  1425. X    set_tcp_make ();
  1426. X
  1427. X  if (p[s].domain != AF_INET && p[s].domain != AF_X25)
  1428. X    return -1;
  1429. X
  1430. X  /* If we're not onto datagrams, then it's possible that a previous
  1431. X     call to recvfrom didn't read all the data, and left some behind.
  1432. X     So first of all, look in our data buffer for any leftovers that
  1433. X     will satisfy this read.  */
  1434. X
  1435. X  /* We couldn't satisfy the request from previous calls so we must now
  1436. X     wait for a message to come through.  */
  1437. X  if (wait_efn (s) == -1)
  1438. X    /* Timed out.  */
  1439. X    return -1;
  1440. X
  1441. X  if (p[s].closed_by_remote == 1)
  1442. X    {
  1443. X      /* This could have happened! */
  1444. X      errno = ECONNRESET;
  1445. X      return -1;
  1446. X    }
  1447. X
  1448. X  if (from != NULL)
  1449. X    {
  1450. X      if (tcp_make == CMU)
  1451. X    {
  1452. X      if (p[s].type == SOCK_DGRAM)
  1453. X        {
  1454. X          /* Not documented but we get the from data from the beginning of
  1455. X         the data buffer.  */
  1456. X          *fromlen = sizeof (p[s].from.in);
  1457. X          from->in.sin_family = AF_INET;
  1458. X          bcopy (&p[s].fd_buff[8], &(from->in.sin_port), 2);
  1459. X          from->in.sin_port = htons (from->in.sin_port);
  1460. X          bcopy (&p[s].fd_buff[0], &(from->in.sin_addr), 4);
  1461. X
  1462. X          /* Remove the address data from front of data buffer.  */
  1463. X          bcopy (p[s].fd_buff + 12, p[s].fd_buff, p[s].fd_buff_size);
  1464. X        }
  1465. X      else
  1466. X        {
  1467. X          *fromlen = p[s].fromlen;
  1468. X          bcopy (&p[s].from, from, p[s].fromlen);
  1469. X        }
  1470. X    }
  1471. X      else if (tcp_make == UCX)
  1472. X    {
  1473. X      *fromlen = p[s].fromdummy;
  1474. X      bcopy (&p[s].from, from, p[s].fromdummy);
  1475. X    }
  1476. X      else
  1477. X    {
  1478. X      *fromlen = p[s].fromlen;
  1479. X      bcopy (&p[s].from, from, p[s].fromlen);
  1480. X    }
  1481. X    }
  1482. X
  1483. X  /* We may've received too much.  */
  1484. X  number = p[s].fd_buff_size;
  1485. X  if (number <= len)
  1486. X    {
  1487. X      /* If we haven't give back all the data available.  */
  1488. X      bcopy (p[s].fd_buff, buf, number);
  1489. X      p[s].fd_leftover = 0;
  1490. X      hang_a_read (s);
  1491. X      return (number);
  1492. X    }
  1493. X  else
  1494. X    {
  1495. X      /* If we have too much data then split it up.  */
  1496. X      p[s].fd_leftover = p[s].fd_buff;
  1497. X      bcopy (p[s].fd_leftover, buf, len);
  1498. X      /* And change the pointers.  */
  1499. X      p[s].fd_leftover += len;
  1500. X      p[s].fd_buff_size -= len;
  1501. X      return (len);
  1502. X    }
  1503. X}
  1504. X
  1505. X/* Send routine.  */
  1506. Xint
  1507. XVMSsend (s, msg, len, flags)
  1508. X     int s;
  1509. X     char *msg;
  1510. X     int len, flags;
  1511. X{
  1512. X  return sendto (s, msg, len, flags, 0, 0);
  1513. X}
  1514. X
  1515. X/* Sendto routine.  */
  1516. Xint
  1517. XVMSsendto (s, msg, len, flags, to, tolen)
  1518. X     int s;
  1519. X     unsigned char *msg;
  1520. X     int len, flags;
  1521. X     union socket_addr *to;
  1522. X     int tolen;
  1523. X{
  1524. X  int i, j, st, size;
  1525. X  unsigned char udpbuf[BUF_SIZE + 12];
  1526. X  char infobuff[1024], lhost[32];
  1527. X  unsigned short int temp;
  1528. X
  1529. X  if (!tcp_make)
  1530. X    set_tcp_make ();
  1531. X
  1532. X  /* First remember who we sent it to and set the value of size.  */
  1533. X  if (to != 0)
  1534. X    {
  1535. X      p[s].tolen = tolen;
  1536. X      bcopy (to, &(p[s].to), tolen);
  1537. X      size = tolen;
  1538. X    }
  1539. X  else
  1540. X    size = 0;
  1541. X
  1542. X  if (p[s].domain == AF_INET)
  1543. X    {
  1544. X      /* We might never have started a read for udp (socket/sendto) so
  1545. X     put one here.  */
  1546. X      if (p[s].type == SOCK_DGRAM)
  1547. X    hang_a_read (s);
  1548. X
  1549. X      if (tcp_make == CMU)
  1550. X    {
  1551. X      if (p[s].type == SOCK_DGRAM)
  1552. X        {
  1553. X          /* We might never have opened up a udp connection yet,
  1554. X         so check.  */
  1555. X          if (p[s].cmu_open != 1)
  1556. X        {
  1557. X          st = sys$qiow (0, p[s].channel, TCP$OPEN, p[s].iosb, 0, 0,
  1558. X                 0, 0, 0, 0, 1, 0);
  1559. X          if (QIO_ST_FAILED)
  1560. X            return -1;
  1561. X
  1562. X          p[s].cmu_open = 1;
  1563. X          sys$qiow (0, p[s].channel, TCP$INFO, p[s].iosb,
  1564. X                0, 0, &infobuff, 1024, 0, 0, 0, 0);
  1565. X          bcopy (infobuff + 264, &(p[s].name.in.sin_port), 2);
  1566. X          p[s].name.in.sin_port = htons (p[s].name.in.sin_port);
  1567. X          bcopy (infobuff + 136, lhost, infobuff[1]);
  1568. X          lhost[infobuff[1]] = '\0';
  1569. X          sys$qiow (0, p[s].channel, GTHST, p[s].iosb,
  1570. X                0, 0, &infobuff, 1024, 1, lhost, 0, 0);
  1571. X          bcopy (infobuff + 4, &(p[s].name.in.sin_addr), 4);
  1572. X        }
  1573. X
  1574. X          /* This isn't well documented.  To send to a UDP socket, we
  1575. X         need to put the address info at the beginning of the
  1576. X         buffer.  */
  1577. X          bcopy (msg, udpbuf + 12, len);
  1578. X          bcopy (&p[s].to.in.sin_addr, udpbuf + 4, 4);
  1579. X          temp = ntohs (p[s].to.in.sin_port);
  1580. X          bcopy (&temp, udpbuf + 10, 2);
  1581. X          bcopy (&p[s].name.in.sin_addr, udpbuf, 4);
  1582. X          temp = ntohs (p[s].name.in.sin_port);
  1583. X          bcopy (&temp, udpbuf + 8, 2);
  1584. X          temp = len + 12;
  1585. X          st = sys$qiow (0, p[s].channel, TCP$SEND, p[s].iosb, 0, 0,
  1586. X                 udpbuf, temp, 0, 0, 0, 0);
  1587. X          if (QIO_FAILED)
  1588. X        return -1;
  1589. X        }
  1590. X      else
  1591. X        {
  1592. X          /* TCP (! UDP)  */
  1593. X          st = sys$qiow (0, p[s].channel, TCP$SEND, p[s].iosb, 0, 0,
  1594. X                 msg, len, 0, 0, 0, 0);
  1595. X          if (QIO_FAILED)
  1596. X        return -1;
  1597. X        }
  1598. X      return len;
  1599. X    }
  1600. X      else if (tcp_make == UCX)
  1601. X    {
  1602. X      struct itemlist rhost;
  1603. X      rhost.length = sizeof (struct sockaddr_in);
  1604. X      rhost.code = 0;
  1605. X      rhost.dataptr = (char *) &p[s].to;
  1606. X
  1607. X      st = sys$qiow (0, p[s].channel, IO$_WRITEVBLK, p[s].iosb, 0, 0,
  1608. X             msg, len, &rhost, 0, 0, 0);
  1609. X      if (QIO_FAILED)
  1610. X        return -1;
  1611. X
  1612. X      return len;
  1613. X    }
  1614. X      else
  1615. X    {
  1616. X      /* TWG */
  1617. X      st = sys$qiow (0, p[s].channel, IO$_WRITEVBLK, p[s].iosb,
  1618. X             0, 0, msg, len, 0, &p[s].to, size, 0);
  1619. X      if (QIO_FAILED)
  1620. X        return -1;
  1621. X
  1622. X      return len;
  1623. X    }
  1624. X    }
  1625. X  else
  1626. X    /* We don't handle any other domain yet.  */
  1627. X    return -1;
  1628. X}
  1629. X
  1630. X/* Getsockname routine.  */
  1631. Xint
  1632. XVMSgetsockname (s, name, namelen)
  1633. X     int s;
  1634. X     union socket_addr *name;
  1635. X     int *namelen;
  1636. X{
  1637. X  int st;
  1638. X
  1639. X  if (!tcp_make)
  1640. X    set_tcp_make ();
  1641. X
  1642. X  if (p[s].domain == AF_INET)
  1643. X    {
  1644. X      if (tcp_make == CMU)
  1645. X    {
  1646. X      /* For CMU we just return values held in our data structure.  */
  1647. X      *namelen = p[s].namelen;
  1648. X      bcopy (&(p[s].name), name, *namelen);
  1649. X      return (0);
  1650. X    }
  1651. X      else if (tcp_make == UCX)
  1652. X    {
  1653. X      /* An item_list_3 descriptor.  */
  1654. X      struct itemlist lhost;
  1655. X
  1656. X      lhost.length = *namelen;
  1657. X      lhost.code = 0;
  1658. X      lhost.dataptr = (char *) name;
  1659. X
  1660. X      /* Fill in namelen with actual ret len value.  */
  1661. X      lhost.retlenptr = (short int *) namelen;
  1662. X
  1663. X      st = sys$qiow (0, p[s].channel, IO$_SENSEMODE, p[s].iosb, 0, 0,
  1664. X             0, 0, &lhost, 0, 0, 0);
  1665. X      if (QIO_FAILED)
  1666. X        return -1;
  1667. X
  1668. X      return 0;
  1669. X    }
  1670. X      else
  1671. X    {
  1672. X      /* TWG gives us the information. */
  1673. X      st = sys$qiow (0, p[s].channel, IO$_GETSOCKNAME, p[s].iosb,
  1674. X             0, 0, name, namelen, 0, 0, 0, 0);
  1675. X      if (QIO_FAILED)
  1676. X        return -1;
  1677. X
  1678. X      return 0;
  1679. X    }
  1680. X    }
  1681. X  else
  1682. X    /* We don't handle any other domain yet.  */
  1683. X    return -1;
  1684. X}
  1685. X
  1686. X/* Select routine.  */
  1687. Xint
  1688. XVMSselect (nfds, readfds, writefds, exceptfds, timeout)
  1689. X     int nfds;
  1690. X     fd_set *readfds, *writefds, *exceptfds;
  1691. X     struct timeval *timeout;
  1692. X{
  1693. X  int timer, fd, alarm_set, total, end;
  1694. X  long mask, cluster;
  1695. X  struct descriptor termdesc;
  1696. X  static fd_set new_readfds, new_writefds, new_exceptfds;
  1697. X
  1698. X  FD_ZERO (&new_readfds);
  1699. X  FD_ZERO (&new_writefds);
  1700. X  FD_ZERO (&new_exceptfds);
  1701. X  total = 0;
  1702. X
  1703. X  /* Assign a terminal channel if we haven't already.  */
  1704. X  if (terminal.chan == -1)
  1705. X    {
  1706. X      termdesc.size = 10;
  1707. X      termdesc.ptr = "SYS$INPUT:";
  1708. X      sys$assign (&termdesc, &terminal.chan, 0, 0);
  1709. X    }
  1710. X  alarm_set = 0;
  1711. X  if (timeout != NULL)
  1712. X    {
  1713. X      /* If a timeout is given then set the alarm.  */
  1714. X      end = timeout->tv_sec;
  1715. X      if (timer != 0)
  1716. X    {
  1717. X      /* We need to reset the alarm if it didn't fire, but we set it.  */
  1718. X      alarm_set = 1;
  1719. X      si_alarm (end);
  1720. X    }
  1721. X    }
  1722. X  else
  1723. X    end = 1;
  1724. X
  1725. X  do
  1726. X    {
  1727. X      if (exceptfds)
  1728. X    {
  1729. X       /* Nothing */ ;
  1730. X    }
  1731. X
  1732. X      if (writefds)
  1733. X    {
  1734. X      for (fd = 0; fd < nfds; fd++)
  1735. X        if (FD_ISSET (fd, writefds))
  1736. X          {
  1737. X        if (p[fd].connect_pending)
  1738. X           /* Nothing */ ;
  1739. X        else if ((p[fd].status == ACTIVE_CONNECTION)
  1740. X             || (p[fd].status == PASSIVE_CONNECTION))
  1741. X          {
  1742. X            FD_SET (fd, &new_writefds);
  1743. X            total++;
  1744. X          }
  1745. X          }
  1746. X    }
  1747. X
  1748. X      if (readfds)
  1749. X    {
  1750. X      /* True if data pending or an accept.  */
  1751. X      for (fd = 3; fd < nfds; fd++)
  1752. X        if (FD_ISSET (fd, readfds) &&
  1753. X        ((p[fd].fd_buff_size != -1) || (p[fd].accept_pending == 1)))
  1754. X          {
  1755. X        FD_SET (fd, &new_readfds);
  1756. X        total++;
  1757. X          }
  1758. X    }
  1759. X
  1760. X      if (total || (end == 0))
  1761. X    break;
  1762. X
  1763. X      /* Otherwise, wait on an event flag.  It's possible that the wait can
  1764. X     be stopped by a spurious event flag being set -- i.e. one that's
  1765. X     got a status not normal.  So we've got to be prepared to loop
  1766. X     around the wait until a valid reason happens.  */
  1767. X
  1768. X      /* Set up the wait mask.  */
  1769. X      cluster = 0;
  1770. X      mask = 0;
  1771. X      for (fd = 3; fd < nfds; fd++)
  1772. X    {
  1773. X      sys$clref (fd);
  1774. X      if (readfds)
  1775. X        if FD_ISSET
  1776. X          (fd, readfds) mask |= (1 << fd);
  1777. X      if (writefds)
  1778. X        if FD_ISSET
  1779. X          (fd, writefds) mask |= (1 << fd);
  1780. X      if (exceptfds)
  1781. X        if FD_ISSET
  1782. X          (fd, exceptfds) mask |= (1 << fd);
  1783. X    }
  1784. X
  1785. X      mask |= (1 << TIMER_EFN);
  1786. X
  1787. X      /* Clear it off just in case.  */
  1788. X      sys$clref (TIMER_EFN);
  1789. X
  1790. X      /* Wait around.  */
  1791. X      sys$wflor (cluster, mask);
  1792. X
  1793. X      mask = 0;
  1794. X      if (read_efn (TIMER_EFN))
  1795. X    {
  1796. X      errno = EINTR;
  1797. X      break;
  1798. X    }
  1799. X  } while (1);
  1800. X  /*NOTREACHED*/
  1801. X
  1802. X  /* Unset the alarm if we set it.  */
  1803. X  if (alarm_set == 1)
  1804. X    alarm (0);
  1805. X
  1806. X  if (readfds)
  1807. X    *readfds = new_readfds;
  1808. X
  1809. X  if (writefds)
  1810. X    *writefds = new_writefds;
  1811. X
  1812. X  if (exceptfds)
  1813. X    *exceptfds = new_exceptfds;
  1814. X
  1815. X  return total;
  1816. X}
  1817. X
  1818. X/* Shutdown routine.  */
  1819. XVMSshutdown (s, how)
  1820. X     int s, how;
  1821. X{
  1822. X  int st;
  1823. X  int ucx_how;
  1824. X
  1825. X  if (!tcp_make)
  1826. X    set_tcp_make ();
  1827. X
  1828. X  if (p[s].domain == AF_INET)
  1829. X    {
  1830. X      if (tcp_make == CMU)
  1831. X    {
  1832. X      /* For CMU we just close off.  */
  1833. X      si_close (s);
  1834. X      return 0;
  1835. X    }
  1836. X      else if (tcp_make == UCX)
  1837. X    {
  1838. X      st = sys$qiow (0, p[s].channel, IO$_DEACCESS | IO$M_SHUTDOWN,
  1839. X             p[s].iosb, 0, 0, 0, 0, 0, how, 0, 0);
  1840. X      if (QIO_FAILED)
  1841. X        return -1;
  1842. X
  1843. X      return 0;
  1844. X    }
  1845. X      else
  1846. X    {
  1847. X      /* TWG lets us do it.  */
  1848. X      st = sys$qiow (0, p[s].channel, IO$_SHUTDOWN, p[s].iosb, 0, 0, how,
  1849. X             0, 0, 0, 0, 0);
  1850. X      if (QIO_FAILED)
  1851. X        return -1;
  1852. X
  1853. X      return 0;
  1854. X    }
  1855. X    }
  1856. X  else                /* it wasn't a socket */
  1857. X    return -1;
  1858. X}
  1859. X
  1860. X/*   */
  1861. X
  1862. X/* The following routines are used by the above socket calls.  */
  1863. X
  1864. X/* hang_a_read sets up a read to be finished at some later time.  */
  1865. Xhang_a_read (s)
  1866. X     int s;
  1867. X{
  1868. X  extern int read_ast ();
  1869. X  int size, st;
  1870. X
  1871. X  /* Don't bother if we already did it.  */
  1872. X  if (p[s].read_outstanding == 1)
  1873. X    return;
  1874. X
  1875. X  /* Have a read outstanding.  */
  1876. X  p[s].read_outstanding = 1;
  1877. X  size = sizeof (p[s].from) + 4;
  1878. X  sys$clref (s);
  1879. X
  1880. X  /* Clear off the event flag just in case, and reset the buf size.  */
  1881. X  p[s].fd_buff_size = -1;
  1882. X  if (p[s].domain == AF_INET)
  1883. X    {
  1884. X      if (tcp_make == CMU)
  1885. X    {
  1886. X      st = sys$qio (s, p[s].channel, TCP$RECEIVE, p[s].iosb, read_ast,
  1887. X            &p[s], p[s].fd_buff, BUF_SIZE, 0, 0, 0, 0);
  1888. X      if (QIO_ST_FAILED)
  1889. X        return -1;
  1890. X    }
  1891. X      else if (tcp_make == UCX)
  1892. X    {
  1893. X
  1894. X      p[s].rhost.length = sizeof (struct sockaddr_in);
  1895. X      p[s].rhost.code = 0;
  1896. X      p[s].rhost.dataptr = (char *) &p[s].from;
  1897. X      p[s].rhost.retlenptr = &p[s].fromdummy;
  1898. X
  1899. X      st = sys$qio (s, p[s].channel, IO$_READVBLK, p[s].iosb, read_ast,
  1900. X            &p[s], p[s].fd_buff, BUF_SIZE, &p[s].rhost, 0, 0, 0);
  1901. X      if (QIO_ST_FAILED)
  1902. X        return -1;
  1903. X    }
  1904. X      else
  1905. X    {
  1906. X      /* TWG */
  1907. X      st = sys$qio (s, p[s].channel, IO$_READVBLK, p[s].iosb, read_ast,
  1908. X            &p[s], p[s].fd_buff, BUF_SIZE, 0, &p[s].fromlen,
  1909. X            size, 0);
  1910. X      if (QIO_ST_FAILED)
  1911. X        return -1;
  1912. X    }
  1913. X    }
  1914. X  else
  1915. X    /* We don't handle any other domain yet.  */
  1916. X    return -1;
  1917. X}
  1918. X
  1919. X/* hang_an_accept waits for a connection request to come in.  */
  1920. Xhang_an_accept (s)
  1921. X     int s;
  1922. X{
  1923. X  extern int accept_ast ();
  1924. X  int st;
  1925. X
  1926. X  /* Clear the event flag just in case.  */
  1927. X  sys$clref (s);
  1928. X
  1929. X  /* Reset our flag & buf size.  */
  1930. X  p[s].accept_pending = 0;
  1931. X  p[s].fd_buff_size = -1;
  1932. X  if (p[s].domain == AF_INET)
  1933. X    {
  1934. X      if (tcp_make == CMU)
  1935. X    {
  1936. X      st = sys$qio (s, p[s].channel, TCP$OPEN, p[s].iosb, accept_ast,
  1937. X            &p[s], 0, 0, ntohs (p[s].name.in.sin_port), 0, 0, 0);
  1938. X      if (QIO_ST_FAILED)
  1939. X        return -1;
  1940. X    }
  1941. X      else if (tcp_make == UCX)
  1942. X    {
  1943. X      struct descriptor inetdesc;
  1944. X
  1945. X      /* Assign channel for actual connection off listener.  */
  1946. X      inetdesc.size = 3;
  1947. X      inetdesc.ptr = "BG:";
  1948. X      if (sys$assign (&inetdesc, &p[s].ucx_accept_chan, 0,
  1949. X              0) != SS$_NORMAL)
  1950. X        return -1;
  1951. X
  1952. X      /* UCX's accept returns remote host info and the channel for a new
  1953. X         socket to perform reads/writes on, so a sys$assign isn't
  1954. X         really necessary.  */
  1955. X      p[s].rhost.length = sizeof (struct sockaddr_in);
  1956. X      p[s].rhost.dataptr = (char *) &p[s].from;
  1957. X      p[s].fromdummy = 0;
  1958. X      p[s].rhost.retlenptr = &p[s].fromdummy;
  1959. X
  1960. X      st = sys$qio (s, p[s].channel, IO$_ACCESS | IO$M_ACCEPT, p[s].iosb,
  1961. X            accept_ast, &p[s], 0, 0, &p[s].rhost,
  1962. X            &p[s].ucx_accept_chan, 0, 0);
  1963. X      if (QIO_ST_FAILED)
  1964. X        return -1;
  1965. X    }
  1966. X      else
  1967. X    {
  1968. X      st = sys$qio (s, p[s].channel, IO$_ACCEPT_WAIT, p[s].iosb,
  1969. X            accept_ast, &p[s], 0, 0, 0, 0, 0, 0);
  1970. X      if (QIO_ST_FAILED)
  1971. X        return -1;
  1972. X    }
  1973. X    }
  1974. X  else
  1975. X    /* We don't handle any other domain yet.  */
  1976. X    return -1;
  1977. X}
  1978. X
  1979. X/* wait_efn just sets up a wait on either an event or the timer.  */
  1980. Xwait_efn (s)
  1981. X     int s;
  1982. X{
  1983. X  long mask, cluster;
  1984. X
  1985. X  cluster = 0;
  1986. X  sys$clref (TIMER_EFN);
  1987. X  mask = (1 << s) | (1 << TIMER_EFN);
  1988. X  sys$wflor (cluster, mask);
  1989. X
  1990. X  if (read_efn (TIMER_EFN))
  1991. X    {
  1992. X      errno = EINTR;
  1993. X      return -1;
  1994. X    }
  1995. X
  1996. X  return 0;
  1997. X}
  1998. X
  1999. X/* read_ast is called by the system whenever a read is done.  */
  2000. Xread_ast (p)
  2001. X     struct fd_entry *p;
  2002. X{
  2003. X  int i, j;
  2004. X  unsigned char *v, *w;
  2005. X
  2006. X  /* Reset the outstanding flag.  */
  2007. X  p->read_outstanding = 0;
  2008. X  if (p->iosb[0] == SS$_NORMAL)
  2009. X    {
  2010. X      /* Check no errors.  */
  2011. X      p->fd_buff_size = p->iosb[1];
  2012. X      if (tcp_make == CMU)
  2013. X    {
  2014. X      /* fiddle for DGRMs */
  2015. X      if (p->type == SOCK_DGRAM)
  2016. X        p->fd_buff_size -= 12;
  2017. X    }
  2018. X      if (p->sig_req == 1)
  2019. X    gsignal (SIGIO);
  2020. X    }
  2021. X  else if (p->iosb[0] == SS$_CLEARED)
  2022. X    p->closed_by_remote = 1;
  2023. X  else if (tcp_make == UCX)
  2024. X    {
  2025. X      if (p->iosb[0] == SS$_LINKDISCON)
  2026. X    p->closed_by_remote = 1;
  2027. X    }
  2028. X}
  2029. X
  2030. X/* accept_ast is called whenever an incoming call is detected.  */
  2031. Xaccept_ast (p)
  2032. X     struct fd_entry *p;
  2033. X{
  2034. X  if (p->iosb[0] == SS$_NORMAL)
  2035. X    p->accept_pending = 1;
  2036. X  else
  2037. X    /* If it failed set up another listen.  */
  2038. X    listen (p->s, p[p->s].backlog);
  2039. X}
  2040. X
  2041. X/* connect_ast is called whenever an async connect is made.  */
  2042. Xconnect_ast (p)
  2043. X     struct fd_entry *p;
  2044. X{
  2045. X  p->connect_pending = 0;
  2046. X  if ((p->connected = p->iosb[0]) == SS$_NORMAL)
  2047. X    {
  2048. X      /* We made the connection.  */
  2049. X      p->status = ACTIVE_CONNECTION;
  2050. X
  2051. X      /* Be prepared to accept a msg.  */
  2052. X      hang_a_read (p->s);
  2053. X    }
  2054. X}
  2055. X
  2056. X/*   */
  2057. X/* These routines handle stream I/O.  */
  2058. X
  2059. X/* si_close -- must close off any connection in progress.  */
  2060. Xsi_close (s)
  2061. X     int s;
  2062. X{
  2063. X  if (!tcp_make)
  2064. X    set_tcp_make ();
  2065. X
  2066. X  if ((s < 0) || (s > 31))
  2067. X    return -1;
  2068. X
  2069. X  if (p[s].channel != 0)
  2070. X    {
  2071. X      /* Was it one of our descriptors? */
  2072. X      if (p[s].domain == AF_INET)
  2073. X    {
  2074. X      if (tcp_make == CMU)
  2075. X        sys$qiow (0, p[s].channel, TCP$CLOSE, p[s].iosb,
  2076. X              0, 0, 0, 0, 0, 0, 0, 0);
  2077. X      if (p[s].status != HANDED_OFF)
  2078. X        sys$dassgn (p[s].channel);
  2079. X      close (s);
  2080. X      free (p[s].fd_buff);
  2081. X      p_initialise (s);
  2082. X    }
  2083. X      return 0;
  2084. X    }
  2085. X  else
  2086. X    {
  2087. X      /* Re-initialise data structure just in case.  */
  2088. X      p[s].fd_buff_size = -1;
  2089. X      p[s].accept_pending = 0;
  2090. X      p[s].status = INITIALISED;
  2091. X      return close (s);
  2092. X    }
  2093. X}
  2094. X
  2095. X/* si_alarm -- insert a call to our own alarm function.  */
  2096. Xsi_alarm (i)
  2097. X     int i;
  2098. X{
  2099. X  extern int pre_alarm ();
  2100. X
  2101. X  /* Make the call to pre_alarm instead of what the user wants;
  2102. X     pre_alarm will call his routine when it finishes.  */
  2103. X  /* VAX needs this call each time! */
  2104. X  signal (SIGALRM, pre_alarm);
  2105. X  alarm (i);
  2106. X}
  2107. X
  2108. X/* pre_alarm -- gets called first on an alarm signal.  */
  2109. Xpre_alarm ()
  2110. X{
  2111. X  /* Come here first so we can set our timer event flag.  */
  2112. X  sys$setef (TIMER_EFN);
  2113. X  (*alarm_function) ();
  2114. X}
  2115. X
  2116. X/* p_initialise - initialise our data array.  */
  2117. Xp_initialise (s)
  2118. X     int s;
  2119. X{
  2120. X  int j;
  2121. X  for (j = 0; j < 4; j++)
  2122. X    p[s].iosb[j] = 0;
  2123. X  p[s].channel = 0;
  2124. X  p[s].fd_buff_size = -1;
  2125. X  p[s].accept_pending = 0;
  2126. X  p[s].connect_pending = 0;
  2127. X  p[s].connected = 0;
  2128. X  p[s].fd_buff = NULL;
  2129. X  p[s].fd_leftover = NULL;
  2130. X  p[s].fptr = NULL;
  2131. X  p[s].s = s;
  2132. X  p[s].name.in.sin_port = 0;
  2133. X  p[s].masklen = 4;
  2134. X  for (j = 0; j < 16; j++)
  2135. X    p[s].mask[j] = 0xff;
  2136. X  p[s].need_header = 0;
  2137. X  p[s].status = INITIALISED;
  2138. X  p[s].read_outstanding = 0;
  2139. X  p[s].cmu_open = 0;
  2140. X  p[s].x25_listener = 0;
  2141. X  p[s].mother = s;
  2142. X  p[s].child = 0;
  2143. X  p[s].no_more_accepts = 0;
  2144. X  p[s].closed_by_remote = 0;
  2145. X  p[s].non_blocking = 0;
  2146. X  p[s].sig_req = 0;
  2147. X  sys$clref (s);
  2148. X}
  2149. X
  2150. X/* read_efn -- see whether an event flag is set.  */
  2151. Xread_efn (i)
  2152. X     int i;
  2153. X{
  2154. X  int j;
  2155. X  sys$readef (i, &j);
  2156. X  j &= (1 << i);
  2157. X
  2158. X  return j;
  2159. X}
  2160. X
  2161. Xstatic
  2162. Xset_tcp_make ()
  2163. X{
  2164. X  struct descriptor inetdesc;
  2165. X  int channel;
  2166. X  /* first try CMU */
  2167. X  inetdesc.size = 3;
  2168. X  inetdesc.ptr = "IP:";
  2169. X  if (sys$assign (&inetdesc, &channel, 0, 0) == SS$_NORMAL)
  2170. X    {
  2171. X      sys$dassgn (channel);
  2172. X      tcp_make = CMU;
  2173. X      return;
  2174. X    }
  2175. X
  2176. X  /* next try TWG */
  2177. X  inetdesc.size = 7;
  2178. X  inetdesc.ptr = "_INET0:";
  2179. X  if (sys$assign (&inetdesc, &channel, 0, 0) == SS$_NORMAL)
  2180. X    {
  2181. X      sys$dassgn (channel);
  2182. X      tcp_make = WG;
  2183. X      return;
  2184. X    }
  2185. X
  2186. X  /* next try UCX */
  2187. X  inetdesc.size = 4;
  2188. X  inetdesc.ptr = "BG0:";
  2189. X  if (sys$assign (&inetdesc, &channel, 0, 0) == SS$_NORMAL)
  2190. X    {
  2191. X      sys$dassgn (channel);
  2192. X      tcp_make = UCX;
  2193. X      return;
  2194. X    }
  2195. X
  2196. X  /* nothing there oh dear!*/
  2197. X  tcp_make = NONE;
  2198. X  return;
  2199. X}
  2200. X
  2201. Xstatic char *
  2202. Xgetdevicename (channel)
  2203. X     unsigned short int channel;
  2204. X{
  2205. X  int st;
  2206. X  struct
  2207. X  {
  2208. X    struct itemlist id;
  2209. X    int eol;
  2210. X  } itmlst;
  2211. X  static char name[64];
  2212. X  short int lgth;
  2213. X
  2214. X  name[0] = '\0';
  2215. X  itmlst.id.code = DVI$_DEVNAM;
  2216. X  itmlst.id.length = 64;
  2217. X  itmlst.id.dataptr = name;
  2218. X  itmlst.id.retlenptr = &lgth;
  2219. X  itmlst.eol = 0;
  2220. X  st = sys$getdvi (0, channel, 0, &itmlst, 0, 0, 0, 0);
  2221. X  if (QIO_ST_FAILED)
  2222. X    fprintf (stderr, "error getting device name %d\n", st);
  2223. X
  2224. X  return (name);
  2225. X}
  2226. END_OF_FILE
  2227.   if test 32780 -ne `wc -c <'./vms_support.c'`; then
  2228.     echo shar: \"'./vms_support.c'\" unpacked with wrong size!
  2229.   fi
  2230.   # end of './vms_support.c'
  2231. fi
  2232. echo shar: End of archive 1 \(of 5\).
  2233. cp /dev/null ark1isdone
  2234. MISSING=""
  2235. for I in 1 2 3 4 5 ; do
  2236.     if test ! -f ark${I}isdone ; then
  2237.     MISSING="${MISSING} ${I}"
  2238.     fi
  2239. done
  2240. if test "${MISSING}" = "" ; then
  2241.     echo You have unpacked all 5 archives.
  2242.     rm -f ark[1-9]isdone
  2243. else
  2244.     echo You still must unpack the following archives:
  2245.     echo "        " ${MISSING}
  2246. fi
  2247. exit 0
  2248. exit 0 # Just in case...
  2249.