/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/* dlopen.c--Unix dlopen() dynamic loader interface
* Rob Siemborski
* Rob Earhart
* $Id: dlopen.c,v 1.45 2003/07/14 20:08:50 rbraun Exp $
*/
/*
* Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any other legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY 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.
*/
#include <config.h>
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <limits.h>
#include <sasl.h>
#include "saslint.h"
#ifndef PIC
#include <saslplug.h>
#include "staticopen.h"
#endif
#ifdef _SUN_SDK_
#endif /* _SUN_SDK_ */
#ifdef DO_DLOPEN
#if HAVE_DIRENT_H
# include <dirent.h>
#else /* HAVE_DIRENT_H */
# if HAVE_SYS_NDIR_H
# endif
# if HAVE_SYS_DIR_H
# endif
# if HAVE_NDIR_H
# include <ndir.h>
# endif
#endif /* ! HAVE_DIRENT_H */
#ifndef NAME_MAX
# ifdef _POSIX_NAME_MAX
# else
# endif
#endif
#if NAME_MAX < 8
#endif
#ifdef __hpux
#include <dl.h>
typedef void * dll_func;
{
if (h) {
if (!hp) {
shl_unload(h);
} else {
*hp = h;
}
}
return (dll_handle)hp;
}
int
{
return shl_unload(h);
}
{
return NULL;
}
char *dlerror()
{
if (errno != 0) {
}
return "Generic shared library error";
}
#else /* __hpux */
#endif /* __hpux */
#endif /* DO_DLOPEN */
typedef struct lib_list
{
void *library;
} lib_list_t;
#ifndef _SUN_SDK_
#endif /* !_SUN_SDK_ */
#endif /* DO_DLOPEN || WIN_PLUG */ /* _SUN_SDK_ */
void **entry_point)
{
#ifdef DO_DLOPEN
/* note that we still check for known problem systems in
* case we are cross-compiling */
#if defined(DLSYM_NEEDS_UNDERSCORE) || defined(__OpenBSD__)
#else
#define adj_entryname entryname
#endif
if(!entryname) {
#ifndef _SUN_SDK_
"no entryname in _sasl_locate_entry");
#endif /* _SUN_SDK_ */
return SASL_BADPARAM;
}
if(!library) {
#ifndef _SUN_SDK_
"no library in _sasl_locate_entry");
#endif /* _SUN_SDK_ */
return SASL_BADPARAM;
}
if(!entry_point) {
#ifndef _SUN_SDK_
"no entrypoint output pointer in _sasl_locate_entry");
#endif /* _SUN_SDK_ */
return SASL_BADPARAM;
}
#if defined(DLSYM_NEEDS_UNDERSCORE) || defined(__OpenBSD__)
#endif
*entry_point = NULL;
if (*entry_point == NULL) {
#if 0 /* This message appears to confuse people */
"unable to get entry point %s: %s", adj_entryname,
dlerror());
#endif
return SASL_FAIL;
}
return SASL_OK;
#else
return SASL_FAIL;
#endif /* DO_DLOPEN */
}
#ifdef DO_DLOPEN
#ifdef _SUN_SDK_
const char *entryname,
const char *, void *))
#else
const char *entryname,
int (*add_plugin)(const char *, void *))
#endif /* _SUN_SDK_ */
{
void *entry_point;
int result;
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
#ifdef _SUN_SDK_
"_sasl_plugin_load failed on %s for plugin: %s\n",
#else
"_sasl_plugin_load failed on %s for plugin: %s\n",
#endif /* _SUN_SDK_ */
}
return result;
}
#ifndef _SUN_SDK_
/* this returns the file to actually open.
* out should be a buffer of size PATH_MAX
* and may be the same as in. */
/* We'll use a static buffer for speed unless someone complains */
{
/* Set this so we can detect failure */
*out = '\0';
/* check for a .la file */
if(file) {
/* We'll get it on the .la open */
return SASL_FAIL;
}
}
return SASL_OK;
}
if(!file) {
"unable to open LA file: %s", line);
return SASL_FAIL;
}
"LA file has too long of a line: %s", in);
return SASL_BUFOVER;
}
/* We found the line with the name in it */
char *end;
char *start;
if(!end) continue;
*end='\0';
/* Do we have dlname="" ? */
"dlname is empty in .la file: %s", in);
return SASL_FAIL;
}
}
break;
}
}
"Error reading .la: %s\n", in);
return SASL_FAIL;
}
if(!(*out)) {
"Could not find a dlname line in .la file: %s", in);
return SASL_FAIL;
}
return SASL_OK;
}
#endif /* !_SUN_SDK_ */
#endif /* DO_DLOPEN */
/* loads a plugin library */
#ifdef _SUN_SDK_
const char *file,
const sasl_callback_t *verifyfile_cb,
void **libraryptr)
#else
int _sasl_get_plugin(const char *file,
const sasl_callback_t *verifyfile_cb,
void **libraryptr)
#endif /* _SUN_SDK_ */
{
#ifdef DO_DLOPEN
int r = 0;
int flag;
void *library;
if (r != SASL_OK) return r;
#ifdef RTLD_NOW
#else
flag = 0;
#endif
if(!newhead) return SASL_NOMEM;
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
return SASL_FAIL;
}
#ifdef _SUN_SDK_
if (LOCK_MUTEX(&global_mutex) < 0) {
return (SASL_FAIL);
}
#endif /* _SUN_SDK_ */
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
*libraryptr = library;
return SASL_OK;
#else
return SASL_FAIL;
#endif /* DO_DLOPEN */
}
#ifdef _SUN_SDK_
{
int r;
r = LOCK_MUTEX(&global_mutex);
if (r < 0)
return;
#if defined DO_DLOPEN /* _SUN_SDK_ */
#else
#endif /* DO_DLOPEN */ /* _SUN_SDK_ */
break;
}
}
if (libptr_prev == NULL)
else
}
#endif /* DO_DLOPEN || WIN_PLUG */ /* _SUN_SDK_ */
#endif /* _SUN_SDK_ */
/* gets the list of mechanisms */
#ifdef _SUN_SDK_
int server,
const add_plugin_list_t *entrypoints,
const sasl_callback_t *getpath_cb,
const sasl_callback_t *verifyfile_cb)
#else
const sasl_callback_t *getpath_cb,
const sasl_callback_t *verifyfile_cb)
#endif /* _SUN_SDK_ */
{
int result;
#ifdef _SUN_SDK_
#endif /* _SUN_SDK_ */
#ifdef DO_DLOPEN
/* 1 for '/' 1 for trailing '\0' */
char c;
int pos;
int position;
#ifdef _SUN_SDK_
int plugin_loaded;
struct stat b;
#endif /* _SUN_SDK_ */
#endif
#ifndef PIC
_sasl_plug_rec *p;
#endif
if (! entrypoints
|| ! getpath_cb
|| ! getpath_cb->proc
|| ! verifyfile_cb
|| ! verifyfile_cb->proc)
return SASL_BADPARAM;
#ifndef PIC
/* do all the static plugins first */
/* What type of plugin are we looking for? */
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
} else {
/* What are we looking for then? */
return SASL_FAIL;
}
for (p=_sasl_static_plugins; p->type; p++) {
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
}
}
#endif /* !PIC */
/* only do the following if:
*
* we support dlopen()
* AND we are not staticly compiled
* OR we are staticly compiled and TRY_DLOPEN_WHEN_STATIC is defined
*/
/* get the path to the plugins */
&path);
return SASL_FAIL;
}
position=0;
do {
pos=0;
do {
position++;
pos++;
} while ((c!=':') && (c!='=') && (c!=0));
#ifdef _SUN_SDK_
break;
}
continue;
}
p_info = (_sasl_path_info_t *)
sasl_ALLOC(sizeof (_sasl_path_info_t));
return SASL_NOMEM;
}
return SASL_NOMEM;
}
if (server) {
} else {
}
} else {
continue;
}
}
#endif /* _SUN_SDK_ */
{
{
void *library;
#ifndef _SUN_SDK_
char *c;
#endif /* !_SUN_SDK_ */
#ifndef _SUN_SDK_
if (length < 4)
continue; /* can not possibly be what we're looking for */
#endif /* !_SUN_SDK_ */
#ifdef _SUN_SDK_
continue;
#else
continue;
#endif /* _SUN_SDK_ */
#ifdef _SUN_SDK_
#else
continue;
#endif /* _SUN_SDK_ */
#ifdef _SUN_SDK_
continue; /* Can't stat it */
continue;
/* Sun plugins don't have lib prefix */
#else
/* skip "lib" and cut off suffix --
this only need be approximate */
if(c) *c = '\0';
#endif /* _SUN_SDK_ */
#ifdef _SUN_SDK_
&library);
#else
#endif /* _SUN_SDK_ */
continue;
#ifdef _SUN_SDK_
plugin_loaded = 0;
/* If this fails, it's not the end of the world */
plugin_loaded = 1;
}
}
if (!plugin_loaded)
#else
cur_ep->add_plugin);
/* If this fails, it's not the end of the world */
}
#endif /* _SUN_SDK_ */
}
}
} while ((c!='=') && (c!=0));
result =
return (result);
#endif /* defined(DO_DLOPEN) && (!defined(PIC) || (defined(PIC) && defined(TRY_DLOPEN_WHEN_STATIC))) */
return SASL_OK;
}
#ifdef _SUN_SDK_
int
#else
int
_sasl_done_with_plugins(void)
#endif /* _SUN_SDK_ */
{
#ifdef _SUN_SDK_
if (LOCK_MUTEX(&global_mutex) < 0)
return (SASL_FAIL);
#endif /* _SUN_SDK_ */
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
#ifdef DO_DLOPEN /* _SUN_SDK_ */
#else
#endif /* DO_DLOPEN */ /* _SUN_SDK_ */
}
#ifdef _SUN_SDK_
#else
#endif /* _SUN_SDK_ */
#ifdef _SUN_SDK_
#endif /* _SUN_SDK_ */
#endif /* DO_DLOPEN || WIN_PLUG */ /* _SUN_SDK_ */
return SASL_OK;
}
#ifdef WIN_MUTEX
int win_global_mutex_lock()
{
if (global_mutex == NULL) {
if (global_mutex == NULL)
return (-1);
}
switch (dwWaitResult) {
case WAIT_OBJECT_0:
return (0);
case WAIT_TIMEOUT:
return (-1); /* Shouldn't happen */
case WAIT_ABANDONED:
return (-1); /* Shouldn't happen */
}
return (-1); /* Unexpected result */
}
int win_global_mutex_unlock()
{
if (global_mutex == NULL)
return (-1);
}
{
switch( ul_reason_for_call ) {
case DLL_PROCESS_ATTACH:
if (global_mutex == NULL)
return (FALSE);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
#endif