1252372Sray/* $FreeBSD$ */ 2252372Sray/* $NetBSD: citrus_module.c,v 1.9 2009/01/11 02:46:24 christos Exp $ */ 3252372Sray 4252372Sray/*- 5252372Sray * Copyright (c)1999, 2000, 2001, 2002 Citrus Project, 6252372Sray * All rights reserved. 7252372Sray * 8252372Sray * Redistribution and use in source and binary forms, with or without 9252372Sray * modification, are permitted provided that the following conditions 10252372Sray * are met: 11252372Sray * 1. Redistributions of source code must retain the above copyright 12252372Sray * notice, this list of conditions and the following disclaimer. 13252372Sray * 2. Redistributions in binary form must reproduce the above copyright 14252372Sray * notice, this list of conditions and the following disclaimer in the 15252372Sray * documentation and/or other materials provided with the distribution. 16252372Sray * 17252372Sray * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18252372Sray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19252372Sray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20252372Sray * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21252372Sray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22252372Sray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23252372Sray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24252372Sray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25252372Sray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26252372Sray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27252372Sray * SUCH DAMAGE. 28252372Sray */ 29252372Sray 30252372Sray/*- 31252372Sray * Copyright (c) 1998 The NetBSD Foundation, Inc. 32252372Sray * All rights reserved. 33252372Sray * 34252372Sray * This code is derived from software contributed to The NetBSD Foundation 35252372Sray * by Paul Kranenburg. 36252372Sray * 37252372Sray * Redistribution and use in source and binary forms, with or without 38252372Sray * modification, are permitted provided that the following conditions 39252372Sray * are met: 40252372Sray * 1. Redistributions of source code must retain the above copyright 41252372Sray * notice, this list of conditions and the following disclaimer. 42252372Sray * 2. Redistributions in binary form must reproduce the above copyright 43252372Sray * notice, this list of conditions and the following disclaimer in the 44252372Sray * documentation and/or other materials provided with the distribution. 45252372Sray * 46252372Sray * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 47252372Sray * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 48252372Sray * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 49252372Sray * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 50252372Sray * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 51252372Sray * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 52252372Sray * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 53252372Sray * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 54252372Sray * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 55252372Sray * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 56252372Sray * POSSIBILITY OF SUCH DAMAGE. 57252372Sray */ 58252372Sray 59252372Sray/*- 60252372Sray * Copyright (c) 1993 61252372Sray * The Regents of the University of California. All rights reserved. 62252780Sray * 63252780Sray * This code is derived from software contributed to Berkeley by 64252780Sray * Paul Borman at Krystal Technologies. 65252780Sray * 66252780Sray * Redistribution and use in source and binary forms, with or without 67252372Sray * modification, are permitted provided that the following conditions 68252780Sray * are met: 69252780Sray * 1. Redistributions of source code must retain the above copyright 70252780Sray * notice, this list of conditions and the following disclaimer. 71252780Sray * 2. Redistributions in binary form must reproduce the above copyright 72252780Sray * notice, this list of conditions and the following disclaimer in the 73252780Sray * documentation and/or other materials provided with the distribution. 74252780Sray * 3. Neither the name of the University nor the names of its contributors 75252372Sray * may be used to endorse or promote products derived from this software 76252372Sray * without specific prior written permission. 77266352Sian * 78266352Sian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 79252372Sray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 80252372Sray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 81252372Sray * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 82252372Sray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 83252372Sray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 84252372Sray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 85266352Sian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 86266352Sian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 87266352Sian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 88266352Sian * SUCH DAMAGE. 89275764Sandrew */ 90266352Sian 91266352Sian#include <sys/cdefs.h> 92266352Sian#include <sys/types.h> 93252372Sray 94252372Sray#include <assert.h> 95252372Sray#include <dirent.h> 96252372Sray#include <dlfcn.h> 97252372Sray#include <errno.h> 98252372Sray#include <limits.h> 99252372Sray#include <paths.h> 100252372Sray#include <stdbool.h> 101252372Sray#include <stddef.h> 102252372Sray#include <stdio.h> 103252372Sray#include <stdlib.h> 104252372Sray#include <string.h> 105252372Sray#include <unistd.h> 106252372Sray 107252372Sray#define I18NMODULE_MAJOR 4 108252372Sray 109252372Sray#include "citrus_namespace.h" 110252372Sray#include "citrus_bcs.h" 111252372Sray#include "citrus_module.h" 112252372Sray#include "libc_private.h" 113252372Sray 114252372Sraystatic int _getdewey(int[], char *); 115252372Sraystatic int _cmpndewey(int[], int, int[], int); 116252372Sraystatic const char *_findshlib(char *, int *, int *); 117252372Sray 118252372Sraystatic const char *_pathI18nModule = NULL; 119252372Sray 120252372Sray/* from libexec/ld.aout_so/shlib.c */ 121252372Sray#undef major 122252372Sray#undef minor 123252372Sray#define MAXDEWEY 3 /*ELF*/ 124252372Sray 125252372Sraystatic int 126252372Sray_getdewey(int dewey[], char *cp) 127252372Sray{ 128252372Sray int i, n; 129252372Sray 130252372Sray for (n = 0, i = 0; i < MAXDEWEY; i++) { 131252372Sray if (*cp == '\0') 132252372Sray break; 133252372Sray 134252372Sray if (*cp == '.') cp++; 135252372Sray if (*cp < '0' || '9' < *cp) 136252372Sray return (0); 137252372Sray 138252372Sray dewey[n++] = (int)_bcs_strtol(cp, &cp, 10); 139252372Sray } 140252372Sray 141252372Sray return (n); 142252372Sray} 143252372Sray 144252372Sray/* 145252372Sray * Compare two dewey arrays. 146252372Sray * Return -1 if `d1' represents a smaller value than `d2'. 147252372Sray * Return 1 if `d1' represents a greater value than `d2'. 148252372Sray * Return 0 if equal. 149252372Sray */ 150252372Sraystatic int 151252372Sray_cmpndewey(int d1[], int n1, int d2[], int n2) 152252372Sray{ 153252372Sray int i; 154252372Sray 155252372Sray for (i = 0; i < n1 && i < n2; i++) { 156252372Sray if (d1[i] < d2[i]) 157252372Sray return (-1); 158252372Sray if (d1[i] > d2[i]) 159252372Sray return (1); 160252372Sray } 161252372Sray 162252372Sray if (n1 == n2) 163252372Sray return (0); 164252372Sray 165252372Sray if (i == n1) 166252372Sray return (-1); 167252372Sray 168252372Sray if (i == n2) 169252372Sray return (1); 170252372Sray 171252372Sray /* cannot happen */ 172252372Sray return (0); 173252372Sray} 174252372Sray 175252372Sraystatic const char * 176252372Sray_findshlib(char *name, int *majorp, int *minorp) 177252372Sray{ 178252372Sray char *lname; 179252372Sray const char *search_dirs[1]; 180252372Sray static char path[PATH_MAX]; 181252372Sray int dewey[MAXDEWEY], tmp[MAXDEWEY]; 182252372Sray int i, len, major, minor, ndewey, n_search_dirs; 183252372Sray 184252780Sray n_search_dirs = 1; 185252780Sray major = *majorp; 186252372Sray minor = *minorp; 187252372Sray path[0] = '\0'; 188252372Sray search_dirs[0] = _pathI18nModule; 189252372Sray len = strlen(name); 190252372Sray lname = name; 191252372Sray 192252372Sray ndewey = 0; 193252372Sray 194252372Sray for (i = 0; i < n_search_dirs; i++) { 195252372Sray struct dirent *dp; 196252372Sray DIR *dd = opendir(search_dirs[i]); 197252372Sray int found_dot_a = 0, found_dot_so = 0; 198252372Sray 199252372Sray if (dd == NULL) 200252372Sray break; 201252372Sray 202252372Sray while ((dp = readdir(dd)) != NULL) { 203252372Sray int n; 204252372Sray 205252372Sray if (dp->d_namlen < len + 4) 206252372Sray continue; 207252372Sray if (strncmp(dp->d_name, lname, (size_t)len) != 0) 208252780Sray continue; 209252780Sray if (strncmp(dp->d_name+len, ".so.", 4) != 0) 210252372Sray continue; 211252372Sray 212252372Sray if ((n = _getdewey(tmp, dp->d_name+len+4)) == 0) 213252372Sray continue; 214252372Sray 215252372Sray if (major != -1 && found_dot_a) 216252372Sray found_dot_a = 0; 217252372Sray 218252372Sray /* XXX should verify the library is a.out/ELF? */ 219252372Sray 220252372Sray if (major == -1 && minor == -1) 221252372Sray goto compare_version; 222252372Sray else if (major != -1 && minor == -1) { 223252372Sray if (tmp[0] == major) 224252372Sray goto compare_version; 225252780Sray } else if (major != -1 && minor != -1) { 226252372Sray if (tmp[0] == major) { 227252372Sray if (n == 1 || tmp[1] >= minor) 228252372Sray goto compare_version; 229252372Sray } 230252372Sray } 231252372Sray 232252372Sray /* else, this file does not qualify */ 233252372Sray continue; 234252372Sray 235252372Sray compare_version: 236252372Sray if (_cmpndewey(tmp, n, dewey, ndewey) <= 0) 237252372Sray continue; 238252372Sray 239252780Sray /* We have a better version */ 240252780Sray found_dot_so = 1; 241252372Sray snprintf(path, sizeof(path), "%s/%s", search_dirs[i], 242252372Sray dp->d_name); 243252372Sray found_dot_a = 0; 244252372Sray bcopy(tmp, dewey, sizeof(dewey)); 245252372Sray ndewey = n; 246252372Sray *majorp = dewey[0]; 247252372Sray *minorp = dewey[1]; 248252372Sray } 249252372Sray closedir(dd); 250252372Sray 251252372Sray if (found_dot_a || found_dot_so) 252252372Sray /* 253252372Sray * There's a lib in this dir; take it. 254266152Sian */ 255266152Sian return (path[0] ? path : NULL); 256266152Sian } 257252372Sray 258252372Sray return (path[0] ? path : NULL); 259252372Sray} 260252372Sray 261252372Srayvoid * 262252372Sray_citrus_find_getops(_citrus_module_t handle, const char *modname, 263252372Sray const char *ifname) 264252372Sray{ 265252372Sray char name[PATH_MAX]; 266252372Sray void *p; 267252372Sray 268252372Sray snprintf(name, sizeof(name), "_citrus_%s_%s_getops", 269252372Sray modname, ifname); 270252372Sray p = dlsym((void *)handle, name); 271252372Sray return (p); 272266352Sian} 273252372Sray 274252372Srayint 275252372Sray_citrus_load_module(_citrus_module_t *rhandle, const char *encname) 276252372Sray{ 277252372Sray const char *p; 278252372Sray char path[PATH_MAX]; 279252372Sray void *handle; 280252372Sray int maj, min; 281266352Sian 282266352Sian if (_pathI18nModule == NULL) { 283266352Sian p = getenv("PATH_I18NMODULE"); 284266352Sian if (p != NULL && !issetugid()) { 285266352Sian _pathI18nModule = strdup(p); 286266352Sian if (_pathI18nModule == NULL) 287266352Sian return (ENOMEM); 288266352Sian } else 289266352Sian _pathI18nModule = _PATH_I18NMODULE; 290266352Sian } 291266352Sian 292252372Sray (void)snprintf(path, sizeof(path), "lib%s", encname); 293252372Sray maj = I18NMODULE_MAJOR; 294252372Sray min = -1; 295266352Sian p = _findshlib(path, &maj, &min); 296266352Sian if (!p) 297266352Sian return (EINVAL); 298266352Sian handle = libc_dlopen(p, RTLD_LAZY); 299252372Sray if (!handle) { 300252372Sray printf("%s", dlerror()); 301252372Sray return (EINVAL); 302266352Sian } 303266352Sian 304266352Sian *rhandle = (_citrus_module_t)handle; 305266352Sian 306266352Sian return (0); 307266352Sian} 308266352Sian 309266352Sianvoid 310252372Sray_citrus_unload_module(_citrus_module_t handle) 311252372Sray{ 312252372Sray 313252372Sray if (handle) 314252427Sray dlclose((void *)handle); 315252372Sray} 316252372Sray