Back to index

im-sdk  12.3.91
Xtrans.c
Go to the documentation of this file.
00001 /* $XConsortium: Xtrans.c,v 1.31 95/03/28 19:49:02 mor Exp $ */
00002 /*
00003 
00004 Copyright (c) 1993, 1994  X Consortium
00005 
00006 Permission is hereby granted, free of charge, to any person obtaining
00007 a copy of this software and associated documentation files (the
00008 "Software"), to deal in the Software without restriction, including
00009 without limitation the rights to use, copy, modify, merge, publish,
00010 distribute, sublicense, and/or sell copies of the Software, and to
00011 permit persons to whom the Software is furnished to do so, subject to
00012 the following conditions:
00013 
00014 The above copyright notice and this permission notice shall be included
00015 in all copies or substantial portions of the Software.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00018 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00019 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00020 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
00021 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00022 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00023 OTHER DEALINGS IN THE SOFTWARE.
00024 
00025 Except as contained in this notice, the name of the X Consortium shall
00026 not be used in advertising or otherwise to promote the sale, use or
00027 other dealings in this Software without prior written authorization
00028 from the X Consortium.
00029 
00030 */
00031 
00032 /* Copyright (c) 1993, 1994 NCR Corporation - Dayton, Ohio, USA
00033  *
00034  * All Rights Reserved
00035  *
00036  * Permission to use, copy, modify, and distribute this software and its
00037  * documentation for any purpose and without fee is hereby granted, provided
00038  * that the above copyright notice appear in all copies and that both that
00039  * copyright notice and this permission notice appear in supporting
00040  * documentation, and that the name NCR not be used in advertising
00041  * or publicity pertaining to distribution of the software without specific,
00042  * written prior permission.  NCR makes no representations about the
00043  * suitability of this software for any purpose.  It is provided "as is"
00044  * without express or implied warranty.
00045  *
00046  * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
00047  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
00048  * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
00049  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
00050  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
00051  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
00052  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00053  */
00054 
00055 #include <ctype.h>
00056 
00057 /*
00058  * The transport table contains a definition for every transport (protocol)
00059  * family. All operations that can be made on the transport go through this
00060  * table.
00061  *
00062  * Each transport is assigned a unique transport id.
00063  *
00064  * New transports can be added by adding an entry in this table.
00065  * For compatiblity, the transport ids should never be renumbered.
00066  * Always add to the end of the list.
00067  */
00068 
00069 #define TRANS_TLI_INET_INDEX              1
00070 #define TRANS_TLI_TCP_INDEX        2
00071 #define TRANS_TLI_TLI_INDEX        3
00072 #define TRANS_SOCKET_UNIX_INDEX           4
00073 #define TRANS_SOCKET_LOCAL_INDEX   5
00074 #define TRANS_SOCKET_INET_INDEX           6
00075 #define TRANS_SOCKET_TCP_INDEX            7
00076 #define TRANS_DNET_INDEX           8
00077 #define TRANS_LOCAL_LOCAL_INDEX           9
00078 #define TRANS_LOCAL_PTS_INDEX             10
00079 #define TRANS_LOCAL_NAMED_INDEX           11
00080 #define TRANS_LOCAL_ISC_INDEX             12
00081 #define TRANS_LOCAL_SCO_INDEX             13
00082 #define TRANS_AMOEBA_INDEX         14
00083 
00084 
00085 static
00086 Xtransport_table Xtransports[] = {
00087 #if defined(STREAMSCONN)
00088     {&TRANS(TLITCPFuncs),   TRANS_TLI_TCP_INDEX},
00089     {&TRANS(TLIINETFuncs),  TRANS_TLI_INET_INDEX},
00090     {&TRANS(TLITLIFuncs),   TRANS_TLI_TLI_INDEX},
00091 #endif /* STREAMSCONN */
00092 #if defined(TCPCONN)
00093     {&TRANS(SocketTCPFuncs),       TRANS_SOCKET_TCP_INDEX},
00094     {&TRANS(SocketINETFuncs),      TRANS_SOCKET_INET_INDEX},
00095 #endif /* TCPCONN */
00096 #if defined(DNETCONN)
00097     {&TRANS(DNETFuncs),            TRANS_DNET_INDEX},
00098 #endif /* DNETCONN */
00099 #if defined(UNIXCONN)
00100 #if !defined(LOCALCONN)
00101     {&TRANS(SocketLocalFuncs),     TRANS_SOCKET_LOCAL_INDEX},
00102 #endif /* !LOCALCONN */
00103     {&TRANS(SocketUNIXFuncs),      TRANS_SOCKET_UNIX_INDEX},
00104 #endif /* UNIXCONN */
00105 #if defined(LOCALCONN)
00106     {&TRANS(LocalFuncs),    TRANS_LOCAL_LOCAL_INDEX},
00107     {&TRANS(PTSFuncs),             TRANS_LOCAL_PTS_INDEX},
00108     {&TRANS(NAMEDFuncs),    TRANS_LOCAL_NAMED_INDEX},
00109     {&TRANS(ISCFuncs),             TRANS_LOCAL_ISC_INDEX},
00110     {&TRANS(SCOFuncs),             TRANS_LOCAL_SCO_INDEX},
00111 #endif /* LOCALCONN */
00112 #if defined(AMRPCCONN) || defined(AMTCPCONN)
00113     {&TRANS(AmConnFuncs),   TRANS_AMOEBA_INDEX},
00114 #endif /* AMRPCCONN || AMTCPCONN */
00115 };
00116 
00117 #define NUMTRANS     (sizeof(Xtransports)/sizeof(Xtransport_table))
00118 
00119 
00120 #ifdef WIN32
00121 #define ioctl ioctlsocket
00122 #endif
00123 
00124 
00125 
00126 /*
00127  * These are a few utility function used by the public interface functions.
00128  */
00129 
00130 void
00131 TRANS(FreeConnInfo) (ciptr)
00132 
00133 XtransConnInfo ciptr;
00134 
00135 {
00136     PRMSG (3,"TRANS(FreeConnInfo) (%x)\n", ciptr, 0, 0);
00137 
00138     if (ciptr->addr)
00139        free (ciptr->addr);
00140 
00141     if (ciptr->peeraddr)
00142        free (ciptr->peeraddr);
00143 
00144     if (ciptr->port)
00145        free (ciptr->port);
00146 
00147     free ((char *) ciptr);
00148 }
00149 
00150 
00151 #define PROTOBUFSIZE 20
00152 
00153 static Xtransport *
00154 TRANS(SelectTransport) (protocol)
00155 
00156 char *protocol;
00157 
00158 {
00159     char      protobuf[PROTOBUFSIZE];
00160     int              i;
00161 
00162     PRMSG (3,"TRANS(SelectTransport) (%s)\n", protocol, 0, 0);
00163 
00164     /*
00165      * Force Protocol to be lowercase as a way of doing
00166      * a case insensitive match.
00167      */
00168 
00169     strncpy (protobuf, protocol, PROTOBUFSIZE);
00170 
00171     for (i = 0; i < PROTOBUFSIZE && protobuf[i] != '\0'; i++)
00172        if (isupper (protobuf[i]))
00173            protobuf[i] = tolower (protobuf[i]);
00174 
00175     /* Look at all of the configured protocols */
00176 
00177     for (i = 0; i < NUMTRANS; i++)
00178     {
00179        if (!strcmp (protobuf, Xtransports[i].transport->TransName))
00180            return Xtransports[i].transport;
00181     }
00182 
00183     return NULL;
00184 }
00185 
00186 #ifndef TEST_t
00187 static
00188 #endif /* TEST_t */
00189 int
00190 TRANS(ParseAddress) (address, protocol, host, port)
00191 
00192 char   *address;
00193 char   **protocol;
00194 char   **host;
00195 char   **port;
00196 
00197 {
00198     /*
00199      * For the font library, the address is a string formatted
00200      * as "protocol/host:port[/catalogue]".  Note that the catologue
00201      * is optional.  At this time, the catologue info is ignored, but
00202      * we have to parse it anyways.
00203      *
00204      * Other than fontlib, the address is a string formatted
00205      * as "protocol/host:port".
00206      *
00207      * If the protocol part is missing, then assume INET.
00208      * If the protocol part and host part are missing, then assume local.
00209      * If a "::" is found then assume DNET.
00210      */
00211 
00212     char      *mybuf, *tmpptr;
00213     char      *_protocol, *_host, *_port;
00214     char      hostnamebuf[256];
00215 
00216     PRMSG (3,"TRANS(ParseAddress) (%s)\n", address, 0, 0);
00217 
00218     /* Copy the string so it can be changed */
00219 
00220     tmpptr = mybuf = (char *) malloc (strlen (address) + 1);
00221     strcpy (mybuf, address);
00222 
00223     /* Parse the string to get each component */
00224     
00225     /* Get the protocol part */
00226 
00227     _protocol = mybuf;
00228 
00229     if ((mybuf = strpbrk (mybuf,"/:")) == NULL)
00230     {
00231        /* adress is in a bad format */
00232        *protocol = NULL;
00233        *host = NULL;
00234        *port = NULL;
00235        free (tmpptr);
00236        return 0;
00237     }
00238 
00239     if (*mybuf == ':')
00240     {
00241        /*
00242         * If there is a hostname, then assume inet, otherwise
00243         * it must be local.
00244         */
00245        if (mybuf == tmpptr)
00246        {
00247            /* There is neither a protocol or host specified */
00248            _protocol = "local";
00249        }
00250        else
00251        {
00252            /* Ther is a hostname specified */
00253            _protocol = "inet";
00254            mybuf = tmpptr;  /* reset to the begining of the host ptr */
00255        }
00256     }
00257     else
00258     {
00259        /* *mybuf == '/' */
00260 
00261        *mybuf ++= '\0'; /* put a null at the end of the protocol */
00262 
00263        if (strlen(_protocol) == 0)
00264        {
00265            /*
00266             * If there is a hostname, then assume inet, otherwise
00267             * it must be local.
00268             */
00269            if (*mybuf != ':')
00270               _protocol = "inet";
00271            else
00272               _protocol = "local";
00273        }
00274     }
00275 
00276     /* Get the host part */
00277 
00278     _host = mybuf;
00279 
00280     if ((mybuf = strchr (mybuf,':')) == NULL)
00281     {
00282        *protocol = NULL;
00283        *host = NULL;
00284        *port = NULL;
00285        free (tmpptr);
00286        return 0;
00287     }
00288 
00289     *mybuf ++= '\0';
00290 
00291     if (strlen(_host) == 0)
00292     {
00293        TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
00294        _host = hostnamebuf;
00295     }
00296 
00297     /* Check for DECnet */
00298 
00299     if (*mybuf == ':')
00300     {
00301        _protocol = "dnet";
00302        mybuf++;
00303     }
00304 
00305     /* Get the port */
00306 
00307 /*
00308 get_port:
00309 */
00310 
00311     _port = mybuf;
00312 
00313 #if defined(FONT_t) || defined(FS_t)
00314     /*
00315      * Is there an optional catalogue list?
00316      */
00317 
00318     if ((mybuf = strchr (mybuf,'/')) != NULL)
00319        *mybuf ++= '\0';
00320 
00321     /*
00322      * The rest, if any, is the (currently unused) catalogue list.
00323      *
00324      * _catalogue = mybuf;
00325      */
00326 #endif
00327 
00328     /*
00329      * Now that we have all of the components, allocate new
00330      * string space for them.
00331      */
00332 
00333     if ((*protocol = (char *) malloc(strlen (_protocol) + 1)) == NULL)
00334     {
00335        /* Malloc failed */
00336        *port = NULL;
00337        *host = NULL;
00338        *protocol = NULL;
00339        free (tmpptr);
00340        return 0;
00341     }
00342     else
00343         strcpy (*protocol, _protocol);
00344 
00345     if ((*host = (char *) malloc (strlen (_host) + 1)) == NULL)
00346     {
00347        /* Malloc failed */
00348        *port = NULL;
00349        *host = NULL;
00350        free (*protocol);
00351        *protocol = NULL;
00352        free (tmpptr);
00353        return 0;
00354        }
00355     else
00356         strcpy (*host, _host);
00357 
00358     if ((*port = (char *) malloc (strlen (_port) + 1)) == NULL)
00359     {
00360        /* Malloc failed */
00361        *port = NULL;
00362        free (*host);
00363        *host = NULL;
00364        free (*protocol);
00365        *protocol = NULL;
00366        free (tmpptr);
00367        return 0;
00368     }
00369     else
00370         strcpy (*port, _port);
00371 
00372     free (tmpptr);
00373 
00374     return 1;
00375 }
00376 
00377 
00378 /*
00379  * TRANS(Open) does all of the real work opening a connection. The only
00380  * funny part about this is the type parameter which is used to decide which
00381  * type of open to perform.
00382  */
00383 
00384 static XtransConnInfo
00385 TRANS(Open) (type, address)
00386 
00387 int    type;
00388 char   *address;
00389 
00390 {
00391     char             *protocol = NULL, *host = NULL, *port = NULL;
00392     XtransConnInfo   ciptr = NULL;
00393     Xtransport              *thistrans;
00394 
00395     PRMSG (2,"TRANS(Open) (%d,%s)\n", type, address, 0);
00396 
00397 #if defined(WIN32) && (defined(TCPCONN) || defined(DNETCONN))
00398     if (TRANS(WSAStartup)())
00399     {
00400        PRMSG (1,"TRANS(Open): WSAStartup failed\n", 0, 0, 0);
00401        return NULL;
00402     }
00403 #endif
00404 
00405     /* Parse the Address */
00406 
00407     if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
00408     {
00409        PRMSG (1,"TRANS(Open): Unable to Parse address %s\n", address, 0, 0);
00410        return NULL;
00411     }
00412 
00413     /* Determine the transport type */
00414 
00415     if ((thistrans = TRANS(SelectTransport) (protocol)) == NULL)
00416     {
00417        PRMSG (1,"TRANS(Open): Unable to find transport for %s\n",
00418               protocol, 0, 0);
00419 
00420        free (protocol);
00421        free (host);
00422        free (port);
00423        return NULL;
00424     }
00425 
00426     /* Open the transport */
00427 
00428     switch (type)
00429     {
00430     case XTRANS_OPEN_COTS_CLIENT:
00431 #ifdef TRANS_CLIENT
00432        ciptr = thistrans->OpenCOTSClient(thistrans, protocol, host, port);
00433 #endif /* TRANS_CLIENT */
00434        break;
00435     case XTRANS_OPEN_COTS_SERVER:
00436 #ifdef TRANS_SERVER
00437        ciptr = thistrans->OpenCOTSServer(thistrans, protocol, host, port);
00438 #endif /* TRANS_SERVER */
00439        break;
00440     case XTRANS_OPEN_CLTS_CLIENT:
00441 #ifdef TRANS_CLIENT
00442        ciptr = thistrans->OpenCLTSClient(thistrans, protocol, host, port);
00443 #endif /* TRANS_CLIENT */
00444        break;
00445     case XTRANS_OPEN_CLTS_SERVER:
00446 #ifdef TRANS_SERVER
00447        ciptr = thistrans->OpenCLTSServer(thistrans, protocol, host, port);
00448 #endif /* TRANS_SERVER */
00449        break;
00450     default:
00451        PRMSG (1,"TRANS(Open): Unknown Open type %d\n", type, 0, 0);
00452     }
00453 
00454     if (ciptr == NULL)
00455     {
00456        PRMSG (1,"TRANS(Open): transport open failed for %s/%s:%s\n",
00457               protocol, host, port);
00458        free (protocol);
00459        free (host);
00460        free (port);
00461        return NULL;
00462     }
00463 
00464     ciptr->transptr = thistrans;
00465     ciptr->port = port;                   /* We need this for TRANS(Reopen) */
00466 
00467     free (protocol);
00468     free (host);
00469 
00470     return ciptr;
00471 }
00472 
00473 
00474 #ifdef TRANS_REOPEN
00475 
00476 /*
00477  * We might want to create an XtransConnInfo object based on a previously
00478  * opened connection.  For example, the font server may clone itself and
00479  * pass file descriptors to the parent.
00480  */
00481 
00482 static XtransConnInfo
00483 TRANS(Reopen) (type, trans_id, fd, port)
00484 
00485 int    type;
00486 int    trans_id;
00487 int    fd;
00488 char   *port;
00489 
00490 {
00491     XtransConnInfo   ciptr = NULL;
00492     Xtransport              *thistrans = NULL;
00493     char             *save_port;
00494     int                     i;
00495 
00496     PRMSG (2,"TRANS(Reopen) (%d,%d,%s)\n", trans_id, fd, port);
00497 
00498     /* Determine the transport type */
00499 
00500     for (i = 0; i < NUMTRANS; i++)
00501        if (Xtransports[i].transport_id == trans_id)
00502        {
00503            thistrans = Xtransports[i].transport;
00504            break;
00505        }
00506 
00507     if (thistrans == NULL)
00508     {
00509        PRMSG (1,"TRANS(Reopen): Unable to find transport id %d\n",
00510               trans_id, 0, 0);
00511 
00512        return NULL;
00513     }
00514 
00515     if ((save_port = (char *) malloc (strlen (port) + 1)) == NULL)
00516     {
00517        PRMSG (1,"TRANS(Reopen): Unable to malloc port string\n", 0, 0, 0);
00518 
00519        return NULL;
00520     }
00521 
00522     strcpy (save_port, port);
00523 
00524     /* Get a new XtransConnInfo object */
00525 
00526     switch (type)
00527     {
00528     case XTRANS_OPEN_COTS_SERVER:
00529        ciptr = thistrans->ReopenCOTSServer(thistrans, fd, port);
00530        break;
00531     case XTRANS_OPEN_CLTS_SERVER:
00532        ciptr = thistrans->ReopenCLTSServer(thistrans, fd, port);
00533        break;
00534     default:
00535        PRMSG (1,"TRANS(Reopen): Bad Open type %d\n", type, 0, 0);
00536     }
00537 
00538     if (ciptr == NULL)
00539     {
00540        PRMSG (1,"TRANS(Reopen): transport open failed\n", 0, 0, 0);
00541        return NULL;
00542     }
00543 
00544     ciptr->transptr = thistrans;
00545     ciptr->port = save_port;
00546 
00547     return ciptr;
00548 }
00549 
00550 #endif /* TRANS_REOPEN */
00551 
00552 
00553 
00554 /*
00555  * These are the public interfaces to this Transport interface.
00556  * These are the only functions that should have knowledge of the transport
00557  * table.
00558  */
00559 
00560 #ifdef TRANS_CLIENT
00561 
00562 XtransConnInfo
00563 TRANS(OpenCOTSClient) (address)
00564 
00565 char   *address;
00566 
00567 {
00568     PRMSG (2,"TRANS(OpenCOTSClient) (%s)\n", address, 0, 0);
00569     return TRANS(Open) (XTRANS_OPEN_COTS_CLIENT, address);
00570 }
00571 
00572 #endif /* TRANS_CLIENT */
00573 
00574 
00575 #ifdef TRANS_SERVER
00576 
00577 XtransConnInfo
00578 TRANS(OpenCOTSServer) (address)
00579 
00580 char   *address;
00581 
00582 {
00583     PRMSG (2,"TRANS(OpenCOTSServer) (%s)\n", address, 0, 0);
00584     return TRANS(Open) (XTRANS_OPEN_COTS_SERVER, address);
00585 }
00586 
00587 #endif /* TRANS_SERVER */
00588 
00589 
00590 #ifdef TRANS_CLIENT
00591 
00592 XtransConnInfo
00593 TRANS(OpenCLTSClient) (address)
00594 
00595 char   *address;
00596 {
00597     PRMSG (2,"TRANS(OpenCLTSClient) (%s)\n", address, 0, 0);
00598     return TRANS(Open) (XTRANS_OPEN_CLTS_CLIENT, address);
00599 }
00600 
00601 #endif /* TRANS_CLIENT */
00602 
00603 
00604 #ifdef TRANS_SERVER
00605 
00606 XtransConnInfo
00607 TRANS(OpenCLTSServer) (address)
00608 
00609 char   *address;
00610 
00611 {
00612     PRMSG (2,"TRANS(OpenCLTSServer) (%s)\n", address, 0, 0);
00613     return TRANS(Open) (XTRANS_OPEN_CLTS_SERVER, address);
00614 }
00615 
00616 #endif /* TRANS_SERVER */
00617 
00618 
00619 #ifdef TRANS_REOPEN
00620 
00621 XtransConnInfo
00622 TRANS(ReopenCOTSServer) (trans_id, fd, port)
00623 
00624 int  trans_id;
00625 int  fd;
00626 char *port;
00627 
00628 {
00629     PRMSG (2,"TRANS(ReopenCOTSServer) (%d, %d, %s)\n", trans_id, fd, port);
00630     return TRANS(Reopen) (XTRANS_OPEN_COTS_SERVER, trans_id, fd, port);
00631 }
00632 
00633 XtransConnInfo
00634 TRANS(ReopenCLTSServer) (trans_id, fd, port)
00635 
00636 int  trans_id;
00637 int  fd;
00638 char *port;
00639 
00640 {
00641     PRMSG (2,"TRANS(ReopenCLTSServer) (%d, %d, %s)\n", trans_id, fd, port);
00642     return TRANS(Reopen) (XTRANS_OPEN_CLTS_SERVER, trans_id, fd, port);
00643 }
00644 
00645 
00646 int
00647 TRANS(GetReopenInfo) (ciptr, trans_id, fd, port)
00648 
00649 XtransConnInfo       ciptr;
00650 int           *trans_id;
00651 int           *fd;
00652 char          **port;
00653 
00654 {
00655     int i;
00656 
00657     for (i = 0; i < NUMTRANS; i++)
00658        if (Xtransports[i].transport == ciptr->transptr)
00659        {
00660            *trans_id = Xtransports[i].transport_id;
00661            *fd = ciptr->fd;
00662 
00663            if ((*port = (char *) malloc (strlen (ciptr->port) + 1)) == NULL)
00664               return 0;
00665            else
00666            {
00667               strcpy (*port, ciptr->port);
00668               return 1;
00669            }
00670        }
00671 
00672     return 0;
00673 }
00674 
00675 #endif /* TRANS_REOPEN */
00676 
00677 
00678 int
00679 TRANS(SetOption) (ciptr, option, arg)
00680 
00681 XtransConnInfo       ciptr;
00682 int           option;
00683 int           arg;
00684 
00685 {
00686     int       fd = ciptr->fd;
00687     int       ret = 0;
00688 
00689     PRMSG (2,"TRANS(SetOption) (%d,%d,%d)\n", fd, option, arg);
00690 
00691     /*
00692      * For now, all transport type use the same stuff for setting options.
00693      * As long as this is true, we can put the common code here. Once a more
00694      * complicated transport such as shared memory or an OSI implementation
00695      * that uses the session and application libraries is implemented, this
00696      * code may have to move to a transport dependent function.
00697      *
00698      * ret = ciptr->transptr->SetOption (ciptr, option, arg);
00699      */
00700 
00701     switch (option)
00702     {
00703     case TRANS_NONBLOCKING:
00704        switch (arg)
00705        {
00706        case 0:
00707            /* Set to blocking mode */
00708            break;
00709        case 1: /* Set to non-blocking mode */
00710 #if defined(O_NONBLOCK) && (!defined(ultrix) && !defined(hpux) && !defined(AIXV3) && !defined(uniosu))
00711            ret = fcntl (fd, F_SETFL, O_NONBLOCK);
00712 #else
00713 #ifdef FIOSNBIO
00714        {
00715            int arg;
00716            arg = 1;
00717            ret = ioctl (fd, FIOSNBIO, &arg);
00718        }
00719 #else
00720 #if (defined(AIXV3) || defined(uniosu) || defined(WIN32)) && defined(FIONBIO)
00721        {
00722            int arg;
00723            arg = 1;
00724            ret = ioctl (fd, FIONBIO, &arg);
00725        }
00726 #else
00727 #ifdef FNDELAY
00728            ret = fcntl (fd, F_SETFL, FNDELAY);
00729 #else
00730            ret = fcntl (fd, F_SETFL, O_NDELAY);
00731 #endif
00732 #endif /* AIXV3  || uniosu */
00733 #endif /* FIOSNBIO */
00734 #endif /* O_NONBLOCK */
00735            break;
00736        default:
00737            /* Unknown option */
00738            break;
00739        }
00740        break;
00741     case TRANS_CLOSEONEXEC:
00742 #ifdef F_SETFD
00743 #ifdef FD_CLOEXEC
00744        ret = fcntl (fd, F_SETFD, FD_CLOEXEC);
00745 #else
00746        ret = fcntl (fd, F_SETFD, 1);
00747 #endif /* FD_CLOEXEC */
00748 #endif /* F_SETFD */
00749        break;
00750     }
00751     
00752     return ret;
00753 }
00754 
00755 #ifdef TRANS_SERVER
00756 
00757 int
00758 TRANS(CreateListener) (ciptr, port)
00759 
00760 XtransConnInfo       ciptr;
00761 char          *port;
00762 
00763 {
00764     return ciptr->transptr->CreateListener (ciptr, port);
00765 }
00766 
00767 
00768 int
00769 TRANS(ResetListener) (ciptr)
00770 
00771 XtransConnInfo       ciptr;
00772 
00773 {
00774     if (ciptr->transptr->ResetListener)
00775        return ciptr->transptr->ResetListener (ciptr);
00776     else
00777        return TRANS_RESET_NOOP;
00778 }
00779 
00780 
00781 XtransConnInfo
00782 TRANS(Accept) (ciptr, status)
00783 
00784 XtransConnInfo       ciptr;
00785 int           *status;
00786 
00787 {
00788     XtransConnInfo   newciptr;
00789 
00790     PRMSG (2,"TRANS(Accept) (%d)\n", ciptr->fd, 0, 0);
00791 
00792     newciptr = ciptr->transptr->Accept (ciptr, status);
00793 
00794     if (newciptr)
00795        newciptr->transptr = ciptr->transptr;
00796 
00797     return newciptr;
00798 }
00799 
00800 #endif /* TRANS_SERVER */
00801 
00802 
00803 #ifdef TRANS_CLIENT
00804 
00805 int
00806 TRANS(Connect) (ciptr, address)
00807 
00808 XtransConnInfo       ciptr;
00809 char          *address;
00810 
00811 {
00812     char      *protocol;
00813     char      *host;
00814     char      *port;
00815     int              ret;
00816 
00817     PRMSG (2,"TRANS(Connect) (%d,%s)\n", ciptr->fd, address, 0);
00818 
00819     if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
00820     {
00821        PRMSG (1,"TRANS(Connect): Unable to Parse address %s\n",
00822               address, 0, 0);
00823        return -1;
00824     }
00825 
00826     if (!port || !*port)
00827     {
00828        PRMSG (1,"TRANS(Connect): Missing port specification in %s\n",
00829              address, 0, 0);
00830        if (protocol) free (protocol);
00831        if (host) free (host);
00832        return -1;
00833     }
00834 
00835     ret = ciptr->transptr->Connect (ciptr, host, port);
00836 
00837     if (protocol) free (protocol);
00838     if (host) free (host);
00839     if (port) free (port);
00840     
00841     return ret;
00842 }
00843 
00844 #endif /* TRANS_CLIENT */
00845 
00846 
00847 int
00848 TRANS(BytesReadable) (ciptr, pend)
00849 
00850 XtransConnInfo       ciptr;
00851 BytesReadable_t      *pend;
00852 
00853 {
00854     return ciptr->transptr->BytesReadable (ciptr, pend);
00855 }
00856 
00857 int
00858 TRANS(Read) (ciptr, buf, size)
00859 
00860 XtransConnInfo       ciptr;
00861 char          *buf;
00862 int           size;
00863 
00864 {
00865     return ciptr->transptr->Read (ciptr, buf, size);
00866 }
00867 
00868 int
00869 TRANS(Write) (ciptr, buf, size)
00870 
00871 XtransConnInfo       ciptr;
00872 char          *buf;
00873 int           size;
00874 
00875 {
00876     return ciptr->transptr->Write (ciptr, buf, size);
00877 }
00878 
00879 int
00880 TRANS(Readv) (ciptr, buf, size)
00881 
00882 XtransConnInfo       ciptr;
00883 struct iovec  *buf;
00884 int           size;
00885 {
00886     return ciptr->transptr->Readv (ciptr, buf, size);
00887 }
00888 
00889 int
00890 TRANS(Writev) (ciptr, buf, size)
00891 
00892 XtransConnInfo       ciptr;
00893 struct iovec  *buf;
00894 int           size;
00895 
00896 {
00897     return ciptr->transptr->Writev (ciptr, buf, size);
00898 }
00899 
00900 int
00901 TRANS(Disconnect) (ciptr)
00902 
00903 XtransConnInfo       ciptr;
00904 
00905 {
00906     return ciptr->transptr->Disconnect (ciptr);
00907 }
00908 
00909 int
00910 TRANS(Close) (ciptr)
00911 
00912 XtransConnInfo       ciptr;
00913 
00914 {
00915     int ret;
00916 
00917     PRMSG (2,"TRANS(Close) (%d)\n", ciptr->fd, 0, 0);
00918 
00919     ret = ciptr->transptr->Close (ciptr);
00920 
00921     TRANS(FreeConnInfo) (ciptr);
00922 
00923     return ret;
00924 }
00925 
00926 int
00927 TRANS(CloseForCloning) (ciptr)
00928 
00929 XtransConnInfo       ciptr;
00930 
00931 {
00932     int ret;
00933 
00934     PRMSG (2,"TRANS(CloseForCloning) (%d)\n", ciptr->fd, 0, 0);
00935 
00936     ret = ciptr->transptr->CloseForCloning (ciptr);
00937 
00938     TRANS(FreeConnInfo) (ciptr);
00939 
00940     return ret;
00941 }
00942 
00943 int
00944 TRANS(IsLocal) (ciptr)
00945 
00946 XtransConnInfo       ciptr;
00947 
00948 {
00949     return (ciptr->family == AF_UNIX);
00950 }
00951 
00952 
00953 int
00954 TRANS(GetMyAddr) (ciptr, familyp, addrlenp, addrp)
00955 
00956 XtransConnInfo       ciptr;
00957 int           *familyp;
00958 int           *addrlenp;
00959 Xtransaddr    **addrp;
00960 
00961 {
00962     PRMSG (2,"TRANS(GetMyAddr) (%d)\n", ciptr->fd, 0, 0);
00963 
00964     *familyp = ciptr->family;
00965     *addrlenp = ciptr->addrlen;
00966 
00967     if ((*addrp = (Xtransaddr *) malloc (ciptr->addrlen)) == NULL)
00968     {
00969        PRMSG (1,"TRANS(GetMyAddr) malloc failed\n", 0, 0, 0);
00970        return -1;
00971     }
00972     memcpy(*addrp, ciptr->addr, ciptr->addrlen);
00973 
00974     return 0;
00975 }
00976 
00977 int
00978 TRANS(GetPeerAddr) (ciptr, familyp, addrlenp, addrp)
00979 
00980 XtransConnInfo       ciptr;
00981 int           *familyp;
00982 int           *addrlenp;
00983 Xtransaddr    **addrp;
00984 
00985 {
00986     PRMSG (2,"TRANS(GetPeerAddr) (%d)\n", ciptr->fd, 0, 0);
00987 
00988     *familyp = ciptr->family;
00989     *addrlenp = ciptr->peeraddrlen;
00990 
00991     if ((*addrp = (Xtransaddr *) malloc (ciptr->peeraddrlen)) == NULL)
00992     {
00993        PRMSG (1,"TRANS(GetPeerAddr) malloc failed\n", 0, 0, 0);
00994        return -1;
00995     }
00996     memcpy(*addrp, ciptr->peeraddr, ciptr->peeraddrlen);
00997 
00998     return 0;
00999 }
01000 
01001 
01002 int
01003 TRANS(GetConnectionNumber) (ciptr)
01004 
01005 XtransConnInfo       ciptr;
01006 
01007 {
01008     return ciptr->fd;
01009 }
01010 
01011 
01012 /*
01013  * These functions are really utility functions, but they require knowledge
01014  * of the internal data structures, so they have to be part of the Transport
01015  * Independant API.
01016  */
01017 
01018 static int
01019 complete_network_count ()
01020 
01021 {
01022     int count = 0;
01023     int found_local = 0;
01024     int i;
01025 
01026     /*
01027      * For a complete network, we only need one LOCALCONN transport to work
01028      */
01029 
01030     for (i = 0; i < NUMTRANS; i++)
01031     {
01032        if (Xtransports[i].transport->flags & TRANS_ALIAS)
01033            continue;
01034 
01035        if (Xtransports[i].transport->flags & TRANS_LOCAL)
01036            found_local = 1;
01037        else
01038            count++;
01039     }
01040 
01041     return (count + found_local);
01042 }
01043 
01044 
01045 #ifdef TRANS_SERVER
01046 
01047 int
01048 TRANS(MakeAllCOTSServerListeners) (port, partial, count_ret, ciptrs_ret)
01049 
01050 char          *port;
01051 int           *partial;
01052 int           *count_ret;
01053 XtransConnInfo       **ciptrs_ret;
01054 
01055 {
01056     char             buffer[256]; /* ??? What size ?? */
01057     XtransConnInfo   ciptr, temp_ciptrs[NUMTRANS];
01058     int                     status, i, j;
01059 
01060     PRMSG (2,"TRANS(MakeAllCOTSServerListeners) (%s,%x)\n",
01061           port ? port : "NULL", ciptrs_ret, 0);
01062 
01063     *count_ret = 0;
01064 
01065     for (i = 0; i < NUMTRANS; i++)
01066     {
01067        Xtransport *trans = Xtransports[i].transport;
01068 
01069        if (trans->flags&TRANS_ALIAS)
01070            continue;
01071 
01072        sprintf(buffer,"%s/:%s", trans->TransName, port ? port : "");
01073 
01074        PRMSG (5,"TRANS(MakeAllCOTSServerListeners) opening %s\n",
01075               buffer, 0, 0);
01076 
01077        if ((ciptr = TRANS(OpenCOTSServer(buffer))) == NULL)
01078        {
01079            PRMSG (1,
01080          "TRANS(MakeAllCOTSServerListeners) failed to open listener for %s\n",
01081                 trans->TransName, 0, 0);
01082            continue;
01083        }
01084 
01085        if ((status = TRANS(CreateListener (ciptr, port))) < 0)
01086        {
01087            if (status == TRANS_ADDR_IN_USE)
01088            {
01089               /*
01090                * We failed to bind to the specified address because the
01091                * address is in use.  It must be that a server is already
01092                * running at this address, and this function should fail.
01093                */
01094 
01095               PRMSG (1,
01096               "TRANS(MakeAllCOTSServerListeners) server already running\n",
01097                 0, 0, 0);
01098 
01099               for (j = 0; j < *count_ret; j++)
01100                   TRANS(Close) (temp_ciptrs[j]);
01101 
01102               *count_ret = 0;
01103               *ciptrs_ret = NULL;
01104               *partial = 0;
01105               return -1;
01106            }
01107            else
01108            {
01109               PRMSG (1,
01110        "TRANS(MakeAllCOTSServerListeners) failed to create listener for %s\n",
01111                 trans->TransName, 0, 0);
01112 
01113               continue;
01114            }
01115        }
01116 
01117        PRMSG (5,
01118              "TRANS(MakeAllCOTSServerListeners) opened listener for %s, %d\n",
01119              trans->TransName, ciptr->fd, 0);
01120 
01121        temp_ciptrs[*count_ret] = ciptr;
01122        (*count_ret)++;
01123     }
01124 
01125     *partial = (*count_ret < complete_network_count());
01126 
01127     PRMSG (5,
01128      "TRANS(MakeAllCLTSServerListeners) partial=%d, actual=%d, complete=%d \n",
01129        *partial, *count_ret, complete_network_count());
01130 
01131     if (*count_ret > 0)
01132     {
01133        if ((*ciptrs_ret = (XtransConnInfo *) malloc (
01134            *count_ret * sizeof (XtransConnInfo))) == NULL)
01135        {
01136            return -1;
01137        }
01138 
01139        for (i = 0; i < *count_ret; i++)
01140        {
01141            (*ciptrs_ret)[i] = temp_ciptrs[i];
01142        }
01143     }
01144     else
01145        *ciptrs_ret = NULL;
01146  
01147     return 0;
01148 }
01149 
01150 int
01151 TRANS(MakeAllCLTSServerListeners) (port, partial, count_ret, ciptrs_ret)
01152 
01153 char          *port;
01154 int           *partial;
01155 int           *count_ret;
01156 XtransConnInfo       **ciptrs_ret;
01157 
01158 {
01159     char             buffer[256]; /* ??? What size ?? */
01160     XtransConnInfo   ciptr, temp_ciptrs[NUMTRANS];
01161     int                     status, i, j;
01162 
01163     PRMSG (2,"TRANS(MakeAllCLTSServerListeners) (%s,%x)\n",
01164        port ? port : "NULL", ciptrs_ret, 0);
01165 
01166     *count_ret = 0;
01167 
01168     for (i = 0; i < NUMTRANS; i++)
01169     {
01170        Xtransport *trans = Xtransports[i].transport;
01171 
01172        if (trans->flags&TRANS_ALIAS)
01173            continue;
01174 
01175        sprintf(buffer,"%s/:%s", trans->TransName, port ? port : "");
01176 
01177        PRMSG (5,"TRANS(MakeAllCLTSServerListeners) opening %s\n",
01178            buffer, 0, 0);
01179 
01180        if ((ciptr = TRANS(OpenCLTSServer (buffer))) == NULL)
01181        {
01182            PRMSG (1,
01183        "TRANS(MakeAllCLTSServerListeners) failed to open listener for %s\n",
01184                 trans->TransName, 0, 0);
01185            continue;
01186        }
01187 
01188        if ((status = TRANS(CreateListener (ciptr, port))) < 0)
01189        {
01190            if (status == TRANS_ADDR_IN_USE)
01191            {
01192               /*
01193                * We failed to bind to the specified address because the
01194                * address is in use.  It must be that a server is already
01195                * running at this address, and this function should fail.
01196                */
01197 
01198               PRMSG (1,
01199               "TRANS(MakeAllCLTSServerListeners) server already running\n",
01200                 0, 0, 0);
01201 
01202               for (j = 0; j < *count_ret; j++)
01203                   TRANS(Close) (temp_ciptrs[j]);
01204 
01205               *count_ret = 0;
01206               *ciptrs_ret = NULL;
01207               *partial = 0;
01208               return -1;
01209            }
01210            else
01211            {
01212               PRMSG (1,
01213        "TRANS(MakeAllCLTSServerListeners) failed to create listener for %s\n",
01214                 trans->TransName, 0, 0);
01215 
01216               continue;
01217            }
01218        }
01219 
01220        PRMSG (5,
01221        "TRANS(MakeAllCLTSServerListeners) opened listener for %s, %d\n",
01222              trans->TransName, ciptr->fd, 0);
01223        temp_ciptrs[*count_ret] = ciptr;
01224        (*count_ret)++;
01225     }
01226 
01227     *partial = (*count_ret < complete_network_count());
01228 
01229     PRMSG (5,
01230      "TRANS(MakeAllCLTSServerListeners) partial=%d, actual=%d, complete=%d \n",
01231        *partial, *count_ret, complete_network_count());
01232 
01233     if (*count_ret > 0)
01234     {
01235        if ((*ciptrs_ret = (XtransConnInfo *) malloc (
01236            *count_ret * sizeof (XtransConnInfo))) == NULL)
01237        {
01238            return -1;
01239        }
01240 
01241        for (i = 0; i < *count_ret; i++)
01242        {
01243            (*ciptrs_ret)[i] = temp_ciptrs[i];
01244        }
01245     }
01246     else
01247        *ciptrs_ret = NULL;
01248     
01249     return 0;
01250 }
01251 
01252 #endif /* TRANS_SERVER */
01253 
01254 
01255 
01256 /*
01257  * These routines are not part of the X Transport Interface, but they
01258  * may be used by it.
01259  */
01260 
01261 #ifdef CRAY
01262 
01263 /*
01264  * Cray UniCOS does not have readv and writev so we emulate
01265  */
01266 
01267 static int TRANS(ReadV) (ciptr, iov, iovcnt)
01268 
01269 XtransConnInfo       ciptr;
01270 struct iovec  *iov;
01271 int           iovcnt;
01272 
01273 {
01274     struct msghdr hdr;
01275 
01276     hdr.msg_iov = iov;
01277     hdr.msg_iovlen = iovcnt;
01278     hdr.msg_accrights = 0;
01279     hdr.msg_accrightslen = 0;
01280     hdr.msg_name = 0;
01281     hdr.msg_namelen = 0;
01282 
01283     return (recvmsg (ciptr->fd, &hdr, 0));
01284 }
01285 
01286 static int TRANS(WriteV) (ciptr, iov, iovcnt)
01287 
01288 XtransConnInfo       ciptr;
01289 struct iovec  *iov;
01290 int           iovcnt;
01291 
01292 {
01293     struct msghdr hdr;
01294 
01295     hdr.msg_iov = iov;
01296     hdr.msg_iovlen = iovcnt;
01297     hdr.msg_accrights = 0;
01298     hdr.msg_accrightslen = 0;
01299     hdr.msg_name = 0;
01300     hdr.msg_namelen = 0;
01301 
01302     return (sendmsg (ciptr->fd, &hdr, 0));
01303 }
01304 
01305 #endif /* CRAY */
01306 
01307 #if (defined(SYSV) && defined(i386)) || defined(WIN32) || defined(__sxg__) || defined(SCO)
01308 
01309 /*
01310  * emulate readv
01311  */
01312 
01313 static int TRANS(ReadV) (ciptr, iov, iovcnt)
01314 
01315 XtransConnInfo       ciptr;
01316 struct iovec  *iov;
01317 int           iovcnt;
01318 
01319 {
01320     int i, len, total;
01321     char *base;
01322 
01323     ESET(0);
01324     for (i = 0, total = 0;  i < iovcnt;  i++, iov++) {
01325        len = iov->iov_len;
01326        base = iov->iov_base;
01327        while (len > 0) {
01328            register int nbytes;
01329            nbytes = TRANS(Read) (ciptr, base, len);
01330            if (nbytes < 0 && total == 0)  return -1;
01331            if (nbytes <= 0)  return total;
01332            ESET(0);
01333            len   -= nbytes;
01334            total += nbytes;
01335            base  += nbytes;
01336        }
01337     }
01338     return total;
01339 }
01340 
01341 #endif /* SYSV && SYSV386 || WIN32 || __sxg__ || SCO */
01342 
01343 #if defined(WIN32) || defined(__sxg__) || defined(SCO)
01344 
01345 /*
01346  * emulate writev
01347  */
01348 
01349 static int TRANS(WriteV) (ciptr, iov, iovcnt)
01350 
01351 XtransConnInfo       ciptr;
01352 struct iovec  *iov;
01353 int           iovcnt;
01354 
01355 {
01356     int i, len, total;
01357     char *base;
01358 
01359     ESET(0);
01360     for (i = 0, total = 0;  i < iovcnt;  i++, iov++) {
01361        len = iov->iov_len;
01362        base = iov->iov_base;
01363        while (len > 0) {
01364            register int nbytes;
01365            nbytes = TRANS(Write) (ciptr, base, len);
01366            if (nbytes < 0 && total == 0)  return -1;
01367            if (nbytes <= 0)  return total;
01368            ESET(0);
01369            len   -= nbytes;
01370            total += nbytes;
01371            base  += nbytes;
01372        }
01373     }
01374     return total;
01375 }
01376 
01377 #endif /* WIN32 || __sxg__ || SCO */
01378 
01379 
01380 #if (defined(_POSIX_SOURCE) && !defined(AIXV3)) || defined(hpux) || defined(USG) || defined(SVR4)
01381 #define NEED_UTSNAME
01382 #include <sys/utsname.h>
01383 #endif
01384 
01385 /*
01386  * TRANS(GetHostname) - similar to gethostname but allows special processing.
01387  */
01388 
01389 int TRANS(GetHostname) (buf, maxlen)
01390 
01391 char *buf;
01392 int maxlen;
01393 
01394 {
01395     int len;
01396 
01397 #ifdef NEED_UTSNAME
01398     struct utsname name;
01399 
01400     uname (&name);
01401     len = strlen (name.nodename);
01402     if (len >= maxlen) len = maxlen - 1;
01403     strncpy (buf, name.nodename, len);
01404     buf[len] = '\0';
01405 #else
01406     buf[0] = '\0';
01407     (void) gethostname (buf, maxlen);
01408     buf [maxlen - 1] = '\0';
01409     len = strlen(buf);
01410 #endif /* NEED_UTSNAME */
01411     return len;
01412 }