XlcDL.c revision d8e76104
1/* 2Copyright 1985, 1986, 1987, 1991, 1998 The Open Group 3 4Permission is hereby granted, free of charge, to any person obtaining a 5copy of this software and associated documentation files (the 6"Software"), to deal in the Software without restriction, including 7without limitation the rights to use, copy, modify, merge, publish, 8distribute, sublicense, and/or sell copies of the Software, and to 9permit persons to whom the Software is furnished to do so, subject to 10the following conditions: The above copyright notice and this 11permission notice shall be included in all copies or substantial 12portions of the Software. 13 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE 21EVEN IF ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES. 22 23 24Except as contained in this notice, the name of The Open Group shall not be 25used in advertising or otherwise to promote the sale, use or other dealings 26in this Software without prior written authorization from The Open Group. 27 28 29X Window System is a trademark of The Open Group 30 31OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF 32logo, LBX, X Window System, and Xinerama are trademarks of the Open 33Group. All other trademarks and registered trademarks mentioned herein 34are the property of their respective owners. No right, title or 35interest in or to any trademark, service mark, logo or trade name of 36Sun Microsystems, Inc. or its licensors is granted. 37 38*/ 39/* 40 * Copyright 2000 Oracle and/or its affiliates. All rights reserved. 41 * 42 * Permission is hereby granted, free of charge, to any person obtaining a 43 * copy of this software and associated documentation files (the "Software"), 44 * to deal in the Software without restriction, including without limitation 45 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 46 * and/or sell copies of the Software, and to permit persons to whom the 47 * Software is furnished to do so, subject to the following conditions: 48 * 49 * The above copyright notice and this permission notice (including the next 50 * paragraph) shall be included in all copies or substantial portions of the 51 * Software. 52 * 53 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 54 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 55 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 56 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 57 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 58 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 59 * DEALINGS IN THE SOFTWARE. 60 */ 61 62 63#ifdef HAVE_CONFIG_H 64# include <config.h> 65#else 66# if defined(hpux) 67# define HAVE_DL_H 68# else 69# define HAVE_DLFCN_H 70# endif 71#endif 72 73#include <stdio.h> 74 75#ifdef HAVE_DL_H 76#include <dl.h> 77#endif 78 79#ifdef HAVE_DLFCN_H 80#include <dlfcn.h> 81#endif 82 83#include <ctype.h> 84 85#include "Xlibint.h" 86#include "XlcPublic.h" 87#include "XlcPubI.h" 88 89#define XI18N_DLREL 2 90 91#define iscomment(ch) ((ch) == '\0' || (ch) == '#') 92 93typedef enum { 94 XLC_OBJECT, 95 XIM_OBJECT, 96 XOM_OBJECT 97} XI18NDLType; 98 99typedef struct { 100 XI18NDLType type; 101 int locale_name_len; 102 char *locale_name; 103 char *dl_name; 104 char *open; 105 char *im_register; 106 char *im_unregister; 107 int dl_release; 108 unsigned int refcount; 109#if defined(hpux) 110 shl_t dl_module; 111#else 112 void *dl_module; 113#endif 114} XI18NObjectsListRec, *XI18NObjectsList; 115 116#define OBJECT_INIT_LEN 8 117#define OBJECT_INC_LEN 4 118static int lc_len = 0; 119static XI18NObjectsListRec *xi18n_objects_list = NULL; 120static int lc_count = 0; 121 122static int 123parse_line(char *line, char **argv, int argsize) 124{ 125 int argc = 0; 126 char *p = line; 127 128 while (argc < argsize) { 129 while (isspace(*p)) { 130 ++p; 131 } 132 if (iscomment(*p)){ 133 break; 134 } 135 argv[argc++] = p; 136 while (!isspace(*p)) { 137 ++p; 138 } 139 if (iscomment(*p)) { 140 break; 141 } 142 *p++ = '\0'; 143 } 144 return argc; 145} 146 147static char * 148strdup_with_underscore(const char *symbol) 149{ 150 char *result; 151 152 if ((result = malloc(strlen(symbol) + 2)) == NULL) 153 return NULL; 154 result[0] = '_'; 155 strcpy(result + 1, symbol); 156 return result; 157} 158 159#ifndef hpux 160static void * 161try_both_dlsym (void *handle, char *name) 162{ 163 void *ret; 164 165 ret = dlsym (handle, name); 166 if (!ret) 167 { 168 name = strdup_with_underscore (name); 169 if (name) 170 { 171 ret = dlsym (handle, name); 172 free (name); 173 } 174 } 175 return ret; 176} 177#endif 178 179static void 180resolve_object(char *path, const char *lc_name) 181{ 182 char filename[BUFSIZ]; 183 FILE *fp; 184 char buf[BUFSIZ]; 185 186 if (lc_len == 0) { /* True only for the 1st time */ 187 lc_len = OBJECT_INIT_LEN; 188 xi18n_objects_list = (XI18NObjectsList) 189 Xmalloc(sizeof(XI18NObjectsListRec) * lc_len); 190 if (!xi18n_objects_list) return; 191 } 192/* 1931266793 194Limit the length of path to prevent stack buffer corruption. 195 sprintf(filename, "%s/%s", path, "XI18N_OBJS"); 196*/ 197 sprintf(filename, "%.*s/%s", BUFSIZ - 12, path, "XI18N_OBJS"); 198 fp = fopen(filename, "r"); 199 if (fp == (FILE *)NULL){ 200 return; 201 } 202 203 while (fgets(buf, BUFSIZ, fp) != NULL){ 204 char *p = buf; 205 int n; 206 char *args[6]; 207 while (isspace(*p)){ 208 ++p; 209 } 210 if (iscomment(*p)){ 211 continue; 212 } 213 214 if (lc_count == lc_len) { 215 lc_len += OBJECT_INC_LEN; 216 xi18n_objects_list = (XI18NObjectsList) 217 Xrealloc(xi18n_objects_list, 218 sizeof(XI18NObjectsListRec) * lc_len); 219 if (!xi18n_objects_list) return; 220 } 221 n = parse_line(p, args, 6); 222 223 if (n == 3 || n == 5) { 224 if (!strcmp(args[0], "XLC")){ 225 xi18n_objects_list[lc_count].type = XLC_OBJECT; 226 } else if (!strcmp(args[0], "XOM")){ 227 xi18n_objects_list[lc_count].type = XOM_OBJECT; 228 } else if (!strcmp(args[0], "XIM")){ 229 xi18n_objects_list[lc_count].type = XIM_OBJECT; 230 } 231 xi18n_objects_list[lc_count].dl_name = strdup(args[1]); 232 xi18n_objects_list[lc_count].open = strdup(args[2]); 233 xi18n_objects_list[lc_count].dl_release = XI18N_DLREL; 234 xi18n_objects_list[lc_count].locale_name = strdup(lc_name); 235 xi18n_objects_list[lc_count].refcount = 0; 236 xi18n_objects_list[lc_count].dl_module = (void*)NULL; 237 if (n == 5) { 238 xi18n_objects_list[lc_count].im_register = strdup(args[3]); 239 xi18n_objects_list[lc_count].im_unregister = strdup(args[4]); 240 } else { 241 xi18n_objects_list[lc_count].im_register = NULL; 242 xi18n_objects_list[lc_count].im_unregister = NULL; 243 } 244 lc_count++; 245 } 246 } 247 fclose(fp); 248} 249 250static char* 251__lc_path(const char *dl_name, const char *lc_dir) 252{ 253 char *path; 254 size_t len; 255 256 /* 257 * reject this for possible security issue 258 */ 259 if (strstr (dl_name, "../")) 260 return NULL; 261 262 len = (lc_dir ? strlen(lc_dir) : 0 ) + 263 (dl_name ? strlen(dl_name) : 0) + 10; 264#if defined POSTLOCALELIBDIR 265 len += (strlen(POSTLOCALELIBDIR) + 1); 266#endif 267 path = Xmalloc(len + 1); 268 269 if (strchr(dl_name, '/') != NULL) { 270 char *slash_p; 271 slash_p = strrchr(lc_dir, '/'); 272 *slash_p = '\0'; 273 strcpy(path, lc_dir); strcat(path, "/"); 274#if defined POSTLOCALELIBDIR 275 strcat(path, POSTLOCALELIBDIR); strcat(path, "/"); 276#endif 277 strcat(path, dl_name); strcat(path, ".so.2"); 278 *slash_p = '/'; 279 } else { 280 strcpy(path, lc_dir); strcat(path, "/"); 281#if defined POSTLOCALELIBDIR 282 strcat(path, POSTLOCALELIBDIR); strcat(path, "/"); 283#endif 284 strcat(path, dl_name); strcat(path, ".so.2"); 285 } 286 return path; 287} 288 289/* We reference count dlopen() and dlclose() of modules; unfortunately, 290 * since XCloseIM, XCloseOM, XlcClose aren't wrapped, but directly 291 * call the close method of the object, we leak a reference count every 292 * time we open then close a module. Fixing this would require 293 * either creating proxy objects or hooks for close_im/close_om 294 * in XLCd 295 */ 296static Bool 297open_object( 298 XI18NObjectsList object, 299 char *lc_dir) 300{ 301 char *path; 302 303 if (object->refcount == 0) { 304 path = __lc_path(object->dl_name, lc_dir); 305 if (!path) 306 return False; 307#if defined(hpux) 308 object->dl_module = shl_load(path, BIND_DEFERRED, 0L); 309#else 310 object->dl_module = dlopen(path, RTLD_LAZY); 311#endif 312 Xfree(path); 313 314 if (!object->dl_module) 315 return False; 316 } 317 318 object->refcount++; 319 return True; 320} 321 322static void * 323fetch_symbol( 324 XI18NObjectsList object, 325 char *symbol) 326{ 327 void *result = NULL; 328#if defined(hpux) 329 int getsyms_cnt, i; 330 struct shl_symbol *symbols; 331#endif 332 333 if (symbol == NULL) 334 return NULL; 335 336#if defined(hpux) 337 getsyms_cnt = shl_getsymbols(object->dl_module, TYPE_PROCEDURE, 338 EXPORT_SYMBOLS, malloc, &symbols); 339 340 for(i=0; i<getsyms_cnt; i++) { 341 if(!strcmp(symbols[i].name, symbol)) { 342 result = symbols[i].value; 343 break; 344 } 345 } 346 347 if(getsyms_cnt > 0) { 348 free(symbols); 349 } 350#else 351 result = try_both_dlsym(object->dl_module, symbol); 352#endif 353 354 return result; 355} 356 357static void 358close_object(XI18NObjectsList object) 359{ 360 object->refcount--; 361 if (object->refcount == 0) 362 { 363#if defined(hpux) 364 shl_unload(object->dl_module); 365#else 366 dlclose(object->dl_module); 367#endif 368 object->dl_module = NULL; 369 } 370} 371 372 373typedef XLCd (*dynamicLoadProc)(const char *); 374 375XLCd 376_XlcDynamicLoad(const char *lc_name) 377{ 378 XLCd lcd = (XLCd)NULL; 379 dynamicLoadProc lc_loader = (dynamicLoadProc)NULL; 380 int count; 381 XI18NObjectsList objects_list; 382 char lc_dir[BUFSIZE], lc_lib_dir[BUFSIZE]; 383 384 if (lc_name == NULL) return (XLCd)NULL; 385 386 if (_XlcLocaleDirName(lc_dir, BUFSIZE, (char *)lc_name) == (char *)NULL) 387 return (XLCd)NULL; 388 if (_XlcLocaleLibDirName(lc_lib_dir, BUFSIZE, (char *)lc_name) == (char*)NULL) 389 return (XLCd)NULL; 390 391 resolve_object(lc_dir, lc_name); 392 resolve_object(lc_lib_dir, lc_name); 393 394 objects_list = xi18n_objects_list; 395 count = lc_count; 396 for (; count-- > 0; objects_list++) { 397 if (objects_list->type != XLC_OBJECT || 398 strcmp(objects_list->locale_name, lc_name)) continue; 399 if (!open_object (objects_list, lc_dir) && \ 400 !open_object (objects_list, lc_lib_dir)) 401 continue; 402 403 lc_loader = (dynamicLoadProc)fetch_symbol (objects_list, objects_list->open); 404 if (!lc_loader) continue; 405 lcd = (*lc_loader)(lc_name); 406 if (lcd != (XLCd)NULL) { 407 break; 408 } 409 410 close_object (objects_list); 411 } 412 return (XLCd)lcd; 413} 414 415 416typedef XIM (*dynamicOpenProcp)(XLCd, Display *, XrmDatabase, char *, char *); 417 418static XIM 419_XDynamicOpenIM(XLCd lcd, Display *display, XrmDatabase rdb, 420 char *res_name, char *res_class) 421{ 422 XIM im = (XIM)NULL; 423 char lc_dir[BUFSIZE]; 424 char *lc_name; 425 dynamicOpenProcp im_openIM = (dynamicOpenProcp)NULL; 426 int count; 427 XI18NObjectsList objects_list = xi18n_objects_list; 428 429 lc_name = lcd->core->name; 430 431 if (_XlcLocaleLibDirName(lc_dir, BUFSIZE, lc_name) == NULL) return (XIM)0; 432 433 count = lc_count; 434 for (; count-- > 0; objects_list++) { 435 if (objects_list->type != XIM_OBJECT || 436 strcmp(objects_list->locale_name, lc_name)) continue; 437 438 if (!open_object (objects_list, lc_dir)) 439 continue; 440 441 im_openIM = (dynamicOpenProcp)fetch_symbol(objects_list, objects_list->open); 442 if (!im_openIM) continue; 443 im = (*im_openIM)(lcd, display, rdb, res_name, res_class); 444 if (im != (XIM)NULL) { 445 break; 446 } 447 448 close_object (objects_list); 449 } 450 return (XIM)im; 451} 452 453typedef Bool (*dynamicRegisterCBProcp)( 454 XLCd, Display *, XrmDatabase, char *, char *, XIDProc, XPointer); 455 456static Bool 457_XDynamicRegisterIMInstantiateCallback( 458 XLCd lcd, 459 Display *display, 460 XrmDatabase rdb, 461 char *res_name, 462 char *res_class, 463 XIDProc callback, 464 XPointer client_data) 465{ 466 char lc_dir[BUFSIZE]; 467 char *lc_name; 468 dynamicRegisterCBProcp im_registerIM = (dynamicRegisterCBProcp)NULL; 469 Bool ret_flag = False; 470 int count; 471 XI18NObjectsList objects_list = xi18n_objects_list; 472#if defined(hpux) 473 int getsyms_cnt, i; 474 struct shl_symbol *symbols; 475#endif 476 477 lc_name = lcd->core->name; 478 479 if (_XlcLocaleLibDirName(lc_dir, BUFSIZE, lc_name) == NULL) return False; 480 481 count = lc_count; 482 for (; count-- > 0; objects_list++) { 483 if (objects_list->type != XIM_OBJECT || 484 strcmp(objects_list->locale_name, lc_name)) continue; 485 486 if (!open_object (objects_list, lc_dir)) 487 continue; 488 im_registerIM = (dynamicRegisterCBProcp)fetch_symbol(objects_list, 489 objects_list->im_register); 490 if (!im_registerIM) continue; 491 ret_flag = (*im_registerIM)(lcd, display, rdb, 492 res_name, res_class, 493 callback, client_data); 494 if (ret_flag) break; 495 496 close_object (objects_list); 497 } 498 return (Bool)ret_flag; 499} 500 501typedef Bool (*dynamicUnregisterProcp)( 502 XLCd, Display *, XrmDatabase, char *, char *, XIDProc, XPointer); 503 504static Bool 505_XDynamicUnRegisterIMInstantiateCallback( 506 XLCd lcd, 507 Display *display, 508 XrmDatabase rdb, 509 char *res_name, 510 char *res_class, 511 XIDProc callback, 512 XPointer client_data) 513{ 514 char lc_dir[BUFSIZE]; 515 char *lc_name; 516 dynamicUnregisterProcp im_unregisterIM = (dynamicUnregisterProcp)NULL; 517 Bool ret_flag = False; 518 int count; 519 XI18NObjectsList objects_list = xi18n_objects_list; 520#if defined(hpux) 521 int getsyms_cnt, i; 522 struct shl_symbol *symbols; 523#endif 524 525 lc_name = lcd->core->name; 526 if (_XlcLocaleDirName(lc_dir, BUFSIZE, lc_name) == NULL) return False; 527 528 count = lc_count; 529 for (; count-- > 0; objects_list++) { 530 if (objects_list->type != XIM_OBJECT || 531 strcmp(objects_list->locale_name, lc_name)) continue; 532 533 if (!objects_list->refcount) /* Must already be opened */ 534 continue; 535 536 im_unregisterIM = (dynamicUnregisterProcp)fetch_symbol(objects_list, 537 objects_list->im_unregister); 538 539 if (!im_unregisterIM) continue; 540 ret_flag = (*im_unregisterIM)(lcd, display, rdb, 541 res_name, res_class, 542 callback, client_data); 543 if (ret_flag) { 544 close_object (objects_list); /* opened in RegisterIMInstantiateCallback */ 545 break; 546 } 547 } 548 return (Bool)ret_flag; 549} 550 551Bool 552_XInitDynamicIM(XLCd lcd) 553{ 554 if(lcd == (XLCd)NULL) 555 return False; 556 lcd->methods->open_im = _XDynamicOpenIM; 557 lcd->methods->register_callback = _XDynamicRegisterIMInstantiateCallback; 558 lcd->methods->unregister_callback = _XDynamicUnRegisterIMInstantiateCallback; 559 return True; 560} 561 562 563typedef XOM (*dynamicIOpenProcp)( 564 XLCd, Display *, XrmDatabase, _Xconst char *, _Xconst char *); 565 566static XOM 567_XDynamicOpenOM(XLCd lcd, Display *display, XrmDatabase rdb, 568 _Xconst char *res_name, _Xconst char *res_class) 569{ 570 XOM om = (XOM)NULL; 571 int count; 572 char lc_dir[BUFSIZE]; 573 char *lc_name; 574 dynamicIOpenProcp om_openOM = (dynamicIOpenProcp)NULL; 575 XI18NObjectsList objects_list = xi18n_objects_list; 576#if defined(hpux) 577 int getsyms_cnt, i; 578 struct shl_symbol *symbols; 579#endif 580 581 lc_name = lcd->core->name; 582 583 if (_XlcLocaleLibDirName(lc_dir, BUFSIZE, lc_name) == NULL) return (XOM)0; 584 585 count = lc_count; 586 for (; count-- > 0; objects_list++) { 587 if (objects_list->type != XOM_OBJECT || 588 strcmp(objects_list->locale_name, lc_name)) continue; 589 if (!open_object (objects_list, lc_dir)) 590 continue; 591 592 om_openOM = (dynamicIOpenProcp)fetch_symbol(objects_list, objects_list->open); 593 if (!om_openOM) continue; 594 om = (*om_openOM)(lcd, display, rdb, res_name, res_class); 595 if (om != (XOM)NULL) { 596 break; 597 } 598 close_object(objects_list); 599 } 600 return (XOM)om; 601} 602 603Bool 604_XInitDynamicOM(XLCd lcd) 605{ 606 if(lcd == (XLCd)NULL) 607 return False; 608 609 lcd->methods->open_om = _XDynamicOpenOM; 610 611 return True; 612} 613