/* $XConsortium: aixlcLoad.c /main/12 1996/09/28 16:36:57 rws $ */ /* * * Copyright IBM Corporation 1993 * * All Rights Reserved * * License to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation, and that the name of IBM not be * used in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING * ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS, AND * NONINFRINGEMENT OF THIRD PARTY RIGHTS, IN NO EVENT SHALL * IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * */ /* $XFree86: xc/lib/X11/aixlcLoad.c,v 3.3.2.2 1998/02/01 22:08:10 robin Exp $ */ /************************************************************************/ /* XaixlcLoad.c */ /************************************************************************/ #include #include #include #include #include "Xlibint.h" #include "Xaixlcint.h" /************************************************************************/ /* Private defines */ /************************************************************************/ enum { LDX_INVALID_TYPE, LDX_DYNAMIC, LDX_STATIC_SIM, LDX_STATIC_MIM }; enum { LDX_INVALID_VERSION, LDX_R5, LDX_R6 }; typedef XLCd (*XLCdLoader)(); typedef _XlcCoreObj (*XdlEntry)(); #define SECURE_PATH "/usr/lib/nls/loc/X11" #ifndef LDXDBFILE #define LDXDBFILE "ldx.dir" #endif #define LDXFILE_SUFFIX ".ldx" #ifndef _POSIX_PATH_MAX #define _POSIX_PATH_MAX 1024 #endif #define iscomment(ch) ((ch) == '\0' || (ch) == '#') /* standard AIX interfaces */ extern void *__lc_load(); extern int __issetuid(); extern int _XlcParsePath(char*, char**, int); /************************************************************************/ /* Private functions */ /************************************************************************/ static int parse_line(line, argv, argsize) char *line; char **argv; int argsize; { int argc = 0; char *p = line; while(argc < argsize){ while(isspace(*p)){ ++p; } if(*p == '\0'){ break; } argv[argc++] = p; while(! isspace(*p)){ ++p; } if(*p == '\0'){ break; } *p++ = '\0'; } return argc; } static int read_ldxdb(lc_name, path, type, option) char *lc_name; char *path; int *type; char *option; { char filename[_POSIX_PATH_MAX]; FILE *fp; char buf[BUFSIZE]; int found = 0; sprintf(filename, "%s/%s", path, LDXDBFILE); fp = fopen(filename, "r"); if(fp == (FILE *)NULL){ return 0; } while(fgets(buf, BUFSIZE, fp) != NULL){ char *p = buf; int n; char *args[3]; while(isspace(*p)){ ++p; } if(iscomment(*p)){ continue; } n = parse_line(p, args, 3); if(n == 0){ continue; } if(! strcmp(args[0], lc_name)){ char *str; *type = LDX_STATIC_SIM; if(n > 1){ str = args[1]; if(! _XlcCompareISOLatin1(str, "LDX_DYNAMIC")){ *type = LDX_DYNAMIC; }else if(! _XlcCompareISOLatin1(str, "LDX_STATIC_MIM")){ *type = LDX_STATIC_MIM; } } *option = '\0'; if(n > 2){ str = args[2]; if(! _XlcCompareISOLatin1(str, "NONE")){ ; /* ignore option */ }else{ strcpy(option, str); } } found = 1; break; } } fclose(fp); return found; } static int resolve_ldxinfo(lc_name, type, option) char *lc_name; int *type; char *option; { char buf[BUFSIZE], *dir; int i, n; char *args[256]; dir = getenv("LDXDBPATH"); if(dir != NULL){ strncpy(buf, dir, BUFSIZE); buf[BUFSIZE-1] = '\0'; }else{ /* Resolve default path for database */ _XlcResolveI18NPath(buf, BUFSIZE); } n = _XlcParsePath(buf, args, 256); for(i = 0; i < n; ++i){ if(read_ldxdb(lc_name, args[i], type, option)){ if(*type == LDX_DYNAMIC && *option != '/'){ /* the option should be absolute path */ char tmp[_POSIX_PATH_MAX]; sprintf(tmp, "%s/%s", args[i], option); strcpy(option, tmp); } return 1; } } return 0; } static int get_ldxversion(ldx) _XlcCoreObj ldx; { if(ldx == (_XlcCoreObj)NULL){ return LDX_INVALID_VERSION; } #ifdef AIXV4 if(ldx->lc_object_header.__type_id == _LC_LDX_R6 && ldx->lc_object_header.__magic == _LC_MAGIC && ldx->lc_object_header.__version == _LC_VERSION_R6){ return LDX_R6; } if(ldx->lc_object_header.__type_id == _LC_LDX && ldx->lc_object_header.__magic == _LC_MAGIC && ldx->lc_object_header.__version == _LC_VERSION){ return LDX_R5; } #else if(ldx->lc_object_header.type_id == _LC_LDX_R6 && ldx->lc_object_header.magic == _LC_MAGIC && ldx->lc_object_header.version == _LC_VERSION_R6){ return LDX_R6; } if(ldx->lc_object_header.type_id == _LC_LDX && ldx->lc_object_header.magic == _LC_MAGIC && ldx->lc_object_header.version == _LC_VERSION){ return LDX_R5; } #endif return LDX_INVALID_VERSION; } static int complete_path(lc_name, path) char *lc_name; char *path; { if(path == NULL){ return 0; } if(*path == '\0' || #ifdef never getuid() != geteuid() || getgid() != getegid() #else __issetuid() #endif ){ /* use secure path */ sprintf(path, "%s/%s%s", SECURE_PATH, lc_name, LDXFILE_SUFFIX); }else{ int i, len; len = strlen(path); i = len - strlen(LDXFILE_SUFFIX); if(i < 0 || strcmp(path + i, LDXFILE_SUFFIX)){ if(path[len - 1] == '/'){ strcpy(path + len, lc_name); len += strlen(lc_name); } strcpy(path + len, LDXFILE_SUFFIX); } } return (*path != '\0') ? 1 : 0; } /************************************************************************/ typedef struct _ldxList{ char *path; XdlEntry entrypoint; _XlcCoreObj obj; int ref_count; struct _ldxList *next; } ldxList; static ldxList *_ldxlist = (ldxList *)NULL; static void unload_ldx(obj) _XlcCoreObj obj; { ldxList *pre, *ptr; for(pre = (ldxList *)NULL, ptr = _ldxlist; ptr != (ldxList *)NULL; pre = ptr, ptr = ptr->next){ if(ptr->obj == obj){ if((-- ptr->ref_count) < 1){ /* free and rechain cache list */ Xfree(ptr->path); unload((void *)ptr->entrypoint); if(pre != (ldxList *)NULL){ pre->next = ptr->next; }else{ _ldxlist = ptr->next; } Xfree((char *)ptr); } return; } } } static void * instantiate(path, p) char *path; void *(*p)(); { /* return entry point simply */ return (void *)p; } static _XlcCoreObj load_ldx(path) char *path; { ldxList *ptr = (ldxList *)NULL; XdlEntry entry; _XlcCoreObj ldx = (_XlcCoreObj)NULL; for(ptr = _ldxlist; ptr != (ldxList *)NULL; ptr = ptr->next){ if(! strcmp(path, ptr->path)){ ++ (ptr->ref_count); return ptr->obj; } } /* dynamic load */ /* the given path should be absolute path */ #ifdef never entry = (XdlEntry)load(path, 1, NULL); #else entry = (XdlEntry)__lc_load(path, instantiate); #endif if(entry == (XdlEntry)NULL){ goto err; } ldx = (*entry)(); if(ldx == (_XlcCoreObj)NULL){ goto err; } /* create cache list */ ptr = (ldxList *)Xmalloc(sizeof(ldxList)); if(ptr == (ldxList *)NULL){ goto err; } ptr->path = Xmalloc(strlen(path) + 1); if(ptr->path == NULL){ goto err; } strcpy(ptr->path, path); ptr->entrypoint = entry; ptr->obj = ldx; ptr->ref_count = 1; ptr->next = _ldxlist; _ldxlist = ptr; return ldx; err:; if(entry != (XdlEntry)NULL){ unload((void *)entry); } if(ptr != (ldxList *)NULL){ Xfree((char *)ptr); } return (_XlcCoreObj)NULL; } /************************************************************************/ typedef struct _lcdList { XLCd lcd; _XlcCoreObj ldx; XCloseLCProc close; struct _lcdList *next; } lcdList; static lcdList *_lcdlist = (lcdList *)NULL; static void close_xlcd(lcd) XLCd lcd; { lcdList *pre, *ptr; for(pre = (lcdList *)NULL, ptr = _lcdlist; ptr != (lcdList *)NULL; pre = ptr, ptr = ptr->next){ if(lcd == ptr->lcd){ /* free and rechain cache list */ (*ptr->close)(lcd); unload_ldx(ptr->ldx); if(pre != (lcdList *)NULL){ pre->next = ptr->next; }else{ _lcdlist = ptr->next; } Xfree((char *)ptr); return; } } } /************************************************************************/ #ifdef STATIC_LOAD extern XLCd _XaixlcSIMLoader(); extern XLCd _XaixlcMIMLoader(); #endif static XLCd instantiate_xlcd(lc_name) char *lc_name; { int type; char path[_POSIX_PATH_MAX]; _XlcCoreObj ldx = (_XlcCoreObj)NULL; XLCdLoader _XlcInstantiate = (XLCdLoader)NULL; XLCd lcd = (XLCd)NULL; if(! resolve_ldxinfo(lc_name, &type, path)){ return (XLCd)NULL; } switch(type){ #ifdef STATIC_LOAD case LDX_STATIC_SIM: _XlcInstantiate = _XaixlcSIMLoader; break; case LDX_STATIC_MIM: _XlcInstantiate = _XaixlcMIMLoader; break; #endif case LDX_DYNAMIC: if(! complete_path(lc_name, path)){ break; } ldx = load_ldx(path); if(ldx == (_XlcCoreObj)NULL){ break; } switch(get_ldxversion(ldx)){ case LDX_R5: /* X11.5 LDX is not supported. */ break; case LDX_R6: _XlcInstantiate = (XLCdLoader)ldx->default_loader; break; default: break; } break; } if(_XlcInstantiate != (XLCdLoader)NULL){ lcd = (*_XlcInstantiate)(lc_name); } switch(type){ case LDX_STATIC_SIM: break; case LDX_STATIC_MIM: break; case LDX_DYNAMIC: if(ldx != (_XlcCoreObj)NULL){ if(ldx->sticky){ break; } if(lcd != (XLCd)NULL){ lcdList *ptr = (lcdList *)Xmalloc(sizeof(lcdList)); if(ptr != (lcdList *)NULL){ ptr->lcd = lcd; ptr->ldx = ldx; ptr->close = lcd->methods->close; lcd->methods->close = (XCloseLCProc)close_xlcd; ptr->next = _lcdlist; _lcdlist = ptr; }else{ (*lcd->methods->close)(lcd); lcd = (XLCd)NULL; } } if(lcd == (XLCd)NULL){ /* fail to instantiate lcd */ unload_ldx(ldx); } } break; } return lcd; } /************************************************************************/ /* _XaixOsDynamicLoad() */ /*----------------------------------------------------------------------*/ /* This loader creates XLCd with using AIX dynamic loading */ /* feature. */ /************************************************************************/ XLCd _XaixOsDynamicLoad(name) _Xconst char *name; { return instantiate_xlcd(name); }