dtlogin: Resolve 27 compiler warnings
[oweals/cde.git] / cde / programs / dtlogin / chooser.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*                                                                      *
24  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
25  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
26  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
27  * (c) Copyright 1993, 1994 Novell, Inc.                                *
28  */
29 /*
30  * $TOG: chooser.c /main/8 1998/03/04 19:26:30 mgreess $
31  *
32 Copyright (c) 1990  X Consortium
33
34 Permission is hereby granted, free of charge, to any person obtaining a copy
35 of this software and associated documentation files (the "Software"), to deal
36 in the Software without restriction, including without limitation the rights
37 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
38 copies of the Software, and to permit persons to whom the Software is
39 furnished to do so, subject to the following conditions:
40
41 The above copyright notice and this permission notice shall be included in
42 all copies or substantial portions of the Software.
43
44 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
45 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
46 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
47 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
48 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
49 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
50
51 Except as contained in this notice, the name of the X Consortium shall not be
52 used in advertising or otherwise to promote the sale, use or other dealings
53 in this Software without prior written authorization from the X Consortium.
54  *
55  * Author:  Keith Packard, MIT X Consortium
56  */
57
58 /*
59  * Chooser - display a menu of names and let the user select one
60  */
61
62 /*
63  * Layout:
64  *
65  *  +--------------------------------------------------+
66  *  |             +------------------+                 |
67  *  |             |      Label       |                 |
68  *  |             +------------------+                 |
69  *  |    +-+--------------+                            |
70  *  |    |^| name-1       |                            |
71  *  |    ||| name-2       |                            |
72  *  |    |v| name-3       |                            |
73  *  |    | | name-4       |                            |
74  *  |    | | name-5       |                            |
75  *  |    | | name-6       |                            |
76  *  |    +----------------+                            |
77  *  |    cancel  accept  ping                          |
78  *  +--------------------------------------------------+
79  */
80
81 #include    <X11/Intrinsic.h>
82 #include    <X11/StringDefs.h>
83 #include    <X11/Xatom.h>
84
85
86 #include    <Xm/Xm.h>
87 #include    <Xm/DragC.h>
88 #include    <Xm/List.h>
89
90 #define     CHOOSER
91
92 #include    "dm.h"
93
94 #include    "vg.h"
95 #include    "vgmsg.h"
96
97 #include    <X11/Xdmcp.h>
98
99 #include    <sys/types.h>
100 #include    <stdio.h>
101 #include    <ctype.h>
102 #include    <locale.h>
103 #include    <nl_types.h>
104 #ifndef NL_CAT_LOCALE
105 #define NL_CAT_LOCALE 0
106 #endif
107
108 #ifdef SVR4
109 #include    <sys/sockio.h>
110 #endif
111 #include    <sys/socket.h>
112 #include    <netinet/in.h>
113 #include    <sys/ioctl.h>
114
115 /*
116  * From Xm/XmStringI.h
117  */
118 extern XtPointer _XmStringUngenerate (
119                                 XmString string,
120                                 XmStringTag tag,
121                                 XmTextType tag_type,
122                                 XmTextType output_type);
123
124 #define BROADCAST_HOSTNAME  "BROADCAST"
125
126 #ifndef ishexdigit
127 #define ishexdigit(c)   (isdigit(c) || 'a' <= (c) && (c) <= 'f')
128 #endif
129
130 #ifdef hpux
131 # include <sys/utsname.h>
132 # ifdef HAS_IFREQ
133 #  include <net/if.h>
134 # endif
135 #else
136 #ifdef __convex__
137 # include <sync/queue.h>
138 # include <sync/sema.h>
139 #endif
140 # include <net/if.h>
141 #endif /* hpux */
142
143 #include    <netdb.h>
144
145 Widget      toplevel, label, viewport, paned, list, box, cancel, acceptit, ping;
146
147 extern Widget chooser_list;
148 extern int orig_argc;
149 extern char **orig_argv;
150 extern int amChooser;
151 extern void MakeOptionsProc();
152
153 static Arg  chooserArgs[25];     /** Hopefully enough args **/
154
155 static void     CvtStringToARRAY8();
156
157 static struct _app_resources {
158     ARRAY8Ptr   xdmAddress;
159     ARRAY8Ptr   clientAddress;
160     int         connectionType;
161 } app_resources;
162
163 static int FromHex (char *s, char *d, int len);
164
165 #define offset(field) XtOffsetOf(struct _app_resources, field)
166
167 #define XtRARRAY8   "ARRAY8"
168
169 static XtResource  resources[] = {
170     {"xdmAddress",      "XdmAddress",  XtRARRAY8,       sizeof (ARRAY8Ptr),
171         offset (xdmAddress),        XtRString,  NULL },
172     {"clientAddress",   "ClientAddress",  XtRARRAY8,    sizeof (ARRAY8Ptr),
173         offset (clientAddress),     XtRString,  NULL },
174     {"connectionType",  "ConnectionType",   XtRInt,     sizeof (int),
175         offset (connectionType),    XtRImmediate,       (XtPointer) 0 }
176 };
177 #undef offset
178
179 static XrmOptionDescRec options[] = {
180     "-xdmaddress",      "*xdmAddress",      XrmoptionSepArg,    NULL,
181     "-clientaddress",   "*clientAddress",   XrmoptionSepArg,    NULL,
182     "-connectionType",  "*connectionType",  XrmoptionSepArg,    NULL,
183 };
184
185 typedef struct _hostAddr {
186     struct _hostAddr    *next;
187     struct sockaddr     *addr;
188     int                 addrlen;
189     xdmOpCode           type;
190 } HostAddr;
191
192 static HostAddr    *hostAddrdb;
193
194 typedef struct _hostName {
195     struct _hostName    *next;
196     char                *fullname;
197     int                 willing;
198     ARRAY8              hostname, status;
199     CARD16              connectionType;
200     ARRAY8              hostaddr;
201 } HostName;
202
203 static HostName    *hostNamedb;
204
205 static int  socketFD;
206
207 static int  pingTry;
208
209 #define PING_INTERVAL   2000
210 #define TRIES           3
211
212 static XdmcpBuffer      directBuffer, broadcastBuffer;
213 static XdmcpBuffer      buffer;
214
215
216 /* ARGSUSED */
217 static void
218 PingHosts (XtPointer closure, XtIntervalId *id)
219 {
220     HostAddr    *hosts;
221
222     for (hosts = hostAddrdb; hosts; hosts = hosts->next)
223     {
224         if (hosts->type == QUERY)
225             XdmcpFlush (socketFD, &directBuffer, hosts->addr, hosts->addrlen);
226         else
227             XdmcpFlush (socketFD, &broadcastBuffer, hosts->addr, hosts->addrlen);
228     }
229     if (++pingTry < TRIES)
230         XtAddTimeOut (PING_INTERVAL, PingHosts, (XtPointer) 0);
231 }
232
233 char    **NameTable;
234 int     NameTableSize;
235
236 #if defined(__STDC__)
237 static int
238 HostnameCompare (const void *a, const void *b)
239 #else
240 static int
241 HostnameCompare (char *a, char *b)
242 #endif
243 {
244     return strcmp (*(char **)a, *(char **)b);
245 }
246
247 static void
248 RebuildTable (int size)
249 {
250     char        **newTable = 0;
251     HostName    *names;
252     int         i;
253     XmStringTable newStringTable;
254     Arg         listArgs[10];
255     int         numArgs;
256
257     if (size)
258     {
259         newTable = (char **) malloc (size * sizeof (char *));
260         if (!newTable)
261             return;
262         for (names = hostNamedb, i = 0; names; names = names->next, i++)
263             newTable[i] = names->fullname;
264         qsort (newTable, size, sizeof (char *), HostnameCompare);
265     }
266       else  {
267         XmListDeleteAllItems(chooser_list);
268         if (NameTable)
269             free((char *)NameTable);
270         NameTableSize = 0;
271         return;
272     }
273
274     /***********************************/
275     /** Reload the data in the XmList **/
276     /***********************************/
277     newStringTable = (XmStringTable)malloc(size * sizeof(XmString));
278     if (!newStringTable) {
279         free((char *)newTable);
280         return;
281     }
282     for (i = 0; i < size; i++) {
283         newStringTable[i] = XmStringCreateLocalized(newTable[i]);
284     }
285     numArgs = 0;
286     XtSetArg(listArgs[numArgs], XmNitemCount, size); numArgs++;
287     XtSetArg(listArgs[numArgs], XmNitems, newStringTable); numArgs++;
288     XtSetValues(chooser_list, listArgs, numArgs);
289
290     free((char *) newStringTable);
291
292     if (NameTable)
293         free ((char *) NameTable);
294     NameTable = newTable;
295     NameTableSize = size;
296 }
297
298 static void
299 RebuildTableAdd (int size)
300 {
301     char        **newTable = 0;
302     HostName    *names;
303     int         i;
304     XmString    tempString;
305     int         position;
306
307     if (size)
308     {
309         newTable = (char **) malloc (size * sizeof (char *));
310         if (!newTable)
311             return;
312         for (names = hostNamedb, i = 0; names; names = names->next, i++)
313             newTable[i] = names->fullname;
314         qsort (newTable, size, sizeof (char *), HostnameCompare);
315     }
316
317     for (i = 0; i < size; i++) {
318         tempString = XmStringCreateLocalized(newTable[i]);
319         if ((position = XmListItemPos(chooser_list, tempString)) == 0) {
320             /****************************/
321             /** need to add a new host **/
322             /****************************/
323             XmListAddItemUnselected(chooser_list, tempString, (i+1));
324             XmStringFree(tempString);
325             break;
326         }
327         XmStringFree(tempString);
328     }
329
330     if (NameTable)
331         free ((char *) NameTable);
332     NameTable = newTable;
333     NameTableSize = size;
334 }
335
336
337 static int
338 AddHostname (ARRAY8Ptr hostname, ARRAY8Ptr status, struct sockaddr *addr, int willing)
339 {
340     HostName    *new, **names, *name;
341     ARRAY8      hostAddr;
342     CARD16      connectionType;
343     int         fulllen;
344     int         update = 0;
345
346     switch (addr->sa_family)
347     {
348     case AF_INET:
349         hostAddr.data = (CARD8 *) &((struct sockaddr_in *) addr)->sin_addr;
350         hostAddr.length = 4;
351         connectionType = FamilyInternet;
352         break;
353     default:
354         hostAddr.data = (CARD8 *) "";
355         hostAddr.length = 0;
356         connectionType = FamilyLocal;
357         break;
358     }
359     for (names = &hostNamedb; *names; names = & (*names)->next)
360     {
361         name = *names;
362         if (connectionType == name->connectionType &&
363             XdmcpARRAY8Equal (&hostAddr, &name->hostaddr))
364         {
365             if (XdmcpARRAY8Equal (status, &name->status))
366             {
367                 return 0;
368             }
369             update = 1;
370             break;
371         }
372     }
373     if (!*names)
374     {
375         new = (HostName *) malloc (sizeof (HostName));
376         if (!new)
377             return 0;
378         if (hostname->length)
379         {
380             switch (addr->sa_family)
381             {
382             case AF_INET:
383                 {
384                     struct hostent  *hostent;
385                     char            *host;
386         
387                     hostent = gethostbyaddr ((char *)hostAddr.data, hostAddr.length, AF_INET);
388                     if (hostent)
389                     {
390                         XdmcpDisposeARRAY8 (hostname);
391                         host = hostent->h_name;
392                         XdmcpAllocARRAY8 (hostname, strlen (host));
393                         memmove( hostname->data, host, hostname->length);
394                     }
395                 }
396             }
397         }
398         if (!XdmcpAllocARRAY8 (&new->hostaddr, hostAddr.length))
399         {
400             free ((char *) new->fullname);
401             free ((char *) new);
402             return 0;
403         }
404         memmove( new->hostaddr.data, hostAddr.data, hostAddr.length);
405         new->connectionType = connectionType;
406         new->hostname = *hostname;
407
408         *names = new;
409         new->next = 0;
410         NameTableSize++;
411     }
412     else
413     {
414         new = *names;
415         free (new->fullname);
416         XdmcpDisposeARRAY8 (&new->status);
417         XdmcpDisposeARRAY8 (hostname);
418     }
419     new->willing = willing;
420     new->status = *status;
421
422     hostname = &new->hostname;
423     fulllen = hostname->length;
424     if (fulllen < 30)
425         fulllen = 30;
426     new->fullname = malloc (fulllen + status->length + 10);
427     if (!new->fullname)
428     {
429         new->fullname = "Unknown";
430     }
431     else
432     {
433         sprintf (new->fullname, "%-30.*s %*.*s",
434                  hostname->length, hostname->data,
435                  status->length, status->length, status->data);
436     }
437     if (update)
438         RebuildTable (NameTableSize);
439     else
440         RebuildTableAdd (NameTableSize);
441     return 1;
442 }
443
444 static void
445 DisposeHostname (HostName *host)
446 {
447     XdmcpDisposeARRAY8 (&host->hostname);
448     XdmcpDisposeARRAY8 (&host->hostaddr);
449     XdmcpDisposeARRAY8 (&host->status);
450     free ((char *) host->fullname);
451     free ((char *) host);
452 }
453
454 static int
455 RemoveHostname (HostName *host)
456 {
457     HostName    **prev, *hosts;
458
459     prev = &hostNamedb;;
460     for (hosts = hostNamedb; hosts; hosts = hosts->next)
461     {
462         if (hosts == host)
463             break;
464         prev = &hosts->next;
465     }
466     if (!hosts)
467         return 0;
468     *prev = host->next;
469     DisposeHostname (host);
470     NameTableSize--;
471     RebuildTable (NameTableSize);
472
473     return 1;
474 }
475
476 static void
477 EmptyHostnames (void)
478 {
479     HostName    *hosts, *next;
480
481     for (hosts = hostNamedb; hosts; hosts = next)
482     {
483         next = hosts->next;
484         DisposeHostname (hosts);
485     }
486     NameTableSize = 0;
487     hostNamedb = 0;
488     RebuildTable (NameTableSize);
489 }
490
491 /* ARGSUSED */
492 static void
493 ReceivePacket (XtPointer closure, int *source, XtInputId *id)
494 {
495     XdmcpHeader     header;
496     ARRAY8          authenticationName;
497     ARRAY8          hostname;
498     ARRAY8          status;
499     int             saveHostname = 0;
500     struct sockaddr addr;
501     int             addrlen;
502
503     addrlen = sizeof (addr);
504     if (!XdmcpFill (socketFD, &buffer, &addr, &addrlen))
505         return;
506     if (!XdmcpReadHeader (&buffer, &header))
507         return;
508     if (header.version != XDM_PROTOCOL_VERSION)
509         return;
510     hostname.data = 0;
511     status.data = 0;
512     authenticationName.data = 0;
513     switch (header.opcode) {
514     case WILLING:
515         if (XdmcpReadARRAY8 (&buffer, &authenticationName) &&
516             XdmcpReadARRAY8 (&buffer, &hostname) &&
517             XdmcpReadARRAY8 (&buffer, &status))
518         {
519             if (header.length == 6 + authenticationName.length +
520                 hostname.length + status.length)
521             {
522                 if (AddHostname (&hostname, &status, &addr, header.opcode == (int) WILLING))
523                     saveHostname = 1;
524             }
525         }
526         XdmcpDisposeARRAY8 (&authenticationName);
527         break;
528     case UNWILLING:
529         if (XdmcpReadARRAY8 (&buffer, &hostname) &&
530             XdmcpReadARRAY8 (&buffer, &status))
531         {
532             if (header.length == 4 + hostname.length + status.length)
533             {
534                 if (AddHostname (&hostname, &status, &addr, header.opcode == (int) WILLING))
535                     saveHostname = 1;
536
537             }
538         }
539         break;
540     default:
541         break;
542     }
543     if (!saveHostname)
544     {
545         XdmcpDisposeARRAY8 (&hostname);
546         XdmcpDisposeARRAY8 (&status);
547     }
548 }
549
550 int
551 RegisterHostaddr (struct sockaddr *addr, int len, xdmOpCode type)
552 {
553     HostAddr            *host, **prev;
554
555     host = (HostAddr *) malloc (sizeof (HostAddr));
556     if (!host)
557         return 0;
558     host->addr = (struct sockaddr *) malloc (len);
559     if (!host->addr)
560     {
561         free ((char *) host);
562         return 0;
563     }
564     memmove( (char *) host->addr, (char *) addr, len);
565     host->addrlen = len;
566     host->type = type;
567     for (prev = &hostAddrdb; *prev; prev = &(*prev)->next)
568         ;
569     *prev = host;
570     host->next = NULL;
571     return 1;
572 }
573
574 /*
575  * Register the address for this host.
576  * Called with each of the names on the command line.
577  * The special name "BROADCAST" looks up all the broadcast
578  *  addresses on the local host.
579  */
580 int
581 RegisterHostname (char *name)
582 {
583     struct hostent      *hostent;
584     struct sockaddr_in  in_addr;
585     struct ifconf       ifc;
586     register struct ifreq *ifr;
587     struct sockaddr     broad_addr;
588     char                buf[2048];
589     int                 n;
590
591     if (!strcmp (name, BROADCAST_HOSTNAME))
592     {
593         ifc.ifc_len = sizeof (buf);
594         ifc.ifc_buf = buf;
595         if (ioctl (socketFD, (int) SIOCGIFCONF, (char *) &ifc) < 0)
596             return 0;
597         for (ifr = ifc.ifc_req
598 #if defined (__bsdi__) || defined(__NetBSD__)
599              ; (char *)ifr < ifc.ifc_buf + ifc.ifc_len;
600              ifr = (struct ifreq *)((char *)ifr + sizeof (struct ifreq) +
601                 (ifr->ifr_addr.sa_len > sizeof (ifr->ifr_addr) ?
602                  ifr->ifr_addr.sa_len - sizeof (ifr->ifr_addr) : 0))
603 #else
604              , n = ifc.ifc_len / sizeof (struct ifreq); --n >= 0; ifr++
605 #endif
606              )
607         {
608             if (ifr->ifr_addr.sa_family != AF_INET)
609                 continue;
610
611             broad_addr = ifr->ifr_addr;
612             ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
613                 htonl (INADDR_BROADCAST);
614 #ifdef SIOCGIFBRDADDR
615             {
616                 struct ifreq    broad_req;
617     
618                 broad_req = *ifr;
619                 if (ioctl (socketFD, SIOCGIFFLAGS, (char *) &broad_req) != -1 &&
620                     (broad_req.ifr_flags & IFF_BROADCAST) &&
621                     (broad_req.ifr_flags & IFF_UP)
622                     )
623                 {
624                     broad_req = *ifr;
625                     if (ioctl (socketFD, SIOCGIFBRDADDR, &broad_req) != -1)
626                         broad_addr = broad_req.ifr_addr;
627                     else
628                         continue;
629                 }
630                 else
631                     continue;
632             }
633 #endif
634             in_addr = *((struct sockaddr_in *) &broad_addr);
635             in_addr.sin_port = htons (XDM_UDP_PORT);
636 #ifdef BSD44SOCKETS
637             in_addr.sin_len = sizeof(in_addr);
638 #endif
639             RegisterHostaddr ((struct sockaddr *)&in_addr, sizeof (in_addr),
640                               BROADCAST_QUERY);
641         }
642     }
643     else
644     {
645
646         /* address as hex string, e.g., "12180022" (depreciated) */
647         if (strlen(name) == 8 &&
648             FromHex(name, (char *)&in_addr.sin_addr, strlen(name)) == 0)
649         {
650             in_addr.sin_family = AF_INET;
651         }
652         /* Per RFC 1123, check first for IP address in dotted-decimal form */
653         else if ((in_addr.sin_addr.s_addr = inet_addr(name)) != -1)
654             in_addr.sin_family = AF_INET;
655         else
656         {
657             hostent = gethostbyname (name);
658             if (!hostent)
659                 return 0;
660             if (hostent->h_addrtype != AF_INET || hostent->h_length != 4)
661                 return 0;
662             in_addr.sin_family = hostent->h_addrtype;
663             memmove( &in_addr.sin_addr, hostent->h_addr, 4);
664         }
665         in_addr.sin_port = htons (XDM_UDP_PORT);
666 #ifdef BSD44SOCKETS
667         in_addr.sin_len = sizeof(in_addr);
668 #endif
669         RegisterHostaddr ((struct sockaddr *)&in_addr, sizeof (in_addr),
670                           QUERY);
671     }
672     return 1;
673 }
674
675 static ARRAYofARRAY8    AuthenticationNames;
676
677 static int
678 RegisterAuthenticationName (char *name, int namelen)
679 {
680     ARRAY8Ptr   authName;
681     if (!XdmcpReallocARRAYofARRAY8 (&AuthenticationNames,
682                                     AuthenticationNames.length + 1))
683         return 0;
684     authName = &AuthenticationNames.data[AuthenticationNames.length-1];
685     if (!XdmcpAllocARRAY8 (authName, namelen))
686         return 0;
687     memmove( authName->data, name, namelen);
688
689     return 1;
690 }
691
692 int
693 InitXDMCP (char **argv)
694 {
695     int soopts = 1;
696     XdmcpHeader header;
697     int i;
698     int optlen;
699
700     header.version = XDM_PROTOCOL_VERSION;
701     header.opcode = (CARD16) BROADCAST_QUERY;
702     header.length = 1;
703     for (i = 0; i < (int)AuthenticationNames.length; i++)
704         header.length += 2 + AuthenticationNames.data[i].length;
705     XdmcpWriteHeader (&broadcastBuffer, &header);
706     XdmcpWriteARRAYofARRAY8 (&broadcastBuffer, &AuthenticationNames);
707
708     header.version = XDM_PROTOCOL_VERSION;
709     header.opcode = (CARD16) QUERY;
710     header.length = 1;
711     for (i = 0; i < (int)AuthenticationNames.length; i++)
712         header.length += 2 + AuthenticationNames.data[i].length;
713     XdmcpWriteHeader (&directBuffer, &header);
714     XdmcpWriteARRAYofARRAY8 (&directBuffer, &AuthenticationNames);
715     if ((socketFD = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
716         return 0;
717 #ifdef SO_BROADCAST
718     soopts = 1;
719     if (setsockopt (socketFD, SOL_SOCKET, SO_BROADCAST, (char *)&soopts, sizeof (soopts)) < 0)
720         perror ("setsockopt");
721 #endif
722     
723     XtAddInput (socketFD, (XtPointer) XtInputReadMask, ReceivePacket,
724                 (XtPointer) 0);
725     while (*argv)
726     {
727         RegisterHostname (*argv);
728         ++argv;
729     }
730     pingTry = 0;
731     PingHosts ((XtPointer)NULL, (XtIntervalId *)NULL);
732     return 1;
733 }
734
735 void
736 Choose (HostName *h)
737 {
738     if (app_resources.xdmAddress)
739     {
740         struct sockaddr_in  in_addr;
741         struct sockaddr *addr;
742         int             family;
743         int             len;
744         int             fd;
745         char            buf[1024];
746         XdmcpBuffer     buffer;
747         char            *xdm;
748
749         xdm = (char *) app_resources.xdmAddress->data;
750         family = (xdm[0] << 8) + xdm[1];
751         switch (family) {
752         case AF_INET:
753 #ifdef BSD44SOCKETS
754             in_addr.sin_len = sizeof(in_addr);
755 #endif
756             in_addr.sin_family = family;
757             memmove( &in_addr.sin_port, xdm + 2, 2);
758             memmove( &in_addr.sin_addr, xdm + 4, 4);
759             addr = (struct sockaddr *) &in_addr;
760             len = sizeof (in_addr);
761             break;
762         }
763         if ((fd = socket (family, SOCK_STREAM, 0)) == -1)
764         {
765             fprintf (stderr, "Cannot create response socket\n");
766             exit (REMANAGE_DISPLAY);
767         }
768         if (connect (fd, addr, len) == -1)
769         {
770             fprintf (stderr, "Cannot connect to xdm\n");
771             exit (REMANAGE_DISPLAY);
772         }
773         buffer.data = (BYTE *) buf;
774         buffer.size = sizeof (buf);
775         buffer.pointer = 0;
776         buffer.count = 0;
777         XdmcpWriteARRAY8 (&buffer, app_resources.clientAddress);
778         XdmcpWriteCARD16 (&buffer, (CARD16) app_resources.connectionType);
779         XdmcpWriteARRAY8 (&buffer, &h->hostaddr);
780         if(-1 == write (fd, (char *)buffer.data, buffer.pointer)) {
781             perror(strerror(errno));
782         }
783         close (fd);
784     }
785     else
786     {
787         int i;
788
789         printf ("%u\n", h->connectionType);
790         for (i = 0; i < (int)h->hostaddr.length; i++)
791             printf ("%u%s", h->hostaddr.data[i],
792                     i == h->hostaddr.length - 1 ? "\n" : " ");
793     }
794 }
795
796 /* ARGSUSED */
797 void
798 DoAccept (Widget w, XEvent *event, String *params, Cardinal *num_params)
799 {
800     HostName            *h;
801     XmStringTable       selectedItem;
802     int                 selectedCount;
803     int                 i;
804     char                *text;
805
806     /*********************************/
807     /** see if anything is selected **/
808     /*********************************/
809     i = 0;
810     XtSetArg(chooserArgs[i], XmNselectedItemCount, &selectedCount); i++;
811     XtGetValues(chooser_list, chooserArgs, i);
812     if (selectedCount != 1) {
813         XBell (XtDisplay (toplevel), 0);
814         return;
815     }
816
817     /**********************************************/
818     /** retrieve the selected item from the list **/
819     /**********************************************/
820     i = 0;
821     XtSetArg(chooserArgs[i], XmNselectedItems, &selectedItem); i++;
822     XtGetValues(chooser_list, chooserArgs, i);
823     text = (char*) _XmStringUngenerate(
824                         selectedItem[0], NULL,
825                         XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT);
826     if (NULL == text) return;
827     
828     for (h = hostNamedb; h; h = h->next)
829         if (!strcmp (text, h->fullname))
830         {
831             Choose (h);
832         }
833     if (NULL != text) XtFree(text);
834     exit (OBEYSESS_DISPLAY);
835 }
836
837 /* ARGSUSED */
838 static void
839 DoCheckWilling (Widget w, XEvent *event, String *params, Cardinal *num_params)
840 {
841     HostName            *h;
842     XmStringTable       selectedItem;
843     int                 selectedCount;
844     int                 i;
845     char                *text;
846
847     /*********************************/
848     /** see if anything is selected **/
849     /*********************************/
850     i = 0;
851     XtSetArg(chooserArgs[i], XmNselectedItemCount, &selectedCount); i++;
852     XtGetValues(chooser_list, chooserArgs, i);
853     if (selectedCount != 1) {
854         return;
855     }
856
857     /**********************************************/
858     /** retrieve the selected item from the list **/
859     /**********************************************/
860     i = 0;
861     XtSetArg(chooserArgs[i], XmNselectedItems, &selectedItem); i++;
862     XtGetValues(chooser_list, chooserArgs, i);
863     text = (char*) _XmStringUngenerate(
864                         selectedItem[0], NULL,
865                         XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT);
866     if (NULL == text) return;
867     
868     for (h = hostNamedb; h; h = h->next)
869         if (!strcmp (text, h->fullname))
870             if (!h->willing)
871                 XmListDeselectAllItems (chooser_list);
872
873     if (NULL != text) XtFree(text);
874 }
875
876 /* ARGSUSED */
877 void
878 DoCancel (Widget w, XEvent *event, String *params, Cardinal *num_params)
879 {
880     exit (OBEYSESS_DISPLAY);
881 }
882
883 /* ARGSUSED */
884 void
885 DoPing (Widget w, XEvent *event, String *params, Cardinal *num_params)
886 {
887     EmptyHostnames ();
888     pingTry = 0;
889     PingHosts ((XtPointer)NULL, (XtIntervalId *)NULL);
890 }
891
892 static XtActionsRec app_actions[] = {
893     "Accept",       DoAccept,
894     "Cancel",       DoCancel,
895     "CheckWilling", DoCheckWilling,
896     "Ping",         DoPing,
897 };
898
899 int
900 main (int argc, char **argv)
901 {
902     Arg         position[3];
903     Dimension   width, height;
904     Position    x, y;
905     int         i;
906     char        *xsetup;
907
908     /******************************/
909     /** set the locale, and      **/
910     /** open the message catalog **/
911     /******************************/
912
913     setlocale(LC_ALL, "");
914     XtSetLanguageProc( NULL, NULL, NULL );
915     langenv = getenv("LANG");
916
917     /******************************************/
918     /** set the font paths                   **/
919     /******************************************/
920     if ( (xsetup = getenv("XSETUP")) != NULL)
921       if(system(xsetup) == -1)
922             fprintf (stderr, "dtchooser: Cannot source %s\n",xsetup);
923
924     /******************************************/
925     /** save argc and argv for RespondLangCB **/
926     /******************************************/
927     amChooser = 1;  /** tell RespondLangCB we are a chooser **/
928     orig_argc = argc;
929     orig_argv = (char **)malloc(sizeof(char *) * (orig_argc+1));
930     for (i = 0; i < orig_argc; i++) {
931         orig_argv[i] = argv[i];
932     }
933     orig_argv[orig_argc] = NULL;
934
935     toplevel = XtInitialize (argv[0], "Dtlogin", options, XtNumber(options),
936                              &argc, argv);
937
938     XtVaSetValues(XmGetXmDisplay(XtDisplay(toplevel)),
939                 XmNdragInitiatorProtocolStyle, XmDRAG_NONE,
940                 NULL);
941
942     XtAddConverter(XtRString, XtRARRAY8, CvtStringToARRAY8, NULL, 0);
943
944     XtGetApplicationResources (toplevel, (XtPointer) &app_resources, resources,
945                                XtNumber (resources), NULL, (Cardinal) 0);
946
947     dpyinfo.dpy         = XtDisplay(toplevel);
948 /*    dpyinfo.name      = "";*/
949     dpyinfo.screen      = DefaultScreen(dpyinfo.dpy);
950     dpyinfo.root        = RootWindow   (dpyinfo.dpy, dpyinfo.screen);
951     dpyinfo.depth       = DefaultDepth (dpyinfo.dpy, dpyinfo.screen);
952     dpyinfo.width       = DisplayWidth (dpyinfo.dpy, dpyinfo.screen);
953     dpyinfo.height      = DisplayHeight(dpyinfo.dpy, dpyinfo.screen);
954     dpyinfo.black_pixel = BlackPixel   (dpyinfo.dpy, dpyinfo.screen);
955     dpyinfo.visual      = DefaultVisual(dpyinfo.dpy, dpyinfo.screen);
956
957     /*
958      *  build widgets...
959      */
960
961     MakeBackground();           /* login_shell, table, matte              */
962     MakeLogo();                 /* logo, logo_pixmap, logo_shadow         */
963     MakeButtons();              /* Push Buttons                           */
964     MakeChooser();              /* Chooser List ...                       */
965
966     if (appInfo.optionsDelay == 0 )
967         MakeOptionsMenu();      /* make option_button pop-up menu         */
968     else
969         XtAddTimeOut((unsigned long) appInfo.optionsDelay * 1000, MakeOptionsProc, NULL);
970
971 #if 0
972     /*
973      * center ourselves on the screen
974      */
975     XtSetMappedWhenManaged(toplevel, FALSE);
976     XtRealizeWidget (toplevel);
977 #endif
978     XtRealizeWidget (login_shell);
979 XtPopup(login_shell, XtGrabNone);
980 #if 0
981     XtSetArg (position[0], XtNwidth, &width);
982     XtSetArg (position[1], XtNheight, &height);
983     XtGetValues (login_shell, position, (Cardinal) 2);
984     x = (Position)(WidthOfScreen (XtScreen (toplevel)) - width) / 2;
985     y = (Position)(HeightOfScreen (XtScreen (toplevel)) - height) / 3;
986     XtSetArg (position[0], XtNx, x);
987     XtSetArg (position[1], XtNy, y);
988     XtSetValues (login_shell, position, (Cardinal) 2);
989 #endif
990
991     /*
992      * Run
993      */
994 #if 0
995     XtMapWidget(toplevel);
996 #endif
997     InitXDMCP (argv + 1);
998     XtMainLoop ();
999
1000     return 0;
1001 }
1002
1003 /* Converts the hex string s of length len into the byte array d.
1004    Returns 0 if s was a legal hex string, 1 otherwise.
1005    */
1006 static int
1007 FromHex (char *s, char *d, int len)
1008 {
1009     int t;
1010     int ret = len&1;            /* odd-length hex strings are illegal */
1011     while (len >= 2)
1012     {
1013 #define HexChar(c)  ('0' <= (c) && (c) <= '9' ? (c) - '0' : (c) - 'a' + 10)
1014
1015         if (!ishexdigit(*s))
1016             ret = 1;
1017         t = HexChar (*s) << 4;
1018         s++;
1019         if (!ishexdigit(*s))
1020             ret = 1;
1021         t += HexChar (*s);
1022         s++;
1023         *d++ = t;
1024         len -= 2;
1025     }
1026     return ret;
1027 }
1028
1029 /*ARGSUSED*/
1030 static void
1031 CvtStringToARRAY8 (XrmValuePtr args, Cardinal *num_args, XrmValuePtr fromVal, XrmValuePtr toVal)
1032 {
1033     static ARRAY8Ptr    dest;
1034     char        *s;
1035     int         len;
1036
1037     dest = (ARRAY8Ptr) XtMalloc (sizeof (ARRAY8));
1038     len = fromVal->size;
1039     s = (char *) fromVal->addr;
1040     if (!XdmcpAllocARRAY8 (dest, len >> 1))
1041         XtStringConversionWarning ((char *) fromVal->addr, XtRARRAY8);
1042     else
1043     {
1044         FromHex (s, (char *) dest->data, len);
1045     }
1046     toVal->addr = (caddr_t) &dest;
1047     toVal->size = sizeof (ARRAY8Ptr);
1048 }