2
* $XdotOrg: xc/programs/xdm/chooser.c,v 1.2 2004/04/23 19:54:42 eich Exp $
3
* $Xorg: chooser.c,v 1.4 2001/02/09 02:05:40 xorgcvs Exp $
5
Copyright 1990, 1998 The Open Group
7
Permission to use, copy, modify, distribute, and sell this software and its
8
documentation for any purpose is hereby granted without fee, provided that
9
the above copyright notice appear in all copies and that both that
10
copyright notice and this permission notice appear in supporting
13
The above copyright notice and this permission notice shall be included in
14
all copies or substantial portions of the Software.
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
Except as contained in this notice, the name of The Open Group shall not be
24
used in advertising or otherwise to promote the sale, use or other dealings
25
in this Software without prior written authorization from The Open Group.
27
* Author: Keith Packard, MIT X Consortium
30
/* $XFree86: xc/programs/xdm/chooser.c,v 3.26 2003/07/18 15:53:28 tsi Exp $ */
33
* Chooser - display a menu of names and let the user select one
39
* +--------------------------------------------------+
40
* | +------------------+ |
42
* | +------------------+ |
43
* | +-+--------------+ |
50
* | +----------------+ |
51
* | cancel accept ping |
52
* +--------------------------------------------------+
55
#include <X11/Intrinsic.h>
56
#include <X11/StringDefs.h>
57
#include <X11/Xatom.h>
59
#include <X11/Xaw/Paned.h>
60
#include <X11/Xaw/Label.h>
61
#include <X11/Xaw/Viewport.h>
62
#include <X11/Xaw/List.h>
63
#include <X11/Xaw/Box.h>
64
#include <X11/Xaw/Command.h>
68
#include <X11/Xdmcp.h>
70
#include <sys/types.h>
75
#include <X11/extensions/Xinerama.h>
78
#if defined(SVR4) && !defined(SCO325)
79
#include <sys/sockio.h>
81
#if defined(SVR4) && defined(PowerMAX_OS)
82
#include <sys/stropts.h>
84
#if defined(SYSV) && defined(i386)
85
#include <sys/stream.h>
87
#include <sys/sioctl.h>
88
#include <sys/stropts.h>
92
#include "dm_socket.h"
94
#include <arpa/inet.h>
96
#include <sys/ioctl.h>
98
#ifdef WINTCP /* NCR with Wollongong TCP */
99
#include <netinet/ip.h>
103
#include <netconfig.h>
108
#include <sys/param.h>
110
#define VARIABLE_IFREQ
115
#include <X11/extensions/XKBbells.h>
118
#define BROADCAST_HOSTNAME "BROADCAST"
121
#define ishexdigit(c) (isdigit(c) || ('a' <= (c) && (c) <= 'f'))
125
# include <sys/utsname.h>
131
# include <sync/queue.h>
132
# include <sync/sema.h>
138
#include <X11/keysym.h>
140
static int FromHex (char *s, char *d, int len);
143
Widget toplevel, label, viewport, paned, list, box, cancel, acceptit, ping;
145
static void CvtStringToARRAY8(
151
static struct _app_resources {
152
ARRAY8Ptr xdmAddress;
153
ARRAY8Ptr clientAddress;
157
#define offset(field) XtOffsetOf(struct _app_resources, field)
159
#define XtRARRAY8 "ARRAY8"
161
static XtResource resources[] = {
162
{"xdmAddress", "XdmAddress", XtRARRAY8, sizeof (ARRAY8Ptr),
163
offset (xdmAddress), XtRString, NULL },
164
{"clientAddress", "ClientAddress", XtRARRAY8, sizeof (ARRAY8Ptr),
165
offset (clientAddress), XtRString, NULL },
166
{"connectionType", "ConnectionType", XtRInt, sizeof (int),
167
offset (connectionType), XtRImmediate, (XtPointer) 0 }
171
static XrmOptionDescRec options[] = {
172
{ "-xdmaddress", "*xdmAddress", XrmoptionSepArg, NULL },
173
{ "-clientaddress", "*clientAddress", XrmoptionSepArg, NULL },
174
{ "-connectionType","*connectionType", XrmoptionSepArg, NULL },
177
typedef struct _hostAddr {
178
struct _hostAddr *next;
179
struct sockaddr *addr;
184
static HostAddr *hostAddrdb;
186
typedef struct _hostName {
187
struct _hostName *next;
190
ARRAY8 hostname, status;
191
CARD16 connectionType;
195
static HostName *hostNamedb;
198
#if defined(IPv6) && defined(AF_INET6)
199
static int socket6FD;
204
#define PING_INTERVAL 2000
207
static XdmcpBuffer directBuffer, broadcastBuffer;
208
static XdmcpBuffer buffer;
210
#if ((defined(SVR4) && !defined(sun) && !defined(__sgi) && !defined(NCR)) || defined(ISC)) && defined(SIOCGIFCONF)
212
/* Deal with different SIOCGIFCONF ioctl semantics on these OSs */
215
ifioctl (int fd, int cmd, char *arg)
220
bzero((char *) &ioc, sizeof(ioc));
223
if (cmd == SIOCGIFCONF)
225
ioc.ic_len = ((struct ifconf *) arg)->ifc_len;
226
ioc.ic_dp = ((struct ifconf *) arg)->ifc_buf;
228
/* SIOCGIFCONF is somewhat brain damaged on ISC. The argument
229
* buffer must contain the ifconf structure as header. Ifc_req
230
* is also not a pointer but a one element array of ifreq
231
* structures. On return this array is extended by enough
232
* ifreq fields to hold all interfaces. The return buffer length
233
* is placed in the buffer header.
235
((struct ifconf *) ioc.ic_dp)->ifc_len =
236
ioc.ic_len - sizeof(struct ifconf);
241
ioc.ic_len = sizeof(struct ifreq);
244
ret = ioctl(fd, I_STR, (char *) &ioc);
245
if (ret >= 0 && cmd == SIOCGIFCONF)
247
((struct ifconf *) arg)->ifc_len = ioc.ic_len;
251
((struct ifconf *) arg)->ifc_len =
252
((struct ifconf *)ioc.ic_dp)->ifc_len;
253
((struct ifconf *) arg)->ifc_buf =
254
(caddr_t)((struct ifconf *)ioc.ic_dp)->ifc_req;
259
#else /* ((SVR4 && !sun && !NCR) || ISC) && SIOCGIFCONF */
260
#define ifioctl ioctl
261
#endif /* ((SVR4 && !sun) || ISC) && SIOCGIFCONF */
266
PingHosts (XtPointer closure, XtIntervalId *id)
271
for (hosts = hostAddrdb; hosts; hosts = hosts->next)
273
#if defined(IPv6) && defined(AF_INET6)
274
if ( ((struct sockaddr *) hosts->addr)->sa_family == AF_INET6 )
279
if (hosts->type == QUERY)
280
XdmcpFlush (sfd, &directBuffer,
281
(XdmcpNetaddr) hosts->addr, hosts->addrlen);
283
XdmcpFlush (sfd, &broadcastBuffer,
284
(XdmcpNetaddr) hosts->addr, hosts->addrlen);
286
if (++pingTry < TRIES)
287
XtAddTimeOut (PING_INTERVAL, PingHosts, (XtPointer) 0);
294
HostnameCompare (const void *a, const void *b)
296
return strcmp (*(char **)a, *(char **)b);
300
RebuildTable (int size)
308
newTable = (char **) malloc (size * sizeof (char *));
311
for (names = hostNamedb, i = 0; names; names = names->next, i++)
312
newTable[i] = names->fullname;
313
qsort (newTable, size, sizeof (char *), HostnameCompare);
315
XawListChange (list, newTable, size, 0, TRUE);
317
free ((char *) NameTable);
318
NameTable = newTable;
319
NameTableSize = size;
323
AddHostname (ARRAY8Ptr hostname, ARRAY8Ptr status, struct sockaddr *addr, int willing)
325
HostName *new, **names, *name;
327
CARD16 connectionType;
330
switch (addr->sa_family)
333
hostAddr.data = (CARD8 *) &((struct sockaddr_in *) addr)->sin_addr;
335
connectionType = FamilyInternet;
337
#if defined(IPv6) && defined(AF_INET6)
339
hostAddr.data = (CARD8 *) &((struct sockaddr_in6 *) addr)->sin6_addr;
340
hostAddr.length = 16;
341
connectionType = FamilyInternet6;
345
hostAddr.data = (CARD8 *) "";
347
connectionType = FamilyLocal;
350
for (names = &hostNamedb; *names; names = & (*names)->next)
353
if (connectionType == name->connectionType &&
354
XdmcpARRAY8Equal (&hostAddr, &name->hostaddr))
356
if (XdmcpARRAY8Equal (status, &name->status))
365
new = (HostName *) malloc (sizeof (HostName));
368
if (hostname->length)
370
switch (addr->sa_family)
373
#if defined(IPv6) && defined(AF_INET6)
377
struct hostent *hostent;
380
hostent = gethostbyaddr ((char *)hostAddr.data, hostAddr.length, addr->sa_family);
383
XdmcpDisposeARRAY8 (hostname);
384
host = (char *)hostent->h_name;
385
XdmcpAllocARRAY8 (hostname, strlen (host));
386
memmove( hostname->data, host, hostname->length);
391
if (!XdmcpAllocARRAY8 (&new->hostaddr, hostAddr.length))
393
free ((char *) new->fullname);
397
memmove( new->hostaddr.data, hostAddr.data, hostAddr.length);
398
new->connectionType = connectionType;
399
new->hostname = *hostname;
408
free (new->fullname);
409
XdmcpDisposeARRAY8 (&new->status);
410
XdmcpDisposeARRAY8 (hostname);
412
new->willing = willing;
413
new->status = *status;
415
hostname = &new->hostname;
416
fulllen = hostname->length;
419
new->fullname = malloc (fulllen + status->length + 10);
422
new->fullname = "Unknown";
426
sprintf (new->fullname, "%-30.*s %*.*s",
427
hostname->length, hostname->data,
428
status->length, status->length, status->data);
430
RebuildTable (NameTableSize);
435
DisposeHostname (HostName *host)
437
XdmcpDisposeARRAY8 (&host->hostname);
438
XdmcpDisposeARRAY8 (&host->hostaddr);
439
XdmcpDisposeARRAY8 (&host->status);
440
free ((char *) host->fullname);
441
free ((char *) host);
446
RemoveHostname (HostName *host)
448
HostName **prev, *hosts;
451
for (hosts = hostNamedb; hosts; hosts = hosts->next)
460
DisposeHostname (host);
462
RebuildTable (NameTableSize);
467
EmptyHostnames (void)
469
HostName *hosts, *next;
471
for (hosts = hostNamedb; hosts; hosts = next)
474
DisposeHostname (hosts);
478
RebuildTable (NameTableSize);
483
ReceivePacket (XtPointer closure, int *source, XtInputId *id)
486
ARRAY8 authenticationName;
489
int saveHostname = 0;
490
#if defined(IPv6) && defined(AF_INET6)
491
struct sockaddr_storage addr;
493
struct sockaddr addr;
496
int sfd = * (int *) closure;
498
addrlen = sizeof (addr);
499
if (!XdmcpFill (sfd, &buffer, (XdmcpNetaddr) &addr, &addrlen))
501
if (!XdmcpReadHeader (&buffer, &header))
503
if (header.version != XDM_PROTOCOL_VERSION)
507
authenticationName.data = 0;
508
switch (header.opcode) {
510
if (XdmcpReadARRAY8 (&buffer, &authenticationName) &&
511
XdmcpReadARRAY8 (&buffer, &hostname) &&
512
XdmcpReadARRAY8 (&buffer, &status))
514
if (header.length == 6 + authenticationName.length +
515
hostname.length + status.length)
517
if (AddHostname (&hostname, &status, (struct sockaddr *) &addr,
518
header.opcode == (int) WILLING))
522
XdmcpDisposeARRAY8 (&authenticationName);
525
if (XdmcpReadARRAY8 (&buffer, &hostname) &&
526
XdmcpReadARRAY8 (&buffer, &status))
528
if (header.length == 4 + hostname.length + status.length)
530
if (AddHostname (&hostname, &status, (struct sockaddr *) &addr,
531
header.opcode == (int) WILLING))
542
XdmcpDisposeARRAY8 (&hostname);
543
XdmcpDisposeARRAY8 (&status);
548
RegisterHostaddr (struct sockaddr *addr, int len, xdmOpCode type)
550
HostAddr *host, **prev;
552
host = (HostAddr *) malloc (sizeof (HostAddr));
555
host->addr = (struct sockaddr *) malloc (len);
558
free ((char *) host);
561
memmove( (char *) host->addr, (char *) addr, len);
564
for (prev = &hostAddrdb; *prev; prev = &(*prev)->next)
571
* Register the address for this host.
572
* Called with each of the names on the command line.
573
* The special name "BROADCAST" looks up all the broadcast
574
* addresses on the local host.
577
/* Handle variable length ifreq in BNR2 and later */
578
#ifdef VARIABLE_IFREQ
579
#define ifr_size(p) (sizeof (struct ifreq) + \
580
(p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \
581
p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0))
583
#define ifr_size(p) (sizeof (struct ifreq))
587
RegisterHostname (char *name)
589
#if !defined(IPv6) || !defined(AF_INET6)
590
struct hostent *hostent;
592
struct sockaddr_in in_addr;
594
register struct ifreq *ifr;
595
struct sockaddr broad_addr;
596
char buf[2048], *cp, *cplim;
598
if (!strcmp (name, BROADCAST_HOSTNAME))
600
#ifdef WINTCP /* NCR with Wollongong TCP */
606
ifcp = (struct ifconf *)buf;
607
ifcp->ifc_buf = buf+4;
608
ifcp->ifc_len = sizeof (buf) - 4;
610
if ((ipfd=open( "/dev/ip", O_RDONLY )) < 0 )
612
t_error( "RegisterHostname() t_open(/dev/ip) failed" );
616
ioc.ic_cmd = IPIOC_GETIFCONF;
618
ioc.ic_len = sizeof( buf );
619
ioc.ic_dp = (char *)ifcp;
621
if (ioctl (ipfd, (int) I_STR, (char *) &ioc) < 0)
623
perror( "RegisterHostname() ioctl(I_STR(IPIOC_GETIFCONF)) failed" );
628
for (ifr = ifcp->ifc_req, n = ifcp->ifc_len / sizeof (struct ifreq);
632
ifc.ifc_len = sizeof (buf);
634
if (ifioctl (socketFD, (int) SIOCGIFCONF, (char *) &ifc) < 0)
638
#define IFC_IFC_REQ (struct ifreq *) ifc.ifc_buf
640
#define IFC_IFC_REQ ifc.ifc_req
643
cplim = (char *) IFC_IFC_REQ + ifc.ifc_len;
645
for (cp = (char *) IFC_IFC_REQ; cp < cplim; cp += ifr_size (ifr))
649
ifr = (struct ifreq *) cp;
651
if (ifr->ifr_addr.sa_family != AF_INET)
654
broad_addr = ifr->ifr_addr;
655
((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
656
htonl (INADDR_BROADCAST);
657
#ifdef SIOCGIFBRDADDR
659
struct ifreq broad_req;
662
#ifdef WINTCP /* NCR with Wollongong TCP */
663
ioc.ic_cmd = IPIOC_GETIFFLAGS;
665
ioc.ic_len = sizeof( broad_req );
666
ioc.ic_dp = (char *)&broad_req;
668
if (ioctl (ipfd, I_STR, (char *) &ioc) != -1 &&
670
if (ifioctl (socketFD, SIOCGIFFLAGS, (char *) &broad_req) != -1 &&
672
(broad_req.ifr_flags & IFF_BROADCAST) &&
673
(broad_req.ifr_flags & IFF_UP)
677
#ifdef WINTCP /* NCR with Wollongong TCP */
678
ioc.ic_cmd = IPIOC_GETIFBRDADDR;
680
ioc.ic_len = sizeof( broad_req );
681
ioc.ic_dp = (char *)&broad_req;
683
if (ioctl (ipfd, I_STR, (char *) &ioc) != -1)
685
if (ifioctl (socketFD, SIOCGIFBRDADDR, &broad_req) != -1)
687
broad_addr = broad_req.ifr_addr;
695
in_addr = *((struct sockaddr_in *) &broad_addr);
696
in_addr.sin_port = htons (XDM_UDP_PORT);
698
in_addr.sin_len = sizeof(in_addr);
700
RegisterHostaddr ((struct sockaddr *)&in_addr, sizeof (in_addr),
706
/* address as hex string, e.g., "12180022" (deprecated) */
707
if (strlen(name) == 8 &&
708
FromHex(name, (char *)&in_addr.sin_addr, strlen(name)) == 0)
710
in_addr.sin_family = AF_INET;
711
in_addr.sin_port = htons (XDM_UDP_PORT);
713
in_addr.sin_len = sizeof(in_addr);
715
RegisterHostaddr ((struct sockaddr *)&in_addr, sizeof (in_addr),
718
#if defined(IPv6) && defined(AF_INET6)
721
struct addrinfo *ai, *nai, hints;
722
bzero(&hints,sizeof(hints));
723
hints.ai_socktype = SOCK_DGRAM;
724
sprintf(sport, "%d", XDM_UDP_PORT);
725
if (getaddrinfo(name, sport, &hints, &ai) == 0) {
726
for (nai = ai ; nai != NULL ; nai = nai->ai_next) {
727
if ((nai->ai_family == AF_INET) ||
728
(nai->ai_family == AF_INET6)) {
729
if (((nai->ai_family == AF_INET) &&
730
IN_MULTICAST(((struct sockaddr_in *) nai->ai_addr)
732
|| ((nai->ai_family == AF_INET6) &&
733
IN6_IS_ADDR_MULTICAST(
734
&((struct sockaddr_in6 *) nai->ai_addr)
737
RegisterHostaddr(nai->ai_addr, nai->ai_addrlen,
740
RegisterHostaddr(nai->ai_addr, nai->ai_addrlen,
748
/* Per RFC 1123, check first for IP address in dotted-decimal form */
749
else if ((in_addr.sin_addr.s_addr = inet_addr(name)) != -1)
750
in_addr.sin_family = AF_INET;
753
hostent = gethostbyname (name);
756
if (hostent->h_addrtype != AF_INET || hostent->h_length != 4)
758
in_addr.sin_family = hostent->h_addrtype;
759
memmove( &in_addr.sin_addr, hostent->h_addr, 4);
761
in_addr.sin_port = htons (XDM_UDP_PORT);
763
in_addr.sin_len = sizeof(in_addr);
765
RegisterHostaddr ((struct sockaddr *)&in_addr, sizeof (in_addr),
771
static ARRAYofARRAY8 AuthenticationNames;
775
RegisterAuthenticationName (char *name, int namelen)
778
if (!XdmcpReallocARRAYofARRAY8 (&AuthenticationNames,
779
AuthenticationNames.length + 1))
781
authName = &AuthenticationNames.data[AuthenticationNames.length-1];
782
if (!XdmcpAllocARRAY8 (authName, namelen))
784
memmove( authName->data, name, namelen);
789
InitXDMCP (char **argv)
795
header.version = XDM_PROTOCOL_VERSION;
796
header.opcode = (CARD16) BROADCAST_QUERY;
798
for (i = 0; i < (int)AuthenticationNames.length; i++)
799
header.length += 2 + AuthenticationNames.data[i].length;
800
XdmcpWriteHeader (&broadcastBuffer, &header);
801
XdmcpWriteARRAYofARRAY8 (&broadcastBuffer, &AuthenticationNames);
803
header.version = XDM_PROTOCOL_VERSION;
804
header.opcode = (CARD16) QUERY;
806
for (i = 0; i < (int)AuthenticationNames.length; i++)
807
header.length += 2 + AuthenticationNames.data[i].length;
808
XdmcpWriteHeader (&directBuffer, &header);
809
XdmcpWriteARRAYofARRAY8 (&directBuffer, &AuthenticationNames);
810
#if defined(STREAMSCONN)
811
if ((socketFD = t_open ("/dev/udp", O_RDWR, 0)) < 0)
814
if (t_bind( socketFD, NULL, NULL ) < 0)
821
* This part of the code looks contrived. It will actually fit in nicely
822
* when the CLTS part of Xtrans is implemented.
825
struct netconfig *nconf;
827
if( (nconf=getnetconfigent("udp")) == NULL )
834
if( netdir_options(nconf, ND_SET_BROADCAST, socketFD, NULL) )
836
freenetconfigent(nconf);
842
freenetconfigent(nconf);
845
if ((socketFD = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
847
#if defined(IPv6) && defined(AF_INET6)
848
socket6FD = socket (AF_INET6, SOCK_DGRAM, 0);
854
if (setsockopt (socketFD, SOL_SOCKET, SO_BROADCAST, (char *)&soopts, sizeof (soopts)) < 0)
855
perror ("setsockopt");
859
XtAddInput (socketFD, (XtPointer) XtInputReadMask, ReceivePacket,
860
(XtPointer) &socketFD);
861
#if defined(IPv6) && defined(AF_INET6)
863
XtAddInput (socket6FD, (XtPointer) XtInputReadMask, ReceivePacket,
864
(XtPointer) &socket6FD);
868
RegisterHostname (*argv);
872
PingHosts ((XtPointer)NULL, (XtIntervalId *)NULL);
879
if (app_resources.xdmAddress)
881
struct sockaddr_in in_addr;
882
#if defined(IPv6) && defined(AF_INET6)
883
struct sockaddr_in6 in6_addr;
885
struct sockaddr *addr = NULL;
892
#if defined(STREAMSCONN)
893
struct t_call call, rcv;
896
xdm = (char *) app_resources.xdmAddress->data;
897
family = (xdm[0] << 8) + xdm[1];
901
in_addr.sin_len = sizeof(in_addr);
903
in_addr.sin_family = family;
904
memmove( &in_addr.sin_port, xdm + 2, 2);
905
memmove( &in_addr.sin_addr, xdm + 4, 4);
906
addr = (struct sockaddr *) &in_addr;
907
len = sizeof (in_addr);
909
#if defined(IPv6) && defined(AF_INET6)
911
bzero(&in6_addr, sizeof(in6_addr));
913
in6_addr.sin6_len = sizeof(in6_addr);
915
in6_addr.sin6_family = family;
916
memmove( &in6_addr.sin6_port, xdm + 2, 2);
917
memmove( &in6_addr.sin6_addr, xdm + 4, 16);
918
addr = (struct sockaddr *) &in6_addr;
919
len = sizeof (in6_addr);
923
#if defined(STREAMSCONN)
924
if ((fd = t_open ("/dev/tcp", O_RDWR, NULL)) == -1)
926
fprintf (stderr, "Cannot create response endpoint\n");
928
exit (REMANAGE_DISPLAY);
930
if (t_bind (fd, NULL, NULL) == -1)
932
fprintf (stderr, "Cannot bind response endpoint\n");
935
exit (REMANAGE_DISPLAY);
937
call.addr.buf=(char *)addr;
939
call.addr.maxlen=len;
944
if (t_connect (fd, &call, NULL) == -1)
946
t_error ("Cannot connect to xdm\n");
950
exit (REMANAGE_DISPLAY);
953
if ((fd = socket (family, SOCK_STREAM, 0)) == -1)
955
fprintf (stderr, "Cannot create response socket\n");
956
exit (REMANAGE_DISPLAY);
958
if (connect (fd, addr, len) == -1)
960
fprintf (stderr, "Cannot connect to xdm\n");
961
exit (REMANAGE_DISPLAY);
964
buffer.data = (BYTE *) buf;
965
buffer.size = sizeof (buf);
968
XdmcpWriteARRAY8 (&buffer, app_resources.clientAddress);
969
XdmcpWriteCARD16 (&buffer, (CARD16) app_resources.connectionType);
970
XdmcpWriteARRAY8 (&buffer, &h->hostaddr);
971
#if defined(STREAMSCONN)
972
if( t_snd (fd, (char *)buffer.data, buffer.pointer, 0) < 0 )
974
fprintf (stderr, "Cannot send to xdm\n");
978
exit (REMANAGE_DISPLAY);
980
sleep(5); /* Hack because sometimes the connection gets
981
closed before the data arrives on the other end. */
986
write (fd, (char *)buffer.data, buffer.pointer);
994
printf ("%u\n", h->connectionType);
995
for (i = 0; i < (int)h->hostaddr.length; i++)
996
printf ("%u%s", h->hostaddr.data[i],
997
i == h->hostaddr.length - 1 ? "\n" : " ");
1002
next_line returns the next line in a list
1003
across the list end.
1004
(0, 1, 2, 3, 0, 1, 2, 3 ....)
1008
next_line(unsigned int current, unsigned int size, int event)
1012
return (current + 1) % size;
1014
return (current + size - 1) % size;
1016
return (current + 1) % size;
1018
return (current + size - 1) % size;
1024
Hostselect selects a given chooser line.
1025
Returns 1 when host is willing and 0 if not
1029
Hostselect (int line)
1031
XawListReturnStruct *r;
1033
r = XawListShowCurrent (list);
1034
/* Assume the next host is willing */
1035
XawListHighlight (list,line);
1036
r = XawListShowCurrent (list);
1037
/* copied from DoCheckWilling */
1038
for (h = hostNamedb; h; h = h->next)
1040
if (!strcmp (r->string, h->fullname))
1043
XawListUnhighlight (list);
1046
/* Scroll viewport to make sure new selection is visible */
1048
Dimension height, portheight;
1050
int lineheight, liney, newy = 0;
1052
XtSetArg (size[0], XtNheight, &height);
1053
XtSetArg (size[1], XtNy, &y);
1054
XtGetValues (list, size, (Cardinal) 2);
1056
XtSetArg (size[0], XtNheight, &portheight);
1057
XtGetValues (viewport, size, (Cardinal) 1);
1059
lineheight = height / NameTableSize;
1060
liney = lineheight * line;
1062
if ((y + liney) < 0) {
1063
XawViewportSetCoordinates(viewport, 0, liney);
1064
} else if ((y + liney + lineheight) > portheight) {
1065
XawViewportSetCoordinates(viewport, 0,
1066
(liney + lineheight) - portheight);
1077
Selectfirst selects the first willing host
1078
in the chooser list (so you can select a host without
1079
presence of mouse, but with pressing space or return,
1088
for (line = 0; line < NameTableSize; line++)
1090
if (Hostselect(line))
1097
Storeold stores the selected line into global int oldentry
1101
Storeold (Widget w, XEvent *event, String *params, Cardinal *num_params)
1103
oldline = (XawListShowCurrent(list))->list_index;
1107
Setold restores the global int oldentry
1108
when you try to select a host with your mouse
1109
who is unwilling as follows:
1110
<Btn1Down>: Store() Set() CheckWilling() Setold() \n\
1114
Setold (Widget w, XEvent *event, String *params, Cardinal *num_params)
1117
if ( (XawListShowCurrent(list))->list_index == XAW_LIST_NONE && oldline != XAW_LIST_NONE)
1118
XawListHighlight (list, oldline);
1122
HostCycle tries to select the next willing host across
1123
the list end and will stop at the first found willing host
1124
or after trying all entries.
1128
HostCycle(unsigned int line, unsigned int size, KeySym keysym)
1130
unsigned int newline = line;
1131
/* Do it only once around the chooser list, either direction */
1132
while ( (newline = next_line(newline,size,keysym)) != line && newline != -1)
1134
if (Hostselect(newline))
1137
/* No other willing host could be found, stay at the old one*/
1138
XawListHighlight (list, line);
1143
Switch_Key handles XK_Up and XK_Down
1144
and highlights an appropriate line in the chooser list.
1148
Switch_Key (Widget w, XEvent *event, String *params, Cardinal *num_params)
1152
static XComposeStatus compose_status = {NULL, 0};
1153
XawListReturnStruct *r;
1155
XLookupString (&event->xkey, strbuf, sizeof (strbuf),
1156
&keysym, &compose_status);
1158
if (keysym != XK_Up && keysym != XK_Down)
1161
r = XawListShowCurrent (list);
1163
if (r->list_index == XAW_LIST_NONE)
1166
HostCycle(r->list_index,NameTableSize,keysym);
1174
Switch_Btn handles ScrollWheel Forward (Button5) and Backward
1175
(Button4) and highlights an appropriate line in the chooser list.
1179
Switch_Btn (Widget w, XEvent *event, String *params, Cardinal *num_params)
1181
XawListReturnStruct *r;
1182
r = XawListShowCurrent (list);
1184
if (r->list_index == XAW_LIST_NONE)
1187
HostCycle(r->list_index,NameTableSize,event->xbutton.button);
1195
DoAccept (Widget w, XEvent *event, String *params, Cardinal *num_params)
1197
XawListReturnStruct *r;
1200
r = XawListShowCurrent (list);
1201
if (r->list_index == XAW_LIST_NONE)
1203
XkbStdBell(XtDisplay(toplevel),XtWindow(w),0,XkbBI_MinorError);
1205
XBell (XtDisplay (toplevel), 0);
1209
for (h = hostNamedb; h; h = h->next)
1210
if (!strcmp (r->string, h->fullname))
1214
exit (OBEYSESS_DISPLAY);
1220
DoCheckWilling (Widget w, XEvent *event, String *params, Cardinal *num_params)
1222
XawListReturnStruct *r;
1225
r = XawListShowCurrent (list);
1226
if (r->list_index == XAW_LIST_NONE)
1228
for (h = hostNamedb; h; h = h->next)
1229
if (!strcmp (r->string, h->fullname))
1231
XawListUnhighlight (list);
1236
DoCancel (Widget w, XEvent *event, String *params, Cardinal *num_params)
1238
exit (OBEYSESS_DISPLAY);
1243
DoPing (Widget w, XEvent *event, String *params, Cardinal *num_params)
1247
PingHosts ((XtPointer)NULL, (XtIntervalId *)NULL);
1250
static XtActionsRec app_actions[] = {
1251
{ "Accept", DoAccept },
1252
{ "Cancel", DoCancel },
1253
{ "CheckWilling", DoCheckWilling },
1255
{ "KeySwitch", Switch_Key },
1256
{ "BtnSwitch", Switch_Btn },
1257
{ "Store", Storeold },
1258
{ "Setold", Setold },
1262
main (int argc, char **argv)
1265
Dimension width, height;
1268
XineramaScreenInfo *screens;
1273
toplevel = XtInitialize (argv[0], "Chooser", options, XtNumber(options), &argc, argv);
1275
XtAddConverter(XtRString, XtRARRAY8, CvtStringToARRAY8, NULL, 0);
1277
XtGetApplicationResources (toplevel, (XtPointer) &app_resources, resources,
1278
XtNumber (resources), NULL, (Cardinal) 0);
1280
XtAddActions (app_actions, XtNumber (app_actions));
1281
paned = XtCreateManagedWidget ("paned", panedWidgetClass, toplevel, NULL, 0);
1282
label = XtCreateManagedWidget ("label", labelWidgetClass, paned, NULL, 0);
1283
viewport = XtCreateManagedWidget ("viewport", viewportWidgetClass, paned, NULL, 0);
1284
list = XtCreateManagedWidget ("list", listWidgetClass, viewport, NULL, 0);
1285
box = XtCreateManagedWidget ("box", boxWidgetClass, paned, NULL, 0);
1286
cancel = XtCreateManagedWidget ("cancel", commandWidgetClass, box, NULL, 0);
1287
acceptit = XtCreateManagedWidget ("accept", commandWidgetClass, box, NULL, 0);
1288
ping = XtCreateManagedWidget ("ping", commandWidgetClass, box, NULL, 0);
1291
* center ourselves on the screen
1293
XtSetMappedWhenManaged(toplevel, FALSE);
1294
XtRealizeWidget (toplevel);
1296
XtSetArg (position[0], XtNwidth, &width);
1297
XtSetArg (position[1], XtNheight, &height);
1298
XtGetValues (toplevel, position, (Cardinal) 2);
1301
XineramaIsActive(XtDisplay(toplevel)) &&
1302
(screens = XineramaQueryScreens(XtDisplay(toplevel), &s_num)) != NULL
1305
x = (Position)(screens[0].x_org + (screens[0].width - width) / 2);
1306
y = (Position)(screens[0].y_org + (screens[0].height - height) / 3);
1313
x = (Position)(WidthOfScreen (XtScreen (toplevel)) - width) / 2;
1314
y = (Position)(HeightOfScreen (XtScreen (toplevel)) - height) / 3;
1316
XtSetArg (position[0], XtNx, x);
1317
XtSetArg (position[1], XtNy, y);
1318
XtSetValues (toplevel, position, (Cardinal) 2);
1323
XtMapWidget(toplevel);
1324
InitXDMCP (argv + 1);
1330
/* Converts the hex string s of length len into the byte array d.
1331
Returns 0 if s was a legal hex string, 1 otherwise.
1334
FromHex (char *s, char *d, int len)
1337
int ret = len&1; /* odd-length hex strings are illegal */
1340
#define HexChar(c) ('0' <= (c) && (c) <= '9' ? (c) - '0' : (c) - 'a' + 10)
1342
if (!ishexdigit(*s))
1344
t = HexChar (*s) << 4;
1346
if (!ishexdigit(*s))
1358
CvtStringToARRAY8 (XrmValuePtr args, Cardinal *num_args, XrmValuePtr fromVal, XrmValuePtr toVal)
1360
static ARRAY8Ptr dest;
1364
dest = (ARRAY8Ptr) XtMalloc (sizeof (ARRAY8));
1365
len = fromVal->size;
1366
s = (char *) fromVal->addr;
1367
if (!XdmcpAllocARRAY8 (dest, len >> 1))
1368
XtStringConversionWarning ((char *) fromVal->addr, XtRARRAY8);
1371
FromHex (s, (char *) dest->data, len);
1373
toVal->addr = (caddr_t) &dest;
1374
toVal->size = sizeof (ARRAY8Ptr);