~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/xdm/chooser.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Xorg: chooser.c,v 1.4 2001/02/09 02:05:40 xorgcvs Exp $
 
3
 *
 
4
Copyright 1990, 1998  The Open Group
 
5
 
 
6
Permission to use, copy, modify, distribute, and sell this software and its
 
7
documentation for any purpose is hereby granted without fee, provided that
 
8
the above copyright notice appear in all copies and that both that
 
9
copyright notice and this permission notice appear in supporting
 
10
documentation.
 
11
 
 
12
The above copyright notice and this permission notice shall be included in
 
13
all copies or substantial portions of the Software.
 
14
 
 
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 
18
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
19
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
20
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
21
 
 
22
Except as contained in this notice, the name of The Open Group shall not be
 
23
used in advertising or otherwise to promote the sale, use or other dealings
 
24
in this Software without prior written authorization from The Open Group.
 
25
 *
 
26
 * Author:  Keith Packard, MIT X Consortium
 
27
 */
 
28
 
 
29
/* $XFree86: xc/programs/xdm/chooser.c,v 3.24 2001/12/14 20:01:20 dawes Exp $ */
 
30
 
 
31
/*
 
32
 * Chooser - display a menu of names and let the user select one
 
33
 */
 
34
 
 
35
/*
 
36
 * Layout:
 
37
 *
 
38
 *  +--------------------------------------------------+
 
39
 *  |             +------------------+                 |
 
40
 *  |             |      Label       |                 |
 
41
 *  |             +------------------+                 |
 
42
 *  |    +-+--------------+                            |
 
43
 *  |    |^| name-1       |                            |
 
44
 *  |    ||| name-2       |                            |
 
45
 *  |    |v| name-3       |                            |
 
46
 *  |    | | name-4       |                            |
 
47
 *  |    | | name-5       |                            |
 
48
 *  |    | | name-6       |                            |
 
49
 *  |    +----------------+                            |
 
50
 *  |    cancel  accept  ping                          |
 
51
 *  +--------------------------------------------------+
 
52
 */
 
53
 
 
54
#include    <X11/Intrinsic.h>
 
55
#include    <X11/StringDefs.h>
 
56
#include    <X11/Xatom.h>
 
57
 
 
58
#include    <X11/Xaw/Paned.h>
 
59
#include    <X11/Xaw/Label.h>
 
60
#include    <X11/Xaw/Viewport.h>
 
61
#include    <X11/Xaw/List.h>
 
62
#include    <X11/Xaw/Box.h>
 
63
#include    <X11/Xaw/Command.h>
 
64
 
 
65
#include    "dm.h"
 
66
 
 
67
#include    <X11/Xdmcp.h>
 
68
 
 
69
#include    <sys/types.h>
 
70
#include    <stdio.h>
 
71
#include    <ctype.h>
 
72
 
 
73
#ifdef USE_XINERAMA
 
74
#include    <X11/extensions/Xinerama.h>
 
75
#endif
 
76
 
 
77
#if defined(SVR4) && !defined(SCO325)
 
78
#include    <sys/sockio.h>
 
79
#endif
 
80
#if defined(SVR4) && defined(PowerMAX_OS)
 
81
#include    <sys/stropts.h>
 
82
#endif
 
83
#if defined(SYSV) && defined(i386)
 
84
#include    <sys/stream.h>
 
85
#ifdef ISC
 
86
#include    <sys/sioctl.h>
 
87
#include    <sys/stropts.h>
 
88
#endif
 
89
#endif
 
90
 
 
91
#include    "dm_socket.h"
 
92
 
 
93
#include    <arpa/inet.h>
 
94
 
 
95
#include    <sys/ioctl.h>
 
96
#ifdef STREAMSCONN
 
97
#ifdef WINTCP /* NCR with Wollongong TCP */
 
98
#include    <netinet/ip.h>
 
99
#endif
 
100
#include    <stropts.h>
 
101
#include    <tiuser.h>
 
102
#include    <netconfig.h>
 
103
#include    <netdir.h>
 
104
#endif
 
105
 
 
106
#ifdef CSRG_BASED
 
107
#include <sys/param.h>
 
108
#if (BSD >= 199103)
 
109
#define VARIABLE_IFREQ
 
110
#endif
 
111
#endif
 
112
 
 
113
#ifdef XKB
 
114
#include <X11/extensions/XKBbells.h>
 
115
#endif
 
116
 
 
117
#define BROADCAST_HOSTNAME  "BROADCAST"
 
118
 
 
119
#ifndef ishexdigit
 
120
#define ishexdigit(c)   (isdigit(c) || ('a' <= (c) && (c) <= 'f'))
 
121
#endif
 
122
 
 
123
#ifdef hpux
 
124
# include <sys/utsname.h>
 
125
# ifdef HAS_IFREQ
 
126
#  include <net/if.h>
 
127
# endif
 
128
#else
 
129
#ifdef __convex__
 
130
# include <sync/queue.h>
 
131
# include <sync/sema.h>
 
132
#endif
 
133
#ifndef __GNU__
 
134
# include <net/if.h>
 
135
#endif /* __GNU__ */
 
136
#endif /* hpux */
 
137
 
 
138
#include    <netdb.h>
 
139
 
 
140
static int FromHex (char *s, char *d, int len);
 
141
 
 
142
Widget      toplevel, label, viewport, paned, list, box, cancel, acceptit, ping;
 
143
 
 
144
static void     CvtStringToARRAY8(
 
145
    XrmValuePtr args,
 
146
    Cardinal    *num_args,
 
147
    XrmValuePtr fromVal,
 
148
    XrmValuePtr toVal);
 
149
 
 
150
static struct _app_resources {
 
151
    ARRAY8Ptr   xdmAddress;
 
152
    ARRAY8Ptr   clientAddress;
 
153
    int         connectionType;
 
154
} app_resources;
 
155
 
 
156
#define offset(field) XtOffsetOf(struct _app_resources, field)
 
157
 
 
158
#define XtRARRAY8   "ARRAY8"
 
159
 
 
160
static XtResource  resources[] = {
 
161
    {"xdmAddress",      "XdmAddress",  XtRARRAY8,       sizeof (ARRAY8Ptr),
 
162
        offset (xdmAddress),        XtRString,  NULL },
 
163
    {"clientAddress",   "ClientAddress",  XtRARRAY8,    sizeof (ARRAY8Ptr),
 
164
        offset (clientAddress),     XtRString,  NULL },
 
165
    {"connectionType",  "ConnectionType",   XtRInt,     sizeof (int),
 
166
        offset (connectionType),    XtRImmediate,       (XtPointer) 0 }
 
167
};
 
168
#undef offset
 
169
 
 
170
static XrmOptionDescRec options[] = {
 
171
    { "-xdmaddress",    "*xdmAddress",      XrmoptionSepArg,    NULL },
 
172
    { "-clientaddress", "*clientAddress",   XrmoptionSepArg,    NULL },
 
173
    { "-connectionType","*connectionType",  XrmoptionSepArg,    NULL },
 
174
};
 
175
 
 
176
typedef struct _hostAddr {
 
177
    struct _hostAddr    *next;
 
178
    struct sockaddr     *addr;
 
179
    int                 addrlen;
 
180
    xdmOpCode           type;
 
181
} HostAddr;
 
182
 
 
183
static HostAddr    *hostAddrdb;
 
184
 
 
185
typedef struct _hostName {
 
186
    struct _hostName    *next;
 
187
    char                *fullname;
 
188
    int                 willing;
 
189
    ARRAY8              hostname, status;
 
190
    CARD16              connectionType;
 
191
    ARRAY8              hostaddr;
 
192
} HostName;
 
193
 
 
194
static HostName    *hostNamedb;
 
195
 
 
196
static int  socketFD;
 
197
 
 
198
static int  pingTry;
 
199
 
 
200
#define PING_INTERVAL   2000
 
201
#define TRIES           3
 
202
 
 
203
static XdmcpBuffer      directBuffer, broadcastBuffer;
 
204
static XdmcpBuffer      buffer;
 
205
 
 
206
#if ((defined(SVR4) && !defined(sun) && !defined(__sgi) && !defined(NCR)) || defined(ISC)) && defined(SIOCGIFCONF)
 
207
 
 
208
/* Deal with different SIOCGIFCONF ioctl semantics on these OSs */
 
209
 
 
210
static int
 
211
ifioctl (int fd, int cmd, char *arg)
 
212
{
 
213
    struct strioctl ioc;
 
214
    int ret;
 
215
 
 
216
    bzero((char *) &ioc, sizeof(ioc));
 
217
    ioc.ic_cmd = cmd;
 
218
    ioc.ic_timout = 0;
 
219
    if (cmd == SIOCGIFCONF)
 
220
    {
 
221
        ioc.ic_len = ((struct ifconf *) arg)->ifc_len;
 
222
        ioc.ic_dp = ((struct ifconf *) arg)->ifc_buf;
 
223
#ifdef ISC
 
224
        /* SIOCGIFCONF is somewhat brain damaged on ISC. The argument
 
225
         * buffer must contain the ifconf structure as header. Ifc_req
 
226
         * is also not a pointer but a one element array of ifreq
 
227
         * structures. On return this array is extended by enough
 
228
         * ifreq fields to hold all interfaces. The return buffer length
 
229
         * is placed in the buffer header.
 
230
         */
 
231
        ((struct ifconf *) ioc.ic_dp)->ifc_len =
 
232
                                         ioc.ic_len - sizeof(struct ifconf);
 
233
#endif
 
234
    }
 
235
    else
 
236
    {
 
237
        ioc.ic_len = sizeof(struct ifreq);
 
238
        ioc.ic_dp = arg;
 
239
    }
 
240
    ret = ioctl(fd, I_STR, (char *) &ioc);
 
241
    if (ret >= 0 && cmd == SIOCGIFCONF)
 
242
#ifdef SVR4
 
243
        ((struct ifconf *) arg)->ifc_len = ioc.ic_len;
 
244
#endif
 
245
#ifdef ISC
 
246
    {
 
247
        ((struct ifconf *) arg)->ifc_len =
 
248
                                 ((struct ifconf *)ioc.ic_dp)->ifc_len;
 
249
        ((struct ifconf *) arg)->ifc_buf = 
 
250
                        (caddr_t)((struct ifconf *)ioc.ic_dp)->ifc_req;
 
251
    }
 
252
#endif
 
253
    return(ret);
 
254
}
 
255
#else /* ((SVR4 && !sun && !NCR) || ISC) && SIOCGIFCONF */
 
256
#define ifioctl ioctl
 
257
#endif /* ((SVR4 && !sun) || ISC) && SIOCGIFCONF */
 
258
 
 
259
 
 
260
/* ARGSUSED */
 
261
static void
 
262
PingHosts (XtPointer closure, XtIntervalId *id)
 
263
{
 
264
    HostAddr    *hosts;
 
265
 
 
266
    for (hosts = hostAddrdb; hosts; hosts = hosts->next)
 
267
    {
 
268
        if (hosts->type == QUERY)
 
269
            XdmcpFlush (socketFD, &directBuffer, (XdmcpNetaddr) hosts->addr, hosts->addrlen);
 
270
        else
 
271
            XdmcpFlush (socketFD, &broadcastBuffer, (XdmcpNetaddr) hosts->addr, hosts->addrlen);
 
272
    }
 
273
    if (++pingTry < TRIES)
 
274
        XtAddTimeOut (PING_INTERVAL, PingHosts, (XtPointer) 0);
 
275
}
 
276
 
 
277
char    **NameTable;
 
278
int     NameTableSize;
 
279
 
 
280
static int
 
281
HostnameCompare (const void *a, const void *b)
 
282
{
 
283
    return strcmp (*(char **)a, *(char **)b);
 
284
}
 
285
 
 
286
static void
 
287
RebuildTable (int size)
 
288
{
 
289
    char        **newTable = 0;
 
290
    HostName    *names;
 
291
    int         i;
 
292
 
 
293
    if (size)
 
294
    {
 
295
        newTable = (char **) malloc (size * sizeof (char *));
 
296
        if (!newTable)
 
297
            return;
 
298
        for (names = hostNamedb, i = 0; names; names = names->next, i++)
 
299
            newTable[i] = names->fullname;
 
300
        qsort (newTable, size, sizeof (char *), HostnameCompare);
 
301
    }
 
302
    XawListChange (list, newTable, size, 0, TRUE);
 
303
    if (NameTable)
 
304
        free ((char *) NameTable);
 
305
    NameTable = newTable;
 
306
    NameTableSize = size;
 
307
}
 
308
 
 
309
static int
 
310
AddHostname (ARRAY8Ptr hostname, ARRAY8Ptr status, struct sockaddr *addr, int willing)
 
311
{
 
312
    HostName    *new, **names, *name;
 
313
    ARRAY8      hostAddr;
 
314
    CARD16      connectionType;
 
315
    int         fulllen;
 
316
 
 
317
    switch (addr->sa_family)
 
318
    {
 
319
    case AF_INET:
 
320
        hostAddr.data = (CARD8 *) &((struct sockaddr_in *) addr)->sin_addr;
 
321
        hostAddr.length = 4;
 
322
        connectionType = FamilyInternet;
 
323
        break;
 
324
    default:
 
325
        hostAddr.data = (CARD8 *) "";
 
326
        hostAddr.length = 0;
 
327
        connectionType = FamilyLocal;
 
328
        break;
 
329
    }
 
330
    for (names = &hostNamedb; *names; names = & (*names)->next)
 
331
    {
 
332
        name = *names;
 
333
        if (connectionType == name->connectionType &&
 
334
            XdmcpARRAY8Equal (&hostAddr, &name->hostaddr))
 
335
        {
 
336
            if (XdmcpARRAY8Equal (status, &name->status))
 
337
            {
 
338
                return 0;
 
339
            }
 
340
            break;
 
341
        }
 
342
    }
 
343
    if (!*names)
 
344
    {
 
345
        new = (HostName *) malloc (sizeof (HostName));
 
346
        if (!new)
 
347
            return 0;
 
348
        if (hostname->length)
 
349
        {
 
350
            switch (addr->sa_family)
 
351
            {
 
352
            case AF_INET:
 
353
                {
 
354
                    struct hostent  *hostent;
 
355
                    char            *host;
 
356
        
 
357
                    hostent = gethostbyaddr ((char *)hostAddr.data, hostAddr.length, AF_INET);
 
358
                    if (hostent)
 
359
                    {
 
360
                        XdmcpDisposeARRAY8 (hostname);
 
361
                        host = (char *)hostent->h_name;
 
362
                        XdmcpAllocARRAY8 (hostname, strlen (host));
 
363
                        memmove( hostname->data, host, hostname->length);
 
364
                    }
 
365
                }
 
366
            }
 
367
        }
 
368
        if (!XdmcpAllocARRAY8 (&new->hostaddr, hostAddr.length))
 
369
        {
 
370
            free ((char *) new->fullname);
 
371
            free ((char *) new);
 
372
            return 0;
 
373
        }
 
374
        memmove( new->hostaddr.data, hostAddr.data, hostAddr.length);
 
375
        new->connectionType = connectionType;
 
376
        new->hostname = *hostname;
 
377
 
 
378
        *names = new;
 
379
        new->next = 0;
 
380
        NameTableSize++;
 
381
    }
 
382
    else
 
383
    {
 
384
        new = *names;
 
385
        free (new->fullname);
 
386
        XdmcpDisposeARRAY8 (&new->status);
 
387
        XdmcpDisposeARRAY8 (hostname);
 
388
    }
 
389
    new->willing = willing;
 
390
    new->status = *status;
 
391
 
 
392
    hostname = &new->hostname;
 
393
    fulllen = hostname->length;
 
394
    if (fulllen < 30)
 
395
        fulllen = 30;
 
396
    new->fullname = malloc (fulllen + status->length + 10);
 
397
    if (!new->fullname)
 
398
    {
 
399
        new->fullname = "Unknown";
 
400
    }
 
401
    else
 
402
    {
 
403
        sprintf (new->fullname, "%-30.*s %*.*s",
 
404
                 hostname->length, hostname->data,
 
405
                 status->length, status->length, status->data);
 
406
    }
 
407
    RebuildTable (NameTableSize);
 
408
    return 1;
 
409
}
 
410
 
 
411
static void
 
412
DisposeHostname (HostName *host)
 
413
{
 
414
    XdmcpDisposeARRAY8 (&host->hostname);
 
415
    XdmcpDisposeARRAY8 (&host->hostaddr);
 
416
    XdmcpDisposeARRAY8 (&host->status);
 
417
    free ((char *) host->fullname);
 
418
    free ((char *) host);
 
419
}
 
420
 
 
421
#if 0
 
422
static void
 
423
RemoveHostname (HostName *host)
 
424
{
 
425
    HostName    **prev, *hosts;
 
426
 
 
427
    prev = &hostNamedb;;
 
428
    for (hosts = hostNamedb; hosts; hosts = hosts->next)
 
429
    {
 
430
        if (hosts == host)
 
431
            break;
 
432
        prev = &hosts->next;
 
433
    }
 
434
    if (!hosts)
 
435
        return;
 
436
    *prev = host->next;
 
437
    DisposeHostname (host);
 
438
    NameTableSize--;
 
439
    RebuildTable (NameTableSize);
 
440
}
 
441
#endif
 
442
 
 
443
static void
 
444
EmptyHostnames (void)
 
445
{
 
446
    HostName    *hosts, *next;
 
447
 
 
448
    for (hosts = hostNamedb; hosts; hosts = next)
 
449
    {
 
450
        next = hosts->next;
 
451
        DisposeHostname (hosts);
 
452
    }
 
453
    NameTableSize = 0;
 
454
    hostNamedb = 0;
 
455
    RebuildTable (NameTableSize);
 
456
}
 
457
 
 
458
/* ARGSUSED */
 
459
static void
 
460
ReceivePacket (XtPointer closure, int *source, XtInputId *id)
 
461
{
 
462
    XdmcpHeader     header;
 
463
    ARRAY8          authenticationName;
 
464
    ARRAY8          hostname;
 
465
    ARRAY8          status;
 
466
    int             saveHostname = 0;
 
467
    struct sockaddr addr;
 
468
    int             addrlen;
 
469
 
 
470
    addrlen = sizeof (addr);
 
471
    if (!XdmcpFill (socketFD, &buffer, (XdmcpNetaddr) &addr, &addrlen))
 
472
        return;
 
473
    if (!XdmcpReadHeader (&buffer, &header))
 
474
        return;
 
475
    if (header.version != XDM_PROTOCOL_VERSION)
 
476
        return;
 
477
    hostname.data = 0;
 
478
    status.data = 0;
 
479
    authenticationName.data = 0;
 
480
    switch (header.opcode) {
 
481
    case WILLING:
 
482
        if (XdmcpReadARRAY8 (&buffer, &authenticationName) &&
 
483
            XdmcpReadARRAY8 (&buffer, &hostname) &&
 
484
            XdmcpReadARRAY8 (&buffer, &status))
 
485
        {
 
486
            if (header.length == 6 + authenticationName.length +
 
487
                hostname.length + status.length)
 
488
            {
 
489
                if (AddHostname (&hostname, &status, &addr, header.opcode == (int) WILLING))
 
490
                    saveHostname = 1;
 
491
            }
 
492
        }
 
493
        XdmcpDisposeARRAY8 (&authenticationName);
 
494
        break;
 
495
    case UNWILLING:
 
496
        if (XdmcpReadARRAY8 (&buffer, &hostname) &&
 
497
            XdmcpReadARRAY8 (&buffer, &status))
 
498
        {
 
499
            if (header.length == 4 + hostname.length + status.length)
 
500
            {
 
501
                if (AddHostname (&hostname, &status, &addr, header.opcode == (int) WILLING))
 
502
                    saveHostname = 1;
 
503
 
 
504
            }
 
505
        }
 
506
        break;
 
507
    default:
 
508
        break;
 
509
    }
 
510
    if (!saveHostname)
 
511
    {
 
512
        XdmcpDisposeARRAY8 (&hostname);
 
513
        XdmcpDisposeARRAY8 (&status);
 
514
    }
 
515
}
 
516
 
 
517
static void
 
518
RegisterHostaddr (struct sockaddr *addr, int len, xdmOpCode type)
 
519
{
 
520
    HostAddr            *host, **prev;
 
521
 
 
522
    host = (HostAddr *) malloc (sizeof (HostAddr));
 
523
    if (!host)
 
524
        return;
 
525
    host->addr = (struct sockaddr *) malloc (len);
 
526
    if (!host->addr)
 
527
    {
 
528
        free ((char *) host);
 
529
        return;
 
530
    }
 
531
    memmove( (char *) host->addr, (char *) addr, len);
 
532
    host->addrlen = len;
 
533
    host->type = type;
 
534
    for (prev = &hostAddrdb; *prev; prev = &(*prev)->next)
 
535
        ;
 
536
    *prev = host;
 
537
    host->next = NULL;
 
538
}
 
539
 
 
540
/*
 
541
 * Register the address for this host.
 
542
 * Called with each of the names on the command line.
 
543
 * The special name "BROADCAST" looks up all the broadcast
 
544
 *  addresses on the local host.
 
545
 */
 
546
 
 
547
#if !defined(__GNU__)
 
548
 
 
549
/* Handle variable length ifreq in BNR2 and later */
 
550
#ifdef VARIABLE_IFREQ
 
551
#define ifr_size(p) (sizeof (struct ifreq) + \
 
552
                     (p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \
 
553
                      p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0))
 
554
#else
 
555
#define ifr_size(p) (sizeof (struct ifreq))
 
556
#endif
 
557
 
 
558
static void
 
559
RegisterHostname (char *name)
 
560
{
 
561
    struct hostent      *hostent;
 
562
    struct sockaddr_in  in_addr;
 
563
    struct ifconf       ifc;
 
564
    register struct ifreq *ifr;
 
565
    struct sockaddr     broad_addr;
 
566
    char                buf[2048], *cp, *cplim;
 
567
 
 
568
    if (!strcmp (name, BROADCAST_HOSTNAME))
 
569
    {
 
570
#ifdef WINTCP /* NCR with Wollongong TCP */
 
571
    int                 ipfd;
 
572
    struct ifconf       *ifcp;
 
573
    struct strioctl     ioc;
 
574
    int                 n;
 
575
 
 
576
        ifcp = (struct ifconf *)buf;
 
577
        ifcp->ifc_buf = buf+4;
 
578
        ifcp->ifc_len = sizeof (buf) - 4;
 
579
 
 
580
        if ((ipfd=open( "/dev/ip", O_RDONLY )) < 0 )
 
581
            {
 
582
            t_error( "RegisterHostname() t_open(/dev/ip) failed" );
 
583
            return;
 
584
            }
 
585
 
 
586
        ioc.ic_cmd = IPIOC_GETIFCONF;
 
587
        ioc.ic_timout = 60;
 
588
        ioc.ic_len = sizeof( buf );
 
589
        ioc.ic_dp = (char *)ifcp;
 
590
 
 
591
        if (ioctl (ipfd, (int) I_STR, (char *) &ioc) < 0)
 
592
            {
 
593
            perror( "RegisterHostname() ioctl(I_STR(IPIOC_GETIFCONF)) failed" );
 
594
            close( ipfd );
 
595
            return;
 
596
            }
 
597
 
 
598
        for (ifr = ifcp->ifc_req, n = ifcp->ifc_len / sizeof (struct ifreq);
 
599
            --n >= 0;
 
600
            ifr++)
 
601
#else /* WINTCP */
 
602
        ifc.ifc_len = sizeof (buf);
 
603
        ifc.ifc_buf = buf;
 
604
        if (ifioctl (socketFD, (int) SIOCGIFCONF, (char *) &ifc) < 0)
 
605
            return;
 
606
 
 
607
#ifdef ISC
 
608
#define IFC_IFC_REQ (struct ifreq *) ifc.ifc_buf
 
609
#else
 
610
#define IFC_IFC_REQ ifc.ifc_req
 
611
#endif
 
612
 
 
613
        cplim = (char *) IFC_IFC_REQ + ifc.ifc_len;
 
614
 
 
615
        for (cp = (char *) IFC_IFC_REQ; cp < cplim; cp += ifr_size (ifr))
 
616
#endif /* WINTCP */
 
617
        {
 
618
#ifndef WINTCP
 
619
            ifr = (struct ifreq *) cp;
 
620
#endif
 
621
            if (ifr->ifr_addr.sa_family != AF_INET)
 
622
                continue;
 
623
 
 
624
            broad_addr = ifr->ifr_addr;
 
625
            ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
 
626
                htonl (INADDR_BROADCAST);
 
627
#ifdef SIOCGIFBRDADDR
 
628
            {
 
629
                struct ifreq    broad_req;
 
630
    
 
631
                broad_req = *ifr;
 
632
#ifdef WINTCP /* NCR with Wollongong TCP */
 
633
                ioc.ic_cmd = IPIOC_GETIFFLAGS;
 
634
                ioc.ic_timout = 0;
 
635
                ioc.ic_len = sizeof( broad_req );
 
636
                ioc.ic_dp = (char *)&broad_req;
 
637
 
 
638
                if (ioctl (ipfd, I_STR, (char *) &ioc) != -1 &&
 
639
#else /* WINTCP */
 
640
                if (ifioctl (socketFD, SIOCGIFFLAGS, (char *) &broad_req) != -1 &&
 
641
#endif /* WINTCP */
 
642
                    (broad_req.ifr_flags & IFF_BROADCAST) &&
 
643
                    (broad_req.ifr_flags & IFF_UP)
 
644
                    )
 
645
                {
 
646
                    broad_req = *ifr;
 
647
#ifdef WINTCP /* NCR with Wollongong TCP */
 
648
                    ioc.ic_cmd = IPIOC_GETIFBRDADDR;
 
649
                    ioc.ic_timout = 0;
 
650
                    ioc.ic_len = sizeof( broad_req );
 
651
                    ioc.ic_dp = (char *)&broad_req;
 
652
 
 
653
                    if (ioctl (ipfd, I_STR, (char *) &ioc) != -1)
 
654
#else /* WINTCP */
 
655
                    if (ifioctl (socketFD, SIOCGIFBRDADDR, &broad_req) != -1)
 
656
#endif /* WINTCP */
 
657
                        broad_addr = broad_req.ifr_addr;
 
658
                    else
 
659
                        continue;
 
660
                }
 
661
                else
 
662
                    continue;
 
663
            }
 
664
#endif
 
665
            in_addr = *((struct sockaddr_in *) &broad_addr);
 
666
            in_addr.sin_port = htons (XDM_UDP_PORT);
 
667
#ifdef BSD44SOCKETS
 
668
            in_addr.sin_len = sizeof(in_addr);
 
669
#endif
 
670
            RegisterHostaddr ((struct sockaddr *)&in_addr, sizeof (in_addr),
 
671
                              BROADCAST_QUERY);
 
672
        }
 
673
    }
 
674
    else
 
675
    {
 
676
 
 
677
        /* address as hex string, e.g., "12180022" (depreciated) */
 
678
        if (strlen(name) == 8 &&
 
679
            FromHex(name, (char *)&in_addr.sin_addr, strlen(name)) == 0)
 
680
        {
 
681
            in_addr.sin_family = AF_INET;
 
682
        }
 
683
        /* Per RFC 1123, check first for IP address in dotted-decimal form */
 
684
        else if ((in_addr.sin_addr.s_addr = inet_addr(name)) != -1)
 
685
            in_addr.sin_family = AF_INET;
 
686
        else
 
687
        {
 
688
            hostent = gethostbyname (name);
 
689
            if (!hostent)
 
690
                return;
 
691
            if (hostent->h_addrtype != AF_INET || hostent->h_length != 4)
 
692
                return;
 
693
            in_addr.sin_family = hostent->h_addrtype;
 
694
            memmove( &in_addr.sin_addr, hostent->h_addr, 4);
 
695
        }
 
696
        in_addr.sin_port = htons (XDM_UDP_PORT);
 
697
#ifdef BSD44SOCKETS
 
698
        in_addr.sin_len = sizeof(in_addr);
 
699
#endif
 
700
        RegisterHostaddr ((struct sockaddr *)&in_addr, sizeof (in_addr),
 
701
                          QUERY);
 
702
    }
 
703
}
 
704
#else /* __GNU__ */
 
705
static void
 
706
RegisterHostname (char *name)
 
707
{
 
708
    struct hostent      *hostent;
 
709
    struct sockaddr_in  in_addr;
 
710
 
 
711
    if (!strcmp (name, BROADCAST_HOSTNAME))
 
712
    {
 
713
            in_addr.sin_addr.s_addr= htonl(0xFFFFFFFF);
 
714
            in_addr.sin_port = htons (XDM_UDP_PORT);
 
715
            RegisterHostaddr ((struct sockaddr *)&in_addr, sizeof (in_addr),
 
716
                              BROADCAST_QUERY);
 
717
    }
 
718
    else
 
719
    {
 
720
 
 
721
        /* address as hex string, e.g., "12180022" (depreciated) */
 
722
        if (strlen(name) == 8 &&
 
723
            FromHex(name, (char *)&in_addr.sin_addr, strlen(name)) == 0)
 
724
        {
 
725
            in_addr.sin_family = AF_INET;
 
726
        }
 
727
        /* Per RFC 1123, check first for IP address in dotted-decimal form */
 
728
        else if ((in_addr.sin_addr.s_addr = inet_addr(name)) != -1)
 
729
            in_addr.sin_family = AF_INET;
 
730
        else
 
731
        {
 
732
            hostent = gethostbyname (name);
 
733
            if (!hostent)
 
734
                return;
 
735
            if (hostent->h_addrtype != AF_INET || hostent->h_length != 4)
 
736
                return;
 
737
            in_addr.sin_family = hostent->h_addrtype;
 
738
            memmove( &in_addr.sin_addr, hostent->h_addr, 4);
 
739
        }
 
740
        in_addr.sin_port = htons (XDM_UDP_PORT);
 
741
        RegisterHostaddr ((struct sockaddr *)&in_addr, sizeof (in_addr),
 
742
                          QUERY);
 
743
    }
 
744
}
 
745
#endif /* __GNU__ */
 
746
 
 
747
static ARRAYofARRAY8    AuthenticationNames;
 
748
 
 
749
#if 0
 
750
static void
 
751
RegisterAuthenticationName (char *name, int namelen)
 
752
{
 
753
    ARRAY8Ptr   authName;
 
754
    if (!XdmcpReallocARRAYofARRAY8 (&AuthenticationNames,
 
755
                                    AuthenticationNames.length + 1))
 
756
        return;
 
757
    authName = &AuthenticationNames.data[AuthenticationNames.length-1];
 
758
    if (!XdmcpAllocARRAY8 (authName, namelen))
 
759
        return;
 
760
    memmove( authName->data, name, namelen);
 
761
}
 
762
#endif
 
763
 
 
764
static int
 
765
InitXDMCP (char **argv)
 
766
{
 
767
    int soopts = 1;
 
768
    XdmcpHeader header;
 
769
    int i;
 
770
 
 
771
    header.version = XDM_PROTOCOL_VERSION;
 
772
    header.opcode = (CARD16) BROADCAST_QUERY;
 
773
    header.length = 1;
 
774
    for (i = 0; i < (int)AuthenticationNames.length; i++)
 
775
        header.length += 2 + AuthenticationNames.data[i].length;
 
776
    XdmcpWriteHeader (&broadcastBuffer, &header);
 
777
    XdmcpWriteARRAYofARRAY8 (&broadcastBuffer, &AuthenticationNames);
 
778
 
 
779
    header.version = XDM_PROTOCOL_VERSION;
 
780
    header.opcode = (CARD16) QUERY;
 
781
    header.length = 1;
 
782
    for (i = 0; i < (int)AuthenticationNames.length; i++)
 
783
        header.length += 2 + AuthenticationNames.data[i].length;
 
784
    XdmcpWriteHeader (&directBuffer, &header);
 
785
    XdmcpWriteARRAYofARRAY8 (&directBuffer, &AuthenticationNames);
 
786
#if defined(STREAMSCONN)
 
787
    if ((socketFD = t_open ("/dev/udp", O_RDWR, 0)) < 0)
 
788
        return 0;
 
789
 
 
790
    if (t_bind( socketFD, NULL, NULL ) < 0)
 
791
        {
 
792
        t_close(socketFD);
 
793
        return 0;
 
794
        }
 
795
 
 
796
    /*
 
797
     * This part of the code looks contrived. It will actually fit in nicely
 
798
     * when the CLTS part of Xtrans is implemented.
 
799
     */
 
800
    {
 
801
    struct netconfig *nconf;
 
802
 
 
803
    if( (nconf=getnetconfigent("udp")) == NULL )
 
804
        {
 
805
        t_unbind(socketFD);
 
806
        t_close(socketFD);
 
807
        return 0;
 
808
        }
 
809
 
 
810
    if( netdir_options(nconf, ND_SET_BROADCAST, socketFD, NULL) )
 
811
        {
 
812
        freenetconfigent(nconf);
 
813
        t_unbind(socketFD);
 
814
        t_close(socketFD);
 
815
        return 0;
 
816
        }
 
817
 
 
818
    freenetconfigent(nconf);
 
819
    }
 
820
#else
 
821
    if ((socketFD = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
 
822
        return 0;
 
823
#endif
 
824
#ifndef STREAMSCONN
 
825
#ifdef SO_BROADCAST
 
826
    soopts = 1;
 
827
    if (setsockopt (socketFD, SOL_SOCKET, SO_BROADCAST, (char *)&soopts, sizeof (soopts)) < 0)
 
828
        perror ("setsockopt");
 
829
#endif
 
830
#endif
 
831
    
 
832
    XtAddInput (socketFD, (XtPointer) XtInputReadMask, ReceivePacket,
 
833
                (XtPointer) 0);
 
834
    while (*argv)
 
835
    {
 
836
        RegisterHostname (*argv);
 
837
        ++argv;
 
838
    }
 
839
    pingTry = 0;
 
840
    PingHosts ((XtPointer)NULL, (XtIntervalId *)NULL);
 
841
    return 1;
 
842
}
 
843
 
 
844
static void
 
845
Choose (HostName *h)
 
846
{
 
847
    if (app_resources.xdmAddress)
 
848
    {
 
849
        struct sockaddr_in  in_addr;
 
850
        struct sockaddr *addr = NULL;
 
851
        int             family;
 
852
        int             len = 0;
 
853
        int             fd;
 
854
        char            buf[1024];
 
855
        XdmcpBuffer     buffer;
 
856
        char            *xdm;
 
857
#if defined(STREAMSCONN)
 
858
        struct  t_call  call, rcv;
 
859
#endif
 
860
 
 
861
        xdm = (char *) app_resources.xdmAddress->data;
 
862
        family = (xdm[0] << 8) + xdm[1];
 
863
        switch (family) {
 
864
        case AF_INET:
 
865
#ifdef BSD44SOCKETS
 
866
            in_addr.sin_len = sizeof(in_addr);
 
867
#endif
 
868
            in_addr.sin_family = family;
 
869
            memmove( &in_addr.sin_port, xdm + 2, 2);
 
870
            memmove( &in_addr.sin_addr, xdm + 4, 4);
 
871
            addr = (struct sockaddr *) &in_addr;
 
872
            len = sizeof (in_addr);
 
873
            break;
 
874
        }
 
875
#if defined(STREAMSCONN)
 
876
        if ((fd = t_open ("/dev/tcp", O_RDWR, NULL)) == -1)
 
877
        {
 
878
            fprintf (stderr, "Cannot create response endpoint\n");
 
879
            fflush(stderr);
 
880
            exit (REMANAGE_DISPLAY);
 
881
        }
 
882
        if (t_bind (fd, NULL, NULL) == -1)
 
883
        {
 
884
            fprintf (stderr, "Cannot bind response endpoint\n");
 
885
            fflush(stderr);
 
886
            t_close (fd);
 
887
            exit (REMANAGE_DISPLAY);
 
888
        }
 
889
        call.addr.buf=(char *)addr;
 
890
        call.addr.len=len;
 
891
        call.addr.maxlen=len;
 
892
        call.opt.len=0;
 
893
        call.opt.maxlen=0;
 
894
        call.udata.len=0;
 
895
        call.udata.maxlen=0;
 
896
        if (t_connect (fd, &call, NULL) == -1)
 
897
        {
 
898
            t_error ("Cannot connect to xdm\n");
 
899
            fflush(stderr);
 
900
            t_unbind (fd);
 
901
            t_close (fd);
 
902
            exit (REMANAGE_DISPLAY);
 
903
        }
 
904
#else
 
905
        if ((fd = socket (family, SOCK_STREAM, 0)) == -1)
 
906
        {
 
907
            fprintf (stderr, "Cannot create response socket\n");
 
908
            exit (REMANAGE_DISPLAY);
 
909
        }
 
910
        if (connect (fd, addr, len) == -1)
 
911
        {
 
912
            fprintf (stderr, "Cannot connect to xdm\n");
 
913
            exit (REMANAGE_DISPLAY);
 
914
        }
 
915
#endif
 
916
        buffer.data = (BYTE *) buf;
 
917
        buffer.size = sizeof (buf);
 
918
        buffer.pointer = 0;
 
919
        buffer.count = 0;
 
920
        XdmcpWriteARRAY8 (&buffer, app_resources.clientAddress);
 
921
        XdmcpWriteCARD16 (&buffer, (CARD16) app_resources.connectionType);
 
922
        XdmcpWriteARRAY8 (&buffer, &h->hostaddr);
 
923
#if defined(STREAMSCONN)
 
924
        if( t_snd (fd, (char *)buffer.data, buffer.pointer, 0) < 0 )
 
925
        {
 
926
            fprintf (stderr, "Cannot send to xdm\n");
 
927
            fflush(stderr);
 
928
            t_unbind (fd);
 
929
            t_close (fd);
 
930
            exit (REMANAGE_DISPLAY);
 
931
        }
 
932
        sleep(5);       /* Hack because sometimes the connection gets
 
933
                           closed before the data arrives on the other end. */
 
934
        t_snddis (fd,NULL);
 
935
        t_unbind (fd);
 
936
        t_close (fd);
 
937
#else
 
938
        write (fd, (char *)buffer.data, buffer.pointer);
 
939
        close (fd);
 
940
#endif
 
941
    }
 
942
    else
 
943
    {
 
944
        int i;
 
945
 
 
946
        printf ("%u\n", h->connectionType);
 
947
        for (i = 0; i < (int)h->hostaddr.length; i++)
 
948
            printf ("%u%s", h->hostaddr.data[i],
 
949
                    i == h->hostaddr.length - 1 ? "\n" : " ");
 
950
    }
 
951
}
 
952
 
 
953
/* ARGSUSED */
 
954
static void
 
955
DoAccept (Widget w, XEvent *event, String *params, Cardinal *num_params)
 
956
{
 
957
    XawListReturnStruct *r;
 
958
    HostName            *h;
 
959
 
 
960
    r = XawListShowCurrent (list);
 
961
    if (r->list_index == XAW_LIST_NONE)
 
962
#ifdef XKB
 
963
        XkbStdBell(XtDisplay(toplevel),XtWindow(w),0,XkbBI_MinorError);
 
964
#else
 
965
        XBell (XtDisplay (toplevel), 0);
 
966
#endif
 
967
    else
 
968
    {
 
969
        for (h = hostNamedb; h; h = h->next)
 
970
            if (!strcmp (r->string, h->fullname))
 
971
            {
 
972
                Choose (h);
 
973
            }
 
974
        exit (OBEYSESS_DISPLAY);
 
975
    }
 
976
}
 
977
 
 
978
/* ARGSUSED */
 
979
static void
 
980
DoCheckWilling (Widget w, XEvent *event, String *params, Cardinal *num_params)
 
981
{
 
982
    XawListReturnStruct *r;
 
983
    HostName            *h;
 
984
    
 
985
    r = XawListShowCurrent (list);
 
986
    if (r->list_index == XAW_LIST_NONE)
 
987
        return;
 
988
    for (h = hostNamedb; h; h = h->next)
 
989
        if (!strcmp (r->string, h->fullname))
 
990
            if (!h->willing)
 
991
                XawListUnhighlight (list);
 
992
}
 
993
 
 
994
/* ARGSUSED */
 
995
static void
 
996
DoCancel (Widget w, XEvent *event, String *params, Cardinal *num_params)
 
997
{
 
998
    exit (OBEYSESS_DISPLAY);
 
999
}
 
1000
 
 
1001
/* ARGSUSED */
 
1002
static void
 
1003
DoPing (Widget w, XEvent *event, String *params, Cardinal *num_params)
 
1004
{
 
1005
    EmptyHostnames ();
 
1006
    pingTry = 0;
 
1007
    PingHosts ((XtPointer)NULL, (XtIntervalId *)NULL);
 
1008
}
 
1009
 
 
1010
static XtActionsRec app_actions[] = {
 
1011
    { "Accept",       DoAccept },
 
1012
    { "Cancel",       DoCancel },
 
1013
    { "CheckWilling", DoCheckWilling },
 
1014
    { "Ping",         DoPing },
 
1015
};
 
1016
 
 
1017
int
 
1018
main (int argc, char **argv)
 
1019
{
 
1020
    Arg         position[3];
 
1021
    Dimension   width, height;
 
1022
    Position    x, y;
 
1023
#ifdef USE_XINERAMA
 
1024
    XineramaScreenInfo *screens;
 
1025
    int                 s_num;
 
1026
#endif
 
1027
 
 
1028
 
 
1029
    toplevel = XtInitialize (argv[0], "Chooser", options, XtNumber(options), &argc, argv);
 
1030
 
 
1031
    XtAddConverter(XtRString, XtRARRAY8, CvtStringToARRAY8, NULL, 0);
 
1032
 
 
1033
    XtGetApplicationResources (toplevel, (XtPointer) &app_resources, resources,
 
1034
                               XtNumber (resources), NULL, (Cardinal) 0);
 
1035
 
 
1036
    XtAddActions (app_actions, XtNumber (app_actions));
 
1037
    paned = XtCreateManagedWidget ("paned", panedWidgetClass, toplevel, NULL, 0);
 
1038
    label = XtCreateManagedWidget ("label", labelWidgetClass, paned, NULL, 0);
 
1039
    viewport = XtCreateManagedWidget ("viewport", viewportWidgetClass, paned, NULL, 0);
 
1040
    list = XtCreateManagedWidget ("list", listWidgetClass, viewport, NULL, 0);
 
1041
    box = XtCreateManagedWidget ("box", boxWidgetClass, paned, NULL, 0);
 
1042
    cancel = XtCreateManagedWidget ("cancel", commandWidgetClass, box, NULL, 0);
 
1043
    acceptit = XtCreateManagedWidget ("accept", commandWidgetClass, box, NULL, 0);
 
1044
    ping = XtCreateManagedWidget ("ping", commandWidgetClass, box, NULL, 0);
 
1045
 
 
1046
    /*
 
1047
     * center ourselves on the screen
 
1048
     */
 
1049
    XtSetMappedWhenManaged(toplevel, FALSE);
 
1050
    XtRealizeWidget (toplevel);
 
1051
 
 
1052
    XtSetArg (position[0], XtNwidth, &width);
 
1053
    XtSetArg (position[1], XtNheight, &height);
 
1054
    XtGetValues (toplevel, position, (Cardinal) 2);
 
1055
#ifdef USE_XINERAMA
 
1056
    if (
 
1057
        XineramaIsActive(XtDisplay(toplevel)) &&
 
1058
        (screens = XineramaQueryScreens(XtDisplay(toplevel), &s_num)) != NULL
 
1059
       )
 
1060
    {
 
1061
        x = (Position)(screens[0].x_org + (screens[0].width - width) / 2);
 
1062
        y = (Position)(screens[0].y_org + (screens[0].height - height) / 3);
 
1063
        
 
1064
        XFree(screens);
 
1065
    }
 
1066
    else
 
1067
#endif
 
1068
    {
 
1069
        x = (Position)(WidthOfScreen (XtScreen (toplevel)) - width) / 2;
 
1070
        y = (Position)(HeightOfScreen (XtScreen (toplevel)) - height) / 3;
 
1071
    }
 
1072
    XtSetArg (position[0], XtNx, x);
 
1073
    XtSetArg (position[1], XtNy, y);
 
1074
    XtSetValues (toplevel, position, (Cardinal) 2);
 
1075
 
 
1076
    /*
 
1077
     * Run
 
1078
     */
 
1079
    XtMapWidget(toplevel);
 
1080
    InitXDMCP (argv + 1);
 
1081
    XtMainLoop ();
 
1082
    exit(0);
 
1083
    /*NOTREACHED*/
 
1084
}
 
1085
 
 
1086
/* Converts the hex string s of length len into the byte array d.
 
1087
   Returns 0 if s was a legal hex string, 1 otherwise.
 
1088
   */
 
1089
static int
 
1090
FromHex (char *s, char *d, int len)
 
1091
{
 
1092
    int t;
 
1093
    int ret = len&1;            /* odd-length hex strings are illegal */
 
1094
    while (len >= 2)
 
1095
    {
 
1096
#define HexChar(c)  ('0' <= (c) && (c) <= '9' ? (c) - '0' : (c) - 'a' + 10)
 
1097
 
 
1098
        if (!ishexdigit(*s))
 
1099
            ret = 1;
 
1100
        t = HexChar (*s) << 4;
 
1101
        s++;
 
1102
        if (!ishexdigit(*s))
 
1103
            ret = 1;
 
1104
        t += HexChar (*s);
 
1105
        s++;
 
1106
        *d++ = t;
 
1107
        len -= 2;
 
1108
    }
 
1109
    return ret;
 
1110
}
 
1111
 
 
1112
/*ARGSUSED*/
 
1113
static void
 
1114
CvtStringToARRAY8 (XrmValuePtr args, Cardinal *num_args, XrmValuePtr fromVal, XrmValuePtr toVal)
 
1115
{
 
1116
    static ARRAY8Ptr    dest;
 
1117
    char        *s;
 
1118
    int         len;
 
1119
 
 
1120
    dest = (ARRAY8Ptr) XtMalloc (sizeof (ARRAY8));
 
1121
    len = fromVal->size;
 
1122
    s = (char *) fromVal->addr;
 
1123
    if (!XdmcpAllocARRAY8 (dest, len >> 1))
 
1124
        XtStringConversionWarning ((char *) fromVal->addr, XtRARRAY8);
 
1125
    else
 
1126
    {
 
1127
        FromHex (s, (char *) dest->data, len);
 
1128
    }
 
1129
    toVal->addr = (caddr_t) &dest;
 
1130
    toVal->size = sizeof (ARRAY8Ptr);
 
1131
}
 
1132