#if defined(sun) && !defined(SVR4)
#define memmove(t,f,c) bcopy(f,t,c)
#endif
#define NEED_EVENTS
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xos.h>
#include <sys/param.h>
#include <X11/Xlibint.h>
#include "Xlibnet.h"
#include <arpa/inet.h>
#ifndef hpux
#include <X11/Xauth.h>
#else
#define FamilyLocal (256)
#endif
#include <ctype.h>
#ifdef DNETCONN
#include <netdnet/dn.h>
#include <netdnet/dnetdb.h>
#endif
#include <netdb.h>
#include "DPSCAPproto.h"
#include "cslibint.h"
#include "dpsassert.h"
#if defined(hpux) || defined(AIXV3)
#define SELECT_TYPE int *
#else
#define SELECT_TYPE fd_set *
#endif
#ifndef _XANYSET
#define _XANYSET N_XANYSET
#endif
#ifndef X_CONNECTION_RETRIES
#define X_CONNECTION_RETRIES 5
#endif
#define CONN_PARAMS char *, int , int , int *, int *, char **
#ifdef DNETCONN
static int MakeDECnetConnection(CONN_PARAMS);
#endif
#ifdef UNIXCONN
static int MakeUNIXSocketConnection(CONN_PARAMS);
#endif
#ifdef TCPCONN
static int MakeTCPConnection(CONN_PARAMS);
#endif
#ifdef STREAMSCONN
extern int _XMakeStreamsConnection(CONN_PARAMS);
#endif
int gNXSndBufSize = 0;
static char *copystring (char *src, int len)
{
char *dst = Xmalloc (len + 1);
if (dst) {
strncpy (dst, src, len);
dst[len] = '\0';
}
return dst;
}
int
DPSCAPConnect(
char *display_name,
char **fullnamep,
int *dpynump,
int *familyp,
int *saddrlenp,
char **saddrp)
{
char *lastp, *p;
char *phostname = NULL;
char *pdpynum = NULL;
char *pscrnum = NULL;
Bool dnet = False;
int iagent;
int (*connfunc)(CONN_PARAMS);
int fd = -1;
int len;
p = display_name;
*saddrlenp = 0;
*saddrp = NULL;
for (lastp = p; *p && *p != ':'; p++) ;
if (!*p) return -1;
if (p != lastp) {
phostname = copystring (lastp, p - lastp);
if (!phostname) goto bad;
}
if (p[1] == ':') {
dnet = True;
p++;
}
#ifndef DNETCONN
if (dnet) goto bad;
#endif
for (lastp = ++p; *p && isascii(*p) && isdigit(*p); p++) ;
if ((p == lastp) ||
(*p != '\0' && *p != '.') ||
!(pdpynum = copystring (lastp, p - lastp)))
goto bad;
iagent = atoi (pdpynum);
#ifdef DNETCONN
if (dnet)
connfunc = MakeDECnetConnection;
else
#endif
#ifdef TCPCONN
connfunc = MakeTCPConnection;
#else
#ifdef STREAMSCONN
connfunc = _XMakeStreamsConnection;
#else
connfunc = NULL;
#endif
#endif
#ifdef UNIXCONN
if (!phostname) {
connfunc = MakeUNIXSocketConnection;
}
else if (strcmp (phostname, "unix") == 0) {
connfunc = MakeUNIXSocketConnection;
}
#endif
if (!connfunc)
goto bad;
#ifdef UNIXCONN
#define LOCALCONNECTION (!phostname || connfunc == MakeUNIXSocketConnection)
#else
#define LOCALCONNECTION (!phostname)
#endif
if (LOCALCONNECTION) {
char hostnamebuf[256];
int len = N_XGetHostname (hostnamebuf, sizeof hostnamebuf);
*familyp = FamilyLocal;
if (len > 0) {
*saddrp = Xmalloc (len + 1);
if (*saddrp) {
strcpy (*saddrp, hostnamebuf);
*saddrlenp = len;
} else {
*saddrlenp = 0;
}
}
}
#undef LOCALCONNECTION
#ifndef ultrix
if (iagent == 0) {
struct servent *serventInfo;
if ((serventInfo = getservbyname(DPS_NX_SERV_NAME,
(char *) NULL)) != NULL) {
if (strcmp("tcp", serventInfo->s_proto) != 0) {
DPSWarnProc(NULL, "Services database specifies a protocol other than tcp. Using default port.\n");
} else
iagent = ntohs(serventInfo->s_port);
}
}
#endif
if ((fd = (*connfunc) (phostname, iagent, X_CONNECTION_RETRIES,
familyp, saddrlenp, saddrp)) < 0)
goto bad;
#ifdef FIOSNBIO
{
int arg = 1;
ioctl (fd, FIOSNBIO, &arg);
}
#else
#if defined(O_NONBLOCK)
(void) fcntl (fd, F_SETFL, O_NONBLOCK);
#elif defined(FNDELAY)
(void) fcntl (fd, F_SETFL, FNDELAY);
#else
(void) fcntl (fd, F_SETFL, O_NDELAY);
#endif
#endif
(void) fcntl (fd, F_SETFD, 1);
len = ((phostname ? strlen(phostname) : 0) + 1 + (dnet ? 1 : 0) +
strlen(pdpynum) + 1);
*fullnamep = (char *) Xmalloc (len);
if (!*fullnamep) goto bad;
sprintf (*fullnamep, "%s%s%d",
(phostname ? phostname : ""), (dnet ? "::" : ":"),
iagent);
*dpynump = iagent;
if (phostname) Xfree (phostname);
if (pdpynum) Xfree (pdpynum);
if (pscrnum) Xfree (pscrnum);
return fd;
bad:
if (fd >= 0) (void) close (fd);
if (*saddrp) {
Xfree (*saddrp);
*saddrp = NULL;
}
*saddrlenp = 0;
if (phostname) Xfree (phostname);
if (pdpynum) Xfree (pdpynum);
return -1;
}
#ifdef DNETCONN
#define NEED_BSDISH
#endif
#ifdef UNIXCONN
#define NEED_BSDISH
#endif
#ifdef TCPCONN
#define NEED_BSDISH
#endif
#ifdef NEED_BSDISH
#include <sys/socket.h>
#ifndef hpux
#ifdef apollo
#ifndef NO_TCP_H
#include <netinet/tcp.h>
#endif
#else
#include <netinet/tcp.h>
#endif
#endif
#endif
#ifdef DNETCONN
static int MakeDECnetConnection (phostname, iagent, retries,
familyp, saddrlenp, saddrp)
char *phostname;
int iagent;
int retries;
int *familyp;
int *saddrlenp;
char **saddrp;
{
int fd;
char objname[20];
extern int dnet_conn();
struct dn_naddr *dnaddrp, dnaddr;
struct nodeent *np;
if (!phostname) phostname = "0";
sprintf (objname, "DPS$EXECUTIVE_%d", iagent);
if ((fd = dnet_conn (phostname, objname, SOCK_STREAM, 0, 0, 0, 0)) < 0) {
return -1;
}
*familyp = FamilyDECnet;
if (dnaddrp = dnet_addr (phostname)) {
dnaddr = *dnaddrp;
} else {
if ((np = getnodebyname (phostname)) == NULL) {
(void) close (fd);
return -1;
}
dnaddr.a_len = np->n_length;
memmove(dnaddr.a_addr, np->n_addr, np->n_length);
}
*saddrlenp = sizeof (struct dn_naddr);
*saddrp = Xmalloc (*saddrlenp);
if (!*saddrp) {
(void) close (fd);
return -1;
}
memmove (*saddrp, (char *)&dnaddr, *saddrlenp);
return fd;
}
#endif
#ifdef UNIXCONN
#ifndef X_NO_SYS_UN
#include <sys/un.h>
#endif
#ifndef CSDPS_UNIX_PATH
#ifdef hpux
#define CSDPS_UNIX_DIR "/usr/spool/sockets/DPSNX"
#define CSDPS_UNIX_PATH "/usr/spool/sockets/DPSNX/"
#else
#define CSDPS_UNIX_DIR "/tmp/.DPSNX-unix"
#define CSDPS_UNIX_PATH "/tmp/.DPSNX-unix/AGENT"
#endif
#endif
static int MakeUNIXSocketConnection (
char *phostname,
int iagent,
int retries,
int *familyp,
int *saddrlenp,
char **saddrp)
{
struct sockaddr_un unaddr;
struct sockaddr *addr;
int addrlen;
int fd;
int port = (iagent == 0) ? CSDPSPORT : iagent;
unaddr.sun_family = AF_UNIX;
sprintf (unaddr.sun_path, "%s_%d", CSDPS_UNIX_PATH, port);
addr = (struct sockaddr *) &unaddr;
addrlen = strlen(unaddr.sun_path) + sizeof(unaddr.sun_family);
do {
if ((fd = socket ((int) addr->sa_family, SOCK_STREAM, 0)) < 0) {
return -1;
}
if (gNXSndBufSize > 0)
setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &gNXSndBufSize, sizeof(gNXSndBufSize));
if (connect (fd, addr, addrlen) < 0) {
int olderrno = errno;
(void) close (fd);
if (olderrno != ENOENT || retries <= 0) {
errno = olderrno;
return -1;
}
sleep (1);
} else {
break;
}
} while (retries-- > 0);
return fd;
}
#endif
#ifdef TCPCONN
static int MakeTCPConnection (
char *phostname,
int iagent,
int retries,
int *familyp,
int *saddrlenp,
char **saddrp)
{
char hostnamebuf[256];
unsigned long hostinetaddr;
struct sockaddr_in inaddr;
struct sockaddr *addr;
int addrlen;
struct hostent *hp;
char *cp;
int fd;
int len;
#define INVALID_INETADDR ((unsigned long) -1)
if (!phostname) {
hostnamebuf[0] = '\0';
(void) N_XGetHostname (hostnamebuf, sizeof hostnamebuf);
phostname = hostnamebuf;
}
if (isascii(phostname[0]) && isdigit(phostname[0])) {
hostinetaddr = inet_addr (phostname);
} else {
hostinetaddr = INVALID_INETADDR;
}
if (hostinetaddr == INVALID_INETADDR) {
if ((hp = gethostbyname(phostname)) == NULL) {
return -1;
}
if (hp->h_addrtype != AF_INET) {
return -1;
}
inaddr.sin_family = hp->h_addrtype;
#if defined(CRAY) && defined(OLDTCP)
{
long t;
memmove ((char *)&t, (char *)hp->h_addr, sizeof(t));
inaddr.sin_addr = t;
}
#else
memmove ((char *)&inaddr.sin_addr, (char *)hp->h_addr,
sizeof(inaddr.sin_addr));
#endif
} else {
#if defined(CRAY) && defined(OLDTCP)
inaddr.sin_addr = hostinetaddr;
#else
inaddr.sin_addr.s_addr = hostinetaddr;
#endif
inaddr.sin_family = AF_INET;
}
addr = (struct sockaddr *) &inaddr;
addrlen = sizeof (struct sockaddr_in);
inaddr.sin_port = (iagent == 0) ? CSDPSPORT : iagent;
inaddr.sin_port = htons (inaddr.sin_port);
do {
if ((fd = socket ((int) addr->sa_family, SOCK_STREAM, 0)) < 0) {
return -1;
}
#ifdef TCP_NODELAY
{
int tmp = 1;
setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (char *)&tmp, sizeof (int));
}
#endif
if (gNXSndBufSize > 0)
len = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &gNXSndBufSize, sizeof(gNXSndBufSize));
if (connect (fd, addr, addrlen) < 0) {
int olderrno = errno;
(void) close (fd);
if (olderrno != ECONNREFUSED || retries <= 0) {
errno = olderrno;
return -1;
}
sleep (1);
} else {
break;
}
} while (retries-- > 0);
#ifdef CRAY
#ifdef OLDTCP
len = sizeof(inaddr.sin_addr);
#else
len = SIZEOF_in_addr;
#endif
cp = (char *) &inaddr.sin_addr;
#else
len = sizeof(inaddr.sin_addr.s_addr);
cp = (char *) &inaddr.sin_addr.s_addr;
#endif
if (!((len == 4) && (cp[0] == 127) && (cp[1] == 0) &&
(cp[2] == 0) && (cp[3] == 1))) {
*saddrp = Xmalloc (len);
if (*saddrp) {
*saddrlenp = len;
memmove (*saddrp, cp, len);
*familyp = FamilyInternet;
} else {
*saddrlenp = 0;
}
}
return fd;
}
#undef INVALID_INETADDR
#endif
int N_XDisconnectDisplay (int server)
{
(void) close(server);
return 0;
}
#include <stddef.h>
void N_XWaitForWritable(Display *dpy)
{
unsigned long r_mask[MSKCNT];
unsigned long w_mask[MSKCNT];
int nfound;
CLEARBITS(r_mask);
CLEARBITS(w_mask);
while (1) {
BITSET(r_mask, dpy->fd);
BITSET(w_mask, dpy->fd);
do {
nfound = select (dpy->fd + 1, (SELECT_TYPE) r_mask,
(SELECT_TYPE) w_mask, (SELECT_TYPE) NULL,
(struct timeval *) NULL);
if (nfound < 0 && errno != EINTR)
_XIOError(dpy);
} while (nfound <= 0);
if (_XANYSET(r_mask)) {
char buf[BUFSIZE];
long pend_not_register;
register long pend;
register xEvent *ev;
if (BytesReadable(dpy->fd, (char *) &pend_not_register) < 0)
_XIOError(dpy);
pend = pend_not_register;
if (pend < SIZEOF(xEvent)) pend = SIZEOF(xEvent);
if (pend > BUFSIZE) pend = BUFSIZE;
pend = (pend / SIZEOF(xEvent)) * SIZEOF(xEvent);
N_XRead (dpy, buf, pend);
STARTITERATE (ev,xEvent, buf, (pend > 0),
(pend -= SIZEOF(xEvent))) {
if (ev->u.u.type == X_Error)
_XError (dpy, (xError *) ev);
else
DPSFatalProc((DPSContext)0, "N_XWaitForWritable read bogus X event");
}
ENDITERATE
}
if (_XANYSET(w_mask))
return;
}
}
void N_XWaitForReadable(Display *dpy)
{
unsigned long r_mask[MSKCNT];
int result;
CLEARBITS(r_mask);
do {
BITSET(r_mask, dpy->fd);
result = select(dpy->fd + 1, (SELECT_TYPE) r_mask, (SELECT_TYPE) NULL,
(SELECT_TYPE) NULL, (struct timeval *) NULL);
if (result == -1 && errno != EINTR) _XIOError(dpy);
} while (result <= 0);
}
#ifdef XXX
static int padlength[4] = {0, 3, 2, 1};
_XSendClientPrefix (
Display *dpy,
xConnClientPrefix *client,
char *auth_proto,
char char *auth_string)
{
int auth_length = client->nbytesAuthProto;
int auth_strlen = client->nbytesAuthString;
char padbuf[3];
int pad;
struct iovec iovarray[5], *iov = iovarray;
int niov = 0;
#define add_to_iov(b,l) \
{ iov->iov_base = (b); iov->iov_len = (l); iov++, niov++; }
add_to_iov ((caddr_t) client, SIZEOF(xConnClientPrefix));
if (auth_length > 0) {
add_to_iov (auth_proto, auth_length);
pad = padlength [auth_length & 3];
if (pad) add_to_iov (padbuf, pad);
}
if (auth_strlen > 0) {
add_to_iov (auth_string, auth_strlen);
pad = padlength [auth_strlen & 3];
if (pad) add_to_iov (padbuf, pad);
}
#undef add_to_iov
(void) WritevToServer (dpy->fd, iovarray, niov);
return;
}
#endif