Adapt dtlogin/config/_common.ksh.src for OpenBSD:
[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 #define offset(field) XtOffsetOf(struct _app_resources, field)
164
165 #define XtRARRAY8   "ARRAY8"
166
167 static XtResource  resources[] = {
168     {"xdmAddress",      "XdmAddress",  XtRARRAY8,       sizeof (ARRAY8Ptr),
169         offset (xdmAddress),        XtRString,  NULL },
170     {"clientAddress",   "ClientAddress",  XtRARRAY8,    sizeof (ARRAY8Ptr),
171         offset (clientAddress),     XtRString,  NULL },
172     {"connectionType",  "ConnectionType",   XtRInt,     sizeof (int),
173         offset (connectionType),    XtRImmediate,       (XtPointer) 0 }
174 };
175 #undef offset
176
177 static XrmOptionDescRec options[] = {
178     "-xdmaddress",      "*xdmAddress",      XrmoptionSepArg,    NULL,
179     "-clientaddress",   "*clientAddress",   XrmoptionSepArg,    NULL,
180     "-connectionType",  "*connectionType",  XrmoptionSepArg,    NULL,
181 };
182
183 typedef struct _hostAddr {
184     struct _hostAddr    *next;
185     struct sockaddr     *addr;
186     int                 addrlen;
187     xdmOpCode           type;
188 } HostAddr;
189
190 static HostAddr    *hostAddrdb;
191
192 typedef struct _hostName {
193     struct _hostName    *next;
194     char                *fullname;
195     int                 willing;
196     ARRAY8              hostname, status;
197     CARD16              connectionType;
198     ARRAY8              hostaddr;
199 } HostName;
200
201 static HostName    *hostNamedb;
202
203 static int  socketFD;
204
205 static int  pingTry;
206
207 #define PING_INTERVAL   2000
208 #define TRIES           3
209
210 static XdmcpBuffer      directBuffer, broadcastBuffer;
211 static XdmcpBuffer      buffer;
212
213
214 /* ARGSUSED */
215 static void
216 PingHosts (closure, id)
217     XtPointer closure;
218     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 static int
237 HostnameCompare (a, b)
238 #if defined(__STDC__)
239     const void *a, *b;
240 #else
241     char *a, *b;
242 #endif
243 {
244     return strcmp (*(char **)a, *(char **)b);
245 }
246
247 static void
248 RebuildTable (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 (size)
300         int size;
301 {
302     char        **newTable = 0;
303     HostName    *names;
304     int         i;
305     XmString    tempString;
306     int         position;
307
308     if (size)
309     {
310         newTable = (char **) malloc (size * sizeof (char *));
311         if (!newTable)
312             return;
313         for (names = hostNamedb, i = 0; names; names = names->next, i++)
314             newTable[i] = names->fullname;
315         qsort (newTable, size, sizeof (char *), HostnameCompare);
316     }
317
318     for (i = 0; i < size; i++) {
319         tempString = XmStringCreateLocalized(newTable[i]);
320         if ((position = XmListItemPos(chooser_list, tempString)) == 0) {
321             /****************************/
322             /** need to add a new host **/
323             /****************************/
324             XmListAddItemUnselected(chooser_list, tempString, (i+1));
325             XmStringFree(tempString);
326             break;
327         }
328         XmStringFree(tempString);
329     }
330
331     if (NameTable)
332         free ((char *) NameTable);
333     NameTable = newTable;
334     NameTableSize = size;
335 }
336
337
338 static int
339 AddHostname (hostname, status, addr, willing)
340     ARRAY8Ptr       hostname, status;
341     struct sockaddr *addr;
342     int             willing;
343 {
344     HostName    *new, **names, *name;
345     ARRAY8      hostAddr;
346     CARD16      connectionType;
347     int         fulllen;
348     int         update = 0;
349
350     switch (addr->sa_family)
351     {
352     case AF_INET:
353         hostAddr.data = (CARD8 *) &((struct sockaddr_in *) addr)->sin_addr;
354         hostAddr.length = 4;
355         connectionType = FamilyInternet;
356         break;
357     default:
358         hostAddr.data = (CARD8 *) "";
359         hostAddr.length = 0;
360         connectionType = FamilyLocal;
361         break;
362     }
363     for (names = &hostNamedb; *names; names = & (*names)->next)
364     {
365         name = *names;
366         if (connectionType == name->connectionType &&
367             XdmcpARRAY8Equal (&hostAddr, &name->hostaddr))
368         {
369             if (XdmcpARRAY8Equal (status, &name->status))
370             {
371                 return 0;
372             }
373             update = 1;
374             break;
375         }
376     }
377     if (!*names)
378     {
379         new = (HostName *) malloc (sizeof (HostName));
380         if (!new)
381             return 0;
382         if (hostname->length)
383         {
384             switch (addr->sa_family)
385             {
386             case AF_INET:
387                 {
388                     struct hostent  *hostent;
389                     char            *host;
390         
391                     hostent = gethostbyaddr ((char *)hostAddr.data, hostAddr.length, AF_INET);
392                     if (hostent)
393                     {
394                         XdmcpDisposeARRAY8 (hostname);
395                         host = hostent->h_name;
396                         XdmcpAllocARRAY8 (hostname, strlen (host));
397                         memmove( hostname->data, host, hostname->length);
398                     }
399                 }
400             }
401         }
402         if (!XdmcpAllocARRAY8 (&new->hostaddr, hostAddr.length))
403         {
404             free ((char *) new->fullname);
405             free ((char *) new);
406             return 0;
407         }
408         memmove( new->hostaddr.data, hostAddr.data, hostAddr.length);
409         new->connectionType = connectionType;
410         new->hostname = *hostname;
411
412         *names = new;
413         new->next = 0;
414         NameTableSize++;
415     }
416     else
417     {
418         new = *names;
419         free (new->fullname);
420         XdmcpDisposeARRAY8 (&new->status);
421         XdmcpDisposeARRAY8 (hostname);
422     }
423     new->willing = willing;
424     new->status = *status;
425
426     hostname = &new->hostname;
427     fulllen = hostname->length;
428     if (fulllen < 30)
429         fulllen = 30;
430     new->fullname = malloc (fulllen + status->length + 10);
431     if (!new->fullname)
432     {
433         new->fullname = "Unknown";
434     }
435     else
436     {
437         sprintf (new->fullname, "%-30.*s %*.*s",
438                  hostname->length, hostname->data,
439                  status->length, status->length, status->data);
440     }
441     if (update)
442         RebuildTable (NameTableSize);
443     else
444         RebuildTableAdd (NameTableSize);
445     return 1;
446 }
447
448 static
449 DisposeHostname (host)
450     HostName    *host;
451 {
452     XdmcpDisposeARRAY8 (&host->hostname);
453     XdmcpDisposeARRAY8 (&host->hostaddr);
454     XdmcpDisposeARRAY8 (&host->status);
455     free ((char *) host->fullname);
456     free ((char *) host);
457 }
458
459 static
460 RemoveHostname (host)
461     HostName    *host;
462 {
463     HostName    **prev, *hosts;
464
465     prev = &hostNamedb;;
466     for (hosts = hostNamedb; hosts; hosts = hosts->next)
467     {
468         if (hosts == host)
469             break;
470         prev = &hosts->next;
471     }
472     if (!hosts)
473         return;
474     *prev = host->next;
475     DisposeHostname (host);
476     NameTableSize--;
477     RebuildTable (NameTableSize);
478 }
479
480 static
481 EmptyHostnames ()
482 {
483     HostName    *hosts, *next;
484
485     for (hosts = hostNamedb; hosts; hosts = next)
486     {
487         next = hosts->next;
488         DisposeHostname (hosts);
489     }
490     NameTableSize = 0;
491     hostNamedb = 0;
492     RebuildTable (NameTableSize);
493 }
494
495 /* ARGSUSED */
496 static void
497 ReceivePacket (closure, source, id)
498     XtPointer   closure;
499     int         *source;
500     XtInputId   *id;
501 {
502     XdmcpHeader     header;
503     ARRAY8          authenticationName;
504     ARRAY8          hostname;
505     ARRAY8          status;
506     int             saveHostname = 0;
507     struct sockaddr addr;
508     int             addrlen;
509
510     addrlen = sizeof (addr);
511     if (!XdmcpFill (socketFD, &buffer, &addr, &addrlen))
512         return;
513     if (!XdmcpReadHeader (&buffer, &header))
514         return;
515     if (header.version != XDM_PROTOCOL_VERSION)
516         return;
517     hostname.data = 0;
518     status.data = 0;
519     authenticationName.data = 0;
520     switch (header.opcode) {
521     case WILLING:
522         if (XdmcpReadARRAY8 (&buffer, &authenticationName) &&
523             XdmcpReadARRAY8 (&buffer, &hostname) &&
524             XdmcpReadARRAY8 (&buffer, &status))
525         {
526             if (header.length == 6 + authenticationName.length +
527                 hostname.length + status.length)
528             {
529                 if (AddHostname (&hostname, &status, &addr, header.opcode == (int) WILLING))
530                     saveHostname = 1;
531             }
532         }
533         XdmcpDisposeARRAY8 (&authenticationName);
534         break;
535     case UNWILLING:
536         if (XdmcpReadARRAY8 (&buffer, &hostname) &&
537             XdmcpReadARRAY8 (&buffer, &status))
538         {
539             if (header.length == 4 + hostname.length + status.length)
540             {
541                 if (AddHostname (&hostname, &status, &addr, header.opcode == (int) WILLING))
542                     saveHostname = 1;
543
544             }
545         }
546         break;
547     default:
548         break;
549     }
550     if (!saveHostname)
551     {
552         XdmcpDisposeARRAY8 (&hostname);
553         XdmcpDisposeARRAY8 (&status);
554     }
555 }
556
557 RegisterHostaddr (addr, len, type)
558     struct sockaddr *addr;
559     int             len;
560     xdmOpCode       type;
561 {
562     HostAddr            *host, **prev;
563
564     host = (HostAddr *) malloc (sizeof (HostAddr));
565     if (!host)
566         return;
567     host->addr = (struct sockaddr *) malloc (len);
568     if (!host->addr)
569     {
570         free ((char *) host);
571         return;
572     }
573     memmove( (char *) host->addr, (char *) addr, len);
574     host->addrlen = len;
575     host->type = type;
576     for (prev = &hostAddrdb; *prev; prev = &(*prev)->next)
577         ;
578     *prev = host;
579     host->next = NULL;
580 }
581
582 /*
583  * Register the address for this host.
584  * Called with each of the names on the command line.
585  * The special name "BROADCAST" looks up all the broadcast
586  *  addresses on the local host.
587  */
588
589 RegisterHostname (name)
590     char    *name;
591 {
592     struct hostent      *hostent;
593     struct sockaddr_in  in_addr;
594     struct ifconf       ifc;
595     register struct ifreq *ifr;
596     struct sockaddr     broad_addr;
597     char                buf[2048];
598     int                 n;
599
600     if (!strcmp (name, BROADCAST_HOSTNAME))
601     {
602         ifc.ifc_len = sizeof (buf);
603         ifc.ifc_buf = buf;
604         if (ioctl (socketFD, (int) SIOCGIFCONF, (char *) &ifc) < 0)
605             return;
606         for (ifr = ifc.ifc_req
607 #if defined (__bsdi__) || defined(__NetBSD__)
608              ; (char *)ifr < ifc.ifc_buf + ifc.ifc_len;
609              ifr = (struct ifreq *)((char *)ifr + sizeof (struct ifreq) +
610                 (ifr->ifr_addr.sa_len > sizeof (ifr->ifr_addr) ?
611                  ifr->ifr_addr.sa_len - sizeof (ifr->ifr_addr) : 0))
612 #else
613              , n = ifc.ifc_len / sizeof (struct ifreq); --n >= 0; ifr++
614 #endif
615              )
616         {
617             if (ifr->ifr_addr.sa_family != AF_INET)
618                 continue;
619
620             broad_addr = ifr->ifr_addr;
621             ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
622                 htonl (INADDR_BROADCAST);
623 #ifdef SIOCGIFBRDADDR
624             {
625                 struct ifreq    broad_req;
626     
627                 broad_req = *ifr;
628                 if (ioctl (socketFD, SIOCGIFFLAGS, (char *) &broad_req) != -1 &&
629                     (broad_req.ifr_flags & IFF_BROADCAST) &&
630                     (broad_req.ifr_flags & IFF_UP)
631                     )
632                 {
633                     broad_req = *ifr;
634                     if (ioctl (socketFD, SIOCGIFBRDADDR, &broad_req) != -1)
635                         broad_addr = broad_req.ifr_addr;
636                     else
637                         continue;
638                 }
639                 else
640                     continue;
641             }
642 #endif
643             in_addr = *((struct sockaddr_in *) &broad_addr);
644             in_addr.sin_port = htons (XDM_UDP_PORT);
645 #ifdef BSD44SOCKETS
646             in_addr.sin_len = sizeof(in_addr);
647 #endif
648             RegisterHostaddr ((struct sockaddr *)&in_addr, sizeof (in_addr),
649                               BROADCAST_QUERY);
650         }
651     }
652     else
653     {
654
655         /* address as hex string, e.g., "12180022" (depreciated) */
656         if (strlen(name) == 8 &&
657             FromHex(name, (char *)&in_addr.sin_addr, strlen(name)) == 0)
658         {
659             in_addr.sin_family = AF_INET;
660         }
661         /* Per RFC 1123, check first for IP address in dotted-decimal form */
662         else if ((in_addr.sin_addr.s_addr = inet_addr(name)) != -1)
663             in_addr.sin_family = AF_INET;
664         else
665         {
666             hostent = gethostbyname (name);
667             if (!hostent)
668                 return;
669             if (hostent->h_addrtype != AF_INET || hostent->h_length != 4)
670                 return;
671             in_addr.sin_family = hostent->h_addrtype;
672             memmove( &in_addr.sin_addr, hostent->h_addr, 4);
673         }
674         in_addr.sin_port = htons (XDM_UDP_PORT);
675 #ifdef BSD44SOCKETS
676         in_addr.sin_len = sizeof(in_addr);
677 #endif
678         RegisterHostaddr ((struct sockaddr *)&in_addr, sizeof (in_addr),
679                           QUERY);
680     }
681 }
682
683 static ARRAYofARRAY8    AuthenticationNames;
684
685 RegisterAuthenticationName (name, namelen)
686     char    *name;
687     int     namelen;
688 {
689     ARRAY8Ptr   authName;
690     if (!XdmcpReallocARRAYofARRAY8 (&AuthenticationNames,
691                                     AuthenticationNames.length + 1))
692         return;
693     authName = &AuthenticationNames.data[AuthenticationNames.length-1];
694     if (!XdmcpAllocARRAY8 (authName, namelen))
695         return;
696     memmove( authName->data, name, namelen);
697 }
698
699 InitXDMCP (argv)
700     char    **argv;
701 {
702     int soopts = 1;
703     XdmcpHeader header;
704     int i;
705     int optlen;
706
707     header.version = XDM_PROTOCOL_VERSION;
708     header.opcode = (CARD16) BROADCAST_QUERY;
709     header.length = 1;
710     for (i = 0; i < (int)AuthenticationNames.length; i++)
711         header.length += 2 + AuthenticationNames.data[i].length;
712     XdmcpWriteHeader (&broadcastBuffer, &header);
713     XdmcpWriteARRAYofARRAY8 (&broadcastBuffer, &AuthenticationNames);
714
715     header.version = XDM_PROTOCOL_VERSION;
716     header.opcode = (CARD16) QUERY;
717     header.length = 1;
718     for (i = 0; i < (int)AuthenticationNames.length; i++)
719         header.length += 2 + AuthenticationNames.data[i].length;
720     XdmcpWriteHeader (&directBuffer, &header);
721     XdmcpWriteARRAYofARRAY8 (&directBuffer, &AuthenticationNames);
722     if ((socketFD = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
723         return 0;
724 #ifdef SO_BROADCAST
725     soopts = 1;
726     if (setsockopt (socketFD, SOL_SOCKET, SO_BROADCAST, (char *)&soopts, sizeof (soopts)) < 0)
727         perror ("setsockopt");
728 #endif
729     
730     XtAddInput (socketFD, (XtPointer) XtInputReadMask, ReceivePacket,
731                 (XtPointer) 0);
732     while (*argv)
733     {
734         RegisterHostname (*argv);
735         ++argv;
736     }
737     pingTry = 0;
738     PingHosts ((XtPointer)NULL, (XtIntervalId *)NULL);
739     return 1;
740 }
741
742 void
743 Choose (h)
744     HostName    *h;
745 {
746     if (app_resources.xdmAddress)
747     {
748         struct sockaddr_in  in_addr;
749         struct sockaddr *addr;
750         int             family;
751         int             len;
752         int             fd;
753         char            buf[1024];
754         XdmcpBuffer     buffer;
755         char            *xdm;
756
757         xdm = (char *) app_resources.xdmAddress->data;
758         family = (xdm[0] << 8) + xdm[1];
759         switch (family) {
760         case AF_INET:
761 #ifdef BSD44SOCKETS
762             in_addr.sin_len = sizeof(in_addr);
763 #endif
764             in_addr.sin_family = family;
765             memmove( &in_addr.sin_port, xdm + 2, 2);
766             memmove( &in_addr.sin_addr, xdm + 4, 4);
767             addr = (struct sockaddr *) &in_addr;
768             len = sizeof (in_addr);
769             break;
770         }
771         if ((fd = socket (family, SOCK_STREAM, 0)) == -1)
772         {
773             fprintf (stderr, "Cannot create response socket\n");
774             exit (REMANAGE_DISPLAY);
775         }
776         if (connect (fd, addr, len) == -1)
777         {
778             fprintf (stderr, "Cannot connect to xdm\n");
779             exit (REMANAGE_DISPLAY);
780         }
781         buffer.data = (BYTE *) buf;
782         buffer.size = sizeof (buf);
783         buffer.pointer = 0;
784         buffer.count = 0;
785         XdmcpWriteARRAY8 (&buffer, app_resources.clientAddress);
786         XdmcpWriteCARD16 (&buffer, (CARD16) app_resources.connectionType);
787         XdmcpWriteARRAY8 (&buffer, &h->hostaddr);
788         write (fd, (char *)buffer.data, buffer.pointer);
789         close (fd);
790     }
791     else
792     {
793         int i;
794
795         printf ("%u\n", h->connectionType);
796         for (i = 0; i < (int)h->hostaddr.length; i++)
797             printf ("%u%s", h->hostaddr.data[i],
798                     i == h->hostaddr.length - 1 ? "\n" : " ");
799     }
800 }
801
802 /* ARGSUSED */
803 void
804 DoAccept (w, event, params, num_params)
805     Widget w;
806     XEvent *event;
807     String *params;
808     Cardinal *num_params;
809 {
810     HostName            *h;
811     XmStringTable       selectedItem;
812     int                 selectedCount;
813     int                 i;
814     char                *text;
815
816     /*********************************/
817     /** see if anything is selected **/
818     /*********************************/
819     i = 0;
820     XtSetArg(chooserArgs[i], XmNselectedItemCount, &selectedCount); i++;
821     XtGetValues(chooser_list, chooserArgs, i);
822     if (selectedCount != 1) {
823         XBell (XtDisplay (toplevel), 0);
824         return;
825     }
826
827     /**********************************************/
828     /** retrieve the selected item from the list **/
829     /**********************************************/
830     i = 0;
831     XtSetArg(chooserArgs[i], XmNselectedItems, &selectedItem); i++;
832     XtGetValues(chooser_list, chooserArgs, i);
833     text = (char*) _XmStringUngenerate(
834                         selectedItem[0], NULL,
835                         XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT);
836     if (NULL == text) return;
837     
838     for (h = hostNamedb; h; h = h->next)
839         if (!strcmp (text, h->fullname))
840         {
841             Choose (h);
842         }
843     if (NULL != text) XtFree(text);
844     exit (OBEYSESS_DISPLAY);
845 }
846
847 /* ARGSUSED */
848 static void
849 DoCheckWilling (w, event, params, num_params)
850     Widget w;
851     XEvent *event;
852     String *params;
853     Cardinal *num_params;
854 {
855     HostName            *h;
856     XmStringTable       selectedItem;
857     int                 selectedCount;
858     int                 i;
859     char                *text;
860
861     /*********************************/
862     /** see if anything is selected **/
863     /*********************************/
864     i = 0;
865     XtSetArg(chooserArgs[i], XmNselectedItemCount, &selectedCount); i++;
866     XtGetValues(chooser_list, chooserArgs, i);
867     if (selectedCount != 1) {
868         return;
869     }
870
871     /**********************************************/
872     /** retrieve the selected item from the list **/
873     /**********************************************/
874     i = 0;
875     XtSetArg(chooserArgs[i], XmNselectedItems, &selectedItem); i++;
876     XtGetValues(chooser_list, chooserArgs, i);
877     text = (char*) _XmStringUngenerate(
878                         selectedItem[0], NULL,
879                         XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT);
880     if (NULL == text) return;
881     
882     for (h = hostNamedb; h; h = h->next)
883         if (!strcmp (text, h->fullname))
884             if (!h->willing)
885                 XmListDeselectAllItems (chooser_list);
886
887     if (NULL != text) XtFree(text);
888 }
889
890 /* ARGSUSED */
891 void
892 DoCancel (w, event, params, num_params)
893     Widget w;
894     XEvent *event;
895     String *params;
896     Cardinal *num_params;
897 {
898     exit (OBEYSESS_DISPLAY);
899 }
900
901 /* ARGSUSED */
902 void
903 DoPing (w, event, params, num_params)
904     Widget w;
905     XEvent *event;
906     String *params;
907     Cardinal *num_params;
908 {
909     EmptyHostnames ();
910     pingTry = 0;
911     PingHosts ((XtPointer)NULL, (XtIntervalId *)NULL);
912 }
913
914 static XtActionsRec app_actions[] = {
915     "Accept",       DoAccept,
916     "Cancel",       DoCancel,
917     "CheckWilling", DoCheckWilling,
918     "Ping",         DoPing,
919 };
920
921 main (argc, argv)
922     char    **argv;
923 {
924     Arg         position[3];
925     Dimension   width, height;
926     Position    x, y;
927     int         i;
928     char        *xsetup;
929
930     /******************************/
931     /** set the locale, and      **/
932     /** open the message catalog **/
933     /******************************/
934
935     setlocale(LC_ALL, "");
936     XtSetLanguageProc( NULL, NULL, NULL );
937     langenv = getenv("LANG");
938
939     /******************************************/
940     /** set the font paths                   **/
941     /******************************************/
942     if ( (xsetup = getenv("XSETUP")) != NULL)
943       if(system(xsetup) == -1)
944             fprintf (stderr, "dtchooser: Cannot source %s\n",xsetup);
945
946     /******************************************/
947     /** save argc and argv for RespondLangCB **/
948     /******************************************/
949     amChooser = 1;  /** tell RespondLangCB we are a chooser **/
950     orig_argc = argc;
951     orig_argv = (char **)malloc(sizeof(char *) * (orig_argc+1));
952     for (i = 0; i < orig_argc; i++) {
953         orig_argv[i] = argv[i];
954     }
955     orig_argv[orig_argc] = NULL;
956
957     toplevel = XtInitialize (argv[0], "Dtlogin", options, XtNumber(options),
958                              &argc, argv);
959
960     XtVaSetValues(XmGetXmDisplay(XtDisplay(toplevel)),
961                 XmNdragInitiatorProtocolStyle, XmDRAG_NONE,
962                 NULL);
963
964     XtAddConverter(XtRString, XtRARRAY8, CvtStringToARRAY8, NULL, 0);
965
966     XtGetApplicationResources (toplevel, (XtPointer) &app_resources, resources,
967                                XtNumber (resources), NULL, (Cardinal) 0);
968
969     dpyinfo.dpy         = XtDisplay(toplevel);
970 /*    dpyinfo.name      = "";*/
971     dpyinfo.screen      = DefaultScreen(dpyinfo.dpy);
972     dpyinfo.root        = RootWindow   (dpyinfo.dpy, dpyinfo.screen);
973     dpyinfo.depth       = DefaultDepth (dpyinfo.dpy, dpyinfo.screen);
974     dpyinfo.width       = DisplayWidth (dpyinfo.dpy, dpyinfo.screen);
975     dpyinfo.height      = DisplayHeight(dpyinfo.dpy, dpyinfo.screen);
976     dpyinfo.black_pixel = BlackPixel   (dpyinfo.dpy, dpyinfo.screen);
977     dpyinfo.visual      = DefaultVisual(dpyinfo.dpy, dpyinfo.screen);
978
979     /*
980      *  build widgets...
981      */
982
983     MakeBackground();           /* login_shell, table, matte              */
984     MakeLogo();                 /* logo, logo_pixmap, logo_shadow         */
985     MakeButtons();              /* Push Buttons                           */
986     MakeChooser();              /* Chooser List ...                       */
987
988     if (appInfo.optionsDelay == 0 )
989         MakeOptionsMenu();      /* make option_button pop-up menu         */
990     else
991         XtAddTimeOut((unsigned long) appInfo.optionsDelay * 1000, MakeOptionsProc, NULL);
992
993 #if 0
994     /*
995      * center ourselves on the screen
996      */
997     XtSetMappedWhenManaged(toplevel, FALSE);
998     XtRealizeWidget (toplevel);
999 #endif
1000     XtRealizeWidget (login_shell);
1001 XtPopup(login_shell, XtGrabNone);
1002 #if 0
1003     XtSetArg (position[0], XtNwidth, &width);
1004     XtSetArg (position[1], XtNheight, &height);
1005     XtGetValues (login_shell, position, (Cardinal) 2);
1006     x = (Position)(WidthOfScreen (XtScreen (toplevel)) - width) / 2;
1007     y = (Position)(HeightOfScreen (XtScreen (toplevel)) - height) / 3;
1008     XtSetArg (position[0], XtNx, x);
1009     XtSetArg (position[1], XtNy, y);
1010     XtSetValues (login_shell, position, (Cardinal) 2);
1011 #endif
1012
1013     /*
1014      * Run
1015      */
1016 #if 0
1017     XtMapWidget(toplevel);
1018 #endif
1019     InitXDMCP (argv + 1);
1020     XtMainLoop ();
1021     exit(0);
1022     /*NOTREACHED*/
1023 }
1024
1025 /* Converts the hex string s of length len into the byte array d.
1026    Returns 0 if s was a legal hex string, 1 otherwise.
1027    */
1028 int
1029 FromHex (s, d, len)
1030     char    *s, *d;
1031     int     len;
1032 {
1033     int t;
1034     int ret = len&1;            /* odd-length hex strings are illegal */
1035     while (len >= 2)
1036     {
1037 #define HexChar(c)  ('0' <= (c) && (c) <= '9' ? (c) - '0' : (c) - 'a' + 10)
1038
1039         if (!ishexdigit(*s))
1040             ret = 1;
1041         t = HexChar (*s) << 4;
1042         s++;
1043         if (!ishexdigit(*s))
1044             ret = 1;
1045         t += HexChar (*s);
1046         s++;
1047         *d++ = t;
1048         len -= 2;
1049     }
1050     return ret;
1051 }
1052
1053 /*ARGSUSED*/
1054 static void
1055 CvtStringToARRAY8 (args, num_args, fromVal, toVal)
1056     XrmValuePtr args;
1057     Cardinal    *num_args;
1058     XrmValuePtr fromVal;
1059     XrmValuePtr toVal;
1060 {
1061     static ARRAY8Ptr    dest;
1062     char        *s;
1063     int         len;
1064
1065     dest = (ARRAY8Ptr) XtMalloc (sizeof (ARRAY8));
1066     len = fromVal->size;
1067     s = (char *) fromVal->addr;
1068     if (!XdmcpAllocARRAY8 (dest, len >> 1))
1069         XtStringConversionWarning ((char *) fromVal->addr, XtRARRAY8);
1070     else
1071     {
1072         FromHex (s, (char *) dest->data, len);
1073     }
1074     toVal->addr = (caddr_t) &dest;
1075     toVal->size = sizeof (ARRAY8Ptr);
1076 }