2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /* (c) Copyright 1997 The Open Group */
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. *
31 * xdm - display manager daemon
33 * $TOG: util.c /main/15 1998/04/06 13:22:20 mgreess $
35 * Copyright 1988 Massachusetts Institute of Technology
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.
47 * Author: Keith Packard, MIT X Consortium
53 * various utility routines
63 # include <sys/signal.h>
72 nl_catd nl_fd = (nl_catd)-1; /* message catalog file descriptor */
74 #if !defined(NL_CAT_LOCALE)
75 #define NL_CAT_LOCALE 0
78 #if !defined (ENABLE_DYNAMIC_LANGLIST)
79 #define LANGLISTSIZE 2048
80 char languageList[LANGLISTSIZE]; /* global list of languages */
81 #endif /* ENABLE_DYNAMIC_LANGLIST */
83 /***************************************************************************
85 * Local procedure declarations
87 ***************************************************************************/
89 static char * makeEnv(
93 static SIGVAL MakeLangAbort(
96 static int MatchesFileSuffix(const char *filename, const char *suffix);
98 static void ScanNLSDir(
101 /******** End Local Function Declarations ********/
104 /***************************************************************************
108 * read a string from the message catalog
109 ***************************************************************************/
112 ReadCatalog( int set_num, int msg_num, char *def_str )
114 static Bool alreadyopen = False;
117 if (alreadyopen == False)
119 char *curNlsPath, *newNlsPath;
125 * Desktop message catalogs are in DT directory, so append desktop
126 * search paths to current NLSPATH.
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"
133 curNlsPath = getenv("NLSPATH");
134 if (curNlsPath && strlen(curNlsPath) == 0)
142 * <length of NLS_PATH_STRING>
145 newNlsPathLen = 7 + 1 + strlen(NLS_PATH_STRING) + 1;
147 if (curNlsPath != NULL)
151 * <length of curNlsPath>
153 newNlsPathLen += (1 + strlen(curNlsPath));
156 newNlsPath = malloc(newNlsPathLen); /* placed in environ, do not free */
158 if (curNlsPath != NULL)
160 sprintf(newNlsPath, "NLSPATH=%s:%s", curNlsPath, NLS_PATH_STRING);
164 sprintf(newNlsPath, "NLSPATH=%s", NLS_PATH_STRING);
168 * Store new NLSPATH in environment. Note this memory cannot be freed
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'.
177 nl_fd = catopen("dtlogin", NL_CAT_LOCALE);
180 s = catgets(nl_fd,set_num,msg_num,def_str);
182 return((unsigned char *)s);
189 Debug (" %s\n", *e++);
193 makeEnv( char *name, char *value )
197 result = malloc ((unsigned) (strlen (name) + strlen (value) + 2));
200 ReadCatalog(MC_LOG_SET,MC_LOG_MAKEENV,MC_DEF_LOG_MAKEENV));
205 sprintf (result, "%s=%s", name, value);
208 sprintf (result, "%s", name);
215 getEnv( char **e, char *name )
217 int l = strlen (name);
220 if ((int) strlen (*e) > l &&
221 !strncmp (*e, name, l) &&
231 setEnv( char **e, char *name, char *value )
239 newe = makeEnv (name, value);
241 LogOutOfMem(ReadCatalog(MC_LOG_SET,MC_LOG_SETENV,MC_DEF_LOG_SETENV));
245 for (old = e; *old; old++)
246 if ((int) strlen (*old) > l &&
247 !strncmp (*old, name, l) &&
258 realloc((char *) e, (unsigned) ((envsize + 2) * sizeof (char *)));
261 new = (char **) malloc (2 * sizeof (char *));
264 LogOutOfMem(ReadCatalog(MC_LOG_SET,MC_LOG_SETENV,MC_DEF_LOG_SETENV));
280 for (e = env; *e; e++)
286 # define isblank(c) ((c) == ' ' || c == '\t')
289 parseArgs( char **argv, char *string )
296 while (argv && argv[i])
299 argv = (char **) malloc (sizeof (char *));
301 LogOutOfMem(ReadCatalog(
302 MC_LOG_SET,MC_LOG_PARSEARGS,MC_DEF_LOG_PARSEARGS));
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,
316 MC_DEF_LOG_PARSEARGS));
318 free ((char *) argv);
323 argv[i] = strncpy (save, word, string-word);
324 argv[i][string-word] = '\0';
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.
347 #if defined (SYSV) || defined (SVR4) || defined(__linux__)
350 setpgrp (0, getpid ());
354 (void) signal (SIGCHLD, SIG_DFL);
356 (void) signal (SIGTERM, SIG_DFL);
357 (void) signal (SIGPIPE, SIG_DFL);
358 (void) signal (SIGALRM, SIG_DFL);
359 (void) signal (SIGHUP, SIG_DFL);
364 parseEnv( char **e, char *string )
367 char *s1, *s2, *t1, *t2;
369 s1 = s2 = strdup(string);
371 while ((t1 = strtok(s1," \t")) != NULL ) {
372 if ( (t2 = strchr(t1,'=')) != NULL ) {
374 e = setEnv(e, t1, t2);
384 /*************************************<->*************************************
386 * void SetHourGlassCursor
391 * sets the window cursor to an hourglass
405 * None. (None doesn't count as a comment)
407 *************************************<->***********************************/
410 SetHourGlassCursor( Display *dpy, Window w )
414 XUndefineCursor(dpy, w);
416 cursor = _DtGetHourGlassCursor(dpy);
418 XDefineCursor(dpy, w, cursor);
419 XFreeCursor(dpy, cursor);
423 #if !defined (ENABLE_DYNAMIC_LANGLIST)
424 /***************************************************************************
428 * Generate the list of languages installed on the host.
429 * Result is stored the global array "languageList"
431 ***************************************************************************/
433 #define DELIM " \t" /* delimiters in language list */
435 static jmp_buf langJump;
438 MakeLangAbort( int arg )
441 longjmp (langJump, 1);
449 char *lang[500]; /* sort list for languages */
450 int nlang; /* total number of languages */
455 * build language list from set of languages installed on the host...
456 * Wrap a timer around it so it doesn't hang things up too long.
457 * langListTimeout resource by default is 30 seconds to scan NLS dir.
463 signal (SIGALRM, MakeLangAbort);
464 alarm ((unsigned) langListTimeout);
466 if (!setjmp (langJump)) {
467 ScanNLSDir(DEF_NLS_DIR);
470 LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SCAN,MC_DEF_LOG_NO_SCAN),
471 DEF_NLS_DIR, langListTimeout);
475 signal (SIGALRM, SIG_DFL);
479 * sort the list to eliminate duplicates and replace in global array...
482 p = savelist = strdup(languageList);
485 while ( (s = strtok(p, DELIM)) != NULL ) {
494 for (i = nlang; i > 0 && strcmp(s,lang[i-1]) < 0; i--);
496 if (i==0 || strcmp(s,lang[i-1]) != 0 ) {
497 for (j = nlang; j > i; j--)
511 for ( i = 0; i < nlang; i++) {
522 MatchesFileSuffix(const char *filename, const char *suffix)
525 #if defined(_AIX) || defined(SVR4) || defined(__linux__) || defined(CSRG_BASED)
529 * The assumption here is that the use of strrstr is
530 * to determine if "dp->d_name" ends in ".cat".
532 if (strlen(filename) >= strlen(suffix)) {
533 different = strcmp(filename + (strlen(filename) - strlen (suffix)), suffix);
536 return (different == 0);
538 return (strrstr(filename, suffix) != NULL);
542 /***************************************************************************
546 * Scan a directory structure to see if it contains an installed language.
547 * If so, the name of the language is appended to a global list of languages.
549 * Scan method and scan directory will vary by platform.
551 ***************************************************************************/
555 ScanNLSDir(char *dirname)
559 * Search installed locale names for AIX 3.2.5
565 /* Search valid locales which are locale database files in
567 * File name is "??_??" which can be used as LANG variable.
569 if((dirp = opendir(dirname)) != NULL)
571 while((dp = readdir(dirp)) != NULL)
573 if(strlen(dp->d_name) == 5 && dp->d_name[2] == '_')
575 if((int) strlen(languageList) + 7 < LANGLISTSIZE )
577 strcat(languageList, " ");
578 strcat(languageList, dp->d_name);
588 #define LOCALE "locale.inf"
589 #define LOCALEOLD "locale.def"
590 #define COLLATE8 "collate8"
591 #define MAILX "mailx"
593 #define MSGCAT ".cat"
598 * Scan for installed locales on HP platform.
601 /***************************************************************************
602 * Scan supplied NLS directory structure to see if it contains an
603 * installed language. If so, the name of the language is appended
604 * to a global list of languages.
606 * This routine is recursively called as a directory structure is
609 *************************************************************************/
618 * Scan input directory, looking for a LOCALE file. If a sub-directory
619 * is found, recurse down into it...
621 if ( (dirp = opendir(dirname)) != NULL )
623 while ( (dp = readdir(dirp)) != NULL )
626 * ignore files that are known not to be candidates...
628 if ( MatchesFileSuffix(dp->d_name, MSGCAT) ||
629 (strcmp (dp->d_name, COLLATE8) == 0 ) ||
630 (strcmp (dp->d_name, MAILX) == 0 ) ||
631 (strcmp (dp->d_name, ELM) == 0 ) ||
632 (strcmp (dp->d_name, DOT) == 0 ) ||
633 (strcmp (dp->d_name, DOTDOT) == 0 ) )
638 * check to see if this is the locale file...
640 if ( (strcmp(dp->d_name, LOCALEOLD) == 0 ) ||
641 (strcmp(dp->d_name, LOCALE) == 0 ) )
646 * Convert directory name to language name...
648 if ( (p = strstr(dirname, DEF_NLS_DIR)) != NULL )
650 p += strlen(DEF_NLS_DIR);
655 while ( (p = strchr(s,'/')) != NULL )
659 * append to global list of languages...
661 if ((int) (strlen(languageList)+strlen(s)+2) < LANGLISTSIZE)
663 strcat(languageList, " ");
664 strcat(languageList, s);
672 * if this file is a directory, scan it also...
674 strcpy(buf, dirname);
676 strcat(buf, dp->d_name);
678 if (stat(buf, &statb) == 0 && S_ISDIR(statb.st_mode))
686 #else /* !_AIX && !hpV4 */
688 * Scan for installed locales on generic platform
694 char locale_path[MAXPATHLEN];
695 struct stat locale_stat;
699 * To determin the fully installed locale list, check several locations.
701 if(NULL != (dirp = opendir(dirname)))
703 while((dp = readdir(dirp)) != NULL)
707 if ( (strcmp(dp->d_name, ".") == 0) ||
708 (strcmp(dp->d_name, "..") == 0) )
711 if (locale[0] != '.' &&
712 LANGLISTSIZE > (int) (strlen(languageList)+strlen(locale)+2));
714 (void) sprintf(locale_path, "%s/%s", dirname, locale);
715 retval = stat(locale_path, &locale_stat);
717 if (0 == retval && S_ISDIR(locale_stat.st_mode))
719 strcat(languageList, " ");
720 strcat(languageList, locale);
730 #endif /* ENABLE_DYNAMIC_LANGLIST */
733 #define ENVFILE "/etc/environment"
735 /* Refer to the LANG environment variable, first.
736 * Or, search a line which includes "LANG=XX_XX" in /etc/environment.
737 * If succeeded, set the value to d->language.
740 SetDefaultLanguage(struct display *d)
748 if((lang = getenv( "LANG" )) == NULL ) {
749 if((file = fopen(ENVFILE, "r")) != NULL) {
750 while(fgets(lineBuf, sizeof(lineBuf) - 1, file)) {
752 if(n > 1 && lineBuf[0] != '#') {
753 if(lineBuf[n - 1] == '\n')
754 lineBuf[n - 1] = '\0';
755 if((p = strstr(lineBuf, "LANG=")) != NULL) {
757 if(strlen(p) == 5 && p[2] == '_') {
767 if(lang != NULL && strlen(lang) > 0) {
769 * If LANG is set for hft, we need to change it for X.
770 * Currently there are four hft LANG variables.
772 d->language = (char *)malloc(strlen(lang)+1);
773 if(strcmp(lang, "En_JP") == 0)
774 strcpy(d->language, "Ja_JP");
775 else if(strcmp(lang, "en_JP") == 0)
776 strcpy(d->language, "ja_JP");
777 else if(strcmp(lang, "en_KR") == 0)
778 strcpy(d->language, "ko_KR");
779 else if(strcmp(lang, "en_TW") == 0)
780 strcpy(d->language, "zh_TW");
782 strcpy(d->language, lang);
789 setLang( struct display *d, char **env , char *langptr)
791 char langlist[LANGLISTSIZE];
793 char *element = NULL;
794 int set_def_lang = FALSE;
798 Debug("setLang(): langlist = %s\n", langptr);
800 Debug("setLang(): langlist = NULL\n");
803 snprintf(langlist, sizeof(langlist), "%s", langptr);
805 snprintf(langlist, sizeof(langlist), "%s", getEnv(env, "LANGLIST"));
807 if (strlen(langlist) > 0) {
808 element = strtok(langlist, DELIM);
810 set_def_lang = FALSE;
811 if (strcmp(element,d->language) == 0){
812 env = setEnv(env, "LANG", d->language);
818 s += strlen(element) +1;
819 element = strtok(langlist+s, DELIM);
825 env = setEnv(env, "LANG", "C");
826 d->language = strdup("C");
831 static char localHostbuf[256];
832 static int gotLocalHostname;
837 if (!gotLocalHostname)
839 XmuGetHostname (localHostbuf, sizeof (localHostbuf) - 1);
840 gotLocalHostname = 1;