home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #19 / NN_1992_19.iso / spool / vmsnet / sources / 349 < prev    next >
Encoding:
Internet Message Format  |  1992-09-03  |  47.3 KB

  1. Path: sparky!uunet!usc!news.service.uci.edu!unogate!mvb.saic.com!vmsnet-sources
  2. From: mahan@tgv.com (Patrick L. Mahan - TGV Window Washer)
  3. Newsgroups: vmsnet.sources
  4. Subject: XSCOPE/VMS 1.0, part 02/08
  5. Message-ID: <8045405@MVB.SAIC.COM>
  6. Date: Fri, 04 Sep 1992 05:34:15 GMT
  7. Reply-To: mahan@tgv.com
  8. Organization: TGV Incorporated (Tech Support) in Santa Cruz, CA
  9. Lines: 1745
  10. Approved: Mark.Berryman@Mvb.Saic.Com
  11.  
  12. Submitted-by: mahan@tgv.com (Patrick L. Mahan - TGV Window Washer)
  13. Posting-number: Volume 3, Issue 154
  14. Archive-name: xscope/part02
  15.  
  16.  
  17. -+-+-+-+-+-+-+-+ START OF PART 2 -+-+-+-+-+-+-+-+
  18. X    `09if ((!caddr) `7C`7C (!*caddr)) return 0;
  19. X    `09if (strchr(caddr, '.')) return 0;
  20. X    `09for ( a = caddr; *a; a++)
  21. X    `09`09if((*a < '0') `7C`7C (*a > '9')) return 0;
  22. X    `09if (a == caddr) return 0;
  23. X#ifdef DNDEBUG
  24. X    `09fprintf(stderr, "isEtherAddr: %s is an ethernet address\n",caddr);
  25. X#endif
  26. X    `09return 1;
  27. X    `09`09
  28. X`7D
  29. X
  30. X`0C
  31. X/*
  32. X * isDnetAddr
  33. X * Boolean routine to determine if a passed client node name
  34. X * is a valid DECnet address.
  35. X */
  36. Xint
  37. XisDnetAddr (caddr)
  38. X    `09char *caddr;
  39. X`7B
  40. X    `09if (strchr(caddr, '.')) return 1;
  41. X    `09return 0;
  42. X`7D
  43. X
  44. X`0C
  45. X/*
  46. X * issueNetCmdRead
  47. X * Reading from the Network Command Mailbox willbe done on the mbxChannel, b
  48. Vut
  49. X * will be treated as a read in the NET: channel, since it is the channel th
  50. Vat the
  51. X * upper layer sees.
  52. X */
  53. Xint
  54. XissueNetCmdRead (chan)
  55. X`09unsigned short chan;
  56. X`7B
  57. X    `09int status;
  58. X
  59. X    `09if (!ChanTableInfo`5B(mbxChannel>>4)`5D->readAstPend)
  60. X    `09`7B
  61. X#ifdef DNDEBUG
  62. X    `09`09fprintf(stderr, "issueNetCmdRead: read pending on channel %d from
  63. V chan %d\n", mbxChannel, chan);
  64. X#endif
  65. X    `09`09ChanTableInfo`5B(mbxChannel>>4)`5D->readAstPend = 1;
  66. X        `09status = SYS$QIO (0, mbxChannel, IO$_READVBLK, &netiosb, &netCmdA
  67. Vst, NET_CMD,
  68. X                                &nb, mbxMsgLen, 0, 0, 0, 0);
  69. X    `09`09if (VMSFAIL(status)) LIB$SIGNAL(status);
  70. X    `09`7D
  71. X    `09return status;
  72. X`7D
  73. X
  74. X`0C
  75. X/*
  76. X * issueRead (chan)
  77. X * Routine to setup a read AST on the passed channel.  In our emulation
  78. X * we must check the channel's buffers to see if any remaining data is left
  79. X * to be read.  In the case that there is some remainder, the routine will`2
  80. V0
  81. X * "fake" an AST event by shoving interrupt information in the stack.  Other
  82. Vwise
  83. X * the routine sets up the AST normally with the buffer being the base of th
  84. Ve`20
  85. X * vm area setup.
  86. X */
  87. Xint
  88. XissueRead (chan)
  89. X`09unsigned short chan;
  90. X`7B
  91. X`09astParam ap;
  92. X`09int shiftChan = chan>>4;
  93. X`09char *vmbase = ChanTableInfo`5BshiftChan`5D->base;
  94. X`09char *vmdelta = ChanTableInfo`5BshiftChan`5D->delta;
  95. X`09int vmlen = ChanTableInfo`5BshiftChan`5D->len;
  96. X`09int remainder = (vmbase + vmlen) - vmdelta;
  97. X    `09int status;
  98. X/*`20
  99. X * Insert a fake result in the stack if there is unread data in our channel'
  100. Vs buffer.`20
  101. X * Then return without setting up the read attention AST QIO.
  102. X */
  103. X`09if (remainder > 0)
  104. X`09`7B
  105. X`09`09stack`5BstackIndex`5D.channel = chan;
  106. X`09`09stack`5BstackIndex`5D.type = NET_RD;
  107. X`09`09stackIndex++;
  108. X`09`09ChanTableInfo`5B(chan>>4)`5D->readAstPend = 0;
  109. X`09`09ChanTableInfo`5B(chan>>4)`5D->readAstDone = 1;
  110. X#ifdef DNDEBUG
  111. X`09`09fprintf(stderr, "issueRead: (puesdoread) to channel %d remainder %d\n"
  112. V, chan, remainder);
  113. X#endif
  114. X`09`09return SS$_NORMAL;
  115. X`09`7D
  116. X        ChanTableInfo`5BshiftChan`5D->base = vmbase;
  117. X        ChanTableInfo`5BshiftChan`5D->delta = vmdelta = vmbase;
  118. X        ChanTableInfo`5BshiftChan`5D->len = vmlen = 0;
  119. X
  120. X`09ap.ast.type = NET_RD;
  121. X`09ap.ast.chan = chan;
  122. X
  123. X#ifdef DNDEBUG
  124. X    `09fprintf(stderr, "issueRead: read pending on channel %d\n", chan);
  125. X#endif
  126. X`09ChanTableInfo`5BshiftChan`5D->readAstDone = 0;
  127. X`09ChanTableInfo`5BshiftChan`5D->readAstPend = 1;
  128. X        status = SYS$QIO (0, chan, IO$_READVBLK, &ChanTableInfo`5BshiftChan`
  129. V5D->read_iosb,`20
  130. X`09`09`09&readAst, ap.astid, vmbase, MAX_QIO, 0, 0, 0, 0);
  131. X    `09if (VMSFAIL(status)) LIB$SIGNAL(status);
  132. X`7D
  133. X
  134. X`0C
  135. X/*
  136. X * linkInit
  137. X * Routine to intercept the network message and parse it into a node name.
  138. X */
  139. Xvoid
  140. XlinkInit ()
  141. X`7B
  142. X`09int i = nb.mbxMsg`5B0`5D + 1;
  143. X`09int start = i + 1;
  144. X
  145. X`09info_cnt = nb.mbxMsg`5Bi`5D;
  146. X`09ncb = &nb.mbxMsg`5Bstart`5D;
  147. X`7D
  148. X
  149. X`0C
  150. X/*
  151. X * linkTerm
  152. X * Routine to terminate a link (low level - socket_close is high level) give
  153. Vn
  154. X * a channel spec or the network message block's unit number.
  155. X */
  156. Xvoid
  157. XlinkTerm(sChan)
  158. X`09unsigned short sChan;
  159. X`7B
  160. X`09int status;
  161. X`09unsigned short channel;
  162. X`09unsigned short next;
  163. X`09int currChannel;
  164. X`09int i;
  165. X
  166. X    `09next = 0;
  167. X`09if (sChan)
  168. X    `09`7B
  169. X    `09`09if (!ChanTableInfo`5BsChan`5D) return;
  170. X    `09`09if (((sChan<<4) == netChannel) && (lisChannel)) netChannel = lisCh
  171. Vannel;
  172. X        `09if (ChanTableInfo`5BsChan`5D->chanDassgn) return;
  173. X`09`09next = sChan;
  174. X`09`09goto bash;
  175. X`09`7D
  176. X`09for (i = 0; i < (FD_SETSIZE/NFDBITS); i++)
  177. X`09`7B
  178. X`09`09currChannel = (int) allChannels->bits`5Bi`5D;
  179. X`09`09while (currChannel)
  180. X`09`09`7B
  181. X`09`09`09next = (ffs(currChannel) - 1) + (i * NFDBITS);
  182. X`09`09`09if (ChanTableInfo`5Bnext`5D->unit == nb.unit) goto bash;
  183. X`09`09`09currChannel &= `7E(1 << next);
  184. X`09`09`7D
  185. X`09`7D
  186. Xbash:
  187. X`09if ((!next) `7C`7C (next > FD_SETSIZE))
  188. X    `09`09return;
  189. X`09else
  190. X`09`7B
  191. X`09`09channel = next<<4;
  192. X#ifdef DNDEBUG
  193. X`09`09fprintf(stderr, "linkTerm: terminating link to %d\n",channel);
  194. X#endif
  195. X`09`09status = SYS$DASSGN (channel);
  196. X`09`09if (VMSFAIL(status)) LIB$SIGNAL(status);
  197. X        `09ChanTableInfo`5Bnext`5D->chanDassgn = 1;
  198. X`09`7D
  199. X`7D
  200. X
  201. X`0C
  202. X/*
  203. X * nameFromPort
  204. X * A hack to translate the passed port number to a DECnet OBJECT name. Its u
  205. Vgly
  206. X * but hey, who asked you?
  207. X */
  208. Xstruct dsc$descriptor
  209. X*nameFromPort (sa)
  210. X`09struct sockaddr *sa;
  211. X`7B
  212. X`09union
  213. X`09`7B
  214. X`09`09unsigned short port;
  215. X`09`09char t`5B2`5D;
  216. X`09`7D temp;
  217. X    `09int i = 0;
  218. X
  219. X`09temp.t`5B0`5D = sa->sa_data`5B1`5D;
  220. X`09temp.t`5B1`5D = sa->sa_data`5B0`5D;
  221. X    `09for (i = 0; i < Number(transTable); i++)
  222. X    `09`7B
  223. X    `09`09if (transTable`5Bi`5D.port == temp.port)
  224. X    `09`09`7B
  225. X    `09`09`09if (transTable`5Bi`5D.port = X11_PORT)
  226. X`09`09`09`09x11_dsc.dsc$a_pointer`5B3`5D = 0x30;
  227. X    `09`09`09return transTable`5Bi`5D.object;
  228. X        `09`7D
  229. X    `09`7D
  230. X/*
  231. X * Of course - the obligatory special case: used when someone tries to`20
  232. X * access a X11 "reserved" port 6001-9 (beyond 6009, I don't care!)
  233. X */
  234. X`09if ((temp.port > X11_PORT) && (temp.port < X11_PORT + 10))
  235. X`09`7B
  236. X`09`09x11_dsc.dsc$a_pointer`5B3`5D = ((temp.port - X11_PORT) + 0x30);
  237. X`09`09return &x11_dsc;
  238. X`09`7D`20
  239. X`09fprintf (stderr, "nameFromPort: unrecognized port request: %d\n");
  240. X`09return NULL;
  241. X`7D
  242. X
  243. X`0C
  244. X/*
  245. X * NCPpredicate
  246. X * Routine that is passed to qsort.
  247. X */
  248. Xstatic int
  249. XNCPpredicate (c1, c2)
  250. X    `09NCPstruct *c1;
  251. X    `09NCPstruct *c2;
  252. X`7B
  253. X    `09return (memcmp (c1->nodebuf, c2->nodebuf, MAX(strlen(c1->nodebuf), st
  254. Vrlen(c2->nodebuf))));
  255. X`7D
  256. X
  257. X`0C
  258. X/*
  259. X * NCPinit()
  260. X * Routine to load the NCP table of node/addresses from its data base using
  261. V the Network
  262. X * File Block (NFB$) defined constants for node and address matching of the
  263. V on-line`20
  264. X * data base.
  265. X */
  266. Xint
  267. XNCPinit()
  268. X`7B
  269. X    `09int`09i;
  270. X    `09int`09j;
  271. X    `09int`09add;
  272. X    `09int`09retLen = 0;
  273. X    `09int`09status;
  274. X    `09int`09seg = MAXDNETNODES + 1;
  275. X`09unsigned short netNCPChan;
  276. X    `09struct io_stat_blk iosb;
  277. X    `09char `09*delta;
  278. X    `09struct nfbdef nfb = `7B NFB$C_FC_SHOW, 0, NFB$C_DB_NDI, NFB$C_OP_EQL,
  279. X    `09`09`09      NFB$C_WILDCARD, NFB$C_WILDCARD, 0, 0, 0,
  280. X    `09`09`09      NFB$C_NDI_NNA, NFB$C_NDI_TAD, NFB$C_ENDOFLIST `7D;
  281. X    `09struct dsc$descriptor nfbDes = `7Bsizeof(nfb), 0, 0, &nfb`7D;
  282. X    `09char *keyArea = DNETALLOC(NFB$C_CTX_SIZE);
  283. X    `09struct dsc$descriptor kaDes = `7BNFB$C_CTX_SIZE, 0, 0, keyArea`7D;
  284. X    `09char *bufArea = DNETALLOC(BUF_QUO);
  285. X    `09struct dsc$descriptor bufDes = `7BBUF_QUO, 0, 0, bufArea`7D;
  286. X    `09struct nfbdef1 *prm;
  287. X    `09struct nfbdef2 *val;
  288. X
  289. X    `09i = 0;
  290. X/*
  291. X * Assign a temporary channel to _NET: to return NCP db info
  292. X */
  293. X`09status = SYS$ASSIGN (&net_device, &netNCPChan, 0, 0);
  294. X`09if (VMSFAIL(status)) LIB$SIGNAL(status);
  295. X    `09LIB$MOVC5 (&zero, NULL, "\0", &kaDes, keyArea);
  296. X        status = SYS$QIOW (0, netChannel, IO$_ACPCONTROL, &iosb, 0, 0,`20
  297. X    `09`09&nfbDes, &kaDes, &retLen, &bufDes, 0, 0);
  298. X    `09if (!VMSFAIL(status)) status = iosb.status;
  299. X    `09if ((VMSFAIL(status)) && (status != SS$_ENDOFFILE)) LIB$SIGNAL(status
  300. V);
  301. X/*
  302. X * Main loop for calling ACPCONTROL on the _NET: device, returning database
  303. V information.
  304. X */
  305. X    `09while (status != SS$_ENDOFFILE)
  306. X    `09`7B
  307. X        `09delta = bufArea;
  308. X    `09`09if (seg > MAXDNETNODES)`09`09/* add memory in puesdo realloc mode
  309. V */
  310. X    `09`09`7B
  311. X    `09`09`09NCPstruct *tmp = (NCPstruct *)`20
  312. X    `09`09`09`09DNETALLOC((i+MAXDNETNODES)*sizeof(NCPstruct));
  313. X    `09`09`09if(!tmp) exit(SS$_INSFMEM);
  314. X    `09`09`09if (pNCP)
  315. X    `09`09`09`7B
  316. X   `09`09`09`09bcopy ((char *) pNCP, (char *) tmp, sizeof(NCPstruct) * i);
  317. X   `09`09`09`09DNETFREE(pNCP);
  318. X    `09`09`09`7D
  319. X   `09`09`09pNCP = tmp;
  320. X    `09`09`09seg = 0;
  321. X    `09`09`7D
  322. X/*
  323. X * Loop through the NFB records that the NETACP passed back to this routine.
  324. X */
  325. X    `09`09for (j = 0; nfb.fldid`5Bj`5D != NFB$C_ENDOFLIST; ++j)
  326. X    `09`09`7B
  327. X    `09`09`09add = 0;
  328. X    `09`09`09prm = (struct nfbdef1 *) &nfb.fldid`5Bj`5D;
  329. X    `09`09`09val = (struct nfbdef2 *) delta;
  330. X    `09`09`09switch (prm->overlay.fields.typ)
  331. X    `09`09`09`7B
  332. X    `09`09`09case NFB$C_TYP_BIT:
  333. X    `09`09`09case NFB$C_TYP_LNG:
  334. X`09`09`09`09pNCP`5Bi`5D.area = (short) (val->overlay.lngValue / 1024);
  335. X`09`09`09`09pNCP`5Bi`5D.node = (short) (val->overlay.lngValue % 1024);
  336. X    `09`09`09`09add = sizeof(long);
  337. X    `09`09`09`09break;
  338. X    `09`09`09case NFB$C_TYP_STR:
  339. X    `09`09    `09`09pNCP`5Bi`5D.nodebuf = DNETALLOC (NODNAMSIZ);
  340. X    `09`09`09`09bcopy (&val->overlay.string.strText, pNCP`5Bi`5D.nodebuf,
  341. X    `09`09`09`09`09val->overlay.string.strCount);
  342. X    `09`09`09`09pNCP`5Bi`5D.nodebuf`5Bval->overlay.string.strCount`5D = 0x0;
  343. X    `09`09`09`09add = val->overlay.string.strCount + sizeof(short);
  344. X    `09`09`09`09break;
  345. X    `09`09`09default:
  346. X    `09`09`09`09fprintf(stderr, "NCPinit: unrecognized %d\n",val->overlay.ln
  347. VgValue);
  348. X    `09`09`09`09add = sizeof(long);
  349. X    `09`09`09`7D
  350. X    `09`09`09delta += add;
  351. X    `09`09`7D
  352. X#ifdef NCPDEBUG
  353. X       `09`09fprintf(stderr, "NCPinit: %d.%d: %s\n",pNCP`5Bi`5D.area, pNCP`5
  354. VBi`5D.node, pNCP`5Bi`5D.nodebuf);
  355. X#endif /* NCPDEBUG */
  356. X    `09`09i++;
  357. X    `09`09seg++;
  358. X        `09status = SYS$QIOW (0, netNCPChan, IO$_ACPCONTROL, &iosb, 0, 0,`20
  359. X    `09`09`09&nfbDes, &kaDes, &retLen, &bufDes, 0, 0);
  360. X    `09`09if (!VMSFAIL(status)) status = iosb.status;
  361. X    `09`09if ((VMSFAIL(status)) && (status != SS$_ENDOFFILE)) LIB$SIGNAL(sta
  362. Vtus);
  363. X`09`7D
  364. X/*
  365. X * Hopefully we have some nodes here to sort...
  366. X */
  367. X    `09if (i)
  368. X    `09`7B
  369. X    `09`09NCPtot = i;
  370. X    `09`09qsort ((char *) pNCP, NCPtot, sizeof(NCPstruct), NCPpredicate);
  371. X    `09`09SYS$DASSGN (netNCPChan);
  372. X#ifdef NCPDEBUG
  373. X    `09`09fprintf(stderr, "NCPinit: %d nodes found\n", NCPtot);
  374. X#endif
  375. X    `09`7D
  376. X    `09else
  377. X    `09`09fprintf(stderr, "NCPinit: no nodes found!\n");
  378. X`7D
  379. X
  380. X`0C
  381. X/*
  382. X * NCPfind
  383. X * Ah, the luscious jewel of the Nile, itself!  This baby looks up a given n
  384. Vode id
  385. X * in the NCP table (built in NCPinit()).  The id can be in one of three for
  386. Vms:
  387. X * 1) DECnet Node Name - Phase IV has a max of 6 characters
  388. X * 2) DECnet Node Address - up to the max of 63.1023
  389. X * 3) Unknown Node Address - this sucker comes from the active ethernet addr
  390. Vess.
  391. X *    It is composed of all numbers (illegal for a node name spec).  The rtn
  392. V can
  393. X *    translate this address to become a DECnet Node Address type above.  Th
  394. Ve fact
  395. X *    that a node comes in as a hybrid active ethernet address name portends
  396. V that
  397. X *    the node is not known by NCP.
  398. X * The routine returns a binary value of the address in the sockaddr passed
  399. V area and
  400. X * the resolved node name/address in "client".
  401. X */
  402. Xint
  403. XNCPfind (sChan, psock, client)
  404. X    `09unsigned short sChan;
  405. X    `09char`09*psock;
  406. X    `09char `09*client;
  407. X`7B
  408. X    `09int `09status;
  409. X    `09int `09i;
  410. X    `09short `09node;
  411. X    `09short`09area;
  412. X    `09int`09result;
  413. X    `09int`09last;
  414. X    `09int`09strt;
  415. X    `09char `09*b1;
  416. X    `09char `09*b2;
  417. X    `09char `09*aoff;
  418. X    `09static NCPstruct dum = `7BNULL, 0, 0`7D;
  419. X    `09NCPstruct *pNCPf;
  420. X    `09struct sht
  421. X    `09`7B
  422. X    `09`09union
  423. X    `09`09`7B
  424. X    `09`09`09struct chs
  425. X    `09`09`09`7B
  426. X    `09`09`09`09char c1;
  427. X    `09`09`09`09char c2;
  428. X    `09`09`09`7Dc;
  429. X    `09`09`09short s1;
  430. X    `09`09`7Do;
  431. X    `09`7Ds;
  432. X
  433. X    `09if (!pNCP) NCPinit();
  434. X    `09if (sChan)
  435. X    `09`7B
  436. X    `09`09aoff = (char *) (psock + sizeof(long));
  437. X    `09`09if (ChanTableInfo`5BsChan`5D)
  438. X    `09`09`7B
  439. X    `09`09`09if (ChanTableInfo`5BsChan`5D->node + ChanTableInfo`5BsChan`5D->
  440. Varea)
  441. X    `09`09`09`7B
  442. X        `09`09`09if (ChanTableInfo`5BsChan`5D->nodename)
  443. X    `09`09`09`09`7B
  444. X   `09`09     `09`09`09bcopy (ChanTableInfo`5BsChan`5D->nodename, client,`20
  445. X    `09`09`09`09`09`09strlen(ChanTableInfo`5BsChan`5D->nodename)+1);
  446. X    `09`09`09`09`09client`5Bstrlen(ChanTableInfo`5BsChan`5D->nodename)`5D =
  447. V 0x0;
  448. X    `09`09`09`09`7D
  449. X   `09 `09`09`09else
  450. X   `09 `09`09`09`09sprintf (client, "%d.%d", ChanTableInfo`5BsChan`5D->area,
  451. V`20
  452. X    `09`09`09`09`09`09ChanTableInfo`5Bi`5D->node);
  453. X        `09`09`09bcopy ((char *) &ChanTableInfo`5BsChan`5D->area, aoff, size
  454. Vof(short));
  455. X   `09 `09`09`09bcopy ((char *) &ChanTableInfo`5BsChan`5D->node,`20
  456. X    `09`09`09`09`09(char *) (aoff + sizeof(short)), sizeof(short));
  457. X    `09`09`09`09return 0;
  458. X    `09        `09`7D
  459. X        `09`7D
  460. X    `09`7D
  461. X    `09else
  462. X    `09`09aoff = psock;
  463. X    `09if ((!client) `7C`7C (!*client)) fprintf(stderr, "NCPaddr: error no c
  464. Vlient spec in call\n");
  465. X`09upper(client);
  466. X    `09if (strchr(client, ':')) *((char *) strchr(client, ':')) = '\0';
  467. X    `09if (isEtherAddr(client)) `09/* it's an active ethernet hybrid address
  468. V */
  469. X    `09`7B
  470. X    `09`09result = atoi(client);
  471. X    `09`09DNETFREE(client);
  472. X    `09`09client = DNETALLOC(NODNAMSIZ);
  473. X    `09`09sprintf(client, "%d.%d", result/1024, result % 1024);
  474. X    `09`7D
  475. X    `09if (isDnetAddr(client)) `09/* it's a DECnet address (eg., "1.22") */
  476. X    `09`7B
  477. X    `09`09b1 = client;
  478. X    `09`09b2 = strchr (client, '.');
  479. X    `09`09*b2++ = 0x0;
  480. X    `09`09area = (short) atoi(b1);
  481. X    `09`09node = (short) atoi(b2);
  482. X`09`09sprintf (client, "%d.%d", area, node);
  483. X    `09`09for (i = 0; i < NCPtot; i++)
  484. X    `09`09`7B
  485. X    `09`09`09if ((pNCP`5Bi`5D.area == area) && (pNCP`5Bi`5D.node == node)) b
  486. Vreak;
  487. X        `09`7D
  488. X    `09`7D
  489. X    `09else `09`09`09`09/* it's a node name (eg., "NCD999") */
  490. X    `09`7B
  491. X    `09`09dum.nodebuf = client;
  492. X    `09`09i = -1;
  493. X    `09`09if((pNCPf = (NCPstruct *) bsearch (&dum, pNCP, NCPtot,`20
  494. X    `09`09`09sizeof(NCPstruct), NCPpredicate)))
  495. X    `09`09`09i = (pNCPf - pNCP);
  496. X    `09`7D
  497. X/*
  498. X * We should now have either a valid index into the NCP table or a indicatio
  499. Vn that
  500. X * the node name/address is not currently known by this host node.
  501. X */
  502. X`09if ((i > -1) && (i < NCPtot))
  503. X    `09`7B
  504. X    `09`09if (pNCP`5Bi`5D.nodebuf)
  505. X        `09`09bcopy (pNCP`5Bi`5D.nodebuf, client, strlen(pNCP`5Bi`5D.nodebuf
  506. V)+1);
  507. X    `09`09else
  508. X    `09`09`09sprintf (client, "%d.%d", pNCP`5Bi`5D.area, pNCP`5Bi`5D.node);
  509. X    `09`09bcopy ((char *) &pNCP`5Bi`5D.area, aoff, sizeof(short));
  510. X    `09`09bcopy ((char *) &pNCP`5Bi`5D.node, (char *) (aoff + sizeof(short))
  511. V, sizeof(short));
  512. X    `09`09if (sChan && ChanTableInfo`5BsChan`5D)
  513. X    `09`09`7B
  514. X    `09`09`09if (!ChanTableInfo`5BsChan`5D->nodename)`20
  515. X    `09`09`09`09ChanTableInfo`5BsChan`5D->nodename = DNETALLOC(NODNAMSIZ);
  516. X    `09`09`09bcopy (client, ChanTableInfo`5BsChan`5D->nodename, strlen(clien
  517. Vt) + 1);
  518. X    `09`09`09ChanTableInfo`5BsChan`5D->nodename`5Bstrlen(client)`5D = 0x0;
  519. X    `09`09`09ChanTableInfo`5BsChan`5D->node = pNCP`5Bi`5D.node;
  520. X    `09`09`09ChanTableInfo`5BsChan`5D->area = pNCP`5Bi`5D.area;
  521. X    `09`09`7D
  522. X    `09`09return 0;
  523. X    `09`7D
  524. X    `09else
  525. X    `09`7B
  526. X    `09`09fprintf(stderr, "NCPfind: %s not found in node lookup\n",client);
  527. X    `09`09return -1;
  528. X    `09`7D
  529. X`7D
  530. X
  531. X`0C
  532. X/*
  533. X * netCmdAst
  534. X * AST routine the fires for incoming network messages.
  535. X */
  536. Xvoid
  537. XnetCmdAst (type)
  538. X`09int type;
  539. X`7B
  540. X`09int i;
  541. X`09int start;
  542. X
  543. X    `09ChanTableInfo`5B(mbxChannel>>4)`5D->readAstPend = 0;
  544. X`09stack`5BstackIndex`5D.channel = netChannel;
  545. X`09stack`5BstackIndex`5D.type = NET_CMD;
  546. X`09stackIndex++;
  547. X`09WAKE_UP_DAMMIT;
  548. X`7D
  549. X
  550. X`0C
  551. Xvoid
  552. XnotUsed()
  553. X`7B
  554. X`09fprintf (stderr, "Unused message %d detected\n", nb.netCmd);
  555. X`7D
  556. X
  557. X`0C
  558. X/*
  559. X * processNetCmd
  560. X * Routine to process a network message.
  561. X */
  562. Xint
  563. XprocessNetCmd (pChan)
  564. X    `09unsigned short *pChan;
  565. X`7B
  566. X    `09unsigned short sChan = ((*pChan)>>4);
  567. X/*
  568. X * Note that the current netChannel could have disappeared during the interi
  569. Vm (as
  570. X * with an xscope connect()ed link with the X11 server), so that issuing the
  571. V netcmd read
  572. X * using that channel would be invalid on the next network directive.  There
  573. Vfore, there
  574. X * must be a provision for testing the passed channel information.
  575. X */
  576. X    `09if (!ChanTableInfo`5BsChan`5D)
  577. X    `09`7B
  578. X    `09`09if (lisChannel)`20
  579. X    `09`09`09*pChan = lisChannel;
  580. X    `09`09else
  581. X    `09`09`09fprintf(stderr, "processNetCmd: error on invalid netChannel %d\
  582. Vn", *pChan);
  583. X    `09`7D
  584. X/* Reissue on the passed or updated channel */
  585. X`09issueNetCmdRead (*pChan);
  586. X#ifdef DNDEBUG
  587. X    `09fprintf(stderr, "processNetCmd: netiosb: %d status: %d\n", netiosb.ms
  588. Vg_len, netiosb.status);
  589. X#endif
  590. X
  591. X`09switch (nb.netCmd)
  592. X`09`7B
  593. X`09`09case MSG$_CONNECT    :`09
  594. X#ifdef DNDEBUG
  595. X    `09`09`09`09`09fprintf(stderr, "Link init\n");
  596. X#endif
  597. X    `09`09`09`09`09linkInit (); return 1; break;
  598. X                case MSG$_ABORT      :
  599. X                case MSG$_DISCON     :
  600. X                case MSG$_EXIT       :
  601. X                case MSG$_PATHLOST   :
  602. X                case MSG$_PROTOCOL   :
  603. X                case MSG$_THIRDPARTY :
  604. X                case MSG$_TIMEOUT    :`09
  605. X#ifdef DNDEBUG
  606. X    `09`09`09`09`09fprintf(stderr, "processNetCmd: linkTerm\n");
  607. X#endif
  608. X`09`09`09`09`09linkTerm ((unsigned short) 0); break;
  609. X                case MSG$_NETSHUT    :`09fprintf (stderr, "DECnet shutdown d
  610. Vetected - exiting\n");`20
  611. X`09`09`09`09`09exit(1);
  612. X                case MSG$_CONFIRM    : `20
  613. X#ifdef DNDEBUG
  614. X    `09`09`09`09`09fprintf(stderr, "Connection confirmed\n");`20
  615. X#endif
  616. X    `09`09`09`09`09break;
  617. X                case MSG$_INTMSG     :  break;
  618. X                case MSG$_REJECT     :  break;
  619. X                default              :`09notUsed(); break;
  620. X`09`7D
  621. X`09return 0;
  622. X`7D
  623. X
  624. X`0C
  625. X/* readAst (ap)
  626. X * AST routine to update the stack, increment the channel's length variable,
  627. X * and wake up the server.
  628. X */
  629. Xint
  630. XreadAst (ap)
  631. X`09struct astblk ap;
  632. X`7B
  633. X    `09unsigned short sChan = ap.chan>>4;
  634. X
  635. X    `09if (ChanTableInfo`5BsChan`5D)
  636. X    `09`7B
  637. X    `09`09stack`5BstackIndex`5D.channel = ap.chan;
  638. X    `09`09stack`5BstackIndex`5D.type = ap.type;
  639. X`09`09stackIndex++;
  640. X`09`09ChanTableInfo`5BsChan`5D->len = ChanTableInfo`5BsChan`5D->read_iosb.ms
  641. Vg_len;
  642. X`09`09ChanTableInfo`5BsChan`5D->readAstPend = 0;
  643. X`09`09ChanTableInfo`5BsChan`5D->readAstDone = 1;
  644. X    `09`09WAKE_UP_DAMMIT;
  645. X    `09`7D
  646. X`7D
  647. X
  648. X`0C
  649. X/*
  650. X * timeoutAst
  651. X * Routine that fires after the select() timer expires.
  652. X */
  653. Xvoid
  654. XtimeoutAst()
  655. X`7B
  656. X`09timerExpired = 1;
  657. X`09WAKE_UP_DAMMIT;
  658. X`7D
  659. X
  660. X`0C
  661. X/*
  662. X * upper
  663. X * Routine to convert a NUL terminated string to uppercase.
  664. X */
  665. Xvoid
  666. Xupper (s)
  667. X        char    *s;
  668. X`7B
  669. X        int     i;
  670. X        char    *tp;
  671. X
  672. X        for (i = 0, tp = s; i < strlen(s); i++, tp++)
  673. X                if (islower(*tp)) *tp = toupper(*tp);
  674. X`7D
  675. X
  676. X`0C
  677. X/*
  678. X * EMULATION ROUTINES
  679. X */
  680. X
  681. X`0C
  682. X/*
  683. X * accept():
  684. X * Module to emulate the "acceptance" of a connection over a "listen()"ing c
  685. Vhannel.
  686. X * In the current paradigm, only one listening channel is supported (called
  687. V "lisChannel");
  688. X * even though the actual network command(s) arrive over the channel assigne
  689. Vd to the`20
  690. X * network command mailbox (w/ the NET: device; called "mbxChannel").  The "
  691. Vchan" being
  692. X * passed to this and all other socket emulation routines dealing with netwo
  693. Vrk issues (i.e.,
  694. X * the only non-client channel) is the listening channel established in sock
  695. Vet().  All
  696. X * references to the Net Command Mailbox channel are internal to this librar
  697. Vy, and`20
  698. X * are opaque to the upper layer program.
  699. X */
  700. Xunsigned short
  701. Xaccept (chan, psock, psock_l)
  702. X`09unsigned short chan;
  703. X`09struct sockaddr *psock;
  704. X`09long psock_l;
  705. X`7B
  706. X        int status;
  707. X`09int dvi_unit;
  708. X`09unsigned short channel;
  709. X`09unsigned short sChan;
  710. X`09struct io_stat_blk iosb;
  711. X`09struct dsc$descriptor_s ncbd;
  712. X`09struct`20
  713. X`09`7B
  714. X`09`09short buf_len;
  715. X`09`09short code;
  716. X`09`09int *ret_code;
  717. X`09`09int ret_len;
  718. X`09`09int term;
  719. X`09`7D dviitm = `7B 4, DVI$_UNIT, &dvi_unit, 0, 0`7D;
  720. X
  721. X#ifdef DNDEBUG
  722. X    `09fprintf(stderr, "accept: start - passed chan %d\n", chan);
  723. X#endif /* DNDEBUG */
  724. X`09if (!ncb)`20
  725. X`09`7B
  726. X`09`09fprintf (stderr, "accept: no ncb received!\n");
  727. X`09`09return -1;
  728. X`09`7D
  729. X`09ncb`5Binfo_cnt`5D = '\0';
  730. X        ncbd.dsc$w_length = info_cnt;
  731. X        ncbd.dsc$a_pointer = ncb;
  732. X        ncbd.dsc$b_dtype = DSC$K_DTYPE_T;
  733. X        ncbd.dsc$b_class = DSC$K_CLASS_S;
  734. X
  735. X    `09if (!mbx_created)
  736. X    `09`7B
  737. X    `09`09fprintf(stderr, "accept: error - mailbox not created yet\n");
  738. X    `09`09exit();
  739. X    `09`7D
  740. X        status = SYS$ASSIGN (&net_device, &channel, 0, &netcmd_mbx);
  741. X`09if (VMSFAIL(status)) LIB$SIGNAL(status);
  742. X`09status = SYS$GETDVI (0, channel, 0, &dviitm, &iosb, 0, 0, 0);
  743. X`09if (VMSFAIL(status)) LIB$SIGNAL(status);
  744. X    `09sChan = channel>>4;
  745. X`09clearChanTable ((sChan));
  746. X`09ChanTableInfo`5B(sChan)`5D->unit = dvi_unit;
  747. X`09ChanTableInfo`5B(sChan)`5D->nodename = DNETALLOC (NODNAMSIZ);
  748. X`09bcopy ((char *) ncb, ChanTableInfo`5B(sChan)`5D->nodename, info_cnt);
  749. X    `09ChanTableInfo`5B(sChan)`5D->user = (strchr(ChanTableInfo`5B(sChan)`5D
  750. V->nodename, '=') + 1);
  751. X    `09*((char *) strchr(ChanTableInfo`5B(sChan)`5D->nodename,':') + 2) = '\
  752. V0';
  753. X    `09*((char *) strchr(ChanTableInfo`5B(sChan)`5D->user,'/')) = '\0';
  754. X`09FD_SET(channel, allChannels);
  755. X#ifdef DNDEBUG
  756. X`09fprintf(stderr, "accept: from Node: %s User: %s on channel %d\n",
  757. X    `09`09ChanTableInfo`5B(sChan)`5D->nodename, ChanTableInfo`5B(sChan)`5D->
  758. Vuser, channel);
  759. X#endif
  760. X        status = SYS$QIOW (0, channel, IO$_ACCESS, &iosb, 0, 0, 0, &ncbd, 0,
  761. V 0, 0, 0);
  762. X`09if(!VMSFAIL(status) && !VMSFAIL(iosb.status))
  763. X`09`7B
  764. X`09`09ncb = NULL;
  765. X`09        return channel;
  766. X`09`7D
  767. X`09if (VMSFAIL(status)) LIB$SIGNAL (status);
  768. X`09if (VMSFAIL(iosb.status)) LIB$SIGNAL(iosb.status);
  769. X`09return -1;
  770. X`7D
  771. X
  772. X`0C
  773. X/*
  774. X * B routines: bcmp, bcopy, bzero
  775. X * These routines are declared here in function form to provide
  776. X * a global linker resolution for references in upper level code.
  777. X */
  778. Xint
  779. Xbcmp (s1, s2, l)
  780. X`09char *s1;
  781. X`09char *s2;
  782. X`09int l;
  783. X`7B
  784. X`09return (BCMP(s1, s2, l));
  785. X`7D
  786. X
  787. X`0C
  788. Xvoid *
  789. Xbcopy (s, d, l)
  790. X`09char *s;
  791. X`09char *d;
  792. X`09int l;
  793. X`7B
  794. X`09return BCOPY(s, d, l);
  795. X`7D
  796. X
  797. X`0C
  798. X/*
  799. X * bind():
  800. X * bind the NET channel to the correct object name.
  801. X */
  802. Xint
  803. Xbind (chan, sa, sa_len)
  804. X`09unsigned short chan;
  805. X`09struct sockaddr *sa;
  806. X`09unsigned int sa_len;
  807. X`7B
  808. X`09int status;
  809. X`09struct io_stat_blk iosb;
  810. X`09struct dsc$descriptor_s nfbd;
  811. X`09struct dsc$descriptor_s *object_name;
  812. X
  813. X#ifdef DNDEBUG
  814. X    `09fprintf(stderr, "bind: start - passed chan %d\n", chan);
  815. X#endif /* DNDEBUG */
  816. X        nfbd.dsc$w_length = sizeof(nfb);
  817. X        nfbd.dsc$a_pointer = &nfb;
  818. X        nfbd.dsc$b_dtype = DSC$K_DTYPE_T;
  819. X        nfbd.dsc$b_class = DSC$K_CLASS_S;
  820. X/*
  821. X * Bind to the declare channel in the ChanTableInfo struct.
  822. X */
  823. X`09object_name = nameFromPort (sa);
  824. X`09status = SYS$QIOW (0, chan, IO$_ACPCONTROL, &iosb, 0, 0, &nfbd, object_na
  825. Vme, 0, 0, 0, 0);
  826. X`09if (VMSFAIL(status) `7C`7C VMSFAIL(iosb.status)) return -1;
  827. X#ifdef DNDEBUG
  828. X    `09fprintf(stderr, "bind: on channel %d to %s\n", chan, object_name->dsc
  829. V$a_pointer);
  830. X#endif
  831. X`09return 0;
  832. X`7D
  833. X
  834. X`0C
  835. Xint
  836. Xbzero (buf, size)
  837. X`09char *buf;
  838. X`09int size;
  839. X`7B
  840. X`09return (BZERO(buf, size));
  841. X`7D
  842. X
  843. X`0C
  844. X#ifdef NOTDEF
  845. X/*
  846. X * connect():
  847. X * supports connecting to a "socket" given the network channel (from socket(
  848. V))
  849. X */
  850. Xint
  851. Xconnect (chan, name, namelen)
  852. X`09unsigned short chan;
  853. X`09struct sockaddr *name;
  854. X`09unsigned int namelen;
  855. X`7B
  856. X`09int`09`09status;
  857. X`09unsigned short`09objlen;
  858. X`09char *pncb;
  859. X`09struct dsc$descriptor ncb_desc;
  860. X`09static struct io_stat_blk iosb;
  861. X`09struct dsc$descriptor_s *objdsc;
  862. X    `09static char *objstr = NULL;
  863. X    `09char hname`5B32`5D;
  864. X    `09int l = 0;
  865. X
  866. X#ifdef DNDEBUG
  867. X    `09fprintf(stderr, "connect: start - passed chan %d\n", chan);
  868. X#endif /* DNDEBUG */
  869. X    `09if (!objstr) objstr = DNETALLOC(NCBSIZE);
  870. X        if (!(pncb = initNCB(name, &objlen, TASKOBJECT, NULL)))`20
  871. X    `09`7B
  872. X    `09`09char *a = objstr;
  873. X    `09`09short *area = &name->sa_data`5B2`5D;
  874. X    `09`09short *node = &name->sa_data`5B4`5D;
  875. X
  876. X       `09`09objdsc = nameFromPort (name);
  877. X    `09`09BCOPY(TASKOBJECT, a, strlen(TASKOBJECT));
  878. X    `09`09a += strlen(TASKOBJECT);
  879. X    `09`09BCOPY(objdsc->dsc$a_pointer, a, strlen(objdsc->dsc$a_pointer));
  880. X    `09`09a+= strlen(objdsc->dsc$a_pointer);
  881. X    `09`09*a = 0x0;
  882. X    `09`09sprintf (hname, "%d.%d::", *area, *node);
  883. X    `09`09pncb = initNCB(name, &objlen, objstr, hname);
  884. X    `09`7D
  885. X    `09ncb_desc.dsc$w_length = objlen;
  886. X        ncb_desc.dsc$a_pointer = pncb;
  887. X        ncb_desc.dsc$b_dtype = DSC$K_DTYPE_T;
  888. X        ncb_desc.dsc$b_class = DSC$K_CLASS_S;
  889. X
  890. X        status = SYS$QIOW (0, chan, IO$_ACCESS, &iosb, 0, 0, 0, &ncb_desc, 0
  891. V, 0, 0, 0);
  892. X        if (!VMSFAIL(status)) status = iosb.status;
  893. X        if (!VMSFAIL(status))
  894. X`09`7B
  895. X#ifdef DNDEBUG
  896. X`09`09fprintf(stderr, "connect: Connection to %s on channel %d\n", pncb, cha
  897. Vn);
  898. X#endif
  899. X    `09`09DNETFREE (pncb);
  900. X                return 0;
  901. X`09`7D
  902. X        else
  903. X                LIB$SIGNAL (status);
  904. X`09DNETFREE (pncb);
  905. X`09return -1;
  906. X`7D
  907. X#endif /* NOTDEF */
  908. X
  909. X`0C
  910. X/*
  911. X * connect():
  912. X * supports connecting to a "socket" given the network channel (from socket(
  913. V))
  914. X */
  915. Xint
  916. Xconnect (chan, name, namelen)
  917. X        unsigned short chan;
  918. X        struct sockaddr *name;
  919. X        unsigned int namelen;
  920. X`7B
  921. X        int             status;
  922. X        unsigned short  objlen;
  923. X        char *pncb;
  924. X        struct dsc$descriptor ncb_desc;
  925. X        static struct io_stat_blk iosb;
  926. X        struct dsc$descriptor_s *objdsc;
  927. X        char *objstr = DNETALLOC(NCBSIZE);
  928. X        char *hname;
  929. X        int l = 0;
  930. X        char *a;
  931. X        short *port = &name->sa_data`5B0`5D;
  932. X        short *area = &name->sa_data`5B2`5D;
  933. X        short *node = &name->sa_data`5B4`5D;
  934. X
  935. X#ifdef DNDEBUG
  936. X        fprintf(stderr, "connect: start - passed chan %d port %d addr %d.%d\
  937. Vn",
  938. X                chan, *port, *area, *node);
  939. X#endif /* DNDEBUG */
  940. X        BCOPY (TASKOBJECT, objstr, strlen(TASKOBJECT));
  941. X        hname = NULL;
  942. X        if ((objdsc = nameFromPort (name)))
  943. X        `7B
  944. X                hname = DNETALLOC(32);
  945. X                a = objstr + strlen(TASKOBJECT);
  946. X                BCOPY(objdsc->dsc$a_pointer, a, strlen(objdsc->dsc$a_pointer
  947. V));
  948. X                a+= strlen(objdsc->dsc$a_pointer);
  949. X                *a = 0x0;
  950. X                sprintf (hname, "%d.%d::", *area, *node);
  951. X        `7D
  952. X        pncb = initNCB(name, &objlen, objstr, hname);
  953. X        if (hname) DNETFREE(hname);
  954. X        ncb_desc.dsc$w_length = objlen;
  955. X        ncb_desc.dsc$a_pointer = pncb;
  956. X        ncb_desc.dsc$b_dtype = DSC$K_DTYPE_T;
  957. X        ncb_desc.dsc$b_class = DSC$K_CLASS_S;
  958. X
  959. X        status = SYS$QIOW (0, chan, IO$_ACCESS, &iosb, 0, 0, 0, &ncb_desc, 0
  960. V, 0, 0, 0);
  961. X        if (!VMSFAIL(status)) status = iosb.status;
  962. X        if (!VMSFAIL(status))
  963. X        `7B
  964. X#ifdef DNDEBUG
  965. X                fprintf(stderr, "connect: Connection to %s on channel %d\n",
  966. V pncb, chan);
  967. X#endif
  968. X                DNETFREE (pncb);
  969. X                return 0;
  970. X        `7D
  971. X        else
  972. X                LIB$SIGNAL (status);
  973. X        DNETFREE (pncb);
  974. X        return -1;
  975. X`7D
  976. X
  977. X`0C
  978. X/*
  979. X * ffs
  980. X * Emulates the find first set function for UNIX.
  981. X */
  982. Xint
  983. Xffs (lw)
  984. X`09int lw;
  985. X`7B
  986. X`09int fp;
  987. X`09int sp = 0;
  988. X`09int status;
  989. X`09int sz = sizeof(lw)*BITSPERBYTE;
  990. X
  991. X`09status = lib$ffs(&sp, &sz, &lw, &fp);
  992. X`09if (VMSFAIL(status))
  993. X`09`7B
  994. X`09`09LIB$SIGNAL(status);
  995. X`09`09exit();
  996. X`09`7D
  997. X`09return ++fp;
  998. X`7D
  999. X
  1000. X`0C
  1001. X/*
  1002. X * getdtablesize
  1003. X * Routine to return the given size of the file descriptor table (channel ta
  1004. Vble).
  1005. X */
  1006. Xint
  1007. Xgetdtablesize()
  1008. X`7B
  1009. X`09return FD_SETSIZE;  /* *** should be CHANNELCNT in SYSGEN */
  1010. X`7D
  1011. X
  1012. X`0C
  1013. X/*
  1014. X * gethostbyaddr
  1015. X * Socket library emulation routine to return the host name given a (DECnet)
  1016. X * network address.
  1017. X */
  1018. Xstruct hostent *
  1019. Xgethostbyaddr (addr, length, family)
  1020. X`09unsigned char *addr;
  1021. X`09unsigned int length;
  1022. X`09unsigned int family;
  1023. X`7B
  1024. X`09static struct hostent *t = NULL;
  1025. X
  1026. X#ifdef DNDEBUG
  1027. X    `09fprintf(stderr, "gethostbyaddr: start\n");
  1028. X#endif /* DNDEBUG */
  1029. X    `09if (!t)
  1030. X    `09`7B
  1031. X    `09`09t = DNETALLOC (sizeof(struct hostent));
  1032. X    `09`09t->h_name = DNETALLOC(NODNAMSIZ);
  1033. X`09`09t->h_aliases = NULL;
  1034. X    `09`09t->h_addrtype = AF_DECnet;`20
  1035. X`09`09t->h_length = sizeof(long);
  1036. X`09`09t->h_addr_list = DNETALLOC (sizeof(long));
  1037. X`09`09t->h_addr_list`5B0`5D = DNETALLOC (sizeof(long));
  1038. X`09`09t->h_cputype = DNETALLOC (strlen(CPUTYPE)+1);
  1039. X`09`09t->h_opsys = DNETALLOC (strlen(OPSYS)+1);
  1040. X`09`09bcopy (CPUTYPE, t->h_cputype, strlen(CPUTYPE));
  1041. X`09`09bcopy (OPSYS, t->h_opsys, strlen(OPSYS));
  1042. X    `09`7D
  1043. X#ifdef DNDEBUG
  1044. X    `09fprintf (stderr, "gethostbyaddr: DECnet address %d.%d\n",`20
  1045. X    `09`09(short) *addr, (short) (*(addr+sizeof(short))));
  1046. X#endif
  1047. X    `09sprintf (t->h_name, "%d.%d", (short) *addr, (short) *(addr+sizeof(sho
  1048. Vrt)));
  1049. X    `09if (NCPfind (0, t->h_addr_list`5B0`5D, t->h_name) < 0)
  1050. X    `09`7B
  1051. X    `09`09h_errno = HOST_NOT_FOUND;
  1052. X    `09`09return 0;
  1053. X    `09`7D
  1054. X`09return t;
  1055. X`7D
  1056. X
  1057. X`0C
  1058. X/*
  1059. X * gethostbyname
  1060. X * Routine to return the network address of a given node name.
  1061. X */
  1062. Xstruct hostent *
  1063. Xgethostbyname (name)
  1064. X`09char *name;
  1065. X`7B
  1066. X`09static struct hostent *t = NULL;
  1067. X
  1068. X#ifdef DNDEBUG
  1069. X    `09fprintf(stderr, "gethostbyname: start\n");
  1070. X#endif /* DNDEBUG */
  1071. X    `09if (!t)
  1072. X    `09`7B
  1073. X    `09`09t = DNETALLOC (sizeof(struct hostent));
  1074. X    `09`09t->h_name = DNETALLOC(NODNAMSIZ);
  1075. X`09`09t->h_aliases = NULL;
  1076. X`09`09t->h_addrtype = AF_DECnet;
  1077. X`09`09t->h_length = sizeof(long);
  1078. X`09`09t->h_addr_list = DNETALLOC (sizeof(long));
  1079. X`09`09t->h_addr_list`5B0`5D = DNETALLOC (sizeof(long));
  1080. X`09`09t->h_cputype = DNETALLOC (strlen(CPUTYPE)+1);
  1081. X`09`09t->h_opsys = DNETALLOC (strlen(OPSYS)+1);
  1082. X`09`09bcopy (CPUTYPE, t->h_cputype, strlen(CPUTYPE));
  1083. X`09`09bcopy (OPSYS, t->h_opsys, strlen(OPSYS));
  1084. X    `09`7D
  1085. X`09bcopy (name, t->h_name, strlen(name)+1);
  1086. X    `09if (NCPfind (0, t->h_addr_list`5B0`5D, t->h_name) < 0)
  1087. X    `09`7B
  1088. X    `09`09h_errno = HOST_NOT_FOUND;
  1089. X    `09`09return 0;
  1090. X    `09`7D
  1091. X`09return t;
  1092. X`7D
  1093. X
  1094. X`0C
  1095. X/*
  1096. X * gethostname
  1097. X * Routine to return the host node name.
  1098. X */
  1099. Xint
  1100. Xgethostname (hname, l)
  1101. X    `09char *hname;
  1102. X    `09int l;
  1103. X`7B
  1104. X        short retlen = 0;
  1105. X
  1106. X        unsigned short iosb`5B4`5D;
  1107. X        struct
  1108. X            `7B
  1109. X            unsigned short id_buflen;
  1110. X            unsigned short id_itmcod;
  1111. X            int *id_scsid;
  1112. X            unsigned short *id_retlen;
  1113. X            int listend;
  1114. X            `7D itmlst = `7Bl, SYI$_NODENAME, hname, &retlen, 0`7D;
  1115. X
  1116. X#ifdef DNDEBUG
  1117. X    `09fprintf(stderr, "gethostname: start\n");
  1118. X#endif /* DNDEBUG */
  1119. X        SYS$GETSYIW (0, 0, 0, &itmlst, iosb, 0, 0);
  1120. X        hname`5Bretlen`5D = '\0';
  1121. X`09return 0;
  1122. X`7D
  1123. X
  1124. X`0C
  1125. X/*
  1126. X * getpeername
  1127. X * Routine to return the node address (DECnet) associated with a given chann
  1128. Vel.
  1129. X */
  1130. Xint
  1131. Xgetpeername (chan, psock, psock_l)
  1132. X`09unsigned short chan;
  1133. X`09struct sockaddr *psock;
  1134. X`09long *psock_l;
  1135. X`7B
  1136. X    `09unsigned short sChan = chan>>4;
  1137. X
  1138. X#ifdef DNDEBUG
  1139. X    `09fprintf(stderr, "getpeername: start\n");
  1140. X#endif /* DNDEBUG */
  1141. X`09psock->sa_family = AF_DECnet;
  1142. X    `09if (!ChanTableInfo`5BsChan`5D) return -1;
  1143. X    `09*psock_l = sizeof(long);
  1144. X`09return NCPfind (sChan, psock, ChanTableInfo`5BsChan`5D->nodename);
  1145. X`7D
  1146. X
  1147. X`0C
  1148. X/*
  1149. X * gettimeofday
  1150. X * Routine to return the time in secs and millisecs
  1151. X */
  1152. Xint
  1153. Xgettimeofday (timev)
  1154. X`09struct timeval *timev;
  1155. X`7B
  1156. X`09static timeb_t t;
  1157. X
  1158. X#ifdef DNDEBUG
  1159. X    `09fprintf(stderr, "gettimeofday: start\n");
  1160. X#endif /* DNDEBUG */
  1161. X`09ftime (&t);
  1162. X`09timev->tv_sec = t.time;
  1163. X`09timev->tv_usec = t.millitm * 1000;
  1164. X
  1165. X`09return 0;
  1166. X`7D
  1167. X
  1168. X`0C
  1169. Xint
  1170. Xhtonl (i)
  1171. X`09int i;
  1172. X`7B
  1173. X        int t1;
  1174. X`09int t2;
  1175. X
  1176. X        t2 = i;`20
  1177. X        ((char *)&t1)`5B0`5D = ((char *)&t2)`5B3`5D;
  1178. X`09((char *)&t1)`5B1`5D = ((char *)&t2)`5B2`5D;
  1179. X        ((char *)&t1)`5B2`5D = ((char *)&t2)`5B1`5D;
  1180. X`09((char *)&t1)`5B3`5D = ((char *)&t2)`5B0`5D;
  1181. X
  1182. X`09return t1;
  1183. X`7D
  1184. X
  1185. X`0C
  1186. Xunsigned short
  1187. Xhtons (i)
  1188. X`09unsigned short i;
  1189. X`7B
  1190. X        unsigned short t1;
  1191. X`09unsigned short t2;
  1192. X
  1193. X        t2 = i;
  1194. X        ((char *)&t1)`5B0`5D = ((char *)&t2)`5B1`5D;
  1195. X`09((char *)&t1)`5B1`5D = ((char *)&t2)`5B0`5D;
  1196. X
  1197. X        return t1;
  1198. X`7D
  1199. X
  1200. X`0C
  1201. X/*
  1202. X * inet_addr
  1203. X * Routine to translate the network address into a longword value.
  1204. X */
  1205. Xint
  1206. Xinet_addr (address)
  1207. X`09char *address;
  1208. X`7B
  1209. X`09char`09*a;
  1210. X`09char`09*b`5B4`5D;
  1211. X    `09char `09*tmpvm;
  1212. X`09int`09i;
  1213. X`09int`09j = 0;
  1214. X`09int`09out;
  1215. X
  1216. X#ifdef DNDEBUG
  1217. X    `09fprintf(stderr, "inet_addr: start\n");
  1218. X#endif /* DNDEBUG */
  1219. X    `09if(isalpha(*address)) return -1;
  1220. X`09b`5Bj++`5D = address;
  1221. X    `09tmpvm = DNETALLOC(strlen(address));
  1222. X    `09bcopy (address, tmpvm, strlen(address));
  1223. X`09for (i = 0, a = tmpvm; i < strlen(address); i++, a++)
  1224. X`09`7B
  1225. X`09`09if ((*a == '.') `7C`7C (*a = ':'))
  1226. X`09`09`7B
  1227. X`09`09`09*a = '\0';
  1228. X`09`09`09b`5Bj++`5D = a + 1;
  1229. X`09`09`7D
  1230. X`09`7D
  1231. X/* *** Needs to read all network address types (?) */
  1232. X`09a = (char *) &out;
  1233. X`09for (i = 0; i < j; i++, a++)
  1234. X`09`09*a = (char) atoi(b`5Bi`5D);
  1235. X`09DNETFREE(tmpvm);
  1236. X`09return (htonl(out));
  1237. X`7D
  1238. X
  1239. X`0C
  1240. X/*
  1241. X * listen():
  1242. X * Module to emulate a "listen" placed on the passed channel.  In the case o
  1243. Vf
  1244. X * DECnet, we'll interpret this to mean issue a read to the network command
  1245. X * mailbox associated with the NET: device.  Right now I don't really have a
  1246. X * use for the back log queue length, but we'll keep it around anyhow.
  1247. X */
  1248. Xint
  1249. Xlisten (chan, bl)
  1250. X`09unsigned short chan;
  1251. X`09unsigned int bl;
  1252. X`7B
  1253. X`09int`09status;
  1254. X
  1255. X#ifdef DNDEBUG
  1256. X    `09fprintf(stderr, "listen: start - passed chan %d\n", chan);
  1257. X#endif /* DNDEBUG */
  1258. X    `09lisChannel = netChannel;
  1259. X`09ChanTableInfo`5B(chan>>4)`5D->backLogQueueLength = bl; /* *** */
  1260. X`09if (!ChanTableInfo`5B(chan>>4)`5D->readAstPend)
  1261. X`09`7B
  1262. X`09`09DISABLE_ASTS;`09`09/* don't forget this or we're toast! */
  1263. X`09`09status = issueNetCmdRead (chan);
  1264. X`09`09ChanTableInfo`5B(chan>>4)`5D->readAstPend = 1;
  1265. X`09`09if (VMSFAIL(status))
  1266. X`09`09`7B
  1267. X`09`09`09LIB$SIGNAL (status);
  1268. X`09`09`09exit(0);
  1269. X`09`09`7D
  1270. X`09`7D
  1271. X`09return 0;
  1272. X`7D
  1273. X
  1274. X`0C
  1275. X/*
  1276. X *
  1277. X * SELECT for DECnet
  1278. X * Note:
  1279. X *`09readfds should contain the fd for the _NET: device for new connections.
  1280. X * `09writefds will be returned from outstanding write AST notification.
  1281. X *
  1282. X * Return:
  1283. X * `09int value specifying the number of channels ready.
  1284. X *
  1285. X */
  1286. Xint
  1287. Xselect (width, readfds, writefds, exceptfds, timeout)
  1288. X`09int width;
  1289. X`09fd_set *readfds;
  1290. X`09fd_set *writefds;
  1291. X`09fd_set *exceptfds;
  1292. X`09struct timeval *timeout;
  1293. X`7B
  1294. X`09int i;
  1295. X`09int j;
  1296. X`09int k;
  1297. X`09int lw;
  1298. X`09char *plw;
  1299. X`09int delta`5B2`5D;
  1300. X`09int totset;
  1301. X`09int fd_group;
  1302. X`09int numBytes = width/NBBY;
  1303. X`09int status;
  1304. X    `09int bit;
  1305. X    `09int pos;
  1306. X`09fd_set readMask;
  1307. X`09fd_set writeMask;
  1308. X`09fd_set exceptMask;
  1309. X
  1310. X`09stackIndex = 0;
  1311. X`09timerExpired = 0;
  1312. X`09totset = 0;
  1313. X
  1314. X#ifdef DNDEBUG
  1315. X    `09fprintf(stderr, "select: start\n");
  1316. X#endif /* DNDEBUG */
  1317. X/*
  1318. X * Optimized channel listening setup loop.
  1319. X */
  1320. X`09for (fd_group = 0, i = 0, j = 0; j < width; ++fd_group)
  1321. X`09`7B
  1322. X`09`09if (readfds->bits`5Bfd_group`5D)
  1323. X`09`09`7B
  1324. X    `09`09`09pos = -1;
  1325. X`09`09`09while( _FFS(pos+1, ((NBLW-1)-pos), &readfds->bits`5Bfd_group`5D, &p
  1326. Vos))
  1327. X    `09`09`09`7B
  1328. X    `09`09`09`09bit = j + pos;
  1329. X    `09`09`09`09if (!ChanTableInfo`5Bbit`5D)
  1330. X    `09`09`09`09`7B
  1331. X    `09`09`09`09`09errno = EBADF;
  1332. X    `09`09`09`09`09return -1;
  1333. X    `09`09`09`09`7D
  1334. X    `09`09`09`09if (!ChanTableInfo`5Bbit`5D->readAstPend)`20
  1335. X    `09`09`09`09`09status = issueRead ((bit<<4));
  1336. X`09`09`09`7D
  1337. X`09`09`7D
  1338. X`09`09else
  1339. X`09`09`09j += NBLW;
  1340. X`09`7D
  1341. X`09LIB$MOVC5(&zero, NULL, "\0", &numBytes, (char *) &readMask);
  1342. X`09if (writefds) LIB$MOVC5(&zero, NULL, "\0", &numBytes, (char *) &writeMask
  1343. V);
  1344. X/*
  1345. X`09This is a future enhancement, currently omitted for time considerations:
  1346. X`09if (exceptfds) LIB$MOVC5(&zero, NULL, "\0", &numBytes, (char *) &exceptMa
  1347. Vsk);
  1348. X*/
  1349. X`09if (!stackIndex)
  1350. X`09`7B
  1351. X`09`09int sec = 0;
  1352. X`09`09int usec = 0;
  1353. X
  1354. X`09`09if (timeout)
  1355. X`09`09`7B
  1356. X`09`09`09sec = timeout->tv_sec;
  1357. X`09`09`09usec = timeout->tv_usec;
  1358. X`09`09`7D
  1359. X`09`09if ((timeout) && (!(sec + usec)))
  1360. X`09`09`09timerExpired = 1;
  1361. X`09`09else
  1362. X`09`09`7B
  1363. X/*
  1364. X * Here's the juicy part of select().  Check for a timeout value to be setup
  1365. V. Then
  1366. X * enable ASTs, check for any I/O completion, and disable ASTs.
  1367. X */
  1368. X`09`09`09if (timeout)
  1369. X`09`09`09`7B
  1370. X`09`09`09`09delta`5B0`5D = (sec * -10000000) + (usec * -10);
  1371. X`09`09`09`09delta`5B1`5D = -1;
  1372. X`09`09`09`09SYS$SETIMR ( 0, delta, timeoutAst, timeout, 0);
  1373. X`09`09`09`7D
  1374. X`09`09`09ENABLE_ASTS;
  1375. X`09`09`09HIBERNATE;
  1376. X`09`09`09DISABLE_ASTS;
  1377. X`09`09`09if ((!timerExpired) && (timeout))
  1378. X`09`09`09`7B
  1379. X`09`09`09`09status = SYS$CANTIM (timeout, 0);
  1380. X`09`09`09`09if (VMSFAIL(status)) LIB$SIGNAL(status);
  1381. X`09`09`09`7D
  1382. X`09`09`7D
  1383. X`09`7D
  1384. X`09if (!stackIndex && !timerExpired)
  1385. X`09`09fprintf (stderr, "select: error - stackIndex 0 timerExpired 0\n");
  1386. X/*
  1387. X * Now check the ast stack for completions.  Mark any channel's with I/O pen
  1388. Vding
  1389. X * on the internal fd masks.
  1390. X */
  1391. X`09if ((timerExpired) && (!stackIndex))
  1392. X`09`7B
  1393. X`09`09for (i = 0, lw = 0, fd_group = 0; lw < width; lw+=NBLW, fd_group++)
  1394. X`09`09`7B
  1395. X`09`09`09if (readfds)
  1396. X`09`09`09`09readfds->bits`5Bfd_group`5D = 0;
  1397. X`09`09`09if (writefds)
  1398. X`09`09`09`09writefds->bits`5Bfd_group`5D = 0;
  1399. X`09`09`09if (exceptfds)
  1400. X`09`09`09`09exceptfds->bits`5Bfd_group`5D = 0;
  1401. X`09`09`7D
  1402. X`09`7D
  1403. X`09else
  1404. X`09`7B
  1405. X#ifdef DNDEBUG
  1406. X`09`09fprintf(stderr, "select: stackIndex %d\n", stackIndex);
  1407. X#endif
  1408. X`09`09for (i = 0; i < stackIndex; i++)
  1409. X`09`09`7B
  1410. X/*
  1411. X *`09Note, read_iosb.status = SS$_LINKABORT, when the line dies!`20
  1412. X */
  1413. X`09`09`09if ((stack`5Bi`5D.type == NET_CMD) `7C`7C (ChanTableInfo`5B(stack`5
  1414. VBi`5D.channel>>4)`5D))
  1415. X`09`09`09`7B
  1416. X`09`09`09switch (stack`5Bi`5D.type)
  1417. X`09`09`09`7B
  1418. X`09`09`09case NET_CMD :
  1419. X`09`09`09`7B
  1420. X`09`09`09`09if (processNetCmd(&stack`5Bi`5D.channel))
  1421. X`09`09`09`09`7B
  1422. X`09`09`09`09`09FD_SET(stack`5Bi`5D.channel, &readMask);
  1423. X`09`09`09`09`09totset++;
  1424. X`09`09`09`09`7D
  1425. X`09`09`09`09break;
  1426. X`09`09`09`7D
  1427. X`09`09`09case NET_RD :
  1428. X`09`09`09`7B
  1429. X`09`09`09`09if (readfds)
  1430. X`09`09`09`09`7B
  1431. X`09`09`09`09`09if (FD_ISSET(stack`5Bi`5D.channel, readfds))
  1432. X`09`09`09`09`09`7B
  1433. X`09`09`09`09`09`09FD_SET(stack`5Bi`5D.channel, &readMask);
  1434. X`09`09`09`09`09`09totset++;
  1435. X`09`09`09`09`09`7D
  1436. X`09`09`09`09`7D
  1437. X`09`09`09`7D
  1438. X`09`09`09case NET_WRT :`20
  1439. X`09`09`09`7B
  1440. X`09`09`09`09if (writefds)
  1441. X`09`09`09`09`7B
  1442. X`09`09`09`09`09if (FD_ISSET(stack`5Bi`5D.channel, writefds))
  1443. X`09`09`09`09`09`7B
  1444. X`09`09`09`09`09`09FD_SET(stack`5Bi`5D.channel, &writeMask);
  1445. X`09`09`09`09`09`09totset++;
  1446. X`09`09`09`09`09`7D
  1447. X`09`09`09`09`7D
  1448. X`09`09`09`7D
  1449. X/*
  1450. X *`09`09`09case NET_CMD :`20
  1451. X *`09`09`09`7B
  1452. X *`09`09`09`09if (exceptfds)
  1453. X *`09`09`09`09`7B
  1454. X *`09`09`09`09`09if (FD_ISSET(stack`5Bi`5D.channel, exceptfds))
  1455. X *`09`09`09`09`09`7B
  1456. X *`09`09`09`09`09`09FD_SET(stack`5Bi`5D.channel, &exceptMask);
  1457. X *`09`09`09`09`09`09totset++;
  1458. X *`09`09`09`09`09`7D
  1459. X *`09`09`09`09`7D
  1460. X *`09`09`09`7D
  1461. X */
  1462. X`09`09`09`7D /* switch */
  1463. X`09`09`09`7D /* LINKABORT if */
  1464. X`09`09`09else
  1465. X`09`09`09`7B
  1466. X`09`09`09`09errno = EBADF;
  1467. X`09`09`09`09totset = -1;
  1468. X`09`09`09`09break;
  1469. X`09`09`09`7D
  1470. X`09`09`7D
  1471. X/*
  1472. X * Now "and" the two tables together to create the returned fd table(s).
  1473. X */
  1474. X`09`09for (lw = 0, fd_group = 0; lw < width; lw+=NBLW, ++fd_group)
  1475. X`09`09`7B
  1476. X`09`09`09if (readfds)
  1477. X`09`09`09`09readfds->bits`5Bfd_group`5D &= readMask.bits`5Bfd_group`5D;
  1478. X`09`09`09if (writefds)
  1479. X`09`09`09`09writefds->bits`5Bfd_group`5D &= writeMask.bits`5Bfd_group`5D;
  1480. X`09`09`09if (exceptfds)
  1481. X`09`09`09`09exceptfds->bits`5Bfd_group`5D &= exceptMask.bits`5Bfd_group`5D;
  1482. X`09`09`7D
  1483. X`09`7D
  1484. X#ifdef DNDEBUG
  1485. X    `09fprintf(stderr, "select: returning %d\n", totset);
  1486. X#endif
  1487. X`09return totset;
  1488. X`7D
  1489. X
  1490. X`0C
  1491. X/*
  1492. X * setsockopt
  1493. X * Stub routine for emulation purposes right now.
  1494. X */
  1495. Xint
  1496. Xsetsockopt (chan, level, optname, optval, optlen)
  1497. X`09unsigned short chan;
  1498. X`09unsigned long level;
  1499. X`09unsigned long optname;
  1500. X`09char *optval;
  1501. X`09unsigned long optlen;
  1502. X`7B
  1503. X#ifdef DNDEBUG
  1504. X    `09fprintf(stderr, "setsockopt: start - passed chan %d\n", chan);
  1505. X#endif /* DNDEBUG */
  1506. X`09ChanTableInfo`5B(chan>>4)`5D->o`5Boptname`5D.option = optval;
  1507. X`09ChanTableInfo`5B(chan>>4)`5D->o`5Boptname`5D.optionlen = optlen;
  1508. X`09return 0;
  1509. X`7D
  1510. X
  1511. X`0C
  1512. X/*
  1513. X * socket():
  1514. X * Two channels are created as a result of this call,
  1515. X * 1) mbxChannel - the network command mailbox throught which all low level`
  1516. V20
  1517. X *`09`09   connection information and management crap flows
  1518. X * 2) netChannel - the channel to the NET device, used by a server to est. a
  1519. V`20
  1520. X *`09`09   DECnet object; used by a client to connect and perform I/O on
  1521. X *`09`09   the aforementioned object.
  1522. X * Note: only netChannel is "seen" by the calling layer program.
  1523. X */
  1524. Xunsigned short
  1525. Xsocket (addrfam, type, proto)
  1526. X`09unsigned long addrfam;
  1527. X`09unsigned long type;
  1528. X`09unsigned long proto;
  1529. X`7B
  1530. X`09int status;
  1531. X
  1532. X#ifdef DNDEBUG
  1533. X    `09fprintf(stderr, "socket: start\n");
  1534. X#endif /* DNDEBUG */
  1535. X    `09connectNet ();
  1536. X`09if (!ChanTableInfo`5B(netChannel>>4)`5D) clearChanTable((netChannel>>4));
  1537. X`09if (!ChanTableInfo`5B(mbxChannel>>4)`5D) clearChanTable((mbxChannel>>4));
  1538. X`09return netChannel;
  1539. X`7D
  1540. X
  1541. X`0C
  1542. X/*
  1543. X * socket_close
  1544. X * Emulation routine for closing channels.
  1545. X */
  1546. Xint
  1547. Xsocket_close (chan)
  1548. X        unsigned short chan;
  1549. X`7B
  1550. X`09unsigned short shiftChan = chan>>4;
  1551. X
  1552. X#ifdef DNDEBUG
  1553. X`09fprintf(stderr, "socket_close: linkTerm %d\n", chan);
  1554. X#endif
  1555. X`09linkTerm (shiftChan);
  1556. X`09clearChanTable (shiftChan);
  1557. X`09return 0;
  1558. X`7D
  1559. X
  1560. X`0C
  1561. X/*
  1562. X * socket_ioctl
  1563. X * Emualtion routine for stubbing purposes only.
  1564. X */
  1565. Xint
  1566. Xsocket_ioctl (chan, request, argp)
  1567. X`09unsigned short chan;
  1568. X`09unsigned int request;
  1569. X`09char *argp;
  1570. X`7B
  1571. X#ifdef DNDEBUG
  1572. X    `09fprintf(stderr, "socket_ioctl: start - passed chan %d\n", chan);
  1573. X#endif /* DNDEBUG */
  1574. X`09if (chan > FD_SETSIZE)
  1575. X`09`09return -1;
  1576. X`09ChanTableInfo`5B(chan>>4)`5D->type = request;
  1577. X`7D
  1578. X
  1579. X`0C
  1580. X/*
  1581. X * socket_perror
  1582. X * Emulation for the same.  Relatively weak right now in that it ignores err
  1583. Vno
  1584. X * values.
  1585. X */
  1586. Xvoid
  1587. Xsocket_perror (s)
  1588. X`09char *s;
  1589. X`7B
  1590. X#ifdef DNDEBUG
  1591. X    `09fprintf(stderr, "socket_perror: start\n");
  1592. X#endif /* DNDEBUG */
  1593. X`09fprintf(stdout, "%s", s);
  1594. X`7D
  1595. X
  1596. X`0C
  1597. X/*
  1598. X * socket_read (chan, target, length)
  1599. X * Routine to emulate the a streamed read on a socket.  Currently the read
  1600. X * supports ONLY nonblocking I/O.  That is, the read will complete is there
  1601. X * is ANYTHING in the channel buffer not depending on the passed "length" fi
  1602. Veld.
  1603. X * With blocking I/O, the read will wait until the length field request has
  1604. X * been statisfied.
  1605. X */
  1606. Xint
  1607. Xsocket_read (chan, target, l)
  1608. X        unsigned short   chan;
  1609. X        char    *target;
  1610. X        int     l;
  1611. X`7B
  1612. X`09int`09shiftChan = chan>>4;
  1613. X`09char *vmbase = ChanTableInfo`5BshiftChan`5D->base;
  1614. X`09char *vmdelta = ChanTableInfo`5BshiftChan`5D->delta;
  1615. X`09int vmlen = ChanTableInfo`5BshiftChan`5D->len;
  1616. X        int     remainder;
  1617. X        char    *savtarget;
  1618. X        int     movetot;
  1619. X`09int`09pass;
  1620. X`09int`09status;
  1621. X`09struct io_stat_blk iosb;
  1622. X
  1623. X#ifdef DNDEBUG
  1624. X    `09fprintf(stderr, "socket_read: start - passed chan %d\n", chan);
  1625. X#endif /* DNDEBUG */
  1626. X`09if (!ChanTableInfo`5BshiftChan`5D) return -1;
  1627. X        if (!l) return l;
  1628. X
  1629. X        savtarget = target;
  1630. X        movetot = 0;
  1631. X/* Check the size of the channel's read buffer `09`09`09*/
  1632. X        remainder = (vmbase + vmlen) - vmdelta;
  1633. X/*
  1634. X * If this routine was called after an AST read notification from select() a
  1635. Vnd the
  1636. X * read in buffer size was 0, return 0 now so that a QIO is *not* performed.
  1637. V  In the
  1638. X * case of a calling program that does *not* use select/AST's, readAstDone w
  1639. Vill remain 0.
  1640. X */
  1641. X    `09if (ChanTableInfo`5BshiftChan`5D->readAstDone)
  1642. X    `09`7B
  1643. X    `09`09ChanTableInfo`5BshiftChan`5D->readAstDone = 0;
  1644. X    `09`09if(!remainder) return 0;
  1645. X    `09`7D
  1646. X/*
  1647. X * See if the VM area exists and, if so, is there anything in there?  If yes
  1648. V again,
  1649. X * move it, update VM pointers, and return. (Non blocking I/O).
  1650. X */
  1651. X        if (remainder)
  1652. X        `7B
  1653. X`09`09pass = MIN(remainder, l);
  1654. X                bcopy (vmdelta, target, pass);
  1655. X                movetot += pass;
  1656. X                savtarget += pass;
  1657. X                vmdelta += pass;
  1658. X`09`09ChanTableInfo`5BshiftChan`5D->base = vmbase;
  1659. X`09`09ChanTableInfo`5BshiftChan`5D->delta = vmdelta;
  1660. X`09`09ChanTableInfo`5BshiftChan`5D->len = vmlen;
  1661. X`09`09return movetot;
  1662. X        `7D
  1663. X/*
  1664. X * VM memory area is empty, so fill it up and update the pointers.
  1665. X */
  1666. X`09if (!remainder)
  1667. X`09`7B
  1668. X                status = SYS$QIOW (0, chan, IO$_READVBLK, &iosb, 0, 0, vmbas
  1669. Ve,
  1670. X                        MAX_QIO, 0, 0, 0, 0);
  1671. X                if (!(status & STS$M_SUCCESS) `7C`7C !(iosb.status & STS$M_S
  1672. VUCCESS))
  1673. X                        return -1;
  1674. X`09`09vmdelta = vmbase;
  1675. X                vmlen = iosb.msg_len;
  1676. X#ifdef DNDEBUG
  1677. X    `09`09fprintf(stderr,"socket_read: iosb.len %d on channel %d\n",iosb.msg
  1678. V_len, chan);
  1679. X#endif
  1680. X`09`09if (vmlen < l) fprintf(stderr, "socket_read: returned < request %d/%d\
  1681. Vn", vmlen, l);
  1682. X        `7D
  1683. X`09pass = MIN(vmlen, l);
  1684. X        bcopy (vmdelta, savtarget, pass);
  1685. X        movetot += pass;
  1686. X        vmdelta += pass;
  1687. X`09ChanTableInfo`5BshiftChan`5D->base = vmbase;
  1688. X`09ChanTableInfo`5BshiftChan`5D->delta = vmdelta;
  1689. X`09ChanTableInfo`5BshiftChan`5D->len = vmlen;
  1690. X`09return movetot;
  1691. X`7D
  1692. X
  1693. X`0C
  1694. X/*
  1695. X * socket_write
  1696. X * Emulation routine for writes to a given channel.  Note that I tried IO$M_
  1697. VNOW
  1698. X * but it had the effect of causing an error (overflow I believe). `20
  1699. X * Does buffering occur?  Is it detrimental to the works since I don't check
  1700. V for
  1701. X * write completion?
  1702. X */
  1703. Xint
  1704. Xsocket_write (chan, buffer, l)   /* Issue writes, (IO$_WRITEVBLK), over the
  1705. V logical link.*/
  1706. X        unsigned short`09chan;
  1707. X        char            *buffer;
  1708. X        int             l;
  1709. X`7B
  1710. X`09int status;
  1711. X`09struct io_stat_blk iosb;
  1712. X`09
  1713. X#ifdef DNDEBUG
  1714. X    `09fprintf(stderr, "socket_write: start - passed chan %d\n", chan);
  1715. X#endif /* DNDEBUG */
  1716. X        status = SYS$QIOW (0, chan, IO$_WRITEVBLK, &iosb, 0, 0, buffer,
  1717. X                        l, 0, 0, 0, 0);
  1718. X        if (VMSFAIL(status))`20
  1719. X`09`7B
  1720. X`09`09LIB$SIGNAL(status);
  1721. X`09`09return -1;
  1722. X`09`7D
  1723. X        if (VMSFAIL(iosb.status))`20
  1724. X`09`7B
  1725. X`09`09LIB$SIGNAL(iosb.status);
  1726. X`09`09return -1;
  1727. X`09`7D
  1728. X#ifdef DNDEBUG
  1729. X`09fprintf(stderr, "socket_write: wrote %d/%d to channel %d\n",iosb.msg_len,
  1730. V l, chan);
  1731. X#endif
  1732. X`09return iosb.msg_len;
  1733. X`7D
  1734. X
  1735. X`0C
  1736. X/*
  1737. X * socket_writev
  1738. X * Emulation routine for the ugly iov style socket writing.
  1739. X */
  1740. Xint
  1741. Xsocket_writev( d, iov, iovcnt)
  1742. X        int d;
  1743. X        struct iovec *iov;
  1744. X        int iovcnt;
  1745. X`7B
  1746. X        int     totbytes;
  1747. +-+-+-+-+-+-+-+-  END  OF PART 2 +-+-+-+-+-+-+-+-
  1748. --
  1749. Patrick L. Mahan
  1750.  
  1751. --- TGV Window Washer ------------------------------- Mahan@TGV.COM ---------
  1752.  
  1753. Waking a person unnecessarily should not be considered  - Lazarus Long
  1754. a capital crime.  For a first offense, that is            From the Notebooks of
  1755.                               Lazarus Long
  1756.  
  1757.