home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!usc!news.service.uci.edu!unogate!mvb.saic.com!vmsnet-sources
- From: mahan@tgv.com (Patrick L. Mahan - TGV Window Washer)
- Newsgroups: vmsnet.sources
- Subject: XSCOPE/VMS 1.0, part 02/08
- Message-ID: <8045405@MVB.SAIC.COM>
- Date: Fri, 04 Sep 1992 05:34:15 GMT
- Reply-To: mahan@tgv.com
- Organization: TGV Incorporated (Tech Support) in Santa Cruz, CA
- Lines: 1745
- Approved: Mark.Berryman@Mvb.Saic.Com
-
- Submitted-by: mahan@tgv.com (Patrick L. Mahan - TGV Window Washer)
- Posting-number: Volume 3, Issue 154
- Archive-name: xscope/part02
-
-
- -+-+-+-+-+-+-+-+ START OF PART 2 -+-+-+-+-+-+-+-+
- X `09if ((!caddr) `7C`7C (!*caddr)) return 0;
- X `09if (strchr(caddr, '.')) return 0;
- X `09for ( a = caddr; *a; a++)
- X `09`09if((*a < '0') `7C`7C (*a > '9')) return 0;
- X `09if (a == caddr) return 0;
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "isEtherAddr: %s is an ethernet address\n",caddr);
- X#endif
- X `09return 1;
- X `09`09
- X`7D
- X
- X`0C
- X/*
- X * isDnetAddr
- X * Boolean routine to determine if a passed client node name
- X * is a valid DECnet address.
- X */
- Xint
- XisDnetAddr (caddr)
- X `09char *caddr;
- X`7B
- X `09if (strchr(caddr, '.')) return 1;
- X `09return 0;
- X`7D
- X
- X`0C
- X/*
- X * issueNetCmdRead
- X * Reading from the Network Command Mailbox willbe done on the mbxChannel, b
- Vut
- X * will be treated as a read in the NET: channel, since it is the channel th
- Vat the
- X * upper layer sees.
- X */
- Xint
- XissueNetCmdRead (chan)
- X`09unsigned short chan;
- X`7B
- X `09int status;
- X
- X `09if (!ChanTableInfo`5B(mbxChannel>>4)`5D->readAstPend)
- X `09`7B
- X#ifdef DNDEBUG
- X `09`09fprintf(stderr, "issueNetCmdRead: read pending on channel %d from
- V chan %d\n", mbxChannel, chan);
- X#endif
- X `09`09ChanTableInfo`5B(mbxChannel>>4)`5D->readAstPend = 1;
- X `09status = SYS$QIO (0, mbxChannel, IO$_READVBLK, &netiosb, &netCmdA
- Vst, NET_CMD,
- X &nb, mbxMsgLen, 0, 0, 0, 0);
- X `09`09if (VMSFAIL(status)) LIB$SIGNAL(status);
- X `09`7D
- X `09return status;
- X`7D
- X
- X`0C
- X/*
- X * issueRead (chan)
- X * Routine to setup a read AST on the passed channel. In our emulation
- X * we must check the channel's buffers to see if any remaining data is left
- X * to be read. In the case that there is some remainder, the routine will`2
- V0
- X * "fake" an AST event by shoving interrupt information in the stack. Other
- Vwise
- X * the routine sets up the AST normally with the buffer being the base of th
- Ve`20
- X * vm area setup.
- X */
- Xint
- XissueRead (chan)
- X`09unsigned short chan;
- X`7B
- X`09astParam ap;
- X`09int shiftChan = chan>>4;
- X`09char *vmbase = ChanTableInfo`5BshiftChan`5D->base;
- X`09char *vmdelta = ChanTableInfo`5BshiftChan`5D->delta;
- X`09int vmlen = ChanTableInfo`5BshiftChan`5D->len;
- X`09int remainder = (vmbase + vmlen) - vmdelta;
- X `09int status;
- X/*`20
- X * Insert a fake result in the stack if there is unread data in our channel'
- Vs buffer.`20
- X * Then return without setting up the read attention AST QIO.
- X */
- X`09if (remainder > 0)
- X`09`7B
- X`09`09stack`5BstackIndex`5D.channel = chan;
- X`09`09stack`5BstackIndex`5D.type = NET_RD;
- X`09`09stackIndex++;
- X`09`09ChanTableInfo`5B(chan>>4)`5D->readAstPend = 0;
- X`09`09ChanTableInfo`5B(chan>>4)`5D->readAstDone = 1;
- X#ifdef DNDEBUG
- X`09`09fprintf(stderr, "issueRead: (puesdoread) to channel %d remainder %d\n"
- V, chan, remainder);
- X#endif
- X`09`09return SS$_NORMAL;
- X`09`7D
- X ChanTableInfo`5BshiftChan`5D->base = vmbase;
- X ChanTableInfo`5BshiftChan`5D->delta = vmdelta = vmbase;
- X ChanTableInfo`5BshiftChan`5D->len = vmlen = 0;
- X
- X`09ap.ast.type = NET_RD;
- X`09ap.ast.chan = chan;
- X
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "issueRead: read pending on channel %d\n", chan);
- X#endif
- X`09ChanTableInfo`5BshiftChan`5D->readAstDone = 0;
- X`09ChanTableInfo`5BshiftChan`5D->readAstPend = 1;
- X status = SYS$QIO (0, chan, IO$_READVBLK, &ChanTableInfo`5BshiftChan`
- V5D->read_iosb,`20
- X`09`09`09&readAst, ap.astid, vmbase, MAX_QIO, 0, 0, 0, 0);
- X `09if (VMSFAIL(status)) LIB$SIGNAL(status);
- X`7D
- X
- X`0C
- X/*
- X * linkInit
- X * Routine to intercept the network message and parse it into a node name.
- X */
- Xvoid
- XlinkInit ()
- X`7B
- X`09int i = nb.mbxMsg`5B0`5D + 1;
- X`09int start = i + 1;
- X
- X`09info_cnt = nb.mbxMsg`5Bi`5D;
- X`09ncb = &nb.mbxMsg`5Bstart`5D;
- X`7D
- X
- X`0C
- X/*
- X * linkTerm
- X * Routine to terminate a link (low level - socket_close is high level) give
- Vn
- X * a channel spec or the network message block's unit number.
- X */
- Xvoid
- XlinkTerm(sChan)
- X`09unsigned short sChan;
- X`7B
- X`09int status;
- X`09unsigned short channel;
- X`09unsigned short next;
- X`09int currChannel;
- X`09int i;
- X
- X `09next = 0;
- X`09if (sChan)
- X `09`7B
- X `09`09if (!ChanTableInfo`5BsChan`5D) return;
- X `09`09if (((sChan<<4) == netChannel) && (lisChannel)) netChannel = lisCh
- Vannel;
- X `09if (ChanTableInfo`5BsChan`5D->chanDassgn) return;
- X`09`09next = sChan;
- X`09`09goto bash;
- X`09`7D
- X`09for (i = 0; i < (FD_SETSIZE/NFDBITS); i++)
- X`09`7B
- X`09`09currChannel = (int) allChannels->bits`5Bi`5D;
- X`09`09while (currChannel)
- X`09`09`7B
- X`09`09`09next = (ffs(currChannel) - 1) + (i * NFDBITS);
- X`09`09`09if (ChanTableInfo`5Bnext`5D->unit == nb.unit) goto bash;
- X`09`09`09currChannel &= `7E(1 << next);
- X`09`09`7D
- X`09`7D
- Xbash:
- X`09if ((!next) `7C`7C (next > FD_SETSIZE))
- X `09`09return;
- X`09else
- X`09`7B
- X`09`09channel = next<<4;
- X#ifdef DNDEBUG
- X`09`09fprintf(stderr, "linkTerm: terminating link to %d\n",channel);
- X#endif
- X`09`09status = SYS$DASSGN (channel);
- X`09`09if (VMSFAIL(status)) LIB$SIGNAL(status);
- X `09ChanTableInfo`5Bnext`5D->chanDassgn = 1;
- X`09`7D
- X`7D
- X
- X`0C
- X/*
- X * nameFromPort
- X * A hack to translate the passed port number to a DECnet OBJECT name. Its u
- Vgly
- X * but hey, who asked you?
- X */
- Xstruct dsc$descriptor
- X*nameFromPort (sa)
- X`09struct sockaddr *sa;
- X`7B
- X`09union
- X`09`7B
- X`09`09unsigned short port;
- X`09`09char t`5B2`5D;
- X`09`7D temp;
- X `09int i = 0;
- X
- X`09temp.t`5B0`5D = sa->sa_data`5B1`5D;
- X`09temp.t`5B1`5D = sa->sa_data`5B0`5D;
- X `09for (i = 0; i < Number(transTable); i++)
- X `09`7B
- X `09`09if (transTable`5Bi`5D.port == temp.port)
- X `09`09`7B
- X `09`09`09if (transTable`5Bi`5D.port = X11_PORT)
- X`09`09`09`09x11_dsc.dsc$a_pointer`5B3`5D = 0x30;
- X `09`09`09return transTable`5Bi`5D.object;
- X `09`7D
- X `09`7D
- X/*
- X * Of course - the obligatory special case: used when someone tries to`20
- X * access a X11 "reserved" port 6001-9 (beyond 6009, I don't care!)
- X */
- X`09if ((temp.port > X11_PORT) && (temp.port < X11_PORT + 10))
- X`09`7B
- X`09`09x11_dsc.dsc$a_pointer`5B3`5D = ((temp.port - X11_PORT) + 0x30);
- X`09`09return &x11_dsc;
- X`09`7D`20
- X`09fprintf (stderr, "nameFromPort: unrecognized port request: %d\n");
- X`09return NULL;
- X`7D
- X
- X`0C
- X/*
- X * NCPpredicate
- X * Routine that is passed to qsort.
- X */
- Xstatic int
- XNCPpredicate (c1, c2)
- X `09NCPstruct *c1;
- X `09NCPstruct *c2;
- X`7B
- X `09return (memcmp (c1->nodebuf, c2->nodebuf, MAX(strlen(c1->nodebuf), st
- Vrlen(c2->nodebuf))));
- X`7D
- X
- X`0C
- X/*
- X * NCPinit()
- X * Routine to load the NCP table of node/addresses from its data base using
- V the Network
- X * File Block (NFB$) defined constants for node and address matching of the
- V on-line`20
- X * data base.
- X */
- Xint
- XNCPinit()
- X`7B
- X `09int`09i;
- X `09int`09j;
- X `09int`09add;
- X `09int`09retLen = 0;
- X `09int`09status;
- X `09int`09seg = MAXDNETNODES + 1;
- X`09unsigned short netNCPChan;
- X `09struct io_stat_blk iosb;
- X `09char `09*delta;
- X `09struct nfbdef nfb = `7B NFB$C_FC_SHOW, 0, NFB$C_DB_NDI, NFB$C_OP_EQL,
- X `09`09`09 NFB$C_WILDCARD, NFB$C_WILDCARD, 0, 0, 0,
- X `09`09`09 NFB$C_NDI_NNA, NFB$C_NDI_TAD, NFB$C_ENDOFLIST `7D;
- X `09struct dsc$descriptor nfbDes = `7Bsizeof(nfb), 0, 0, &nfb`7D;
- X `09char *keyArea = DNETALLOC(NFB$C_CTX_SIZE);
- X `09struct dsc$descriptor kaDes = `7BNFB$C_CTX_SIZE, 0, 0, keyArea`7D;
- X `09char *bufArea = DNETALLOC(BUF_QUO);
- X `09struct dsc$descriptor bufDes = `7BBUF_QUO, 0, 0, bufArea`7D;
- X `09struct nfbdef1 *prm;
- X `09struct nfbdef2 *val;
- X
- X `09i = 0;
- X/*
- X * Assign a temporary channel to _NET: to return NCP db info
- X */
- X`09status = SYS$ASSIGN (&net_device, &netNCPChan, 0, 0);
- X`09if (VMSFAIL(status)) LIB$SIGNAL(status);
- X `09LIB$MOVC5 (&zero, NULL, "\0", &kaDes, keyArea);
- X status = SYS$QIOW (0, netChannel, IO$_ACPCONTROL, &iosb, 0, 0,`20
- X `09`09&nfbDes, &kaDes, &retLen, &bufDes, 0, 0);
- X `09if (!VMSFAIL(status)) status = iosb.status;
- X `09if ((VMSFAIL(status)) && (status != SS$_ENDOFFILE)) LIB$SIGNAL(status
- V);
- X/*
- X * Main loop for calling ACPCONTROL on the _NET: device, returning database
- V information.
- X */
- X `09while (status != SS$_ENDOFFILE)
- X `09`7B
- X `09delta = bufArea;
- X `09`09if (seg > MAXDNETNODES)`09`09/* add memory in puesdo realloc mode
- V */
- X `09`09`7B
- X `09`09`09NCPstruct *tmp = (NCPstruct *)`20
- X `09`09`09`09DNETALLOC((i+MAXDNETNODES)*sizeof(NCPstruct));
- X `09`09`09if(!tmp) exit(SS$_INSFMEM);
- X `09`09`09if (pNCP)
- X `09`09`09`7B
- X `09`09`09`09bcopy ((char *) pNCP, (char *) tmp, sizeof(NCPstruct) * i);
- X `09`09`09`09DNETFREE(pNCP);
- X `09`09`09`7D
- X `09`09`09pNCP = tmp;
- X `09`09`09seg = 0;
- X `09`09`7D
- X/*
- X * Loop through the NFB records that the NETACP passed back to this routine.
- X */
- X `09`09for (j = 0; nfb.fldid`5Bj`5D != NFB$C_ENDOFLIST; ++j)
- X `09`09`7B
- X `09`09`09add = 0;
- X `09`09`09prm = (struct nfbdef1 *) &nfb.fldid`5Bj`5D;
- X `09`09`09val = (struct nfbdef2 *) delta;
- X `09`09`09switch (prm->overlay.fields.typ)
- X `09`09`09`7B
- X `09`09`09case NFB$C_TYP_BIT:
- X `09`09`09case NFB$C_TYP_LNG:
- X`09`09`09`09pNCP`5Bi`5D.area = (short) (val->overlay.lngValue / 1024);
- X`09`09`09`09pNCP`5Bi`5D.node = (short) (val->overlay.lngValue % 1024);
- X `09`09`09`09add = sizeof(long);
- X `09`09`09`09break;
- X `09`09`09case NFB$C_TYP_STR:
- X `09`09 `09`09pNCP`5Bi`5D.nodebuf = DNETALLOC (NODNAMSIZ);
- X `09`09`09`09bcopy (&val->overlay.string.strText, pNCP`5Bi`5D.nodebuf,
- X `09`09`09`09`09val->overlay.string.strCount);
- X `09`09`09`09pNCP`5Bi`5D.nodebuf`5Bval->overlay.string.strCount`5D = 0x0;
- X `09`09`09`09add = val->overlay.string.strCount + sizeof(short);
- X `09`09`09`09break;
- X `09`09`09default:
- X `09`09`09`09fprintf(stderr, "NCPinit: unrecognized %d\n",val->overlay.ln
- VgValue);
- X `09`09`09`09add = sizeof(long);
- X `09`09`09`7D
- X `09`09`09delta += add;
- X `09`09`7D
- X#ifdef NCPDEBUG
- X `09`09fprintf(stderr, "NCPinit: %d.%d: %s\n",pNCP`5Bi`5D.area, pNCP`5
- VBi`5D.node, pNCP`5Bi`5D.nodebuf);
- X#endif /* NCPDEBUG */
- X `09`09i++;
- X `09`09seg++;
- X `09status = SYS$QIOW (0, netNCPChan, IO$_ACPCONTROL, &iosb, 0, 0,`20
- X `09`09`09&nfbDes, &kaDes, &retLen, &bufDes, 0, 0);
- X `09`09if (!VMSFAIL(status)) status = iosb.status;
- X `09`09if ((VMSFAIL(status)) && (status != SS$_ENDOFFILE)) LIB$SIGNAL(sta
- Vtus);
- X`09`7D
- X/*
- X * Hopefully we have some nodes here to sort...
- X */
- X `09if (i)
- X `09`7B
- X `09`09NCPtot = i;
- X `09`09qsort ((char *) pNCP, NCPtot, sizeof(NCPstruct), NCPpredicate);
- X `09`09SYS$DASSGN (netNCPChan);
- X#ifdef NCPDEBUG
- X `09`09fprintf(stderr, "NCPinit: %d nodes found\n", NCPtot);
- X#endif
- X `09`7D
- X `09else
- X `09`09fprintf(stderr, "NCPinit: no nodes found!\n");
- X`7D
- X
- X`0C
- X/*
- X * NCPfind
- X * Ah, the luscious jewel of the Nile, itself! This baby looks up a given n
- Vode id
- X * in the NCP table (built in NCPinit()). The id can be in one of three for
- Vms:
- X * 1) DECnet Node Name - Phase IV has a max of 6 characters
- X * 2) DECnet Node Address - up to the max of 63.1023
- X * 3) Unknown Node Address - this sucker comes from the active ethernet addr
- Vess.
- X * It is composed of all numbers (illegal for a node name spec). The rtn
- V can
- X * translate this address to become a DECnet Node Address type above. Th
- Ve fact
- X * that a node comes in as a hybrid active ethernet address name portends
- V that
- X * the node is not known by NCP.
- X * The routine returns a binary value of the address in the sockaddr passed
- V area and
- X * the resolved node name/address in "client".
- X */
- Xint
- XNCPfind (sChan, psock, client)
- X `09unsigned short sChan;
- X `09char`09*psock;
- X `09char `09*client;
- X`7B
- X `09int `09status;
- X `09int `09i;
- X `09short `09node;
- X `09short`09area;
- X `09int`09result;
- X `09int`09last;
- X `09int`09strt;
- X `09char `09*b1;
- X `09char `09*b2;
- X `09char `09*aoff;
- X `09static NCPstruct dum = `7BNULL, 0, 0`7D;
- X `09NCPstruct *pNCPf;
- X `09struct sht
- X `09`7B
- X `09`09union
- X `09`09`7B
- X `09`09`09struct chs
- X `09`09`09`7B
- X `09`09`09`09char c1;
- X `09`09`09`09char c2;
- X `09`09`09`7Dc;
- X `09`09`09short s1;
- X `09`09`7Do;
- X `09`7Ds;
- X
- X `09if (!pNCP) NCPinit();
- X `09if (sChan)
- X `09`7B
- X `09`09aoff = (char *) (psock + sizeof(long));
- X `09`09if (ChanTableInfo`5BsChan`5D)
- X `09`09`7B
- X `09`09`09if (ChanTableInfo`5BsChan`5D->node + ChanTableInfo`5BsChan`5D->
- Varea)
- X `09`09`09`7B
- X `09`09`09if (ChanTableInfo`5BsChan`5D->nodename)
- X `09`09`09`09`7B
- X `09`09 `09`09`09bcopy (ChanTableInfo`5BsChan`5D->nodename, client,`20
- X `09`09`09`09`09`09strlen(ChanTableInfo`5BsChan`5D->nodename)+1);
- X `09`09`09`09`09client`5Bstrlen(ChanTableInfo`5BsChan`5D->nodename)`5D =
- V 0x0;
- X `09`09`09`09`7D
- X `09 `09`09`09else
- X `09 `09`09`09`09sprintf (client, "%d.%d", ChanTableInfo`5BsChan`5D->area,
- V`20
- X `09`09`09`09`09`09ChanTableInfo`5Bi`5D->node);
- X `09`09`09bcopy ((char *) &ChanTableInfo`5BsChan`5D->area, aoff, size
- Vof(short));
- X `09 `09`09`09bcopy ((char *) &ChanTableInfo`5BsChan`5D->node,`20
- X `09`09`09`09`09(char *) (aoff + sizeof(short)), sizeof(short));
- X `09`09`09`09return 0;
- X `09 `09`7D
- X `09`7D
- X `09`7D
- X `09else
- X `09`09aoff = psock;
- X `09if ((!client) `7C`7C (!*client)) fprintf(stderr, "NCPaddr: error no c
- Vlient spec in call\n");
- X`09upper(client);
- X `09if (strchr(client, ':')) *((char *) strchr(client, ':')) = '\0';
- X `09if (isEtherAddr(client)) `09/* it's an active ethernet hybrid address
- V */
- X `09`7B
- X `09`09result = atoi(client);
- X `09`09DNETFREE(client);
- X `09`09client = DNETALLOC(NODNAMSIZ);
- X `09`09sprintf(client, "%d.%d", result/1024, result % 1024);
- X `09`7D
- X `09if (isDnetAddr(client)) `09/* it's a DECnet address (eg., "1.22") */
- X `09`7B
- X `09`09b1 = client;
- X `09`09b2 = strchr (client, '.');
- X `09`09*b2++ = 0x0;
- X `09`09area = (short) atoi(b1);
- X `09`09node = (short) atoi(b2);
- X`09`09sprintf (client, "%d.%d", area, node);
- X `09`09for (i = 0; i < NCPtot; i++)
- X `09`09`7B
- X `09`09`09if ((pNCP`5Bi`5D.area == area) && (pNCP`5Bi`5D.node == node)) b
- Vreak;
- X `09`7D
- X `09`7D
- X `09else `09`09`09`09/* it's a node name (eg., "NCD999") */
- X `09`7B
- X `09`09dum.nodebuf = client;
- X `09`09i = -1;
- X `09`09if((pNCPf = (NCPstruct *) bsearch (&dum, pNCP, NCPtot,`20
- X `09`09`09sizeof(NCPstruct), NCPpredicate)))
- X `09`09`09i = (pNCPf - pNCP);
- X `09`7D
- X/*
- X * We should now have either a valid index into the NCP table or a indicatio
- Vn that
- X * the node name/address is not currently known by this host node.
- X */
- X`09if ((i > -1) && (i < NCPtot))
- X `09`7B
- X `09`09if (pNCP`5Bi`5D.nodebuf)
- X `09`09bcopy (pNCP`5Bi`5D.nodebuf, client, strlen(pNCP`5Bi`5D.nodebuf
- V)+1);
- X `09`09else
- X `09`09`09sprintf (client, "%d.%d", pNCP`5Bi`5D.area, pNCP`5Bi`5D.node);
- X `09`09bcopy ((char *) &pNCP`5Bi`5D.area, aoff, sizeof(short));
- X `09`09bcopy ((char *) &pNCP`5Bi`5D.node, (char *) (aoff + sizeof(short))
- V, sizeof(short));
- X `09`09if (sChan && ChanTableInfo`5BsChan`5D)
- X `09`09`7B
- X `09`09`09if (!ChanTableInfo`5BsChan`5D->nodename)`20
- X `09`09`09`09ChanTableInfo`5BsChan`5D->nodename = DNETALLOC(NODNAMSIZ);
- X `09`09`09bcopy (client, ChanTableInfo`5BsChan`5D->nodename, strlen(clien
- Vt) + 1);
- X `09`09`09ChanTableInfo`5BsChan`5D->nodename`5Bstrlen(client)`5D = 0x0;
- X `09`09`09ChanTableInfo`5BsChan`5D->node = pNCP`5Bi`5D.node;
- X `09`09`09ChanTableInfo`5BsChan`5D->area = pNCP`5Bi`5D.area;
- X `09`09`7D
- X `09`09return 0;
- X `09`7D
- X `09else
- X `09`7B
- X `09`09fprintf(stderr, "NCPfind: %s not found in node lookup\n",client);
- X `09`09return -1;
- X `09`7D
- X`7D
- X
- X`0C
- X/*
- X * netCmdAst
- X * AST routine the fires for incoming network messages.
- X */
- Xvoid
- XnetCmdAst (type)
- X`09int type;
- X`7B
- X`09int i;
- X`09int start;
- X
- X `09ChanTableInfo`5B(mbxChannel>>4)`5D->readAstPend = 0;
- X`09stack`5BstackIndex`5D.channel = netChannel;
- X`09stack`5BstackIndex`5D.type = NET_CMD;
- X`09stackIndex++;
- X`09WAKE_UP_DAMMIT;
- X`7D
- X
- X`0C
- Xvoid
- XnotUsed()
- X`7B
- X`09fprintf (stderr, "Unused message %d detected\n", nb.netCmd);
- X`7D
- X
- X`0C
- X/*
- X * processNetCmd
- X * Routine to process a network message.
- X */
- Xint
- XprocessNetCmd (pChan)
- X `09unsigned short *pChan;
- X`7B
- X `09unsigned short sChan = ((*pChan)>>4);
- X/*
- X * Note that the current netChannel could have disappeared during the interi
- Vm (as
- X * with an xscope connect()ed link with the X11 server), so that issuing the
- V netcmd read
- X * using that channel would be invalid on the next network directive. There
- Vfore, there
- X * must be a provision for testing the passed channel information.
- X */
- X `09if (!ChanTableInfo`5BsChan`5D)
- X `09`7B
- X `09`09if (lisChannel)`20
- X `09`09`09*pChan = lisChannel;
- X `09`09else
- X `09`09`09fprintf(stderr, "processNetCmd: error on invalid netChannel %d\
- Vn", *pChan);
- X `09`7D
- X/* Reissue on the passed or updated channel */
- X`09issueNetCmdRead (*pChan);
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "processNetCmd: netiosb: %d status: %d\n", netiosb.ms
- Vg_len, netiosb.status);
- X#endif
- X
- X`09switch (nb.netCmd)
- X`09`7B
- X`09`09case MSG$_CONNECT :`09
- X#ifdef DNDEBUG
- X `09`09`09`09`09fprintf(stderr, "Link init\n");
- X#endif
- X `09`09`09`09`09linkInit (); return 1; break;
- X case MSG$_ABORT :
- X case MSG$_DISCON :
- X case MSG$_EXIT :
- X case MSG$_PATHLOST :
- X case MSG$_PROTOCOL :
- X case MSG$_THIRDPARTY :
- X case MSG$_TIMEOUT :`09
- X#ifdef DNDEBUG
- X `09`09`09`09`09fprintf(stderr, "processNetCmd: linkTerm\n");
- X#endif
- X`09`09`09`09`09linkTerm ((unsigned short) 0); break;
- X case MSG$_NETSHUT :`09fprintf (stderr, "DECnet shutdown d
- Vetected - exiting\n");`20
- X`09`09`09`09`09exit(1);
- X case MSG$_CONFIRM : `20
- X#ifdef DNDEBUG
- X `09`09`09`09`09fprintf(stderr, "Connection confirmed\n");`20
- X#endif
- X `09`09`09`09`09break;
- X case MSG$_INTMSG : break;
- X case MSG$_REJECT : break;
- X default :`09notUsed(); break;
- X`09`7D
- X`09return 0;
- X`7D
- X
- X`0C
- X/* readAst (ap)
- X * AST routine to update the stack, increment the channel's length variable,
- X * and wake up the server.
- X */
- Xint
- XreadAst (ap)
- X`09struct astblk ap;
- X`7B
- X `09unsigned short sChan = ap.chan>>4;
- X
- X `09if (ChanTableInfo`5BsChan`5D)
- X `09`7B
- X `09`09stack`5BstackIndex`5D.channel = ap.chan;
- X `09`09stack`5BstackIndex`5D.type = ap.type;
- X`09`09stackIndex++;
- X`09`09ChanTableInfo`5BsChan`5D->len = ChanTableInfo`5BsChan`5D->read_iosb.ms
- Vg_len;
- X`09`09ChanTableInfo`5BsChan`5D->readAstPend = 0;
- X`09`09ChanTableInfo`5BsChan`5D->readAstDone = 1;
- X `09`09WAKE_UP_DAMMIT;
- X `09`7D
- X`7D
- X
- X`0C
- X/*
- X * timeoutAst
- X * Routine that fires after the select() timer expires.
- X */
- Xvoid
- XtimeoutAst()
- X`7B
- X`09timerExpired = 1;
- X`09WAKE_UP_DAMMIT;
- X`7D
- X
- X`0C
- X/*
- X * upper
- X * Routine to convert a NUL terminated string to uppercase.
- X */
- Xvoid
- Xupper (s)
- X char *s;
- X`7B
- X int i;
- X char *tp;
- X
- X for (i = 0, tp = s; i < strlen(s); i++, tp++)
- X if (islower(*tp)) *tp = toupper(*tp);
- X`7D
- X
- X`0C
- X/*
- X * EMULATION ROUTINES
- X */
- X
- X`0C
- X/*
- X * accept():
- X * Module to emulate the "acceptance" of a connection over a "listen()"ing c
- Vhannel.
- X * In the current paradigm, only one listening channel is supported (called
- V "lisChannel");
- X * even though the actual network command(s) arrive over the channel assigne
- Vd to the`20
- X * network command mailbox (w/ the NET: device; called "mbxChannel"). The "
- Vchan" being
- X * passed to this and all other socket emulation routines dealing with netwo
- Vrk issues (i.e.,
- X * the only non-client channel) is the listening channel established in sock
- Vet(). All
- X * references to the Net Command Mailbox channel are internal to this librar
- Vy, and`20
- X * are opaque to the upper layer program.
- X */
- Xunsigned short
- Xaccept (chan, psock, psock_l)
- X`09unsigned short chan;
- X`09struct sockaddr *psock;
- X`09long psock_l;
- X`7B
- X int status;
- X`09int dvi_unit;
- X`09unsigned short channel;
- X`09unsigned short sChan;
- X`09struct io_stat_blk iosb;
- X`09struct dsc$descriptor_s ncbd;
- X`09struct`20
- X`09`7B
- X`09`09short buf_len;
- X`09`09short code;
- X`09`09int *ret_code;
- X`09`09int ret_len;
- X`09`09int term;
- X`09`7D dviitm = `7B 4, DVI$_UNIT, &dvi_unit, 0, 0`7D;
- X
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "accept: start - passed chan %d\n", chan);
- X#endif /* DNDEBUG */
- X`09if (!ncb)`20
- X`09`7B
- X`09`09fprintf (stderr, "accept: no ncb received!\n");
- X`09`09return -1;
- X`09`7D
- X`09ncb`5Binfo_cnt`5D = '\0';
- X ncbd.dsc$w_length = info_cnt;
- X ncbd.dsc$a_pointer = ncb;
- X ncbd.dsc$b_dtype = DSC$K_DTYPE_T;
- X ncbd.dsc$b_class = DSC$K_CLASS_S;
- X
- X `09if (!mbx_created)
- X `09`7B
- X `09`09fprintf(stderr, "accept: error - mailbox not created yet\n");
- X `09`09exit();
- X `09`7D
- X status = SYS$ASSIGN (&net_device, &channel, 0, &netcmd_mbx);
- X`09if (VMSFAIL(status)) LIB$SIGNAL(status);
- X`09status = SYS$GETDVI (0, channel, 0, &dviitm, &iosb, 0, 0, 0);
- X`09if (VMSFAIL(status)) LIB$SIGNAL(status);
- X `09sChan = channel>>4;
- X`09clearChanTable ((sChan));
- X`09ChanTableInfo`5B(sChan)`5D->unit = dvi_unit;
- X`09ChanTableInfo`5B(sChan)`5D->nodename = DNETALLOC (NODNAMSIZ);
- X`09bcopy ((char *) ncb, ChanTableInfo`5B(sChan)`5D->nodename, info_cnt);
- X `09ChanTableInfo`5B(sChan)`5D->user = (strchr(ChanTableInfo`5B(sChan)`5D
- V->nodename, '=') + 1);
- X `09*((char *) strchr(ChanTableInfo`5B(sChan)`5D->nodename,':') + 2) = '\
- V0';
- X `09*((char *) strchr(ChanTableInfo`5B(sChan)`5D->user,'/')) = '\0';
- X`09FD_SET(channel, allChannels);
- X#ifdef DNDEBUG
- X`09fprintf(stderr, "accept: from Node: %s User: %s on channel %d\n",
- X `09`09ChanTableInfo`5B(sChan)`5D->nodename, ChanTableInfo`5B(sChan)`5D->
- Vuser, channel);
- X#endif
- X status = SYS$QIOW (0, channel, IO$_ACCESS, &iosb, 0, 0, 0, &ncbd, 0,
- V 0, 0, 0);
- X`09if(!VMSFAIL(status) && !VMSFAIL(iosb.status))
- X`09`7B
- X`09`09ncb = NULL;
- X`09 return channel;
- X`09`7D
- X`09if (VMSFAIL(status)) LIB$SIGNAL (status);
- X`09if (VMSFAIL(iosb.status)) LIB$SIGNAL(iosb.status);
- X`09return -1;
- X`7D
- X
- X`0C
- X/*
- X * B routines: bcmp, bcopy, bzero
- X * These routines are declared here in function form to provide
- X * a global linker resolution for references in upper level code.
- X */
- Xint
- Xbcmp (s1, s2, l)
- X`09char *s1;
- X`09char *s2;
- X`09int l;
- X`7B
- X`09return (BCMP(s1, s2, l));
- X`7D
- X
- X`0C
- Xvoid *
- Xbcopy (s, d, l)
- X`09char *s;
- X`09char *d;
- X`09int l;
- X`7B
- X`09return BCOPY(s, d, l);
- X`7D
- X
- X`0C
- X/*
- X * bind():
- X * bind the NET channel to the correct object name.
- X */
- Xint
- Xbind (chan, sa, sa_len)
- X`09unsigned short chan;
- X`09struct sockaddr *sa;
- X`09unsigned int sa_len;
- X`7B
- X`09int status;
- X`09struct io_stat_blk iosb;
- X`09struct dsc$descriptor_s nfbd;
- X`09struct dsc$descriptor_s *object_name;
- X
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "bind: start - passed chan %d\n", chan);
- X#endif /* DNDEBUG */
- X nfbd.dsc$w_length = sizeof(nfb);
- X nfbd.dsc$a_pointer = &nfb;
- X nfbd.dsc$b_dtype = DSC$K_DTYPE_T;
- X nfbd.dsc$b_class = DSC$K_CLASS_S;
- X/*
- X * Bind to the declare channel in the ChanTableInfo struct.
- X */
- X`09object_name = nameFromPort (sa);
- X`09status = SYS$QIOW (0, chan, IO$_ACPCONTROL, &iosb, 0, 0, &nfbd, object_na
- Vme, 0, 0, 0, 0);
- X`09if (VMSFAIL(status) `7C`7C VMSFAIL(iosb.status)) return -1;
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "bind: on channel %d to %s\n", chan, object_name->dsc
- V$a_pointer);
- X#endif
- X`09return 0;
- X`7D
- X
- X`0C
- Xint
- Xbzero (buf, size)
- X`09char *buf;
- X`09int size;
- X`7B
- X`09return (BZERO(buf, size));
- X`7D
- X
- X`0C
- X#ifdef NOTDEF
- X/*
- X * connect():
- X * supports connecting to a "socket" given the network channel (from socket(
- V))
- X */
- Xint
- Xconnect (chan, name, namelen)
- X`09unsigned short chan;
- X`09struct sockaddr *name;
- X`09unsigned int namelen;
- X`7B
- X`09int`09`09status;
- X`09unsigned short`09objlen;
- X`09char *pncb;
- X`09struct dsc$descriptor ncb_desc;
- X`09static struct io_stat_blk iosb;
- X`09struct dsc$descriptor_s *objdsc;
- X `09static char *objstr = NULL;
- X `09char hname`5B32`5D;
- X `09int l = 0;
- X
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "connect: start - passed chan %d\n", chan);
- X#endif /* DNDEBUG */
- X `09if (!objstr) objstr = DNETALLOC(NCBSIZE);
- X if (!(pncb = initNCB(name, &objlen, TASKOBJECT, NULL)))`20
- X `09`7B
- X `09`09char *a = objstr;
- X `09`09short *area = &name->sa_data`5B2`5D;
- X `09`09short *node = &name->sa_data`5B4`5D;
- X
- X `09`09objdsc = nameFromPort (name);
- X `09`09BCOPY(TASKOBJECT, a, strlen(TASKOBJECT));
- X `09`09a += strlen(TASKOBJECT);
- X `09`09BCOPY(objdsc->dsc$a_pointer, a, strlen(objdsc->dsc$a_pointer));
- X `09`09a+= strlen(objdsc->dsc$a_pointer);
- X `09`09*a = 0x0;
- X `09`09sprintf (hname, "%d.%d::", *area, *node);
- X `09`09pncb = initNCB(name, &objlen, objstr, hname);
- X `09`7D
- X `09ncb_desc.dsc$w_length = objlen;
- X ncb_desc.dsc$a_pointer = pncb;
- X ncb_desc.dsc$b_dtype = DSC$K_DTYPE_T;
- X ncb_desc.dsc$b_class = DSC$K_CLASS_S;
- X
- X status = SYS$QIOW (0, chan, IO$_ACCESS, &iosb, 0, 0, 0, &ncb_desc, 0
- V, 0, 0, 0);
- X if (!VMSFAIL(status)) status = iosb.status;
- X if (!VMSFAIL(status))
- X`09`7B
- X#ifdef DNDEBUG
- X`09`09fprintf(stderr, "connect: Connection to %s on channel %d\n", pncb, cha
- Vn);
- X#endif
- X `09`09DNETFREE (pncb);
- X return 0;
- X`09`7D
- X else
- X LIB$SIGNAL (status);
- X`09DNETFREE (pncb);
- X`09return -1;
- X`7D
- X#endif /* NOTDEF */
- X
- X`0C
- X/*
- X * connect():
- X * supports connecting to a "socket" given the network channel (from socket(
- V))
- X */
- Xint
- Xconnect (chan, name, namelen)
- X unsigned short chan;
- X struct sockaddr *name;
- X unsigned int namelen;
- X`7B
- X int status;
- X unsigned short objlen;
- X char *pncb;
- X struct dsc$descriptor ncb_desc;
- X static struct io_stat_blk iosb;
- X struct dsc$descriptor_s *objdsc;
- X char *objstr = DNETALLOC(NCBSIZE);
- X char *hname;
- X int l = 0;
- X char *a;
- X short *port = &name->sa_data`5B0`5D;
- X short *area = &name->sa_data`5B2`5D;
- X short *node = &name->sa_data`5B4`5D;
- X
- X#ifdef DNDEBUG
- X fprintf(stderr, "connect: start - passed chan %d port %d addr %d.%d\
- Vn",
- X chan, *port, *area, *node);
- X#endif /* DNDEBUG */
- X BCOPY (TASKOBJECT, objstr, strlen(TASKOBJECT));
- X hname = NULL;
- X if ((objdsc = nameFromPort (name)))
- X `7B
- X hname = DNETALLOC(32);
- X a = objstr + strlen(TASKOBJECT);
- X BCOPY(objdsc->dsc$a_pointer, a, strlen(objdsc->dsc$a_pointer
- V));
- X a+= strlen(objdsc->dsc$a_pointer);
- X *a = 0x0;
- X sprintf (hname, "%d.%d::", *area, *node);
- X `7D
- X pncb = initNCB(name, &objlen, objstr, hname);
- X if (hname) DNETFREE(hname);
- X ncb_desc.dsc$w_length = objlen;
- X ncb_desc.dsc$a_pointer = pncb;
- X ncb_desc.dsc$b_dtype = DSC$K_DTYPE_T;
- X ncb_desc.dsc$b_class = DSC$K_CLASS_S;
- X
- X status = SYS$QIOW (0, chan, IO$_ACCESS, &iosb, 0, 0, 0, &ncb_desc, 0
- V, 0, 0, 0);
- X if (!VMSFAIL(status)) status = iosb.status;
- X if (!VMSFAIL(status))
- X `7B
- X#ifdef DNDEBUG
- X fprintf(stderr, "connect: Connection to %s on channel %d\n",
- V pncb, chan);
- X#endif
- X DNETFREE (pncb);
- X return 0;
- X `7D
- X else
- X LIB$SIGNAL (status);
- X DNETFREE (pncb);
- X return -1;
- X`7D
- X
- X`0C
- X/*
- X * ffs
- X * Emulates the find first set function for UNIX.
- X */
- Xint
- Xffs (lw)
- X`09int lw;
- X`7B
- X`09int fp;
- X`09int sp = 0;
- X`09int status;
- X`09int sz = sizeof(lw)*BITSPERBYTE;
- X
- X`09status = lib$ffs(&sp, &sz, &lw, &fp);
- X`09if (VMSFAIL(status))
- X`09`7B
- X`09`09LIB$SIGNAL(status);
- X`09`09exit();
- X`09`7D
- X`09return ++fp;
- X`7D
- X
- X`0C
- X/*
- X * getdtablesize
- X * Routine to return the given size of the file descriptor table (channel ta
- Vble).
- X */
- Xint
- Xgetdtablesize()
- X`7B
- X`09return FD_SETSIZE; /* *** should be CHANNELCNT in SYSGEN */
- X`7D
- X
- X`0C
- X/*
- X * gethostbyaddr
- X * Socket library emulation routine to return the host name given a (DECnet)
- X * network address.
- X */
- Xstruct hostent *
- Xgethostbyaddr (addr, length, family)
- X`09unsigned char *addr;
- X`09unsigned int length;
- X`09unsigned int family;
- X`7B
- X`09static struct hostent *t = NULL;
- X
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "gethostbyaddr: start\n");
- X#endif /* DNDEBUG */
- X `09if (!t)
- X `09`7B
- X `09`09t = DNETALLOC (sizeof(struct hostent));
- X `09`09t->h_name = DNETALLOC(NODNAMSIZ);
- X`09`09t->h_aliases = NULL;
- X `09`09t->h_addrtype = AF_DECnet;`20
- X`09`09t->h_length = sizeof(long);
- X`09`09t->h_addr_list = DNETALLOC (sizeof(long));
- X`09`09t->h_addr_list`5B0`5D = DNETALLOC (sizeof(long));
- X`09`09t->h_cputype = DNETALLOC (strlen(CPUTYPE)+1);
- X`09`09t->h_opsys = DNETALLOC (strlen(OPSYS)+1);
- X`09`09bcopy (CPUTYPE, t->h_cputype, strlen(CPUTYPE));
- X`09`09bcopy (OPSYS, t->h_opsys, strlen(OPSYS));
- X `09`7D
- X#ifdef DNDEBUG
- X `09fprintf (stderr, "gethostbyaddr: DECnet address %d.%d\n",`20
- X `09`09(short) *addr, (short) (*(addr+sizeof(short))));
- X#endif
- X `09sprintf (t->h_name, "%d.%d", (short) *addr, (short) *(addr+sizeof(sho
- Vrt)));
- X `09if (NCPfind (0, t->h_addr_list`5B0`5D, t->h_name) < 0)
- X `09`7B
- X `09`09h_errno = HOST_NOT_FOUND;
- X `09`09return 0;
- X `09`7D
- X`09return t;
- X`7D
- X
- X`0C
- X/*
- X * gethostbyname
- X * Routine to return the network address of a given node name.
- X */
- Xstruct hostent *
- Xgethostbyname (name)
- X`09char *name;
- X`7B
- X`09static struct hostent *t = NULL;
- X
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "gethostbyname: start\n");
- X#endif /* DNDEBUG */
- X `09if (!t)
- X `09`7B
- X `09`09t = DNETALLOC (sizeof(struct hostent));
- X `09`09t->h_name = DNETALLOC(NODNAMSIZ);
- X`09`09t->h_aliases = NULL;
- X`09`09t->h_addrtype = AF_DECnet;
- X`09`09t->h_length = sizeof(long);
- X`09`09t->h_addr_list = DNETALLOC (sizeof(long));
- X`09`09t->h_addr_list`5B0`5D = DNETALLOC (sizeof(long));
- X`09`09t->h_cputype = DNETALLOC (strlen(CPUTYPE)+1);
- X`09`09t->h_opsys = DNETALLOC (strlen(OPSYS)+1);
- X`09`09bcopy (CPUTYPE, t->h_cputype, strlen(CPUTYPE));
- X`09`09bcopy (OPSYS, t->h_opsys, strlen(OPSYS));
- X `09`7D
- X`09bcopy (name, t->h_name, strlen(name)+1);
- X `09if (NCPfind (0, t->h_addr_list`5B0`5D, t->h_name) < 0)
- X `09`7B
- X `09`09h_errno = HOST_NOT_FOUND;
- X `09`09return 0;
- X `09`7D
- X`09return t;
- X`7D
- X
- X`0C
- X/*
- X * gethostname
- X * Routine to return the host node name.
- X */
- Xint
- Xgethostname (hname, l)
- X `09char *hname;
- X `09int l;
- X`7B
- X short retlen = 0;
- X
- X unsigned short iosb`5B4`5D;
- X struct
- X `7B
- X unsigned short id_buflen;
- X unsigned short id_itmcod;
- X int *id_scsid;
- X unsigned short *id_retlen;
- X int listend;
- X `7D itmlst = `7Bl, SYI$_NODENAME, hname, &retlen, 0`7D;
- X
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "gethostname: start\n");
- X#endif /* DNDEBUG */
- X SYS$GETSYIW (0, 0, 0, &itmlst, iosb, 0, 0);
- X hname`5Bretlen`5D = '\0';
- X`09return 0;
- X`7D
- X
- X`0C
- X/*
- X * getpeername
- X * Routine to return the node address (DECnet) associated with a given chann
- Vel.
- X */
- Xint
- Xgetpeername (chan, psock, psock_l)
- X`09unsigned short chan;
- X`09struct sockaddr *psock;
- X`09long *psock_l;
- X`7B
- X `09unsigned short sChan = chan>>4;
- X
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "getpeername: start\n");
- X#endif /* DNDEBUG */
- X`09psock->sa_family = AF_DECnet;
- X `09if (!ChanTableInfo`5BsChan`5D) return -1;
- X `09*psock_l = sizeof(long);
- X`09return NCPfind (sChan, psock, ChanTableInfo`5BsChan`5D->nodename);
- X`7D
- X
- X`0C
- X/*
- X * gettimeofday
- X * Routine to return the time in secs and millisecs
- X */
- Xint
- Xgettimeofday (timev)
- X`09struct timeval *timev;
- X`7B
- X`09static timeb_t t;
- X
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "gettimeofday: start\n");
- X#endif /* DNDEBUG */
- X`09ftime (&t);
- X`09timev->tv_sec = t.time;
- X`09timev->tv_usec = t.millitm * 1000;
- X
- X`09return 0;
- X`7D
- X
- X`0C
- Xint
- Xhtonl (i)
- X`09int i;
- X`7B
- X int t1;
- X`09int t2;
- X
- X t2 = i;`20
- X ((char *)&t1)`5B0`5D = ((char *)&t2)`5B3`5D;
- X`09((char *)&t1)`5B1`5D = ((char *)&t2)`5B2`5D;
- X ((char *)&t1)`5B2`5D = ((char *)&t2)`5B1`5D;
- X`09((char *)&t1)`5B3`5D = ((char *)&t2)`5B0`5D;
- X
- X`09return t1;
- X`7D
- X
- X`0C
- Xunsigned short
- Xhtons (i)
- X`09unsigned short i;
- X`7B
- X unsigned short t1;
- X`09unsigned short t2;
- X
- X t2 = i;
- X ((char *)&t1)`5B0`5D = ((char *)&t2)`5B1`5D;
- X`09((char *)&t1)`5B1`5D = ((char *)&t2)`5B0`5D;
- X
- X return t1;
- X`7D
- X
- X`0C
- X/*
- X * inet_addr
- X * Routine to translate the network address into a longword value.
- X */
- Xint
- Xinet_addr (address)
- X`09char *address;
- X`7B
- X`09char`09*a;
- X`09char`09*b`5B4`5D;
- X `09char `09*tmpvm;
- X`09int`09i;
- X`09int`09j = 0;
- X`09int`09out;
- X
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "inet_addr: start\n");
- X#endif /* DNDEBUG */
- X `09if(isalpha(*address)) return -1;
- X`09b`5Bj++`5D = address;
- X `09tmpvm = DNETALLOC(strlen(address));
- X `09bcopy (address, tmpvm, strlen(address));
- X`09for (i = 0, a = tmpvm; i < strlen(address); i++, a++)
- X`09`7B
- X`09`09if ((*a == '.') `7C`7C (*a = ':'))
- X`09`09`7B
- X`09`09`09*a = '\0';
- X`09`09`09b`5Bj++`5D = a + 1;
- X`09`09`7D
- X`09`7D
- X/* *** Needs to read all network address types (?) */
- X`09a = (char *) &out;
- X`09for (i = 0; i < j; i++, a++)
- X`09`09*a = (char) atoi(b`5Bi`5D);
- X`09DNETFREE(tmpvm);
- X`09return (htonl(out));
- X`7D
- X
- X`0C
- X/*
- X * listen():
- X * Module to emulate a "listen" placed on the passed channel. In the case o
- Vf
- X * DECnet, we'll interpret this to mean issue a read to the network command
- X * mailbox associated with the NET: device. Right now I don't really have a
- X * use for the back log queue length, but we'll keep it around anyhow.
- X */
- Xint
- Xlisten (chan, bl)
- X`09unsigned short chan;
- X`09unsigned int bl;
- X`7B
- X`09int`09status;
- X
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "listen: start - passed chan %d\n", chan);
- X#endif /* DNDEBUG */
- X `09lisChannel = netChannel;
- X`09ChanTableInfo`5B(chan>>4)`5D->backLogQueueLength = bl; /* *** */
- X`09if (!ChanTableInfo`5B(chan>>4)`5D->readAstPend)
- X`09`7B
- X`09`09DISABLE_ASTS;`09`09/* don't forget this or we're toast! */
- X`09`09status = issueNetCmdRead (chan);
- X`09`09ChanTableInfo`5B(chan>>4)`5D->readAstPend = 1;
- X`09`09if (VMSFAIL(status))
- X`09`09`7B
- X`09`09`09LIB$SIGNAL (status);
- X`09`09`09exit(0);
- X`09`09`7D
- X`09`7D
- X`09return 0;
- X`7D
- X
- X`0C
- X/*
- X *
- X * SELECT for DECnet
- X * Note:
- X *`09readfds should contain the fd for the _NET: device for new connections.
- X * `09writefds will be returned from outstanding write AST notification.
- X *
- X * Return:
- X * `09int value specifying the number of channels ready.
- X *
- X */
- Xint
- Xselect (width, readfds, writefds, exceptfds, timeout)
- X`09int width;
- X`09fd_set *readfds;
- X`09fd_set *writefds;
- X`09fd_set *exceptfds;
- X`09struct timeval *timeout;
- X`7B
- X`09int i;
- X`09int j;
- X`09int k;
- X`09int lw;
- X`09char *plw;
- X`09int delta`5B2`5D;
- X`09int totset;
- X`09int fd_group;
- X`09int numBytes = width/NBBY;
- X`09int status;
- X `09int bit;
- X `09int pos;
- X`09fd_set readMask;
- X`09fd_set writeMask;
- X`09fd_set exceptMask;
- X
- X`09stackIndex = 0;
- X`09timerExpired = 0;
- X`09totset = 0;
- X
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "select: start\n");
- X#endif /* DNDEBUG */
- X/*
- X * Optimized channel listening setup loop.
- X */
- X`09for (fd_group = 0, i = 0, j = 0; j < width; ++fd_group)
- X`09`7B
- X`09`09if (readfds->bits`5Bfd_group`5D)
- X`09`09`7B
- X `09`09`09pos = -1;
- X`09`09`09while( _FFS(pos+1, ((NBLW-1)-pos), &readfds->bits`5Bfd_group`5D, &p
- Vos))
- X `09`09`09`7B
- X `09`09`09`09bit = j + pos;
- X `09`09`09`09if (!ChanTableInfo`5Bbit`5D)
- X `09`09`09`09`7B
- X `09`09`09`09`09errno = EBADF;
- X `09`09`09`09`09return -1;
- X `09`09`09`09`7D
- X `09`09`09`09if (!ChanTableInfo`5Bbit`5D->readAstPend)`20
- X `09`09`09`09`09status = issueRead ((bit<<4));
- X`09`09`09`7D
- X`09`09`7D
- X`09`09else
- X`09`09`09j += NBLW;
- X`09`7D
- X`09LIB$MOVC5(&zero, NULL, "\0", &numBytes, (char *) &readMask);
- X`09if (writefds) LIB$MOVC5(&zero, NULL, "\0", &numBytes, (char *) &writeMask
- V);
- X/*
- X`09This is a future enhancement, currently omitted for time considerations:
- X`09if (exceptfds) LIB$MOVC5(&zero, NULL, "\0", &numBytes, (char *) &exceptMa
- Vsk);
- X*/
- X`09if (!stackIndex)
- X`09`7B
- X`09`09int sec = 0;
- X`09`09int usec = 0;
- X
- X`09`09if (timeout)
- X`09`09`7B
- X`09`09`09sec = timeout->tv_sec;
- X`09`09`09usec = timeout->tv_usec;
- X`09`09`7D
- X`09`09if ((timeout) && (!(sec + usec)))
- X`09`09`09timerExpired = 1;
- X`09`09else
- X`09`09`7B
- X/*
- X * Here's the juicy part of select(). Check for a timeout value to be setup
- V. Then
- X * enable ASTs, check for any I/O completion, and disable ASTs.
- X */
- X`09`09`09if (timeout)
- X`09`09`09`7B
- X`09`09`09`09delta`5B0`5D = (sec * -10000000) + (usec * -10);
- X`09`09`09`09delta`5B1`5D = -1;
- X`09`09`09`09SYS$SETIMR ( 0, delta, timeoutAst, timeout, 0);
- X`09`09`09`7D
- X`09`09`09ENABLE_ASTS;
- X`09`09`09HIBERNATE;
- X`09`09`09DISABLE_ASTS;
- X`09`09`09if ((!timerExpired) && (timeout))
- X`09`09`09`7B
- X`09`09`09`09status = SYS$CANTIM (timeout, 0);
- X`09`09`09`09if (VMSFAIL(status)) LIB$SIGNAL(status);
- X`09`09`09`7D
- X`09`09`7D
- X`09`7D
- X`09if (!stackIndex && !timerExpired)
- X`09`09fprintf (stderr, "select: error - stackIndex 0 timerExpired 0\n");
- X/*
- X * Now check the ast stack for completions. Mark any channel's with I/O pen
- Vding
- X * on the internal fd masks.
- X */
- X`09if ((timerExpired) && (!stackIndex))
- X`09`7B
- X`09`09for (i = 0, lw = 0, fd_group = 0; lw < width; lw+=NBLW, fd_group++)
- X`09`09`7B
- X`09`09`09if (readfds)
- X`09`09`09`09readfds->bits`5Bfd_group`5D = 0;
- X`09`09`09if (writefds)
- X`09`09`09`09writefds->bits`5Bfd_group`5D = 0;
- X`09`09`09if (exceptfds)
- X`09`09`09`09exceptfds->bits`5Bfd_group`5D = 0;
- X`09`09`7D
- X`09`7D
- X`09else
- X`09`7B
- X#ifdef DNDEBUG
- X`09`09fprintf(stderr, "select: stackIndex %d\n", stackIndex);
- X#endif
- X`09`09for (i = 0; i < stackIndex; i++)
- X`09`09`7B
- X/*
- X *`09Note, read_iosb.status = SS$_LINKABORT, when the line dies!`20
- X */
- X`09`09`09if ((stack`5Bi`5D.type == NET_CMD) `7C`7C (ChanTableInfo`5B(stack`5
- VBi`5D.channel>>4)`5D))
- X`09`09`09`7B
- X`09`09`09switch (stack`5Bi`5D.type)
- X`09`09`09`7B
- X`09`09`09case NET_CMD :
- X`09`09`09`7B
- X`09`09`09`09if (processNetCmd(&stack`5Bi`5D.channel))
- X`09`09`09`09`7B
- X`09`09`09`09`09FD_SET(stack`5Bi`5D.channel, &readMask);
- X`09`09`09`09`09totset++;
- X`09`09`09`09`7D
- X`09`09`09`09break;
- X`09`09`09`7D
- X`09`09`09case NET_RD :
- X`09`09`09`7B
- X`09`09`09`09if (readfds)
- X`09`09`09`09`7B
- X`09`09`09`09`09if (FD_ISSET(stack`5Bi`5D.channel, readfds))
- X`09`09`09`09`09`7B
- X`09`09`09`09`09`09FD_SET(stack`5Bi`5D.channel, &readMask);
- X`09`09`09`09`09`09totset++;
- X`09`09`09`09`09`7D
- X`09`09`09`09`7D
- X`09`09`09`7D
- X`09`09`09case NET_WRT :`20
- X`09`09`09`7B
- X`09`09`09`09if (writefds)
- X`09`09`09`09`7B
- X`09`09`09`09`09if (FD_ISSET(stack`5Bi`5D.channel, writefds))
- X`09`09`09`09`09`7B
- X`09`09`09`09`09`09FD_SET(stack`5Bi`5D.channel, &writeMask);
- X`09`09`09`09`09`09totset++;
- X`09`09`09`09`09`7D
- X`09`09`09`09`7D
- X`09`09`09`7D
- X/*
- X *`09`09`09case NET_CMD :`20
- X *`09`09`09`7B
- X *`09`09`09`09if (exceptfds)
- X *`09`09`09`09`7B
- X *`09`09`09`09`09if (FD_ISSET(stack`5Bi`5D.channel, exceptfds))
- X *`09`09`09`09`09`7B
- X *`09`09`09`09`09`09FD_SET(stack`5Bi`5D.channel, &exceptMask);
- X *`09`09`09`09`09`09totset++;
- X *`09`09`09`09`09`7D
- X *`09`09`09`09`7D
- X *`09`09`09`7D
- X */
- X`09`09`09`7D /* switch */
- X`09`09`09`7D /* LINKABORT if */
- X`09`09`09else
- X`09`09`09`7B
- X`09`09`09`09errno = EBADF;
- X`09`09`09`09totset = -1;
- X`09`09`09`09break;
- X`09`09`09`7D
- X`09`09`7D
- X/*
- X * Now "and" the two tables together to create the returned fd table(s).
- X */
- X`09`09for (lw = 0, fd_group = 0; lw < width; lw+=NBLW, ++fd_group)
- X`09`09`7B
- X`09`09`09if (readfds)
- X`09`09`09`09readfds->bits`5Bfd_group`5D &= readMask.bits`5Bfd_group`5D;
- X`09`09`09if (writefds)
- X`09`09`09`09writefds->bits`5Bfd_group`5D &= writeMask.bits`5Bfd_group`5D;
- X`09`09`09if (exceptfds)
- X`09`09`09`09exceptfds->bits`5Bfd_group`5D &= exceptMask.bits`5Bfd_group`5D;
- X`09`09`7D
- X`09`7D
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "select: returning %d\n", totset);
- X#endif
- X`09return totset;
- X`7D
- X
- X`0C
- X/*
- X * setsockopt
- X * Stub routine for emulation purposes right now.
- X */
- Xint
- Xsetsockopt (chan, level, optname, optval, optlen)
- X`09unsigned short chan;
- X`09unsigned long level;
- X`09unsigned long optname;
- X`09char *optval;
- X`09unsigned long optlen;
- X`7B
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "setsockopt: start - passed chan %d\n", chan);
- X#endif /* DNDEBUG */
- X`09ChanTableInfo`5B(chan>>4)`5D->o`5Boptname`5D.option = optval;
- X`09ChanTableInfo`5B(chan>>4)`5D->o`5Boptname`5D.optionlen = optlen;
- X`09return 0;
- X`7D
- X
- X`0C
- X/*
- X * socket():
- X * Two channels are created as a result of this call,
- X * 1) mbxChannel - the network command mailbox throught which all low level`
- V20
- X *`09`09 connection information and management crap flows
- X * 2) netChannel - the channel to the NET device, used by a server to est. a
- V`20
- X *`09`09 DECnet object; used by a client to connect and perform I/O on
- X *`09`09 the aforementioned object.
- X * Note: only netChannel is "seen" by the calling layer program.
- X */
- Xunsigned short
- Xsocket (addrfam, type, proto)
- X`09unsigned long addrfam;
- X`09unsigned long type;
- X`09unsigned long proto;
- X`7B
- X`09int status;
- X
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "socket: start\n");
- X#endif /* DNDEBUG */
- X `09connectNet ();
- X`09if (!ChanTableInfo`5B(netChannel>>4)`5D) clearChanTable((netChannel>>4));
- X`09if (!ChanTableInfo`5B(mbxChannel>>4)`5D) clearChanTable((mbxChannel>>4));
- X`09return netChannel;
- X`7D
- X
- X`0C
- X/*
- X * socket_close
- X * Emulation routine for closing channels.
- X */
- Xint
- Xsocket_close (chan)
- X unsigned short chan;
- X`7B
- X`09unsigned short shiftChan = chan>>4;
- X
- X#ifdef DNDEBUG
- X`09fprintf(stderr, "socket_close: linkTerm %d\n", chan);
- X#endif
- X`09linkTerm (shiftChan);
- X`09clearChanTable (shiftChan);
- X`09return 0;
- X`7D
- X
- X`0C
- X/*
- X * socket_ioctl
- X * Emualtion routine for stubbing purposes only.
- X */
- Xint
- Xsocket_ioctl (chan, request, argp)
- X`09unsigned short chan;
- X`09unsigned int request;
- X`09char *argp;
- X`7B
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "socket_ioctl: start - passed chan %d\n", chan);
- X#endif /* DNDEBUG */
- X`09if (chan > FD_SETSIZE)
- X`09`09return -1;
- X`09ChanTableInfo`5B(chan>>4)`5D->type = request;
- X`7D
- X
- X`0C
- X/*
- X * socket_perror
- X * Emulation for the same. Relatively weak right now in that it ignores err
- Vno
- X * values.
- X */
- Xvoid
- Xsocket_perror (s)
- X`09char *s;
- X`7B
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "socket_perror: start\n");
- X#endif /* DNDEBUG */
- X`09fprintf(stdout, "%s", s);
- X`7D
- X
- X`0C
- X/*
- X * socket_read (chan, target, length)
- X * Routine to emulate the a streamed read on a socket. Currently the read
- X * supports ONLY nonblocking I/O. That is, the read will complete is there
- X * is ANYTHING in the channel buffer not depending on the passed "length" fi
- Veld.
- X * With blocking I/O, the read will wait until the length field request has
- X * been statisfied.
- X */
- Xint
- Xsocket_read (chan, target, l)
- X unsigned short chan;
- X char *target;
- X int l;
- X`7B
- X`09int`09shiftChan = chan>>4;
- X`09char *vmbase = ChanTableInfo`5BshiftChan`5D->base;
- X`09char *vmdelta = ChanTableInfo`5BshiftChan`5D->delta;
- X`09int vmlen = ChanTableInfo`5BshiftChan`5D->len;
- X int remainder;
- X char *savtarget;
- X int movetot;
- X`09int`09pass;
- X`09int`09status;
- X`09struct io_stat_blk iosb;
- X
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "socket_read: start - passed chan %d\n", chan);
- X#endif /* DNDEBUG */
- X`09if (!ChanTableInfo`5BshiftChan`5D) return -1;
- X if (!l) return l;
- X
- X savtarget = target;
- X movetot = 0;
- X/* Check the size of the channel's read buffer `09`09`09*/
- X remainder = (vmbase + vmlen) - vmdelta;
- X/*
- X * If this routine was called after an AST read notification from select() a
- Vnd the
- X * read in buffer size was 0, return 0 now so that a QIO is *not* performed.
- V In the
- X * case of a calling program that does *not* use select/AST's, readAstDone w
- Vill remain 0.
- X */
- X `09if (ChanTableInfo`5BshiftChan`5D->readAstDone)
- X `09`7B
- X `09`09ChanTableInfo`5BshiftChan`5D->readAstDone = 0;
- X `09`09if(!remainder) return 0;
- X `09`7D
- X/*
- X * See if the VM area exists and, if so, is there anything in there? If yes
- V again,
- X * move it, update VM pointers, and return. (Non blocking I/O).
- X */
- X if (remainder)
- X `7B
- X`09`09pass = MIN(remainder, l);
- X bcopy (vmdelta, target, pass);
- X movetot += pass;
- X savtarget += pass;
- X vmdelta += pass;
- X`09`09ChanTableInfo`5BshiftChan`5D->base = vmbase;
- X`09`09ChanTableInfo`5BshiftChan`5D->delta = vmdelta;
- X`09`09ChanTableInfo`5BshiftChan`5D->len = vmlen;
- X`09`09return movetot;
- X `7D
- X/*
- X * VM memory area is empty, so fill it up and update the pointers.
- X */
- X`09if (!remainder)
- X`09`7B
- X status = SYS$QIOW (0, chan, IO$_READVBLK, &iosb, 0, 0, vmbas
- Ve,
- X MAX_QIO, 0, 0, 0, 0);
- X if (!(status & STS$M_SUCCESS) `7C`7C !(iosb.status & STS$M_S
- VUCCESS))
- X return -1;
- X`09`09vmdelta = vmbase;
- X vmlen = iosb.msg_len;
- X#ifdef DNDEBUG
- X `09`09fprintf(stderr,"socket_read: iosb.len %d on channel %d\n",iosb.msg
- V_len, chan);
- X#endif
- X`09`09if (vmlen < l) fprintf(stderr, "socket_read: returned < request %d/%d\
- Vn", vmlen, l);
- X `7D
- X`09pass = MIN(vmlen, l);
- X bcopy (vmdelta, savtarget, pass);
- X movetot += pass;
- X vmdelta += pass;
- X`09ChanTableInfo`5BshiftChan`5D->base = vmbase;
- X`09ChanTableInfo`5BshiftChan`5D->delta = vmdelta;
- X`09ChanTableInfo`5BshiftChan`5D->len = vmlen;
- X`09return movetot;
- X`7D
- X
- X`0C
- X/*
- X * socket_write
- X * Emulation routine for writes to a given channel. Note that I tried IO$M_
- VNOW
- X * but it had the effect of causing an error (overflow I believe). `20
- X * Does buffering occur? Is it detrimental to the works since I don't check
- V for
- X * write completion?
- X */
- Xint
- Xsocket_write (chan, buffer, l) /* Issue writes, (IO$_WRITEVBLK), over the
- V logical link.*/
- X unsigned short`09chan;
- X char *buffer;
- X int l;
- X`7B
- X`09int status;
- X`09struct io_stat_blk iosb;
- X`09
- X#ifdef DNDEBUG
- X `09fprintf(stderr, "socket_write: start - passed chan %d\n", chan);
- X#endif /* DNDEBUG */
- X status = SYS$QIOW (0, chan, IO$_WRITEVBLK, &iosb, 0, 0, buffer,
- X l, 0, 0, 0, 0);
- X if (VMSFAIL(status))`20
- X`09`7B
- X`09`09LIB$SIGNAL(status);
- X`09`09return -1;
- X`09`7D
- X if (VMSFAIL(iosb.status))`20
- X`09`7B
- X`09`09LIB$SIGNAL(iosb.status);
- X`09`09return -1;
- X`09`7D
- X#ifdef DNDEBUG
- X`09fprintf(stderr, "socket_write: wrote %d/%d to channel %d\n",iosb.msg_len,
- V l, chan);
- X#endif
- X`09return iosb.msg_len;
- X`7D
- X
- X`0C
- X/*
- X * socket_writev
- X * Emulation routine for the ugly iov style socket writing.
- X */
- Xint
- Xsocket_writev( d, iov, iovcnt)
- X int d;
- X struct iovec *iov;
- X int iovcnt;
- X`7B
- X int totbytes;
- +-+-+-+-+-+-+-+- END OF PART 2 +-+-+-+-+-+-+-+-
- --
- Patrick L. Mahan
-
- --- TGV Window Washer ------------------------------- Mahan@TGV.COM ---------
-
- Waking a person unnecessarily should not be considered - Lazarus Long
- a capital crime. For a first offense, that is From the Notebooks of
- Lazarus Long
-
-