home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / osi / isode / vmsisode / vmsisode80_tar.Z / vmsisode80_tar / sockit / source / socket.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-23  |  88.6 KB  |  2,903 lines

  1. /* Emulation of 4.2 UNIX socket interface routines              */
  2. /* includes drivers for Wollongong ,CMU-TEK, UCX tcp/ip interface */
  3. /* and also emulates the SUN version of X.25 sockets            */
  4. /*                                                              */
  5. /* outstanding problems are:                                    */
  6. /* we have to use the awful fiddle.h to get stream io to work   */
  7. /* with file descriptor based sockets. (instead of rewriting    */
  8. /* the standard library, which we don't have access to)         */
  9.  
  10. #include <stdio.h>
  11. #include <errno.h>
  12. #include <ssdef.h>
  13. #include <dvidef.h>
  14. #include <signal.h>
  15. #include <fcntl.h>
  16. #include <msgdef.h>
  17. #include <psicodes.h>
  18. #include <iodef.h>
  19. #include <ttdef.h>
  20. #include <tt2def.h>
  21. #include <sgtty.h>
  22. #include <netdb.h>
  23. #include <sys/types.h>
  24. #ifndef FD_SET
  25. #define FD_SET(f,s)         ((s)->fds_bits[0] |= (1 << (f)))
  26. #define FD_CLR(f,s)         ((s)->fds_bits[0] &= ~(1 << (f)))
  27. #define FD_ISSET(f,s)       ((s)->fds_bits[0] & (1 << (f)))
  28. #define FD_ZERO(s)          ((s)->fds_bits[0] = 0)
  29. #endif
  30. #include <sys/socket.h>
  31. #include <sys/ioctl.h>
  32. #include <sys/uio.h>
  33. #include <netinet/in.h>
  34. #include <netx25/x25_ctl.h>
  35. #include <netx25/x25_ioctl.h>
  36. #include <netx25/x25_pk.h>
  37. #include <sys/time.h>
  38. #include <sys/termio.h>
  39. #include <ucxcodes.h>
  40. #include <ctype.h>
  41.  
  42. /* actually an itemlist_3, but can be used for itemlist_2's */
  43. struct itemlist {
  44.   short length;
  45.   short code;
  46.   char *dataptr;
  47.   short *retlenptr;
  48. };
  49.  
  50. union socket_addr {struct sockaddr_in in;CONN_DB x25;};
  51. union ioctl_arg {CONN_DB x25;MASK_DATA_DB mask;FACILITY_DB fac;
  52.        X25_CAUSE_DIAG diag;int i;struct sgttyb sg;struct ltchars t;
  53.     struct termio te;};
  54.  
  55. #define   TCP$SEND        (IO$_WRITEVBLK)
  56. #define   TCP$RECEIVE     (IO$_READVBLK)
  57. #define   TCP$OPEN        (IO$_CREATE)
  58. #define   TCP$CLOSE       (IO$_DELETE)
  59. #define   TCP$ABORT       (IO$_DEACCESS)
  60. #define   TCP$STATUS      (IO$_ACPCONTROL)
  61. #define   TCP$INFO        (IO$_MODIFY)
  62. #define   GTHST           (IO$_SKIPFILE)
  63.  
  64. #define   IO$_SEND        (IO$_WRITEVBLK)
  65. #define   IO$_RECEIVE     (IO$_READVBLK)
  66. #ifndef IO$S_FCODE
  67. #define IO$S_FCODE 0x0006
  68. #endif
  69. #define   IO$_SOCKET      (IO$_ACCESS | (0 << IO$S_FCODE))
  70. #define   IO$_BIND        (IO$_ACCESS | (1 << IO$S_FCODE))
  71. #define   IO$_LISTEN      (IO$_ACCESS | (2 << IO$S_FCODE))
  72. #define   IO$_ACCEPT      (IO$_ACCESS | (3 << IO$S_FCODE))
  73. #define   IO$_CONNECT     (IO$_ACCESS | (4 << IO$S_FCODE))
  74. #define   IO$_SETSOCKOPT  (IO$_ACCESS | (5 << IO$S_FCODE))
  75. #define   IO$_GETSOCKOPT  (IO$_ACCESS | (6 << IO$S_FCODE))
  76. #define   IO$_IOCTL       (IO$_ACCESS | (8 << IO$S_FCODE))
  77. #define   IO$_ACCEPT_WAIT (IO$_ACCESS | (10 << IO$S_FCODE))
  78. #define   IO$_NETWORK_PTY (IO$_ACCESS | (11 << IO$S_FCODE))
  79. #define   IO$_SHUTDOWN    (IO$_ACCESS | (12 << IO$S_FCODE))
  80. #define   IO$_GETSOCKNAME (IO$_ACCESS | (13 << IO$S_FCODE))
  81. #define      SETCHAR_HANDOFF (1<<2)
  82.  
  83. #define   NFB$C_DECLNAME   0x15
  84.  
  85. #define TRACE(x) if (trace__) {\
  86.   fprintf(ftrace__,x);\
  87.   fprintf(ftrace__," failed %d %d\n",st,p[s].iosb[0]);\
  88.   }
  89. #define TRACE1(x) if (trace__) {\
  90.   fprintf(ftrace__,x);\
  91.   fprintf(ftrace__," ast called %d %d %d\n",p->s,p->iosb[0],p->iosb[1]);\
  92.   }
  93. FILE *ftrace__;
  94. int trace__ = 0;
  95.  
  96. #define TIMER_EFN 1
  97. #define TERM_EFN  2
  98. #define BUF_SIZE 5000
  99.  
  100. #define INITIALISED 0
  101. #define ACTIVE_CONNECTION 1
  102. #define PASSIVE_CONNECTION 2
  103. #define LISTENING 3
  104. #define HANDED_OFF 4
  105.  
  106. static struct fd_entry {
  107.   unsigned short int channel;   /* vms channel assigned to this socket */
  108.   unsigned short int iosb[4];   /* returned status block */
  109.   int fd_buff_size;             /* number of chrs in buffer still to be read */
  110.   int accept_pending;           /* a call is waiting to be accepted */
  111.   int connect_pending;        /* a connect is outstanding*/
  112.   int connected;        /* this descriptor is connected */
  113.   unsigned char *fd_buff;       /* pointer to buffer dyn assigned */
  114.   unsigned char *fd_leftover;   /* pointer to any chrs still to be read */
  115.   FILE *fptr;                   /* we need to assgn a file ptr for stream io */
  116.   int s;                        /* socket number - needed in the ast's */
  117.   int namelen;                  /* our socket address name */
  118.   union socket_addr name;
  119.   short int fromdummy; /* wg - accept wants an int - recvfrom wants a short!!*/
  120.   short int fromlen;            /* the from socket address name */
  121.   union socket_addr from;
  122.   int tolen;                    /* wg - sendto wants an int*/
  123.   union socket_addr to;         /* the to socket address name */
  124.   int passive;                  /* still needed because of x25 close ambig */
  125.   int backlog;                  /* backlog - not handled well! */
  126.   int domain;                   /* domain of socket AF_INET or AF_X25 */
  127.   int type;                     /* type of socket stream or datagram */
  128.   int protocol;                 /* protocol of socket - ignored */
  129.   int mbx_channel;              /* mailbox channel - needed for x25 */
  130.   unsigned char mbx_buff[255];  /* mailbox buffer */
  131.   unsigned short int miosb[4];  /* mailbox status block */
  132.   int ncb_size;                 /* x25 connection information */
  133.   unsigned char ncb[128];
  134.   unsigned char masklen;        /* x25 user data mask */
  135.   unsigned char mask[16];
  136.   int need_header;              /* x25 header field gives data status if req*/
  137.   int send_type;                /* x25 data packet type eg more bit set etc */
  138.   int status;                   /* status of socket */
  139.   int closed_by_remote;         /* flag for remote dropouts */
  140.   int read_outstanding;         /* flag so we don't hang two reads */
  141.   int cmu_open;                 /* flag to say whether a cmu open was hung */
  142.   int x25_listener;             /* flag to say we are an x25 listener */
  143.   int oob_type;                 /* handles interrupt messages */
  144.   int mother;                   /* mother socket for X25 accepts */
  145.   int child;                    /* child socket for X25 accepts */
  146.   int no_more_accepts;          /* don't accept anymore calls */
  147.   char int_data;                /* interrupt data - only 1 char supported */
  148.   int non_blocking;             /* don't block on a read if no data */
  149.   int sig_req;                  /* generate SIGIO on data ready */
  150.   struct itemlist rhost;    /* descriptor pointing to "p[].from" info for UCX */
  151.   unsigned short ucx_accept_chan; /* Channel returned by a UCX accept via hang_an_accept */
  152. } p[32];
  153.  
  154. static struct term_entry{       /* so we can handle select on terminal input */
  155.   int chan;
  156.   short int iosb[4];
  157.   short int char_available;
  158.   short int read_outstanding;
  159.   char c[1];
  160. } terminal = {-1,0,0,0,0,0,0};
  161.  
  162. static struct sgttyb def_tty = {13, 13, 0x7f, 0x18, 0000010};
  163. static struct termio def_te = {0x2526,0x1805,0x1ad,0x8a3b,0x0,0x3,0x1c,0x7f,0x15,0x4,0,0,0};
  164.  
  165. #define CMU 1
  166. #define WG  2
  167. #define NONE 3
  168. #define TGV 4
  169. #define UCX 5
  170. static int tcp_make = 0;
  171.  
  172. struct descriptor{
  173.   int size;
  174.   char *ptr;
  175. };
  176.  
  177. static int p_initialised = 0;   /* initialise certain things 1st time thru */
  178. static int si_dummy(){}          /* a routine to point SIGALRM and SIGURG at */
  179. static int (*alarm_function)()  = si_dummy;
  180. static int (*sigurg_function)() = si_dummy;
  181. static int (*remembered_alarm_function)();
  182.  
  183. FILE *fdopen();
  184. static set_tcp_make();
  185. static char *getdevicename();
  186.  
  187. /************************************************************/
  188. /* socket routine                                           */
  189. /************************************************************/
  190. int socket(domain,type,protocol)
  191. int domain,type,protocol;
  192. {
  193.   struct descriptor inetdesc,x25desc,mbxdesc;
  194.   extern int mailbox_ast();
  195.   int i, st, s, p_initialise();
  196.   long ucx_sock_def;
  197.   char mailbox_logical_name[16];
  198.   char *getenv();
  199.  
  200.   if ( ! tcp_make) set_tcp_make();
  201.  
  202.   if (p_initialised == 0) {
  203.      for (i=0;i<32;i++) p_initialise(i);
  204.      if ((getenv("PACKET_TRACE") != NULL) &&
  205.       (strcmp(getenv("PACKET_TRACE"),"TRUE") == 0)) {
  206.         trace__ = 1;
  207.         ftrace__ = fopen("packet_trace.log","w");
  208.      }
  209.      p_initialised = 1;
  210.   }
  211.  
  212. if (trace__) fprintf(ftrace__,"socket called domain = %d ",domain);
  213.  
  214.   /* first of all get a file descriptor and file pointer we can associate */
  215.   /* with the socket, allocate a buffer and remember the socket details   */
  216.   s = dup(0);
  217.   if (s >31 ) {
  218.      errno = EMFILE;
  219.      close(s);
  220. if (trace__) fprintf(ftrace__,"socket failed errno = %d\n",errno);
  221.      return(-1);
  222.   }
  223.  
  224.   p[s].fptr = fdopen(s,"r");
  225.   p[s].fd_buff  = (unsigned char *)malloc(BUF_SIZE);
  226.   p[s].domain   = domain;
  227.   p[s].type     = type;
  228.   p[s].protocol = protocol;
  229.  
  230.   /* handle the case of INET and X.25 separately */
  231.   if (domain == AF_INET) {
  232.  
  233.      if (tcp_make == NONE) {
  234.         printf("Trying to obtain a TCP socket when we don't have TCP!\n");
  235.         exit(1);
  236.      }
  237.      if (tcp_make == CMU) {
  238.         /* for CMU we need only assign a channel */
  239.         inetdesc.size = 3;
  240.         inetdesc.ptr = "IP:";
  241.         if (sys$assign(&inetdesc,&p[s].channel,0,0) != SS$_NORMAL) return(-1);
  242.      }  /* end of if CMU */
  243.      else if (tcp_make == UCX) {
  244.  
  245.         /* for UCX assign channel and associate a socket with it */
  246.         inetdesc.size = 3;
  247.     inetdesc.ptr = "BG:";
  248.     if (sys$assign(&inetdesc,&p[s].channel,0,0) != SS$_NORMAL)
  249.        return(-1);
  250.  
  251.     ucx_sock_def = (domain << 24) + (type << 16) + protocol;
  252.         if ((st=sys$qiow(0,p[s].channel,IO$_SETMODE,p[s].iosb,0,0,
  253.       &ucx_sock_def,0,0,0,0,0)) != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL) {
  254.        return(-1);
  255.     }
  256.      }  /* end of if UCX */
  257.      else {  /* TWG */
  258.         /* for WG we assign the channel and associate a socket with it */
  259.         inetdesc.size = 7;
  260.         inetdesc.ptr = "_INET0:";
  261.         if (sys$assign(&inetdesc,&p[s].channel,0,0) != SS$_NORMAL) {
  262. if (trace__) fprintf(ftrace__,"socket failed couldn't assign channel\n");
  263.            return(-1);
  264.         }
  265.         if ((st=sys$qiow(0,p[s].channel,IO$_SOCKET,p[s].iosb,0,0,
  266.          domain,type,0,0,0,0)) != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL) {
  267. if (trace__) fprintf(ftrace__,"socket failed 1 st=%d\n",st);
  268.            return(-1);
  269.         }
  270.      }  /* end of if TWG */
  271.    }
  272.    else if (domain == AF_X25) {
  273.      /* for X.25 we have to assign a channel with a mailbox */
  274.      x25desc.size = 5;
  275.      x25desc.ptr = "NWA0:";
  276.      strcpy(mailbox_logical_name, "X25_MBXn");  /* we need a unique name */
  277.      mailbox_logical_name[7] = 'A'+s;
  278.      mbxdesc.size = 8;
  279.      mbxdesc.ptr  = mailbox_logical_name;
  280.      if ((st=sys$crembx(0,&p[s].mbx_channel,0,0,0,0,&mbxdesc)) != SS$_NORMAL) {
  281. if (trace__) fprintf(ftrace__,"socket failed couldn't assign mailbox\n");
  282.        return(-1);
  283.      }
  284.      if ((st=sys$assign(&x25desc,&p[s].channel,0,&mbxdesc)) != SS$_NORMAL) {
  285. if (trace__) fprintf(ftrace__,"socket failed couldn't assign channel\n");
  286.        return(-1);
  287.      }
  288.      /* set the initial read on the mailbox - the ast will keep this going */
  289.      if ((st=sys$qio(0,p[s].mbx_channel,IO$_READVBLK,p[s].miosb,mailbox_ast,&p[s],
  290.       p[s].mbx_buff,255,0,0,0,0)) != SS$_NORMAL){
  291. if (trace__) fprintf(ftrace__,"socket failed 1 st=%d\n",st);
  292.        return(-1);
  293.      }
  294.    }
  295.    else return(-1);   /* we don't handle any other domain yet */
  296.  
  297.    /* for each case if we are successful we return the descriptor */
  298. if (trace__) fprintf(ftrace__,"socket succeeded s=%d\n",s);
  299.    return(s);
  300. }
  301.  
  302. /************************************************************/
  303. /* bind routine                                             */
  304. /************************************************************/
  305. bind(s,name,namelen)
  306. int s;
  307. union socket_addr *name;
  308. int namelen;
  309. {
  310.   char infobuff[1024], lhost[32];
  311.   int st;
  312.  
  313. if (trace__) fprintf(ftrace__,"bind called s=%d name->in.sin_port=%d ",s,ntohs(name->in.sin_port));
  314.   if ( ! tcp_make) set_tcp_make();
  315.  
  316.   if (p[s].domain == AF_INET) {
  317.   /* one main problem with bind is that if we are given a 0 port number */
  318.   /* then we are expected to return a unique port number, which we don't*/
  319.   /* know! So we return 1050+s and hope!                                */
  320.  
  321.      if (tcp_make == CMU) {
  322.         if (name->in.sin_port == 0 && p[s].type != SOCK_DGRAM)
  323.          name->in.sin_port = 1050+s;
  324.         p[s].namelen = namelen;
  325.         bcopy(name,&(p[s].name),namelen);
  326.  
  327.         if (p[s].type == SOCK_DGRAM) {
  328.            /* another problem is that CMU still needs an OPEN request */
  329.            /* even if its a datagram socket.                          */
  330.            if ((st=sys$qiow(0,p[s].channel,TCP$OPEN,p[s].iosb,0,0,
  331.             0,0,ntohs(p[s].name.in.sin_port),0,1,0)) != SS$_NORMAL) return(-1);
  332.            p[s].cmu_open = 1;
  333.            sys$qiow(0,p[s].channel,TCP$INFO,p[s].iosb,0,0,&infobuff,1024,0,0,0,0);
  334.            bcopy(infobuff+264,&(p[s].name.in.sin_port),2);
  335.            p[s].name.in.sin_port = htons(p[s].name.in.sin_port);
  336. /*         bcopy(infobuff+268,&(p[s].name.in.sin_addr),4); /*doesn't work!*/
  337.            bcopy(infobuff+136,lhost,infobuff[1]); /* so get it another way */
  338.            lhost[infobuff[1]] = '\0';
  339.            sys$qiow(0,p[s].channel,GTHST,p[s].iosb,0,0,&infobuff,1024,1,lhost,0,0);
  340.            bcopy(infobuff+4,&(p[s].name.in.sin_addr),4);
  341.            hang_a_read(s);  /* be prepared to receive a message */
  342.         }
  343.      }
  344.      else if (tcp_make == UCX) {
  345.     /* UCX will select a port for you if port number is 0 */
  346.        /* translate "name" into an item_2 list */
  347.        struct itemlist lhost;
  348.        lhost.length = namelen;
  349.        lhost.code = 0;
  350.        lhost.dataptr = (char *)name;
  351.  
  352.        if ((st = sys$qiow(0,p[s].channel,IO$_SETMODE,p[s].iosb,0,0,
  353.         0,0,&lhost,0,0,0)) != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL) {
  354.             TRACE("bind")
  355.         return(-1);
  356.        }
  357.        if (p[s].type == SOCK_DGRAM)
  358.            hang_a_read(s);
  359.  
  360.      }
  361.      else {
  362.         /* WG is more straightforward */
  363.         if ((st=sys$qiow(0,p[s].channel,IO$_BIND,p[s].iosb,0,0,
  364.          name,namelen,0,0,0,0)) != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL){
  365.           TRACE("bind")
  366.           return(-1);
  367.         }
  368.         if (p[s].type == SOCK_DGRAM) hang_a_read(s); /* be prepared for msg */
  369.      }
  370.   }
  371.  
  372.   else if (p[s].domain == AF_X25) {
  373.      /* for x.25 we can only remember the details */
  374.      p[s].namelen = namelen;
  375.      bcopy(name,&(p[s].name),namelen);
  376.   }
  377.  
  378.   else return(-1);   /* we don't handle any other domain yet */
  379. if (trace__) fprintf(ftrace__," succeeded\n");
  380.  
  381.   return(0);
  382. }
  383.  
  384. /************************************************************/
  385. /* connect routine                                          */
  386. /************************************************************/
  387. connect(s,name,namelen)
  388. int s;
  389. union socket_addr *name;
  390. int namelen;
  391. {
  392.   int pr, fl, st;
  393.   char *inet_ntoa();
  394.   static struct {int len; char name[128];} gethostbuf;
  395.   extern int connect_ast();
  396.  
  397. if (trace__) fprintf(ftrace__,"connect called s=%d %s port %d non_blocking = %d",
  398. s,inet_ntoa(name->in.sin_addr.s_addr),ntohs(name->in.sin_port),p[s].non_blocking);
  399.   if ( ! tcp_make) set_tcp_make();
  400.  
  401.   /* for datagrams we need to  remember who*/
  402.   /* the name was so we can send all msgs  */
  403.   /* to that address without having to     */
  404.   /* specify it all the time               */
  405.   if (p[s].connected) {
  406.      if (p[s].connected == 1) errno = EISCONN;
  407.      else {
  408.         errno = ECONNREFUSED;
  409.         p[s].connected = 0;
  410.      }
  411. if (trace__) fprintf(ftrace__," p[s].connected is true errno = %d\n",errno);
  412.      return(-1);
  413.   }
  414.   if (p[s].connect_pending) {
  415.      errno = EALREADY;
  416. if (trace__) fprintf(ftrace__," p[s].connect_pending is true errno = %d\n",errno);
  417.      return(-1);
  418.   }
  419.  
  420.   p[s].passive = 0;
  421.   p[s].tolen = namelen;
  422.   bcopy(name,&(p[s].to),namelen);
  423.  
  424.   if (p[s].domain == AF_INET) {
  425.      if (tcp_make == CMU) {
  426.  
  427.         /* Get the info about the remote host  and open up a connection */
  428.  
  429.         if ((st=sys$qiow(0,p[s].channel,GTHST,p[s].iosb,0,0,&gethostbuf,132,2,
  430.         name->in.sin_addr.s_addr,0,0)) != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL){
  431. /*
  432.           TRACE("connect")
  433.           return(-1);
  434. */
  435.           strcpy(gethostbuf.name,inet_ntoa(name->in.sin_addr.s_addr));
  436.           gethostbuf.len = strlen(gethostbuf.name);
  437.         }
  438.         gethostbuf.name[gethostbuf.len] = 0;
  439.         pr = 0; /*TCP*/
  440.         fl = 1; /*active*/
  441.         if (p[s].type == SOCK_DGRAM) return(0); /* nothing else for datagrams*/
  442.         if ((st=sys$qio(s,p[s].channel,TCP$OPEN,p[s].iosb,connect_ast,&p[s],
  443.          &(gethostbuf.name),
  444.          ntohs(name->in.sin_port),ntohs(p[s].name.in.sin_port),fl,pr,0))
  445.          != SS$_NORMAL) {
  446.           TRACE("connect")
  447.           return(-1);
  448.         }
  449.      } /* end of CMU */
  450.      else if (tcp_make == UCX) {
  451.     /* both UDP and TCP can use a connect - IO$_ACCESS */
  452.     p[s].rhost.length = namelen;
  453.     p[s].rhost.code = 0;
  454.     p[s].rhost.dataptr = (char *)name;
  455.  
  456.     if ((st=sys$qio(s,p[s].channel,IO$_ACCESS,p[s].iosb,connect_ast,&p[s],
  457.        0,0,&p[s].rhost,0,0,0)) != SS$_NORMAL) {
  458.        TRACE("connect");
  459.        return(-1);
  460.     }
  461.      } /* end of UCX */
  462.      else {  /* TWG */
  463.         if (p[s].type == SOCK_DGRAM) return(0);
  464.         if ((st=sys$qio(s,p[s].channel,IO$_CONNECT,p[s].iosb,connect_ast,&p[s],
  465.          name,namelen,0,0,0,0)) != SS$_NORMAL){
  466.           TRACE("connect")
  467.           return(-1);
  468.         }
  469.      }
  470.   }
  471.   else if (p[s].domain == AF_X25) {
  472.      struct descriptor ncbdesc;
  473.      int i;
  474.      i = setup_ncb(s,name);
  475.      ncbdesc.size = i;
  476.      ncbdesc.ptr  = (char *)&(p[s].ncb);
  477.      if ((st=sys$qio(s,p[s].channel,IO$_ACCESS,p[s].iosb,connect_ast,&p[s],
  478.       0,&ncbdesc,0,0,0,0)) != SS$_NORMAL){
  479.        TRACE("connect")
  480.        errno = ECONNABORTED;
  481.        return(-1);
  482.      }
  483.   }
  484.  
  485.   else return(-1);   /* we don't handle any other domain yet */
  486.  
  487.   if (p[s].non_blocking) {
  488.      if (p[s].connected) {
  489.         if (p[s].connected == 1) {
  490. if (trace__) fprintf(ftrace__," succeeded\n");
  491.            return(0);
  492.         }
  493.         else {
  494.            p[s].connected = 0;
  495.            errno = ECONNREFUSED;
  496. if (trace__) fprintf(ftrace__," failed 1 errno=%d\n",errno);
  497.            return(-1);
  498.         }
  499.      }
  500.      else {
  501.         p[s].connect_pending = 1;
  502.         errno = EINPROGRESS;
  503. if (trace__) fprintf(ftrace__," failed 2 errno=%d\n",errno);
  504.         return(-1);
  505.      }
  506.   }
  507.   else {
  508.     /* wait for the connection to occur */
  509.      if (p[s].connected) {
  510.         if (p[s].connected == 1) {
  511. if (trace__) fprintf(ftrace__," succeeded\n");
  512.            return(0);
  513.         }
  514.         else {
  515.            p[s].connected = 0;
  516.            errno = ECONNREFUSED;
  517. if (trace__) fprintf(ftrace__," failed 3 errno=%d\n",errno);
  518.            return(-1);
  519.         }
  520.      }
  521.     if (wait_efn(s) == -1) return(-1);  /* time out*/
  522.     if (p[s].connected != SS$_NORMAL){
  523.        errno = ECONNREFUSED;
  524. if (trace__) fprintf(ftrace__," failed 4 errno=%d\n",errno);
  525.        return(-1);
  526.     }
  527. if (trace__) fprintf(ftrace__," succeeded\n");
  528.     return(0);
  529.   }
  530. }
  531.  
  532. /************************************************************/
  533. /* listen routine                                           */
  534. /************************************************************/
  535. listen(s,backlog)
  536. int s;
  537. int backlog;
  538. {
  539.   int st;
  540.  
  541. if (trace__) fprintf(ftrace__,"listen called s=%d backlog=%d",s,backlog);
  542.   if ( ! tcp_make) set_tcp_make();
  543.  
  544.   p[s].passive = 1;
  545.   p[s].backlog = backlog;
  546.   if (p[s].domain == AF_INET) {
  547.      if (tcp_make == CMU) {
  548.      /* For the CMU sockets we can't do the open call in listen we */
  549.      /* have to do it in hang_an_accept, because when we close off */
  550.      /* the connection we have to be ready to accept another one.  */
  551.      /* accept also calls hang_an_accept on the old descriptor */
  552.      } /* end of CMU */
  553.      else if (tcp_make == UCX) {
  554. /*
  555.  * doc verbage sez backlog is descriptor of byte.
  556.  * doc examples and common sense sez backlog is value
  557.  * value don't work, so lets try descriptor of byte after all
  558.  */
  559.        struct descriptor bl;
  560.        unsigned char ucx_backlog;
  561.  
  562.        ucx_backlog =(unsigned char) backlog;
  563.        bl.size = sizeof (ucx_backlog);
  564.        bl.ptr = (char *)&ucx_backlog;
  565.  
  566.        if ((st=sys$qiow(0,p[s].channel,IO$_SETMODE,p[s].iosb,0,0,
  567.           0,0,0, &bl,0,0)) != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL) {
  568.       TRACE("listen")
  569.       return(-1);
  570.        }
  571.      }  /* end of UCX */
  572.      else { /* TWG */
  573.         if ((st=sys$qiow(0,p[s].channel,IO$_LISTEN,p[s].iosb,0,0,backlog,
  574.          0,0,0,0,0)) != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL) {
  575.           TRACE("listen")
  576. if (trace__) fprintf(ftrace__," failed\n",st);
  577.           return(-1);
  578.         }
  579.      }
  580.   }
  581.   else if (p[s].domain == AF_X25) {
  582.      /* for x25 we have to declare ourselves as a process wanting to*/
  583.      /* accept calls with the acpcontrol command */
  584.      struct descriptor funcdesc, npbdesc;
  585.      char funcblock[5];
  586.      unsigned char npb_blk[64];
  587.      int i;
  588.      if (p[s].x25_listener == 0) {
  589.         p[s].x25_listener = 1;
  590.         funcblock[0] = NFB$C_DECLNAME;
  591.         for (i=1;i<5;i++) funcblock[i] = 0;
  592.         funcdesc.size = 5;
  593.         funcdesc.ptr  = funcblock;
  594.         i = setup_npb(s,npb_blk);
  595.         npbdesc.size  = i;
  596.         npbdesc.ptr   = (char *)npb_blk;
  597.         if ((st=sys$qiow(0,p[s].channel,IO$_ACPCONTROL,p[s].iosb,0,0,&funcdesc,
  598.          &npbdesc,0,0,0,0)) != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL) {
  599.           TRACE("listen")
  600.          return(-1);
  601.         }
  602.      }
  603.   }
  604.  
  605.   else return(-1);   /* we don't handle any other domain yet */
  606.  
  607. if (trace__) fprintf(ftrace__," succeeded\n");
  608.   p[s].status = LISTENING;
  609.   hang_an_accept(s);
  610.   return(0);
  611. }
  612.  
  613. /************************************************************/
  614. /* accept routine                                           */
  615. /************************************************************/
  616. int accept(s,addr,addrlen)
  617. int s;
  618. union socket_addr *addr;
  619. int *addrlen;
  620. {
  621.   int news, st;
  622.   struct descriptor inetdesc;
  623.  
  624. if (trace__) fprintf(ftrace__,"accept called s=%d port=%d ",
  625. s,htons(addr->in.sin_port));
  626.   if ( ! tcp_make) set_tcp_make();
  627.  
  628.   if (p[s].non_blocking && !p[s].accept_pending) {
  629. if (trace__) fprintf(ftrace__," failed errno=%d\n",errno);
  630.      errno = EWOULDBLOCK;
  631.      return(-1);
  632.   }
  633.  
  634.   /* we still have an unresolved problem in this routine for x25*/
  635.   /* accept should return a new socket descriptor, yet this seems*/
  636.   /* rather tricky as our mailbox is connected with the previous */
  637.   /* descriptor. Sooner or later I'll get my mind round to thinking*/
  638.   /* it out so that its right */
  639.  
  640.   /* hang_an_accept set up an incoming connection request so we */
  641.   /* have first to hang around until one appears or we time out */
  642.  
  643.   if (p[s].domain == AF_INET) {
  644.      if (tcp_make == CMU) {
  645.         char infobuff[1024];
  646.  
  647.         if (wait_efn(s) == -1) return(-1);  /* time out*/
  648.  
  649.         news = dup(0);     /* ok get a new descriptor */
  650.     if (news >31 ) {
  651.        errno = EMFILE;
  652.        close(news);
  653.        return(-1);
  654.     }
  655.         bcopy(&p[s],&p[news],sizeof(p[0]));  /* and copy all our data across */
  656.         p[news].s = news;  /* but not of course this field!*/
  657.         sys$qiow(0,p[news].channel,TCP$INFO,p[news].iosb,0,0,&infobuff,1024,0,0,0,0);
  658.         if (addr != 0) {  /* do we need to return the connection info?*/
  659.           *addrlen = sizeof(struct sockaddr_in);  /* yes so copy across the info */
  660.           bcopy(infobuff+132,&(addr->in.sin_port),2);
  661.           addr->in.sin_port = htons(addr->in.sin_port);
  662.           addr->in.sin_family = AF_INET;
  663.           bcopy(infobuff+272,&(addr->in.sin_addr),4);
  664.           p[news].fromlen = *addrlen;
  665.           bcopy(addr,&(p[news].from),*addrlen);
  666.         }
  667.         p[news].status = PASSIVE_CONNECTION;
  668.         p[news].fptr = fdopen(news,"r"); /* get a new file ptr for the socket*/
  669.         p[news].accept_pending = 0;     /* reset this field */
  670.         p[news].fd_buff = (unsigned char *)malloc(BUF_SIZE); /*allocate a buffer*/
  671.         p[news].fd_leftover = 0;
  672.         hang_a_read(news);              /* be prepared to get msgs */
  673.         inetdesc.size = 3;              /* now fix up our previous socket */
  674.         inetdesc.ptr = "IP:";           /* so it is again listening for conns*/
  675.         if (sys$assign(&inetdesc,&p[s].channel,0,0) != SS$_NORMAL) return(-1);
  676.         p[s].status = LISTENING;
  677.         hang_an_accept(s);
  678.         return(news);     /* return the new socket descriptor */
  679.      }
  680.      else if (tcp_make == UCX) {
  681.     /*
  682.      * UCX does the actual accept from hang_an_accept.  The accept info
  683.      * is put into the data structure for the "listening" socket.
  684.      * These just need to be copied into a newly allocated socket for
  685.      * the connect and the listening socket re-started.
  686.      */
  687.  
  688.     /* wait for event flag from accept being received in hang_an_accept() */
  689.         if (wait_efn(s) == -1)
  690.         return(-1);   /* time out */
  691.  
  692.         news = dup(0);  /* get new descriptor */
  693.       if (news >31 ) {
  694.        errno = EMFILE;
  695.        close(news);
  696.        return(-1);
  697.     }
  698.         bcopy(&p[s], &p[news], sizeof(p[0]));  /* and copy all our data across */
  699.     p[news].s = news; /* but not this field */
  700.         p[news].channel = p[s].ucx_accept_chan;
  701.  
  702.         /* initialize the remote host address item_list_3 struct */
  703.     p[news].rhost.length = sizeof(struct sockaddr_in);
  704.     p[news].rhost.code = 0;
  705.     p[news].rhost.dataptr = (char *)&p[news].from;
  706.     p[news].rhost.retlenptr = &p[news].fromdummy;
  707.  
  708.     if (addr != 0) {  /* return the callers info, if requested */
  709.        *addrlen = p[news].fromdummy;
  710.        bcopy(&p[news].from, addr, p[news].fromdummy);
  711.     }
  712.  
  713.         /* finish fleshing out the new structure */
  714.         p[news].status = PASSIVE_CONNECTION;
  715.     p[news].fptr = fdopen(news,"r");   /* get a new file pointer for the socket */
  716.     p[news].accept_pending = 0;   /* reset this field */
  717.     p[news].fd_buff = (unsigned char *)malloc(BUF_SIZE);  /* allocate a buffer */
  718.     p[news].fd_leftover = 0;
  719.  
  720.     hang_a_read(news);   /* get it started reading */
  721.  
  722.     p[s].status = LISTENING;
  723.     hang_an_accept(s);
  724.  
  725.     return(news);
  726.  
  727.      } /* end of UCX */
  728.      else {  /* TWG */
  729.         struct descriptor inetdesc;
  730.         int size;
  731.  
  732.         if (wait_efn(s) == -1) return(-1);  /* time out*/
  733.  
  734.         news = dup(0);      /* get new descriptor */
  735.       if (news >31 ) {
  736.        errno = EMFILE;
  737.        close(news);
  738.        return(-1);
  739.     }
  740.         inetdesc.size = 7;  /* assign a new channel */
  741.         inetdesc.ptr = "_INET0:";
  742.         if ((st=sys$assign(&inetdesc,&p[news].channel,0,0)) != SS$_NORMAL){
  743.           TRACE("assign new channel")
  744.           p[s].accept_pending = 0;
  745.           sys$clref(s);
  746. if (trace__) fprintf(ftrace__," failed to assign new channel st=%d\n",st);
  747.           return(-1);
  748.         }
  749.         size = sizeof(p[s].from)+4;   /* from info needs an int length field!*/
  750.         if ((st=sys$qiow(0,p[news].channel,IO$_ACCEPT,p[news].iosb,0,0,
  751.          &p[s].fromdummy,size,p[s].channel,0,0,0))
  752.          != SS$_NORMAL || p[news].iosb[0] != SS$_NORMAL) {
  753.           TRACE("accept")
  754.           p[s].accept_pending = 0;
  755.           sys$clref(s);
  756.           return(-1);
  757.         }
  758.         if (addr != 0) {      /* return the callers info if requested */
  759.            *addrlen = p[s].fromdummy;
  760.            bcopy(&p[s].from,addr,*addrlen);
  761.         }
  762.         p[news].status = PASSIVE_CONNECTION; /*fix up our new data structure */
  763.         p[news].domain = AF_INET;
  764.         p[news].passive = 1;
  765.         p[news].fptr = fdopen(news,"r");
  766.         p[news].fd_buff = (unsigned char *)malloc(BUF_SIZE); /*allocate a buffer*/
  767.         hang_a_read(news);      /* be prepared to accept msgs */
  768.         hang_an_accept(s);     /* get the old descriptor back onto accepting */
  769. if (trace__) fprintf(ftrace__," succeeded returning news=%d\n",news);
  770.         return(news);
  771.      }
  772.   }
  773.   else if (p[s].domain == AF_X25) {
  774.      struct descriptor accept_ncb;
  775.  
  776.      if (wait_efn(s) == -1) return(-1);  /* time out*/
  777.  
  778.      news = dup(0);     /* ok get a new descriptor */
  779.      if (news >31 ) {
  780.     errno = EMFILE;
  781.     close(news);
  782.     return(-1);
  783.      }
  784.      bcopy(&p[s],&p[news],sizeof(p[0]));  /* and copy all our data across */
  785.      p[news].s = news;  /* but not of course this field!*/
  786.  
  787.      accept_ncb.size = p[s].ncb_size;   /* accept the call */
  788.      accept_ncb.ptr  = (char *)&(p[s].ncb);
  789.      if ((st=sys$qiow(0,p[s].channel,IO$_ACCESS | IO$M_ACCEPT,p[s].iosb,0,0,
  790.       0,&accept_ncb,0,0,0,0)) != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL) {
  791.        TRACE("accept")
  792.        p[s].accept_pending = 0;
  793.        sys$clref(s);
  794.        return(-1);
  795.      }
  796.      if (addr != 0) {       /* return the callers info if requested */
  797.         decode_ncb(&(p[s].mbx_buff[20]),addr);
  798.         *addrlen = 10+addr->x25.datalen;
  799.         p[news].fromlen = *addrlen;
  800.         bcopy(addr,&(p[news].from),*addrlen);
  801.      }
  802.      p[news].status = PASSIVE_CONNECTION;
  803.      p[news].fptr = fdopen(news,"r");   /* get a new file ptr for the socket*/
  804.      p[news].accept_pending = 0;        /* reset this field */
  805.      p[news].fd_buff = (unsigned char *)malloc(BUF_SIZE); /*allocate a buffer*/
  806.      p[news].fd_leftover = 0;
  807.      p[news].mother = s;
  808.      hang_a_read(news);
  809.      p[s].status = LISTENING;  /* fix up our data structure */
  810.      p[s].child = news;
  811.      hang_an_accept(s);
  812.      return(news);
  813.   }
  814.  
  815.   else return(-1);   /* we don't handle any other domain yet */
  816. }
  817.  
  818. /************************************************************/
  819. /* recv routine                                             */
  820. /************************************************************/
  821. int recv(s,buf,len,flags)
  822. int s;
  823. char *buf;
  824. int len, flags;
  825. {
  826.    return(recvfrom(s,buf,len,flags,0,0));  /* its just a subset */
  827. }
  828.  
  829. /************************************************************/
  830. /* recvfrom routine                                         */
  831. /************************************************************/
  832. int recvfrom(s,buf,len,flags,from,fromlen)
  833. int s;
  834. char *buf;
  835. int len, flags;
  836. union socket_addr *from;
  837. int *fromlen;
  838. {
  839.   int number;
  840.  
  841.   if ( ! tcp_make) set_tcp_make();
  842.  
  843.   if (p[s].domain != AF_INET && p[s].domain != AF_X25) return(-1);
  844.  
  845.   /* if we are not onto datagrams, then its possible that a previous */
  846.   /* call to recvfrom didn't read all the data, and left some behind */
  847.   /* so first of all look in our data buffer for any leftovers that  */
  848.   /* will satisfy this read */
  849.   if (p[s].type != SOCK_DGRAM) {
  850.      if (flags == MSG_OOB) {  /* return any interrupt data requested */
  851.         if (p[s].oob_type == INT_DATA) {
  852.            *buf = p[s].int_data;
  853.            p[s].oob_type = 0;
  854.            return(1);
  855.         }
  856.         else return(-1);
  857.      }
  858.      if (p[s].fd_leftover != 0) { /* we have some data left over */
  859.         if (from != NULL) {  /* say who its from */
  860.        if (tcp_make == UCX) {
  861.           *fromlen = p[s].fromdummy;
  862.           bcopy(&p[s].from,from,p[s].fromdummy);
  863.        }
  864.        else {
  865.               *fromlen = p[s].fromlen;
  866.               bcopy(&p[s].from,from,p[s].fromlen);
  867.        }
  868.         }/* from != NULL */
  869.         if (p[s].fd_buff_size <= len) { /* if we don't have enough then */
  870.             number = p[s].fd_buff_size; /* just return what we have */
  871.             bcopy(p[s].fd_leftover,buf,number);
  872.             p[s].fd_leftover = 0;
  873.             hang_a_read(s);   /* and then be prepared to accept more */
  874.             return(number);
  875.         }
  876.         else {
  877.             bcopy(p[s].fd_leftover,buf,len); /* if we have more than enough */
  878.             p[s].fd_leftover += len;   /* just copy as much is necessary */
  879.             p[s].fd_buff_size -= len;  /* fix up our ptrs and return */
  880.             return(len);
  881.         }
  882.      }
  883.   }
  884.  
  885.   /* we couldn't satisfy the request from previous calls so we must now */
  886.   /* wait for a message to come through */
  887.   if (wait_efn(s) == -1) return(-1); /* time out*/
  888.  
  889.   while ((p[s].fd_buff_size == -1) && (tcp_make == CMU)) {
  890.      hang_a_read(s);
  891.      if (wait_efn(s) == -1) return(-1);
  892.   }
  893.  
  894.   if (p[s].closed_by_remote == 1) { /* this could have happened!*/
  895.      errno = ECONNRESET;
  896.      return(-1);
  897.   }
  898.   if (p[s].oob_type == INT_DATA) { /* or we could have been sent an interrupt*/
  899.      errno = 39;
  900.      return(-1);
  901.   }
  902.  
  903.   if (from != NULL) {
  904.      if (tcp_make == CMU) {
  905.         if (p[s].type == SOCK_DGRAM) {
  906.            /* not documented but we get the from data from the beginning of */
  907.            /* the data buffer */
  908.            *fromlen = sizeof(p[s].from.in);
  909.            from->in.sin_family = AF_INET;
  910.            bcopy(&p[s].fd_buff[8],&(from->in.sin_port),2);
  911.            from->in.sin_port = htons(from->in.sin_port);
  912.            bcopy(&p[s].fd_buff[0],&(from->in.sin_addr),4);
  913.         }
  914.         else {
  915.            *fromlen = p[s].fromlen;
  916.            bcopy(&p[s].from,from,p[s].fromlen);
  917.         }
  918.      }
  919.      else if (tcp_make == UCX) {
  920.        *fromlen = p[s].fromdummy;
  921.        bcopy(&p[s].from,from,p[s].fromdummy);
  922.      }  /* end of if UCX */
  923.      else {
  924.         *fromlen = p[s].fromlen;
  925.         bcopy(&p[s].from,from,p[s].fromlen);
  926.      }
  927.   }
  928.  
  929.   if ((tcp_make == CMU) && (p[s].type == SOCK_DGRAM)) {
  930.      /* remove the address data from front of data buffer */
  931.      bcopy(p[s].fd_buff+12,p[s].fd_buff,p[s].fd_buff_size);
  932.   }
  933.  
  934.   number = p[s].fd_buff_size;  /* we may have received too much */
  935.   if (number <= len) {   /* if we haven't give back all the data available */
  936.      bcopy(p[s].fd_buff,buf,number);
  937.      p[s].fd_leftover = 0;
  938.      hang_a_read(s);
  939.      return(number);
  940.   }
  941.   else {   /* if we have too much data then split it up */
  942.      p[s].fd_leftover = p[s].fd_buff;
  943.      bcopy(p[s].fd_leftover,buf,len);
  944.      p[s].fd_leftover += len;  /* and change the pointers */
  945.      p[s].fd_buff_size -= len;
  946.      return(len);
  947.   }
  948. }
  949.  
  950. /************************************************************/
  951. /* send routine                                             */
  952. /************************************************************/
  953. int send(s,msg,len,flags)
  954. int s;
  955. char *msg;
  956. int len, flags;
  957. {
  958.   return(sendto(s,msg,len,flags,0,0));  /* just a subset of sendto */
  959. }
  960.  
  961. /************************************************************/
  962. /* sendto routine                                           */
  963. /************************************************************/
  964. int sendto(s,msg,len,flags,to,tolen)
  965. int s;
  966. unsigned char *msg;
  967. int len, flags;
  968. union socket_addr *to;
  969. int tolen;
  970. {
  971.   int i, j, st, size;
  972.   unsigned char udpbuf[BUF_SIZE+12];
  973.   char infobuff[1024], lhost[32];
  974.   unsigned short int temp;
  975.  
  976.   if ( ! tcp_make) set_tcp_make();
  977.  
  978.   /* first remember who we sent it to and set the value of size */
  979.   if (to != 0) {
  980.      p[s].tolen = tolen;
  981.      bcopy(to,&(p[s].to),tolen);
  982.      size = tolen;
  983.   }
  984.   else size = 0;
  985.   if (trace__){
  986.      fprintf(ftrace__,"Sending to stream %d (%d):\n",s,len);
  987.      dmphx(ftrace__,msg,len);
  988.   }
  989.  
  990.   if (p[s].domain == AF_INET) {
  991. /*we might never have started a read for udp (socket/sendto) so put one here*/
  992.      if (p[s].type == SOCK_DGRAM) hang_a_read(s);
  993.      if (tcp_make == CMU) {
  994.         if (p[s].type == SOCK_DGRAM) {
  995.            /* we might never have opened up a udp connection yet so check */
  996.            if (p[s].cmu_open != 1) {
  997.               if ((st=sys$qiow(0,p[s].channel,TCP$OPEN,p[s].iosb,0,0,
  998.                0,0,0,0,1,0)) != SS$_NORMAL) return(-1);
  999.               p[s].cmu_open = 1;
  1000.               sys$qiow(0,p[s].channel,TCP$INFO,p[s].iosb,0,0,&infobuff,1024,0,0,0,0);
  1001.               bcopy(infobuff+264,&(p[s].name.in.sin_port),2);
  1002.               p[s].name.in.sin_port = htons(p[s].name.in.sin_port);
  1003.    /*         bcopy(infobuff+268,&(p[s].name.in.sin_addr),4); /*doesn't work!*/
  1004.               bcopy(infobuff+136,lhost,infobuff[1]);
  1005.               lhost[infobuff[1]] = '\0';
  1006.               sys$qiow(0,p[s].channel,GTHST,p[s].iosb,0,0,&infobuff,1024,1,lhost,0,0);
  1007.               bcopy(infobuff+4,&(p[s].name.in.sin_addr),4);
  1008.            }
  1009.            /* this is not well documented! but to send to a udp socket */
  1010.            /* we need to put the address info at the beginning of the  */
  1011.            /* buffer. */
  1012.            bcopy(msg,udpbuf+12,len);
  1013.            bcopy(&p[s].to.in.sin_addr,udpbuf+4,4);
  1014.            temp = ntohs(p[s].to.in.sin_port);
  1015.            bcopy(&temp,udpbuf+10,2);
  1016.            bcopy(&p[s].name.in.sin_addr,udpbuf,4);
  1017.            temp = ntohs(p[s].name.in.sin_port);
  1018.            bcopy(&temp,udpbuf+8,2);
  1019.            temp = len+12;
  1020.            if ((st=sys$qiow(0,p[s].channel,TCP$SEND,p[s].iosb,0,0,
  1021.             udpbuf,temp,0,0,0,0)) != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL) {
  1022.               TRACE("send")
  1023.               return(-1);
  1024.            }
  1025.         }
  1026.         else { /* TCP (! UDP)  */
  1027.            if ((st=sys$qiow(0,p[s].channel,TCP$SEND,p[s].iosb,0,0,
  1028.             msg,len,0,0,0,0)) != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL) {
  1029.               TRACE("send")
  1030.               return(-1);
  1031.            }
  1032.         }
  1033.         return(len);
  1034.      }
  1035.      else if (tcp_make == UCX) {
  1036.        struct itemlist rhost;
  1037.        rhost.length = sizeof(struct sockaddr_in);
  1038.        rhost.code = 0;
  1039.        rhost.dataptr = (char *)&p[s].to;
  1040.  
  1041.        if ((st=sys$qiow(0,p[s].channel,IO$_WRITEVBLK,p[s].iosb,0,0,
  1042.        msg,len,&rhost,0,0,0)) != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL) {
  1043.        TRACE("send");
  1044.        return(-1);
  1045.        }
  1046.        return(len);
  1047.      }
  1048.      else {  /* TWG */
  1049.         if ((st=sys$qiow(0,p[s].channel,IO$_WRITEVBLK,p[s].iosb,0,0,msg,len,
  1050.          0,&p[s].to,size,0))!= SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL) {
  1051.            TRACE("send")
  1052.            return(-1);
  1053.         }
  1054.         return(len);
  1055.      }
  1056.   }
  1057.   else if (p[s].domain == AF_X25) {
  1058.      int qual;
  1059.  
  1060.      /* first check whether the connection is still open */
  1061.      if (p[s].closed_by_remote == 1){
  1062.         sys$clref(s);
  1063.         errno = ECONNRESET;
  1064.         return(-1);
  1065.      }
  1066.      /* now check if we are being asked to send interrupt data */
  1067.      if (flags == MSG_OOB) {
  1068.         if ((st=sys$qiow(0,p[s].channel,IO$_NETCONTROL,p[s].iosb,0,0,msg,len,
  1069.          0,psi$k_interrupt,0,0)) != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL) {
  1070.            TRACE("send")
  1071.            return(-1);
  1072.         }
  1073.         return(1);
  1074.      }
  1075.      /* now fix up the qualifier and send the data */
  1076.      qual = 0;
  1077.      if ((p[s].send_type & (1<<M_BIT)) == (1<<M_BIT)) qual |= IO$M_MORE;
  1078.      if ((p[s].send_type & (1<<Q_BIT)) == (1<<Q_BIT)) qual |= IO$M_QUALIFIED;
  1079.      if ((st=sys$qiow(0,p[s].channel,IO$_WRITEVBLK | qual,p[s].iosb,0,0,
  1080.       msg,len,0,0,0,0)) != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL) {
  1081.        TRACE("send")
  1082.        return(-1);
  1083.      }
  1084.      return(len);
  1085.   }
  1086.   else return(-1);   /* we don't handle any other domain yet */
  1087. }
  1088.  
  1089. /************************************************************/
  1090. /* getsockname routine                                      */
  1091. /************************************************************/
  1092. int getsockname(s,name,namelen)
  1093. int s;
  1094. union socket_addr *name;
  1095. int *namelen;
  1096. {
  1097.   int st;
  1098.  
  1099.   if ( ! tcp_make) set_tcp_make();
  1100.  
  1101.   if (p[s].domain == AF_INET) {
  1102.      if (tcp_make == CMU) {
  1103.         /* for CMU we just return values held in our data structure */
  1104.         *namelen = p[s].namelen;
  1105.         bcopy(&(p[s].name),name,*namelen);
  1106.         return(0);
  1107.      }  /* end of if CMU */
  1108.      else if (tcp_make == UCX) {
  1109.        struct itemlist lhost; /* an item_list_3 descriptor */
  1110.  
  1111.        lhost.length = *namelen;
  1112.        lhost.code = 0;
  1113.        lhost.dataptr = (char *)name;
  1114.        lhost.retlenptr = (short int *)namelen;/*?pkay*/  /* fill in namelen with actual ret len value */
  1115.  
  1116.        if ((st=sys$qiow(0,p[s].channel,IO$_SENSEMODE,p[s].iosb,0,0,
  1117.         0,0,&lhost,0,0,0)) != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL) {
  1118.           TRACE("getsockname")
  1119.            return(-1);
  1120.        }
  1121.        return(0);
  1122.      }  /* end of if UCX */
  1123.      else {  /* TWG */
  1124.         /* WG gives us the information */
  1125.         if ((st=sys$qiow(0,p[s].channel,IO$_GETSOCKNAME,p[s].iosb,0,0,name,
  1126.          namelen,0,0,0,0)) != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL) {
  1127.           TRACE("getsockname")
  1128.           return(-1);
  1129.         }
  1130.         return(0);
  1131.      }
  1132.   }
  1133.   else if (p[s].domain == AF_X25) {
  1134.      /* doesn't make sense here ? */
  1135.   }
  1136.   else return(-1);   /* we don't handle any other domain yet */
  1137. }
  1138.  
  1139. /************************************************************/
  1140. /* select routine                                           */
  1141. /************************************************************/
  1142. int select(nfds,readfds,writefds,exceptfds,timeout)
  1143. int nfds;
  1144. fd_set *readfds,*writefds,*exceptfds;
  1145. struct timeval *timeout;
  1146. {
  1147.    int timer,fd,alarm_set,total,end;
  1148.    long mask,cluster;
  1149.    struct descriptor termdesc;
  1150.    static fd_set new_readfds,new_writefds,new_exceptfds;
  1151.  
  1152. if (trace__) fprintf(ftrace__,"select called nfds = %d\n",nfds);
  1153.    remembered_alarm_function = alarm_function;
  1154.    alarm_function = si_dummy;
  1155.  
  1156.    FD_ZERO(&new_readfds);
  1157.    FD_ZERO(&new_writefds);
  1158.    FD_ZERO(&new_exceptfds);
  1159.    total = 0;
  1160.    if (terminal.chan == -1) {  /* assign a terminal channel if we haven't */
  1161.       termdesc.size = 10;      /* already */
  1162.       termdesc.ptr = "SYS$INPUT:";
  1163.       sys$assign(&termdesc,&terminal.chan,0,0);
  1164.    }
  1165.    alarm_set = 0;
  1166.    if (timeout != NULL) {    /* if a timeout is given then set the alarm */
  1167.       end = timeout->tv_sec;
  1168.       if (timer != 0) {
  1169.          alarm_set = 1;   /* we need to reset the alarm if it didn't fire */
  1170.          si_alarm(end);     /* but we set it */
  1171. if (trace__) fprintf(ftrace__,"select setting alarm of %d\n",end);
  1172.       }
  1173.    }
  1174.    else end = 1;
  1175.  
  1176.    do {
  1177.       if (exceptfds) {
  1178.       }
  1179.  
  1180.       if (writefds) {
  1181.          for(fd=0;fd<nfds;fd++)
  1182.             if(FD_ISSET(fd,writefds)) {
  1183.                if (p[fd].connect_pending) ;
  1184.                else if ((p[fd].status == ACTIVE_CONNECTION) ||
  1185.                 (p[fd].status == PASSIVE_CONNECTION)) {
  1186.                   FD_SET(fd,&new_writefds);
  1187.                   total++;
  1188.                }
  1189.            /* CRW -- make stdout available*/
  1190.            if (fd == 1) {
  1191.           FD_SET(fd,&new_writefds);
  1192.           total++;
  1193.            }
  1194.            /* CRW -- end*/
  1195.             }
  1196.       }
  1197.  
  1198.       if (readfds) {
  1199.          /* check the terminal for any pending */
  1200.          if (FD_ISSET(0,readfds) && (terminal.char_available == 1 )) {
  1201.             FD_SET(0,&new_readfds);
  1202.             total++;
  1203.         }
  1204.      /* CRW -- make stdin available*/
  1205.          if (FD_ISSET(0,readfds) && (type_ahead() != 0 )) {
  1206.             FD_SET(0,&new_readfds);
  1207.             total++;
  1208.         }
  1209.      /* CRW -- end*/
  1210.  
  1211.          for (fd=3;fd<nfds;fd++) /* true if data pending or an accept */
  1212.             if (FD_ISSET(fd,readfds)) {
  1213.              if ((p[fd].fd_buff_size != -1) || (p[fd].accept_pending == 1)) {
  1214.                 FD_SET(fd,&new_readfds);
  1215.                 total++;
  1216.               }
  1217.             }
  1218.       }
  1219.  
  1220.       if (end == 0) break;
  1221.       if (total) break;
  1222.  
  1223.       /* otherwise wait on an event flag */
  1224.       /* it is possible that the wait can be stopped by a spuriuous event */
  1225.       /* flag being set - ie one that has a status not normal. So we have */
  1226.       /* to be prepared to loop round the wait until a valid reason happens */
  1227.  
  1228.       /* set up the wait mask */
  1229.       cluster = 0;
  1230.       mask = 0;
  1231.       for (fd=3;fd<nfds;fd++) {
  1232.          sys$clref(fd);
  1233.          if (readfds) if FD_ISSET(fd,readfds) mask |= (1<<fd);
  1234.            if (writefds) if FD_ISSET(fd,writefds) mask |= (1<<fd);
  1235.            if (exceptfds) if FD_ISSET(fd,exceptfds) mask |= (1<<fd);
  1236.          if ((FD_ISSET(fd,readfds)) && (tcp_make == CMU) &&
  1237.           (p[fd].fd_buff_size == -1) && (p[fd].read_outstanding == 0) &&
  1238.           (p[fd].status != LISTENING)) hang_a_read(fd);
  1239.       }
  1240.       mask |= (1<<TIMER_EFN);
  1241.       if (readfds) if (FD_ISSET(0,readfds)) {
  1242.          hang_a_terminal_read();
  1243.          mask |= (1<<TERM_EFN);
  1244.          mask &= 0xfffe;
  1245.       }
  1246.       sys$clref(TIMER_EFN);   /* clear it off just in case */
  1247.       sys$wflor(cluster,mask); /* wait around */
  1248.  
  1249.       mask = 0;
  1250.       if (read_efn(TIMER_EFN)) {
  1251.          errno = EINTR;
  1252.      break;
  1253.       }
  1254.    } while (1);
  1255.  
  1256.    if (alarm_set == 1) alarm(0);  /* unset the alarm if we set it */
  1257.    if (readfds) *readfds = new_readfds;
  1258.    if (writefds) *writefds = new_writefds;
  1259.    if (exceptfds) *exceptfds = new_exceptfds;
  1260.    alarm_function = remembered_alarm_function;
  1261. if (trace__) fprintf(ftrace__,"select returns total = %d\n",total);
  1262.    return(total);
  1263. }
  1264.  
  1265. /************************************************************/
  1266. /* ioctl routine                                            */
  1267. /************************************************************/
  1268. ioctl(s,request,argp)
  1269. int s;
  1270. unsigned long request;
  1271. union ioctl_arg *argp;
  1272. {
  1273.   int i;
  1274.   if (p[s].channel != 0) {
  1275.      if (request == X25_RD_HOSTADR) {
  1276.         myx25_address(argp);
  1277.         return(0);
  1278.      }
  1279.      if (request == X25_WR_MASK_DATA) {
  1280.         bcopy(argp,&(p[s].masklen),17);
  1281.         return(0);
  1282.      }
  1283.      if (request == X25_HEADER) {
  1284.         p[s].need_header = argp->i;
  1285.         return(0);
  1286.      }
  1287.      if (request == X25_SEND_TYPE) {
  1288.         p[s].send_type = argp->i;
  1289.         return(0);
  1290.      }
  1291.      if (request == X25_OOB_TYPE) {
  1292.         argp->i = p[s].oob_type;
  1293.         return(0);
  1294.      }
  1295.      if (request == X25_CALL_ACPT_APPROVAL) {
  1296.         p[s].need_header = argp->i;
  1297.         return(0);
  1298.      }
  1299.      if (request == X25_WR_CAUSE_DIAG) {
  1300.         printf("Reset requests are not handled at present!\n");
  1301.         return(0);
  1302.      }
  1303.      if (request == X25_RD_CAUSE_DIAG) {
  1304.         argp->diag.flags = 0;
  1305.         return(0);
  1306.      }
  1307.      if (request == X25_RD_FACILITY) {
  1308.         argp->fac.reverse_charge = 0;
  1309.         argp->fac.recvpktsize = 128;
  1310.         argp->fac.sendpktsize = 128;
  1311.         argp->fac.recvwndsize = 2;
  1312.         argp->fac.sendwndsize = 2;
  1313.         argp->fac.recvthruput = 10;
  1314.         argp->fac.sendthruput = 10;
  1315.         argp->fac.cug_req     = 0;
  1316.         argp->fac.cug_index   = 0;
  1317.         argp->fac.fast_select_type = 0;
  1318.         argp->fac.rpoa_req    = 0;
  1319.         argp->fac.rpoa        = 0;
  1320.         return(0);
  1321.      }
  1322.      if (request == X25_RECORD_SIZE) {
  1323.         argp->i = 128;
  1324.         return(0);
  1325.      }
  1326.      if (request == X25_SEND_CALL_ACPT) {
  1327.         return(0);
  1328.      }
  1329.      if (request == SIOCSPGRP) {
  1330.         return(0);
  1331.      }
  1332.      if (request == FIONBIO) {
  1333.         p[s].non_blocking = 1;
  1334.         return(0);
  1335.      }
  1336.      printf("ioctl call on socket - not handled yet, request =%x\n",request);
  1337.      return(0);
  1338.   }
  1339.   else if (s == 0) {
  1340.      if (request == FIONREAD) {
  1341.         argp->i = type_ahead();
  1342.         return(0);
  1343.      }
  1344.      if (request == TIOCGETP) {
  1345.         argp->sg.sg_ispeed = def_tty.sg_ispeed;
  1346.         argp->sg.sg_ospeed = def_tty.sg_ospeed;
  1347.         argp->sg.sg_erase = def_tty.sg_erase;
  1348.         argp->sg.sg_kill  = def_tty.sg_kill;
  1349.     argp->sg.sg_flags = def_tty.sg_flags;
  1350.     return(0);
  1351.      }
  1352.      if (request == TIOCSETP) {
  1353.         def_tty.sg_ispeed = argp->sg.sg_ispeed;
  1354.         def_tty.sg_ospeed = argp->sg.sg_ospeed;
  1355.         def_tty.sg_erase = argp->sg.sg_erase;
  1356.         def_tty.sg_kill = argp->sg.sg_kill;
  1357.     def_tty.sg_flags = argp->sg.sg_flags;
  1358.         if ( (def_tty.sg_flags & ECHO) == ECHO ) set_echo();
  1359.         else set_noecho();
  1360.     return(0);
  1361.      }
  1362.      if (request == TIOCGLTC) {
  1363.         argp->t.t_suspc = 0x19;
  1364.         argp->t.t_dsuspc = 0x19;
  1365.         argp->t.t_rprntc = 0xff;
  1366.         argp->t.t_flushc = 0xff;
  1367.     argp->t.t_werasc = 0xff;
  1368.     argp->t.t_lnextc = 0x0;
  1369.     return(0);
  1370.      }
  1371.      if (request == TIOCSLTC) {
  1372.     return(0);
  1373.      }
  1374.      if (request == TCGETA) {
  1375.         argp->te.c_iflag = def_te.c_iflag;
  1376.         argp->te.c_oflag = def_te.c_oflag;
  1377.         argp->te.c_cflag = def_te.c_cflag;
  1378.         argp->te.c_lflag = def_te.c_lflag;
  1379.         argp->te.c_line = def_te.c_line;
  1380.         for (i=0;i<NCC;i++) argp->te.c_cc[i] = def_te.c_cc[i];
  1381.         return(0);
  1382.      }
  1383.      if (request == TCSETA) {
  1384.         def_te.c_iflag = argp->te.c_iflag;
  1385.         def_te.c_oflag = argp->te.c_oflag;
  1386.         def_te.c_cflag = argp->te.c_cflag;
  1387.         def_te.c_lflag = argp->te.c_lflag;
  1388.         def_te.c_line = argp->te.c_line;
  1389.         for (i=0;i<NCC;i++) def_te.c_cc[i] = argp->te.c_cc[i];
  1390.         if ( (def_te.c_lflag & ECHO) == ECHO ) set_echo();
  1391.         else set_noecho();
  1392.         return(0);
  1393.      }
  1394.      printf("ioctl call on terminal - not handled yet, request =%d\n",request);
  1395.      return(-1);
  1396.   }
  1397.   else {
  1398.      printf("ioctl call on file - not handled yet, request =%d\n",request);
  1399.      return(0);
  1400.   }
  1401. }
  1402.  
  1403. /************************************************************/
  1404. /* shutdown routine                                         */
  1405. /************************************************************/
  1406. shutdown(s,how)
  1407. int s,how;
  1408. {
  1409.   int st;
  1410.   int ucx_how;
  1411.  
  1412.   if ( ! tcp_make) set_tcp_make();
  1413.  
  1414.   if (p[s].domain == AF_INET) {
  1415.      if (tcp_make == CMU) {
  1416.         /* for CMU we just close off */
  1417.         si_close(s);
  1418.         return(0);
  1419.      }  /* end of if CMU */
  1420.      else if (tcp_make == UCX) {
  1421.     if ((st=sys$qiow(0,p[s].channel,IO$_DEACCESS | IO$M_SHUTDOWN,p[s].iosb,0,0,
  1422.       0,0,0,how,0,0)) != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL) {
  1423.         TRACE("shutdown")
  1424.         return(-1);
  1425.         }
  1426.         return(0);
  1427.      }  /* end of if UCX */
  1428.      else {  /* TWG */
  1429.         /* WG lets us do it */
  1430.         if ((st=sys$qiow(0,p[s].channel,IO$_SHUTDOWN,p[s].iosb,0,0,how,
  1431.          0,0,0,0,0)) != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL) {
  1432.           TRACE("shutdown")
  1433.           return(-1);
  1434.         }
  1435.         return(0);
  1436.      }
  1437.   }
  1438.   else if (p[s].domain == AF_X25) {
  1439.      /* for X25 we just close off */
  1440.      si_close(s);
  1441.      return(0);
  1442.   }
  1443.   else return(-1);   /* not a socket */
  1444. }
  1445.  
  1446. /************************************************************/
  1447. /* getsockopt routine                                       */
  1448. /************************************************************/
  1449. getsockopt(s,level,optname,optval,optlen)
  1450. int s, level, optname;
  1451. char *optval;
  1452. int *optlen;
  1453. {
  1454. }
  1455.  
  1456. /************************************************************/
  1457. /* setsockopt routine                                       */
  1458. /************************************************************/
  1459. setsockopt(s,level,optname,optval,optlen)
  1460. int s, level, optname;
  1461. char *optval;
  1462. int optlen;
  1463. {
  1464.   int st;
  1465.   unsigned int on = 1;
  1466.  
  1467.   if ( ! tcp_make) set_tcp_make();
  1468.  
  1469.   if (p[s].domain == AF_INET) {
  1470.      if (tcp_make == CMU) {
  1471.         /* for CMU don't know what to do yet */
  1472.         return(0);
  1473.      }  /* end of if CMU */
  1474.      else if (tcp_make == UCX) {
  1475.        struct itemlist topdesc;
  1476.        struct itemlist optitem;
  1477.  
  1478.        /* set up the item lists */
  1479.        topdesc.length = sizeof(optitem);
  1480.        topdesc.code = UCX$C_SOCKOPT;
  1481.        topdesc.dataptr = (char *)&optitem;
  1482.  
  1483.        optitem.length = optlen;
  1484.        optitem.code = optname;
  1485.        optitem.dataptr = optval;
  1486.  
  1487.        if ((st=sys$qiow(0,p[s].channel,IO$_SETMODE, p[s].iosb,0,0,
  1488.         0,0,0,0,&topdesc,0)) != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL) {
  1489.           TRACE("shutdown")
  1490.           return(-1);
  1491.        }
  1492.        return(0);
  1493.      } /* end of if UCX */
  1494.      else {  /* TWG */
  1495.         /* WG lets us do it */
  1496.         if (optval == NULL) {
  1497.            optval = (char *)&on;
  1498.            optlen = sizeof(on);
  1499.         }
  1500.         if ((st=sys$qiow(0,p[s].channel,IO$_SETSOCKOPT,p[s].iosb,0,0,level,
  1501.          optname,optval,optlen,0,0)) != SS$_NORMAL || p[s].iosb[0] != SS$_NORMAL) {
  1502.           TRACE("setsockopt")
  1503.           return(-1);
  1504.         }
  1505.         return(0);
  1506.      }
  1507.   }
  1508.   else if (p[s].domain == AF_X25) {
  1509.      /* doesn't make sense */
  1510.      return(-1);
  1511.   }
  1512.   else return(-1);   /* not a socket */
  1513. }
  1514.  
  1515. /*********************************************************************/
  1516. /* The following routines are used by the above socket calls         */
  1517. /*********************************************************************/
  1518.  
  1519. /************************************************************/
  1520. /* hang a read sets up a read to be finished at some later time*/
  1521. /************************************************************/
  1522. hang_a_read(s)
  1523. int s;
  1524. {
  1525.   extern int read_ast();
  1526.   int size, st;
  1527.  
  1528.   if (p[s].read_outstanding == 1) return; /* don't bother if we already */
  1529.   p[s].read_outstanding = 1;   /* have a read outstanding */
  1530.   size = sizeof(p[s].from)+4;
  1531.   sys$clref(s);    /* clear off the event flag just in case */
  1532.   p[s].fd_buff_size = -1;  /* and reset the buffer size */
  1533.   if (p[s].domain == AF_INET) {
  1534.      if (tcp_make == CMU) {
  1535.         if ((st=sys$qio(s,p[s].channel,TCP$RECEIVE,p[s].iosb,read_ast,&p[s],
  1536.          p[s].fd_buff,BUF_SIZE,0,0,0,0)) != SS$_NORMAL) {
  1537.           TRACE("hang a read")
  1538.           return(-1);
  1539.         }
  1540.      }  /* end of if CMU */
  1541.      else if (tcp_make == UCX) {
  1542.  
  1543.        p[s].rhost.length = sizeof (struct sockaddr_in);
  1544.        p[s].rhost.code = 0;
  1545.        p[s].rhost.dataptr = (char *)&p[s].from;
  1546.        p[s].rhost.retlenptr = &p[s].fromdummy;
  1547.  
  1548.        if ((st=sys$qio(s,p[s].channel,IO$_READVBLK,p[s].iosb,read_ast,&p[s],
  1549.       p[s].fd_buff,BUF_SIZE,&p[s].rhost,0,0,0)) != SS$_NORMAL) {
  1550.         TRACE("hang a read")
  1551.         return(-1);
  1552.        }
  1553.      }
  1554.      else {  /* TWG */
  1555.         if ((st=sys$qio(s,p[s].channel,IO$_READVBLK,p[s].iosb,read_ast,&p[s],
  1556.          p[s].fd_buff,BUF_SIZE,0,&p[s].fromlen,size,0)) != SS$_NORMAL) {
  1557.           TRACE("hang a read")
  1558.           return(-1);
  1559.         }
  1560.      }
  1561.   }
  1562.   else if (p[s].domain == AF_X25) {
  1563.      if (p[s].need_header == 1) {   /* do we need m, q bits */
  1564.         if ((st=sys$qio(s,p[s].channel,IO$_READVBLK,p[s].iosb,read_ast,&p[s],
  1565.          p[s].fd_buff+1,BUF_SIZE-1,0,0,0,0)) != SS$_NORMAL) {
  1566.           TRACE("hang a read")
  1567.           return(-1);
  1568.         }
  1569.      }
  1570.      else {
  1571.         if ((st=sys$qio(s,p[s].channel,IO$_READVBLK,p[s].iosb,read_ast,&p[s],
  1572.          p[s].fd_buff,BUF_SIZE,0,0,0,0)) != SS$_NORMAL) {
  1573.           TRACE("hang a read")
  1574.           return(-1);
  1575.         }
  1576.      }
  1577.   }
  1578.   else return(-1);   /* we don't handle any other domain yet */
  1579. }
  1580.  
  1581. /************************************************************/
  1582. /* hang an accept waits for a connection request to come in */
  1583. /************************************************************/
  1584. hang_an_accept(s)
  1585. int s;
  1586. {
  1587.   extern int accept_ast();
  1588.   int st;
  1589.  
  1590.   sys$clref(s);    /* clear the event flag just in case */
  1591.   p[s].accept_pending = 0;  /* reset our own flag */
  1592.   p[s].fd_buff_size = -1;   /* and buffer size */
  1593.   if (p[s].domain == AF_INET) {
  1594.      if (tcp_make == CMU) {
  1595.         if ((st=sys$qio(s,p[s].channel,TCP$OPEN,p[s].iosb,accept_ast,&p[s],
  1596.          0,0,ntohs(p[s].name.in.sin_port),0,0,0)) != SS$_NORMAL) return(-1);
  1597.      }
  1598.      else if (tcp_make == UCX) {
  1599.         struct descriptor inetdesc;
  1600.     /* Assign channel for actual connection off listener */
  1601.     inetdesc.size = 3;
  1602.     inetdesc.ptr = "BG:";
  1603.     if (sys$assign(&inetdesc,&p[s].ucx_accept_chan,0,0) != SS$_NORMAL)
  1604.        return(-1);
  1605.  
  1606.         /*
  1607.          * UCX's accept returns remote host info and the channel for a new socket
  1608.          * to perform reads/writes on, so a sys$assign is not necessary
  1609.          */
  1610.          p[s].rhost.length = sizeof(struct sockaddr_in);
  1611.          p[s].rhost.dataptr = (char *)&p[s].from;
  1612.      p[s].fromdummy = 0;
  1613.          p[s].rhost.retlenptr = &p[s].fromdummy;
  1614.  
  1615.         if ((st=sys$qio(s,p[s].channel,IO$_ACCESS|IO$M_ACCEPT,p[s].iosb,accept_ast, &p[s],
  1616.             0,0,&p[s].rhost,&p[s].ucx_accept_chan,0,0)) != SS$_NORMAL) { /* since QIO, don't check IOSB */
  1617.             TRACE("hang an accept")
  1618.         return(-1);
  1619.     }
  1620.      }
  1621.      else {  /* TWG */
  1622.         if ((st=sys$qio(s,p[s].channel,IO$_ACCEPT_WAIT,p[s].iosb,accept_ast,&p[s],
  1623.          0,0,0,0,0,0)) != SS$_NORMAL){
  1624.           TRACE("hang a wait")
  1625.           return(-1);
  1626.         }
  1627.      }
  1628.   }
  1629.   else if (p[s].domain == AF_X25) { /* all taken care of by the mailbox */
  1630.   }
  1631.   else return(-1);   /* we don't handle any other domain yet */
  1632. }
  1633.  
  1634. /************************************************************/
  1635. /* hang a terminal read sets up a read on the term with no  */
  1636. /* character filtering or echo. Only ctrl-Y ctrl-C get thru */
  1637. /************************************************************/
  1638. hang_a_terminal_read()
  1639. {
  1640.    extern int term_ast();
  1641.    if (terminal.read_outstanding == 1) return;
  1642.    terminal.char_available = 0;
  1643.    terminal.read_outstanding = 1;
  1644.    sys$clref(TERM_EFN);
  1645.    sys$qio(0,terminal.chan,IO$_READVBLK | IO$M_NOECHO | IO$M_NOFILTR,
  1646.     terminal.iosb,term_ast,0,terminal.c,1,0,0,0,0);
  1647. }
  1648.  
  1649. /************************************************************/
  1650. /* wait_efn just sets up a wait on either an event or the timer */
  1651. /************************************************************/
  1652. wait_efn(s)
  1653. int s;
  1654. {
  1655.    long mask,cluster;
  1656.  
  1657.    cluster = 0;
  1658.    sys$clref(TIMER_EFN);
  1659.    mask = (1<<s) | (1<<TIMER_EFN);
  1660.    sys$wflor(cluster,mask);
  1661.    if (read_efn(TIMER_EFN)) {
  1662.       errno = EINTR;
  1663.       return(-1);
  1664.    }
  1665.    return(0);
  1666. }
  1667.  
  1668. /************************************************************/
  1669. /* read_ast is called by the system whenever a read is done */
  1670. /************************************************************/
  1671. read_ast(p)
  1672. struct fd_entry *p;  /* pointer to data array, the data includes the */
  1673. {                    /* array element number */
  1674.   int i, j;
  1675.   unsigned char *v, *w;
  1676.  
  1677.   TRACE1("read")
  1678.   p->read_outstanding = 0;  /* reset the outstanding flag */
  1679.   if (p->iosb[0] == SS$_NORMAL) { /* check no errors */
  1680.      p->fd_buff_size = p->iosb[1];
  1681.      if (tcp_make == CMU) {
  1682.         if (p->type == SOCK_DGRAM) p->fd_buff_size -= 12; /* fiddle for DGRMs*/
  1683.      }
  1684.      if (p->need_header == 1) { /* x25 sometimes needs this info */
  1685.         *(p->fd_buff) = 0;
  1686.         if (p->iosb[2] == psi$m_qualified) *(p->fd_buff) |= 1<<Q_BIT;
  1687.         if (p->iosb[2] == psi$m_moredata)  *(p->fd_buff) |= 1<<M_BIT;
  1688.      }
  1689.      if (p->sig_req == 1) gsignal(SIGIO);
  1690.      if (trace__) {
  1691.         fprintf(ftrace__,"Received from stream %d (%d):\n",p->s,p->iosb[1]);
  1692.         dmphx(ftrace__,p->fd_buff,p->iosb[1]);
  1693.      }
  1694.   }
  1695.  
  1696.   else if (p->iosb[0] == SS$_CLEARED) {
  1697.      p->closed_by_remote = 1;
  1698.   }
  1699.   else if (tcp_make == UCX) {
  1700.     if (p->iosb[0] == SS$_LINKDISCON) {
  1701.       p->closed_by_remote = 1;
  1702.     }
  1703.   }
  1704. }
  1705.  
  1706. /************************************************************/
  1707. /* accept_ast is called whenever a incoming call is detected*/
  1708. /************************************************************/
  1709. accept_ast(p)
  1710. struct fd_entry *p;
  1711. {
  1712.   TRACE1("accept")
  1713.   if (p->iosb[0] == SS$_NORMAL) p->accept_pending = 1;
  1714.   else {
  1715.     listen(p->s,p[p->s].backlog);  /* if it failed set up another listen */
  1716.   }
  1717. }
  1718.  
  1719. /************************************************************/
  1720. /* connect_ast is called whenever an async connect is made  */
  1721. /************************************************************/
  1722. connect_ast(p)
  1723. struct fd_entry *p;
  1724. {
  1725.   TRACE1("connect")
  1726.   p->connect_pending = 0;
  1727.   if ((p->connected = p->iosb[0]) == SS$_NORMAL) {
  1728.      p->status = ACTIVE_CONNECTION;   /* we made the connection */
  1729.      hang_a_read(p->s);   /* be prepared to accept a msg */
  1730.   }
  1731. }
  1732.  
  1733. /************************************************************/
  1734. /* mailbox_ast is called whenever the x25 state changes     */
  1735. /************************************************************/
  1736. mailbox_ast(p)
  1737. struct fd_entry *p;
  1738. {
  1739.   int st;
  1740.   struct descriptor accept_ncb;
  1741.   if (trace__) {
  1742.     fprintf(ftrace__,"mailbox ast called message type %d\n",p->mbx_buff[0]);
  1743.     fprintf(ftrace__,"stream s=%d status=%d state is %d\n",p->s,p->iosb[0],p->status);
  1744.   }
  1745.  
  1746. /* if we just connected to another DTE we will get a message confirming
  1747.   the call which we just discard */
  1748.   if (p->status == ACTIVE_CONNECTION) {
  1749.      if (p->mbx_buff[0] == MSG$_DISCON) {
  1750.         p->closed_by_remote = 1;
  1751.         sys$setef(p->s);
  1752.      }
  1753.      else if (p->mbx_buff[0] == MSG$_RESET) {
  1754.         p->closed_by_remote = 1;
  1755.         p->oob_type = VC_RESET;
  1756.         sys$setef(p->s);
  1757.         (*sigurg_function)();
  1758.      }
  1759.      else if (p->mbx_buff[0] == MSG$_INTMSG) {
  1760.         p->oob_type = INT_DATA;
  1761.         p->int_data = p->mbx_buff[21];
  1762.         sys$setef(p->s);
  1763.         (*sigurg_function)();
  1764.      }
  1765.   }
  1766.   else if (p->child != 0) {
  1767.      if (p->mbx_buff[0] == MSG$_DISCON) {
  1768.         p[p->child].closed_by_remote = 1;
  1769.         sys$setef(p->child);
  1770.         p->child = 0;  /* in case the child doesn't close!*/
  1771.      }
  1772.      else if (p->mbx_buff[0] == MSG$_RESET) {
  1773.         p[p->child].closed_by_remote = 1;
  1774.         p[p->child].oob_type = VC_RESET;
  1775.         sys$setef(p->child);
  1776.         p->child = 0;  /* in case the child doesn't close!*/
  1777.         (*sigurg_function)();
  1778.      }
  1779.      else if (p->mbx_buff[0] == MSG$_INTMSG) {
  1780.         p[p->child].oob_type = INT_DATA;
  1781.         p[p->child].int_data = p->mbx_buff[21];
  1782.         sys$setef(p->child);
  1783.         (*sigurg_function)();
  1784.      }
  1785.   }
  1786.  
  1787. /* if we get a disconnect message when we have already disconnected then
  1788.    ignore it */
  1789.   else if (p->mbx_buff[0] == MSG$_DISCON) {
  1790.   }
  1791.  
  1792.   else if ((p->status == LISTENING) && (p->mbx_buff[0] == MSG$_CONNECT)) {
  1793.      if (p->no_more_accepts == 1) {
  1794.         p->ncb_size = p->mbx_buff[20];
  1795.         bcopy(p->mbx_buff+21,p->ncb,p->ncb_size);
  1796.         accept_ncb.size = p->ncb_size;   /* accept the call */
  1797.         accept_ncb.ptr  = (char *)p->ncb;
  1798.         sys$qiow(0,p->channel,IO$_ACCESS | IO$M_ABORT,p->iosb,0,0,
  1799.          0,&accept_ncb,0,0,0,0);
  1800.      }
  1801.      else {
  1802. /* copy the ncb into p[s] and signal the event flag s to unhang the wait*/
  1803.         p->ncb_size = p->mbx_buff[20];
  1804.         bcopy(p->mbx_buff+21,p->ncb,p->ncb_size);
  1805.         p->accept_pending = 1;
  1806.         sys$setef(p->s);
  1807.      }
  1808.   }
  1809.  
  1810. /* set up another read*/
  1811.   if ((st=sys$qio(0,p->mbx_channel,IO$_READVBLK,p->miosb,mailbox_ast,p,
  1812.    p->mbx_buff,255,0,0,0,0)) != SS$_NORMAL){
  1813.      return(-1);
  1814.   }
  1815. }
  1816.  
  1817. /************************************************************/
  1818. /* terminal_ast is called whenever a char is typed at the kbd*/
  1819. /************************************************************/
  1820. term_ast()
  1821. {
  1822.   if (trace__) {
  1823.      fprintf(ftrace__,"term ast called %d\n",terminal.iosb[0]);
  1824.   }
  1825.   terminal.read_outstanding = 0;
  1826.   if (terminal.iosb[0] == SS$_NORMAL) {
  1827.      terminal.char_available = 1;
  1828.      sys$setef(TERM_EFN);
  1829.   }
  1830. }
  1831.  
  1832. /************************************************************/
  1833. /* now we get to the fiddled routines to handle stream io   */
  1834. /************************************************************/
  1835.  
  1836. /************************************************************/
  1837. /* si_close - must close off any connection in progress      */
  1838. /************************************************************/
  1839. si_close(s)
  1840. int s;
  1841. {
  1842.   if ( ! tcp_make) set_tcp_make();
  1843.  
  1844.   if ( (s<0) || (s>31) ) return(-1);
  1845. if (trace__) fprintf(ftrace__,"close called s=%d\n",s);
  1846.   if (p[s].channel != 0) {/* was it one of our descriptors*/
  1847.      if (p[s].domain == AF_INET) {
  1848.         if (tcp_make == CMU) {
  1849.            sys$qiow(0,p[s].channel,TCP$CLOSE,p[s].iosb,0,0,0,0,0,0,0,0);
  1850.         }
  1851.         if (p[s].status != HANDED_OFF) sys$dassgn(p[s].channel);
  1852.         close(s);
  1853.         free(p[s].fd_buff);
  1854.         p_initialise(s);
  1855.      }
  1856.      else if (p[s].domain == AF_X25) {
  1857.         if (p[s].status == ACTIVE_CONNECTION) {
  1858.            sys$qiow(0,p[s].channel,IO$_DEACCESS,p[s].iosb,0,0,0,0,0,0,0,0);
  1859.            if (p[s].status != HANDED_OFF) sys$dassgn(p[s].channel);
  1860.            close(s);
  1861.            free(p[s].fd_buff);
  1862.            p_initialise(s);
  1863.     }
  1864.         else if ((p[s].status == LISTENING) && (p[s].child != 0)) {
  1865. /* mother is being closed - child still lives */
  1866.            p[s].no_more_accepts = 1;
  1867.         }
  1868.         else if ((p[s].status == LISTENING) && (p[s].child == 0)) {
  1869. /* mother didn't have any childs so close her off */
  1870.            sys$qiow(0,p[s].channel,IO$_DEACCESS,p[s].iosb,0,0,0,0,0,0,0,0);
  1871.            sys$dassgn(p[s].channel);
  1872.            close(s);
  1873.            free(p[s].fd_buff);
  1874.            p_initialise(s);
  1875.     }
  1876.         else if ((p[s].status == PASSIVE_CONNECTION) && (p[p[s].mother].no_more_accepts == 1)){
  1877. /* child and mother can now be closed */
  1878.            sys$qiow(0,p[s].channel,IO$_DEACCESS,p[s].iosb,0,0,0,0,0,0,0,0);
  1879.            sys$dassgn(p[s].channel);
  1880.            close(s);
  1881.            free(p[s].fd_buff);
  1882.            close(p[s].mother);
  1883.            free(p[p[s].mother].fd_buff);
  1884.            p_initialise(p[s].mother);
  1885.            p_initialise(s);
  1886.         }
  1887.         else if ((p[s].status == PASSIVE_CONNECTION) && (p[p[s].mother].no_more_accepts == 0)){
  1888. /* close off child but leave mother alone for more accepts */
  1889.            p[p[s].mother].child = 0;
  1890.            sys$qiow(0,p[s].channel,IO$_DEACCESS,p[s].iosb,0,0,0,0,0,0,0,0);
  1891.            close(s);
  1892.            free(p[s].fd_buff);
  1893.            p_initialise(s);
  1894.         }
  1895.      }
  1896.      return(0);
  1897.   }
  1898.   else {
  1899.      p[s].fd_buff_size = -1;  /* re-initialise data structure just in case */
  1900.      p[s].accept_pending = 0;
  1901.      p[s].status = INITIALISED;
  1902.      if (s == 0) return(0);
  1903.      return(close(s));
  1904.   }
  1905. }
  1906.  
  1907. /************************************************************/
  1908. /* si_signal - must remember name of function to be called   */
  1909. /************************************************************/
  1910. si_signal(sig,func)
  1911. int sig;
  1912. int (*func)();
  1913. {
  1914.   int pre_alarm();
  1915.  
  1916.   /* we need to catch calls to signal for conditions SIGALRM and SIGURG */
  1917.   /* we divert them through our own routine before running the one the  */
  1918.   /* user wants, so this routine just grabs the name of the function and*/
  1919.   /* stores it away */
  1920.   if (sig == SIGALRM){
  1921.      if (func == SIG_IGN) {
  1922.         alarm_function = si_dummy;
  1923.     signal(sig,func);
  1924.      }
  1925.      else if (func == SIG_DFL) {
  1926.         alarm_function = si_dummy;
  1927.      }
  1928.      else {
  1929.         alarm_function = func;
  1930.      }
  1931.   }
  1932.   else if (sig == SIGURG){
  1933.      if (func == SIG_IGN) {
  1934.         sigurg_function = si_dummy;
  1935.     signal(sig,func);
  1936.      }
  1937.      else if (func == SIG_DFL) {
  1938.         sigurg_function = si_dummy;
  1939.      }
  1940.      else {
  1941.         sigurg_function = func;
  1942.      }
  1943.   }
  1944.   else signal(sig,func);
  1945. }
  1946.  
  1947. /************************************************************/
  1948. /* si_sigvec - must remember name of function to be called   */
  1949. /************************************************************/
  1950. si_sigvec(sig,vec,ovec)
  1951. int sig;
  1952. struct sigvec *vec, *ovec;
  1953. {
  1954.   int pre_alarm();
  1955.  
  1956.   /* we need to catch calls to signal for conditions SIGALRM and SIGURG */
  1957.   /* we divert them through our own routine before running the one the  */
  1958.   /* user wants, so this routine just grabs the name of the function and*/
  1959.   /* stores it away */
  1960.   if (sig == SIGALRM){
  1961.      if (vec->sv_handler == SIG_IGN) {
  1962.         alarm_function = si_dummy;
  1963.         sigvec(sig,vec,ovec);
  1964.      }
  1965.      else if (vec->sv_handler == SIG_DFL) {
  1966.         alarm_function = si_dummy;
  1967.      }
  1968.      else {
  1969.         alarm_function = vec->sv_handler;
  1970.      }
  1971.   }
  1972.   else if (sig == SIGURG){
  1973.      if (vec->sv_handler == SIG_IGN) {
  1974.         sigurg_function = si_dummy;
  1975.         sigvec(sig,vec,ovec);
  1976.      }
  1977.      else if (vec->sv_handler == SIG_DFL) {
  1978.         sigurg_function = si_dummy;
  1979.      }
  1980.      else {
  1981.         sigurg_function = vec->sv_handler;
  1982.      }
  1983.   }
  1984.   else sigvec(sig,vec,ovec);
  1985. }
  1986.  
  1987. /************************************************************/
  1988. /* si_alarm - insert a call to our own alarm function        */
  1989. /************************************************************/
  1990. si_alarm(i)
  1991. int i;
  1992. {
  1993.   extern int pre_alarm();
  1994.  
  1995. if (trace__) fprintf(ftrace__,"si_alarm called time = %d\n",i);
  1996. /* make the call to pre_alarm instead of what the user wants */
  1997.   /* pre_alarm will call his routine when it finishes */
  1998.   signal(SIGALRM,pre_alarm);  /*vax needs this call each time!*/
  1999.   alarm(i);
  2000. }
  2001.  
  2002. /************************************************************/
  2003. /* pre_alarm - gets called first on an alarm signal         */
  2004. /************************************************************/
  2005. pre_alarm()
  2006. {
  2007.   /* come here first so we can set our timer event flag */
  2008.   sys$setef(TIMER_EFN);
  2009.   (*alarm_function)();
  2010. }
  2011.  
  2012. /************************************************************/
  2013. /* si_write - trap system write calls                        */
  2014. /************************************************************/
  2015. int si_write(s,buf,nbytes)
  2016. int s;
  2017. char *buf;
  2018. int nbytes;
  2019. {
  2020.   if ( (s<1) || (s>31) ) return(-1); /*can't write to stdin as well*/
  2021.   /* if its our socket then call sendto instead of write */
  2022. /*fprintf(stderr,"write called s=%d nbytes=%d\n",s,nbytes);*/
  2023.   if (p[s].channel != 0) return(sendto(s,buf,nbytes,0,0,0));
  2024.   return(write(s,buf,nbytes));
  2025. }
  2026.  
  2027. /************************************************************/
  2028. /* writev -  system writev calls                            */
  2029. /*                                */
  2030. /* Revised 2/17/91  Louisa Thomson                          */
  2031. /* Rewrote the code to handle large iov entries and to      */
  2032. /*    flush data out at 512 bytes.  This            */
  2033. /*    appears to be the atomic session data unit, however */
  2034. /*    I was unable to find the symbol for it.  Therefore, */
  2035. /*    512 is hardcoded in there.                     */
  2036. /************************************************************/
  2037.  
  2038. int writev(s,iov,iovcnt)
  2039. int s;
  2040. struct iovec *iov;
  2041. int iovcnt;
  2042. {
  2043.   int cnt, cc, i, j, bufflen, iovlen;
  2044.   char buffer[1024];
  2045.   char *ptr;
  2046.  
  2047.   if ( (s<0) || (s>31) ) return(-1);    /* check channels */
  2048.   cnt = 0;     /* total character count */
  2049.   j = 0;    /* index into the iov entries  */
  2050.   i = 0;  bufflen = 512;
  2051.   ptr = iov[j].iov_base;
  2052.   iovlen = iov[j].iov_len;
  2053.  
  2054.  
  2055.   while (j < iovcnt) {    /* do all the iov blocks   */
  2056.  
  2057.     if (bufflen < iovlen) cc = bufflen;
  2058.     else  cc = iovlen;
  2059.     bcopy(ptr, buffer+i, cc);  /* copy from iov to buffer */
  2060.  
  2061.     /*  increment everything  */
  2062.     ptr += cc;
  2063.     i += cc;
  2064.     iovlen -= cc;
  2065.     bufflen -= cc;
  2066.  
  2067.     if (i >= 512){    /* if buffer is full--flush   */
  2068.         if (p[s].channel != 0) cnt += sendto(s, buffer, i, 0, 0, 0);
  2069.         else cnt += write(s, buffer, i);
  2070.         i=0;  bufflen = 512;     /* reinitialize variables  */
  2071.     }
  2072.  
  2073.     if (iovlen <= 0){  /* if iov block is done...get next one */
  2074.         j += 1;
  2075.         if (j < iovcnt){
  2076.             ptr = iov[j].iov_base;
  2077.             iovlen = iov[j].iov_len;
  2078.         }
  2079.     }
  2080.  
  2081.   }
  2082.  
  2083.   if (bufflen != 512){    /* output any partial buffer  */
  2084.     if (p[s].channel != 0) cnt += sendto(s,buffer,i,0,0,0);
  2085.     else cnt += write(s, buffer, i);
  2086.   }
  2087.  
  2088.   return(cnt);    /* return total character count  */
  2089. }
  2090.  
  2091. /************************************************************/
  2092. /* si_read - trap system read calls                          */
  2093. /************************************************************/
  2094. int si_read(s,buf,nbytes)
  2095. int s;
  2096. char *buf;
  2097. int nbytes;
  2098. {
  2099.   if ( (s<0) || (s>31) ) return(-1);
  2100.   /* if its our socket then call recvfrom instead of read */
  2101.   if (p[s].channel != 0) return(recvfrom(s,buf,nbytes,0,0,0));
  2102.   return(read(s,buf,nbytes));
  2103.  
  2104. }
  2105.  
  2106. /************************************************************/
  2107. /* fcntl - trap system fcntl calls                        */
  2108. /************************************************************/
  2109. int fcntl(s,cmd,arg)
  2110. int s, cmd, arg;
  2111. {
  2112.   int flags;
  2113.   if ( (s<0) || (s>31) ) return(-1);
  2114.   if (p[s].channel != 0) {
  2115.      if (cmd == F_SETFL) {
  2116.         if ( (arg & FNDELAY) == FNDELAY) p[s].non_blocking = 1;
  2117.     else p[s].non_blocking = 0;
  2118.         if ( (arg & FASYNC) == FASYNC) p[s].sig_req = 1;
  2119.     else p[s].sig_req = 0;
  2120.     return(0);
  2121.      }
  2122.      if (cmd == F_GETFL) {
  2123.         flags = 0;
  2124.         if (p[s].non_blocking == 1) flags |= FNDELAY;
  2125.         if (p[s].sig_req == 1) flags |= FASYNC;
  2126.         return(flags);
  2127.      }
  2128.      printf("Unexpected cmd to fcntl - %d\n",cmd);
  2129.      return(-1);
  2130.   }
  2131.   printf("Fcntl called on a descriptor!\n");
  2132.   return(-1);
  2133.  
  2134. }
  2135.  
  2136. /************************************************************/
  2137. /* si_fdopen - return a file ptr for a descriptor            */
  2138. /************************************************************/
  2139. FILE *si_fdopen(fildes,type)
  2140. int fildes;
  2141. char *type;
  2142. {
  2143.   if (p[fildes].channel != 0) return(p[fildes].fptr);
  2144.   return(fdopen(fildes,type));
  2145. }
  2146.  
  2147. /************************************************************/
  2148. /* si_fprintf - printf to a stream                           */
  2149. /************************************************************/
  2150. int si_fprintf(stream,format,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16)
  2151. FILE *stream;
  2152. char *format;
  2153. int *a1,*a2,*a3,*a4,*a5,*a6,*a7,*a8,*a9,*a10,*a11,*a12,*a13,*a14,*a15,*a16;
  2154. {
  2155.   char buf[1024];
  2156.   int fd;
  2157.  
  2158.   /* this is not pretty but how else can we handle variable number of */
  2159.   /* arguments except declare lots of them, no checking is done if we */
  2160.   /* supply to few. Of course if more than 16 are passed we get into  */
  2161.   /* awful trouble */
  2162.   if ((fd=get_fd_fptr(stream)) != -1) {
  2163.      sprintf(buf,format,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16);
  2164.      return(send(fd,buf,strlen(buf),0));
  2165.   }
  2166.   return(fprintf(stream,format,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16));
  2167. }
  2168.  
  2169. /************************************************************/
  2170. /* si_fclose - close of a stream                             */
  2171. /************************************************************/
  2172. si_fclose(stream)
  2173. FILE *stream;
  2174. {
  2175.   int fd;
  2176.  
  2177.   if ((fd=get_fd_fptr(stream)) != -1) return(si_close(fd));
  2178.   return(fclose(stream));
  2179. }
  2180.  
  2181. /************************************************************/
  2182. /* si_rewind - rewind a stream                               */
  2183. /************************************************************/
  2184. si_rewind(stream)
  2185. FILE *stream;
  2186. {
  2187.   int fd;
  2188.  
  2189.   /* don't do anything if its one of ours */
  2190.   if ((fd=get_fd_fptr(stream)) != -1) return(0);
  2191.   return(rewind(stream));
  2192. }
  2193.  
  2194. /************************************************************/
  2195. /* si_fflush - flush a stream                                */
  2196. /************************************************************/
  2197. si_fflush(stream)
  2198. FILE *stream;
  2199. {
  2200.   int fd;
  2201.  
  2202.   /* don't do anything if its one of ours */
  2203.   if ((fd=get_fd_fptr(stream)) != -1) return(0);
  2204.   return(fflush(stream));
  2205. }
  2206.  
  2207. /************************************************************/
  2208. /* si_fgets - get a string from a stream                     */
  2209. /************************************************************/
  2210. char *si_fgets(s,n,stream)
  2211. char *s;
  2212. int n;
  2213. FILE *stream;
  2214. {
  2215.   int fd, i;
  2216.   char buf[1], *t;
  2217.  
  2218.   /* we need to read a character string from the socket which is */
  2219.   /* terminated by a nl. Do this the hard way by reading 1 char  */
  2220.   /* at a time and testing it */
  2221.   if ((fd=get_fd_fptr(stream)) != -1) {
  2222.      t = s;
  2223.      for (i=1;i<n;i++) {
  2224.         if (recvfrom(fd,buf,1,0,0) == 0) {
  2225.            return(0);
  2226.         }
  2227.         *t++ = buf[0];
  2228.         if (buf[0] == '\n') break;
  2229.      }
  2230.      *t = '\0';
  2231.      return(s);
  2232.   }
  2233.   return(fgets(s,n,stream));
  2234. }
  2235.  
  2236. /*************************************************************/
  2237. /*  si_fgetc  - get a character from a stream                */
  2238. /*************************************************************/
  2239. si_fgetc(stream)
  2240. FILE *stream;
  2241. {
  2242.   char buf[1];
  2243.   int fd;
  2244.  
  2245.   if ((fd=get_fd_fptr(stream)) != -1) {
  2246.     if (recvfrom(fd,buf,1,0,0) == 0) {
  2247.       return(EOF);  /* EOF */
  2248.     }
  2249.     return(buf[0]);
  2250.   }
  2251.  
  2252.   return(fgetc(stream));
  2253. }
  2254.  
  2255. /************************************************************/
  2256. /* si_fputc - put a char to a stream                         */
  2257. /************************************************************/
  2258. si_fputc(c,stream)
  2259. char c;
  2260. FILE *stream;
  2261. {
  2262.   int fd;
  2263.  
  2264.   if ((fd=get_fd_fptr(stream)) != -1) return(sendto(fd,&c,1,0,0,0));
  2265.   return(fputc(c,stream));
  2266. }
  2267.  
  2268. /************************************************************/
  2269. /* si_fputs - put a string to a stream                      */
  2270. /************************************************************/
  2271. si_fputs(s,stream)
  2272. char *s;
  2273. FILE *stream;
  2274. {
  2275.   int fd;
  2276.  
  2277.   if ((fd=get_fd_fptr(stream)) != -1) return(sendto(fd,s,strlen(s),0,0,0));
  2278.   if (strlen(s) <= 0x800) return(fputs(s,stream));
  2279.   while (*s != '\0') fputc(*s++,stream);
  2280. }
  2281.  
  2282. /************************************************************/
  2283. /* getpeername                                            */
  2284. /************************************************************/
  2285. getpeername(s,from,fromlen)
  2286. int s;
  2287. struct sockaddr *from;
  2288. int *fromlen;
  2289. {
  2290.   if (p[s].status != 0) {
  2291.     *fromlen = p[s].fromlen;
  2292.     bcopy(from,&(p[s].from),p[s].fromlen);
  2293.     return(0);
  2294.   }
  2295.   return(-1);
  2296. }
  2297.  
  2298. /************************************************************/
  2299. /* gethostbyname                                            */
  2300. /************************************************************/
  2301. gethostname(name, namelen)
  2302. char *name;
  2303. int namelen;
  2304. {
  2305.   char p[24], *t, *getenv();
  2306.  
  2307.   if ( ! tcp_make) set_tcp_make();
  2308.  
  2309.   if (tcp_make == CMU) {
  2310.      t = getenv("INTERNET_HOST_NAME");
  2311.   }
  2312.   else if (tcp_make == UCX) {
  2313.      t = getenv("UCX$INET_HOST");
  2314.   }
  2315.   else {
  2316.      t = getenv("ARPANET_HOST_NAME");
  2317.   }
  2318.   if (t == NULL) {
  2319.      printf("What is your internet name\n");
  2320.      t = (char *)malloc(24);
  2321.      gets(t);
  2322.   }
  2323.   strcpy(name,t);
  2324. }
  2325.  
  2326. /************************************************************/
  2327. /* now some useful internal routines                        */
  2328. /************************************************************/
  2329.  
  2330. /************************************************************/
  2331. /* get_fd_fptr - get the file pointer given the descriptor  */
  2332. /************************************************************/
  2333. int get_fd_fptr(fptr)
  2334. FILE *fptr;
  2335. {
  2336.   int i;
  2337.   for (i=1;i<32;i++) if (fptr == p[i].fptr) return(i);
  2338.   return(-1);
  2339. }
  2340.  
  2341. /************************************************************/
  2342. /* get a line of text from a file                           */
  2343. /************************************************************/
  2344. int getl(fp,s,lim)
  2345. FILE *fp;
  2346. char s[];
  2347. int lim;
  2348. {
  2349.   int c,i;
  2350.   i = 0;
  2351.   while (--lim>0 && (c=getc(fp)) != EOF && c != '\n') s[i++] = c;
  2352.   if (c == '\n') s[i++] = c;
  2353.   s[i] = '\0';
  2354.   return(i);
  2355. }
  2356.  
  2357. /************************************************************/
  2358. /* myx25_address - tell me who I am                         */
  2359. /************************************************************/
  2360. myx25_address(s)
  2361. CONN_DB *s;
  2362. {
  2363.   char p[24], *t, *getenv();
  2364.   t = getenv("X25_ADDRESS");
  2365.   if (t == NULL) {
  2366.      printf("What is your x25 address\n");
  2367.      t = (char *)malloc(24);
  2368.      gets(t);
  2369.   }
  2370.   p[0] = strlen(t) &0xff;
  2371.   strcpy(p+1,t);
  2372.   s->hostlen = strlen(t);
  2373.   ascic_to_bcd(p,s->host);
  2374.   return;
  2375.  }
  2376.  
  2377. /************************************************************/
  2378. /* myx25_subaddress - tell me who I am                      */
  2379. /************************************************************/
  2380. myx25_subaddress(i)
  2381. int *i;
  2382. {
  2383.    char *z, *getenv();
  2384.    z = getenv("X25_SUBADDRESS");
  2385.    if (z == NULL) *i = -1;
  2386.    else if (sscanf(z,"%d",i) == -1) *i = -1;
  2387. }
  2388.  
  2389. /************************************************************/
  2390. /* bcd_to_ascic - convert bcd to counted ascii string       */
  2391. /************************************************************/
  2392. bcd_to_ascic(b,a,len)
  2393. char *b,*a;
  2394. int len;
  2395. {
  2396.   int i;
  2397.   *a++ = len & 0xff;
  2398.   for (i=0;i<len;i++){
  2399.      if ((i%2) == 0) *a = ( (*b>>4)&0x0f ) +'0';
  2400.      else {
  2401.         *a = ( (*b)&0x0f ) +'0';
  2402.         b++;
  2403.      }
  2404.      a++;
  2405.   }
  2406. }
  2407.  
  2408. /************************************************************/
  2409. /* ascic_to_bcd - convert counted ascii string to bcd       */
  2410. /************************************************************/
  2411. ascic_to_bcd(a,b)
  2412. char *a, *b;
  2413. {
  2414.   int i, len;
  2415.   for (i=0;i<8;i++) *b++ = '\0';
  2416.   b -= 8;
  2417.   len = *a++;
  2418.   for (i=0;i<len;i++) {
  2419.      if ((i%2) == 0) *b = ( ((*a-'0')<<4)&0x00f0 );
  2420.      else {
  2421.         *b = *b | ( (*a-'0')&0x000f );
  2422.         b++;
  2423.      }
  2424.      a++;
  2425.   }
  2426. }
  2427.  
  2428. /************************************************************/
  2429. /* p_initialise - initialise our data array                 */
  2430. /************************************************************/
  2431. p_initialise(s)
  2432. int s;
  2433. {
  2434.   int j;
  2435.   for (j=0;j<4;j++) p[s].iosb[j] = 0;
  2436.   p[s].channel = 0;
  2437.   p[s].fd_buff_size = -1;
  2438.   p[s].accept_pending = 0;
  2439.   p[s].connect_pending = 0;
  2440.   p[s].connected = 0;
  2441.   p[s].fd_buff = NULL;
  2442.   p[s].fd_leftover = NULL;
  2443.   p[s].fptr = NULL;
  2444.   p[s].s = s;
  2445.   p[s].name.in.sin_port = 0;
  2446.   p[s].masklen = 4;
  2447.   for (j=0;j<16;j++) p[s].mask[j] = 0xff;
  2448.   p[s].need_header = 0;
  2449.   p[s].status = INITIALISED;
  2450.   p[s].read_outstanding = 0;
  2451.   p[s].cmu_open = 0;
  2452.   p[s].x25_listener = 0;
  2453.   p[s].mother = s;
  2454.   p[s].child = 0;
  2455.   p[s].no_more_accepts = 0;
  2456.   p[s].closed_by_remote = 0;
  2457.   p[s].non_blocking = 0;
  2458.   p[s].sig_req = 0;
  2459.   sys$clref(s);
  2460. }
  2461.  
  2462. /************************************************************/
  2463. /* decode_ncb - decode a network control block              */
  2464. /************************************************************/
  2465. decode_ncb(ncb,addr)
  2466. char *ncb;
  2467. union socket_addr *addr;
  2468. {
  2469.   int maxm,j;
  2470.   maxm = *ncb;
  2471.   ncb++;
  2472.   j = 0;
  2473.   addr->x25.hostlen = 0;
  2474.   addr->x25.datalen = 0;
  2475.   while (j<maxm) {
  2476.      if (*(ncb+2) == psi$c_ncb_incoming_dte) {
  2477.         addr->x25.hostlen = *(ncb+4);
  2478.         ascic_to_bcd(ncb+4,addr->x25.host);
  2479.      }
  2480.      if (*(ncb+2) == psi$c_ncb_userdata) {
  2481.         addr->x25.datalen = *(ncb+4);
  2482.         bcopy(ncb+5,addr->x25.data,addr->x25.datalen);
  2483.      }
  2484.      j += *ncb;
  2485.      ncb += *ncb;
  2486.   }
  2487. }
  2488.  
  2489. /************************************************************/
  2490. /* setup_npb - configure our network parameter block        */
  2491. /************************************************************/
  2492. setup_npb(s,npb_blk)
  2493. int s;
  2494. char *npb_blk;
  2495. {
  2496.   int i, subaddress;
  2497.   myx25_subaddress(&subaddress);
  2498.   for (i=0;i<64;i++) npb_blk[i] = 0;
  2499.   i = 0;
  2500.   npb_blk[0] = 10;
  2501.   npb_blk[2] = psi$c_ntd_acclvl;
  2502.   strcpy(npb_blk+4,"\5X25L3");
  2503.   i += npb_blk[i];
  2504.   if (p[s].name.x25.datalen != 0) {
  2505.      npb_blk[i] = p[s].name.x25.datalen + 5;
  2506.      npb_blk[i+2] = psi$c_ntd_usrdata;
  2507.      bcopy(&(p[s].name.x25.datalen),npb_blk+i+4,p[s].name.x25.datalen+1);
  2508.      i += npb_blk[i];
  2509.      npb_blk[i] = p[s].masklen + 5;
  2510.      npb_blk[i+2] = psi$c_ntd_datmsk;
  2511.      bcopy(&(p[s].masklen),npb_blk+i+4,p[s].masklen+1);
  2512.      i += npb_blk[i];
  2513.   }
  2514.   if (subaddress != -1) {
  2515.      npb_blk[i] = 6;
  2516.      npb_blk[i+2] = psi$c_ntd_salo;
  2517.      npb_blk[i+4] = subaddress;
  2518.      i += npb_blk[i];
  2519.      npb_blk[i] = 6;
  2520.      npb_blk[i+2] = psi$c_ntd_sahi;
  2521.      npb_blk[i+4] = subaddress;
  2522.      i += npb_blk[i];
  2523.   }
  2524.   return(i);
  2525. }
  2526.  
  2527. /************************************************************/
  2528. /* setup_ncb - configure our network control block          */
  2529. /************************************************************/
  2530. setup_ncb(s,name)
  2531. int s;
  2532. union socket_addr *name;
  2533. {
  2534.   char *t, *z, *getenv();
  2535.   int i;
  2536.   i = 0;
  2537.   t = getenv("X25_ADDRESS");
  2538.   z = getenv("X25_SUBADDRESS");
  2539.   p[s].ncb[0] = name->x25.hostlen+5;
  2540.   p[s].ncb[1] = 0;
  2541.   p[s].ncb[2] = psi$c_ncb_remdte;
  2542.   p[s].ncb[3] = 0;
  2543.   bcd_to_ascic(&(name->x25.host),p[s].ncb+4,name->x25.hostlen);
  2544. /*  i += p[s].ncb[i];
  2545.   p[s].ncb[i] = strlen(t)+strlen(z)+5;
  2546.   p[s].ncb[i+1] = 0;
  2547.   p[s].ncb[i+2] = psi$c_ncb_locsubadr;
  2548.   p[s].ncb[i+3] = 0;
  2549.   p[s].ncb[i+4] = strlen(t)+strlen(z);
  2550.   bcopy(t,p[s].ncb+i+5,strlen(t));
  2551.   bcopy(z,p[s].ncb+i+5+strlen(t),strlen(z));*/
  2552.   i += p[s].ncb[i];
  2553.   if (name->x25.datalen != 0) {
  2554.      p[s].ncb[i] = name->x25.datalen+5;
  2555.      p[s].ncb[i+1] = 0;
  2556.      p[s].ncb[i+2] = psi$c_ncb_userdata;
  2557.      p[s].ncb[i+3] = 0;
  2558.      bcopy(&(name->x25.datalen),p[s].ncb+i+4,name->x25.datalen+1);
  2559.      i += p[s].ncb[i];
  2560.   }
  2561.   return(i);
  2562. }
  2563.  
  2564. /************************************************************/
  2565. /* type_ahead - returns number of chars to be read          */
  2566. /************************************************************/
  2567. type_ahead()
  2568. {
  2569.   int st;
  2570.   short int buf[4];
  2571.   short int iosb[4];
  2572.   struct descriptor termdesc;
  2573.  
  2574.   if (terminal.chan == -1) {
  2575.      termdesc.size = 10;
  2576.      termdesc.ptr = "SYS$INPUT:";
  2577.      sys$assign(&termdesc,&terminal.chan,0,0);
  2578.   }
  2579.   st = sys$qiow(0,terminal.chan,IO$_SENSEMODE | IO$M_TYPEAHDCNT,iosb,0,0,
  2580.    buf,8,0,0,0,0);
  2581.   /* remember we may have already pre-read one of the chars!*/
  2582.   if (st != SS$_NORMAL || iosb[0] != SS$_NORMAL) return(0);
  2583.   return(buf[0]+terminal.char_available);
  2584. }
  2585.  
  2586. /************************************************************/
  2587. /* stty - obsolete form of ioctl                            */
  2588. /************************************************************/
  2589. stty(fd,buf)
  2590. int fd;
  2591. struct sgttyb *buf;
  2592. {
  2593.   ioctl(fd, TIOCSETP, buf);
  2594. }
  2595.  
  2596. /************************************************************/
  2597. /* gtty - obsolete form of ioctl                            */
  2598. /************************************************************/
  2599. gtty(fd,buf)
  2600. int fd;
  2601. struct sgttyb *buf;
  2602. {
  2603.   ioctl(fd, TIOCGETP, buf);
  2604. }
  2605.  
  2606. /************************************************************/
  2607. /* set_noecho - just a utility routine to cancel term echo  */
  2608. /************************************************************/
  2609. set_noecho()
  2610. {
  2611.   int st;
  2612.   int buf[3];
  2613.   short int iosb[4];
  2614.   struct descriptor termdesc;
  2615.  
  2616.   if (terminal.chan == -1) {
  2617.      termdesc.size = 10;
  2618.      termdesc.ptr = "SYS$INPUT:";
  2619.      sys$assign(&termdesc,&terminal.chan,0,0);
  2620.   }
  2621.   st = sys$qiow(0,terminal.chan,IO$_SENSEMODE,iosb,0,0,buf,12,0,0,0,0);
  2622.   buf[1] |= TT$M_NOECHO;
  2623.   st = sys$qiow(0,terminal.chan,IO$_SETMODE,iosb,0,0,buf,12,0,0,0,0);
  2624. }
  2625.  
  2626. /************************************************************/
  2627. /* set_echo - just a utility routine to start term echo     */
  2628. /************************************************************/
  2629. set_echo()
  2630. {
  2631.   int st;
  2632.   int buf[3];
  2633.   short int iosb[4];
  2634.   struct descriptor termdesc;
  2635.  
  2636.   if (terminal.chan == -1) {
  2637.      termdesc.size = 10;
  2638.      termdesc.ptr = "SYS$INPUT:";
  2639.      sys$assign(&termdesc,&terminal.chan,0,0);
  2640.   }
  2641.   st = sys$qiow(0,terminal.chan,IO$_SENSEMODE,iosb,0,0,buf,12,0,0,0,0);
  2642.   buf[1] &= ~TT$M_NOECHO;
  2643.   st = sys$qiow(0,terminal.chan,IO$_SETMODE,iosb,0,0,buf,12,0,0,0,0);
  2644. }
  2645.  
  2646. /************************************************************/
  2647. /* get1c - get 1 char from term without echoing it          */
  2648. /************************************************************/
  2649. int get1c()
  2650. {
  2651.   int i;
  2652.   char q[4];
  2653.   short int iosb[4];
  2654.   struct descriptor termdesc;
  2655.  
  2656.   if (terminal.chan == -1) {
  2657.      termdesc.size = 10;
  2658.      termdesc.ptr = "SYS$INPUT:";
  2659.      sys$assign(&termdesc,&terminal.chan,0,0);
  2660.   }
  2661.  
  2662.   if (terminal.char_available == 1) {
  2663.      /* CRW add */
  2664.      terminal.char_available = 0;
  2665.      /* CRW end */
  2666.      i = terminal.c[0];
  2667.      if (i == 13) i = 10;
  2668.      return(i);
  2669.   }
  2670.  
  2671.   sys$qiow(0,terminal.chan,IO$_READVBLK | IO$M_NOECHO | IO$M_NOFILTR,
  2672.    terminal.iosb,0,0,q,1,0,0,0,0);
  2673.   i = q[0];
  2674.   if (i == 13) i = 10;
  2675.   return(i);
  2676. }
  2677.  
  2678. /************************************************************/
  2679. /* getnc - get n chars from term without echoing them       */
  2680. /************************************************************/
  2681. getnc(s,i)
  2682. char *s;
  2683. int i;
  2684. {
  2685.   int j, k;
  2686.   char *q;
  2687.   short int iosb[4];
  2688.   struct descriptor termdesc;
  2689.  
  2690.   j = 0;
  2691.   q = s;
  2692.   if (terminal.chan == -1) {
  2693.      termdesc.size = 10;
  2694.      termdesc.ptr = "SYS$INPUT:";
  2695.      sys$assign(&termdesc,&terminal.chan,0,0);
  2696.   }
  2697.   if (i == 0) {
  2698.      sys$cancel(terminal.chan);
  2699.      sys$dassgn(terminal.chan);
  2700.      terminal.chan = -1;
  2701.      return(0);
  2702.   }
  2703.   if (terminal.char_available == 1) {
  2704.      *q = terminal.c[0];
  2705.      /* CRW add */
  2706.      terminal.char_available = 0;
  2707.      /* CRW end */
  2708.      if (*q == 13) *q = 10;
  2709.      q++;
  2710.      i--;
  2711.      j++;
  2712.   }
  2713.   if (i == 0) return(j);
  2714.   sys$qiow(0,terminal.chan,IO$_READVBLK | IO$M_NOECHO | IO$M_NOFILTR,
  2715.    terminal.iosb,0,0,q,i,0,0,0,0);
  2716.   for (q=s,k=0; k<i+j; k++,q++) if (*q == 13) *q = 10;
  2717.   return(i+j);
  2718. }
  2719.  
  2720. /************************************************************/
  2721. /* read_efn - see whether an event flag is set              */
  2722. /************************************************************/
  2723. read_efn(i)
  2724. int i;
  2725. {
  2726.   int j;
  2727.   sys$readef(i,&j);
  2728.   j = j&(1<<i);
  2729.   return(j);
  2730. }
  2731.  
  2732. /************************************************************/
  2733. /* dmphx - dump a buffer to the debug log in hex and ascii  */
  2734. /************************************************************/
  2735. dmphx(f,msg,len)
  2736. FILE *f;
  2737. unsigned char *msg;
  2738. int len;
  2739. {
  2740.   int i, j;
  2741.   unsigned char *v, *w;
  2742.  
  2743.   v = w = msg;
  2744.   j = len;
  2745.   while (j>0) {
  2746.      if (j>16) i = 16; else i=j;
  2747.      for(;i>0;i--,v++) fprintf(f," %02x",*v);
  2748.      if (j<16) for(i=16-j;i>0;i--) fprintf(f,"   ");
  2749.      fprintf(f,"        ");
  2750.      if (j>16) i = 16; else i=j;
  2751.      for(;i>0;i--,w++) fprintf(f,"%c",(*w>0x1f && *w<0x80)? *w : '.');
  2752.      fprintf(f,"\n");
  2753.      j -= 16;
  2754.   }
  2755. }
  2756.  
  2757. static set_tcp_make()
  2758. {
  2759.   struct descriptor inetdesc;
  2760.   int channel;
  2761.   /* first try CMU */
  2762.   inetdesc.size = 3;
  2763.   inetdesc.ptr = "IP:";
  2764.   if (sys$assign(&inetdesc,&channel,0,0) == SS$_NORMAL) {
  2765.      sys$dassgn(channel);
  2766.      tcp_make = CMU;
  2767.      return;
  2768.   }
  2769.   /* next try WG */
  2770.   inetdesc.size = 7;
  2771.   inetdesc.ptr = "_INET0:";
  2772.   if (sys$assign(&inetdesc,&channel,0,0) == SS$_NORMAL) {
  2773.      sys$dassgn(channel);
  2774.      tcp_make = WG;
  2775.      return;
  2776.   }
  2777.   /* next try UCX */
  2778.   inetdesc.size = 4;
  2779.   inetdesc.ptr = "BG0:";
  2780.   if (sys$assign(&inetdesc,&channel,0,0) == SS$_NORMAL) {
  2781.       sys$dassgn(channel);
  2782.       tcp_make = UCX;
  2783.       return;
  2784.   }
  2785.  
  2786.   /* nothing there oh dear!*/
  2787.   tcp_make = NONE;
  2788.   return;
  2789. }
  2790.  
  2791. stricmp(s1,s2)
  2792.   char *s1;
  2793.   char *s2;
  2794. {
  2795.   int diff = 'a' - 'A';
  2796.  
  2797.   while ((*s1 != '\0') && (*s2 != '\0')) {
  2798.     if (((islower(*s1)) ? (*s1 - diff) : (*s1)) !=
  2799.         ((islower(*s2)) ? (*s2 - diff) : (*s2)))
  2800.       return(((islower(*s1)) ? (*s1 - diff) : (*s1)) -
  2801.              ((islower(*s2)) ? (*s2 - diff) : (*s2)));
  2802.   s1++, s2++;
  2803.   }
  2804.  
  2805.   return(0);
  2806. }
  2807.  
  2808. static char *getdevicename(channel)
  2809. unsigned short int channel;
  2810. {
  2811.    int st;
  2812.    struct {
  2813.       struct itemlist id;
  2814.       int eol;
  2815.    } itmlst;
  2816.    static char name[64];
  2817.    short int lgth;
  2818.  
  2819.    name[0] = '\0';
  2820.    itmlst.id.code = DVI$_DEVNAM;
  2821.    itmlst.id.length = 64;
  2822.    itmlst.id.dataptr = name;
  2823.    itmlst.id.retlenptr = &lgth;
  2824.    itmlst.eol = 0;
  2825.    if ((st=sys$getdvi(0,channel,0,&itmlst,0,0,0,0)) != SS$_NORMAL) {
  2826.       fprintf(stderr, "error getting device name %d\n",st);
  2827.    }
  2828.    return(name);
  2829. }
  2830.  
  2831. #define inpipe 18
  2832. #define outpipe 19
  2833. get_socket_info()
  2834. {
  2835.    int i, st, domain, type;
  2836.    char buffer[64];
  2837.    struct descriptor inetdesc;
  2838.    char *getenv();
  2839.  
  2840.    if ( ! tcp_make) set_tcp_make();
  2841.    if (tcp_make != WG) return(-1);
  2842.   if (p_initialised == 0) {
  2843.      for (i=0;i<32;i++) p_initialise(i);
  2844.      if ((getenv("PACKET_TRACE") != NULL) &&
  2845.       (strcmp(getenv("PACKET_TRACE"),"TRUE") == 0)) {
  2846.         trace__ = 1;
  2847.         ftrace__ = fopen("packet_trace.log","w");
  2848.      }
  2849.      p_initialised = 1;
  2850.   }
  2851.  
  2852.    i = 0;
  2853.    read(inpipe, &i, sizeof(int));
  2854.    while (i != 0) {
  2855.       read(inpipe, &domain, sizeof(int));
  2856.       read(inpipe, &type, sizeof(int));
  2857.       read(inpipe, buffer, 64);
  2858.       inetdesc.size = strlen(buffer);
  2859.       inetdesc.ptr  = buffer;
  2860.       if ((st=sys$assign(&inetdesc,&p[i].channel,0,0)) != SS$_NORMAL){
  2861.          fprintf(stderr,"assign new channel %s - %d\n",buffer,st);
  2862.          return(-1);
  2863.       }
  2864.       p[i].status = PASSIVE_CONNECTION;
  2865.       p[i].domain = domain;
  2866.       p[i].type = type;
  2867.       p[i].passive = 1;
  2868.       p[i].fptr = fdopen(i,"r");
  2869.       p[i].fd_buff = (unsigned char *)malloc(BUF_SIZE);
  2870.       hang_a_read(i);
  2871.       read(inpipe, &i, sizeof(int));
  2872.    }
  2873.    return(0);
  2874. }
  2875.  
  2876. send_socket_info()
  2877. {
  2878.    int pipes[2], i, st, dummy;
  2879.  
  2880.    if (tcp_make == WG) {
  2881. /*we need to search through our fd_entry structure to find which entries
  2882. to hand on to the child*/
  2883.       pipe(pipes);
  2884.       dup2(pipes[0], inpipe);
  2885.       dup2(pipes[1], outpipe);
  2886.       close(pipes[0]);close(pipes[1]);
  2887.       for (i=0;i<32;i++) {
  2888.          if (p[i].status == PASSIVE_CONNECTION) {
  2889.             p[i].status = HANDED_OFF;
  2890.             write(outpipe, (char *)&i, sizeof(int));
  2891.             write(outpipe, (char *)&(p[i].domain), sizeof(int));
  2892.             write(outpipe, (char *)&(p[i].type), sizeof(int));
  2893.             write(outpipe, getdevicename(p[i].channel), 64);
  2894.             dummy = SETCHAR_HANDOFF;
  2895.             st = sys$qiow(0,p[i].channel,IO$_SETCHAR,p[i].iosb,0,0,&dummy,0,0,0,0,0);
  2896.             sys$dassgn(p[i].channel);
  2897.          }
  2898.       }
  2899.       i = 0;
  2900.       write(outpipe, (char *)&i, sizeof(int));
  2901.    }
  2902. }
  2903.