aboutsummaryrefslogtreecommitdiffstats
path: root/jnlib
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2007-06-06 18:12:30 +0000
committerWerner Koch <[email protected]>2007-06-06 18:12:30 +0000
commit2c9791db555cc571eaedfa71444da05454bd052a (patch)
tree9566d22f85e562e0c7b35dacc1697c9a58fcff1a /jnlib
parentPrint passphrase encoding info only in PEM mode. (diff)
downloadgnupg-2c9791db555cc571eaedfa71444da05454bd052a.tar.gz
gnupg-2c9791db555cc571eaedfa71444da05454bd052a.zip
First steps towards supporting W32.
This is mainly source code reorganization. Update gnulib. g10/ does currently not build.
Diffstat (limited to 'jnlib')
-rw-r--r--jnlib/ChangeLog22
-rw-r--r--jnlib/Makefile.am9
-rw-r--r--jnlib/dotlock.c1
-rw-r--r--jnlib/dynload.h73
-rw-r--r--jnlib/libjnlib-config.h13
-rw-r--r--jnlib/stringhelp.c2
-rw-r--r--jnlib/utf8conv.c57
-rw-r--r--jnlib/w32-gettext.c556
-rw-r--r--jnlib/w32-pth.c1500
-rw-r--r--jnlib/w32-pth.h245
-rw-r--r--jnlib/w32-reg.c184
-rw-r--r--jnlib/w32help.h41
12 files changed, 949 insertions, 1754 deletions
diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog
index 0db89e3c4..bb2d06574 100644
--- a/jnlib/ChangeLog
+++ b/jnlib/ChangeLog
@@ -1,3 +1,25 @@
+2007-06-06 Werner Koch <[email protected]>
+
+ * w32help.h: New.
+ * w32-gettext.c: New. Taken from gnupg 1.4, added ngettext,
+ changed to use jnlib malloc functions and put under the LGPL.
+ * w32-reg.c: New. Taken from../common/w32reg.c and changed to
+ LGPL. Changed API to use the jnlib malloc functions.
+ * Makefile.am (libjnlib_a_SOURCES) [!W32]: Do not build the w32
+ specific modules.
+
+ * dotlock.c: Include stringhelp.h for stpcpy prototype.
+
+2007-06-04 Werner Koch <[email protected]>
+
+ * dynload.h: New. Taken from ../common and changed to LGPL.
+
+ * utf8conv.c (load_libiconv): New. Taken from GnuPG 1.4
+
+2007-05-30 Werner Koch <[email protected]>
+
+ * w32-pth.h, w32-pth.c: Remove.
+
2007-04-25 Werner Koch <[email protected]>
* argparse.c (long_opt_strlen): Fixed for utf-8.
diff --git a/jnlib/Makefile.am b/jnlib/Makefile.am
index 951c562f2..0f593bb3f 100644
--- a/jnlib/Makefile.am
+++ b/jnlib/Makefile.am
@@ -41,9 +41,12 @@ libjnlib_a_SOURCES = \
argparse.c argparse.h \
logging.c logging.h \
dotlock.c dotlock.h \
- types.h mischelp.c mischelp.h \
- w32-pth.c w32-pth.h \
- w32-afunix.c w32-afunix.h
+ types.h mischelp.c mischelp.h dynload.h w32help.h
+
+if HAVE_W32_SYSTEM
+libjnlib_a_SOURCES += w32-reg.c w32-afunix.c w32-afunix.h w32-gettext.c
+endif
+
# For GnuPG we don't need the xmalloc stuff.
# xmalloc.c xmalloc.h
diff --git a/jnlib/dotlock.c b/jnlib/dotlock.c
index ba89bcea6..53fb52655 100644
--- a/jnlib/dotlock.c
+++ b/jnlib/dotlock.c
@@ -37,6 +37,7 @@
#include <signal.h>
#include "libjnlib-config.h"
+#include "stringhelp.h"
#include "dotlock.h"
#if !defined(DIRSEP_C) && !defined(EXTSEP_C) \
diff --git a/jnlib/dynload.h b/jnlib/dynload.h
new file mode 100644
index 000000000..e365d4f0d
--- /dev/null
+++ b/jnlib/dynload.h
@@ -0,0 +1,73 @@
+/* dynload.h - Wrapper functions for run-time dynamic loading
+ * Copyright (C) 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of JNLIB.
+ *
+ * JNLIB is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JNLIB is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef LIBJNLIB_DYNLOAD_H
+#define LIBJNLIB_DYNLOAD_H
+
+#ifndef __MINGW32__
+# include <dlfcn.h>
+#else
+# include <windows.h>
+
+# define RTLD_LAZY 0
+
+static inline void *
+dlopen (const char * name, int flag)
+{
+ void * hd = LoadLibrary (name);
+ return hd;
+}
+
+static inline void *
+dlsym (void *hd, const char *sym)
+{
+ if (hd && sym)
+ {
+ void * fnc = GetProcAddress (hd, sym);
+ if (!fnc)
+ return NULL;
+ return fnc;
+ }
+ return NULL;
+}
+
+
+static inline const char *
+dlerror (void)
+{
+ static char buf[32];
+ sprintf (buf, "ec=%lu", GetLastError ());
+ return buf;
+}
+
+
+static inline int
+dlclose (void * hd)
+{
+ if (hd)
+ {
+ CloseHandle (hd);
+ return 0;
+ }
+ return -1;
+}
+# endif /*__MINGW32__*/
+#endif /*LIBJNLIB_DYNLOAD_H*/
diff --git a/jnlib/libjnlib-config.h b/jnlib/libjnlib-config.h
index 4554b9d1a..6c9408fdb 100644
--- a/jnlib/libjnlib-config.h
+++ b/jnlib/libjnlib-config.h
@@ -34,11 +34,14 @@
#define JNLIB_NEED_UTF8CONV 1
+
+#if !defined(JNLIB_NEED_UTF8CONV) && defined(HAVE_W32_SYSTEM)
+#define JNLIB_NEED_UTF8CONV 1
+#endif
+
/* Gettext stuff */
#ifdef USE_SIMPLE_GETTEXT
- int set_gettext_file( const char *filename );
- const char *gettext( const char *msgid );
-
+# include "w32help.h"
# define _(a) gettext (a)
# define N_(a) (a)
@@ -61,7 +64,9 @@
#endif
#endif /* !USE_SIMPLE_GETTEXT */
-/* Malloc functions to be jused by jnlib. */
+/* Malloc functions to be used by jnlib. */
+#define jnlib_malloc(a) gcry_malloc( (a) )
+#define jnlib_calloc(a,b) gcry_calloc( (a), (b) )
#define jnlib_xmalloc(a) gcry_xmalloc( (a) )
#define jnlib_xcalloc(a,b) gcry_xcalloc( (a), (b) )
#define jnlib_xrealloc(a,n) gcry_xrealloc( (a), (n) )
diff --git a/jnlib/stringhelp.c b/jnlib/stringhelp.c
index b74f84a9c..b7f8b28db 100644
--- a/jnlib/stringhelp.c
+++ b/jnlib/stringhelp.c
@@ -821,7 +821,7 @@ memrchr (const void *buffer, int c, size_t n)
for (p += n; n ; n--)
if (*--p == c)
- return p;
+ return (void *)p;
return NULL;
}
#endif /*HAVE_MEMRCHR*/
diff --git a/jnlib/utf8conv.c b/jnlib/utf8conv.c
index d7c0d44ba..90a319984 100644
--- a/jnlib/utf8conv.c
+++ b/jnlib/utf8conv.c
@@ -29,10 +29,13 @@
#include <langinfo.h>
#endif
#include <errno.h>
-#include <iconv.h>
+#ifndef HAVE_W32_SYSTEM
+# include <iconv.h>
+#endif
#include "libjnlib-config.h"
#include "stringhelp.h"
+#include "dynload.h"
#include "utf8conv.h"
#ifndef MB_LEN_MAX
@@ -45,6 +48,58 @@ static int no_translation; /* Set to true if we let simply pass through. */
static int use_iconv; /* iconv comversion fucntions required. */
+/* Under W32 we dlopen the iconv dll and don't require any iconv
+ related headers at all. However we need to define some stuff. */
+#ifdef HAVE_W32_SYSTEM
+typedef void *iconv_t;
+#ifndef ICONV_CONST
+#define ICONV_CONST const
+#endif
+static iconv_t (* __stdcall iconv_open) (const char *tocode,
+ const char *fromcode);
+static size_t (* __stdcall iconv) (iconv_t cd,
+ const char **inbuf, size_t *inbytesleft,
+ char **outbuf, size_t *outbytesleft);
+static int (* __stdcall iconv_close) (iconv_t cd);
+
+static int
+load_libiconv (void)
+{
+ static int done;
+
+ if (!done)
+ {
+ void *handle;
+
+ done = 1; /* Do it right now because we might get called recursivly
+ through gettext. */
+
+ handle = dlopen ("iconv.dll", RTLD_LAZY);
+ if (handle)
+ {
+ iconv_open = dlsym (handle, "libiconv_open");
+ if (iconv_open)
+ iconv = dlsym (handle, "libiconv");
+ if (iconv)
+ iconv_close = dlsym (handle, "libiconv_close");
+ }
+ if (!handle || !iconv_close)
+ {
+ log_info (_("error loading `%s': %s\n"),
+ "iconv.dll", dlerror ());
+ log_info (_("please see http://www.gnupg.org/download/iconv.html "
+ "for more information\n"));
+ iconv_open = NULL;
+ iconv = NULL;
+ iconv_close = NULL;
+ if (handle)
+ dlclose (handle);
+ }
+ }
+ return iconv_open? 0: -1;
+}
+#endif /*HAVE_W32_SYSTEM*/
+
/* Error handler for iconv failures. This is needed to not clutter the
output with repeated diagnostics about a missing conversion. */
diff --git a/jnlib/w32-gettext.c b/jnlib/w32-gettext.c
new file mode 100644
index 000000000..eca1ee324
--- /dev/null
+++ b/jnlib/w32-gettext.c
@@ -0,0 +1,556 @@
+/* w32-gettext.c - A simplified version of gettext for use under W32.
+ * Copyright (C) 1995, 1996, 1997, 1999,
+ * 2005, 2007 Free Software Foundation, Inc.
+ *
+ * This file is part of JNLIB.
+ *
+ * JNLIB is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JNLIB is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ This is a simplified version of gettext written by Ulrich Drepper.
+ It is used for the Win32 version of GnuPG becaise all the overhead
+ of gettext is not needed and we have to do some special Win32
+ stuff. I decided that this is far easier than to tweak gettext for
+ the special cases (I tried it but it is a lot of code). wk 15.09.99
+ */
+
+#include <config.h>
+#ifdef USE_SIMPLE_GETTEXT
+#if !defined (_WIN32) && !defined (__CYGWIN32__)
+#error This module may only be build for Windows or Cygwin32
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "libjnlib-config.h"
+#include "types.h"
+#include "stringhelp.h"
+#include "utf8conv.h"
+#include "w32help.h"
+
+#include "windows.h" /* For GetModuleFileName. */
+
+/* The magic number of the GNU message catalog format. */
+#define MAGIC 0x950412de
+#define MAGIC_SWAPPED 0xde120495
+
+/* Revision number of the currently used .mo (binary) file format. */
+#define MO_REVISION_NUMBER 0
+
+
+/* Header for binary .mo file format. */
+struct mo_file_header
+{
+ /* The magic number. */
+ u32 magic;
+ /* The revision number of the file format. */
+ u32 revision;
+ /* The number of strings pairs. */
+ u32 nstrings;
+ /* Offset of table with start offsets of original strings. */
+ u32 orig_tab_offset;
+ /* Offset of table with start offsets of translation strings. */
+ u32 trans_tab_offset;
+ /* Size of hashing table. */
+ u32 hash_tab_size;
+ /* Offset of first hashing entry. */
+ u32 hash_tab_offset;
+};
+
+struct string_desc
+{
+ /* Length of addressed string. */
+ u32 length;
+ /* Offset of string in file. */
+ u32 offset;
+};
+
+
+struct overflow_space_s
+{
+ struct overflow_space_s *next;
+ u32 idx;
+ char d[1];
+};
+
+struct loaded_domain
+{
+ char *data;
+ int must_swap;
+ u32 nstrings;
+ char *mapped; /* 0 = not yet mapped, 1 = mapped,
+ 2 = mapped to
+ overflow space */
+ struct overflow_space_s *overflow_space;
+ struct string_desc *orig_tab;
+ struct string_desc *trans_tab;
+ u32 hash_size;
+ u32 *hash_tab;
+};
+
+
+static struct loaded_domain *the_domain;
+
+static __inline__ u32
+do_swap_u32( u32 i )
+{
+ return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
+}
+
+#define SWAPIT(flag, data) ((flag) ? do_swap_u32(data) : (data) )
+
+
+/* We assume to have `unsigned long int' value with at least 32 bits. */
+#define HASHWORDBITS 32
+
+/* The so called `hashpjw' function by P.J. Weinberger
+ [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
+ 1986, 1987 Bell Telephone Laboratories, Inc.] */
+
+static __inline__ ulong
+hash_string (const char *str_param)
+{
+ unsigned long int hval, g;
+ const char *str = str_param;
+
+ hval = 0;
+ while (*str != '\0')
+ {
+ hval <<= 4;
+ hval += (unsigned long int) *str++;
+ g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
+ if (g != 0)
+ {
+ hval ^= g >> (HASHWORDBITS - 8);
+ hval ^= g;
+ }
+ }
+ return hval;
+}
+
+
+static struct loaded_domain *
+load_domain (const char *filename)
+{
+ FILE *fp;
+ size_t size;
+ struct stat st;
+ struct mo_file_header *data = NULL;
+ struct loaded_domain *domain = NULL;
+ size_t to_read;
+ char *read_ptr;
+
+ fp = fopen( filename, "rb" );
+ if (!fp)
+ return NULL; /* Can't open the file. */
+ /* We need to know the size of the file. */
+ if (fstat( fileno(fp ), &st )
+ || (size = (size_t)st.st_size) != st.st_size
+ || size < sizeof (struct mo_file_header) )
+ {
+ fclose (fp);
+ return NULL;
+ }
+
+ data = jnlib_malloc (size);
+ if (!data)
+ {
+ fclose (fp);
+ return NULL; /* Out of memory. */
+ }
+
+ to_read = size;
+ read_ptr = (char *) data;
+ do
+ {
+ long int nb;
+
+ nb = fread (read_ptr, 1, to_read, fp);
+ if (nb < to_read )
+ {
+ fclose (fp);
+ jnlib_free (data);
+ return NULL; /* Read error. */
+ }
+ read_ptr += nb;
+ to_read -= nb;
+ }
+ while (to_read > 0);
+ fclose (fp);
+
+ /* Using the magic number we test whether it is really a message
+ catalog file. */
+ if (data->magic != MAGIC && data->magic != MAGIC_SWAPPED)
+ {
+ /* The magic number is wrong: not a message catalog file. */
+ jnlib_free (data);
+ return NULL;
+ }
+
+ domain = jnlib_calloc (1, sizeof *domain);
+ if (!domain)
+ {
+ jnlib_free (data);
+ return NULL;
+ }
+ domain->data = (char *) data;
+ domain->must_swap = data->magic != MAGIC;
+
+ /* Fill in the information about the available tables. */
+ switch (SWAPIT(domain->must_swap, data->revision))
+ {
+ case 0:
+ domain->nstrings = SWAPIT(domain->must_swap, data->nstrings);
+ domain->orig_tab = (struct string_desc *)
+ ((char *) data + SWAPIT(domain->must_swap, data->orig_tab_offset));
+ domain->trans_tab = (struct string_desc *)
+ ((char *) data + SWAPIT(domain->must_swap, data->trans_tab_offset));
+ domain->hash_size = SWAPIT(domain->must_swap, data->hash_tab_size);
+ domain->hash_tab = (u32 *)
+ ((char *) data + SWAPIT(domain->must_swap, data->hash_tab_offset));
+ break;
+
+ default: /* This is an invalid revision. */
+ jnlib_free( data );
+ jnlib_free( domain );
+ return NULL;
+ }
+
+ /* Allocate an array to keep track of code page mappings. */
+ domain->mapped = jnlib_calloc (1, domain->nstrings);
+ if (!domain->mapped)
+ {
+ jnlib_free (data);
+ jnlib_free (domain);
+ return NULL;
+ }
+
+ return domain;
+}
+
+
+/* Set the file used for translations. Pass a NULL to disable
+ translation. A new filename may be set at anytime. WARNING: After
+ changing the filename you should not access any data retrieved by
+ gettext().
+
+ If REGKEY is not NULL, the function tries to selected the language
+ the registry key "Lang" below that key. If in addition the
+ environment variable LANGUAGE has been set, that value will
+ override a value set by the registry key.
+ */
+int
+set_gettext_file ( const char *filename, const char *regkey )
+{
+ struct loaded_domain *domain = NULL;
+
+ if ( filename && *filename )
+ {
+ if ( filename[0] == '/'
+#ifdef HAVE_DRIVE_LETTERS
+ || ( isalpha(filename[0])
+ && filename[1] == ':'
+ && (filename[2] == '/' || filename[2] == '\\') )
+#endif
+ )
+ {
+ /* absolute path - use it as is */
+ domain = load_domain( filename );
+ }
+ else if (regkey) /* Standard. */
+ {
+ char *instdir, *langid, *fname;
+ char *p;
+ int envvar_mode = 0;
+
+ again:
+ if (!envvar_mode && (p = getenv ("LANGUAGE")) && *p)
+ {
+ envvar_mode = 1;
+ langid = jnlib_malloc (strlen (p)+1);
+ if (!langid)
+ return -1;
+ strcpy (langid, p);
+ /* We only make use of the first language given. Strip
+ the rest. */
+ p = strchr (langid, ':');
+ if (p)
+ *p = 0;
+
+ /* In the $LANGUAGE case we do not use the registered
+ installation directory but the one where the gpg
+ binary has been found. */
+ instdir = jnlib_malloc (MAX_PATH+5);
+ if ( !instdir || !GetModuleFileName (NULL, instdir, MAX_PATH) )
+ {
+ jnlib_free (langid);
+ jnlib_free (instdir);
+ return -1; /* Error getting the process' file name. */
+ }
+ p = strrchr (instdir, DIRSEP_C);
+ if (!p)
+ {
+ jnlib_free (langid);
+ jnlib_free (instdir);
+ return -1; /* Invalid file name returned. */
+ }
+ *p = 0;
+ }
+ else
+ {
+ instdir = read_w32_registry_string ("HKEY_LOCAL_MACHINE",
+ regkey,
+ "Install Directory");
+ if (!instdir)
+ return -1;
+ langid = read_w32_registry_string (NULL, /* HKCU then HKLM */
+ regkey,
+ "Lang");
+ if (!langid)
+ {
+ jnlib_free (instdir);
+ return -1;
+ }
+ }
+
+ /* Strip stuff after a dot in case the user tried to enter
+ the entire locale syntacs as usual for POSIX. */
+ p = strchr (langid, '.');
+ if (p)
+ *p = 0;
+
+ /* Build the key: "<instdir>/<domain>.nls/<langid>.mo" We
+ use a directory below the installation directory with the
+ domain included in case the software has been insalled
+ with other software altogether at the same place. */
+ fname = jnlib_malloc (strlen (instdir) + 1 + strlen (filename) + 5
+ + strlen (langid) + 3 + 1);
+ if (!fname)
+ {
+ jnlib_free (instdir);
+ jnlib_free (langid);
+ return -1;
+ }
+ strcpy (stpcpy (stpcpy (stpcpy (stpcpy ( stpcpy (fname,
+ instdir),"\\"), filename), ".nls\\"), langid), ".mo");
+ jnlib_free (instdir);
+ jnlib_free (langid);
+
+ /* Better make sure that we don't mix forward and backward
+ slashes. It seems that some Windoze versions don't
+ accept this. */
+ for (p=fname; *p; p++)
+ {
+ if (*p == '/')
+ *p = '\\';
+ }
+ domain = load_domain (fname);
+ jnlib_free(fname);
+
+ if (!domain && envvar_mode == 1)
+ {
+ /* In case it failed, we try again using the registry
+ method. */
+ envvar_mode++;
+ goto again;
+ }
+ }
+
+
+ if (!domain)
+ return -1;
+ }
+
+ if ( the_domain )
+ {
+ struct overflow_space_s *os, *os2;
+
+ jnlib_free ( the_domain->data );
+ jnlib_free ( the_domain->mapped );
+ for (os=the_domain->overflow_space; os; os = os2)
+ {
+ os2 = os->next;
+ jnlib_free (os);
+ }
+ jnlib_free ( the_domain );
+ the_domain = NULL;
+ }
+ the_domain = domain;
+ return 0;
+}
+
+
+static const char*
+get_string( struct loaded_domain *domain, u32 idx )
+{
+ struct overflow_space_s *os;
+ char *p;
+
+ p = domain->data + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset);
+ if (!domain->mapped[idx])
+ {
+ size_t plen, buflen;
+ char *buf;
+
+ domain->mapped[idx] = 1;
+
+ plen = strlen (p);
+ buf = utf8_to_native (p, plen, -1);
+ buflen = strlen (buf);
+ if (buflen <= plen)
+ strcpy (p, buf);
+ else
+ {
+ /* There is not enough space for the translation - store it
+ in the overflow_space else and mark that in the mapped
+ array. Because we expect that this won't happen too
+ often, we use a simple linked list. */
+ os = jnlib_malloc (sizeof *os + buflen);
+ if (os)
+ {
+ os->idx = idx;
+ strcpy (os->d, buf);
+ os->next = domain->overflow_space;
+ domain->overflow_space = os;
+ p = os->d;
+ }
+ else
+ p = "ERROR in GETTEXT MALLOC";
+ }
+ jnlib_free (buf);
+ }
+ else if (domain->mapped[idx] == 2)
+ { /* We need to get the string from the overflow_space. */
+ for (os=domain->overflow_space; os; os = os->next)
+ if (os->idx == idx)
+ return (const char*)os->d;
+ p = "ERROR in GETTEXT\n";
+ }
+ return (const char*)p;
+}
+
+
+
+const char *
+gettext( const char *msgid )
+{
+ struct loaded_domain *domain;
+ size_t act = 0;
+ size_t top, bottom;
+
+ if (!(domain = the_domain))
+ goto not_found;
+
+ /* Locate the MSGID and its translation. */
+ if (domain->hash_size > 2 && domain->hash_tab)
+ {
+ /* Use the hashing table. */
+ u32 len = strlen (msgid);
+ u32 hash_val = hash_string (msgid);
+ u32 idx = hash_val % domain->hash_size;
+ u32 incr = 1 + (hash_val % (domain->hash_size - 2));
+ u32 nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx]);
+
+ if ( !nstr ) /* Hash table entry is empty. */
+ goto not_found;
+
+ if (SWAPIT(domain->must_swap,
+ domain->orig_tab[nstr - 1].length) == len
+ && !strcmp (msgid,
+ domain->data + SWAPIT(domain->must_swap,
+ domain->orig_tab[nstr-1].offset)))
+ return get_string( domain, nstr - 1 );
+
+ for (;;)
+ {
+ if (idx >= domain->hash_size - incr)
+ idx -= domain->hash_size - incr;
+ else
+ idx += incr;
+
+ nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx]);
+ if (!nstr)
+ goto not_found; /* Hash table entry is empty. */
+
+ if ( SWAPIT(domain->must_swap,
+ domain->orig_tab[nstr - 1].length) == len
+ && !strcmp (msgid,
+ domain->data
+ + SWAPIT(domain->must_swap,
+ domain->orig_tab[nstr-1].offset)))
+ return get_string( domain, nstr-1 );
+ }
+ /*NOTREACHED*/
+ }
+
+ /* Now we try the default method: binary search in the sorted array
+ of messages. */
+ bottom = 0;
+ top = domain->nstrings;
+ while (bottom < top)
+ {
+ int cmp_val;
+
+ act = (bottom + top) / 2;
+ cmp_val = strcmp(msgid, domain->data
+ + SWAPIT(domain->must_swap,
+ domain->orig_tab[act].offset));
+ if (cmp_val < 0)
+ top = act;
+ else if (cmp_val > 0)
+ bottom = act + 1;
+ else
+ return get_string (domain, act);
+ }
+
+ not_found:
+ return msgid;
+}
+
+
+const char *
+ngettext (const char *msgid1, const char *msgid2, unsigned long int n)
+{
+ /* We use the simple Germanic plural rule. */
+ return gettext (n==1? msgid1 : msgid2);
+}
+
+
+
+#if 0
+ unsigned int cp1, cp2;
+
+ cp1 = GetConsoleCP();
+ cp2 = GetConsoleOutputCP();
+
+ log_info("InputCP=%u OutputCP=%u\n", cp1, cp2 );
+
+ if( !SetConsoleOutputCP( 1252 ) )
+ log_info("SetConsoleOutputCP failed: %s\n", w32_strerror (0));
+
+ cp1 = GetConsoleCP();
+ cp2 = GetConsoleOutputCP();
+ log_info("InputCP=%u OutputCP=%u after switch1\n", cp1, cp2 );
+#endif
+
+#endif /* USE_SIMPLE_GETTEXT */
diff --git a/jnlib/w32-pth.c b/jnlib/w32-pth.c
deleted file mode 100644
index 0ef4d9e4e..000000000
--- a/jnlib/w32-pth.c
+++ /dev/null
@@ -1,1500 +0,0 @@
-/* w32-pth.c - GNU Pth emulation for W32 (MS Windows).
- * Copyright (c) 1999-2003 Ralf S. Engelschall <[email protected]>
- * Copyright (C) 2004, 2006 g10 Code GmbH
- *
- * This file is part of JNLIB.
- *
- * JNLIB is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * JNLIB is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * ------------------------------------------------------------------
- * This code is based on Ralf Engelschall's GNU Pth, a non-preemptive
- * thread scheduling library which can be found at
- * http://www.gnu.org/software/pth/. MS Windows (W32) specific code
- * written by Timo Schulz, g10 Code.
- */
-
-#include <config.h>
-#ifdef HAVE_W32_SYSTEM
-#include <windows.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <io.h>
-#include <signal.h>
-
-#include "logging.h" /* For log_get_prefix () */
-
-/* We don't want to have any Windows specific code in the header, thus
- we use a macro which defaults to a compatible type in w32-pth.h. */
-#define W32_PTH_HANDLE_INTERNAL HANDLE
-#include "w32-pth.h"
-
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-#ifndef TRUE
-#define TRUE 1
-#endif
-#if FALSE != 0 || TRUE != 1
-#error TRUE or FALSE defined to wrong values
-#endif
-
-
-/* States whether this module has been initialized. */
-static int pth_initialized;
-
-/* Keeps the current debug level. Define marcos to test them. */
-static int debug_level;
-#define DBG_ERROR (debug_level >= 1)
-#define DBG_INFO (debug_level >= 2)
-#define DBG_CALLS (debug_level >= 3)
-
-/* Variables to support event handling. */
-static int pth_signo;
-static HANDLE pth_signo_ev;
-
-/* Mutex to make sure only one thread is running. */
-static CRITICAL_SECTION pth_shd;
-
-/* Events are store in a double linked event ring. */
-struct pth_event_s
-{
- struct pth_event_s * next;
- struct pth_event_s * prev;
- HANDLE hd;
- union
- {
- struct sigset_s * sig;
- int fd;
- struct timeval tv;
- pth_mutex_t * mx;
- } u;
- int * val;
- int u_type;
- int flags;
-};
-
-
-struct pth_attr_s
-{
- unsigned int flags;
- unsigned int stack_size;
- char * name;
-};
-
-
-/* Object to keep information about a thread. This may eventually be
- used to implement a scheduler queue. */
-struct thread_info_s
-{
- void *(*thread)(void *); /* The actual thread fucntion. */
- void * arg; /* The argument passed to that fucntion. */
- int joinable; /* True if this Thread is joinable. */
- HANDLE th; /* Handle of this thread. Used by non-joinable
- threads to close the handle. */
-};
-
-
-/* Convenience macro to startup the system. */
-#define implicit_init() do { if (!pth_initialized) pth_init(); } while (0)
-
-/* Prototypes. */
-static pth_event_t do_pth_event (unsigned long spec, ...);
-static unsigned int do_pth_waitpid (unsigned pid, int * status, int options);
-static int do_pth_wait (pth_event_t ev);
-static int do_pth_event_status (pth_event_t ev);
-static void *launch_thread (void * ctx);
-
-
-
-
-int
-pth_init (void)
-{
- SECURITY_ATTRIBUTES sa;
- WSADATA wsadat;
- const char *s;
-
- if (pth_initialized)
- return TRUE;
-
- debug_level = (s=getenv ("DEBUG_PTH"))? atoi (s):0;
- if (debug_level)
- fprintf (stderr, "%s: pth_init: called.\n", log_get_prefix (NULL));
-
- if (WSAStartup (0x202, &wsadat))
- return FALSE;
- pth_signo = 0;
- InitializeCriticalSection (&pth_shd);
- if (pth_signo_ev)
- CloseHandle (pth_signo_ev);
- memset (&sa, 0, sizeof sa);
- sa.bInheritHandle = TRUE;
- sa.lpSecurityDescriptor = NULL;
- sa.nLength = sizeof sa;
- pth_signo_ev = CreateEvent (&sa, TRUE, FALSE, NULL);
- if (!pth_signo_ev)
- return FALSE;
-
- pth_initialized = 1;
- EnterCriticalSection (&pth_shd);
- return TRUE;
-}
-
-
-int
-pth_kill (void)
-{
- pth_signo = 0;
- if (pth_signo_ev)
- {
- CloseHandle (pth_signo_ev);
- pth_signo_ev = NULL;
- }
- if (pth_initialized)
- DeleteCriticalSection (&pth_shd);
- WSACleanup ();
- pth_initialized = 0;
- return TRUE;
-}
-
-
-static char *
-w32_strerror (char *strerr, size_t strerrsize)
-{
- if (strerrsize > 1)
- FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, (int)GetLastError (),
- MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
- strerr, strerrsize, NULL);
- return strerr;
-}
-
-
-static void
-enter_pth (const char *function)
-{
- /* Fixme: I am not sure whether the same thread my enter a critical
- section twice. */
- if (DBG_CALLS)
- fprintf (stderr, "%s: enter_pth (%s)\n",
- log_get_prefix (NULL), function? function:"");
- LeaveCriticalSection (&pth_shd);
-}
-
-
-static void
-leave_pth (const char *function)
-{
- EnterCriticalSection (&pth_shd);
- if (DBG_CALLS)
- fprintf (stderr, "%s: leave_pth (%s)\n",
- log_get_prefix (NULL), function? function:"");
-}
-
-
-long
-pth_ctrl (unsigned long query, ...)
-{
- implicit_init ();
-
- switch (query)
- {
- case PTH_CTRL_GETAVLOAD:
- case PTH_CTRL_GETPRIO:
- case PTH_CTRL_GETNAME:
- case PTH_CTRL_GETTHREADS_NEW:
- case PTH_CTRL_GETTHREADS_READY:
- case PTH_CTRL_GETTHREADS_RUNNING:
- case PTH_CTRL_GETTHREADS_WAITING:
- case PTH_CTRL_GETTHREADS_SUSPENDED:
- case PTH_CTRL_GETTHREADS_DEAD:
- case PTH_CTRL_GETTHREADS:
- default:
- return -1;
- }
- return 0;
-}
-
-
-
-pth_time_t
-pth_timeout (long sec, long usec)
-{
- pth_time_t tvd;
-
- tvd.tv_sec = sec;
- tvd.tv_usec = usec;
- return tvd;
-}
-
-
-int
-pth_read_ev (int fd, void *buffer, size_t size, pth_event_t ev)
-{
- implicit_init ();
- return 0;
-}
-
-
-int
-pth_read (int fd, void * buffer, size_t size)
-{
- int n;
-
- implicit_init ();
- enter_pth (__FUNCTION__);
-
- n = recv (fd, buffer, size, 0);
- if (n == -1 && WSAGetLastError () == WSAENOTSOCK)
- {
- DWORD nread = 0;
- n = ReadFile ((HANDLE)fd, buffer, size, &nread, NULL);
- if (!n)
- {
- char strerr[256];
-
- if (DBG_ERROR)
- fprintf (stderr, "%s: pth_read(%d) failed read from file: %s\n",
- log_get_prefix (NULL), fd,
- w32_strerror (strerr, sizeof strerr));
- n = -1;
- }
- else
- n = (int)nread;
- }
- leave_pth (__FUNCTION__);
- return n;
-}
-
-
-int
-pth_write_ev (int fd, const void *buffer, size_t size, pth_event_t ev)
-{
- implicit_init ();
- return 0;
-}
-
-
-int
-pth_write (int fd, const void * buffer, size_t size)
-{
- int n;
-
- implicit_init ();
- enter_pth (__FUNCTION__);
- n = send (fd, buffer, size, 0);
- if (n == -1 && WSAGetLastError () == WSAENOTSOCK)
- {
- DWORD nwrite;
- char strerr[256];
-
- /* This is no real error because we first need to figure out if
- we have a handle or a socket. */
-
- n = WriteFile ((HANDLE)fd, buffer, size, &nwrite, NULL);
- if (!n)
- {
- if (DBG_ERROR)
- fprintf (stderr, "%s: pth_write(%d) failed in write: %s\n",
- log_get_prefix (NULL), fd,
- w32_strerror (strerr, sizeof strerr));
- n = -1;
- }
- else
- n = (int)nwrite;
- }
- leave_pth (__FUNCTION__);
- return n;
-}
-
-
-int
-pth_select (int nfds, fd_set * rfds, fd_set * wfds, fd_set * efds,
- const struct timeval * timeout)
-{
- int n;
-
- implicit_init ();
- enter_pth (__FUNCTION__);
- n = select (nfds, rfds, wfds, efds, timeout);
- leave_pth (__FUNCTION__);
- return n;
-}
-
-
-int
-pth_fdmode (int fd, int mode)
-{
- unsigned long val;
- int ret = PTH_FDMODE_BLOCK;
-
- implicit_init ();
- /* Note: we don't do the eter/leave pth here because this is for one
- a fast fucntion and secondly already called from inside such a
- block. */
- /* XXX: figure out original fd mode */
- switch (mode)
- {
- case PTH_FDMODE_NONBLOCK:
- val = 1;
- if (ioctlsocket (fd, FIONBIO, &val) == SOCKET_ERROR)
- ret = PTH_FDMODE_ERROR;
- break;
-
- case PTH_FDMODE_BLOCK:
- val = 0;
- if (ioctlsocket (fd, FIONBIO, &val) == SOCKET_ERROR)
- ret = PTH_FDMODE_ERROR;
- break;
- }
- return ret;
-}
-
-
-int
-pth_accept (int fd, struct sockaddr *addr, int *addrlen)
-{
- int rc;
-
- implicit_init ();
- enter_pth (__FUNCTION__);
- rc = accept (fd, addr, addrlen);
- leave_pth (__FUNCTION__);
- return rc;
-}
-
-
-int
-pth_accept_ev (int fd, struct sockaddr *addr, int *addrlen,
- pth_event_t ev_extra)
-{
- pth_key_t ev_key;
- pth_event_t ev;
- int rv;
- int fdmode;
-
- implicit_init ();
- enter_pth (__FUNCTION__);
-
- fdmode = pth_fdmode (fd, PTH_FDMODE_NONBLOCK);
- if (fdmode == PTH_FDMODE_ERROR)
- {
- leave_pth (__FUNCTION__);
- return -1;
- }
-
- ev = NULL;
- while ((rv = accept (fd, addr, addrlen)) == -1 &&
- (WSAGetLastError () == WSAEINPROGRESS ||
- WSAGetLastError () == WSAEWOULDBLOCK))
- {
- if (!ev)
- {
- ev = do_pth_event (PTH_EVENT_FD|PTH_UNTIL_FD_READABLE|
- PTH_MODE_STATIC, &ev_key, fd);
- if (!ev)
- {
- leave_pth (__FUNCTION__);
- return -1;
- }
- if (ev_extra)
- pth_event_concat (ev, ev_extra, NULL);
- }
- /* Wait until accept has a chance. */
- do_pth_wait (ev);
- if (ev_extra)
- {
- pth_event_isolate (ev);
- if (do_pth_event_status (ev) != PTH_STATUS_OCCURRED)
- {
- pth_fdmode (fd, fdmode);
- leave_pth (__FUNCTION__);
- return -1;
- }
- }
- }
-
- pth_fdmode (fd, fdmode);
- leave_pth (__FUNCTION__);
- return rv;
-}
-
-
-int
-pth_connect (int fd, struct sockaddr *name, int namelen)
-{
- int rc;
-
- implicit_init ();
- enter_pth (__FUNCTION__);
- rc = connect (fd, name, namelen);
- leave_pth (__FUNCTION__);
- return rc;
-}
-
-
-int
-pth_mutex_release (pth_mutex_t *mutex)
-{
- int rc;
-
- implicit_init ();
- enter_pth (__FUNCTION__);
-
- if (!ReleaseMutex (*mutex))
- {
- char strerr[256];
-
- if (DBG_ERROR)
- fprintf (stderr, "%s: pth_release_mutex %p failed: %s\n",
- log_get_prefix (NULL), *mutex,
- w32_strerror (strerr, sizeof strerr));
- rc = FALSE;
- }
- else
- rc = TRUE;
-
- leave_pth (__FUNCTION__);
- return rc;
-}
-
-
-int
-pth_mutex_acquire (pth_mutex_t *mutex, int tryonly, pth_event_t ev_extra)
-{
- int code;
- int rc;
-
- implicit_init ();
- enter_pth (__FUNCTION__);
-
- /* FIXME: ev_extra is not yet supported. */
-
- code = WaitForSingleObject (*mutex, INFINITE);
- switch (code)
- {
- case WAIT_FAILED:
- {
- char strerr[256];
-
- if (DBG_ERROR)
- fprintf (stderr, "%s: pth_mutex_acquire for %p failed: %s\n",
- log_get_prefix (NULL), *mutex,
- w32_strerror (strerr, sizeof strerr));
- }
- rc = FALSE;
- break;
-
- case WAIT_OBJECT_0:
- rc = TRUE;
- break;
-
- default:
- if (DBG_ERROR)
- fprintf (stderr, "%s: WaitForSingleObject returned unexpected "
- "code %d for mutex %p\n",
- log_get_prefix (NULL), code, *mutex);
- rc = FALSE;
- break;
- }
-
- leave_pth (__FUNCTION__);
- return rc;
-}
-
-
-
-int
-pth_mutex_init (pth_mutex_t *mutex)
-{
- SECURITY_ATTRIBUTES sa;
-
- implicit_init ();
- enter_pth (__FUNCTION__);
-
- memset (&sa, 0, sizeof sa);
- sa.bInheritHandle = TRUE;
- sa.lpSecurityDescriptor = NULL;
- sa.nLength = sizeof sa;
- *mutex = CreateMutex (&sa, FALSE, NULL);
- if (!*mutex)
- {
- free (*mutex);
- *mutex = NULL;
- leave_pth (__FUNCTION__);
- return FALSE;
- }
-
- leave_pth (__FUNCTION__);
- return TRUE;
-}
-
-
-pth_attr_t
-pth_attr_new (void)
-{
- pth_attr_t hd;
-
- implicit_init ();
- hd = calloc (1, sizeof *hd);
- return hd;
-}
-
-
-int
-pth_attr_destroy (pth_attr_t hd)
-{
- if (!hd)
- return -1;
- implicit_init ();
- if (hd->name)
- free (hd->name);
- free (hd);
- return TRUE;
-}
-
-
-int
-pth_attr_set (pth_attr_t hd, int field, ...)
-{
- va_list args;
- char * str;
- int val;
- int rc = TRUE;
-
- implicit_init ();
-
- va_start (args, field);
- switch (field)
- {
- case PTH_ATTR_JOINABLE:
- val = va_arg (args, int);
- if (val)
- {
- hd->flags |= PTH_ATTR_JOINABLE;
- if (DBG_INFO)
- fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_JOINABLE\n",
- log_get_prefix (NULL));
- }
- break;
-
- case PTH_ATTR_STACK_SIZE:
- val = va_arg (args, int);
- if (val)
- {
- hd->flags |= PTH_ATTR_STACK_SIZE;
- hd->stack_size = val;
- if (DBG_INFO)
- fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_STACK_SIZE %d\n",
- log_get_prefix (NULL), val);
- }
- break;
-
- case PTH_ATTR_NAME:
- str = va_arg (args, char*);
- if (hd->name)
- free (hd->name);
- if (str)
- {
- hd->name = strdup (str);
- if (!hd->name)
- return FALSE;
- hd->flags |= PTH_ATTR_NAME;
- if (DBG_INFO)
- fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_NAME %s\n",
- log_get_prefix (NULL), hd->name);
- }
- break;
-
- default:
- rc = FALSE;
- break;
- }
- va_end (args);
- return rc;
-}
-
-
-static pth_t
-do_pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg)
-{
- SECURITY_ATTRIBUTES sa;
- DWORD tid;
- HANDLE th;
- struct thread_info_s *ctx;
-
- if (!hd)
- return NULL;
-
- memset (&sa, 0, sizeof sa);
- sa.bInheritHandle = TRUE;
- sa.lpSecurityDescriptor = NULL;
- sa.nLength = sizeof sa;
-
- ctx = calloc (1, sizeof *ctx);
- if (!ctx)
- return NULL;
- ctx->thread = func;
- ctx->arg = arg;
- ctx->joinable = (hd->flags & PTH_ATTR_JOINABLE);
-
- /* XXX: we don't use all thread attributes. */
-
- /* Note that we create the thread suspended so that we are able to
- store the thread's handle in the context structure. We need to
- do this to be able to close the handle from the launch helper.
-
- FIXME: We should no use th W32's Thread handle directly but keep
- our own thread control structure. CTX may be used for that. */
- if (DBG_INFO)
- fprintf (stderr, "%s: do_pth_spawn creating thread ...\n",
- log_get_prefix (NULL));
- th = CreateThread (&sa, hd->stack_size,
- (LPTHREAD_START_ROUTINE)launch_thread,
- ctx, CREATE_SUSPENDED, &tid);
- ctx->th = th;
- if (DBG_INFO)
- fprintf (stderr, "%s: do_pth_spawn created thread %p\n",
- log_get_prefix (NULL),th);
- if (!th)
- free (ctx);
- else
- ResumeThread (th);
-
- return th;
-}
-
-pth_t
-pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg)
-{
- HANDLE th;
-
- if (!hd)
- return NULL;
-
- implicit_init ();
- enter_pth (__FUNCTION__);
- th = do_pth_spawn (hd, func, arg);
- leave_pth (__FUNCTION__);
- return th;
-}
-
-
-pth_t
-pth_self (void)
-{
- return GetCurrentThread ();
-}
-
-int
-pth_join (pth_t hd, void **value)
-{
- return TRUE;
-}
-
-
-/* friendly */
-int
-pth_cancel (pth_t hd)
-{
- if (!hd)
- return -1;
- implicit_init ();
- enter_pth (__FUNCTION__);
- WaitForSingleObject (hd, 1000);
- TerminateThread (hd, 0);
- leave_pth (__FUNCTION__);
- return TRUE;
-}
-
-
-/* cruel */
-int
-pth_abort (pth_t hd)
-{
- if (!hd)
- return -1;
- implicit_init ();
- enter_pth (__FUNCTION__);
- TerminateThread (hd, 0);
- leave_pth (__FUNCTION__);
- return TRUE;
-}
-
-
-void
-pth_exit (void *value)
-{
- implicit_init ();
- enter_pth (__FUNCTION__);
- pth_kill ();
- leave_pth (__FUNCTION__);
- exit ((int)(long)value);
-}
-
-
-static unsigned int
-do_pth_waitpid (unsigned pid, int * status, int options)
-{
-#if 0
- pth_event_t ev;
- static pth_key_t ev_key = PTH_KEY_INIT;
- pid_t pid;
-
- pth_debug2("pth_waitpid: called from thread \"%s\"", pth_current->name);
-
- for (;;)
- {
- /* do a non-blocking poll for the pid */
- while ( (pid = pth_sc(waitpid)(wpid, status, options|WNOHANG)) < 0
- && errno == EINTR)
- ;
-
- /* if pid was found or caller requested a polling return immediately */
- if (pid == -1 || pid > 0 || (pid == 0 && (options & WNOHANG)))
- break;
-
- /* else wait a little bit */
- ev = pth_event(PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key,
- pth_timeout (0,250000));
- pth_wait(ev);
- }
-
- pth_debug2("pth_waitpid: leave to thread \"%s\"", pth_current->name);
-#endif
- return 0;
-}
-
-
-unsigned int
-pth_waitpid (unsigned pid, int * status, int options)
-{
- unsigned int n;
-
- implicit_init ();
- enter_pth (__FUNCTION__);
- n = do_pth_waitpid (pid, status, options);
- leave_pth (__FUNCTION__);
- return n;
-}
-
-
-static BOOL WINAPI
-sig_handler (DWORD signo)
-{
- switch (signo)
- {
- case CTRL_C_EVENT: pth_signo = SIGINT; break;
- case CTRL_BREAK_EVENT: pth_signo = SIGTERM; break;
- }
- SetEvent (pth_signo_ev);
- if (DBG_INFO)
- fprintf (stderr, "%s: sig_handler=%d\n", log_get_prefix (NULL), pth_signo);
- return TRUE;
-}
-
-
-static pth_event_t
-do_pth_event_body (unsigned long spec, va_list arg)
-{
- SECURITY_ATTRIBUTES sa;
- pth_event_t ev;
- int rc;
-
- if (DBG_INFO)
- fprintf (stderr, "%s: pth_event spec=%lu\n", log_get_prefix (NULL), spec);
- ev = calloc (1, sizeof *ev);
- if (!ev)
- return NULL;
- if (spec == 0)
- ;
- else if (spec & PTH_EVENT_SIGS)
- {
- ev->u.sig = va_arg (arg, struct sigset_s *);
- ev->u_type = PTH_EVENT_SIGS;
- ev->val = va_arg (arg, int *);
- rc = SetConsoleCtrlHandler (sig_handler, TRUE);
- if (DBG_INFO)
- fprintf (stderr, "%s: pth_event: sigs rc=%d\n",
- log_get_prefix (NULL), rc);
- }
- else if (spec & PTH_EVENT_FD)
- {
- if (spec & PTH_UNTIL_FD_READABLE)
- ev->flags |= PTH_UNTIL_FD_READABLE;
- if (spec & PTH_MODE_STATIC)
- ev->flags |= PTH_MODE_STATIC;
- ev->u_type = PTH_EVENT_FD;
- va_arg (arg, pth_key_t);
- ev->u.fd = va_arg (arg, int);
- if (DBG_INFO)
- fprintf (stderr, "%s: pth_event: fd=%d\n",
- log_get_prefix (NULL), ev->u.fd);
- }
- else if (spec & PTH_EVENT_TIME)
- {
- pth_time_t t;
- if (spec & PTH_MODE_STATIC)
- ev->flags |= PTH_MODE_STATIC;
- va_arg (arg, pth_key_t);
- t = va_arg (arg, pth_time_t);
- ev->u_type = PTH_EVENT_TIME;
- ev->u.tv.tv_sec = t.tv_sec;
- ev->u.tv.tv_usec = t.tv_usec;
- }
- else if (spec & PTH_EVENT_MUTEX)
- {
- va_arg (arg, pth_key_t);
- ev->u_type = PTH_EVENT_MUTEX;
- ev->u.mx = va_arg (arg, pth_mutex_t*);
- }
-
- memset (&sa, 0, sizeof sa);
- sa.bInheritHandle = TRUE;
- sa.lpSecurityDescriptor = NULL;
- sa.nLength = sizeof sa;
- ev->hd = CreateEvent (&sa, FALSE, FALSE, NULL);
- if (!ev->hd)
- {
- free (ev);
- return NULL;
- }
- ev->next = ev;
- ev->prev = ev;
-
- return ev;
-}
-
-static pth_event_t
-do_pth_event (unsigned long spec, ...)
-{
- va_list arg;
- pth_event_t ev;
-
- va_start (arg, spec);
- ev = do_pth_event_body (spec, arg);
- va_end (arg);
-
- return ev;
-}
-
-pth_event_t
-pth_event (unsigned long spec, ...)
-{
- va_list arg;
- pth_event_t ev;
-
- implicit_init ();
- enter_pth (__FUNCTION__);
-
- va_start (arg, spec);
- ev = do_pth_event_body (spec, arg);
- va_end (arg);
-
- leave_pth (__FUNCTION__);
- return ev;
-}
-
-
-static void
-pth_event_add (pth_event_t root, pth_event_t node)
-{
- pth_event_t n;
-
- for (n=root; n->next; n = n->next)
- ;
- n->next = node;
-}
-
-
-pth_event_t
-pth_event_concat (pth_event_t evf, ...)
-{
- pth_event_t evn;
- va_list ap;
-
- if (!evf)
- return NULL;
-
- implicit_init ();
-
- va_start (ap, evf);
- while ((evn = va_arg(ap, pth_event_t)) != NULL)
- pth_event_add (evf, evn);
- va_end (ap);
-
- return evf;
-}
-
-
-static int
-wait_for_fd (int fd, int is_read, int nwait)
-{
- struct timeval tv;
- fd_set r;
- fd_set w;
- int n;
-
- FD_ZERO (&r);
- FD_ZERO (&w);
- FD_SET (fd, is_read ? &r : &w);
-
- tv.tv_sec = nwait;
- tv.tv_usec = 0;
-
- while (1)
- {
- n = select (fd+1, &r, &w, NULL, &tv);
- if (DBG_INFO)
- fprintf (stderr, "%s: wait_for_fd=%d fd %d (ec=%d)\n",
- log_get_prefix (NULL), n, fd,(int)WSAGetLastError ());
- if (n == -1)
- break;
- if (!n)
- continue;
- if (n == 1)
- {
- if (is_read && FD_ISSET (fd, &r))
- break;
- else if (FD_ISSET (fd, &w))
- break;
- }
- }
- return 0;
-}
-
-
-static void *
-launch_thread (void *arg)
-{
- struct thread_info_s *c = arg;
-
- if (c)
- {
- leave_pth (__FUNCTION__);
- c->thread (c->arg);
- if (!c->joinable && c->th)
- {
- CloseHandle (c->th);
- c->th = NULL;
- }
- /* FIXME: We would badly fail if someone accesses the now
- deallocated handle. Don't use it directly but setup proper
- scheduling queues. */
- enter_pth (__FUNCTION__);
- free (c);
- }
- ExitThread (0);
- return NULL;
-}
-
-/* void */
-/* sigemptyset (struct sigset_s * ss) */
-/* { */
-/* if (ss) { */
-/* memset (ss->sigs, 0, sizeof ss->sigs); */
-/* ss->idx = 0; */
-/* } */
-/* } */
-
-
-/* int */
-/* sigaddset (struct sigset_s * ss, int signo) */
-/* { */
-/* if (!ss) */
-/* return -1; */
-/* if (ss->idx + 1 > 64) */
-/* return -1; */
-/* ss->sigs[ss->idx] = signo; */
-/* ss->idx++; */
-/* return 0; */
-/* } */
-
-
-static int
-sigpresent (struct sigset_s * ss, int signo)
-{
-/* int i; */
-/* for (i=0; i < ss->idx; i++) { */
-/* if (ss->sigs[i] == signo) */
-/* return 1; */
-/* } */
-/* FIXME: See how to implement it. */
- return 0;
-}
-
-
-static int
-do_pth_event_occurred (pth_event_t ev)
-{
- int ret;
-
- if (!ev)
- return 0;
-
- ret = 0;
- switch (ev->u_type)
- {
- case 0:
- if (WaitForSingleObject (ev->hd, 0) == WAIT_OBJECT_0)
- ret = 1;
- break;
-
- case PTH_EVENT_SIGS:
- if (sigpresent (ev->u.sig, pth_signo) &&
- WaitForSingleObject (pth_signo_ev, 0) == WAIT_OBJECT_0)
- {
- if (DBG_INFO)
- fprintf (stderr, "%s: pth_event_occurred: sig signaled.\n",
- log_get_prefix (NULL));
- (*ev->val) = pth_signo;
- ret = 1;
- }
- break;
-
- case PTH_EVENT_FD:
- if (WaitForSingleObject (ev->hd, 0) == WAIT_OBJECT_0)
- ret = 1;
- break;
- }
-
- return ret;
-}
-
-
-int
-pth_event_occurred (pth_event_t ev)
-{
- int ret;
-
- implicit_init ();
- enter_pth (__FUNCTION__);
- ret = do_pth_event_occurred (ev);
- leave_pth (__FUNCTION__);
- return ret;
-}
-
-
-static int
-do_pth_event_status (pth_event_t ev)
-{
- if (!ev)
- return 0;
- if (do_pth_event_occurred (ev))
- return PTH_STATUS_OCCURRED;
- return 0;
-}
-
-int
-pth_event_status (pth_event_t ev)
-{
- if (!ev)
- return 0;
- if (pth_event_occurred (ev))
- return PTH_STATUS_OCCURRED;
- return 0;
-}
-
-
-static int
-do_pth_event_free (pth_event_t ev, int mode)
-{
- if (!ev)
- return FALSE;
-
- if (mode == PTH_FREE_ALL)
- {
- pth_event_t cur = ev;
- do
- {
- pth_event_t next = cur->next;
- CloseHandle (cur->hd);
- cur->hd = NULL;
- free (cur);
- cur = next;
- }
- while (cur != ev);
- }
- else if (mode == PTH_FREE_THIS)
- {
- ev->prev->next = ev->next;
- ev->next->prev = ev->prev;
- CloseHandle (ev->hd);
- ev->hd = NULL;
- free (ev);
- }
- else
- return FALSE;
-
- return TRUE;
-}
-
-int
-pth_event_free (pth_event_t ev, int mode)
-{
- int rc;
-
- implicit_init ();
- enter_pth (__FUNCTION__);
- rc = do_pth_event_free (ev, mode);
- leave_pth (__FUNCTION__);
- return rc;
-}
-
-
-pth_event_t
-pth_event_isolate (pth_event_t ev)
-{
- pth_event_t ring;
-
- if (!ev)
- return NULL;
- if (ev->next == ev && ev->prev == ev)
- return NULL; /* Only one event. */
-
- ring = ev->next;
- ev->prev->next = ev->next;
- ev->next->prev = ev->prev;
- ev->prev = ev;
- ev->next = ev;
- return ring;
-}
-
-
-static int
-event_count (pth_event_t ev)
-{
- pth_event_t r;
- int cnt = 0;
-
- if (ev)
- {
- r = ev;
- do
- {
- cnt++;
- r = r->next;
- }
- while (r != ev);
- }
-
- return cnt;
-}
-
-
-
-static pth_t
-spawn_helper_thread (void *(*func)(void *), void *arg)
-{
- SECURITY_ATTRIBUTES sa;
- DWORD tid;
- HANDLE th;
-
- memset (&sa, 0, sizeof sa);
- sa.bInheritHandle = TRUE;
- sa.lpSecurityDescriptor = NULL;
- sa.nLength = sizeof sa;
-
- if (DBG_INFO)
- fprintf (stderr, "%s: spawn_helper_thread creating thread ...\n",
- log_get_prefix (NULL));
- th = CreateThread (&sa, 32*1024,
- (LPTHREAD_START_ROUTINE)func,
- arg, 0, &tid);
- if (DBG_INFO)
- fprintf (stderr, "%s: spawn_helper_thread created thread %p\n",
- log_get_prefix (NULL), th);
-
- return th;
-}
-
-
-static void
-free_helper_threads (HANDLE *waitbuf, int *hdidx, int n)
-{
- int i;
-
- for (i=0; i < n; i++)
- {
- CloseHandle (waitbuf[hdidx[i]]);
- waitbuf[hdidx[i]] = NULL;
- }
-}
-
-
-static void *
-wait_fd_thread (void * ctx)
-{
- pth_event_t ev = ctx;
-
- wait_for_fd (ev->u.fd, ev->flags & PTH_UNTIL_FD_READABLE, 3600);
- if (DBG_INFO)
- fprintf (stderr, "%s: wait_fd_thread: exit.\n", log_get_prefix (NULL));
- SetEvent (ev->hd);
- ExitThread (0);
- return NULL;
-}
-
-
-static void *
-wait_timer_thread (void * ctx)
-{
- pth_event_t ev = ctx;
- int n = ev->u.tv.tv_sec*1000;
- Sleep (n);
- SetEvent (ev->hd);
- if (DBG_INFO)
- fprintf (stderr, "%s: wait_timer_thread: exit.\n", log_get_prefix (NULL));
- ExitThread (0);
- return NULL;
-}
-
-
-static int
-do_pth_wait (pth_event_t ev)
-{
- HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS/2];
- int hdidx[MAXIMUM_WAIT_OBJECTS/2];
- DWORD n = 0;
- int pos=0, i=0;
-
- if (!ev)
- return 0;
-
- n = event_count (ev);
- if (n > MAXIMUM_WAIT_OBJECTS/2)
- return -1;
-
- if (DBG_INFO)
- fprintf (stderr, "%s: pth_wait: cnt %lu\n", log_get_prefix (NULL), n);
- if (ev)
- {
- pth_event_t r = ev;
- do
- {
- switch (r->u_type)
- {
- case 0:
- waitbuf[pos++] = r->hd;
- break;
-
- case PTH_EVENT_SIGS:
- waitbuf[pos++] = pth_signo_ev;
- if (DBG_INFO)
- fprintf (stderr, "pth_wait: add signal event.\n");
- break;
-
- case PTH_EVENT_FD:
- if (DBG_INFO)
- fprintf (stderr, "pth_wait: spawn event wait thread.\n");
- hdidx[i++] = pos;
- waitbuf[pos++] = spawn_helper_thread (wait_fd_thread, r);
- break;
-
- case PTH_EVENT_TIME:
- if (DBG_INFO)
- fprintf (stderr, "pth_wait: spawn event timer thread.\n");
- hdidx[i++] = pos;
- waitbuf[pos++] = spawn_helper_thread (wait_timer_thread, r);
- break;
-
- case PTH_EVENT_MUTEX:
- if (DBG_INFO)
- fprintf (stderr, "pth_wait: ignoring mutex event.\n");
- break;
- }
- }
- while ( r != ev );
- }
- if (DBG_INFO)
- fprintf (stderr, "%s: pth_wait: set %d\n", log_get_prefix (NULL), pos);
- n = WaitForMultipleObjects (pos, waitbuf, FALSE, INFINITE);
- free_helper_threads (waitbuf, hdidx, i);
- if (DBG_INFO)
- fprintf (stderr, "%s: pth_wait: n %ld\n", log_get_prefix (NULL), n);
-
- if (n != WAIT_TIMEOUT)
- return 1;
-
- return 0;
-}
-
-int
-pth_wait (pth_event_t ev)
-{
- int rc;
-
- implicit_init ();
- enter_pth (__FUNCTION__);
- rc = do_pth_wait (ev);
- leave_pth (__FUNCTION__);
- return rc;
-}
-
-
-int
-pth_sleep (int sec)
-{
- static pth_key_t ev_key = PTH_KEY_INIT;
- pth_event_t ev;
-
- implicit_init ();
- enter_pth (__FUNCTION__);
-
- if (sec == 0)
- {
- leave_pth (__FUNCTION__);
- return 0;
- }
-
- ev = do_pth_event (PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key,
- pth_timeout (sec, 0));
- if (ev == NULL)
- {
- leave_pth (__FUNCTION__);
- return -1;
- }
- do_pth_wait (ev);
- do_pth_event_free (ev, PTH_FREE_ALL);
-
- leave_pth (__FUNCTION__);
- return 0;
-}
-
-
-
-
-
-/*
- Some simple tests.
- */
-#ifdef TEST
-#include <stdio.h>
-
-void * thread (void * c)
-{
-
- Sleep (2000);
- SetEvent (((pth_event_t)c)->hd);
- fprintf (stderr, "\n\nhallo!.\n");
- pth_exit (NULL);
- return NULL;
-}
-
-
-int main_1 (int argc, char ** argv)
-{
- pth_attr_t t;
- pth_t hd;
- pth_event_t ev;
-
- pth_init ();
- ev = pth_event (0, NULL);
- t = pth_attr_new ();
- pth_attr_set (t, PTH_ATTR_JOINABLE, 1);
- pth_attr_set (t, PTH_ATTR_STACK_SIZE, 4096);
- pth_attr_set (t, PTH_ATTR_NAME, "hello");
- hd = pth_spawn (t, thread, ev);
-
- pth_wait (ev);
- pth_attr_destroy (t);
- pth_event_free (ev, 0);
- pth_kill ();
-
- return 0;
-}
-
-
-static pth_event_t
-setup_signals (struct sigset_s *sigs, int *signo)
-{
- pth_event_t ev;
-
- sigemptyset (sigs);
- sigaddset (sigs, SIGINT);
- sigaddset (sigs, SIGTERM);
-
- ev = pth_event (PTH_EVENT_SIGS, sigs, signo);
- return ev;
-}
-
-int
-main_2 (int argc, char ** argv)
-{
- pth_event_t ev;
- struct sigset_s sigs;
- int signo = 0;
-
- pth_init ();
- ev = setup_signals (&sigs, &signo);
- pth_wait (ev);
- if (pth_event_occured (ev) && signo)
- fprintf (stderr, "signal caught! signo %d\n", signo);
-
- pth_event_free (ev, PTH_FREE_ALL);
- pth_kill ();
- return 0;
-}
-
-int
-main_3 (int argc, char ** argv)
-{
- struct sockaddr_in addr, rem;
- int fd, n = 0, infd;
- int signo = 0;
- struct sigset_s sigs;
- pth_event_t ev;
-
- pth_init ();
- fd = socket (AF_INET, SOCK_STREAM, 0);
-
- memset (&addr, 0, sizeof addr);
- addr.sin_addr.s_addr = INADDR_ANY;
- addr.sin_port = htons (5050);
- addr.sin_family = AF_INET;
- bind (fd, (struct sockaddr*)&addr, sizeof addr);
- listen (fd, 5);
-
- ev = setup_signals (&sigs, &signo);
- n = sizeof addr;
- infd = pth_accept_ev (fd, (struct sockaddr *)&rem, &n, ev);
- fprintf (stderr, "infd %d: %s:%d\n", infd, inet_ntoa (rem.sin_addr),
- htons (rem.sin_port));
-
- closesocket (infd);
- pth_event_free (ev, PTH_FREE_ALL);
- pth_kill ();
- return 0;
-}
-
-int
-main (int argc, char ** argv)
-{
- pth_event_t ev;
- pth_key_t ev_key;
-
- pth_init ();
- /*ev = pth_event (PTH_EVENT_TIME, &ev_key, pth_timeout (5, 0));
- pth_wait (ev);
- pth_event_free (ev, PTH_FREE_ALL);*/
- pth_sleep (5);
- pth_kill ();
- return 0;
-}
-#endif
-
-#endif /*HAVE_W32_SYSTEM*/
-
diff --git a/jnlib/w32-pth.h b/jnlib/w32-pth.h
deleted file mode 100644
index e351a9f0a..000000000
--- a/jnlib/w32-pth.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/* w32-pth.h - GNU Pth emulation for W32 (MS Windows).
- * Copyright (c) 1999-2003 Ralf S. Engelschall <[email protected]>
- * Copyright (C) 2004, 2006 g10 Code GmbH
- *
- * This file is part of JNLIB.
- *
- * JNLIB is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * JNLIB is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * ------------------------------------------------------------------
- * This code is based on Ralf Engelschall's GNU Pth, a non-preemptive
- * thread scheduling library which can be found at
- * http://www.gnu.org/software/pth/.
- */
-
-/* Note that this header is usually used through a symlinked pth.h
- file. This is needed so that we don't have a pth.h file here which
- would conflict if a system really has pth available. */
-#ifndef W32_PTH_H
-#define W32_PTH_H
-
-#include <windows.h> /* We need this for sockaddr et al. FIXME: too
- heavyweight - may be we should factor such
- code out to a second header and adjust all
- user files to include it only if required. */
-
-#ifndef W32_PTH_HANDLE_INTERNAL
-#define W32_PTH_HANDLE_INTERNAL int
-#endif
-
-
-/* Filedescriptor blocking modes. */
-enum
- {
- PTH_FDMODE_ERROR = -1,
- PTH_FDMODE_POLL = 0,
- PTH_FDMODE_BLOCK,
- PTH_FDMODE_NONBLOCK
- };
-
-
-/* Mutex values. */
-#define PTH_MUTEX_INITIALIZED (1<<0)
-#define PTH_MUTEX_LOCKED (1<<1)
-
-/* Note: We can't do static initialization, thus we don't define the
- initializer PTH_MUTEX_INIT. */
-
-
-#define PTH_KEY_INIT (1<<0)
-
-
-/* Event subject classes. */
-#define PTH_EVENT_FD (1<<1)
-#define PTH_EVENT_SELECT (1<<2)
-#define PTH_EVENT_SIGS (1<<3)
-#define PTH_EVENT_TIME (1<<4)
-#define PTH_EVENT_MSG (1<<5)
-#define PTH_EVENT_MUTEX (1<<6)
-#define PTH_EVENT_COND (1<<7)
-#define PTH_EVENT_TID (1<<8)
-#define PTH_EVENT_FUNC (1<<9)
-
-
-
-/* Event occurrence restrictions. */
-#define PTH_UNTIL_OCCURRED (1<<11)
-#define PTH_UNTIL_FD_READABLE (1<<12)
-#define PTH_UNTIL_FD_WRITEABLE (1<<13)
-#define PTH_UNTIL_FD_EXCEPTION (1<<14)
-#define PTH_UNTIL_TID_NEW (1<<15)
-#define PTH_UNTIL_TID_READY (1<<16)
-#define PTH_UNTIL_TID_WAITING (1<<17)
-#define PTH_UNTIL_TID_DEAD (1<<18)
-
-
-/* Event structure handling modes. */
-#define PTH_MODE_REUSE (1<<20)
-#define PTH_MODE_CHAIN (1<<21)
-#define PTH_MODE_STATIC (1<<22)
-
-
-/* Attribute commands for pth_attr_get and pth_attr_set(). */
-enum
- {
- PTH_ATTR_PRIO, /* RW [int] Priority of thread. */
- PTH_ATTR_NAME, /* RW [char *] Name of thread. */
- PTH_ATTR_JOINABLE, /* RW [int] Thread detachment type. */
- PTH_ATTR_CANCEL_STATE, /* RW [unsigned int] Thread cancellation state.*/
- PTH_ATTR_STACK_SIZE, /* RW [unsigned int] Stack size. */
- PTH_ATTR_STACK_ADDR, /* RW [char *] Stack lower address. */
- PTH_ATTR_DISPATCHES, /* RO [int] Total number of
- thread dispatches. */
- PTH_ATTR_TIME_SPAWN, /* RO [pth_time_t] Time thread was spawned. */
- PTH_ATTR_TIME_LAST, /* RO [pth_time_t] Time thread was
- last dispatched. */
- PTH_ATTR_TIME_RAN, /* RO [pth_time_t] Time thread was running. */
- PTH_ATTR_START_FUNC, /* RO [void *(*)(void *)] Thread start function.*/
- PTH_ATTR_START_ARG, /* RO [void *] Thread start argument. */
- PTH_ATTR_STATE, /* RO [pth_state_t] Scheduling state. */
- PTH_ATTR_EVENTS, /* RO [pth_event_t] Events the thread
- is waiting for. */
- PTH_ATTR_BOUND /* RO [int] Whether object is
- bound to thread. */
- };
-
-
-
-/* Queries for pth_ctrl(). */
-#define PTH_CTRL_GETAVLOAD (1<<1)
-#define PTH_CTRL_GETPRIO (1<<2)
-#define PTH_CTRL_GETNAME (1<<3)
-#define PTH_CTRL_GETTHREADS_NEW (1<<4)
-#define PTH_CTRL_GETTHREADS_READY (1<<5)
-#define PTH_CTRL_GETTHREADS_RUNNING (1<<6)
-#define PTH_CTRL_GETTHREADS_WAITING (1<<7)
-#define PTH_CTRL_GETTHREADS_SUSPENDED (1<<8)
-#define PTH_CTRL_GETTHREADS_DEAD (1<<9)
-#define PTH_CTRL_DUMPSTATE (1<<10)
-
-#define PTH_CTRL_GETTHREADS ( PTH_CTRL_GETTHREADS_NEW \
- | PTH_CTRL_GETTHREADS_READY \
- | PTH_CTRL_GETTHREADS_RUNNING \
- | PTH_CTRL_GETTHREADS_WAITING \
- | PTH_CTRL_GETTHREADS_SUSPENDED \
- | PTH_CTRL_GETTHREADS_DEAD )
-
-
-/* Event status codes. */
-typedef enum
- {
- PTH_STATUS_PENDING,
- PTH_STATUS_OCCURRED,
- PTH_STATUS_FAILED
- }
-pth_status_t;
-
-
-/* Event deallocation types. */
-enum
- {
- PTH_FREE_THIS,
- PTH_FREE_ALL
- };
-
-
-/* The Pth thread handle object. */
-typedef void *pth_t;
-
-
-/* The Mutex object. */
-typedef W32_PTH_HANDLE_INTERNAL pth_mutex_t;
-
-
-/* The Event object. */
-struct pth_event_s;
-typedef struct pth_event_s *pth_event_t;
-
-
-/* The Attribute object. */
-struct pth_attr_s;
-typedef struct pth_attr_s *pth_attr_t;
-
-
-/* The Key object. */
-typedef int pth_key_t;
-
-
-/* The Pth time object. */
-typedef struct timeval pth_time_t;
-
-
-/* Function prototypes. */
-int pth_init (void);
-int pth_kill (void);
-long pth_ctrl (unsigned long query, ...);
-
-int pth_read_ev (int fd, void *buffer, size_t size, pth_event_t ev);
-int pth_read (int fd, void *buffer, size_t size);
-int pth_write_ev (int fd, const void *buffer, size_t size, pth_event_t ev);
-int pth_write (int fd, const void *buffer, size_t size);
-
-int pth_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds,
- const struct timeval *timeout);
-
-int pth_accept (int fd, struct sockaddr *addr, int *addrlen);
-int pth_accept_ev (int fd, struct sockaddr *addr, int *addrlen,
- pth_event_t hd);
-
-int pth_connect (int fd, struct sockaddr *name, int namelen);
-
-
-int pth_mutex_release (pth_mutex_t *hd);
-int pth_mutex_acquire(pth_mutex_t *hd, int try_only, pth_event_t ev_extra);
-int pth_mutex_init (pth_mutex_t *hd);
-
-
-pth_attr_t pth_attr_new (void);
-int pth_attr_destroy (pth_attr_t hd);
-int pth_attr_set (pth_attr_t hd, int field, ...);
-
-pth_t pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg);
-pth_t pth_self (void);
-int pth_join (pth_t hd, void **value);
-int pth_abort (pth_t hd);
-void pth_exit (void *value);
-
-unsigned int pth_waitpid (unsigned int, int *status, int options);
-int pth_wait (pth_event_t hd);
-
-int pth_sleep (int n);
-pth_time_t pth_timeout (long sec, long usec);
-
-
-
-pth_event_t pth_event_isolate (pth_event_t hd);
-int pth_event_free (pth_event_t hd, int mode);
-int pth_event_status (pth_event_t hd);
-int pth_event_occurred (pth_event_t hd);
-pth_event_t pth_event_concat (pth_event_t ev, ...);
-pth_event_t pth_event (unsigned long spec, ...);
-
-
-
-/*-- pth_util.c --*/
-
-/* void sigemptyset (struct sigset_s * ss); */
-
-/* int sigaddset (struct sigset_s * ss, int signo); */
-
-
-
-#endif /*W32_PTH_H*/
diff --git a/jnlib/w32-reg.c b/jnlib/w32-reg.c
new file mode 100644
index 000000000..b7a383e3f
--- /dev/null
+++ b/jnlib/w32-reg.c
@@ -0,0 +1,184 @@
+/* w32-reg.c - MS-Windows Registry access
+ * Copyright (C) 1999, 2002, 2007 Free Software Foundation, Inc.
+ *
+ * This file is part of JNLIB.
+ *
+ * JNLIB is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JNLIB is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <config.h>
+#ifdef HAVE_W32_SYSTEM
+ /* This module is only used in this environment */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <windows.h>
+
+#include "libjnlib-config.h"
+#include "w32help.h"
+
+static HKEY
+get_root_key(const char *root)
+{
+ HKEY root_key;
+
+ if (!root)
+ root_key = HKEY_CURRENT_USER;
+ else if (!strcmp( root, "HKEY_CLASSES_ROOT" ) )
+ root_key = HKEY_CLASSES_ROOT;
+ else if (!strcmp( root, "HKEY_CURRENT_USER" ) )
+ root_key = HKEY_CURRENT_USER;
+ else if (!strcmp( root, "HKEY_LOCAL_MACHINE" ) )
+ root_key = HKEY_LOCAL_MACHINE;
+ else if (!strcmp( root, "HKEY_USERS" ) )
+ root_key = HKEY_USERS;
+ else if (!strcmp( root, "HKEY_PERFORMANCE_DATA" ) )
+ root_key = HKEY_PERFORMANCE_DATA;
+ else if (!strcmp( root, "HKEY_CURRENT_CONFIG" ) )
+ root_key = HKEY_CURRENT_CONFIG;
+ else
+ return NULL;
+
+ return root_key;
+}
+
+
+/* Return a string from the Win32 Registry or NULL in case of error.
+ Caller must release the return value. A NULL for root is an alias
+ for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. */
+char *
+read_w32_registry_string (const char *root, const char *dir, const char *name)
+{
+ HKEY root_key, key_handle;
+ DWORD n1, nbytes, type;
+ char *result = NULL;
+
+ if ( !(root_key = get_root_key(root) ) )
+ return NULL;
+
+ if ( RegOpenKeyEx( root_key, dir, 0, KEY_READ, &key_handle ) )
+ {
+ if (root)
+ return NULL; /* No need for a RegClose, so return immediately. */
+ /* It seems to be common practise to fall back to HKLM. */
+ if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) )
+ return NULL; /* Still no need for a RegClose. */
+ }
+
+ nbytes = 1;
+ if (RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) )
+ goto leave;
+ result = jnlib_malloc ((n1=nbytes+1));
+ if (!result)
+ goto leave;
+ if (RegQueryValueEx( key_handle, name, 0, &type, result, &n1 ))
+ {
+ jnlib_free (result);
+ result = NULL;
+ goto leave;
+ }
+ result[nbytes] = 0; /* Make sure it is a string. */
+ if (type == REG_EXPAND_SZ && strchr (result, '%'))
+ {
+ char *tmp;
+
+ n1 += 1000;
+ tmp = jnlib_malloc (n1+1);
+ if (!tmp)
+ goto leave;
+ nbytes = ExpandEnvironmentStrings (result, tmp, n1);
+ if (nbytes && nbytes > n1)
+ {
+ jnlib_free (tmp);
+ n1 = nbytes;
+ tmp = jnlib_malloc (n1 + 1);
+ if (!tmp)
+ goto leave;
+ nbytes = ExpandEnvironmentStrings (result, tmp, n1);
+ if (nbytes && nbytes > n1)
+ {
+ /* Oops - truncated, better don't expand at all. */
+ jnlib_free (tmp);
+ goto leave;
+ }
+ tmp[nbytes] = 0;
+ jnlib_free (result);
+ result = tmp;
+ }
+ else if (nbytes)
+ {
+ /* Okay, reduce the length. */
+ tmp[nbytes] = 0;
+ jnlib_free (result);
+ result = jnlib_malloc (strlen (tmp)+1);
+ if (!result)
+ result = tmp;
+ else
+ {
+ strcpy (result, tmp);
+ jnlib_free (tmp);
+ }
+ }
+ else
+ {
+ /* Error - don't expand. */
+ jnlib_free (tmp);
+ }
+ }
+
+ leave:
+ RegCloseKey (key_handle);
+ return result;
+}
+
+
+int
+write_w32_registry_string (const char *root, const char *dir,
+ const char *name, const char *value)
+{
+ HKEY root_key, reg_key;
+
+ if ( !(root_key = get_root_key(root) ) )
+ return -1;
+
+ if ( RegOpenKeyEx( root_key, dir, 0, KEY_WRITE, &reg_key )
+ != ERROR_SUCCESS )
+ return -1;
+
+ if ( RegSetValueEx (reg_key, name, 0, REG_SZ, (BYTE *)value,
+ strlen( value ) ) != ERROR_SUCCESS )
+ {
+ if ( RegCreateKey( root_key, name, &reg_key ) != ERROR_SUCCESS )
+ {
+ RegCloseKey(reg_key);
+ return -1;
+ }
+ if ( RegSetValueEx (reg_key, name, 0, REG_SZ, (BYTE *)value,
+ strlen( value ) ) != ERROR_SUCCESS )
+ {
+ RegCloseKey(reg_key);
+ return -1;
+ }
+ }
+
+ RegCloseKey (reg_key);
+
+ return 0;
+}
+
+#endif /*HAVE_W32_SYSTEM*/
diff --git a/jnlib/w32help.h b/jnlib/w32help.h
new file mode 100644
index 000000000..cb1dafcf5
--- /dev/null
+++ b/jnlib/w32help.h
@@ -0,0 +1,41 @@
+/* w32help.h - W32 speicif functions
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ *
+ * This file is part of JNLIB.
+ *
+ * JNLIB is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JNLIB is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef LIBJNLIB_W32HELP_H
+#define LIBJNLIB_W32HELP_H
+#ifdef HAVE_W32_SYSTEM
+
+/*-- w32-reg.c --*/
+char *read_w32_registry_string (const char *root,
+ const char *dir, const char *name );
+int write_w32_registry_string (const char *root, const char *dir,
+ const char *name, const char *value);
+
+#ifdef USE_SIMPLE_GETTEXT
+int set_gettext_file (const char *filename, const char *regkey);
+const char *gettext (const char *msgid );
+const char *ngettext (const char *msgid1, const char *msgid2,
+ unsigned long int n);
+#endif /*USE_SIMPLE_GETTEXT*/
+
+
+#endif /*HAVE_W32_SYSTEM*/
+#endif /*LIBJNLIB_MISCHELP_H*/