480 lines
12 KiB
C
480 lines
12 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/* *
|
|
* (c) Copyright 1993, 1994 Hewlett-Packard Company *
|
|
* (c) Copyright 1993, 1994 International Business Machines Corp. *
|
|
* (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
|
|
* (c) Copyright 1993, 1994 Novell, Inc. *
|
|
*/
|
|
/*
|
|
* $TOG: choose.c /main/5 1997/08/13 11:42:50 kaleb $
|
|
*
|
|
* Copyright 1990 Massachusetts Institute of Technology
|
|
*
|
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
* documentation for any purpose is hereby granted without fee, provided that
|
|
* the above copyright notice appear in all copies and that both that
|
|
* copyright notice and this permission notice appear in supporting
|
|
* documentation, and that the name of M.I.T. not be used in advertising or
|
|
* publicity pertaining to distribution of the software without specific,
|
|
* written prior permission. M.I.T. makes no representations about the
|
|
* suitability of this software for any purpose. It is provided "as is"
|
|
* without express or implied warranty.
|
|
*
|
|
* M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
|
|
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*
|
|
* Author: Keith Packard, MIT X Consortium
|
|
*/
|
|
|
|
/*
|
|
* choose.c
|
|
*
|
|
* xdm interface to chooser program
|
|
*/
|
|
|
|
# include "dm.h"
|
|
# include "vg.h"
|
|
|
|
# include <X11/X.h>
|
|
# include <sys/types.h>
|
|
# include <sys/socket.h>
|
|
# include <netinet/in.h>
|
|
# include <sys/un.h>
|
|
# include <ctype.h>
|
|
# include <errno.h>
|
|
|
|
static char *Print8Address (ARRAY8Ptr Address);
|
|
|
|
int LoadXloginResources(struct display *d); // session.c
|
|
void GetSysParms(char **tzpp, char **fhpp, char **ftpp); // fontpath.c
|
|
int GetChooserAddr(char *addr, int *lenp); // socket.c
|
|
int NetaddrFamily(XdmcpNetaddr netaddrp); // netaddr.c
|
|
|
|
|
|
static int
|
|
FormatBytes (
|
|
unsigned char *data,
|
|
int length,
|
|
char *buf,
|
|
int buflen)
|
|
{
|
|
int i;
|
|
static char HexChars[] = "0123456789abcdef";
|
|
|
|
if (buflen < length * 2 + 1)
|
|
return 0;
|
|
for (i = 0; i < length; i++)
|
|
{
|
|
*buf++ = HexChars[(data[i] >> 4) & 0xf];
|
|
*buf++ = HexChars[(data[i]) & 0xf];
|
|
}
|
|
*buf++ = '\0';
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
FormatARRAY8 (
|
|
ARRAY8Ptr a,
|
|
char *buf,
|
|
int buflen)
|
|
{
|
|
return FormatBytes (a->data, a->length, buf, buflen);
|
|
}
|
|
|
|
typedef struct _IndirectUsers {
|
|
struct _IndirectUsers *next;
|
|
ARRAY8 client;
|
|
CARD16 connectionType;
|
|
} IndirectUsersRec, *IndirectUsersPtr;
|
|
|
|
static IndirectUsersPtr indirectUsers;
|
|
|
|
int
|
|
RememberIndirectClient (
|
|
ARRAY8Ptr clientAddress,
|
|
CARD16 connectionType)
|
|
{
|
|
IndirectUsersPtr i;
|
|
|
|
for (i = indirectUsers; i; i = i->next)
|
|
if (XdmcpARRAY8Equal (clientAddress, &i->client) &&
|
|
connectionType == i->connectionType)
|
|
return 1;
|
|
i = (IndirectUsersPtr) malloc (sizeof (IndirectUsersRec));
|
|
if (!XdmcpCopyARRAY8 (clientAddress, &i->client))
|
|
{
|
|
free ((char *) i);
|
|
return 0;
|
|
}
|
|
i->connectionType = connectionType;
|
|
i->next = indirectUsers;
|
|
indirectUsers = i;
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
ForgetIndirectClient (
|
|
ARRAY8Ptr clientAddress,
|
|
CARD16 connectionType)
|
|
{
|
|
IndirectUsersPtr i, prev;
|
|
|
|
prev = 0;
|
|
for (i = indirectUsers; i; i = i->next)
|
|
{
|
|
if (XdmcpARRAY8Equal (clientAddress, &i->client) &&
|
|
connectionType == i->connectionType)
|
|
{
|
|
if (prev)
|
|
prev->next = i->next;
|
|
else
|
|
indirectUsers = i->next;
|
|
XdmcpDisposeARRAY8 (&i->client);
|
|
free ((char *) i);
|
|
break;
|
|
}
|
|
prev = i;
|
|
}
|
|
}
|
|
|
|
int
|
|
IsIndirectClient (
|
|
ARRAY8Ptr clientAddress,
|
|
CARD16 connectionType)
|
|
{
|
|
IndirectUsersPtr i;
|
|
|
|
for (i = indirectUsers; i; i = i->next)
|
|
if (XdmcpARRAY8Equal (clientAddress, &i->client) &&
|
|
connectionType == i->connectionType)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
extern char *NetaddrPort();
|
|
|
|
static int
|
|
FormatChooserArgument (
|
|
char *buf,
|
|
int len)
|
|
{
|
|
unsigned char addr_buf[1024];
|
|
int addr_len = sizeof (addr_buf);
|
|
unsigned char result_buf[1024];
|
|
int result_len = 0;
|
|
int netfamily;
|
|
|
|
if (GetChooserAddr (addr_buf, &addr_len) == -1)
|
|
{
|
|
LogError ((unsigned char *)"Cannot get return address for chooser socket\n");
|
|
Debug ("Cannot get chooser socket address\n");
|
|
return 0;
|
|
}
|
|
netfamily = NetaddrFamily((XdmcpNetaddr)addr_buf);
|
|
switch (netfamily) {
|
|
case AF_INET:
|
|
{
|
|
char *port;
|
|
int portlen;
|
|
ARRAY8Ptr localAddress, getLocalAddress ();
|
|
|
|
port = NetaddrPort((XdmcpNetaddr)addr_buf, &portlen);
|
|
result_buf[0] = netfamily >> 8;
|
|
result_buf[1] = netfamily & 0xFF;
|
|
result_buf[2] = port[0];
|
|
result_buf[3] = port[1];
|
|
localAddress = getLocalAddress ();
|
|
bcopy ((char *)localAddress->data, (char *)result_buf+4, 4);
|
|
result_len = 8;
|
|
}
|
|
break;
|
|
#ifdef AF_DECnet
|
|
case AF_DECnet:
|
|
break;
|
|
#endif
|
|
default:
|
|
Debug ("Chooser family %d isn't known\n", netfamily);
|
|
return 0;
|
|
}
|
|
|
|
return FormatBytes (result_buf, result_len, buf, len);
|
|
}
|
|
|
|
typedef struct _Choices {
|
|
struct _Choices *next;
|
|
ARRAY8 client;
|
|
CARD16 connectionType;
|
|
ARRAY8 choice;
|
|
long time;
|
|
} ChoiceRec, *ChoicePtr;
|
|
|
|
static ChoicePtr choices;
|
|
|
|
ARRAY8Ptr
|
|
IndirectChoice (
|
|
ARRAY8Ptr clientAddress,
|
|
CARD16 connectionType)
|
|
{
|
|
ChoicePtr c, next, prev;
|
|
long now;
|
|
|
|
now = time (0);
|
|
prev = 0;
|
|
for (c = choices; c; c = next)
|
|
{
|
|
next = c->next;
|
|
if (now - c->time > 15)
|
|
{
|
|
Debug ("Timeout choice\n");
|
|
if (prev)
|
|
prev->next = next;
|
|
else
|
|
choices = next;
|
|
XdmcpDisposeARRAY8 (&c->client);
|
|
XdmcpDisposeARRAY8 (&c->choice);
|
|
free ((char *) c);
|
|
}
|
|
else
|
|
{
|
|
if (XdmcpARRAY8Equal (clientAddress, &c->client) &&
|
|
connectionType == c->connectionType)
|
|
return &c->choice;
|
|
prev = c;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
RegisterIndirectChoice (
|
|
ARRAY8Ptr clientAddress,
|
|
CARD16 connectionType,
|
|
ARRAY8Ptr choice)
|
|
{
|
|
ChoicePtr c;
|
|
int insert;
|
|
int found = 0;
|
|
|
|
Debug ("Got indirect choice back (%s)\n", Print8Address(clientAddress));
|
|
for (c = choices; c; c = c->next) {
|
|
if (XdmcpARRAY8Equal (clientAddress, &c->client) &&
|
|
connectionType == c->connectionType) {
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (!found)
|
|
return 0;
|
|
|
|
insert = 0;
|
|
|
|
if (!c)
|
|
{
|
|
c = (ChoicePtr) malloc (sizeof (ChoiceRec));
|
|
insert = 1;
|
|
if (!c)
|
|
return 0;
|
|
c->connectionType = connectionType;
|
|
if (!XdmcpCopyARRAY8 (clientAddress, &c->client))
|
|
{
|
|
free ((char *) c);
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
XdmcpDisposeARRAY8 (&c->choice);
|
|
}
|
|
|
|
if (!XdmcpCopyARRAY8 (choice, &c->choice))
|
|
{
|
|
XdmcpDisposeARRAY8 (&c->client);
|
|
free ((char *) c);
|
|
return 0;
|
|
}
|
|
if (insert)
|
|
{
|
|
c->next = choices;
|
|
choices = c;
|
|
}
|
|
c->time = time (0);
|
|
|
|
Debug("choice=(%s)\n", Print8Address(choice));
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
static void
|
|
AddChooserHost (
|
|
CARD16 connectionType,
|
|
ARRAY8Ptr addr,
|
|
char *closure)
|
|
{
|
|
char ***argp, **parseArgs();
|
|
char hostbuf[1024];
|
|
|
|
argp = (char ***) closure;
|
|
if (addr->length == strlen ("BROADCAST") &&
|
|
!strncmp ((char *)addr->data, "BROADCAST", addr->length))
|
|
{
|
|
*argp = parseArgs (*argp, "BROADCAST");
|
|
}
|
|
else if (FormatARRAY8 (addr, hostbuf, sizeof (hostbuf)))
|
|
{
|
|
*argp = parseArgs (*argp, hostbuf);
|
|
}
|
|
}
|
|
|
|
int
|
|
ProcessChooserSocket (
|
|
int fd)
|
|
{
|
|
int client_fd;
|
|
char buf[1024];
|
|
int len;
|
|
XdmcpBuffer buffer;
|
|
ARRAY8 clientAddress;
|
|
CARD16 connectionType;
|
|
ARRAY8 choice;
|
|
|
|
Debug ("Process chooser socket\n");
|
|
len = sizeof (buf);
|
|
client_fd = accept (fd, (struct sockaddr *)buf, &len);
|
|
if (client_fd == -1)
|
|
{
|
|
LogError ((unsigned char *)"Cannot accept chooser connection\n");
|
|
return 0;
|
|
}
|
|
Debug ("Accepted %d\n", client_fd);
|
|
|
|
len = read (client_fd, buf, sizeof (buf));
|
|
Debug ("Read returns %d\n", len);
|
|
if (len > 0)
|
|
{
|
|
buffer.data = (BYTE *) buf;
|
|
buffer.size = sizeof (buf);
|
|
buffer.count = len;
|
|
buffer.pointer = 0;
|
|
clientAddress.data = 0;
|
|
clientAddress.length = 0;
|
|
choice.data = 0;
|
|
choice.length = 0;
|
|
if (XdmcpReadARRAY8 (&buffer, &clientAddress) &&
|
|
XdmcpReadCARD16 (&buffer, &connectionType) &&
|
|
XdmcpReadARRAY8 (&buffer, &choice))
|
|
{
|
|
Debug ("Read from chooser successfully\n");
|
|
if (!RegisterIndirectChoice (&clientAddress, connectionType, &choice))
|
|
Debug ("Invalid chooser reply\n");
|
|
}
|
|
XdmcpDisposeARRAY8 (&clientAddress);
|
|
XdmcpDisposeARRAY8 (&choice);
|
|
}
|
|
else
|
|
{
|
|
LogError ((unsigned char *)"Choice response read error %s\n", strerror(errno));
|
|
}
|
|
|
|
close (client_fd);
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
RunChooser (
|
|
struct display *d)
|
|
{
|
|
char **args, **parseArgs(), **systemEnv();
|
|
char buf[1024];
|
|
char **env;
|
|
|
|
Debug ("RunChooser %s\n", d->name);
|
|
SetTitle (d->name, "chooser");
|
|
LoadXloginResources (d);
|
|
|
|
args = parseArgs ((char **) 0, d->chooser);
|
|
strcpy (buf, "-xdmaddress ");
|
|
if (FormatChooserArgument (buf + strlen (buf), sizeof (buf) - strlen (buf)))
|
|
args = parseArgs (args, buf);
|
|
strcpy (buf, "-clientaddress ");
|
|
if (FormatARRAY8 (&d->clientAddr, buf + strlen (buf), sizeof (buf) - strlen (buf)))
|
|
args = parseArgs (args, buf);
|
|
sprintf (buf, "-connectionType %d", d->connectionType);
|
|
args = parseArgs (args, buf);
|
|
ForEachChooserHost (&d->clientAddr,
|
|
d->connectionType,
|
|
(int (*)()) AddChooserHost,
|
|
(char *) &args);
|
|
env = systemEnv (d, (char *) 0, (char *) 0);
|
|
if (d->authFile)
|
|
env = setEnv (env, "XAUTHORITY", d->authFile);
|
|
if (d->pmSearchPath)
|
|
env = setEnv(env, "XMICONSEARCHPATH", d->pmSearchPath);
|
|
if (d->bmSearchPath)
|
|
env = setEnv(env, "XMICONBMSEARCHPATH", d->bmSearchPath);
|
|
if ( d->language && strlen(d->language) > 0 )
|
|
env = setEnv(env, "LANG", d->language);
|
|
if ( d->langList && strlen(d->langList) > 0 )
|
|
env = setEnv(env, LANGLIST, d->langList);
|
|
#if !defined (ENABLE_DYNAMIC_LANGLIST)
|
|
else
|
|
if ( strlen(languageList) > 0 )
|
|
env = setEnv(env, LANGLIST, languageList);
|
|
#endif /* ENABLE_DYNAMIC_LANGLIST */
|
|
if ( d->setup)
|
|
env = setEnv(env, "XSETUP", d->setup);
|
|
if(d->displayType.location == Local)
|
|
env = setEnv (env, LOCATION, "local");
|
|
else
|
|
env = setEnv (env, LOCATION, "remote");
|
|
|
|
|
|
Debug ("Running %s\n", args[0]);
|
|
execute (args, env);
|
|
Debug ("Couldn't run %s\n", args[0]);
|
|
LogError ((unsigned char *)"Cannot execute %s\n", args[0]);
|
|
exit (REMANAGE_DISPLAY);
|
|
}
|
|
|
|
static char *
|
|
Print8Address (
|
|
ARRAY8Ptr Address)
|
|
{
|
|
static char buf[200];
|
|
char *b;
|
|
int i;
|
|
|
|
b = buf;
|
|
b[0]='\0';
|
|
for (i = 0; i < (int)Address->length; i++) {
|
|
sprintf(b, " %d", Address->data[i]);
|
|
b = buf + strlen(buf);
|
|
}
|
|
return(buf);
|
|
}
|