Merge branch 'master' into cde-next
[oweals/cde.git] / cde / programs / dtlogin / util.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 /* (c) Copyright 1997 The Open Group */
24 /*                                                                      *
25  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
26  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
27  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
28  * (c) Copyright 1993, 1994 Novell, Inc.                                *
29  */
30 /*
31  * xdm - display manager daemon
32  *
33  * $TOG: util.c /main/15 1998/04/06 13:22:20 mgreess $
34  *
35  * Copyright 1988 Massachusetts Institute of Technology
36  *
37  * Permission to use, copy, modify, and distribute this software and its
38  * documentation for any purpose and without fee is hereby granted, provided
39  * that the above copyright notice appear in all copies and that both that
40  * copyright notice and this permission notice appear in supporting
41  * documentation, and that the name of M.I.T. not be used in advertising or
42  * publicity pertaining to distribution of the software without specific,
43  * written prior permission.  M.I.T. makes no representations about the
44  * suitability of this software for any purpose.  It is provided "as is"
45  * without express or implied warranty.
46  *
47  * Author:  Keith Packard, MIT X Consortium
48  */
49
50 /*
51  * util.c
52  *
53  * various utility routines
54  */
55
56
57 #include    <sys/stat.h>
58 #include    <setjmp.h>
59 #include    <string.h>
60 #include    <dirent.h>
61 #include    <nl_types.h>
62
63 # include   <sys/signal.h>
64
65 # ifndef NULL
66 #  define NULL 0
67 # endif
68
69
70 # include       "dm.h"
71 # include       "vgmsg.h"
72 nl_catd         nl_fd = (nl_catd)-1;    /* message catalog file descriptor */
73
74 #if !defined(NL_CAT_LOCALE)
75 #define NL_CAT_LOCALE 0
76 #endif
77
78 #if !defined (ENABLE_DYNAMIC_LANGLIST)
79 #define LANGLISTSIZE    2048
80 char    languageList[LANGLISTSIZE];     /* global list of languages     */
81 #endif /* ENABLE_DYNAMIC_LANGLIST */
82
83 /***************************************************************************
84  *
85  *  Local procedure declarations
86  *
87  ***************************************************************************/
88
89 static char * makeEnv( 
90                         char *name,
91                         char *value) ;
92
93 static SIGVAL MakeLangAbort(
94                         int arg );
95                         
96 static int MatchesFileSuffix(const char *filename, const char *suffix);
97
98 static void   ScanNLSDir(
99                         char * dirname );
100
101 /********    End Local Function Declarations    ********/
102
103
104 /***************************************************************************
105  *
106  *  ReadCatalog
107  *
108  *  read a string from the message catalog
109  ***************************************************************************/
110
111 unsigned char *
112 ReadCatalog( int set_num, int msg_num, char *def_str )
113 {
114     static Bool alreadyopen = False;
115     char *s;
116
117     if (alreadyopen == False)
118     {
119       char *curNlsPath, *newNlsPath;
120       int newNlsPathLen;
121
122       alreadyopen = True;
123
124      /*
125       * Desktop message catalogs are in DT directory, so append desktop
126       * search paths to current NLSPATH.
127       */
128       #define NLS_PATH_STRING  CDE_INSTALLATION_TOP "/nls/msg/%L/%N.cat:" \
129                          CDE_INSTALLATION_TOP "/lib/nls/msg/%L/%N.cat:" \
130                          CDE_INSTALLATION_TOP "/lib/nls/msg/%l/%t/%c/%N.cat:" \
131                          CDE_INSTALLATION_TOP "/lib/nls/msg/%l/%c/%N.cat"
132
133       curNlsPath = getenv("NLSPATH");
134       if (curNlsPath && strlen(curNlsPath) == 0)
135       {
136         curNlsPath = NULL;
137       }
138  
139      /*
140       * 7 is "NLSPATH"
141       * 1 is "="
142       * <length of NLS_PATH_STRING>
143       * 1 for null byte
144       */
145       newNlsPathLen = 7 + 1 + strlen(NLS_PATH_STRING) + 1;
146
147       if (curNlsPath != NULL)
148       {
149        /*
150         * 1 is ":"
151         * <length of curNlsPath>
152         */
153         newNlsPathLen += (1 + strlen(curNlsPath));
154       }
155
156       newNlsPath = malloc(newNlsPathLen);  /* placed in environ, do not free */
157       
158       if (curNlsPath != NULL)
159       {
160         sprintf(newNlsPath, "NLSPATH=%s:%s", curNlsPath, NLS_PATH_STRING);
161       }
162       else
163       {
164         sprintf(newNlsPath, "NLSPATH=%s", NLS_PATH_STRING);
165       }
166      
167      /*
168       * Store new NLSPATH in environment. Note this memory cannot be freed 
169       */
170       putenv(newNlsPath);
171   
172      /*
173       * Open message catalog. Note, if invalid descriptor returned (ie
174       * msg catalog could not be opened), subsequent call to catgets() using
175       * that descriptor will return 'def_str'.
176       */
177       nl_fd = catopen("dtlogin", NL_CAT_LOCALE);
178     }
179
180     s = catgets(nl_fd,set_num,msg_num,def_str);
181     
182     return((unsigned char *)s);
183 }
184
185 void
186 printEnv( char **e )
187 {
188         while (*e)
189                 Debug ("    %s\n", *e++);
190 }
191
192 static char * 
193 makeEnv( char *name, char *value )
194 {
195         char    *result;
196
197         result = malloc ((unsigned) (strlen (name) + strlen (value) + 2));
198         if (!result) {
199                 LogOutOfMem(
200                   ReadCatalog(MC_LOG_SET,MC_LOG_MAKEENV,MC_DEF_LOG_MAKEENV));
201                 return 0;
202         }
203
204         if (*value) {
205                    sprintf (result, "%s=%s", name, value);
206         }
207         else {
208                 sprintf (result, "%s", name);
209         }
210
211         return result;
212 }
213
214 char * 
215 getEnv( char **e, char *name )
216 {
217     int l = strlen (name);
218
219     while (*e) {
220         if ((int) strlen (*e) > l &&
221             !strncmp (*e, name, l) &&
222             (*e)[l] == '=')
223           return (*e) + l + 1;
224
225         ++e;
226     }
227     return 0;
228 }
229
230 char ** 
231 setEnv( char **e, char *name, char *value )
232 {
233     char        **new, **old;
234     char        *newe;
235     int         envsize;
236     int         l;
237
238     l = strlen (name);
239     newe = makeEnv (name, value);
240     if (!newe) {
241         LogOutOfMem(ReadCatalog(MC_LOG_SET,MC_LOG_SETENV,MC_DEF_LOG_SETENV));
242         return e;
243     }
244     if (e) {
245         for (old = e; *old; old++)
246             if ((int) strlen (*old) > l &&
247                 !strncmp (*old, name, l) &&
248                 (*old)[l] == '=')
249               break;
250
251         if (*old) {
252                 free (*old);
253                 *old = newe;
254                 return e;
255         }
256         envsize = old - e;
257         new = (char **)
258               realloc((char *) e, (unsigned) ((envsize + 2) * sizeof (char *)));
259     } else {
260         envsize = 0;
261         new = (char **) malloc (2 * sizeof (char *));
262     }
263     if (!new) {
264         LogOutOfMem(ReadCatalog(MC_LOG_SET,MC_LOG_SETENV,MC_DEF_LOG_SETENV));
265         free (newe);
266         return e;
267     }
268     new[envsize] = newe;
269     new[envsize+1] = 0;
270     return new;
271 }
272
273 void
274 freeEnv (char **env)
275 {
276     char    **e;
277
278     if (env)
279     {
280         for (e = env; *e; e++)
281             free (*e);
282         free (env);
283     }
284 }
285
286 # define isblank(c)     ((c) == ' ' || c == '\t')
287
288 char ** 
289 parseArgs( char **argv, char *string )
290 {
291         char    *word;
292         char    *save;
293         int     i;
294
295         i = 0;
296         while (argv && argv[i])
297                 ++i;
298         if (!argv) {
299                 argv = (char **) malloc (sizeof (char *));
300                 if (!argv) {
301                         LogOutOfMem(ReadCatalog(
302                           MC_LOG_SET,MC_LOG_PARSEARGS,MC_DEF_LOG_PARSEARGS));
303                         return 0;
304                 }
305         }
306         word = string;
307         for (;;) {
308                 if (!*string || isblank (*string)) {
309                         if (word != string) {
310                                 argv = (char **) realloc ((char *) argv,
311                                         (unsigned) ((i + 2) * sizeof (char *)));
312                                 save = malloc ((unsigned) (string - word + 1));
313                                 if (!argv || !save) {
314                                         LogOutOfMem(ReadCatalog(MC_LOG_SET,
315                                           MC_LOG_PARSEARGS,
316                                           MC_DEF_LOG_PARSEARGS));
317                                         if (argv)
318                                                 free ((char *) argv);
319                                         if (save)
320                                                 free (save);
321                                         return 0;
322                                 }
323                                 argv[i] = strncpy (save, word, string-word);
324                                 argv[i][string-word] = '\0';
325                                 i++;
326                         }
327                         if (!*string)
328                                 break;
329                         word = string + 1;
330                 }
331                 ++string;
332         }
333         argv[i] = 0;
334         return argv;
335 }
336
337 void
338 CleanUpChild( void )
339 {
340 /*
341  *  On i386/i486 platforms setprrp() functions causes the mouse not
342  *  to work.  Since in the daemon mode the parent daemon has already
343  *  executed a setpgrp it is a process and session leader. Since it
344  *  has also gotten rid of the controlling terminal there is no great
345  *  harm in not making the sub-daemons as leaders.
346  */
347 #if defined (SYSV) || defined (SVR4) || defined(__linux__)
348         setpgrp ();
349 #else
350         setpgrp (0, getpid ());
351         sigsetmask (0);
352 #endif
353 #ifdef SIGCHLD
354         (void) signal (SIGCHLD, SIG_DFL);
355 #endif
356         (void) signal (SIGTERM, SIG_DFL);
357         (void) signal (SIGPIPE, SIG_DFL);
358         (void) signal (SIGALRM, SIG_DFL);
359         (void) signal (SIGHUP, SIG_DFL);
360         CloseOnFork ();
361 }
362
363 char * * 
364 parseEnv( char **e, char *string )
365 {
366
367     char *s1, *s2, *t1, *t2;
368     
369     s1 = s2 = strdup(string);
370     
371     while ((t1 = strtok(s1," \t")) != NULL ) {
372         if ( (t2 = strchr(t1,'=')) != NULL ) {
373             *t2++ = '\0';
374             e = setEnv(e, t1, t2);
375         }
376         
377         s1 = NULL;
378     }
379
380     free(s2);
381     return (e);
382 }    
383
384
385
386
387 /*************************************<->*************************************
388  *
389  *  Cursor GetHourGlass ()
390  *
391  *
392  *  Description:
393  *  -----------
394  *  Builds and returns the appropriate Hourglass cursor
395  *
396  *
397  *  Inputs:
398  *  ------
399  *  dpy = display
400  * 
401  *  Outputs:
402  *  -------
403  *  Return = cursor.
404  *
405  *  Comments:
406  *  --------
407  *  None. (None doesn't count as a comment)
408  * 
409  *************************************<->***********************************/
410
411 #define time32_width 32
412 #define time32_height 32
413 #define time32_x_hot 15
414 #define time32_y_hot 15
415 static unsigned char time32_bits[] = {
416    0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x7f,
417    0x8c, 0x00, 0x00, 0x31, 0x4c, 0x00, 0x00, 0x32, 0x4c, 0x00, 0x00, 0x32,
418    0x4c, 0x00, 0x00, 0x32, 0x4c, 0x00, 0x00, 0x32, 0x4c, 0x00, 0x00, 0x32,
419    0x8c, 0x00, 0x00, 0x31, 0x0c, 0x7f, 0xfe, 0x30, 0x0c, 0xfe, 0x7f, 0x30,
420    0x0c, 0xfc, 0x3f, 0x30, 0x0c, 0xf8, 0x1f, 0x30, 0x0c, 0xe0, 0x07, 0x30,
421    0x0c, 0x80, 0x01, 0x30, 0x0c, 0x80, 0x01, 0x30, 0x0c, 0x60, 0x06, 0x30,
422    0x0c, 0x18, 0x18, 0x30, 0x0c, 0x04, 0x20, 0x30, 0x0c, 0x02, 0x40, 0x30,
423    0x0c, 0x01, 0x80, 0x30, 0x8c, 0x00, 0x00, 0x31, 0x4c, 0x80, 0x01, 0x32,
424    0x4c, 0xc0, 0x03, 0x32, 0x4c, 0xf0, 0x1f, 0x32, 0x4c, 0xff, 0xff, 0x32,
425    0xcc, 0xff, 0xff, 0x33, 0x8c, 0xff, 0xff, 0x31, 0xfe, 0xff, 0xff, 0x7f,
426    0xfe, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00};
427
428 #define time32m_width 32
429 #define time32m_height 32
430 static unsigned char time32m_bits[] = {
431    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
432    0xcf, 0x00, 0x00, 0xf3, 0x6e, 0x00, 0x00, 0x76, 0x6e, 0x00, 0x00, 0x76,
433    0x6e, 0x00, 0x00, 0x76, 0x6e, 0x00, 0x00, 0x76, 0x6e, 0x00, 0x00, 0x76,
434    0xce, 0x00, 0x00, 0x73, 0x8e, 0x7f, 0xfe, 0x71, 0x0e, 0xff, 0xff, 0x70,
435    0x0e, 0xfe, 0x7f, 0x70, 0x0e, 0xfc, 0x3f, 0x70, 0x0e, 0xf8, 0x1f, 0x70,
436    0x0e, 0xe0, 0x07, 0x70, 0x0e, 0xe0, 0x07, 0x70, 0x0e, 0x78, 0x1e, 0x70,
437    0x0e, 0x1c, 0x38, 0x70, 0x0e, 0x06, 0x60, 0x70, 0x0e, 0x03, 0xc0, 0x70,
438    0x8e, 0x01, 0x80, 0x71, 0xce, 0x00, 0x00, 0x73, 0x6e, 0x80, 0x01, 0x76,
439    0x6e, 0xc0, 0x03, 0x76, 0x6e, 0xf0, 0x1f, 0x76, 0x6e, 0xff, 0xff, 0x76,
440    0xee, 0xff, 0xff, 0x77, 0xcf, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff,
441    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
442
443
444 #define time16_x_hot 7
445 #define time16_y_hot 7
446 #define time16_width 16
447 #define time16_height 16
448 static unsigned char time16_bits[] = {
449    0x00, 0x00, 0xfe, 0x7f, 0x14, 0x28, 0x14, 0x28, 0x14, 0x28, 0x24, 0x24,
450    0x44, 0x22, 0x84, 0x21, 0x84, 0x21, 0x44, 0x22, 0x24, 0x24, 0x14, 0x28,
451    0x94, 0x29, 0xd4, 0x2b, 0xfe, 0x7f, 0x00, 0x00};
452
453 #define time16m_width 16
454 #define time16m_height 16
455 static unsigned char time16m_bits[] = {
456    0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f,
457    0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f,
458    0xfe, 0x7f, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff};
459
460
461 Cursor GetHourGlass (Display *dpy)
462 {
463     char        *bits;
464     char        *maskBits;
465     unsigned int width;
466     unsigned int height;
467     unsigned int xHotspot;
468     unsigned int yHotspot;
469     Pixmap       pixmap;
470     Pixmap       maskPixmap;
471     XColor       xcolors[2];
472     unsigned int cWidth;
473     unsigned int cHeight;
474     int          useLargeCursors = 0;
475     Cursor       waitCursor;
476
477     if (XQueryBestCursor (dpy, DefaultRootWindow(dpy), 
478         32, 32, &cWidth, &cHeight))
479     {
480         if ((cWidth >= 32) && (cHeight >= 32))
481         {
482             useLargeCursors = 1;
483         }
484     }
485
486     if (useLargeCursors)
487     {
488         width = time32_width;
489         height = time32_height;
490         bits = (char *)time32_bits;
491         maskBits = (char *)time32m_bits;
492         xHotspot = time32_x_hot;
493         yHotspot = time32_y_hot;
494     }
495     else
496     {
497         width = time16_width;
498         height = time16_height;
499         bits = (char *)time16_bits;
500         maskBits = (char *)time16m_bits;
501         xHotspot = time16_x_hot;
502         yHotspot = time16_y_hot;
503     }
504
505     pixmap = XCreateBitmapFromData (dpy, 
506                      DefaultRootWindow(dpy), bits, 
507                      width, height);
508
509     maskPixmap = XCreateBitmapFromData (dpy, 
510                      DefaultRootWindow(dpy), maskBits, 
511                      width, height);
512
513     xcolors[0].pixel = BlackPixelOfScreen(DefaultScreenOfDisplay(dpy));
514     xcolors[1].pixel = WhitePixelOfScreen(DefaultScreenOfDisplay(dpy));
515
516     XQueryColors (dpy, 
517                   DefaultColormapOfScreen(DefaultScreenOfDisplay
518                                           (dpy)), xcolors, 2);
519
520     waitCursor = XCreatePixmapCursor (dpy, pixmap, maskPixmap,
521                                       &(xcolors[0]), &(xcolors[1]),
522                                       xHotspot, yHotspot);
523     XFreePixmap (dpy, pixmap);
524     XFreePixmap (dpy, maskPixmap);
525
526     return (waitCursor);
527 }
528
529
530
531
532 /*************************************<->*************************************
533  *
534  *  void SetHourGlassCursor
535  *
536  *
537  *  Description:
538  *  -----------
539  *  sets the window cursor to an hourglass
540  *
541  *
542  *  Inputs:
543  *  ------
544  *  dpy = display
545  *  w   = window
546  * 
547  *  Outputs:
548  *  -------
549  *  None
550  *
551  *  Comments:
552  *  --------
553  *  None. (None doesn't count as a comment)
554  * 
555  *************************************<->***********************************/
556
557 void 
558 SetHourGlassCursor( Display *dpy, Window w )
559 {
560     Cursor      cursor;
561     
562     XUndefineCursor(dpy, w);
563     
564     cursor = GetHourGlass(dpy);
565
566     XDefineCursor(dpy, w, cursor);
567     XFreeCursor(dpy, cursor);
568     XFlush(dpy);
569 }
570
571 #if !defined (ENABLE_DYNAMIC_LANGLIST)
572 /***************************************************************************
573  *
574  *  MakeLangList
575  *
576  *  Generate the list of languages installed on the host.
577  *  Result is stored the global array "languageList"
578  *  
579  ***************************************************************************/
580
581 #define DELIM           " \t"   /* delimiters in language list             */
582
583 static jmp_buf  langJump;
584
585 static SIGVAL
586 MakeLangAbort( int arg )
587
588 {
589     longjmp (langJump, 1);
590 }
591
592 void
593 MakeLangList( void )
594 {
595     int i, j;
596
597     char        *lang[500];             /* sort list for languages         */
598     int         nlang;                  /* total number of languages       */
599     char        *p, *s;
600     char        *savelist;
601
602     /*
603      *  build language list from set of languages installed on the host...
604      *  Wrap a timer around it so it doesn't hang things up too long.
605      *  langListTimeout resource  by default is 30 seconds to scan NLS dir. 
606      */
607
608     p = languageList;
609     strcpy( p, "C");
610
611     signal (SIGALRM, MakeLangAbort);
612     alarm ((unsigned) langListTimeout);
613
614     if (!setjmp (langJump)) {
615         ScanNLSDir(DEF_NLS_DIR);
616     }
617     else {
618         LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SCAN,MC_DEF_LOG_NO_SCAN),
619                    DEF_NLS_DIR, langListTimeout);
620     }
621
622     alarm (0);
623     signal (SIGALRM, SIG_DFL);
624
625
626     /*
627      *  sort the list to eliminate duplicates and replace in global array...
628      */
629
630     p = savelist = strdup(languageList);
631     nlang = 0;
632
633     while ( (s = strtok(p, DELIM)) != NULL ) {
634
635         if ( nlang == 0 ) {
636             lang[0] = s;
637             lang[++nlang] = 0;
638             p = NULL;
639             continue;
640         }
641
642         for (i = nlang; i > 0 && strcmp(s,lang[i-1]) < 0; i--);
643
644         if (i==0 || strcmp(s,lang[i-1]) != 0 ) {
645             for (j = nlang; j > i; j--)
646                 lang[j] = lang[j-1];
647
648             lang[i] = s;
649             lang[++nlang] = 0;
650         }
651
652         p = NULL;
653     }
654
655
656     p = languageList;
657     strcpy(p,"");
658
659     for ( i = 0; i < nlang; i++) {
660         strcat(p, lang[i]);
661         strcat(p, " ");
662     }
663
664     free(savelist);
665
666 }        
667
668
669 static int
670 MatchesFileSuffix(const char *filename, const char *suffix)
671 {
672     int         retval = 0;
673 #if defined(_AIX) || defined(SVR4) || defined(__linux__) || defined(CSRG_BASED)
674     int         different = 1;
675              
676     /*
677      * The assumption here is that the use of strrstr is
678      * to determine if "dp->d_name" ends in ".cat".
679      */
680     if (strlen(filename) >= strlen(suffix)) {
681       different = strcmp(filename + (strlen(filename) - strlen (suffix)), suffix);
682     }
683
684     return (different == 0);
685 #else
686     return (strrstr(filename, suffix) != NULL);
687 #endif
688 }
689
690 /***************************************************************************
691  *
692  *  ScanNLSDir
693  *
694  *  Scan a directory structure to see if it contains an installed language.
695  *  If so, the name of the language is appended to a global list of languages.
696  *
697  *  Scan method and scan directory will vary by platform. 
698  *
699  ***************************************************************************/
700
701
702 static void
703 ScanNLSDir(char *dirname)
704
705 #if defined(_AIX)
706 /*
707  * Search installed locale names for AIX 3.2.5
708  */
709 {
710     DIR *dirp;
711     struct dirent *dp;
712
713     /*  Search valid locales which are locale database files in
714      *  /usr/lib/nls/loc.
715      *  File name is "??_??" which can be used as LANG variable.
716      */
717     if((dirp = opendir(dirname)) != NULL)
718     {
719         while((dp = readdir(dirp)) != NULL)
720         {
721             if(strlen(dp->d_name) == 5 && dp->d_name[2] == '_')
722             {
723                 if((int) strlen(languageList) + 7 < LANGLISTSIZE )
724                 {
725                     strcat(languageList, " ");
726                     strcat(languageList, dp->d_name);
727                 }
728             }
729         }
730         closedir(dirp);
731     }
732 }
733
734 #elif defined(hpV4)
735
736 #define LOCALE          "locale.inf"
737 #define LOCALEOLD       "locale.def"
738 #define COLLATE8        "collate8"
739 #define MAILX           "mailx"
740 #define ELM             "elm"
741 #define MSGCAT          ".cat"
742 #define DOT             "."
743 #define DOTDOT          ".."
744
745 /*
746  * Scan for installed locales on HP platform.
747  */
748 {
749     /***************************************************************************
750      *  Scan supplied NLS directory structure to see if it contains an
751      *  installed language.  If so, the name of the language is appended
752      *  to a global list of languages.
753      *
754      *  This routine is recursively called as a directory structure is
755      *  traversed.
756      *
757      *************************************************************************/
758
759     DIR *dirp;
760     struct dirent *dp;
761     struct stat statb;
762
763     char buf[1024];
764     
765     /*
766      *  Scan input directory, looking for a LOCALE file. If a sub-directory
767      *  is found, recurse down into it...
768      */
769     if ( (dirp = opendir(dirname)) != NULL )
770     {
771         while ( (dp = readdir(dirp)) != NULL )
772         {
773             /*
774              *  ignore files that are known not to be candidates...
775              */
776             if ( MatchesFileSuffix(dp->d_name, MSGCAT) ||
777                  (strcmp (dp->d_name, COLLATE8) == 0 ) ||
778                  (strcmp (dp->d_name, MAILX)    == 0 ) ||
779                  (strcmp (dp->d_name, ELM)      == 0 ) ||
780                  (strcmp (dp->d_name, DOT)      == 0 ) ||
781                  (strcmp (dp->d_name, DOTDOT)   == 0 ) )
782               continue;
783
784
785             /*
786              *  check to see if this is the locale file...
787              */
788             if ( (strcmp(dp->d_name, LOCALEOLD) == 0 ) ||
789                  (strcmp(dp->d_name, LOCALE)    == 0 ) )
790             {
791                 char *p, *s;
792
793                 /*
794                  *  Convert directory name to language name...
795                  */
796                 if ( (p = strstr(dirname, DEF_NLS_DIR)) != NULL )
797                 {
798                     p += strlen(DEF_NLS_DIR);
799                     if ( *p == '/' )
800                       p++;
801
802                     s = p;
803                     while ( (p = strchr(s,'/')) != NULL )
804                       *p = '.';
805
806                     /*
807                      *  append to global list of languages...
808                      */
809                     if ((int) (strlen(languageList)+strlen(s)+2) < LANGLISTSIZE)
810                     {
811                         strcat(languageList, " ");
812                         strcat(languageList, s);
813                     }
814                 }
815
816                 continue;
817             }
818         
819             /*
820              *  if this file is a directory, scan it also...
821              */
822             strcpy(buf, dirname);
823             strcat(buf, "/");
824             strcat(buf, dp->d_name);
825
826             if  (stat(buf, &statb) == 0  &&  S_ISDIR(statb.st_mode))
827               ScanNLSDir(buf);
828         }
829
830         closedir(dirp);
831     }
832 }
833
834 #else /* !_AIX && !hpV4 */
835 /*
836  * Scan for installed locales on generic platform
837  */
838 {
839     DIR *dirp;
840     struct dirent *dp;
841     char* locale; 
842     char locale_path[MAXPATHLEN];
843     struct stat locale_stat;
844     int retval;
845
846     /* 
847      * To determin the fully installed locale list, check several locations.
848      */
849     if(NULL != (dirp = opendir(dirname)))
850     {
851         while((dp = readdir(dirp)) != NULL)
852         {
853             locale = dp->d_name;
854
855             if ( (strcmp(dp->d_name, ".") == 0) ||
856                  (strcmp(dp->d_name, "..") == 0) )
857               continue;
858
859             if (locale[0] != '.' &&
860                 LANGLISTSIZE > (int) (strlen(languageList)+strlen(locale)+2));
861             {
862                 (void) sprintf(locale_path, "%s/%s", dirname, locale);
863                 retval = stat(locale_path, &locale_stat);
864
865                 if (0 == retval && S_ISDIR(locale_stat.st_mode))
866                 {
867                     strcat(languageList, " ");
868                     strcat(languageList, locale);
869                 }
870             }
871         }
872         closedir(dirp);
873     }
874 }
875
876 #endif
877
878 #endif /* ENABLE_DYNAMIC_LANGLIST */
879
880 #ifdef _AIX
881 #define ENVFILE "/etc/environment"
882
883 /* Refer to the LANG environment variable, first.
884  * Or, search a line which includes "LANG=XX_XX" in /etc/environment.
885  * If succeeded, set the value to d->language.
886  */
887 void
888 SetDefaultLanguage(struct display *d)
889 {
890     FILE *file;
891     char lineBuf[160];
892     int n;
893     char *p;
894     char *lang = NULL;
895
896     if((lang = getenv( "LANG" )) == NULL ) {
897         if((file = fopen(ENVFILE, "r")) != NULL) {
898             while(fgets(lineBuf, sizeof(lineBuf) - 1, file)) {
899                 n = strlen(lineBuf);
900                 if(n > 1 && lineBuf[0] != '#') {
901                     if(lineBuf[n - 1] == '\n')
902                         lineBuf[n - 1] = '\0';
903                     if((p = strstr(lineBuf, "LANG=")) != NULL) {
904                         p += 5;
905                         if(strlen(p) == 5 && p[2] == '_') {
906                             lang = p;
907                             break;
908                         }
909                     }
910                 }
911             }
912             fclose(file);
913         }
914     }
915     if(lang != NULL && strlen(lang) > 0) {
916     /*
917      * If LANG is set for hft, we need to change it for X.
918      * Currently there are four hft LANG variables.
919      */
920         d->language = (char *)malloc(strlen(lang)+1);
921         if(strcmp(lang, "En_JP") == 0)
922             strcpy(d->language, "Ja_JP");
923         else if(strcmp(lang, "en_JP") == 0)
924             strcpy(d->language, "ja_JP");
925         else if(strcmp(lang, "en_KR") == 0)
926             strcpy(d->language, "ko_KR");
927         else if(strcmp(lang, "en_TW") == 0)
928             strcpy(d->language, "zh_TW");
929         else
930             strcpy(d->language, lang);
931     }
932 }
933 #endif /* _AIX */
934
935
936 char **
937 setLang( struct display *d, char **env , char *langptr)
938 {
939     char  langlist[LANGLISTSIZE];
940     int   s = 0;
941     char *element = NULL;
942     int   set_def_lang = FALSE;
943  
944  
945     if (NULL != langptr)
946       Debug("setLang():  langlist = %s\n", langptr);
947     else
948       Debug("setLang():  langlist = NULL\n");
949
950     if (langptr)
951       snprintf(langlist, sizeof(langlist), "%s", langptr);
952     else
953       snprintf(langlist, sizeof(langlist), "%s", getEnv(env, "LANGLIST"));
954
955     if (strlen(langlist) > 0) {
956         element = strtok(langlist, DELIM);
957         while(element) {
958             set_def_lang = FALSE;
959             if (strcmp(element,d->language) == 0){
960                 env = setEnv(env, "LANG",  d->language);
961                 break;
962             }
963             else
964               set_def_lang = TRUE;
965  
966             s += strlen(element) +1;
967             element = strtok(langlist+s, DELIM);
968         }
969     } else
970       set_def_lang = TRUE;
971  
972     if (set_def_lang) {
973         env = setEnv(env, "LANG", "C");
974         d->language = strdup("C");
975     }
976     return env;
977 }
978
979 static char localHostbuf[256];
980 static int  gotLocalHostname;
981
982 char *
983 localHostname (void)
984 {
985     if (!gotLocalHostname)
986     {
987         XmuGetHostname (localHostbuf, sizeof (localHostbuf) - 1);
988         gotLocalHostname = 1;
989     }
990     return localHostbuf;
991 }
992