summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stefw@collabora.co.uk>2011-10-17 14:51:31 +0200
committerStef Walter <stefw@collabora.co.uk>2011-10-17 15:32:41 +0200
commitdb92b76e3acb11e330309ebce071ec2e61400a71 (patch)
treecb11139880974ef8db53dd83a70de8f32d94cc09
parentb1d9fd5f88ade222fbd2206c7e11c5514c8b5634 (diff)
Initial port to win32
* Tests do not all yet pass, at least not on wine * Added abstraction of some non-portable functions in compat.h/c * Build with an argument like this for win32 support: ./autogen.sh --host=i586-mingw32msvc * This win32 port needs more work from interested parties
-rw-r--r--.gitignore3
-rw-r--r--configure.ac35
-rw-r--r--doc/Makefile.am2
-rw-r--r--p11-kit/Makefile.am1
-rw-r--r--p11-kit/compat.c114
-rw-r--r--p11-kit/compat.h143
-rw-r--r--p11-kit/conf.c64
-rw-r--r--p11-kit/debug.c31
-rw-r--r--p11-kit/debug.h2
-rw-r--r--p11-kit/modules.c104
-rw-r--r--p11-kit/private.h40
-rw-r--r--p11-kit/proxy.c7
-rw-r--r--p11-kit/util.c188
-rw-r--r--tests/Makefile.am16
-rw-r--r--tests/conf-test.c2
-rw-r--r--tests/mock-module.c20
-rw-r--r--tests/mock-module.h1
-rw-r--r--tests/pin-test.c3
-rw-r--r--tests/test-init.c56
-rw-r--r--tools/Makefile.am4
-rw-r--r--tools/compat.c228
-rw-r--r--tools/compat.h63
-rw-r--r--tools/p11-kit.c5
23 files changed, 952 insertions, 180 deletions
diff --git a/.gitignore b/.gitignore
index f715e20..6419bd3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
*.la
*.lo
*.bak
+*.exe
*.tar.gz
*.sig
*.gcno
@@ -9,7 +10,9 @@
*.gcov
*~
*.html
+*.so
*.stamp
+*.tmp
.deps
.libs
diff --git a/configure.ac b/configure.ac
index 5dcd6f8..d2ca8f0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -37,15 +37,33 @@ AM_GNU_GETTEXT([external], [need-ngettext])
GTK_DOC_CHECK([1.15])
-# ------------------------------------------------------------------------------
-# Checks for libraries
-
-AC_CHECK_LIB(pthread, pthread_mutex_lock,,
- [AC_MSG_ERROR([could not find pthread_mutex_lock])])
-AC_SEARCH_LIBS([dlopen], [dl dld], [],
- [AC_MSG_ERROR([could not find dlopen])])
+AC_MSG_CHECKING([for win32])
+case "$host" in
+ *-*-mingw*)
+ AC_DEFINE_UNQUOTED(OS_WIN32, 1, [Building for win32])
+ os_win32=yes
+ os_unix=no
+ ;;
+ *)
+ AC_DEFINE_UNQUOTED(OS_UNIX, 1, [Building for unix])
+ os_win32=no
+ os_unix=yes
+ ;;
+esac
+AC_MSG_RESULT([$os_win32])
+AM_CONDITIONAL(OS_WIN32, test "$os_win32" = "yes")
-AC_CHECK_MEMBERS([struct dirent.d_type],,,[#include <dirent.h>])
+# ------------------------------------------------------------------------------
+# Checks for libraries and headers
+
+if test "$os_unix" = "yes"; then
+ AC_CHECK_LIB(pthread, pthread_mutex_lock,,
+ [AC_MSG_ERROR([could not find pthread_mutex_lock])])
+ AC_SEARCH_LIBS([dlopen], [dl dld], [],
+ [AC_MSG_ERROR([could not find dlopen])])
+ AC_CHECK_MEMBERS([struct dirent.d_type],,,[#include <dirent.h>])
+ AC_CHECK_HEADERS([err.h])
+fi
# ------------------------------------------------------------------------------
# PKCS#11 Directories
@@ -199,6 +217,7 @@ AC_OUTPUT
AC_MSG_NOTICE([build options:
+ Host: $host
Debug build: $debug_status
Strict build: $strict_status
System global config: $p11_system_config_file
diff --git a/doc/Makefile.am b/doc/Makefile.am
index cf7f4bc..530b75a 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -42,7 +42,7 @@ CFILE_GLOB=$(top_srcdir)/p11-kit/*.c
# Header files to ignore when scanning.
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
-IGNORE_HFILES= p11-kit-private.h pkcs11.h conf.h debug.h hashmap.h util.h ptr-array.h
+IGNORE_HFILES= private.h pkcs11.h conf.h debug.h hashmap.h util.h ptr-array.h compat.h
# Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
diff --git a/p11-kit/Makefile.am b/p11-kit/Makefile.am
index 3b838b3..72623b3 100644
--- a/p11-kit/Makefile.am
+++ b/p11-kit/Makefile.am
@@ -20,6 +20,7 @@ inc_HEADERS = \
MODULE_SRCS = \
util.c util.h \
+ compat.c compat.h \
conf.c conf.h \
debug.c debug.h \
hashmap.c hashmap.h \
diff --git a/p11-kit/compat.c b/p11-kit/compat.c
new file mode 100644
index 0000000..5fe8a84
--- /dev/null
+++ b/p11-kit/compat.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2011 Collabora Ltd.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@collabora.co.uk>
+ */
+
+#include "config.h"
+
+#include "compat.h"
+#include "private.h"
+
+#include <assert.h>
+
+#ifdef OS_UNIX
+
+void
+mutex_init (mutex_t *mutex)
+{
+ pthread_mutexattr_t attr;
+ int ret;
+
+ pthread_mutexattr_init (&attr);
+ pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
+ ret = pthread_mutex_init (mutex, &attr);
+ assert (ret == 0);
+ pthread_mutexattr_destroy (&attr);
+}
+
+#endif /* OS_UNIX */
+
+#ifdef OS_WIN32
+
+const char *
+module_error (void)
+{
+ DWORD code = GetLastError();
+ p11_local *local;
+ LPVOID msg_buf;
+
+ local = _p11_library_get_thread_local ();
+
+ FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, code,
+ MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&msg_buf, 0, NULL);
+
+ if (local->last_error)
+ LocalFree (local->last_error);
+ local->last_error = msg_buf;
+
+ return msg_buf;
+}
+
+int
+thread_create (thread_t *thread,
+ thread_routine routine,
+ void *arg)
+{
+ assert (thread);
+
+ *thread = CreateThread (NULL, 0,
+ (LPTHREAD_START_ROUTINE)routine,
+ arg, 0, NULL);
+
+ if (*thread == NULL)
+ return GetLastError ();
+
+ return 0;
+}
+
+int
+thread_join (thread_t thread)
+{
+ DWORD res;
+
+ res = WaitForSingleObject (thread, INFINITE);
+ if (res == WAIT_FAILED)
+ return GetLastError ();
+
+ CloseHandle (thread);
+ return 0;
+}
+
+#endif /* OS_WIN32 */
diff --git a/p11-kit/compat.h b/p11-kit/compat.h
new file mode 100644
index 0000000..4972b19
--- /dev/null
+++ b/p11-kit/compat.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2011 Collabora Ltd.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@collabora.co.uk>
+ */
+
+#ifndef __COMPAT_H__
+#define __COMPAT_H__
+
+#include "config.h"
+
+/* -----------------------------------------------------------------------------
+ * WIN32
+ */
+
+#ifdef OS_WIN32
+
+#define _WIN32_WINNT 0x500
+#define _WIN32_IE 0x400
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+
+/* Oh ... my ... god */
+#undef CreateMutex
+
+typedef CRITICAL_SECTION mutex_t;
+
+typedef HANDLE thread_t;
+
+#define mutex_init(m) \
+ (InitializeCriticalSection (m))
+#define mutex_lock(m) \
+ (EnterCriticalSection (m))
+#define mutex_unlock(m) \
+ (LeaveCriticalSection (m))
+#define mutex_uninit(m) \
+ (DeleteCriticalSection (m))
+
+typedef void * (*thread_routine) (void *arg);
+
+int thread_create (thread_t *thread, thread_routine, void *arg);
+
+int thread_join (thread_t thread);
+
+#define thread_self() \
+ (GetCurrentThread ())
+
+typedef HMODULE dl_module_t;
+
+#define module_open(f) \
+ (LoadLibrary (f))
+#define module_close(d) \
+ (FreeLibrary (d))
+#define module_symbol(d, s) \
+ ((void *)GetProcAddress ((d), (s)))
+
+const char * module_error (void);
+
+#define sleep_ms(ms) \
+ (Sleep (ms))
+
+#endif /* OS_WIN32 */
+
+/* ----------------------------------------------------------------------------
+ * UNIX
+ */
+
+#ifdef OS_UNIX
+
+#include <pthread.h>
+#include <dlfcn.h>
+#include <time.h>
+
+typedef pthread_mutex_t mutex_t;
+
+void mutex_init (mutex_t *mutex);
+
+#define mutex_lock(m) \
+ (pthread_mutex_lock (m))
+#define mutex_unlock(m) \
+ (pthread_mutex_unlock (m))
+#define mutex_uninit(m) \
+ (pthread_mutex_destroy(m))
+
+typedef pthread_t thread_t;
+
+typedef void * (*thread_routine) (void *arg);
+
+#define thread_create(t, r, a) \
+ (pthread_create ((t), NULL, (r), (a)))
+#define thread_join(t) \
+ (pthread_join ((t), NULL))
+#define thread_self(m) \
+ (pthread_self ())
+
+typedef void * dl_module_t;
+
+#define module_open(f) \
+ (dlopen ((f), RTLD_LOCAL | RTLD_NOW))
+#define module_close(d) \
+ (dlclose(d))
+#define module_error() \
+ (dlerror ())
+#define module_symbol(d, s) \
+ (dlsym ((d), (s)))
+
+#define sleep_ms(ms) \
+ do { int _ms = (ms); \
+ struct timespec _ts = { _ms / 1000, (_ms % 1000) * 1000 * 1000 }; \
+ nanosleep (&_ts, NULL); \
+ } while(0)
+
+#endif /* OS_UNIX */
+
+#endif /* __COMPAT_H__ */
diff --git a/p11-kit/conf.c b/p11-kit/conf.c
index 1e2d880..b05c8aa 100644
--- a/p11-kit/conf.c
+++ b/p11-kit/conf.c
@@ -37,6 +37,7 @@
#include "config.h"
+#include "compat.h"
#include "conf.h"
#define DEBUG_FLAG DEBUG_CONF
#include "debug.h"
@@ -50,13 +51,20 @@
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
-#include <pwd.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#ifdef OS_UNIX
+#include <pwd.h>
+#endif
+
+#ifdef OS_WIN32
+#include <shlobj.h>
+#endif
+
static void
strcln (char* data, char ch)
{
@@ -327,31 +335,47 @@ _p11_conf_parse_file (const char* filename, int flags)
return map;
}
-static char*
+static char *
expand_user_path (const char *path)
{
const char *env;
- struct passwd *pwd;
- int error = 0;
- if (path[0] == '~' && path[1] == '/') {
- env = getenv ("HOME");
- if (env && env[0]) {
- return strconcat (env, path + 1, NULL);
- } else {
- pwd = getpwuid (getuid ());
- if (!pwd) {
- error = errno;
- _p11_message ("couldn't lookup home directory for user %d: %s",
- getuid (), strerror (errno));
- errno = error;
- return NULL;
- }
- return strconcat (pwd->pw_dir, path + 1, NULL);
+ if (path[0] != '~' || path[1] != '/')
+ return strdup (path);
+
+ path += 1;
+ env = getenv ("HOME");
+ if (env && env[0]) {
+ return strconcat (env, path, NULL);
+
+ } else {
+#ifdef OS_UNIX
+ struct passwd *pwd;
+ int error = 0;
+
+ pwd = getpwuid (getuid ());
+ if (!pwd) {
+ error = errno;
+ _p11_message ("couldn't lookup home directory for user %d: %s",
+ getuid (), strerror (errno));
+ errno = error;
+ return NULL;
}
- }
- return strdup (path);
+ return strconcat (pwd->pw_dir, path, NULL);
+
+#else /* OS_WIN32 */
+ char directory[MAX_PATH + 1];
+
+ if (!SHGetSpecialFolderPathA (NULL, directory, CSIDL_PROFILE, TRUE)) {
+ _p11_message ("couldn't lookup home directory for user");
+ errno = ENOTDIR;
+ return NULL;
+ }
+
+ return strconcat (directory, path, NULL);
+#endif /* OS_WIN32 */
+ }
}
static int
diff --git a/p11-kit/debug.c b/p11-kit/debug.c
index e4b39f0..5766dae 100644
--- a/p11-kit/debug.c
+++ b/p11-kit/debug.c
@@ -36,9 +36,10 @@
#include "config.h"
+#include "compat.h"
#include "debug.h"
-#include <pthread.h>
+#include <assert.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
@@ -58,10 +59,11 @@ static struct DebugKey debug_keys[] = {
{ 0, }
};
-pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER;
+static int debug_inited = 0;
+static mutex_t debug_mutex;
/* global variable exported in debug.h */
-int debug_current_flags = ~0;
+int debug_current_flags;
static int
parse_environ_flags (void)
@@ -109,22 +111,21 @@ parse_environ_flags (void)
}
void
+debug_init (void)
+{
+ debug_current_flags = parse_environ_flags ();
+ mutex_init (&debug_mutex);
+ debug_inited = 1;
+}
+
+void
debug_message (int flag, const char *format, ...)
{
- static int initialized_flags = 0;
char buffer[512];
va_list args;
- pthread_mutex_lock (&debug_mutex);
-
- /*
- * This is not thread-safe, but it's not really the end of the
- * world if it happens more than once.
- */
- if (!initialized_flags) {
- initialized_flags = 1;
- debug_current_flags = parse_environ_flags ();
- }
+ assert (debug_inited);
+ mutex_lock (&debug_mutex);
if (flag & debug_current_flags) {
va_start (args, format);
@@ -134,5 +135,5 @@ debug_message (int flag, const char *format, ...)
fprintf (stderr, "(p11-kit:%d) %s\n", getpid(), buffer);
}
- pthread_mutex_unlock (&debug_mutex);
+ mutex_unlock (&debug_mutex);
}
diff --git a/p11-kit/debug.h b/p11-kit/debug.h
index 2d6a226..b8490dd 100644
--- a/p11-kit/debug.h
+++ b/p11-kit/debug.h
@@ -45,6 +45,8 @@ typedef enum {
extern int debug_current_flags;
+void debug_init (void);
+
void debug_message (int flag,
const char *format,
...);
diff --git a/p11-kit/modules.c b/p11-kit/modules.c
index 1394532..34926a4 100644
--- a/p11-kit/modules.c
+++ b/p11-kit/modules.c
@@ -48,10 +48,8 @@
#include <assert.h>
#include <dirent.h>
-#include <dlfcn.h>
#include <errno.h>
#include <limits.h>
-#include <pthread.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
@@ -105,23 +103,15 @@ typedef struct _Module {
hashmap *config;
/* Loaded modules */
- void *dl_module;
+ dl_module_t dl_module;
/* Initialization, mutex must be held */
- pthread_mutex_t initialize_mutex;
+ mutex_t initialize_mutex;
int initialize_called;
- pthread_t initialize_thread;
+ thread_t initialize_thread;
} Module;
/*
- * This is the mutex that protects the global data of this library
- * and the pkcs11 proxy module. Note that we *never* call into our
- * underlying pkcs11 modules while holding this mutex. Therefore it
- * doesn't have to be recursive and we can keep things simple.
- */
-pthread_mutex_t _p11_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-/*
* Shared data between threads, protected by the mutex, a structure so
* we can audit thread safety easier.
*/
@@ -137,20 +127,15 @@ static struct _Shared {
static CK_RV
create_mutex (CK_VOID_PTR_PTR mut)
{
- pthread_mutex_t *pmutex;
- int err;
+ mutex_t *pmutex;
if (mut == NULL)
return CKR_ARGUMENTS_BAD;
- pmutex = malloc (sizeof (pthread_mutex_t));
+ pmutex = malloc (sizeof (mutex_t));
if (!pmutex)
return CKR_HOST_MEMORY;
- err = pthread_mutex_init (pmutex, NULL);
- if (err == ENOMEM)
- return CKR_HOST_MEMORY;
- else if (err != 0)
- return CKR_GENERAL_ERROR;
+ mutex_init (pmutex);
*mut = pmutex;
return CKR_OK;
}
@@ -158,17 +143,12 @@ create_mutex (CK_VOID_PTR_PTR mut)
static CK_RV
destroy_mutex (CK_VOID_PTR mut)
{
- pthread_mutex_t *pmutex = mut;
- int err;
+ mutex_t *pmutex = mut;
if (mut == NULL)
return CKR_MUTEX_BAD;
- err = pthread_mutex_destroy (pmutex);
- if (err == EINVAL)
- return CKR_MUTEX_BAD;
- else if (err != 0)
- return CKR_GENERAL_ERROR;
+ mutex_uninit (pmutex);
free (pmutex);
return CKR_OK;
}
@@ -176,36 +156,24 @@ destroy_mutex (CK_VOID_PTR mut)
static CK_RV
lock_mutex (CK_VOID_PTR mut)
{
- pthread_mutex_t *pmutex = mut;
- int err;
+ mutex_t *pmutex = mut;
if (mut == NULL)
return CKR_MUTEX_BAD;
- err = pthread_mutex_lock (pmutex);
- if (err == EINVAL)
- return CKR_MUTEX_BAD;
- else if (err != 0)
- return CKR_GENERAL_ERROR;
+ mutex_lock (pmutex);
return CKR_OK;
}
static CK_RV
unlock_mutex (CK_VOID_PTR mut)
{
- pthread_mutex_t *pmutex = mut;
- int err;
+ mutex_t *pmutex = mut;
if (mut == NULL)
return CKR_MUTEX_BAD;
- err = pthread_mutex_unlock (pmutex);
- if (err == EINVAL)
- return CKR_MUTEX_BAD;
- else if (err == EPERM)
- return CKR_MUTEX_NOT_LOCKED;
- else if (err != 0)
- return CKR_GENERAL_ERROR;
+ mutex_unlock (pmutex);
return CKR_OK;
}
@@ -224,9 +192,9 @@ free_module_unlocked (void *data)
assert (mod->ref_count == 0);
if (mod->dl_module)
- dlclose (mod->dl_module);
+ module_close (mod->dl_module);
- pthread_mutex_destroy (&mod->initialize_mutex);
+ mutex_uninit (&mod->initialize_mutex);
hash_free (mod->config);
free (mod->name);
free (mod);
@@ -246,7 +214,7 @@ alloc_module_unlocked (void)
mod->init_args.LockMutex = lock_mutex;
mod->init_args.UnlockMutex = unlock_mutex;
mod->init_args.flags = CKF_OS_LOCKING_OK;
- pthread_mutex_init (&mod->initialize_mutex, NULL);
+ mutex_init (&mod->initialize_mutex);
return mod;
}
@@ -294,16 +262,16 @@ dlopen_and_get_function_list (Module *mod, const char *path)
assert (mod);
assert (path);
- mod->dl_module = dlopen (path, RTLD_LOCAL | RTLD_NOW);
+ mod->dl_module = module_open (path);
if (mod->dl_module == NULL) {
- _p11_message ("couldn't load module: %s: %s", path, dlerror ());
+ _p11_message ("couldn't load module: %s: %s", path, module_error ());
return CKR_GENERAL_ERROR;
}
- gfl = dlsym (mod->dl_module, "C_GetFunctionList");
+ gfl = module_symbol (mod->dl_module, "C_GetFunctionList");
if (!gfl) {
_p11_message ("couldn't find C_GetFunctionList entry point in module: %s: %s",
- path, dlerror ());
+ path, module_error ());
return CKR_GENERAL_ERROR;
}
@@ -515,10 +483,10 @@ static CK_RV
initialize_module_unlocked_reentrant (Module *mod)
{
CK_RV rv = CKR_OK;
- pthread_t self;
+ thread_t self;
assert (mod);
- self = pthread_self ();
+ self = thread_self ();
if (mod->initialize_thread == self) {
_p11_message ("p11-kit initialization called recursively");
@@ -533,7 +501,7 @@ initialize_module_unlocked_reentrant (Module *mod)
mod->initialize_thread = self;
/* Change over to the module specific mutex */
- pthread_mutex_lock (&mod->initialize_mutex);
+ mutex_lock (&mod->initialize_mutex);
_p11_unlock ();
if (!mod->initialize_called) {
@@ -554,7 +522,7 @@ initialize_module_unlocked_reentrant (Module *mod)
rv = CKR_OK;
}
- pthread_mutex_unlock (&mod->initialize_mutex);
+ mutex_unlock (&mod->initialize_mutex);
_p11_lock ();
/* Don't claim reference if failed */
@@ -565,6 +533,8 @@ initialize_module_unlocked_reentrant (Module *mod)
return rv;
}
+#ifdef OS_UNIX
+
static void
reinitialize_after_fork (void)
{
@@ -593,6 +563,8 @@ reinitialize_after_fork (void)
_p11_kit_proxy_after_fork ();
}
+#endif /* OS_UNIX */
+
static CK_RV
init_globals_unlocked (void)
{
@@ -607,7 +579,9 @@ init_globals_unlocked (void)
if (once)
return CKR_OK;
+#ifdef OS_UNIX
pthread_atfork (NULL, NULL, reinitialize_after_fork);
+#endif
once = 1;
return CKR_OK;
@@ -654,7 +628,7 @@ finalize_module_unlocked_reentrant (Module *mod)
*/
++mod->ref_count;
- pthread_mutex_lock (&mod->initialize_mutex);
+ mutex_lock (&mod->initialize_mutex);
_p11_unlock ();
if (mod->initialize_called) {
@@ -665,7 +639,7 @@ finalize_module_unlocked_reentrant (Module *mod)
mod->initialize_called = 0;
}
- pthread_mutex_unlock (&mod->initialize_mutex);
+ mutex_unlock (&mod->initialize_mutex);
_p11_lock ();
/* Match the increment above */
@@ -748,6 +722,8 @@ p11_kit_initialize_registered (void)
/* WARNING: This function must be reentrant */
debug ("in");
+ _p11_library_init_once ();
+
_p11_lock ();
_p11_kit_clear_message ();
@@ -833,6 +809,8 @@ p11_kit_finalize_registered (void)
/* WARNING: This function must be reentrant */
debug ("in");
+ _p11_library_init_once ();
+
_p11_lock ();
_p11_kit_clear_message ();
@@ -886,6 +864,8 @@ p11_kit_registered_modules (void)
{
CK_FUNCTION_LIST_PTR_PTR result;
+ _p11_library_init_once ();
+
_p11_lock ();
_p11_kit_clear_message ();
@@ -916,6 +896,8 @@ p11_kit_registered_module_to_name (CK_FUNCTION_LIST_PTR module)
Module *mod;
char *name = NULL;
+ _p11_library_init_once ();
+
_p11_lock ();
_p11_kit_clear_message ();
@@ -980,6 +962,8 @@ p11_kit_registered_option (CK_FUNCTION_LIST_PTR module, const char *field)
char *option = NULL;
hashmap *config = NULL;
+ _p11_library_init_once ();
+
_p11_lock ();
_p11_kit_clear_message ();
@@ -1044,6 +1028,8 @@ p11_kit_initialize_module (CK_FUNCTION_LIST_PTR module)
/* WARNING: This function must be reentrant for the same arguments */
debug ("in");
+ _p11_library_init_once ();
+
_p11_lock ();
_p11_kit_clear_message ();
@@ -1127,6 +1113,8 @@ p11_kit_finalize_module (CK_FUNCTION_LIST_PTR module)
/* WARNING: This function must be reentrant for the same arguments */
debug ("in");
+ _p11_library_init_once ();
+
_p11_lock ();
_p11_kit_clear_message ();
@@ -1191,6 +1179,8 @@ p11_kit_load_initialize_module (const char *module_path,
/* WARNING: This function must be reentrant for the same arguments */
debug ("in: %s", module_path);
+ _p11_library_init_once ();
+
_p11_lock ();
_p11_kit_clear_message ();
diff --git a/p11-kit/private.h b/p11-kit/private.h
index b5a8653..a8f46c5 100644
--- a/p11-kit/private.h
+++ b/p11-kit/private.h
@@ -36,15 +36,45 @@
#define __P11_KIT_PRIVATE_H__
#include "pkcs11.h"
-#include "pthread.h"
+#include "compat.h"
-extern pthread_mutex_t _p11_mutex;
+extern mutex_t _p11_mutex;
-#define _p11_lock() pthread_mutex_lock (&_p11_mutex);
+#define P11_MAX_MESSAGE 512
-#define _p11_unlock() pthread_mutex_unlock (&_p11_mutex);
+typedef struct {
+ char message[P11_MAX_MESSAGE];
+#ifdef OS_WIN32
+ void *last_error;
+#endif
+} p11_local;
-void _p11_message (const char* msg, ...);
+#define _p11_lock() mutex_lock (&_p11_mutex);
+
+#define _p11_unlock() mutex_unlock (&_p11_mutex);
+
+void _p11_message (const char* msg, ...);
+
+p11_local * _p11_library_get_thread_local (void);
+
+#ifdef OS_WIN32
+
+/* No implementation, because done by DllMain */
+#define _p11_library_init_once()
+
+#else /* !OS_WIN32 */
+
+extern pthread_once_t _p11_once;
+
+#define _p11_library_init_once() \
+ pthread_once (&_p11_once, _p11_library_init);
+
+#endif /* !OS_WIN32 */
+
+
+void _p11_library_init (void);
+
+void _p11_library_uninit (void);
CK_FUNCTION_LIST_PTR_PTR _p11_kit_registered_modules_unlocked (void);
diff --git a/p11-kit/proxy.c b/p11-kit/proxy.c
index 0f0fc42..ebb1309 100644
--- a/p11-kit/proxy.c
+++ b/p11-kit/proxy.c
@@ -38,6 +38,7 @@
#define DEBUG_FLAG DEBUG_PROXY
#include "debug.h"
#include "hashmap.h"
+#define CRYPTOKI_EXPORTS
#include "pkcs11.h"
#include "p11-kit.h"
#include "private.h"
@@ -46,7 +47,6 @@
#include <sys/types.h>
#include <assert.h>
#include <errno.h>
-#include <pthread.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
@@ -1389,8 +1389,13 @@ static CK_FUNCTION_LIST proxy_function_list = {
proxy_C_WaitForSlotEvent
};
+#ifdef OS_WIN32
+__declspec(dllexport)
+#endif
+
CK_RV
C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
{
+ _p11_library_init_once ();
return proxy_C_GetFunctionList (list);
}
diff --git a/p11-kit/util.c b/p11-kit/util.c
index fdf434b..eab0b13 100644
--- a/p11-kit/util.c
+++ b/p11-kit/util.c
@@ -36,6 +36,7 @@
#include "config.h"
+#include "debug.h"
#include "p11-kit.h"
#include "private.h"
#include "util.h"
@@ -46,6 +47,18 @@
#include <stdio.h>
#include <string.h>
+/*
+ * This is the mutex that protects the global data of this library
+ * and the pkcs11 proxy module. Note that we *never* call into our
+ * underlying pkcs11 modules while holding this mutex. Therefore it
+ * doesn't have to be recursive and we can keep things simple.
+ */
+mutex_t _p11_mutex;
+
+#ifdef OS_UNIX
+pthread_once_t _p11_once;
+#endif
+
/**
* SECTION:p11-kit-future
* @title: Future
@@ -56,9 +69,6 @@
* MACRO. See the p11-kit.h header for more details.
*/
-#define MAX_MESSAGE 512
-static pthread_once_t key_once = PTHREAD_ONCE_INIT;
-static pthread_key_t message_buffer_key = 0;
static int print_messages = 1;
void*
@@ -143,44 +153,34 @@ p11_kit_space_strdup (const unsigned char *string, size_t max_length)
}
static void
-create_message_buffer_key (void)
-{
- pthread_key_create (&message_buffer_key, free);
-}
-
-static void
store_message_buffer (const char* msg, size_t length)
{
- char *thread_buf;
+ p11_local *local;
- if (length > MAX_MESSAGE - 1)
- length = MAX_MESSAGE - 1;
+ if (length > P11_MAX_MESSAGE - 1)
+ length = P11_MAX_MESSAGE - 1;
- pthread_once (&key_once, create_message_buffer_key);
- thread_buf = pthread_getspecific (message_buffer_key);
- if (!thread_buf) {
- thread_buf = malloc (MAX_MESSAGE);
- pthread_setspecific (message_buffer_key, thread_buf);
+ local = _p11_library_get_thread_local ();
+ if (local != NULL) {
+ memcpy (local->message, msg, length);
+ local->message[length] = 0;
}
-
- memcpy (thread_buf, msg, length);
- thread_buf[length] = 0;
}
void
_p11_message (const char* msg, ...)
{
- char buffer[MAX_MESSAGE];
+ char buffer[P11_MAX_MESSAGE];
va_list va;
size_t length;
va_start (va, msg);
- length = vsnprintf (buffer, MAX_MESSAGE - 1, msg, va);
+ length = vsnprintf (buffer, P11_MAX_MESSAGE - 1, msg, va);
va_end (va);
/* Was it truncated? */
- if (length > MAX_MESSAGE - 1)
- length = MAX_MESSAGE - 1;
+ if (length > P11_MAX_MESSAGE - 1)
+ length = P11_MAX_MESSAGE - 1;
buffer[length] = 0;
/* If printing is not disabled, just print out */
@@ -220,20 +220,18 @@ p11_kit_be_quiet (void)
const char*
p11_kit_message (void)
{
- char *thread_buf;
- pthread_once (&key_once, create_message_buffer_key);
- thread_buf = pthread_getspecific (message_buffer_key);
- return thread_buf && thread_buf[0] ? thread_buf : NULL;
+ p11_local *local;
+ local = _p11_library_get_thread_local ();
+ return local && local->message[0] ? local->message : NULL;
}
void
_p11_kit_clear_message (void)
{
- char *thread_buf;
- pthread_once (&key_once, create_message_buffer_key);
- thread_buf = pthread_getspecific (message_buffer_key);
- if (thread_buf != NULL)
- thread_buf[0] = 0;
+ p11_local *local;
+ local = _p11_library_get_thread_local ();
+ if (local != NULL)
+ local->message[0] = 0;
}
void
@@ -246,3 +244,127 @@ _p11_kit_default_message (CK_RV rv)
store_message_buffer (msg, strlen (msg));
}
}
+
+#ifdef OS_UNIX
+
+static pthread_key_t thread_local = 0;
+
+p11_local *
+_p11_library_get_thread_local (void)
+{
+ p11_local *local;
+
+ _p11_library_init_once ();
+
+ local = pthread_getspecific (thread_local);
+ if (local == NULL) {
+ local = calloc (1, sizeof (p11_local));
+ pthread_setspecific (thread_local, local);
+ }
+
+ return local;
+}
+
+void
+_p11_library_init (void)
+{
+ debug_init ();
+ mutex_init (&_p11_mutex);
+ pthread_key_create (&thread_local, free);
+}
+
+void
+_p11_library_uninit (void)
+{
+ pthread_key_delete (thread_local);
+ mutex_uninit (&_p11_mutex);
+}
+
+#endif /* OS_UNIX */
+
+#ifdef OS_WIN32
+
+static DWORD thread_local = TLS_OUT_OF_INDEXES;
+
+BOOL WINAPI DllMain (HINSTANCE, DWORD, LPVOID);
+
+p11_local *
+_p11_library_get_thread_local (void)
+{
+ LPVOID data;
+
+ if (thread_local == TLS_OUT_OF_INDEXES)
+ return NULL;
+
+ data = TlsGetValue (thread_local);
+ if (data == NULL) {
+ data = LocalAlloc (LPTR, sizeof (p11_local));
+ TlsSetValue (thread_local, data);
+ }
+
+ return (p11_local *)data;
+}
+
+void
+_p11_library_init (void)
+{
+ debug_init ();
+ mutex_init (&_p11_mutex);
+ thread_local = TlsAlloc ();
+}
+
+static void
+free_tls_value (LPVOID data)
+{
+ p11_local *local = data;
+ if (local->last_error)
+ LocalFree (local->last_error);
+ LocalFree (data);
+}
+
+void
+_p11_library_uninit (void)
+{
+ LPVOID data;
+
+ if (thread_local != TLS_OUT_OF_INDEXES) {
+ data = TlsGetValue (thread_local);
+ free_tls_value (data);
+ TlsFree (thread_local);
+ }
+ mutex_uninit (&_p11_mutex);
+}
+
+BOOL WINAPI
+DllMain (HINSTANCE instance,
+ DWORD reason,
+ LPVOID reserved)
+{
+ LPVOID data;
+
+ switch (reason) {
+ case DLL_PROCESS_ATTACH:
+ _p11_library_init ();
+ if (thread_local == TLS_OUT_OF_INDEXES)
+ return FALSE;
+ break;
+
+ case DLL_THREAD_DETACH:
+ if (thread_local != TLS_OUT_OF_INDEXES) {
+ data = TlsGetValue (thread_local);
+ free_tls_value (data);
+ }
+ break;
+
+ case DLL_PROCESS_DETACH:
+ _p11_library_uninit ();
+ break;
+
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+#endif /* OS_WIN32 */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ab7d8f8..243b869 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -10,26 +10,26 @@ LDADD = \
$(top_builddir)/p11-kit/libp11-kit-testable.la \
$(LTLIBINTL)
-noinst_PROGRAMS = \
+CHECK_PROGS = \
hash-test \
ptr-array-test \
conf-test \
uri-test \
pin-test \
- print-messages \
test-init
+noinst_PROGRAMS = \
+ print-messages \
+ $(CHECK_PROGS)
+
test_init_SOURCES = \
test-init.c \
mock-module.c mock-module.h
+CHECK_EXECUTABLES = $(CHECK_PROGS:=$(EXEEXT))
+
check-am:
- ./hash-test
- ./ptr-array-test
- ./conf-test
- ./uri-test
- ./pin-test
- ./test-init
+ for prog in $(CHECK_EXECUTABLES); do ./$$prog; done
EXTRA_DIST = \
cutest \
diff --git a/tests/conf-test.c b/tests/conf-test.c
index a273c7b..58cb2f4 100644
--- a/tests/conf-test.c
+++ b/tests/conf-test.c
@@ -375,6 +375,8 @@ main (void)
CuSuite* suite = CuSuiteNew ();
int ret;
+ _p11_library_init ();
+
SUITE_ADD_TEST (suite, test_parse_conf_1);
SUITE_ADD_TEST (suite, test_parse_ignore_missing);
SUITE_ADD_TEST (suite, test_parse_fail_missing);
diff --git a/tests/mock-module.c b/tests/mock-module.c
index 201fffc..1b7822a 100644
--- a/tests/mock-module.c
+++ b/tests/mock-module.c
@@ -34,10 +34,12 @@
#include "config.h"
+#define CRYPTOKI_EXPORTS
#include "pkcs11.h"
#include "mock-module.h"
-#include <pthread.h>
+#include "p11-kit/compat.h"
+
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
@@ -48,7 +50,7 @@
*/
/* Various mutexes */
-static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
+static mutex_t init_mutex;
/* Whether we've been initialized, and on what process id it happened */
static int pkcs11_initialized = 0;
@@ -95,7 +97,7 @@ mock_C_Initialize (CK_VOID_PTR init_args)
debug (("C_Initialize: enter"));
- pthread_mutex_lock (&init_mutex);
+ mutex_lock (&init_mutex);
if (init_args != NULL) {
int supplied_ok;
@@ -146,7 +148,7 @@ done:
pkcs11_initialized_pid = 0;
}
- pthread_mutex_unlock (&init_mutex);
+ mutex_unlock (&init_mutex);
debug (("C_Initialize: %d", ret));
return ret;
@@ -159,13 +161,13 @@ mock_C_Finalize (CK_VOID_PTR reserved)
return_val_if_fail (pkcs11_initialized != 0, CKR_CRYPTOKI_NOT_INITIALIZED);
return_val_if_fail (reserved == NULL, CKR_ARGUMENTS_BAD);
- pthread_mutex_lock (&init_mutex);
+ mutex_lock (&init_mutex);
/* This should stop all other calls in */
pkcs11_initialized = 0;
pkcs11_initialized_pid = 0;
- pthread_mutex_unlock (&init_mutex);
+ mutex_unlock (&init_mutex);
debug (("C_Finalize: %d", CKR_OK));
return CKR_OK;
@@ -884,3 +886,9 @@ CK_FUNCTION_LIST mock_module_no_slots = {
mock_C_CancelFunction__not_parallel,
mock_C_WaitForSlotEvent__no_event,
};
+
+void
+mock_module_init (void)
+{
+ mutex_init (&init_mutex);
+}
diff --git a/tests/mock-module.h b/tests/mock-module.h
index f198e46..21fa17a 100644
--- a/tests/mock-module.h
+++ b/tests/mock-module.h
@@ -28,6 +28,7 @@
CK_FUNCTION_LIST mock_module_no_slots;
+void mock_module_init (void);
CK_RV mock_C_Initialize (CK_VOID_PTR init_args);
diff --git a/tests/pin-test.c b/tests/pin-test.c
index 0117908..f4cfd8d 100644
--- a/tests/pin-test.c
+++ b/tests/pin-test.c
@@ -42,6 +42,7 @@
#include <string.h>
#include "p11-kit/pin.h"
+#include "p11-kit/private.h"
static P11KitPin *
callback_one (const char *pin_source, P11KitUri *pin_uri, const char *pin_description,
@@ -274,6 +275,8 @@ main (void)
CuSuite* suite = CuSuiteNew ();
int ret;
+ _p11_library_init ();
+
SUITE_ADD_TEST (suite, test_pin_register_unregister);
SUITE_ADD_TEST (suite, test_pin_read);
SUITE_ADD_TEST (suite, test_pin_read_no_match);
diff --git a/tests/test-init.c b/tests/test-init.c
index d57b49f..8367f10 100644
--- a/tests/test-init.c
+++ b/tests/test-init.c
@@ -36,22 +36,25 @@
#include "CuTest.h"
#include <sys/types.h>
-#include <sys/wait.h>
#include <assert.h>
-#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
+#include "p11-kit/compat.h"
#include "p11-kit/p11-kit.h"
#include "mock-module.h"
CK_FUNCTION_LIST module;
+#ifdef OS_UNIX
+
+#include <sys/wait.h>
+
static CK_RV
mock_C_Initialize__with_fork (CK_VOID_PTR init_args)
{
@@ -95,6 +98,8 @@ test_fork_initialization (CuTest *tc)
CuAssertTrue (tc, rv == CKR_OK);
}
+#endif /* OS_UNIX */
+
static CK_RV
mock_C_Initialize__with_recursive (CK_VOID_PTR init_args)
{
@@ -120,7 +125,7 @@ test_recursive_initialization (CuTest *tc)
CuAssertTrue (tc, rv == CKR_FUNCTION_FAILED);
}
-static pthread_mutex_t race_mutex = PTHREAD_MUTEX_INITIALIZER;
+static mutex_t race_mutex;
static int initialization_count = 0;
static int finalization_count = 0;
@@ -129,30 +134,25 @@ static int finalization_count = 0;
static CK_RV
mock_C_Initialize__threaded_race (CK_VOID_PTR init_args)
{
- struct timespec ts = { 0, 100 * 1000 * 1000 };
-
/* Atomically increment value */
- pthread_mutex_lock (&race_mutex);
+ mutex_lock (&race_mutex);
initialization_count += 1;
- pthread_mutex_unlock (&race_mutex);
+ mutex_unlock (&race_mutex);
- nanosleep (&ts, NULL);
+ sleep_ms (100);
return CKR_OK;
}
static CK_RV
mock_C_Finalize__threaded_race (CK_VOID_PTR reserved)
{
- struct timespec ts = { 0, 100 * 1000 * 1000 };
-
/* Atomically increment value */
- pthread_mutex_lock (&race_mutex);
+ mutex_lock (&race_mutex);
finalization_count += 1;
- pthread_mutex_unlock (&race_mutex);
+ mutex_unlock (&race_mutex);
- nanosleep (&ts, NULL);
- return CKR_OK;
-}
+ sleep_ms (100);
+ return CKR_OK;}
static void *
initialization_thread (void *data)
@@ -181,9 +181,8 @@ finalization_thread (void *data)
static void
test_threaded_initialization (CuTest *tc)
{
- static const int num_threads = 100;
- pthread_t threads[num_threads];
- void *retval;
+ static const int num_threads = 2;
+ thread_t threads[num_threads];
int ret;
int i;
@@ -196,25 +195,27 @@ test_threaded_initialization (CuTest *tc)
finalization_count = 0;
for (i = 0; i < num_threads; i++) {
- ret = pthread_create (&threads[i], NULL, initialization_thread, tc);
+ ret = thread_create (&threads[i], initialization_thread, tc);
CuAssertIntEquals (tc, 0, ret);
+ CuAssertTrue (tc, threads[i] != 0);
}
for (i = 0; i < num_threads; i++) {
- ret = pthread_join (threads[i], &retval);
+ ret = thread_join (threads[i]);
CuAssertIntEquals (tc, 0, ret);
- CuAssertPtrEquals (tc, tc, retval);
+ threads[i] = 0;
}
for (i = 0; i < num_threads; i++) {
- ret = pthread_create (&threads[i], NULL, finalization_thread, tc);
+ ret = thread_create (&threads[i], finalization_thread, tc);
CuAssertIntEquals (tc, 0, ret);
+ CuAssertTrue (tc, threads[i] != 0);
}
for (i = 0; i < num_threads; i++) {
- ret = pthread_join (threads[i], &retval);
+ ret = thread_join (threads[i]);
CuAssertIntEquals (tc, 0, ret);
- CuAssertPtrEquals (tc, tc, retval);
+ threads[i] = 0;
}
/* C_Initialize should have been called exactly once */
@@ -229,7 +230,14 @@ main (void)
CuSuite* suite = CuSuiteNew ();
int ret;
+ mutex_init (&race_mutex);
+ mock_module_init ();
+ _p11_library_init ();
+
+#ifdef OS_UNIX
SUITE_ADD_TEST (suite, test_fork_initialization);
+#endif
+
SUITE_ADD_TEST (suite, test_recursive_initialization);
SUITE_ADD_TEST (suite, test_threaded_initialization);
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 13920d7..e38d1a4 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -7,6 +7,10 @@ INCLUDES = \
bin_PROGRAMS = \
p11-kit
+p11_kit_SOURCES = \
+ compat.c compat.h \
+ p11-kit.c
+
p11_kit_LDADD = \
$(top_builddir)/p11-kit/libp11-kit.la \
$(LTLIBINTL)
diff --git a/tools/compat.c b/tools/compat.c
new file mode 100644
index 0000000..93ba77c
--- /dev/null
+++ b/tools/compat.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2011 Collabora Ltd.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@collabora.co.uk>
+ */
+
+#include "config.h"
+
+#include "compat.h"
+
+#ifndef HAVE_ERR_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+static const char *
+calc_prog_name (void)
+{
+ static char prognamebuf[256];
+ static int prepared = 0;
+
+ if(!prepared)
+ {
+ const char* beg = strrchr(__argv[0], '\\');
+ const char* temp = strrchr(__argv[0], '/');
+ beg = (beg > temp) ? beg : temp;
+ beg = (beg) ? beg + 1 : __argv[0];
+
+ temp = strrchr(__argv[0], '.');
+ temp = (temp > beg) ? temp : __argv[0] + strlen(__argv[0]);
+
+ if((temp - beg) > 255)
+ temp = beg + 255;
+
+ strncpy(prognamebuf, beg, temp - beg);
+ prognamebuf[temp - beg] = 0;
+ prepared = 1;
+ }
+
+ return prognamebuf;
+}
+
+static FILE *err_file; /* file to use for error output */
+
+/*
+ * This is declared to take a `void *' so that the caller is not required
+ * to include <stdio.h> first. However, it is really a `FILE *', and the
+ * manual page documents it as such.
+ */
+void
+err_set_file (void *fp)
+{
+ if (fp)
+ err_file = fp;
+ else
+ err_file = stderr;
+}
+
+void
+err (int eval,
+ const char *fmt,
+ ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ verrc(eval, errno, fmt, ap);
+ va_end(ap);
+}
+
+void
+verr (int eval,
+ const char *fmt,
+ va_list ap)
+{
+ verrc(eval, errno, fmt, ap);
+}
+
+void
+errc (int eval,
+ int code,
+ const char *fmt,
+ ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ verrc(eval, code, fmt, ap);
+ va_end(ap);
+}
+
+void
+verrc (int eval,
+ int code,
+ const char *fmt,
+ va_list ap)
+{
+ if (err_file == 0)
+ err_set_file((FILE *)0);
+ fprintf(err_file, "%s: ", calc_prog_name());
+ if (fmt != NULL) {
+ vfprintf(err_file, fmt, ap);
+ fprintf(err_file, ": ");
+ }
+ fprintf(err_file, "%s\n", strerror(code));
+ exit(eval);
+}
+
+void
+errx (int eval,
+ const char *fmt,
+ ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ verrx(eval, fmt, ap);
+ va_end(ap);
+}
+
+void
+verrx (int eval,
+ const char *fmt,
+ va_list ap)
+{
+ if (err_file == 0)
+ err_set_file((FILE *)0);
+ fprintf(err_file, "%s: ", calc_prog_name());
+ if (fmt != NULL)
+ vfprintf(err_file, fmt, ap);
+ fprintf(err_file, "\n");
+ exit(eval);
+}
+
+void
+warn (const char *fmt,
+ ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vwarnc(errno, fmt, ap);
+ va_end(ap);
+}
+
+void
+vwarn (const char *fmt,
+ va_list ap)
+{
+ vwarnc(errno, fmt, ap);
+}
+
+void
+warnc (int code,
+ const char *fmt,
+ ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vwarnc(code, fmt, ap);
+ va_end(ap);
+}
+
+void
+vwarnc (int code,
+ const char *fmt,
+ va_list ap)
+{
+ if (err_file == 0)
+ err_set_file((FILE *)0);
+ fprintf(err_file, "%s: ", calc_prog_name());
+ if (fmt != NULL)
+ {
+ vfprintf(err_file, fmt, ap);
+ fprintf(err_file, ": ");
+ }
+ fprintf(err_file, "%s\n", strerror(code));
+}
+
+void
+warnx (const char *fmt,
+ ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vwarnx(fmt, ap);
+ va_end(ap);
+}
+
+void
+vwarnx (const char *fmt,
+ va_list ap)
+{
+ if(err_file == 0)
+ err_set_file((FILE*)0);
+ fprintf(err_file, "%s: ", calc_prog_name());
+ if(fmt != NULL)
+ vfprintf(err_file, fmt, ap);
+ fprintf(err_file, "\n");
+}
+
+#endif /* HAVE_ERR_H */
diff --git a/tools/compat.h b/tools/compat.h
new file mode 100644
index 0000000..1562964
--- /dev/null
+++ b/tools/compat.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2011 Collabora Ltd.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@collabora.co.uk>
+ */
+
+#ifndef __ERR_H__
+#define __ERR_H__
+
+#include "config.h"
+
+#ifdef HAVE_ERR_H
+#include <err.h>
+
+#else /* !HAVE_ERR_H */
+
+#include <stdarg.h>
+void err_set_file (void *fp);
+void err_set_exit (void (*ef)(int));
+void err (int eval, const char *fmt, ...);
+void verr (int eval, const char *fmt, va_list ap);
+void errc (int eval, int code, const char *fmt, ...);
+void verrc (int eval, int code, const char *fmt, va_list ap);
+void errx (int eval, const char *fmt, ...);
+void verrx (int eval, const char *fmt, va_list ap);
+void warn (const char *fmt, ...);
+void vwarn (const char *fmt, va_list ap);
+void warnc (int code, const char *fmt, ...);
+void vwarnc (int code, const char *fmt, va_list ap);
+void warnx (const char *fmt, ...);
+void vwarnx (const char *fmt, va_list ap);
+
+#endif /* !HAVE_ERR_H */
+
+#endif /* __ERR_H__ */
diff --git a/tools/p11-kit.c b/tools/p11-kit.c
index 44062d0..f63779e 100644
--- a/tools/p11-kit.c
+++ b/tools/p11-kit.c
@@ -34,9 +34,10 @@
#include "config.h"
+#include "compat.h"
+
#include <assert.h>
#include <ctype.h>
-#include <err.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
@@ -253,7 +254,7 @@ main (int argc, char *argv[])
break;
case 'v':
verbose = 1;
- setenv ("P11_KIT_DEBUG", "all", 1);
+ putenv ("P11_KIT_DEBUG=all");
break;
case 'h':
case '?':