lcFile.c revision 3b4ba46c
11ab64890Smrg/* 21ab64890Smrg * 31ab64890Smrg * Copyright IBM Corporation 1993 41ab64890Smrg * 51ab64890Smrg * All Rights Reserved 61ab64890Smrg * 71ab64890Smrg * License to use, copy, modify, and distribute this software and its 81ab64890Smrg * documentation for any purpose and without fee is hereby granted, 91ab64890Smrg * provided that the above copyright notice appear in all copies and that 101ab64890Smrg * both that copyright notice and this permission notice appear in 111ab64890Smrg * supporting documentation, and that the name of IBM not be 121ab64890Smrg * used in advertising or publicity pertaining to distribution of the 131ab64890Smrg * software without specific, written prior permission. 141ab64890Smrg * 151ab64890Smrg * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 1661b2299dSmrg * ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS, AND 171ab64890Smrg * NONINFRINGEMENT OF THIRD PARTY RIGHTS, IN NO EVENT SHALL 181ab64890Smrg * IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 191ab64890Smrg * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 201ab64890Smrg * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 211ab64890Smrg * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 221ab64890Smrg * SOFTWARE. 231ab64890Smrg * 241ab64890Smrg*/ 251ab64890Smrg 261ab64890Smrg#ifdef HAVE_CONFIG_H 271ab64890Smrg#include <config.h> 281ab64890Smrg#endif 291ab64890Smrg#include <stdlib.h> 301ab64890Smrg#include <stdio.h> 311ab64890Smrg#include <ctype.h> 321ab64890Smrg#include "Xlibint.h" 331ab64890Smrg#include "XlcPubI.h" 341ab64890Smrg#include <X11/Xos.h> 351ab64890Smrg#include <unistd.h> 361ab64890Smrg 371ab64890Smrg/************************************************************************/ 381ab64890Smrg 39eb411b4bSmrg#ifndef HAVE_SETEUID 401ab64890Smrg# define seteuid setuid 411ab64890Smrg#endif 421ab64890Smrg#define iscomment(ch) ((ch) == '#' || (ch) == '\0') 431ab64890Smrg#if defined(WIN32) 441ab64890Smrg#define isreadable(f) (_XAccessFile(f)) 451ab64890Smrg#else 461ab64890Smrg#define isreadable(f) ((access((f), R_OK) != -1) ? 1 : 0) 471ab64890Smrg#endif 481ab64890Smrg 491ab64890Smrg#define LC_PATHDELIM ':' 501ab64890Smrg 511ab64890Smrg#define XLC_BUFSIZE 256 521ab64890Smrg 53eb411b4bSmrg#include "pathmax.h" 541ab64890Smrg 551ab64890Smrg#define NUM_LOCALEDIR 64 561ab64890Smrg 571ab64890Smrg/* Splits a NUL terminated line into constituents, at colons and newline 581ab64890Smrg characters. Leading whitespace is removed from constituents. The 591ab64890Smrg constituents are stored at argv[0..argsize-1]. The number of stored 601ab64890Smrg constituents (<= argsize) is returned. The line is destructively 611ab64890Smrg modified. */ 621ab64890Smrgstatic int 631ab64890Smrgparse_line( 641ab64890Smrg char *line, 651ab64890Smrg char **argv, 661ab64890Smrg int argsize) 671ab64890Smrg{ 681ab64890Smrg int argc = 0; 691ab64890Smrg char *p = line; 701ab64890Smrg 711ab64890Smrg while (argc < argsize) { 721ab64890Smrg while (isspace(*p)) { 731ab64890Smrg ++p; 741ab64890Smrg } 751ab64890Smrg if (*p == '\0') { 761ab64890Smrg break; 771ab64890Smrg } 781ab64890Smrg argv[argc++] = p; 791ab64890Smrg while (*p != ':' && *p != '\n' && *p != '\0') { 801ab64890Smrg ++p; 811ab64890Smrg } 821ab64890Smrg if (*p == '\0') { 831ab64890Smrg break; 841ab64890Smrg } 851ab64890Smrg *p++ = '\0'; 861ab64890Smrg } 871ab64890Smrg 881ab64890Smrg return argc; 891ab64890Smrg} 901ab64890Smrg 91ebe525bcSmrg#ifdef WIN32 921ab64890Smrg/* this is parse_line but skips drive letters at the beginning of the entry */ 931ab64890Smrgstatic int 941ab64890Smrgparse_line1( 951ab64890Smrg char *line, 961ab64890Smrg char **argv, 971ab64890Smrg int argsize) 981ab64890Smrg{ 991ab64890Smrg int argc = 0; 1001ab64890Smrg char *p = line; 1011ab64890Smrg 1021ab64890Smrg while (argc < argsize) { 1031ab64890Smrg while (isspace(*p)) { 1041ab64890Smrg ++p; 1051ab64890Smrg } 1061ab64890Smrg if (*p == '\0') { 1071ab64890Smrg break; 1081ab64890Smrg } 1091ab64890Smrg argv[argc++] = p; 1101ab64890Smrg if (isalpha(*p) && p[1] == ':') { 1111ab64890Smrg p+= 2; /* skip drive letters */ 1121ab64890Smrg } 1131ab64890Smrg while (*p != ':' && *p != '\n' && *p != '\0') { 1141ab64890Smrg ++p; 1151ab64890Smrg } 1161ab64890Smrg if (*p == '\0') { 1171ab64890Smrg break; 1181ab64890Smrg } 1191ab64890Smrg *p++ = '\0'; 1201ab64890Smrg } 1211ab64890Smrg 1221ab64890Smrg return argc; 1231ab64890Smrg} 124ebe525bcSmrg#endif /* WIN32 */ 1251ab64890Smrg 1261ab64890Smrg/* Splits a colon separated list of directories, and returns the constituent 1271ab64890Smrg paths (without trailing slash). At most argsize constituents are stored 1281ab64890Smrg at argv[0..argsize-1]. The number of stored constituents is returned. */ 1291ab64890Smrgstatic int 1301ab64890Smrg_XlcParsePath( 1311ab64890Smrg char *path, 1321ab64890Smrg char **argv, 1331ab64890Smrg int argsize) 1341ab64890Smrg{ 1351ab64890Smrg char *p = path; 1361ab64890Smrg int n, i; 1371ab64890Smrg 138ebe525bcSmrg#ifndef WIN32 1391ab64890Smrg n = parse_line(path, argv, argsize); 1401ab64890Smrg#else 1411ab64890Smrg n = parse_line1(path, argv, argsize); 1421ab64890Smrg#endif 1431ab64890Smrg for (i = 0; i < n; ++i) { 1441ab64890Smrg int len; 1451ab64890Smrg p = argv[i]; 1469c019ec5Smaya len = (int) strlen(p); 1471ab64890Smrg if (len > 0 && p[len - 1] == '/') { 1481ab64890Smrg /* eliminate trailing slash */ 1491ab64890Smrg p[len - 1] = '\0'; 1501ab64890Smrg } 1511ab64890Smrg } 1521ab64890Smrg return n; 1531ab64890Smrg} 1541ab64890Smrg 1551ab64890Smrg#ifndef XLOCALEDIR 1561ab64890Smrg#define XLOCALEDIR "/usr/lib/X11/locale" 1571ab64890Smrg#endif 1581ab64890Smrg 159b4ee4795Smrgvoid 1601ab64890Smrgxlocaledir( 1611ab64890Smrg char *buf, 1621ab64890Smrg int buf_len) 1631ab64890Smrg{ 1641ab64890Smrg char *p = buf; 1651ab64890Smrg int len = 0; 1661ab64890Smrg 1671ab64890Smrg#ifndef NO_XLOCALEDIR 1681ab64890Smrg char *dir; 1691ab64890Smrg int priv = 1; 1701ab64890Smrg 1711ab64890Smrg dir = getenv("XLOCALEDIR"); 1721ab64890Smrg 1731ab64890Smrg if (dir) { 1741ab64890Smrg#ifndef WIN32 1751ab64890Smrg /* 1769c019ec5Smaya * Only use the user-supplied path if the process isn't privileged. 1771ab64890Smrg */ 1781ab64890Smrg if (getuid() == geteuid() && getgid() == getegid()) { 1791ab64890Smrg#if defined(HASSETUGID) 1801ab64890Smrg priv = issetugid(); 1811ab64890Smrg#elif defined(HASGETRESUID) 1821ab64890Smrg { 1831ab64890Smrg uid_t ruid, euid, suid; 1841ab64890Smrg gid_t rgid, egid, sgid; 1851ab64890Smrg if ((getresuid(&ruid, &euid, &suid) == 0) && 1861ab64890Smrg (getresgid(&rgid, &egid, &sgid) == 0)) 1871ab64890Smrg priv = (euid != suid) || (egid != sgid); 1881ab64890Smrg } 1891ab64890Smrg#else 1901ab64890Smrg /* 1919c019ec5Smaya * If there are saved ID's the process might still be privileged 1921ab64890Smrg * even though the above test succeeded. If issetugid() and 1931ab64890Smrg * getresgid() aren't available, test this by trying to set 1941ab64890Smrg * euid to 0. 1951ab64890Smrg * 1961ab64890Smrg * Note: this only protects setuid-root clients. It doesn't 1971ab64890Smrg * protect other setuid or any setgid clients. If this tradeoff 19814db512dSmrg * isn't acceptable, run configure with --disable-xlocaledir . 1991ab64890Smrg */ 2001ab64890Smrg unsigned int oldeuid; 2011ab64890Smrg oldeuid = geteuid(); 2021ab64890Smrg if (seteuid(0) != 0) { 2031ab64890Smrg priv = 0; 2041ab64890Smrg } else { 2051ab64890Smrg if (seteuid(oldeuid) == -1) { 2069c019ec5Smaya /* XXX ouch, couldn't get back to original uid 2071ab64890Smrg what can we do ??? */ 2081ab64890Smrg _exit(127); 2091ab64890Smrg } 2101ab64890Smrg priv = 1; 2111ab64890Smrg } 2121ab64890Smrg#endif 2131ab64890Smrg } 2141ab64890Smrg#else 2151ab64890Smrg priv = 0; 2161ab64890Smrg#endif 2171ab64890Smrg if (!priv) { 2189c019ec5Smaya len = (int) strlen(dir); 2199c019ec5Smaya strncpy(p, dir, (size_t) buf_len); 2201ab64890Smrg if (len < buf_len) { 2211ab64890Smrg p[len++] = LC_PATHDELIM; 2221ab64890Smrg p += len; 2231ab64890Smrg } 2241ab64890Smrg } 2251ab64890Smrg } 2261ab64890Smrg#endif /* NO_XLOCALEDIR */ 2271ab64890Smrg 2281ab64890Smrg if (len < buf_len) 2299c019ec5Smaya strncpy(p, XLOCALEDIR, (size_t) (buf_len - len)); 2301ab64890Smrg buf[buf_len-1] = '\0'; 2311ab64890Smrg} 2321ab64890Smrg 2331ab64890Smrgstatic void 2341ab64890Smrgxlocalelibdir( 2351ab64890Smrg char *buf, 2361ab64890Smrg int buf_len) 2371ab64890Smrg{ 2381ab64890Smrg char *p = buf; 2391ab64890Smrg int len = 0; 2401ab64890Smrg 2411ab64890Smrg#ifndef NO_XLOCALEDIR 2421ab64890Smrg char *dir; 2431ab64890Smrg int priv = 1; 2441ab64890Smrg 2451ab64890Smrg dir = getenv("XLOCALELIBDIR"); 2461ab64890Smrg 2471ab64890Smrg if (dir) { 2481ab64890Smrg#ifndef WIN32 2491ab64890Smrg /* 2509c019ec5Smaya * Only use the user-supplied path if the process isn't privileged. 2511ab64890Smrg */ 2521ab64890Smrg if (getuid() == geteuid() && getgid() == getegid()) { 2531ab64890Smrg#if defined(HASSETUGID) 2541ab64890Smrg priv = issetugid(); 2551ab64890Smrg#elif defined(HASGETRESUID) 2561ab64890Smrg { 2571ab64890Smrg uid_t ruid, euid, suid; 2581ab64890Smrg gid_t rgid, egid, sgid; 2591ab64890Smrg if ((getresuid(&ruid, &euid, &suid) == 0) && 2601ab64890Smrg (getresgid(&rgid, &egid, &sgid) == 0)) 2611ab64890Smrg priv = (euid != suid) || (egid != sgid); 2621ab64890Smrg } 2631ab64890Smrg#else 2641ab64890Smrg /* 2659c019ec5Smaya * If there are saved ID's the process might still be privileged 2661ab64890Smrg * even though the above test succeeded. If issetugid() and 2671ab64890Smrg * getresgid() aren't available, test this by trying to set 2681ab64890Smrg * euid to 0. 2691ab64890Smrg * 2701ab64890Smrg * Note: this only protects setuid-root clients. It doesn't 2711ab64890Smrg * protect other setuid or any setgid clients. If this tradeoff 27214db512dSmrg * isn't acceptable, run configure with --disable-xlocaledir . 2731ab64890Smrg */ 2741ab64890Smrg unsigned int oldeuid; 2751ab64890Smrg oldeuid = geteuid(); 2761ab64890Smrg if (seteuid(0) != 0) { 2771ab64890Smrg priv = 0; 2781ab64890Smrg } else { 2791ab64890Smrg if (seteuid(oldeuid) == -1) { 2809c019ec5Smaya /* XXX ouch, couldn't get back to original uid 2811ab64890Smrg what can we do ??? */ 2821ab64890Smrg _exit(127); 2831ab64890Smrg } 2841ab64890Smrg priv = 1; 2851ab64890Smrg } 2861ab64890Smrg#endif 2871ab64890Smrg } 2881ab64890Smrg#else 2891ab64890Smrg priv = 0; 2901ab64890Smrg#endif 2911ab64890Smrg if (!priv) { 2929c019ec5Smaya len = (int) strlen(dir); 2939c019ec5Smaya strncpy(p, dir, (size_t) buf_len); 2941ab64890Smrg if (len < buf_len) { 2951ab64890Smrg p[len++] = LC_PATHDELIM; 2961ab64890Smrg p += len; 2971ab64890Smrg } 2981ab64890Smrg } 2991ab64890Smrg } 3001ab64890Smrg#endif /* NO_XLOCALEDIR */ 3011ab64890Smrg 3021ab64890Smrg if (len < buf_len) 3039c019ec5Smaya strncpy(p, XLOCALELIBDIR, (size_t) (buf_len - len)); 3041ab64890Smrg buf[buf_len-1] = '\0'; 3051ab64890Smrg} 3061ab64890Smrg 3071ab64890Smrg/* Mapping direction */ 3081ab64890Smrgtypedef enum { 3091ab64890Smrg LtoR, /* Map first field to second field */ 3101ab64890Smrg RtoL /* Map second field to first field */ 3111ab64890Smrg} MapDirection; 3121ab64890Smrg 3131ab64890Smrgstatic char * 3141ab64890Smrgresolve_name( 3151ab64890Smrg const char *lc_name, 3161ab64890Smrg char *file_name, 3171ab64890Smrg MapDirection direction) 3181ab64890Smrg{ 3191ab64890Smrg FILE *fp; 3201ab64890Smrg char buf[XLC_BUFSIZE], *name = NULL; 3211ab64890Smrg 3221ab64890Smrg fp = _XFopenFile (file_name, "r"); 3231ab64890Smrg if (fp == NULL) 3241ab64890Smrg return NULL; 3251ab64890Smrg 3261ab64890Smrg while (fgets(buf, XLC_BUFSIZE, fp) != NULL) { 3271ab64890Smrg char *p = buf; 3281ab64890Smrg int n; 3291ab64890Smrg char *args[2], *from, *to; 3301ab64890Smrg while (isspace(*p)) { 3311ab64890Smrg ++p; 3321ab64890Smrg } 3331ab64890Smrg if (iscomment(*p)) { 3341ab64890Smrg continue; 3351ab64890Smrg } 3361ab64890Smrg n = parse_line(p, args, 2); /* get first 2 fields */ 3371ab64890Smrg if (n != 2) { 3381ab64890Smrg continue; 3391ab64890Smrg } 3401ab64890Smrg if (direction == LtoR) { 3411ab64890Smrg from = args[0], to = args[1]; /* left to right */ 3421ab64890Smrg } else { 3431ab64890Smrg from = args[1], to = args[0]; /* right to left */ 3441ab64890Smrg } 3451ab64890Smrg if (! strcmp(from, lc_name)) { 3466cc2b21fSmrg name = strdup(to); 3471ab64890Smrg break; 3481ab64890Smrg } 3491ab64890Smrg } 3501ab64890Smrg fclose(fp); 3511ab64890Smrg return name; 3521ab64890Smrg} 3531ab64890Smrg 3541ab64890Smrg#define c_tolower(ch) ((ch) >= 'A' && (ch) <= 'Z' ? (ch) - 'A' + 'a' : (ch)) 3551ab64890Smrg 3561ab64890Smrgstatic char * 3571ab64890Smrglowercase( 3581ab64890Smrg char *dst, 3591ab64890Smrg const char *src) 3601ab64890Smrg{ 3611ab64890Smrg const char *s; 3621ab64890Smrg char *t; 3631ab64890Smrg 3641ab64890Smrg for (s = src, t = dst; *s; ++s, ++t) 3659c019ec5Smaya *t = (char) c_tolower(*s); 3661ab64890Smrg *t = '\0'; 3671ab64890Smrg return dst; 3681ab64890Smrg} 3691ab64890Smrg 3701ab64890Smrg/* 3711ab64890Smrg * normalize_lcname(): remove any '_' and '-' and convert any character 3721ab64890Smrg * to lower case after the <language>_<territory> part. If result is identical 3731ab64890Smrg * to argument, free result and 3741ab64890Smrg * return NULL. 3751ab64890Smrg */ 3761ab64890Smrgstatic char * 3771ab64890Smrgnormalize_lcname (const char *name) 3781ab64890Smrg{ 3791ab64890Smrg char *p, *ret; 3801ab64890Smrg const char *tmp = name; 38161b2299dSmrg 3821ab64890Smrg p = ret = Xmalloc(strlen(name) + 1); 3831ab64890Smrg if (!p) 3841ab64890Smrg return NULL; 38561b2299dSmrg 3861ab64890Smrg if (tmp) { 3871ab64890Smrg while (*tmp && *tmp != '.' && *tmp != '@') 3881ab64890Smrg *p++ = *tmp++; 3891ab64890Smrg while (*tmp) { 3901ab64890Smrg if (*tmp != '-') 3919c019ec5Smaya *p++ = (char) c_tolower(*tmp); 3921ab64890Smrg tmp++; 3931ab64890Smrg } 3941ab64890Smrg } 3951ab64890Smrg *p = '\0'; 3961ab64890Smrg 3971ab64890Smrg if (strcmp(ret, name) == 0) { 3981ab64890Smrg Xfree(ret); 3991ab64890Smrg return NULL; 4001ab64890Smrg } 4011ab64890Smrg 4021ab64890Smrg return ret; 4031ab64890Smrg} 4041ab64890Smrg 4051ab64890Smrg/************************************************************************/ 4061ab64890Smrgchar * 4071ab64890Smrg_XlcFileName( 4081ab64890Smrg XLCd lcd, 4091ab64890Smrg const char *category) 4101ab64890Smrg{ 4111ab64890Smrg char *siname; 4121ab64890Smrg char cat[XLC_BUFSIZE], dir[XLC_BUFSIZE]; 4131ab64890Smrg int i, n; 4141ab64890Smrg char *args[NUM_LOCALEDIR]; 4151ab64890Smrg char *file_name = NULL; 4161ab64890Smrg 4171ab64890Smrg if (lcd == (XLCd)NULL) 4181ab64890Smrg return NULL; 4191ab64890Smrg 4201ab64890Smrg siname = XLC_PUBLIC(lcd, siname); 4211ab64890Smrg 42261b2299dSmrg if (category) 42361b2299dSmrg lowercase(cat, category); 42461b2299dSmrg else 42561b2299dSmrg cat[0] = '\0'; 4261ab64890Smrg xlocaledir(dir,XLC_BUFSIZE); 4271ab64890Smrg n = _XlcParsePath(dir, args, NUM_LOCALEDIR); 4281ab64890Smrg for (i = 0; i < n; ++i) { 4291ab64890Smrg char buf[PATH_MAX], *name; 4301ab64890Smrg 431818534a1Smrg if (args[i] == NULL) 432818534a1Smrg continue; 433818534a1Smrg 4341ab64890Smrg name = NULL; 435818534a1Smrg if (snprintf(buf, PATH_MAX, "%s/%s.dir", args[i], cat) < PATH_MAX) { 4361ab64890Smrg name = resolve_name(siname, buf, RtoL); 4371ab64890Smrg } 4381ab64890Smrg if (name == NULL) { 4391ab64890Smrg continue; 4401ab64890Smrg } 4411ab64890Smrg if (*name == '/') { 4421ab64890Smrg /* supposed to be absolute path name */ 4431ab64890Smrg file_name = name; 4441ab64890Smrg } else { 445818534a1Smrg if (snprintf(buf, PATH_MAX, "%s/%s", args[i], name) < PATH_MAX) 446818534a1Smrg file_name = strdup(buf); 447818534a1Smrg else 448818534a1Smrg file_name = NULL; 4491ab64890Smrg Xfree(name); 4501ab64890Smrg } 451818534a1Smrg if (file_name && isreadable(file_name)) { 4521ab64890Smrg break; 4531ab64890Smrg } 4541ab64890Smrg Xfree(file_name); 4551ab64890Smrg file_name = NULL; 4561ab64890Smrg /* Then, try with next dir */ 4571ab64890Smrg } 4581ab64890Smrg return file_name; 4591ab64890Smrg} 4601ab64890Smrg 4611ab64890Smrg/************************************************************************/ 4621ab64890Smrg#ifndef LOCALE_ALIAS 4631ab64890Smrg#define LOCALE_ALIAS "locale.alias" 4641ab64890Smrg#endif 4651ab64890Smrg 4661ab64890Smrgint 4671ab64890Smrg_XlcResolveLocaleName( 4681ab64890Smrg const char* lc_name, 4691ab64890Smrg XLCdPublicPart* pub) 4701ab64890Smrg{ 4711ab64890Smrg char dir[PATH_MAX], buf[PATH_MAX], *name = NULL; 4721ab64890Smrg char *dst; 4731ab64890Smrg int i, n, sinamelen; 4741ab64890Smrg char *args[NUM_LOCALEDIR]; 4751ab64890Smrg static const char locale_alias[] = LOCALE_ALIAS; 4761ab64890Smrg char *tmp_siname; 4771ab64890Smrg char *nlc_name = NULL; 4781ab64890Smrg 4791ab64890Smrg xlocaledir (dir, PATH_MAX); 4801ab64890Smrg n = _XlcParsePath(dir, args, NUM_LOCALEDIR); 4811ab64890Smrg for (i = 0; i < n; ++i) { 482818534a1Smrg if (args[i] == NULL) 483818534a1Smrg continue; 484818534a1Smrg 485818534a1Smrg if (snprintf (buf, PATH_MAX, "%s/%s", args[i], locale_alias) 486818534a1Smrg < PATH_MAX) { 4871ab64890Smrg name = resolve_name (lc_name, buf, LtoR); 4881ab64890Smrg if (!name) { 4891ab64890Smrg if (!nlc_name) 4901ab64890Smrg nlc_name = normalize_lcname(lc_name); 4911ab64890Smrg if (nlc_name) 4921ab64890Smrg name = resolve_name (nlc_name, buf, LtoR); 4931ab64890Smrg } 4941ab64890Smrg } 4951ab64890Smrg if (name != NULL) { 4961ab64890Smrg break; 4971ab64890Smrg } 4981ab64890Smrg } 4990f8248bfSmrg Xfree(nlc_name); 5001ab64890Smrg 5011ab64890Smrg if (name == NULL) { 5021ab64890Smrg /* vendor locale name == Xlocale name, no expansion of alias */ 5036cc2b21fSmrg pub->siname = strdup (lc_name); 5041ab64890Smrg } else { 5051ab64890Smrg pub->siname = name; 5061ab64890Smrg } 5071ab64890Smrg 5089c019ec5Smaya sinamelen = (int) strlen (pub->siname); 5091ab64890Smrg if (sinamelen == 1 && pub->siname[0] == 'C') { 5101ab64890Smrg pub->language = pub->siname; 5111ab64890Smrg pub->territory = pub->codeset = NULL; 5121ab64890Smrg return 1; 5131ab64890Smrg } 5141ab64890Smrg 51561b2299dSmrg /* 5161ab64890Smrg * pub->siname is in the format <lang>_<terr>.<codeset>, typical would 5171ab64890Smrg * be "en_US.ISO8859-1", "en_US.utf8", "ru_RU.KOI-8", or ja_JP.SJIS, 5181ab64890Smrg * although it could be ja.SJIS too. 5191ab64890Smrg */ 5201ab64890Smrg tmp_siname = Xrealloc (pub->siname, 2 * (sinamelen + 1)); 5211ab64890Smrg if (tmp_siname == NULL) { 5221ab64890Smrg return 0; 5231ab64890Smrg } 5241ab64890Smrg pub->siname = tmp_siname; 5251ab64890Smrg 5261ab64890Smrg /* language */ 5271ab64890Smrg dst = &pub->siname[sinamelen + 1]; 5281ab64890Smrg strcpy (dst, pub->siname); 5291ab64890Smrg pub->language = dst; 5301ab64890Smrg 5311ab64890Smrg /* territory */ 5321ab64890Smrg dst = strchr (dst, '_'); 5331ab64890Smrg if (dst) { 5341ab64890Smrg *dst = '\0'; 5351ab64890Smrg pub->territory = ++dst; 5361ab64890Smrg } else 5371ab64890Smrg dst = &pub->siname[sinamelen + 1]; 5381ab64890Smrg 5391ab64890Smrg /* codeset */ 5401ab64890Smrg dst = strchr (dst, '.'); 5411ab64890Smrg if (dst) { 5421ab64890Smrg *dst = '\0'; 5431ab64890Smrg pub->codeset = ++dst; 5441ab64890Smrg } 5451ab64890Smrg 5461ab64890Smrg return (pub->siname[0] != '\0') ? 1 : 0; 5471ab64890Smrg} 5481ab64890Smrg 5491ab64890Smrg/************************************************************************/ 5501ab64890Smrgint 55161b2299dSmrg_XlcResolveI18NPath(char *buf, int buf_len) 5521ab64890Smrg{ 5531ab64890Smrg if (buf != NULL) { 5541ab64890Smrg xlocaledir(buf, buf_len); 5551ab64890Smrg } 5561ab64890Smrg return 1; 5571ab64890Smrg} 5581ab64890Smrg 5591ab64890Smrgchar * 560818534a1Smrg_XlcLocaleDirName(char *dir_name, size_t dir_len, const char *lc_name) 5611ab64890Smrg{ 562818534a1Smrg char dir[PATH_MAX], buf[PATH_MAX]; 5631ab64890Smrg int i, n; 5641ab64890Smrg char *args[NUM_LOCALEDIR]; 5651ab64890Smrg static char locale_alias[] = LOCALE_ALIAS; 566818534a1Smrg char *target_name = NULL; 567818534a1Smrg char *target_dir = NULL; 5681ab64890Smrg char *nlc_name = NULL; 5691ab64890Smrg static char* last_dir_name = 0; 5701ab64890Smrg static size_t last_dir_len = 0; 5711ab64890Smrg static char* last_lc_name = 0; 5721ab64890Smrg 5731ab64890Smrg if (last_lc_name != 0 && strcmp (last_lc_name, lc_name) == 0 5741ab64890Smrg && dir_len >= last_dir_len) { 5751ab64890Smrg strcpy (dir_name, last_dir_name); 5761ab64890Smrg return dir_name; 5771ab64890Smrg } 5781ab64890Smrg 5791ab64890Smrg xlocaledir (dir, PATH_MAX); 580818534a1Smrg n = _XlcParsePath(dir, args, NUM_LOCALEDIR); 5811ab64890Smrg for (i = 0; i < n; ++i) { 582818534a1Smrg char *name = NULL; 58361b2299dSmrg 584818534a1Smrg if (args[i] == NULL) 585818534a1Smrg continue; 586818534a1Smrg 587818534a1Smrg if (snprintf (buf, PATH_MAX, "%s/%s", args[i], locale_alias) 588818534a1Smrg < PATH_MAX) { 5891ab64890Smrg name = resolve_name(lc_name, buf, LtoR); 5901ab64890Smrg if (!name) { 5911ab64890Smrg if (!nlc_name) 5921ab64890Smrg nlc_name = normalize_lcname(lc_name); 5931ab64890Smrg if (nlc_name) 5941ab64890Smrg name = resolve_name (nlc_name, buf, LtoR); 5951ab64890Smrg } 5961ab64890Smrg } 59761b2299dSmrg 5981ab64890Smrg /* look at locale.dir */ 59961b2299dSmrg 6001ab64890Smrg target_dir = args[i]; 601818534a1Smrg if (snprintf(buf, PATH_MAX, "%s/locale.dir", target_dir) < PATH_MAX) { 602818534a1Smrg /* If name is not an alias, use lc_name for locale.dir search */ 603818534a1Smrg target_name = resolve_name(name ? name : lc_name, buf, RtoL); 6041ab64890Smrg } 605818534a1Smrg Xfree(name); 606818534a1Smrg name = NULL; 6071ab64890Smrg if (target_name != NULL) { 6081ab64890Smrg char *p = 0; 6091ab64890Smrg if ((p = strstr(target_name, "/XLC_LOCALE"))) { 6101ab64890Smrg *p = '\0'; 6111ab64890Smrg break; 6121ab64890Smrg } 6131ab64890Smrg Xfree(target_name); 6141ab64890Smrg target_name = NULL; 6151ab64890Smrg } 6161ab64890Smrg } 6170f8248bfSmrg Xfree(nlc_name); 6181ab64890Smrg 619818534a1Smrg if (target_name == NULL) 6201ab64890Smrg /* vendor locale name == Xlocale name, no expansion of alias */ 621818534a1Smrg snprintf(dir_name, dir_len, "%s/%s", args[0], lc_name); 622818534a1Smrg else 623818534a1Smrg snprintf(dir_name, dir_len, "%s/%s", target_dir, target_name); 6240f8248bfSmrg 625818534a1Smrg Xfree(target_name); 6260f8248bfSmrg Xfree (last_dir_name); 6270f8248bfSmrg Xfree (last_lc_name); 6281ab64890Smrg 6293b4ba46cSmrg last_dir_name = strdup (dir_name); 6303b4ba46cSmrg last_dir_len = (last_dir_name != NULL) ? strlen (last_dir_name) + 1 : 0; 6313b4ba46cSmrg 6326cc2b21fSmrg last_lc_name = strdup (lc_name); 6331ab64890Smrg 6341ab64890Smrg return dir_name; 6351ab64890Smrg} 6361ab64890Smrg 6371ab64890Smrgchar * 638818534a1Smrg_XlcLocaleLibDirName(char *dir_name, size_t dir_len, const char *lc_name) 6391ab64890Smrg{ 640818534a1Smrg char dir[PATH_MAX], buf[PATH_MAX]; 6411ab64890Smrg int i, n; 6421ab64890Smrg char *args[NUM_LOCALEDIR]; 6431ab64890Smrg static char locale_alias[] = LOCALE_ALIAS; 644818534a1Smrg char *target_name = NULL; 645818534a1Smrg char *target_dir = NULL; 6461ab64890Smrg char *nlc_name = NULL; 6471ab64890Smrg static char* last_dir_name = 0; 6481ab64890Smrg static size_t last_dir_len = 0; 6491ab64890Smrg static char* last_lc_name = 0; 6501ab64890Smrg 6511ab64890Smrg if (last_lc_name != 0 && strcmp (last_lc_name, lc_name) == 0 6521ab64890Smrg && dir_len >= last_dir_len) { 6531ab64890Smrg strcpy (dir_name, last_dir_name); 6541ab64890Smrg return dir_name; 6551ab64890Smrg } 6561ab64890Smrg 6571ab64890Smrg xlocalelibdir (dir, PATH_MAX); 658818534a1Smrg n = _XlcParsePath(dir, args, NUM_LOCALEDIR); 6591ab64890Smrg for (i = 0; i < n; ++i) { 660818534a1Smrg char *name = NULL; 661818534a1Smrg 662818534a1Smrg if (args[i] == NULL) 663818534a1Smrg continue; 66461b2299dSmrg 665818534a1Smrg if (snprintf (buf, PATH_MAX, "%s/%s", args[i], locale_alias) 666818534a1Smrg < PATH_MAX) { 6671ab64890Smrg name = resolve_name(lc_name, buf, LtoR); 6681ab64890Smrg if (!name) { 6691ab64890Smrg if (!nlc_name) 6701ab64890Smrg nlc_name = normalize_lcname(lc_name); 6711ab64890Smrg if (nlc_name) 6721ab64890Smrg name = resolve_name (nlc_name, buf, LtoR); 6731ab64890Smrg } 6741ab64890Smrg } 67561b2299dSmrg 6761ab64890Smrg /* look at locale.dir */ 67761b2299dSmrg 6781ab64890Smrg target_dir = args[i]; 679818534a1Smrg if (snprintf(buf, PATH_MAX, "%s/locale.dir", target_dir) < PATH_MAX) { 680818534a1Smrg /* If name is not an alias, use lc_name for locale.dir search */ 681818534a1Smrg target_name = resolve_name(name ? name : lc_name, buf, RtoL); 6821ab64890Smrg } 683818534a1Smrg Xfree(name); 684818534a1Smrg name = NULL; 6851ab64890Smrg if (target_name != NULL) { 6861ab64890Smrg char *p = 0; 6871ab64890Smrg if ((p = strstr(target_name, "/XLC_LOCALE"))) { 6881ab64890Smrg *p = '\0'; 6891ab64890Smrg break; 6901ab64890Smrg } 6911ab64890Smrg Xfree(target_name); 6921ab64890Smrg target_name = NULL; 6931ab64890Smrg } 6941ab64890Smrg } 6950f8248bfSmrg Xfree(nlc_name); 6961ab64890Smrg 697818534a1Smrg if (target_name == NULL) 6981ab64890Smrg /* vendor locale name == Xlocale name, no expansion of alias */ 699818534a1Smrg snprintf(dir_name, dir_len, "%s/%s", args[0], lc_name); 700818534a1Smrg else 701818534a1Smrg snprintf(dir_name, dir_len, "%s/%s", target_dir, target_name); 702818534a1Smrg Xfree(target_name); 7030f8248bfSmrg Xfree (last_dir_name); 7040f8248bfSmrg Xfree (last_lc_name); 7051ab64890Smrg 7063b4ba46cSmrg last_dir_name = strdup (dir_name); 7073b4ba46cSmrg last_dir_len = (last_dir_name != NULL) ? strlen (last_dir_name) + 1 : 0; 7083b4ba46cSmrg 7096cc2b21fSmrg last_lc_name = strdup (lc_name); 7101ab64890Smrg 7111ab64890Smrg return dir_name; 7121ab64890Smrg} 713