dtdocbook: Coverity 86763
[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 libraries 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 static char *Print8Address (ARRAY8Ptr   Address);
72
73
74 static int
75 FormatBytes (
76     unsigned char *data,
77     int     length,
78     char    *buf,
79     int     buflen)
80 {
81     int     i;
82     static char     HexChars[] = "0123456789abcdef";
83
84     if (buflen < length * 2 + 1)
85         return 0;
86     for (i = 0; i < length; i++)
87     {
88         *buf++ = HexChars[(data[i] >> 4) & 0xf];
89         *buf++ = HexChars[(data[i]) & 0xf];
90     }
91     *buf++ = '\0';
92     return 1;
93 }
94
95 static int
96 FormatARRAY8 (
97     ARRAY8Ptr   a,
98     char        *buf,
99     int         buflen)
100 {
101     return FormatBytes (a->data, a->length, buf, buflen);
102 }
103
104 typedef struct _IndirectUsers {
105     struct _IndirectUsers   *next;
106     ARRAY8      client;
107     CARD16      connectionType;
108 } IndirectUsersRec, *IndirectUsersPtr;
109
110 static IndirectUsersPtr indirectUsers;
111
112 int
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 void
136 ForgetIndirectClient (
137     ARRAY8Ptr   clientAddress,
138     CARD16      connectionType)
139 {
140     IndirectUsersPtr    i, prev;
141
142     prev = 0;
143     for (i = indirectUsers; i; i = i->next)
144     {
145         if (XdmcpARRAY8Equal (clientAddress, &i->client) &&
146             connectionType == i->connectionType)
147         {
148             if (prev)
149                 prev->next = i->next;
150             else
151                 indirectUsers = i->next;
152             XdmcpDisposeARRAY8 (&i->client);
153             free ((char *) i);
154             break;
155         }
156         prev = i;
157     }
158 }
159
160 int
161 IsIndirectClient (
162     ARRAY8Ptr   clientAddress,
163     CARD16      connectionType)
164 {
165     IndirectUsersPtr    i;
166
167     for (i = indirectUsers; i; i = i->next)
168         if (XdmcpARRAY8Equal (clientAddress, &i->client) &&
169             connectionType == i->connectionType)
170             return 1;
171     return 0;
172 }
173
174 extern char *NetaddrPort();
175
176 static int
177 FormatChooserArgument (
178     char    *buf,
179     int     len)
180 {
181     unsigned char   addr_buf[1024];
182     int             addr_len = sizeof (addr_buf);
183     unsigned char   result_buf[1024];
184     int             result_len = 0;
185     int             netfamily;
186
187     if (GetChooserAddr (addr_buf, &addr_len) == -1)
188     {
189         LogError ((unsigned char *)"Cannot get return address for chooser socket\n");
190         Debug ("Cannot get chooser socket address\n");
191         return 0;
192     }
193     netfamily = NetaddrFamily((XdmcpNetaddr)addr_buf);
194     switch (netfamily) {
195     case AF_INET:
196         {
197             char *port;
198             int portlen;
199             ARRAY8Ptr localAddress, getLocalAddress ();
200
201             port = NetaddrPort((XdmcpNetaddr)addr_buf, &portlen);
202             result_buf[0] = netfamily >> 8;
203             result_buf[1] = netfamily & 0xFF;
204             result_buf[2] = port[0];
205             result_buf[3] = port[1];
206             localAddress = getLocalAddress ();
207             bcopy ((char *)localAddress->data, (char *)result_buf+4, 4);
208             result_len = 8;
209         }
210         break;
211 #ifdef AF_DECnet
212     case AF_DECnet:
213         break;
214 #endif
215     default:
216         Debug ("Chooser family %d isn't known\n", netfamily);
217         return 0;
218     }
219
220     return FormatBytes (result_buf, result_len, buf, len);
221 }
222
223 typedef struct _Choices {
224     struct _Choices *next;
225     ARRAY8          client;
226     CARD16          connectionType;
227     ARRAY8          choice;
228     long            time;
229 } ChoiceRec, *ChoicePtr;
230
231 static ChoicePtr   choices;
232
233 ARRAY8Ptr
234 IndirectChoice (
235     ARRAY8Ptr   clientAddress,
236     CARD16      connectionType)
237 {
238     ChoicePtr   c, next, prev;
239     long        now;
240
241     now = time (0);
242     prev = 0;
243     for (c = choices; c; c = next)
244     {
245         next = c->next;
246         if (now - c->time > 15)
247         {
248             Debug ("Timeout choice\n");
249             if (prev)
250                 prev->next = next;
251             else
252                 choices = next;
253             XdmcpDisposeARRAY8 (&c->client);
254             XdmcpDisposeARRAY8 (&c->choice);
255             free ((char *) c);
256         }
257         else
258         {
259             if (XdmcpARRAY8Equal (clientAddress, &c->client) &&
260                 connectionType == c->connectionType)
261                 return &c->choice;
262             prev = c;
263         }
264     }
265     return 0;
266 }
267
268 static int
269 RegisterIndirectChoice (
270     ARRAY8Ptr   clientAddress,
271     CARD16 connectionType,
272     ARRAY8Ptr   choice)
273 {
274     ChoicePtr   c;
275     int         insert;
276     int         found = 0;
277
278     Debug ("Got indirect choice back (%s)\n", Print8Address(clientAddress));
279     for (c = choices; c; c = c->next) {
280         if (XdmcpARRAY8Equal (clientAddress, &c->client) &&
281             connectionType == c->connectionType) {
282             found = 1;
283             break;
284         }
285     }
286     if (!found)
287         return 0;
288
289     insert = 0;
290
291     if (!c)
292     {
293         c = (ChoicePtr) malloc (sizeof (ChoiceRec));
294         insert = 1;
295         if (!c)
296             return 0;
297         c->connectionType = connectionType;
298         if (!XdmcpCopyARRAY8 (clientAddress, &c->client))
299         {
300             free ((char *) c);
301             return 0;
302         }
303     }
304     else
305     {
306         XdmcpDisposeARRAY8 (&c->choice);
307     }
308
309     if (!XdmcpCopyARRAY8 (choice, &c->choice))
310     {
311         XdmcpDisposeARRAY8 (&c->client);
312         free ((char *) c);
313         return 0;
314     }
315     if (insert)
316     {
317         c->next = choices;
318         choices = c;
319     }
320     c->time = time (0);
321
322     Debug("choice=(%s)\n", Print8Address(choice)); 
323
324     return 1;
325 }
326
327 #ifdef notdef
328 static void
329 RemoveIndirectChoice (clientAddress, connectionType)
330     ARRAY8Ptr   clientAddress;
331     CARD16      connectionType;
332 {
333     ChoicePtr   c, prev;
334
335     prev = 0;
336     for (c = choices; c; c = c->next)
337     {
338         if (XdmcpARRAY8Equal (clientAddress, &c->client) &&
339             connectionType == c->connectionType)
340         {
341             if (prev)
342                 prev->next = c->next;
343             else
344                 choices = c->next;
345             XdmcpDisposeARRAY8 (&c->client);
346             XdmcpDisposeARRAY8 (&c->choice);
347             free ((char *) c);
348             return;
349         }
350         prev = c;
351     }
352 }
353 #endif
354
355 /*ARGSUSED*/
356 static void
357 AddChooserHost (
358     CARD16      connectionType,
359     ARRAY8Ptr   addr,
360     char        *closure)
361 {
362     char        ***argp, **parseArgs();
363     char        hostbuf[1024];
364
365     argp = (char ***) closure;
366     if (addr->length == strlen ("BROADCAST") &&
367         !strncmp ((char *)addr->data, "BROADCAST", addr->length))
368     {
369         *argp = parseArgs (*argp, "BROADCAST");
370     }
371     else if (FormatARRAY8 (addr, hostbuf, sizeof (hostbuf)))
372     {
373         *argp = parseArgs (*argp, hostbuf);
374     }
375 }
376
377 int
378 ProcessChooserSocket (
379     int fd)
380 {
381     int client_fd;
382     char        buf[1024];
383     int         len;
384     XdmcpBuffer buffer;
385     ARRAY8      clientAddress;
386     CARD16      connectionType;
387     ARRAY8      choice;
388
389     Debug ("Process chooser socket\n");
390     len = sizeof (buf);
391     client_fd = accept (fd, (struct sockaddr *)buf, &len);
392     if (client_fd == -1)
393     {
394         LogError ((unsigned char *)"Cannot accept chooser connection\n");
395         return 0;
396     }
397     Debug ("Accepted %d\n", client_fd);
398     
399     len = read (client_fd, buf, sizeof (buf));
400     Debug ("Read returns %d\n", len);
401     if (len > 0)
402     {
403         buffer.data = (BYTE *) buf;
404         buffer.size = sizeof (buf);
405         buffer.count = len;
406         buffer.pointer = 0;
407         clientAddress.data = 0;
408         clientAddress.length = 0;
409         choice.data = 0;
410         choice.length = 0;
411         if (XdmcpReadARRAY8 (&buffer, &clientAddress) &&
412             XdmcpReadCARD16 (&buffer, &connectionType) &&
413             XdmcpReadARRAY8 (&buffer, &choice))
414         {
415             Debug ("Read from chooser successfully\n");
416             if (!RegisterIndirectChoice (&clientAddress, connectionType, &choice))
417                 Debug ("Invalid chooser reply\n");
418         }
419         XdmcpDisposeARRAY8 (&clientAddress);
420         XdmcpDisposeARRAY8 (&choice);
421     }
422     else
423     {
424         LogError ((unsigned char *)"Choice response read error %s\n", strerror(errno));
425     }
426
427     close (client_fd);
428     return 1;
429 }
430
431 void
432 RunChooser (
433     struct display  *d)
434 {
435     char    **args, **parseArgs(), **systemEnv();
436     char    buf[1024];
437     char    **env;
438
439     Debug ("RunChooser %s\n", d->name);
440     SetTitle (d->name, "chooser");
441     LoadXloginResources (d);
442
443     args = parseArgs ((char **) 0, d->chooser);
444     strcpy (buf, "-xdmaddress ");
445     if (FormatChooserArgument (buf + strlen (buf), sizeof (buf) - strlen (buf)))
446         args = parseArgs (args, buf);
447     strcpy (buf, "-clientaddress ");
448     if (FormatARRAY8 (&d->clientAddr, buf + strlen (buf), sizeof (buf) - strlen (buf)))
449         args = parseArgs (args, buf);
450     sprintf (buf, "-connectionType %d", d->connectionType);
451     args = parseArgs (args, buf);
452     ForEachChooserHost (&d->clientAddr,
453                         d->connectionType,
454                         (int (*)()) AddChooserHost,
455                         (char *) &args);
456     env = systemEnv (d, (char *) 0, (char *) 0);
457     if (d->authFile)
458             env = setEnv (env, "XAUTHORITY", d->authFile);
459     if (d->pmSearchPath)
460             env = setEnv(env, "XMICONSEARCHPATH", d->pmSearchPath);
461     if (d->bmSearchPath)
462             env = setEnv(env, "XMICONBMSEARCHPATH", d->bmSearchPath);
463     if ( d->language && strlen(d->language) > 0 )
464             env = setEnv(env, "LANG", d->language);
465     if ( d->langList && strlen(d->langList) > 0 )
466             env = setEnv(env, LANGLIST,  d->langList);
467 #if !defined (ENABLE_DYNAMIC_LANGLIST)
468     else
469             if ( strlen(languageList) > 0 )
470                  env = setEnv(env, LANGLIST, languageList);
471 #endif /* ENABLE_DYNAMIC_LANGLIST */
472     if ( d->setup)
473             env = setEnv(env, "XSETUP", d->setup);
474     if(d->displayType.location == Local)
475             env = setEnv (env, LOCATION, "local");
476     else
477             env = setEnv (env, LOCATION, "remote");
478
479
480     Debug ("Running %s\n", args[0]);
481     execute (args, env);
482     Debug ("Couldn't run %s\n", args[0]);
483     LogError ((unsigned char *)"Cannot execute %s\n", args[0]);
484     exit (REMANAGE_DISPLAY);
485 }
486
487 static char *
488 Print8Address (
489     ARRAY8Ptr   Address)
490 {
491   static char buf[200];
492   char *b;
493   int i;
494
495   b = buf;
496   b[0]='\0';
497   for (i = 0; i < (int)Address->length; i++) {
498       sprintf(b, " %d", Address->data[i]);
499       b = buf + strlen(buf);
500   }
501   return(buf);
502 }