824N/A/*
824N/A * csopendi.c -- open connection to CSDPS agent
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 Massachusetts Institute of Technology 1985, 1986
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$ */
824N/A
824N/A#include <stdlib.h>
824N/A#include <stdio.h>
824N/A#include <sys/param.h> /* for MAXHOSTNAMELEN */
824N/A#define NEED_EVENTS
824N/A#include <X11/Xlibint.h>
824N/A#include <X11/Xos.h>
824N/A#include "cslibint.h"
824N/A#ifdef XXX
824N/A#include <X11/Xauth.h>
824N/A#include <X11/Xatom.h>
824N/A
824N/Aextern int _Xdebug;
824N/Aextern Display *_XHeadOfDisplayList;
824N/A
824N/A#ifndef lint
824N/Astatic int lock; /* get rid of ifdefs when locking implemented */
824N/A#endif
824N/A
824N/A#endif /* XXX */
824N/A
824N/A#include <X11/X.h>
824N/A#include <X11/Xproto.h>
824N/A
824N/A#include "DPSCAPClient.h"
824N/A#include <DPS/dpsXclient.h>
824N/A#include <DPS/dpsNXargs.h>
824N/A#include "dpsassert.h"
824N/A#include "dpsNXprops.h"
824N/A#include "csfindNX.h"
824N/A#include "csstartNX.h"
824N/A
824N/A#ifdef DPSLNKL
824N/A#include "dpslnkl.inc"
824N/A#endif /* DPSLNKL */
824N/A
824N/A
824N/A/* +++ Someday make this common with XDPS.c version */
824N/A#define DPY_NUMBER(dpy) ((dpy)->fd)
824N/A
824N/Astatic xReq _dummy_request = {
824N/A 0, 0, 0
824N/A};
824N/A
824N/Astatic void OutOfMemory (Display *);
824N/A
824N/A#ifdef XXX
824N/A/*
824N/A * First, a routine for setting authorization data
824N/A */
824N/Astatic int xauth_namelen = 0;
824N/Astatic char *xauth_name = NULL; /* NULL means use default mechanism */
824N/Astatic int xauth_datalen = 0;
824N/Astatic char *xauth_data = NULL; /* NULL means get default data */
824N/A
824N/Avoid XSetAuthorization (char *name, int namelen, char *data, int datalen)
824N/A{
824N/A char *tmpname, *tmpdata;
824N/A
824N/A if (xauth_name) Xfree (xauth_name); /* free any existing data */
824N/A if (xauth_data) Xfree (xauth_data);
824N/A
824N/A xauth_name = xauth_data = NULL; /* mark it no longer valid */
824N/A xauth_namelen = xauth_datalen = 0;
824N/A
824N/A if (namelen < 0) namelen = 0; /* check for bogus inputs */
824N/A if (datalen < 0) datalen = 0; /* maybe should return? */
824N/A
824N/A if (namelen > 0) { /* try to allocate space */
824N/A tmpname = Xmalloc ((unsigned) namelen);
824N/A if (!tmpname) return;
824N/A bcopy (name, tmpname, namelen);
824N/A } else {
824N/A tmpname = NULL;
824N/A }
824N/A
824N/A if (datalen > 0) {
824N/A tmpdata = Xmalloc ((unsigned) datalen);
824N/A if (!tmpdata) {
824N/A if (tmpname) (void) Xfree (tmpname);
824N/A return;
824N/A }
824N/A bcopy (data, tmpdata, datalen);
824N/A } else {
824N/A tmpdata = NULL;
824N/A }
824N/A
824N/A xauth_name = tmpname; /* and store the suckers */
824N/A xauth_namelen = namelen;
824N/A xauth_data = tmpdata;
824N/A xauth_datalen = datalen;
824N/A return;
824N/A}
824N/A
824N/A#endif /* XXX */
824N/A
824N/A/*
824N/A * Connects to a server, creates a Display object and returns a pointer to
824N/A * the newly created Display back to the caller.
824N/A */
824N/AXExtData *
824N/ADPSCAPOpenAgent(Display *dpy, char *trueDisplayName)
824N/A{
824N/A register Display *agent;
824N/A char *agentHost = (char *)NULL;
824N/A register int i;
824N/A char display_name[256]; /* pointer to display name */
824N/A char licMethBuf[256];
824N/A char *licMeth = licMethBuf;
824N/A char *fullname = NULL;
824N/A int idisplay;
824N/A char *server_addr = NULL;
824N/A int server_addrlen = 0;
824N/A int conn_family;
824N/A int transport, port;
824N/A XExtData *ext;
824N/A DPSCAPData my;
824N/A char hostname[MAXHOSTNAMELEN];
824N/A
824N/A/*
824N/A * Find an agent to talk to.
824N/A */
824N/A#ifdef DPSLNKL
824N/A extern unsigned ANXPFunc();
824N/A#ifdef PSUSEPN
824N/A (void) sprintf(licMeth, "%s%s:%d",
824N/A LICENSE_METHOD_PREFIX,
824N/A ANXVENDOR, /* From dpslnkl.inc */
824N/A ANXPFunc());
824N/A#else /* PSUSEPN */
824N/A (void) sprintf(licMeth, "%s%s",
824N/A LICENSE_METHOD_PREFIX,
824N/A ANXVENDOR); /* From dpslnkl.inc */
824N/A#endif /* PSUSEPN */
824N/A#else /* DPSLNKL */
824N/A licMeth = NULL; /* We want an open service */
824N/A#endif /* DPSLNKL */
824N/A (void) N_XGetHostname(hostname, MAXHOSTNAMELEN);
824N/A switch(XDPSNXFindNX(dpy, licMeth, &agentHost, &transport, &port)) {
824N/A case findnx_not_found: {
824N/A /* try to start-up an NX? */
824N/A Bool autoLaunch;
824N/A
824N/A XDPSGetNXArg(XDPSNX_AUTO_LAUNCH, (void **) &autoLaunch);
824N/A if (autoLaunch == True) {
824N/A int requestedTrans;
824N/A int requestedPort = 0;
824N/A char **args = NULL;
824N/A char *additionalArgs[2];
824N/A char transportArg[256];
824N/A
824N/A (void) DPSWarnProc(NULL, "Auto-launching DPS NX agent.");
824N/A XDPSGetNXArg(XDPSNX_LAUNCHED_AGENT_TRANS, (void **) &requestedTrans);
824N/A if (requestedTrans == XDPSNX_USE_BEST) {
824N/A XDPSNXSetClientArg(XDPSNX_LAUNCHED_AGENT_TRANS,
824N/A (void *)XDPSNX_TRANS_UNIX);
824N/A requestedTrans = XDPSNX_TRANS_UNIX;
824N/A }
824N/A /* cons-up an arg. to pass to Agent we are forking */
824N/A
824N/A additionalArgs[1] = (char *) NULL;
824N/A additionalArgs[0] = transportArg;
824N/A XDPSGetNXArg(XDPSNX_LAUNCHED_AGENT_PORT, (void **) &requestedPort);
824N/A if (requestedPort == XDPSNX_USE_BEST) {
824N/A requestedPort = XDPSNXRecommendPort(requestedTrans);
824N/A if (requestedPort < 0) {
824N/A DPSWarnProc(NULL, "Auto-launcher can't get a port.");
824N/A return(NULL);
824N/A }
824N/A }
824N/A (void) sprintf(transportArg, "%s/%d",
824N/A (requestedTrans == XDPSNX_TRANS_DECNET ?
824N/A "dec" : "tcp"),
824N/A requestedPort);
824N/A args = additionalArgs;
824N/A /* ASSERT: first argument in additionalArgs must be
824N/A transport/port, unless agent changes to take this
824N/A anywhere */
824N/A if (StartXDPSNX(args) != Success) {
824N/A char tb[256], *fs, **as;
824N/A (void) XDPSGetNXArg(XDPSNX_EXEC_FILE, (void **) &fs);
824N/A (void) XDPSGetNXArg(XDPSNX_EXEC_ARGS, (void **) &as);
824N/A (void) sprintf(tb, "FAILED to auto-launch:\n %s", fs);
824N/A if (as != NULL)
824N/A for (; *as != NULL; as++) {
824N/A if ((int) (strlen(*as) + 1 + (i = strlen(tb))) > 256-1) {
824N/A if (i > 256-1-4)
824N/A strcpy(&(tb[256-1-1-4]), " ...");
824N/A else
824N/A strcat(tb, " ...");
824N/A break;
824N/A }
824N/A (void) strcat(tb, " ");
824N/A (void) strcat(tb, *as);
824N/A }
824N/A DPSWarnProc(NULL, tb);
824N/A return(NULL);
824N/A } else {
824N/A (void) sprintf(display_name, "%s%s%d", hostname,
824N/A (requestedTrans == XDPSNX_TRANS_DECNET ?
824N/A "::" : ":"),
824N/A requestedPort);
824N/A }
824N/A } else { /* autoLaunch != True */
824N/A return(NULL);
824N/A }
824N/A }
824N/A break;
824N/A case findnx_found: { /* XDPSNXFindNX() == Success */
824N/A (void) sprintf(display_name, "%s%s%d",
824N/A (transport == XDPSNX_TRANS_UNIX ?
824N/A "unix" : agentHost),
824N/A (transport == XDPSNX_TRANS_DECNET ? "::" : ":"),
824N/A port);
824N/A /* Free agentHost later */
824N/A }
824N/A break;
824N/A case findnx_error:
824N/A return(NULL);
824N/A break;
824N/A default:
824N/A DPSFatalProc(NULL, "Illegal value returned by XDPSNXFindNX");
824N/A break;
824N/A }
824N/A
824N/A
824N/A/*
824N/A * Attempt to allocate a display structure. Return NULL if allocation fails.
824N/A */
824N/A if ((agent = (Display *)Xcalloc(1, sizeof(Display))) == NULL) {
824N/A return(NULL);
824N/A }
824N/A
824N/A/*
824N/A * Call the Connect routine to get the network socket. If -1 is returned, the
824N/A * connection failed. The connect routine will set fullname to point to the
824N/A * expanded name.
824N/A */
824N/A
824N/A if ((agent->fd = DPSCAPConnect(display_name, &fullname, &idisplay,
824N/A &conn_family,
824N/A &server_addrlen, &server_addr)) < 0) {
824N/A Xfree ((char *) agent);
824N/A return(NULL);
824N/A }
824N/A#ifdef XXX
824N/A/*
824N/A * Look up the authorization protocol name and data if necessary.
824N/A */
824N/A if (xauth_name && xauth_data) {
824N/A conn_auth_namelen = xauth_namelen;
824N/A conn_auth_name = xauth_name;
824N/A conn_auth_datalen = xauth_datalen;
824N/A conn_auth_data = xauth_data;
824N/A } else {
824N/A char dpynumbuf[40]; /* big enough to hold 2^64 and more */
824N/A (void) sprintf (dpynumbuf, "%d", idisplay);
824N/A
824N/A authptr = XauGetAuthByAddr ((unsigned short) conn_family,
824N/A (unsigned short) server_addrlen,
824N/A server_addr,
824N/A (unsigned short) strlen (dpynumbuf),
824N/A dpynumbuf,
824N/A (unsigned short) xauth_namelen,
824N/A xauth_name);
824N/A if (authptr) {
824N/A conn_auth_namelen = authptr->name_length;
824N/A conn_auth_name = (char *)authptr->name;
824N/A conn_auth_datalen = authptr->data_length;
824N/A conn_auth_data = (char *)authptr->data;
824N/A } else {
824N/A conn_auth_namelen = 0;
824N/A conn_auth_name = NULL;
824N/A conn_auth_datalen = 0;
824N/A conn_auth_data = NULL;
824N/A }
824N/A }
824N/A#ifdef HASDES
824N/A /*
824N/A * build XDM-AUTHORIZATION-1 data
824N/A */
824N/A if (conn_auth_namelen == 19 &&
824N/A !strncmp (conn_auth_name, "XDM-AUTHORIZATION-1", 19))
824N/A {
824N/A static char encrypted_data[192/8];
824N/A int i, j;
824N/A struct sockaddr_in in_addr;
824N/A int addrlen;
824N/A long now;
824N/A
824N/A j = 0;
824N/A for (i = 0; i < 8; i++)
824N/A {
824N/A encrypted_data[j] = conn_auth_data[i];
824N/A j++;
824N/A }
824N/A addrlen = sizeof (in_addr);
824N/A getsockname (dpy->fd, (struct sockaddr *) &in_addr, &addrlen);
824N/A if (in_addr.sin_family == 2)
824N/A {
824N/A encrypted_data[j] = in_addr.sin_addr.s_net; j++;
824N/A encrypted_data[j] = in_addr.sin_addr.s_host; j++;
824N/A encrypted_data[j] = in_addr.sin_addr.s_lh; j++;
824N/A encrypted_data[j] = in_addr.sin_addr.s_impno; j++;
824N/A encrypted_data[j] = (in_addr.sin_port >> 8) & 0xff; j++;
824N/A encrypted_data[j] = (in_addr.sin_port) & 0xff; j++;
824N/A }
824N/A else
824N/A {
824N/A encrypted_data[j] = 0xff; j++;
824N/A encrypted_data[j] = 0xff; j++;
824N/A encrypted_data[j] = 0xff; j++;
824N/A encrypted_data[j] = 0xff; j++;
824N/A i = getpid ();
824N/A encrypted_data[j] = (i >> 8) & 0xff; j++;
824N/A encrypted_data[j] = (i) & 0xff; j++;
824N/A }
824N/A time (&now);
824N/A for (i = 3; i >= 0; i--)
824N/A {
824N/A encrypted_data[j] = (now >> (i * 8)) & 0xff;
824N/A j++;
824N/A }
824N/A XdmcpEncrypt (encrypted_data, conn_auth_data + 8,
824N/A encrypted_data, 192/8);
824N/A conn_auth_data = encrypted_data;
824N/A conn_auth_datalen = 192 / 8;
824N/A }
824N/A#endif /* HASDES */
824N/A if (server_addr) (void) Xfree (server_addr);
824N/A
824N/A#endif /* XXX */
824N/A
824N/A/*
824N/A * We succeeded at authorization, so let us move the data into
824N/A * the display structure.
824N/A */
824N/A agent->lock_meaning = NoSymbol;
824N/A#ifdef XXX
824N/A /* this field is not present in post X11R5 */
824N/A agent->current = None;
824N/A#endif
824N/A agent->event_vec[X_Error] = N_XUnknownWireEvent;
824N/A agent->event_vec[X_Reply] = N_XUnknownWireEvent;
824N/A agent->wire_vec[X_Error] = N_XUnknownNativeEvent;
824N/A agent->wire_vec[X_Reply] = N_XUnknownNativeEvent;
824N/A for (i = KeyPress; i < 128; i++) {
824N/A agent->event_vec[i] = N_XUnknownWireEvent;
824N/A agent->wire_vec[i] = N_XUnknownNativeEvent;
824N/A }
824N/A agent->cursor_font = None;
824N/A agent->last_req = (char *)&_dummy_request;
824N/A
824N/A /* Salt away the host:display string for later use.
824N/A Storage owned by agent, Xmalloc'd by connection
824N/A call above */
824N/A agent->display_name = fullname;
824N/A
824N/A /* Set up the output buffers. */
824N/A if ((agent->bufptr = agent->buffer = Xmalloc(BUFSIZE)) == NULL) {
824N/A OutOfMemory (dpy);
824N/A return(NULL);
824N/A }
824N/A agent->bufmax = agent->buffer + BUFSIZE;
824N/A
824N/A
824N/A /* Create extension data */
824N/A
824N/A my = DPSCAPCreate(dpy, agent);
824N/A if (my == (DPSCAPData)NULL)
824N/A {
824N/A OutOfMemory(agent);
824N/A return(NULL);
824N/A }
824N/A ext = (XExtData *)Xcalloc(1, sizeof(XExtData));
824N/A ext->private_data = (char *)my;
824N/A
824N/A /* Parse names to get true display name */
824N/A if (agentHost && strcmp(hostname, agentHost))
824N/A {
824N/A register char *s, *p;
824N/A char *dxname;
824N/A char nametmp[MAXHOSTNAMELEN];
824N/A /* Agent is not on the same host as client, so fix
824N/A up the stupid abbreviations used for the display,
824N/A and whoever came up with the syntax should be shot. */
824N/A dxname = DisplayString(dpy);
824N/A for (s = dxname, p = nametmp; *s; ++s)
824N/A if (*s == ':')
824N/A break;
824N/A else
824N/A *p++ = *s;
824N/A *p = '\0';
824N/A if (nametmp[0] == '\0'
824N/A || !strcmp(nametmp, "unix")
824N/A || !strcmp(nametmp, "localhost"))
824N/A {
824N/A strcpy(trueDisplayName, hostname);
824N/A if (*s)
824N/A strcat(trueDisplayName, s);
824N/A else
824N/A strcat(trueDisplayName, ":0.0");
824N/A }
824N/A else
824N/A strcpy(trueDisplayName, dxname);
824N/A }
824N/A else
824N/A strcpy(trueDisplayName, DisplayString(dpy));
824N/A if (agentHost)
824N/A Xfree(agentHost);
824N/A return(ext);
824N/A}
824N/A
824N/A
824N/A/* OutOfMemory is called if malloc fails. XOpenDisplay returns NULL
824N/A after this returns. */
824N/A
824N/Astatic void OutOfMemory (Display *dpy)
824N/A{
824N/A DPSCAPCloseAgent(dpy);
824N/A}
824N/A
824N/A#ifdef NEEDFORNX
824N/A/* XFreeDisplayStructure frees all the storage associated with a
824N/A * Display. It is used by XOpenDisplay if it runs out of memory,
824N/A * and also by XCloseDisplay. It needs to check whether all pointers
824N/A * are non-NULL before dereferencing them, since it may be called
824N/A * by XOpenDisplay before the Display structure is fully formed.
824N/A * XOpenDisplay must be sure to initialize all the pointers to NULL
824N/A * before the first possible call on this.
824N/A */
824N/A
824N/Astatic void
824N/A_XFreeDisplayStructure(register Display *dpy)
824N/A{
824N/A if (dpy->screens) {
824N/A register int i;
824N/A
824N/A for (i = 0; i < dpy->nscreens; i++) {
824N/A Screen *sp = &dpy->screens[i];
824N/A
824N/A if (sp->depths) {
824N/A register int j;
824N/A
824N/A for (j = 0; j < sp->ndepths; j++) {
824N/A Depth *dp = &sp->depths[j];
824N/A
824N/A if (dp->visuals) {
824N/A register int k;
824N/A
824N/A for (k = 0; k < dp->nvisuals; k++)
824N/A _XFreeExtData (dp->visuals[k].ext_data);
824N/A Xfree ((char *) dp->visuals);
824N/A }
824N/A }
824N/A
824N/A Xfree ((char *) sp->depths);
824N/A }
824N/A
824N/A _XFreeExtData (sp->ext_data);
824N/A }
824N/A
824N/A Xfree ((char *)dpy->screens);
824N/A }
824N/A
824N/A if (dpy->pixmap_format) {
824N/A register int i;
824N/A
824N/A for (i = 0; i < dpy->nformats; i++)
824N/A _XFreeExtData (dpy->pixmap_format[i].ext_data);
824N/A Xfree ((char *)dpy->pixmap_format);
824N/A }
824N/A
824N/A if (dpy->display_name)
824N/A Xfree (dpy->display_name);
824N/A if (dpy->vendor)
824N/A Xfree (dpy->vendor);
824N/A
824N/A if (dpy->buffer)
824N/A Xfree (dpy->buffer);
824N/A if (dpy->atoms)
824N/A Xfree ((char *) dpy->atoms);
824N/A if (dpy->keysyms)
824N/A Xfree ((char *) dpy->keysyms);
824N/A if (dpy->modifiermap)
824N/A XFreeModifiermap(dpy->modifiermap);
824N/A if (dpy->xdefaults)
824N/A Xfree (dpy->xdefaults);
824N/A if (dpy->key_bindings)
824N/A _XFreeKeyBindings(dpy);
824N/A
824N/A while (dpy->ext_procs) {
824N/A _XExtension *ext = dpy->ext_procs;
824N/A dpy->ext_procs = ext->next;
824N/A if (ext->name)
824N/A Xfree (ext->name);
824N/A Xfree ((char *)ext);
824N/A }
824N/A
824N/A _XFreeExtData (dpy->ext_data);
824N/A
824N/A Xfree ((char *)dpy);
824N/A}
824N/A#endif /* NEEDFORNX */
824N/A
824N/A
824N/A
824N/Avoid
824N/ADPSCAPCloseAgent(Display *agent)
824N/A{
824N/A if (!agent) return;
824N/A N_XDisconnectDisplay(agent->fd);
824N/A if (agent->display_name)
824N/A Xfree(agent->display_name);
824N/A if (agent->buffer)
824N/A Xfree(agent->buffer);
824N/A Xfree((char *)agent);
824N/A}