Use C++ linker
[oweals/cde.git] / cde / programs / dtlogin / choose.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: choose.c /main/5 1997/08/13 11:42:50 kaleb $
31  *
32  * Copyright 1990 Massachusetts Institute of Technology
33  *
34  * Permission to use, copy, modify, distribute, and sell this software and its
35  * documentation for any purpose is hereby granted without fee, provided that
36  * the above copyright notice appear in all copies and that both that
37  * copyright notice and this permission notice appear in supporting
38  * documentation, and that the name of M.I.T. not be used in advertising or
39  * publicity pertaining to distribution of the software without specific,
40  * written prior permission.  M.I.T. makes no representations about the
41  * suitability of this software for any purpose.  It is provided "as is"
42  * without express or implied warranty.
43  *
44  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
45  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
46  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
47  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
48  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
49  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
50  *
51  * Author:  Keith Packard, MIT X Consortium
52  */
53
54 /*
55  * choose.c
56  *
57  * xdm interface to chooser program
58  */
59
60 # include   "dm.h"
61 # include   "vg.h"
62
63 # include       <X11/X.h>
64 # include       <sys/types.h>
65 # include       <sys/socket.h>
66 # include       <netinet/in.h>
67 # include       <sys/un.h>
68 # include       <ctype.h>
69 # include       <errno.h>
70
71 char *
72 Print8Address (ARRAY8Ptr   Address);
73
74
75 static
76 FormatBytes (
77     unsigned char *data,
78     int     length,
79     char    *buf,
80     int     buflen)
81 {
82     int     i;
83     static char     HexChars[] = "0123456789abcdef";
84
85     if (buflen < length * 2 + 1)
86         return 0;
87     for (i = 0; i < length; i++)
88     {
89         *buf++ = HexChars[(data[i] >> 4) & 0xf];
90         *buf++ = HexChars[(data[i]) & 0xf];
91     }
92     *buf++ = '\0';
93     return 1;
94 }
95
96 static
97 FormatARRAY8 (
98     ARRAY8Ptr   a,
99     char        *buf,
100     int         buflen)
101 {
102     return FormatBytes (a->data, a->length, buf, buflen);
103 }
104
105 typedef struct _IndirectUsers {
106     struct _IndirectUsers   *next;
107     ARRAY8      client;
108     CARD16      connectionType;
109 } IndirectUsersRec, *IndirectUsersPtr;
110
111 static IndirectUsersPtr indirectUsers;
112
113 RememberIndirectClient (
114     ARRAY8Ptr   clientAddress,
115     CARD16      connectionType)
116 {
117     IndirectUsersPtr    i;
118
119     for (i = indirectUsers; i; i = i->next)
120         if (XdmcpARRAY8Equal (clientAddress, &i->client) &&
121             connectionType == i->connectionType)
122             return 1;
123     i = (IndirectUsersPtr) malloc (sizeof (IndirectUsersRec));
124     if (!XdmcpCopyARRAY8 (clientAddress, &i->client))
125     {
126         free ((char *) i);
127         return 0;
128     }
129     i->connectionType = connectionType;
130     i->next = indirectUsers;
131     indirectUsers = i;
132     return 1;
133 }
134
135 ForgetIndirectClient (
136     ARRAY8Ptr   clientAddress,
137     CARD16      connectionType)
138 {
139     IndirectUsersPtr    i, prev;
140
141     prev = 0;
142     for (i = indirectUsers; i; i = i->next)
143     {
144         if (XdmcpARRAY8Equal (clientAddress, &i->client) &&
145             connectionType == i->connectionType)
146         {
147             if (prev)
148                 prev->next = i->next;
149             else
150                 indirectUsers = i->next;
151             XdmcpDisposeARRAY8 (&i->client);
152             free ((char *) i);
153             break;
154         }
155         prev = i;
156     }
157 }
158
159 IsIndirectClient (
160     ARRAY8Ptr   clientAddress,
161     CARD16      connectionType)
162 {
163     IndirectUsersPtr    i;
164
165     for (i = indirectUsers; i; i = i->next)
166         if (XdmcpARRAY8Equal (clientAddress, &i->client) &&
167             connectionType == i->connectionType)
168             return 1;
169     return 0;
170 }
171
172 extern char *NetaddrPort();
173
174 static
175 FormatChooserArgument (
176     char    *buf,
177     int     len)
178 {
179     unsigned char   addr_buf[1024];
180     int             addr_len = sizeof (addr_buf);
181     unsigned char   result_buf[1024];
182     int             result_len = 0;
183     int             netfamily;
184
185     if (GetChooserAddr (addr_buf, &addr_len) == -1)
186     {
187         LogError ((unsigned char *)"Cannot get return address for chooser socket\n");
188         Debug ("Cannot get chooser socket address\n");
189         return 0;
190     }
191     netfamily = NetaddrFamily((XdmcpNetaddr)addr_buf);
192     switch (netfamily) {
193     case AF_INET:
194         {
195             char *port;
196             int portlen;
197             ARRAY8Ptr localAddress, getLocalAddress ();
198
199             port = NetaddrPort((XdmcpNetaddr)addr_buf, &portlen);
200             result_buf[0] = netfamily >> 8;
201             result_buf[1] = netfamily & 0xFF;
202             result_buf[2] = port[0];
203             result_buf[3] = port[1];
204             localAddress = getLocalAddress ();
205             bcopy ((char *)localAddress->data, (char *)result_buf+4, 4);
206             result_len = 8;
207         }
208         break;
209 #ifdef AF_DECnet
210     case AF_DECnet:
211         break;
212 #endif
213     default:
214         Debug ("Chooser family %d isn't known\n", netfamily);
215         return 0;
216     }
217
218     return FormatBytes (result_buf, result_len, buf, len);
219 }
220
221 typedef struct _Choices {
222     struct _Choices *next;
223     ARRAY8          client;
224     CARD16          connectionType;
225     ARRAY8          choice;
226     long            time;
227 } ChoiceRec, *ChoicePtr;
228
229 static ChoicePtr   choices;
230
231 ARRAY8Ptr
232 IndirectChoice (
233     ARRAY8Ptr   clientAddress,
234     CARD16      connectionType)
235 {
236     ChoicePtr   c, next, prev;
237     long        now;
238
239     now = time (0);
240     prev = 0;
241     for (c = choices; c; c = next)
242     {
243         next = c->next;
244         if (now - c->time > 15)
245         {
246             Debug ("Timeout choice\n");
247             if (prev)
248                 prev->next = next;
249             else
250                 choices = next;
251             XdmcpDisposeARRAY8 (&c->client);
252             XdmcpDisposeARRAY8 (&c->choice);
253             free ((char *) c);
254         }
255         else
256         {
257             if (XdmcpARRAY8Equal (clientAddress, &c->client) &&
258                 connectionType == c->connectionType)
259                 return &c->choice;
260             prev = c;
261         }
262     }
263     return 0;
264 }
265
266 static int
267 RegisterIndirectChoice (
268     ARRAY8Ptr   clientAddress,
269     CARD16 connectionType,
270     ARRAY8Ptr   choice)
271 {
272     ChoicePtr   c;
273     int         insert;
274     int         found;
275
276     Debug ("Got indirect choice back (%s)\n", Print8Address(clientAddress));
277     for (c = choices; c; c = c->next) {
278         if (XdmcpARRAY8Equal (clientAddress, &c->client) &&
279             connectionType == c->connectionType) {
280             found = 1;
281             break;
282         }
283     }
284     if (!found)
285         return 0;
286
287     insert = 0;
288
289     if (!c)
290     {
291         c = (ChoicePtr) malloc (sizeof (ChoiceRec));
292         insert = 1;
293         if (!c)
294             return 0;
295         c->connectionType = connectionType;
296         if (!XdmcpCopyARRAY8 (clientAddress, &c->client))
297         {
298             free ((char *) c);
299             return 0;
300         }
301     }
302     else
303     {
304         XdmcpDisposeARRAY8 (&c->choice);
305     }
306
307     if (!XdmcpCopyARRAY8 (choice, &c->choice))
308     {
309         XdmcpDisposeARRAY8 (&c->client);
310         free ((char *) c);
311         return 0;
312     }
313     if (insert)
314     {
315         c->next = choices;
316         choices = c;
317     }
318     c->time = time (0);
319
320     Debug("choice=(%s)\n", Print8Address(choice)); 
321
322     return 1;
323 }
324
325 #ifdef notdef
326 static
327 RemoveIndirectChoice (clientAddress, connectionType)
328     ARRAY8Ptr   clientAddress;
329     CARD16      connectionType;
330 {
331     ChoicePtr   c, prev;
332
333     prev = 0;
334     for (c = choices; c; c = c->next)
335     {
336         if (XdmcpARRAY8Equal (clientAddress, &c->client) &&
337             connectionType == c->connectionType)
338         {
339             if (prev)
340                 prev->next = c->next;
341             else
342                 choices = c->next;
343             XdmcpDisposeARRAY8 (&c->client);
344             XdmcpDisposeARRAY8 (&c->choice);
345             free ((char *) c);
346             return;
347         }
348         prev = c;
349     }
350 }
351 #endif
352
353 /*ARGSUSED*/
354 static void
355 AddChooserHost (
356     CARD16      connectionType,
357     ARRAY8Ptr   addr,
358     char        *closure)
359 {
360     char        ***argp, **parseArgs();
361     char        hostbuf[1024];
362
363     argp = (char ***) closure;
364     if (addr->length == strlen ("BROADCAST") &&
365         !strncmp ((char *)addr->data, "BROADCAST", addr->length))
366     {
367         *argp = parseArgs (*argp, "BROADCAST");
368     }
369     else if (FormatARRAY8 (addr, hostbuf, sizeof (hostbuf)))
370     {
371         *argp = parseArgs (*argp, hostbuf);
372     }
373 }
374
375 ProcessChooserSocket (
376     int fd)
377 {
378     int client_fd;
379     char        buf[1024];
380     int         len;
381     XdmcpBuffer buffer;
382     ARRAY8      clientAddress;
383     CARD16      connectionType;
384     ARRAY8      choice;
385
386     Debug ("Process chooser socket\n");
387     len = sizeof (buf);
388     client_fd = accept (fd, (struct sockaddr *)buf, &len);
389     if (client_fd == -1)
390     {
391         LogError ((unsigned char *)"Cannot accept chooser connection\n");
392         return;
393     }
394     Debug ("Accepted %d\n", client_fd);
395     
396     len = read (client_fd, buf, sizeof (buf));
397     Debug ("Read returns %d\n", len);
398     if (len > 0)
399     {
400         buffer.data = (BYTE *) buf;
401         buffer.size = sizeof (buf);
402         buffer.count = len;
403         buffer.pointer = 0;
404         clientAddress.data = 0;
405         clientAddress.length = 0;
406         choice.data = 0;
407         choice.length = 0;
408         if (XdmcpReadARRAY8 (&buffer, &clientAddress) &&
409             XdmcpReadCARD16 (&buffer, &connectionType) &&
410             XdmcpReadARRAY8 (&buffer, &choice))
411         {
412             Debug ("Read from chooser succesfully\n");
413             if (!RegisterIndirectChoice (&clientAddress, connectionType, &choice))
414                 Debug ("Invalid chooser reply\n");
415         }
416         XdmcpDisposeARRAY8 (&clientAddress);
417         XdmcpDisposeARRAY8 (&choice);
418     }
419     else
420     {
421         LogError ((unsigned char *)"Choice response read error %s\n", strerror(errno));
422     }
423
424     close (client_fd);
425 }
426
427   RunChooser (
428     struct display  *d)
429 {
430     char    **args, **parseArgs(), **systemEnv();
431     char    buf[1024];
432     char    **env;
433
434     Debug ("RunChooser %s\n", d->name);
435     SetTitle (d->name, "chooser");
436     LoadXloginResources (d);
437
438     args = parseArgs ((char **) 0, d->chooser);
439     strcpy (buf, "-xdmaddress ");
440     if (FormatChooserArgument (buf + strlen (buf), sizeof (buf) - strlen (buf)))
441         args = parseArgs (args, buf);
442     strcpy (buf, "-clientaddress ");
443     if (FormatARRAY8 (&d->clientAddr, buf + strlen (buf), sizeof (buf) - strlen (buf)))
444         args = parseArgs (args, buf);
445     sprintf (buf, "-connectionType %d", d->connectionType);
446     args = parseArgs (args, buf);
447     ForEachChooserHost (&d->clientAddr,
448                         d->connectionType,
449                         (int (*)()) AddChooserHost,
450                         (char *) &args);
451     env = systemEnv (d, (char *) 0, (char *) 0);
452     if (d->authFile)
453             env = setEnv (env, "XAUTHORITY", d->authFile);
454     if (d->pmSearchPath)
455             env = setEnv(env, "XMICONSEARCHPATH", d->pmSearchPath);
456     if (d->bmSearchPath)
457             env = setEnv(env, "XMICONBMSEARCHPATH", d->bmSearchPath);
458     if ( d->language && strlen(d->language) > 0 )
459             env = setEnv(env, "LANG", d->language);
460     if ( d->langList && strlen(d->langList) > 0 )
461             env = setEnv(env, LANGLIST,  d->langList);
462 #if !defined (ENABLE_DYNAMIC_LANGLIST)
463     else
464             if (languageList && strlen(languageList) > 0 )
465                  env = setEnv(env, LANGLIST, languageList);
466 #endif /* ENABLE_DYNAMIC_LANGLIST */
467     if ( d->setup)
468             env = setEnv(env, "XSETUP", d->setup);
469     if(d->displayType.location == Local)
470             env = setEnv (env, LOCATION, "local");
471     else
472             env = setEnv (env, LOCATION, "remote");
473
474
475     Debug ("Running %s\n", args[0]);
476     execute (args, env);
477     Debug ("Couldn't run %s\n", args[0]);
478     LogError ((unsigned char *)"Cannot execute %s\n", args[0]);
479     exit (REMANAGE_DISPLAY);
480 }
481
482 char *
483 Print8Address (
484     ARRAY8Ptr   Address)
485 {
486   static char buf[200];
487   char *b;
488   int i;
489
490   b = buf;
491   b[0]='\0';
492   for (i = 0; i < (int)Address->length; i++) {
493       sprintf(b, " %d", Address->data[i]);
494       b = buf + strlen(buf);
495   }
496   return(buf);
497 }