824N/A/*
824N/A * csconndi.c -- low level connection maker for CSDPS
824N/A *
824N/A * (c) Copyright 1990-1994 Adobe Systems Incorporated.
824N/A * All rights reserved.
824N/A *
824N/A * Permission to use, copy, modify, distribute, and sublicense this software
824N/A * and its documentation for any purpose and without fee is hereby granted,
824N/A * provided that the above copyright notices appear in all copies and that
824N/A * both those copyright notices and this permission notice appear in
824N/A * supporting documentation and that the name of Adobe Systems Incorporated
824N/A * not be used in advertising or publicity pertaining to distribution of the
824N/A * software without specific, written prior permission. No trademark license
824N/A * to use the Adobe trademarks is hereby granted. If the Adobe trademark
824N/A * "Display PostScript"(tm) is used to describe this software, its
824N/A * functionality or for any other purpose, such use shall be limited to a
824N/A * statement that this software works in conjunction with the Display
824N/A * PostScript system. Proper trademark attribution to reflect Adobe's
824N/A * ownership of the trademark shall be given whenever any such reference to
824N/A * the Display PostScript system is made.
824N/A *
824N/A * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
824N/A * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
824N/A * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
824N/A * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
824N/A * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
824N/A * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
824N/A * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
824N/A * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
824N/A * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
824N/A * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
824N/A *
824N/A * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
824N/A * Incorporated which may be registered in certain jurisdictions
824N/A *
824N/A * Portions Copyright 1989 Massachusetts Institute of Technology
824N/A *
824N/A * Permission to use, copy, modify, distribute, and sell this software and its
824N/A * documentation for any purpose is hereby granted without fee, provided that
824N/A * the above copyright notice appear in all copies and that both that
824N/A * copyright notice and this permission notice appear in supporting
824N/A * documentation, and that the name of M.I.T. not be used in advertising or
824N/A * publicity pertaining to distribution of the software without specific,
824N/A * written prior permission. M.I.T. makes no representations about the
824N/A * suitability of this software for any purpose. It is provided "as is"
824N/A * without express or implied warranty.
824N/A *
824N/A * Author: Adobe Systems Incorporated and MIT X Consortium
824N/A */
824N/A/* $XFree86: xc/lib/dps/csconndi.c,v 1.11tsi Exp $ */
824N/A
824N/A#if defined(sun) && !defined(SVR4)
824N/A#define memmove(t,f,c) bcopy(f,t,c)
824N/A#endif
824N/A
824N/A#define NEED_EVENTS
824N/A
824N/A#include <stdio.h>
824N/A#include <stdlib.h>
824N/A#include <X11/Xos.h>
824N/A/* Include this first so that Xasync.h, included from Xlibint.h, can find
824N/A the definition of NOFILE */
824N/A#include <sys/param.h>
824N/A#include <X11/Xlibint.h>
824N/A#include "Xlibnet.h" /* New for R5, delete for R4 */
824N/A#include <arpa/inet.h>
824N/A
824N/A#ifndef hpux /* HP doesn't include Xauth.h :-( */
824N/A#include <X11/Xauth.h>
824N/A#else
824N/A#define FamilyLocal (256)
824N/A#endif
824N/A
824N/A#include <ctype.h>
824N/A#ifdef DNETCONN
824N/A#include <netdnet/dn.h>
824N/A#include <netdnet/dnetdb.h>
824N/A#endif
824N/A
824N/A#include <netdb.h>
824N/A
824N/A#include "DPSCAPproto.h"
824N/A#include "cslibint.h"
824N/A#include "dpsassert.h"
824N/A
824N/A#if defined(hpux) || defined(AIXV3)
824N/A#define SELECT_TYPE int *
824N/A#else
824N/A#define SELECT_TYPE fd_set *
824N/A#endif
824N/A
824N/A#ifndef _XANYSET
824N/A#define _XANYSET N_XANYSET
824N/A#endif /* _XANYSET */
824N/A
824N/A#ifndef X_CONNECTION_RETRIES /* number retries on ECONNREFUSED */
824N/A#define X_CONNECTION_RETRIES 5
824N/A#endif
824N/A
824N/A#define CONN_PARAMS char *, int , int , int *, int *, char **
824N/A
824N/A#ifdef DNETCONN
824N/Astatic int MakeDECnetConnection(CONN_PARAMS);
824N/A#endif
824N/A#ifdef UNIXCONN
824N/Astatic int MakeUNIXSocketConnection(CONN_PARAMS);
824N/A#endif
824N/A#ifdef TCPCONN
824N/Astatic int MakeTCPConnection(CONN_PARAMS);
824N/A#endif
824N/A#ifdef STREAMSCONN
824N/Aextern int _XMakeStreamsConnection(CONN_PARAMS);
824N/A#endif
824N/A
824N/A/* This global controls the size of the output socket buffer. Zero
824N/A means to use the system default size. */
824N/Aint gNXSndBufSize = 0;
824N/A
824N/Astatic char *copystring (char *src, int len)
824N/A{
824N/A char *dst = Xmalloc (len + 1);
824N/A
824N/A if (dst) {
824N/A strncpy (dst, src, len);
824N/A dst[len] = '\0';
824N/A }
824N/A
824N/A return dst;
824N/A}
824N/A
824N/A
824N/A/*
824N/A * Attempts to connect to agent, given name. Returns file descriptor
824N/A * (network socket) or -1 if connection fails. Names may be of the
824N/A * following format:
824N/A *
824N/A * [hostname] : [:] agentnumber
824N/A *
824N/A * The second colon indicates a DECnet style name. No hostname is interpretted
824N/A * as the most efficient local connection to a server on the same machine.
824N/A * This is usually:
824N/A *
824N/A * o shared memory
824N/A * o local stream
824N/A * o UNIX domain socket
824N/A * o TCP to local host
824N/A */
824N/A
824N/Aint
824N/ADPSCAPConnect(
824N/A char *display_name,
824N/A char **fullnamep, /* RETURN */
824N/A int *dpynump, /* RETURN */
824N/A int *familyp, /* RETURN */
824N/A int *saddrlenp, /* RETURN */
824N/A char **saddrp) /* RETURN, freed by caller */
824N/A{
824N/A char *lastp, *p; /* char pointers */
824N/A char *phostname = NULL; /* start of host of display */
824N/A char *pdpynum = NULL; /* start of dpynum of display */
824N/A char *pscrnum = NULL; /* start of screen of display */
824N/A Bool dnet = False; /* if true, then DECnet format */
824N/A int iagent; /* required display number */
824N/A int (*connfunc)(CONN_PARAMS); /* method to create connection */
824N/A int fd = -1; /* file descriptor to return */
824N/A int len; /* length tmp variable */
824N/A
824N/A p = display_name;
824N/A
824N/A *saddrlenp = 0; /* set so that we can clear later */
824N/A *saddrp = NULL;
824N/A
824N/A /*
824N/A * Step 1, find the hostname. This is delimited by the required
824N/A * first colon.
824N/A */
824N/A for (lastp = p; *p && *p != ':'; p++) ;
824N/A if (!*p) return -1; /* must have a colon */
824N/A
824N/A if (p != lastp) { /* no hostname given */
824N/A phostname = copystring (lastp, p - lastp);
824N/A if (!phostname) goto bad; /* no memory */
824N/A }
824N/A
824N/A
824N/A /*
824N/A * Step 2, see if this is a DECnet address by looking for the optional
824N/A * second colon.
824N/A */
824N/A if (p[1] == ':') { /* then DECnet format */
824N/A dnet = True;
824N/A p++;
824N/A }
824N/A
824N/A /*
824N/A * see if we're allowed to have a DECnet address
824N/A */
824N/A#ifndef DNETCONN
824N/A if (dnet) goto bad;
824N/A#endif
824N/A
824N/A
824N/A /*
824N/A * Step 3, find the port number. This field is required.
824N/A * Zero is acceptable as a port number, meaning use the default.
824N/A */
824N/A
824N/A for (lastp = ++p; *p && isascii(*p) && isdigit(*p); p++) ;
824N/A if ((p == lastp) || /* required field */
824N/A (*p != '\0' && *p != '.') || /* invalid non-digit terminator */
824N/A !(pdpynum = copystring (lastp, p - lastp))) /* no memory */
824N/A goto bad;
824N/A iagent = atoi (pdpynum);
824N/A
824N/A
824N/A /*
824N/A * At this point, we know the following information:
824N/A *
824N/A * phostname hostname string or NULL
824N/A * iagent agent port number
824N/A * dnet DECnet boolean
824N/A *
824N/A * We can now decide which transport to use based on the ConnectionFlags
824N/A * build parameter the hostname string. If phostname is NULL or equals
824N/A * the string "local", then choose the best transport. If phostname
824N/A * is "unix", then choose BSD UNIX domain sockets (if configured).
824N/A *
824N/A * First, choose default transports: DECnet else (TCP or STREAMS)
824N/A */
824N/A
824N/A
824N/A#ifdef DNETCONN
824N/A if (dnet)
824N/A connfunc = MakeDECnetConnection;
824N/A else
824N/A#endif
824N/A#ifdef TCPCONN
824N/A connfunc = MakeTCPConnection;
824N/A#else
824N/A#ifdef STREAMSCONN
824N/A connfunc = _XMakeStreamsConnection;
824N/A#else
824N/A connfunc = NULL;
824N/A#endif
824N/A#endif
824N/A
824N/A#ifdef UNIXCONN
824N/A /*
824N/A * Now that the defaults have been established, see if we have any
824N/A * special names that we have to override:
824N/A *
824N/A * :N => if UNIXCONN then unix-domain-socket
824N/A * ::N => if UNIXCONN then unix-domain-socket
824N/A * unix:N => if UNIXCONN then unix-domain-socket
824N/A *
824N/A * Note that if UNIXCONN isn't defined, then we can use the default
824N/A * transport connection function set above.
824N/A */
824N/A if (!phostname) {
824N/A connfunc = MakeUNIXSocketConnection;
824N/A }
824N/A else if (strcmp (phostname, "unix") == 0) {
824N/A connfunc = MakeUNIXSocketConnection;
824N/A }
824N/A#endif
824N/A if (!connfunc)
824N/A goto bad;
824N/A
824N/A
824N/A#ifdef UNIXCONN
824N/A#define LOCALCONNECTION (!phostname || connfunc == MakeUNIXSocketConnection)
824N/A#else
824N/A#define LOCALCONNECTION (!phostname)
824N/A#endif
824N/A
824N/A if (LOCALCONNECTION) {
824N/A /*
824N/A * Get the auth info for local hosts so that it doesn't have to be
824N/A * repeated everywhere; the particular values in these fields are
824N/A * not part of the protocol.
824N/A */
824N/A char hostnamebuf[256];
824N/A int len = N_XGetHostname (hostnamebuf, sizeof hostnamebuf);
824N/A
824N/A *familyp = FamilyLocal;
824N/A if (len > 0) {
824N/A *saddrp = Xmalloc (len + 1);
824N/A if (*saddrp) {
824N/A strcpy (*saddrp, hostnamebuf);
824N/A *saddrlenp = len;
824N/A } else {
824N/A *saddrlenp = 0;
824N/A }
824N/A }
824N/A }
824N/A#undef LOCALCONNECTION
824N/A
824N/A#ifndef ultrix
824N/A /* Ultrix has a nasty bug in getservbyname(); if the name passed to
824N/A it is not in the services list it seg faults! *sigh* So, we
824N/A don't ever look in the services info for ultrix... */
824N/A if (iagent == 0) { /* find service default, if one's defined */
824N/A struct servent *serventInfo;
824N/A
824N/A if ((serventInfo = getservbyname(DPS_NX_SERV_NAME,
824N/A (char *) NULL)) != NULL) {
824N/A if (strcmp("tcp", serventInfo->s_proto) != 0) {
824N/A DPSWarnProc(NULL, "Services database specifies a protocol other than tcp. Using default port.\n");
824N/A } else /* extract the port number */
824N/A iagent = ntohs(serventInfo->s_port);
824N/A }
824N/A }
824N/A#endif /* ultrix */
824N/A /*
824N/A * Make the connection, also need to get the auth address info for
824N/A * non-local connections. Do retries in case server host has hit its
824N/A * backlog (which, unfortunately, isn't distinguishable from there not
824N/A * being a server listening at all, which is why we have to not retry
824N/A * too many times).
824N/A */
824N/A if ((fd = (*connfunc) (phostname, iagent, X_CONNECTION_RETRIES,
824N/A familyp, saddrlenp, saddrp)) < 0)
824N/A goto bad;
824N/A
824N/A
824N/A /*
824N/A * Set the connection non-blocking since we use select() to block; also
824N/A * set close-on-exec so that programs that fork() doesn't get confused.
824N/A */
824N/A#ifdef FIOSNBIO
824N/A {
824N/A int arg = 1;
824N/A ioctl (fd, FIOSNBIO, &arg);
824N/A }
824N/A#else
824N/A#if defined(O_NONBLOCK)
824N/A (void) fcntl (fd, F_SETFL, O_NONBLOCK);
824N/A#elif defined(FNDELAY)
824N/A (void) fcntl (fd, F_SETFL, FNDELAY);
824N/A#else
824N/A (void) fcntl (fd, F_SETFL, O_NDELAY);
824N/A#endif /* O_NONBLOCK/FNDELAY */
824N/A#endif /* FIOSNBIO */
824N/A
824N/A (void) fcntl (fd, F_SETFD, 1);
824N/A
824N/A
824N/A /*
824N/A * Build the expanded display name:
824N/A *
824N/A * [host] : [:] agent \0
824N/A */
824N/A len = ((phostname ? strlen(phostname) : 0) + 1 + (dnet ? 1 : 0) +
824N/A strlen(pdpynum) + 1);
824N/A *fullnamep = (char *) Xmalloc (len);
824N/A if (!*fullnamep) goto bad;
824N/A
824N/A sprintf (*fullnamep, "%s%s%d",
824N/A (phostname ? phostname : ""), (dnet ? "::" : ":"),
824N/A iagent);
824N/A
824N/A *dpynump = iagent;
824N/A if (phostname) Xfree (phostname);
824N/A if (pdpynum) Xfree (pdpynum);
824N/A if (pscrnum) Xfree (pscrnum);
824N/A return fd;
824N/A
824N/A
824N/A /*
824N/A * error return; make sure everything is cleaned up.
824N/A */
824N/A bad:
824N/A if (fd >= 0) (void) close (fd);
824N/A if (*saddrp) {
824N/A Xfree (*saddrp);
824N/A *saddrp = NULL;
824N/A }
824N/A *saddrlenp = 0;
824N/A if (phostname) Xfree (phostname);
824N/A if (pdpynum) Xfree (pdpynum);
824N/A return -1;
824N/A
824N/A}
824N/A
824N/A
824N/A/*****************************************************************************
824N/A * *
824N/A * Make Connection Routines *
824N/A * *
824N/A *****************************************************************************/
824N/A
824N/A#ifdef DNETCONN /* stupid makedepend */
824N/A#define NEED_BSDISH
824N/A#endif
824N/A#ifdef UNIXCONN
824N/A#define NEED_BSDISH
824N/A#endif
824N/A#ifdef TCPCONN
824N/A#define NEED_BSDISH
824N/A#endif
824N/A
824N/A#ifdef NEED_BSDISH /* makedepend can't handle #if */
824N/A/*
824N/A * 4.2bsd-based systems
824N/A */
824N/A#include <sys/socket.h>
824N/A
824N/A#ifndef hpux
824N/A#ifdef apollo /* nest if(n)defs because makedepend is broken */
824N/A#ifndef NO_TCP_H
824N/A#include <netinet/tcp.h>
824N/A#endif /* NO_TCP_H */
824N/A#else /* apollo */
824N/A#include <netinet/tcp.h>
824N/A#endif /* apollo */
824N/A#endif
824N/A#endif /* NEED_BSDISH */
824N/A
824N/A
824N/A#ifdef DNETCONN
824N/Astatic int MakeDECnetConnection (phostname, iagent, retries,
824N/A familyp, saddrlenp, saddrp)
824N/A char *phostname;
824N/A int iagent;
824N/A int retries;
824N/A int *familyp; /* RETURN */
824N/A int *saddrlenp; /* RETURN */
824N/A char **saddrp; /* RETURN */
824N/A{
824N/A int fd;
824N/A char objname[20];
824N/A extern int dnet_conn();
824N/A struct dn_naddr *dnaddrp, dnaddr;
824N/A struct nodeent *np;
824N/A
824N/A if (!phostname) phostname = "0";
824N/A
824N/A /*
824N/A * build the target object name.
824N/A */
824N/A sprintf (objname, "DPS$EXECUTIVE_%d", iagent);
824N/A
824N/A /*
824N/A * Attempt to open the DECnet connection, return -1 if fails; ought to
824N/A * do some retries here....
824N/A */
824N/A if ((fd = dnet_conn (phostname, objname, SOCK_STREAM, 0, 0, 0, 0)) < 0) {
824N/A return -1;
824N/A }
824N/A
824N/A *familyp = FamilyDECnet;
824N/A if (dnaddrp = dnet_addr (phostname)) { /* stolen from xhost */
824N/A dnaddr = *dnaddrp;
824N/A } else {
824N/A if ((np = getnodebyname (phostname)) == NULL) {
824N/A (void) close (fd);
824N/A return -1;
824N/A }
824N/A dnaddr.a_len = np->n_length;
824N/A memmove(dnaddr.a_addr, np->n_addr, np->n_length);
824N/A }
824N/A
824N/A *saddrlenp = sizeof (struct dn_naddr);
824N/A *saddrp = Xmalloc (*saddrlenp);
824N/A if (!*saddrp) {
824N/A (void) close (fd);
824N/A return -1;
824N/A }
824N/A memmove (*saddrp, (char *)&dnaddr, *saddrlenp);
824N/A return fd;
824N/A}
824N/A#endif /* DNETCONN */
824N/A
824N/A
824N/A#ifdef UNIXCONN
824N/A
824N/A#ifndef X_NO_SYS_UN
824N/A#include <sys/un.h>
824N/A#endif
824N/A
824N/A#ifndef CSDPS_UNIX_PATH
824N/A#ifdef hpux
824N/A#define CSDPS_UNIX_DIR "/usr/spool/sockets/DPSNX"
824N/A#define CSDPS_UNIX_PATH "/usr/spool/sockets/DPSNX/"
824N/A#else
824N/A#define CSDPS_UNIX_DIR "/tmp/.DPSNX-unix"
824N/A#define CSDPS_UNIX_PATH "/tmp/.DPSNX-unix/AGENT"
824N/A#endif
824N/A#endif
824N/A
824N/Astatic int MakeUNIXSocketConnection (
824N/A char *phostname,
824N/A int iagent,
824N/A int retries,
824N/A int *familyp, /* RETURN */
824N/A int *saddrlenp, /* RETURN */
824N/A char **saddrp) /* RETURN */
824N/A{
824N/A struct sockaddr_un unaddr; /* UNIX socket data block */
824N/A struct sockaddr *addr; /* generic socket pointer */
824N/A int addrlen; /* length of addr */
824N/A int fd; /* socket file descriptor */
824N/A int port = (iagent == 0) ? CSDPSPORT : iagent;
824N/A
824N/A unaddr.sun_family = AF_UNIX;
824N/A sprintf (unaddr.sun_path, "%s_%d", CSDPS_UNIX_PATH, port);
824N/A
824N/A addr = (struct sockaddr *) &unaddr;
824N/A addrlen = strlen(unaddr.sun_path) + sizeof(unaddr.sun_family);
824N/A
824N/A /*
824N/A * Open the network connection.
824N/A */
824N/A do {
824N/A if ((fd = socket ((int) addr->sa_family, SOCK_STREAM, 0)) < 0) {
824N/A return -1;
824N/A }
824N/A
824N/A if (gNXSndBufSize > 0)
824N/A setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &gNXSndBufSize, sizeof(gNXSndBufSize));
824N/A
824N/A if (connect (fd, addr, addrlen) < 0) {
824N/A int olderrno = errno;
824N/A (void) close (fd);
824N/A if (olderrno != ENOENT || retries <= 0) {
824N/A errno = olderrno;
824N/A return -1;
824N/A }
824N/A sleep (1);
824N/A } else {
824N/A break;
824N/A }
824N/A } while (retries-- > 0);
824N/A
824N/A /*
824N/A * Don't need to get auth info since we're local
824N/A */
824N/A return fd;
824N/A}
824N/A#endif /* UNIXCONN */
824N/A
824N/A
824N/A#ifdef TCPCONN
824N/Astatic int MakeTCPConnection (
824N/A char *phostname,
824N/A int iagent,
824N/A int retries,
824N/A int *familyp, /* RETURN */
824N/A int *saddrlenp, /* RETURN */
824N/A char **saddrp) /* RETURN */
824N/A{
824N/A char hostnamebuf[256]; /* tmp space */
824N/A unsigned long hostinetaddr; /* result of inet_addr of arpa addr */
824N/A struct sockaddr_in inaddr; /* IP socket */
824N/A struct sockaddr *addr; /* generic socket pointer */
824N/A int addrlen; /* length of addr */
824N/A struct hostent *hp; /* entry in hosts table */
824N/A char *cp; /* character pointer iterator */
824N/A int fd; /* file descriptor to return */
824N/A int len; /* length tmp variable */
824N/A
824N/A#define INVALID_INETADDR ((unsigned long) -1)
824N/A
824N/A if (!phostname) {
824N/A hostnamebuf[0] = '\0';
824N/A (void) N_XGetHostname (hostnamebuf, sizeof hostnamebuf);
824N/A phostname = hostnamebuf;
824N/A }
824N/A
824N/A /*
824N/A * if numeric host name then try to parse it as such; do the number
824N/A * first because some systems return garbage instead of INVALID_INETADDR
824N/A */
824N/A if (isascii(phostname[0]) && isdigit(phostname[0])) {
824N/A hostinetaddr = inet_addr (phostname);
824N/A } else {
824N/A hostinetaddr = INVALID_INETADDR;
824N/A }
824N/A
824N/A /*
824N/A * try numeric
824N/A */
824N/A if (hostinetaddr == INVALID_INETADDR) {
824N/A if ((hp = gethostbyname(phostname)) == NULL) {
824N/A /* No such host! */
824N/A return -1;
824N/A }
824N/A if (hp->h_addrtype != AF_INET) { /* is IP host? */
824N/A /* Not an Internet host! */
824N/A return -1;
824N/A }
824N/A
824N/A /* Set up the socket data. */
824N/A inaddr.sin_family = hp->h_addrtype;
824N/A#if defined(CRAY) && defined(OLDTCP)
824N/A /* Only Cray UNICOS3 and UNICOS4 will define this */
824N/A {
824N/A long t;
824N/A memmove ((char *)&t, (char *)hp->h_addr, sizeof(t));
824N/A inaddr.sin_addr = t;
824N/A }
824N/A#else
824N/A memmove ((char *)&inaddr.sin_addr, (char *)hp->h_addr,
824N/A sizeof(inaddr.sin_addr));
824N/A#endif /* CRAY and OLDTCP */
824N/A } else {
824N/A#if defined(CRAY) && defined(OLDTCP)
824N/A /* Only Cray UNICOS3 and UNICOS4 will define this */
824N/A inaddr.sin_addr = hostinetaddr;
824N/A#else
824N/A inaddr.sin_addr.s_addr = hostinetaddr;
824N/A#endif /* CRAY and OLDTCP */
824N/A inaddr.sin_family = AF_INET;
824N/A }
824N/A
824N/A addr = (struct sockaddr *) &inaddr;
824N/A addrlen = sizeof (struct sockaddr_in);
824N/A inaddr.sin_port = (iagent == 0) ? CSDPSPORT : iagent;
824N/A inaddr.sin_port = htons (inaddr.sin_port); /* may be funky macro */
824N/A
824N/A
824N/A /*
824N/A * Open the network connection.
824N/A */
824N/A do {
824N/A if ((fd = socket ((int) addr->sa_family, SOCK_STREAM, 0)) < 0) {
824N/A return -1;
824N/A }
824N/A
824N/A /*
824N/A * turn off TCP coalescence
824N/A */
824N/A#ifdef TCP_NODELAY
824N/A {
824N/A int tmp = 1;
824N/A setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (char *)&tmp, sizeof (int));
824N/A }
824N/A#endif
824N/A if (gNXSndBufSize > 0)
824N/A len = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &gNXSndBufSize, sizeof(gNXSndBufSize));
824N/A
824N/A /*
824N/A * connect to the socket; if there is no X server or if the backlog has
824N/A * been reached, then ECONNREFUSED will be returned.
824N/A */
824N/A if (connect (fd, addr, addrlen) < 0) {
824N/A int olderrno = errno;
824N/A (void) close (fd);
824N/A if (olderrno != ECONNREFUSED || retries <= 0) {
824N/A errno = olderrno;
824N/A return -1;
824N/A }
824N/A sleep (1);
824N/A } else {
824N/A break;
824N/A }
824N/A } while (retries-- > 0);
824N/A
824N/A
824N/A /*
824N/A * Success! So, save the auth information
824N/A */
824N/A#ifdef CRAY
824N/A#ifdef OLDTCP
824N/A len = sizeof(inaddr.sin_addr);
824N/A#else
824N/A len = SIZEOF_in_addr;
824N/A#endif /* OLDTCP */
824N/A cp = (char *) &inaddr.sin_addr;
824N/A#else /* else not CRAY */
824N/A len = sizeof(inaddr.sin_addr.s_addr);
824N/A cp = (char *) &inaddr.sin_addr.s_addr;
824N/A#endif /* CRAY */
824N/A
824N/A /*
824N/A * We are special casing the BSD hack localhost address
824N/A * 127.0.0.1, since this address shouldn't be copied to
824N/A * other machines. So, we simply omit generating the auth info
824N/A * since we set it to the local machine before calling this routine!
824N/A */
824N/A if (!((len == 4) && (cp[0] == 127) && (cp[1] == 0) &&
824N/A (cp[2] == 0) && (cp[3] == 1))) {
824N/A *saddrp = Xmalloc (len);
824N/A if (*saddrp) {
824N/A *saddrlenp = len;
824N/A memmove (*saddrp, cp, len);
824N/A *familyp = FamilyInternet;
824N/A } else {
824N/A *saddrlenp = 0;
824N/A }
824N/A }
824N/A
824N/A return fd;
824N/A}
824N/A#undef INVALID_INETADDR
824N/A#endif /* TCPCONN */
824N/A
824N/A
824N/A/*****************************************************************************
824N/A * *
824N/A * Connection Utility Routines *
824N/A * *
824N/A *****************************************************************************/
824N/A
824N/A/*
824N/A * Disconnect from server.
824N/A */
824N/A
824N/Aint N_XDisconnectDisplay (int server)
824N/A{
824N/A (void) close(server);
824N/A return 0;
824N/A}
824N/A
824N/A
824N/A#include <stddef.h>
824N/A/*
824N/A * This is an OS dependent routine which:
824N/A * 1) returns as soon as the connection can be written on....
824N/A * 2) if the connection can be read, must enqueue events and handle errors,
824N/A * until the connection is writable.
824N/A */
824N/Avoid N_XWaitForWritable(Display *dpy)
824N/A{
824N/A unsigned long r_mask[MSKCNT];
824N/A unsigned long w_mask[MSKCNT];
824N/A int nfound;
824N/A
824N/A CLEARBITS(r_mask);
824N/A CLEARBITS(w_mask);
824N/A
824N/A while (1) {
824N/A BITSET(r_mask, dpy->fd);
824N/A BITSET(w_mask, dpy->fd);
824N/A
824N/A do {
824N/A nfound = select (dpy->fd + 1, (SELECT_TYPE) r_mask,
824N/A (SELECT_TYPE) w_mask, (SELECT_TYPE) NULL,
824N/A (struct timeval *) NULL);
824N/A if (nfound < 0 && errno != EINTR)
824N/A _XIOError(dpy);
824N/A } while (nfound <= 0);
824N/A
824N/A if (_XANYSET(r_mask)) {
824N/A char buf[BUFSIZE];
824N/A long pend_not_register;
824N/A register long pend;
824N/A register xEvent *ev;
824N/A
824N/A /* find out how much data can be read */
824N/A if (BytesReadable(dpy->fd, (char *) &pend_not_register) < 0)
824N/A _XIOError(dpy);
824N/A pend = pend_not_register;
824N/A
824N/A /* must read at least one xEvent; if none is pending, then
824N/A we'll just block waiting for it */
824N/A if (pend < SIZEOF(xEvent)) pend = SIZEOF(xEvent);
824N/A
824N/A /* but we won't read more than the max buffer size */
824N/A if (pend > BUFSIZE) pend = BUFSIZE;
824N/A
824N/A /* round down to an integral number of XReps */
824N/A pend = (pend / SIZEOF(xEvent)) * SIZEOF(xEvent);
824N/A
824N/A N_XRead (dpy, buf, pend);
824N/A
824N/A /* no space between comma and type or else macro will die */
824N/A STARTITERATE (ev,xEvent, buf, (pend > 0),
824N/A (pend -= SIZEOF(xEvent))) {
824N/A if (ev->u.u.type == X_Error)
824N/A _XError (dpy, (xError *) ev);
824N/A else /* it's an event packet; die */
824N/A DPSFatalProc((DPSContext)0, "N_XWaitForWritable read bogus X event");
824N/A }
824N/A ENDITERATE
824N/A }
824N/A if (_XANYSET(w_mask))
824N/A return;
824N/A }
824N/A}
824N/A
824N/A
824N/Avoid N_XWaitForReadable(Display *dpy)
824N/A{
824N/A unsigned long r_mask[MSKCNT];
824N/A int result;
824N/A
824N/A CLEARBITS(r_mask);
824N/A do {
824N/A BITSET(r_mask, dpy->fd);
824N/A result = select(dpy->fd + 1, (SELECT_TYPE) r_mask, (SELECT_TYPE) NULL,
824N/A (SELECT_TYPE) NULL, (struct timeval *) NULL);
824N/A if (result == -1 && errno != EINTR) _XIOError(dpy);
824N/A } while (result <= 0);
824N/A}
824N/A
824N/A#ifdef XXX
824N/A
824N/Astatic int padlength[4] = {0, 3, 2, 1}; /* make sure auth is multiple of 4 */
824N/A
824N/A_XSendClientPrefix (
824N/A Display *dpy,
824N/A xConnClientPrefix *client, /* contains count for auth_* */
824N/A char *auth_proto, /* NOT null-terminated */
824N/A char char *auth_string) /* NOT null-terminated */
824N/A{
824N/A int auth_length = client->nbytesAuthProto;
824N/A int auth_strlen = client->nbytesAuthString;
824N/A char padbuf[3]; /* for padding to 4x bytes */
824N/A int pad;
824N/A struct iovec iovarray[5], *iov = iovarray;
824N/A int niov = 0;
824N/A
824N/A#define add_to_iov(b,l) \
824N/A { iov->iov_base = (b); iov->iov_len = (l); iov++, niov++; }
824N/A
824N/A add_to_iov ((caddr_t) client, SIZEOF(xConnClientPrefix));
824N/A
824N/A /*
824N/A * write authorization protocol name and data
824N/A */
824N/A if (auth_length > 0) {
824N/A add_to_iov (auth_proto, auth_length);
824N/A pad = padlength [auth_length & 3];
824N/A if (pad) add_to_iov (padbuf, pad);
824N/A }
824N/A if (auth_strlen > 0) {
824N/A add_to_iov (auth_string, auth_strlen);
824N/A pad = padlength [auth_strlen & 3];
824N/A if (pad) add_to_iov (padbuf, pad);
824N/A }
824N/A
824N/A#undef add_to_iov
824N/A
824N/A (void) WritevToServer (dpy->fd, iovarray, niov);
824N/A return;
824N/A}
824N/A
824N/A#endif /* XXX */