From db92b76e3acb11e330309ebce071ec2e61400a71 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Mon, 17 Oct 2011 14:51:31 +0200 Subject: 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 --- .gitignore | 3 + configure.ac | 35 ++++++-- doc/Makefile.am | 2 +- p11-kit/Makefile.am | 1 + p11-kit/compat.c | 114 ++++++++++++++++++++++++++ p11-kit/compat.h | 143 ++++++++++++++++++++++++++++++++ p11-kit/conf.c | 64 ++++++++++----- p11-kit/debug.c | 31 +++---- p11-kit/debug.h | 2 + p11-kit/modules.c | 104 +++++++++++------------- p11-kit/private.h | 40 +++++++-- p11-kit/proxy.c | 7 +- p11-kit/util.c | 188 +++++++++++++++++++++++++++++++++++-------- tests/Makefile.am | 16 ++-- tests/conf-test.c | 2 + tests/mock-module.c | 20 +++-- tests/mock-module.h | 1 + tests/pin-test.c | 3 + tests/test-init.c | 56 +++++++------ tools/Makefile.am | 4 + tools/compat.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/compat.h | 63 +++++++++++++++ tools/p11-kit.c | 5 +- 23 files changed, 952 insertions(+), 180 deletions(-) create mode 100644 p11-kit/compat.c create mode 100644 p11-kit/compat.h create mode 100644 tools/compat.c create mode 100644 tools/compat.h 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 ]) +# ------------------------------------------------------------------------------ +# 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 ]) + 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 + */ + +#include "config.h" + +#include "compat.h" +#include "private.h" + +#include + +#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 + */ + +#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 + +/* 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 +#include +#include + +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 #include #include -#include #include #include #include #include #include +#ifdef OS_UNIX +#include +#endif + +#ifdef OS_WIN32 +#include +#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 +#include #include #include #include @@ -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 #include -#include #include #include -#include #include #include #include @@ -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 #include #include -#include #include #include #include @@ -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 #include +/* + * 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 +#include "p11-kit/compat.h" + #include #include #include @@ -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 #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 -#include #include -#include #include #include #include #include #include +#include "p11-kit/compat.h" #include "p11-kit/p11-kit.h" #include "mock-module.h" CK_FUNCTION_LIST module; +#ifdef OS_UNIX + +#include + 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 + */ + +#include "config.h" + +#include "compat.h" + +#ifndef HAVE_ERR_H + +#include +#include +#include +#include + +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 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 + */ + +#ifndef __ERR_H__ +#define __ERR_H__ + +#include "config.h" + +#ifdef HAVE_ERR_H +#include + +#else /* !HAVE_ERR_H */ + +#include +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 #include -#include #include #include #include @@ -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 '?': -- cgit v1.1