aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog25
-rw-r--r--elf/dl-support.c8
-rw-r--r--iconv/gconv.c3
-rw-r--r--iconv/gconv.h1
-rw-r--r--iconv/gconv_builtin.h6
-rw-r--r--iconv/gconv_close.c3
-rw-r--r--iconv/gconv_conf.c158
-rw-r--r--iconv/gconv_db.c72
-rw-r--r--iconv/gconv_dl.c5
-rw-r--r--iconv/gconv_open.c26
-rw-r--r--iconv/gconv_simple.c4
-rw-r--r--iconv/iconv.c38
-rw-r--r--iconv/iconv_close.c7
-rw-r--r--iconv/iconv_open.c13
-rw-r--r--sysdeps/generic/enbl-secure.c5
-rw-r--r--wcsmbs/Makefile2
-rw-r--r--wcsmbs/wchar.h20
-rw-r--r--wcsmbs/wmemrtombs.c121
-rw-r--r--wcsmbs/wmemrtowcs.c134
19 files changed, 520 insertions, 131 deletions
diff --git a/ChangeLog b/ChangeLog
index d18f75f..ad17e4f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+1997-11-24 03:01 Ulrich Drepper <drepper@cygnus.com>
+
+ * elf/dl-support.c: Call __libc_init_secure to make sure
+ __libc_enable_secure is defined early.
+ * sysdeps/generic/enbl-secure.c: Change function name to
+ __libc_init_secure and make it global instead of a constructor.
+
+ * iconv/gconv.c: Fix lots of bugs.
+ * iconv/gconv.h: Likewise.
+ * iconv/gconv_builtin.h: Likewise.
+ * iconv/gconv_close.c: Likewise.
+ * iconv/gconv_conf.c: Likewise.
+ * iconv/gconv_db.c: Likewise.
+ * iconv/gconv_dl.c: Likewise.
+ * iconv/gconv_open.c: Likewise.
+ * iconv/gconv_simple.c: Likewise.
+ * iconv/iconv.c: Likewise.
+ * iconv/iconv_close.c: Likewise.
+ * iconv/iconv_open.c: Likewise.
+
+ * wcsmbs/Makefile (routines): Add wmemrtowcs and wmemrtombs.
+ * wcsmbs/wchar.h: Add prototypes for wmemrtowcs and wmemrtombs.
+ * wcsmbs/wmemrtombs.c: New file.
+ * wcsmbs/wmemrtowcs.c: New file.
+
1997-11-22 19:28 Ulrich Drepper <drepper@cygnus.com>
* iconv/gconv_simple.c: Fix lots of bugs.
diff --git a/elf/dl-support.c b/elf/dl-support.c
index 41997cc..8b69ef0 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -46,6 +46,8 @@ struct r_search_path *_dl_search_paths;
const char *_dl_profile;
struct link_map *_dl_profile_map;
+extern void __libc_init_secure (void);
+
static void non_dynamic_init (void) __attribute__ ((unused));
@@ -54,6 +56,10 @@ non_dynamic_init (void)
{
_dl_verbose = *(getenv ("LD_WARN") ?: "") == '\0' ? 0 : 1;
+ _dl_pagesize = __getpagesize ();
+
+ __libc_init_secure ();
+
/* Initialize the data structures for the search paths for shared
objects. */
_dl_init_paths ();
@@ -65,7 +71,5 @@ non_dynamic_init (void)
/* Now determine the length of the platform string. */
if (_dl_platform != NULL)
_dl_platformlen = strlen (_dl_platform);
-
- _dl_pagesize = __getpagesize ();
}
text_set_element (__libc_subinit, non_dynamic_init);
diff --git a/iconv/gconv.c b/iconv/gconv.c
index 0cbb052..5df1635 100644
--- a/iconv/gconv.c
+++ b/iconv/gconv.c
@@ -30,6 +30,9 @@ __gconv (gconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf,
size_t oldinbytes = *inbytesleft;
int result;
+ if (cd == (gconv_t) -1L)
+ return GCONV_ILLEGAL_DESCRIPTOR;
+
cd->data[last_step].outbuf = *outbuf;
cd->data[last_step].outbufavail = 0;
cd->data[last_step].outbufsize = *outbytesleft;
diff --git a/iconv/gconv.h b/iconv/gconv.h
index 2c42f99..879db49 100644
--- a/iconv/gconv.h
+++ b/iconv/gconv.h
@@ -37,6 +37,7 @@ enum
GCONV_EMPTY_INPUT,
GCONV_FULL_OUTPUT,
GCONV_ILLEGAL_INPUT,
+ GCONV_INCOMPLETE_INPUT,
GCONV_ILLEGAL_DESCRIPTOR,
GCONV_INTERNAL_ERROR
diff --git a/iconv/gconv_builtin.h b/iconv/gconv_builtin.h
index a3070a5..8dcc3aa 100644
--- a/iconv/gconv_builtin.h
+++ b/iconv/gconv_builtin.h
@@ -18,17 +18,17 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-BUILTIN_TRANSFORMATION ("\\([^/]+\\)/UCS4/\\([^/]*\\)", NULL, 0,
+BUILTIN_TRANSFORMATION ("([^/]+)/UCS4/([^/]*)", NULL, 0,
"\\1/UTF8/\\2", 1, "=ucs4->utf8",
__gconv_transform_ucs4_utf8,
__gconv_transform_init_rstate,
__gconv_transform_end_rstate)
-BUILTIN_TRANSFORMATION ("\\([^/]+\\)/UTF8/\\([^/]*\\)", NULL, 0,
+BUILTIN_TRANSFORMATION ("([^/]+)/UTF8/([^/]*)", NULL, 0,
"\\1/UCS4/\\2", 1, "=utf8->ucs4",
__gconv_transform_utf8_ucs4,
__gconv_transform_init_rstate,
__gconv_transform_end_rstate)
-BUILTIN_TRANSFORMATION ("\\(.*\\)", NULL, 0, "\\1", 1, "=dummy",
+BUILTIN_TRANSFORMATION ("(.*)", NULL, 0, "\\1", 1, "=dummy",
__gconv_transform_dummy, NULL, NULL)
diff --git a/iconv/gconv_close.c b/iconv/gconv_close.c
index d3d023f..791c025 100644
--- a/iconv/gconv_close.c
+++ b/iconv/gconv_close.c
@@ -48,9 +48,8 @@ __gconv_close (gconv_t cd)
/* Next step. */
++srunp;
- ++drunp;
}
- while (!drunp->is_last);
+ while (!(drunp++)->is_last);
/* Save the pointer, we need it below. */
srunp = cd->steps;
diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c
index d3c13d7..8a72c7a 100644
--- a/iconv/gconv_conf.c
+++ b/iconv/gconv_conf.c
@@ -19,6 +19,7 @@
Boston, MA 02111-1307, USA. */
#include <ctype.h>
+#include <errno.h>
#include <gconv.h>
#include <search.h>
#include <stdio.h>
@@ -35,6 +36,12 @@ static const char default_gconv_path[] = GCONV_PATH;
along the path. */
static const char gconv_conf_filename[] = "gconv-modules";
+/* Filename extension for the modules. */
+#ifndef MODULE_EXT
+# define MODULE_EXT ".so"
+#endif
+static const char gconv_module_ext[] = MODULE_EXT;
+
/* We have a few builtin transformations. */
static struct gconv_module builtin_modules[] =
{
@@ -111,15 +118,18 @@ add_alias (char *rp)
new_alias = (struct gconv_alias *)
malloc (sizeof (struct gconv_alias) + (wp - from));
- new_alias->fromname = memcpy ((char *) new_alias
- + sizeof (struct gconv_alias),
- from, to - from);
- new_alias->toname = memcpy ((char *) new_alias + sizeof (struct gconv_alias)
- + (to - from), to, wp - to);
-
- if (__tsearch (new_alias, &__gconv_alias_db, __gconv_alias_compare) == NULL)
- /* Something went wrong, free this entry. */
- free (new_alias);
+ if (new_alias != NULL)
+ {
+ new_alias->fromname = memcpy ((char *) new_alias
+ + sizeof (struct gconv_alias),
+ from, wp - from);
+ new_alias->toname = new_alias->fromname + (to - from);
+
+ if (__tsearch (new_alias, &__gconv_alias_db, __gconv_alias_compare)
+ == NULL)
+ /* Something went wrong, free this entry. */
+ free (new_alias);
+ }
}
@@ -138,6 +148,7 @@ add_module (char *rp, const char *directory, size_t dir_len, void **modules,
char *from, *to, *module, *wp;
size_t const_len;
int from_is_regex;
+ int need_ext;
int cost;
while (isspace (*rp))
@@ -195,65 +206,68 @@ add_module (char *rp, const char *directory, size_t dir_len, void **modules,
/* Increment by one for the slash. */
++dir_len;
+ /* See whether we must add the ending. */
+ need_ext = 0;
+ if (wp - module < sizeof (gconv_module_ext)
+ || memcmp (wp - sizeof (gconv_module_ext), gconv_module_ext,
+ sizeof (gconv_module_ext)) != 0)
+ /* We must add the module extension. */
+ need_ext = sizeof (gconv_module_ext) - 1;
+
/* We've collected all the information, now create an entry. */
- const_len = 0;
if (from_is_regex)
- do
- ++const_len;
- while (isalnum (from[const_len]) || from[const_len] == '-'
- || from[const_len] == '/' || from[const_len] == '.'
- || from[const_len] == '_');
+ {
+ const_len = 0;
+ while (isalnum (from[const_len]) || from[const_len] == '-'
+ || from[const_len] == '/' || from[const_len] == '.'
+ || from[const_len] == '_')
+ ++const_len;
+ }
+ else
+ const_len = to - from - 1;
new_module = (struct gconv_module *) malloc (sizeof (struct gconv_module)
- + (wp - from) + const_len
- + dir_len);
+ + (wp - from)
+ + dir_len + need_ext);
if (new_module != NULL)
{
+ char *tmp;
+
+ new_module->from_constpfx = memcpy ((char *) new_module
+ + sizeof (struct gconv_module),
+ from, to - from);
if (from_is_regex)
- {
- new_module->from_pattern = memcpy ((char *) new_module
- + sizeof (struct gconv_module),
- from, to - from);
- new_module->from_constpfx = memcpy ((char *) new_module->from_pattern
- + (to - from),
- from, const_len);
- ((char *) new_module->from_constpfx)[const_len] = '\0';
- new_module->from_constpfx_len = const_len;
- ++const_len;
- }
+ new_module->from_pattern = new_module->from_constpfx;
else
- {
- new_module->from_pattern = NULL;
- new_module->from_constpfx = memcpy ((char *) new_module
- + sizeof (struct gconv_module),
- from, to - from);
- new_module->from_constpfx_len = to - from - 1;
- const_len = to - from;
- }
+ new_module->from_pattern = NULL;
+
+ new_module->from_constpfx_len = const_len;
+
new_module->from_regex = NULL;
new_module->to_string = memcpy ((char *) new_module->from_constpfx
- + const_len + 1, to, module - to);
+ + (to - from), to, module - to);
new_module->cost = cost;
+ new_module->module_name = (char *) new_module->to_string + (module - to);
+
if (dir_len == 0)
- new_module->module_name = memcpy ((char *) new_module->to_string
- + (module - to),
- module, wp - module);
+ tmp = (char *) new_module->module_name;
else
{
- char *tmp;
- new_module->module_name = ((char *) new_module->to_string
- + (module - to));
tmp = __mempcpy ((char *) new_module->module_name,
directory, dir_len - 1);
*tmp++ = '/';
- memcpy (tmp, module, wp - module);
}
- if (__tfind (new_module, *modules, module_compare) != NULL)
+ tmp = __mempcpy (tmp, module, wp - module);
+
+ if (need_ext)
+ memcpy (tmp - 1, gconv_module_ext, sizeof (gconv_module_ext));
+
+ if (__tfind (new_module, modules, module_compare) == NULL)
if (__tsearch (new_module, modules, module_compare) == NULL)
/* Something went wrong while inserting the new module. */
free (new_module);
@@ -267,7 +281,7 @@ static void
insert_module (const void *nodep, VISIT value, int level)
{
if (value == preorder || value == leaf)
- __gconv_modules_db[__gconv_nmodules++] = (struct gconv_module *) nodep;
+ __gconv_modules_db[__gconv_nmodules++] = *(struct gconv_module **) nodep;
}
static void
@@ -302,8 +316,6 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len,
break;
rp = line;
- while (isspace (*rp))
- ++rp;
/* Terminate the line (excluding comments or newline) by an NUL byte
to simplify the following code. */
endp = strchr (rp, '#');
@@ -316,6 +328,9 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len,
*endp = '\0';
}
+ while (isspace (*rp))
+ ++rp;
+
/* If this is an empty line go on with the next one. */
if (rp == endp)
continue;
@@ -325,10 +340,10 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len,
++rp;
if (rp - word == sizeof ("alias") - 1
- && memcpy (word, "alias", sizeof ("alias") - 1) == 0)
+ && memcmp (word, "alias", sizeof ("alias") - 1) == 0)
add_alias (rp);
else if (rp - word == sizeof ("module") - 1
- && memcpy (word, "module", sizeof ("module") - 1) == 0)
+ && memcmp (word, "module", sizeof ("module") - 1) == 0)
add_module (rp, directory, dir_len, modules, nmodules);
/* else */
/* Otherwise ignore the line. */
@@ -349,6 +364,7 @@ __gconv_read_conf (void)
char *gconv_path, *elem;
void *modules = NULL;
size_t nmodules = 0;
+ int save_errno = errno;
if (user_path == NULL)
/* No user-defined path. Make a modifiable copy of the default path. */
@@ -390,31 +406,31 @@ __gconv_read_conf (void)
/* If the configuration files do not contain any valid module specification
remember this by setting the pointer to the module array to NULL. */
- nmodules = sizeof (builtin_modules) / sizeof (struct gconv_module);
+ nmodules += sizeof (builtin_modules) / sizeof (builtin_modules[0]);
if (nmodules == 0)
+ __gconv_modules_db = NULL;
+ else
{
- __gconv_modules_db = NULL;
- return;
- }
+ __gconv_modules_db =
+ (struct gconv_module **) malloc (nmodules
+ * sizeof (struct gconv_module));
+ if (__gconv_modules_db != NULL)
+ {
+ size_t cnt;
- __gconv_modules_db =
- (struct gconv_module **) malloc (nmodules * sizeof (struct gconv_module));
- if (__gconv_modules_db == NULL)
- /* We cannot do anything. */
- return;
+ /* Insert all module entries into the array. */
+ __twalk (modules, insert_module);
- /* First insert the builtin transformations. */
- while (__gconv_nmodules < (sizeof (builtin_modules)
- / sizeof (struct gconv_module)))
- {
- __gconv_modules_db[__gconv_nmodules] =
- &builtin_modules[__gconv_nmodules];
- ++__gconv_nmodules;
- }
+ /* No remove the tree data structure. */
+ __tdestroy (modules, nothing);
- /* Insert all module entries into the array. */
- __twalk (modules, insert_module);
+ /* Finally insert the builtin transformations. */
+ for (cnt = 0; cnt < (sizeof (builtin_modules)
+ / sizeof (struct gconv_module)); ++cnt)
+ __gconv_modules_db[__gconv_nmodules++] = &builtin_modules[cnt];
+ }
+ }
- /* No remove the tree data structure. */
- __tdestroy (modules, nothing);
+ /* Restore the error number. */
+ __set_errno (save_errno);
}
diff --git a/iconv/gconv_db.c b/iconv/gconv_db.c
index ceb94be..b1320ac 100644
--- a/iconv/gconv_db.c
+++ b/iconv/gconv_db.c
@@ -99,7 +99,7 @@ derivation_lookup (const char *fromset, const char *toset,
struct known_derivation key = { fromset, toset, NULL, 0 };
struct known_derivation *result;
- result = __tfind (&key, known_derivations, derivation_compare);
+ result = __tfind (&key, &known_derivations, derivation_compare);
if (result == NULL)
return GCONV_NOCONV;
@@ -169,11 +169,18 @@ gen_steps (struct derivation_step *best, const char *toset,
* step_cnt);
if (result != NULL)
{
+ int failed = 0;
+
+ *nsteps = step_cnt;
current = best;
while (step_cnt-- > 0)
{
- result[step_cnt].from_name = current->last->result_set;
- result[step_cnt].to_name = current->result_set;
+ result[step_cnt].from_name = (step_cnt == 0
+ ? __strdup (fromset)
+ : current->last->result_set);
+ result[step_cnt].to_name = (step_cnt + 1 == *nsteps
+ ? __strdup (current->result_set)
+ : result[step_cnt + 1].from_name);
if (current->code->module_name[0] == '/')
{
@@ -182,7 +189,10 @@ gen_steps (struct derivation_step *best, const char *toset,
__gconv_find_shlib (current->code->module_name);
if (shlib_handle == NULL)
- break;
+ {
+ failed = 1;
+ break;
+ }
result[step_cnt].shlib_handle = shlib_handle;
@@ -192,6 +202,7 @@ gen_steps (struct derivation_step *best, const char *toset,
/* Argh, no conversion function. There is something
wrong here. */
__gconv_release_shlib (result[step_cnt].shlib_handle);
+ failed = 1;
break;
}
@@ -208,18 +219,18 @@ gen_steps (struct derivation_step *best, const char *toset,
current = current->last;
}
- if (step_cnt != 0)
+ if (failed != 0)
{
/* Something went wrong while initializing the modules. */
- while (step_cnt-- > 0)
+ while (++step_cnt < *nsteps)
__gconv_release_shlib (result[step_cnt].shlib_handle);
free (result);
+ *nsteps = 0;
status = GCONV_NOCONV;
}
else
{
*handle = result;
- *nsteps = step_cnt;
status = GCONV_OK;
}
}
@@ -231,12 +242,13 @@ gen_steps (struct derivation_step *best, const char *toset,
/* The main function: find a possible derivation from the `fromset' (either
the given name or the alias) to the `toset' (again with alias). */
static int
+internal_function
find_derivation (const char *toset, const char *toset_expand,
const char *fromset, const char *fromset_expand,
struct gconv_step **handle, size_t *nsteps)
{
__libc_lock_define_initialized (static, lock)
- struct derivation_step *current, **lastp, *best = NULL;
+ struct derivation_step *first, *current, **lastp, *best = NULL;
int best_cost = 0;
int result;
@@ -260,16 +272,17 @@ find_derivation (const char *toset, const char *toset_expand,
The task is to match the `toset' with any of the available. */
if (fromset_expand != NULL)
{
- current = NEW_STEP (fromset_expand, NULL, NULL);
- current->next = NEW_STEP (fromset, NULL, NULL);
- lastp = &current->next->next;
+ first = NEW_STEP (fromset_expand, NULL, NULL);
+ first->next = NEW_STEP (fromset, NULL, NULL);
+ lastp = &first->next->next;
}
else
{
- current = NEW_STEP (fromset, NULL, NULL);
- lastp = &current->next;
+ first = NEW_STEP (fromset, NULL, NULL);
+ lastp = &first->next;
}
+ current = first;
while (current != NULL)
{
/* Now match all the available module specifications against the
@@ -419,13 +432,28 @@ find_derivation (const char *toset, const char *toset_expand,
}
else
{
- /* Append at the end. */
- *lastp = NEW_STEP (result_set, __gconv_modules_db[cnt],
- current);
- lastp = &(*lastp)->next;
+ /* Append at the end if there is no entry with this name. */
+ struct derivation_step *runp = first;
+
+ while (runp != NULL)
+ {
+ if (__strcasecmp (result_set, runp->result_set) == 0)
+ break;
+ runp = runp->next;
+ }
+
+ if (runp == NULL)
+ {
+ *lastp = NEW_STEP (result_set, __gconv_modules_db[cnt],
+ current);
+ lastp = &(*lastp)->next;
+ }
}
}
}
+
+ /* Go on with the next entry. */
+ current = current->next;
}
if (best != NULL)
@@ -470,15 +498,15 @@ __gconv_find_transform (const char *toset, const char *fromset,
if (__gconv_alias_db != NULL)
{
struct gconv_alias key;
- struct gconv_alias *found;
+ struct gconv_alias **found;
key.fromname = fromset;
- found = __tfind (&key, __gconv_alias_db, __gconv_alias_compare);
- fromset_expand = found != NULL ? found->toname : NULL;
+ found = __tfind (&key, &__gconv_alias_db, __gconv_alias_compare);
+ fromset_expand = found != NULL ? (*found)->toname : NULL;
key.fromname = toset;
- found = __tfind (&key, __gconv_alias_db, __gconv_alias_compare);
- toset_expand = found != NULL ? found->toname : NULL;
+ found = __tfind (&key, &__gconv_alias_db, __gconv_alias_compare);
+ toset_expand = found != NULL ? (*found)->toname : NULL;
}
result = find_derivation (toset, toset_expand, fromset, fromset_expand,
diff --git a/iconv/gconv_dl.c b/iconv/gconv_dl.c
index a0003a8..a80e5ef 100644
--- a/iconv/gconv_dl.c
+++ b/iconv/gconv_dl.c
@@ -84,6 +84,7 @@ do_open (void *a)
static int
+internal_function
dlerror_run (void (*operate) (void *), void *args)
{
char *last_errstring = NULL;
@@ -156,7 +157,7 @@ __gconv_find_shlib (const char *name)
enough to a pointer to our structure to use as a lookup key that
will be passed to `known_compare' (above). */
- found = __tfind (&name, loaded, known_compare);
+ found = __tfind (&name, &loaded, known_compare);
if (found == NULL)
{
/* This name was not known before. */
@@ -208,7 +209,7 @@ static void *release_handle;
static void
do_release_shlib (const void *nodep, VISIT value, int level)
{
- struct loaded_object *obj = (struct loaded_object *) nodep;
+ struct loaded_object *obj = *(struct loaded_object **) nodep;
if (value != preorder && value != leaf)
return;
diff --git a/iconv/gconv_open.c b/iconv/gconv_open.c
index 0e789df..343cb70 100644
--- a/iconv/gconv_open.c
+++ b/iconv/gconv_open.c
@@ -69,19 +69,19 @@ __gconv_open (const char *toset, const char *fromset, gconv_t *handle)
if (res != GCONV_OK)
break;
}
- else
- if (!data[cnt].is_last)
- {
- data[cnt].outbufsize = GCONV_DEFAULT_BUFSIZE;
- data[cnt].outbuf =
- (char *) malloc (data[cnt].outbufsize);
- if (data[cnt].outbuf == NULL)
- {
- res = GCONV_NOMEM;
- break;
- }
- data[cnt].outbufavail = 0;
- }
+
+ if (!data[cnt].is_last && data[cnt].outbuf == NULL)
+ {
+ data[cnt].outbufsize = GCONV_DEFAULT_BUFSIZE;
+ data[cnt].outbuf =
+ (char *) malloc (data[cnt].outbufsize);
+ if (data[cnt].outbuf == NULL)
+ {
+ res = GCONV_NOMEM;
+ break;
+ }
+ data[cnt].outbufavail = 0;
+ }
}
}
}
diff --git a/iconv/gconv_simple.c b/iconv/gconv_simple.c
index 582c6f5..f769795 100644
--- a/iconv/gconv_simple.c
+++ b/iconv/gconv_simple.c
@@ -117,7 +117,7 @@ __gconv_transform_ucs4_utf8 (struct gconv_step *step,
do
{
const char *newinbuf = inbuf;
- size_t actually = __wcsnrtombs (&data->outbuf[data->outbufavail],
+ size_t actually = __wmemrtombs (&data->outbuf[data->outbufavail],
(const wchar_t **) &newinbuf,
*inlen / sizeof (wchar_t),
data->outbufsize - data->outbufavail,
@@ -206,7 +206,7 @@ __gconv_transform_utf8_ucs4 (struct gconv_step *step,
do
{
const char *newinbuf = inbuf;
- size_t actually = __mbsnrtowcs ((wchar_t *) &data->outbuf[data->outbufavail],
+ size_t actually = __wmemrtowcs ((wchar_t *) &data->outbuf[data->outbufavail],
&newinbuf, *inlen,
((data->outbufsize
- data->outbufavail)
diff --git a/iconv/iconv.c b/iconv/iconv.c
index e5b0eb7..8804e85 100644
--- a/iconv/iconv.c
+++ b/iconv/iconv.c
@@ -19,9 +19,12 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#include <errno.h>
#include <iconv.h>
#include <gconv.h>
+#include <assert.h>
+
size_t
iconv (iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf,
@@ -29,10 +32,39 @@ iconv (iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf,
{
gconv_t gcd = (gconv_t) cd;
size_t converted;
+ int result;
+
+ result = __gconv (gcd, inbuf, inbytesleft, outbuf, outbytesleft, &converted);
+ switch (result)
+ {
+ case GCONV_ILLEGAL_DESCRIPTOR:
+ __set_errno (EBADF);
+ converted = (size_t) -1L;
+ break;
+
+ case GCONV_ILLEGAL_INPUT:
+ __set_errno (EILSEQ);
+ converted = (size_t) -1L;
+ break;
+
+ case GCONV_FULL_OUTPUT:
+ __set_errno (E2BIG);
+ converted = (size_t) -1L;
+ break;
+
+ case GCONV_INCOMPLETE_INPUT:
+ __set_errno (EINVAL);
+ converted = (size_t) -1L;
+ break;
+
+ case GCONV_EMPTY_INPUT:
+ case GCONV_OK:
+ /* Nothing. */
+ break;
- if (__gconv (gcd, inbuf, inbytesleft, outbuf, outbytesleft, &converted)
- != GCONV_OK)
- return (size_t) -1;
+ default:
+ assert (!"Nothing like this should happen");
+ }
return converted;
}
diff --git a/iconv/iconv_close.c b/iconv/iconv_close.c
index d3123e2..ccd9d5f 100644
--- a/iconv/iconv_close.c
+++ b/iconv/iconv_close.c
@@ -18,6 +18,7 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#include <errno.h>
#include <iconv.h>
#include <gconv.h>
@@ -26,5 +27,11 @@
int
iconv_close (iconv_t cd)
{
+ if (cd == (iconv_t *) -1L)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+
return __gconv_close ((gconv_t) cd) ? -1 : 0;
}
diff --git a/iconv/iconv_open.c b/iconv/iconv_open.c
index 82802b7..bfff00d 100644
--- a/iconv/iconv_open.c
+++ b/iconv/iconv_open.c
@@ -27,11 +27,9 @@
static inline void
-strip (char *s)
+strip (char *wp, const char *s)
{
int slash_count = 0;
- char *wp;
- wp = s;
while (*s != '\0')
{
@@ -39,7 +37,7 @@ strip (char *s)
*wp++ = *s;
else if (*s == '/')
{
- if (++slash_count == 2)
+ if (++slash_count == 3)
break;
*wp++ = '/';
}
@@ -67,14 +65,15 @@ iconv_open (const char *tocode, const char *fromcode)
'_', '-', '/', and '.'. */
tocode_len = strlen (tocode);
tocode_conv = alloca (tocode_len + 3);
- strip (memcpy (tocode_conv, tocode, tocode_len + 1));
+ strip (tocode_conv, tocode);
fromcode_len = strlen (fromcode);
fromcode_conv = alloca (fromcode_len + 3);
- strip (memcpy (fromcode_conv, fromcode, fromcode_len + 1));
+ strip (fromcode_conv, fromcode);
res = __gconv_open (tocode_conv[2] == '\0' ? tocode : tocode_conv,
- fromcode_conv[2] == '\0' ? fromcode, fromcode_conv, &cd);
+ fromcode_conv[2] == '\0' ? fromcode : fromcode_conv,
+ &cd);
if (res != GCONV_OK)
{
diff --git a/sysdeps/generic/enbl-secure.c b/sysdeps/generic/enbl-secure.c
index b4c8e00..fdf6f15 100644
--- a/sysdeps/generic/enbl-secure.c
+++ b/sysdeps/generic/enbl-secure.c
@@ -26,9 +26,8 @@
/* Safest assumption, if somehow the initializer isn't run. */
int __libc_enable_secure = 1;
-static void
-__attribute__ ((unused, constructor))
-init_secure (void)
+void
+__libc_init_secure (void)
{
__libc_enable_secure = (__geteuid () != __getuid () ||
__getegid () != __getgid ());
diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile
index 985f595..5dd46da 100644
--- a/wcsmbs/Makefile
+++ b/wcsmbs/Makefile
@@ -29,7 +29,7 @@ routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \
wmemcmp wmemcpy wmemmove wmemset wcpcpy wcpncpy \
btowc wctob mbsinit \
mbrlen mbrtowc wcrtomb mbsrtowcs wcsrtombs \
- mbsnrtowcs wcsnrtombs \
+ mbsnrtowcs wcsnrtombs wmemrtowcs wmemrtombs \
wcstol wcstoul wcstoll wcstoull wcstod wcstold wcstof \
wcstol_l wcstoul_l wcstoll_l wcstoull_l \
wcstod_l wcstold_l wcstof_l \
diff --git a/wcsmbs/wchar.h b/wcsmbs/wchar.h
index 966d20c..4c8f9a4 100644
--- a/wcsmbs/wchar.h
+++ b/wcsmbs/wchar.h
@@ -253,6 +253,16 @@ extern size_t mbsnrtowcs __P ((wchar_t *__restrict __dst,
__const char **__restrict __src, size_t __nmc,
size_t __len, mbstate_t *__restrict __ps));
+/* Similar function to the above but this does not stop at NUL bytes. */
+extern size_t __wmemrtowcs __P ((wchar_t *__restrict __dst,
+ __const char **__restrict __src,
+ size_t __nmc, size_t __len,
+ mbstate_t *__restrict __ps));
+extern size_t wmemrtowcs __P ((wchar_t *__restrict __dst,
+ __const char **__restrict __src,
+ size_t __nmc, size_t __len,
+ mbstate_t *__restrict __ps));
+
/* Write multibyte character representation of at most NWC characters
from the wide character string SRC to DST. */
extern size_t __wcsnrtombs __P ((char *__restrict __dst,
@@ -264,6 +274,16 @@ extern size_t wcsnrtombs __P ((char *__restrict __dst,
size_t __nwc, size_t __len,
mbstate_t *__restrict __ps));
+/* Similar function to the above but this does not stop at NUL bytes. */
+extern size_t __wmemrtombs __P ((char *__restrict __dst,
+ __const wchar_t **__restrict __src,
+ size_t __nwc, size_t len,
+ mbstate_t *__restrict __ps));
+extern size_t wmemrtombs __P ((char *__restrict __dst,
+ __const wchar_t **__restrict __src,
+ size_t __nwc, size_t len,
+ mbstate_t *__restrict __ps));
+
/* The following functions are extensions found in X/Open CAE. */
diff --git a/wcsmbs/wmemrtombs.c b/wcsmbs/wmemrtombs.c
new file mode 100644
index 0000000..2bbd667
--- /dev/null
+++ b/wcsmbs/wmemrtombs.c
@@ -0,0 +1,121 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@gnu.org>, 1997.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <errno.h>
+#include <wchar.h>
+
+#ifndef EILSEQ
+#define EILSEQ EINVAL
+#endif
+
+
+static const wchar_t encoding_mask[] =
+{
+ ~0x7ff, ~0xffff, ~0x1fffff, ~0x3ffffff
+};
+
+static const unsigned char encoding_byte[] =
+{
+ 0xc0, 0xe0, 0xf0, 0xf8, 0xfc
+};
+
+/* We don't need the state really because we don't have shift states
+ to maintain between calls to this function. */
+static mbstate_t internal;
+
+/* This is a non-standard function but it is very useful in the
+ implementation of stdio because we have to deal with unterminated
+ buffers. At most NWC wide character will be converted. */
+size_t
+__wmemrtombs (dst, src, nwc, len, ps)
+ char *dst;
+ const wchar_t **src;
+ size_t nwc;
+ size_t len;
+ mbstate_t *ps;
+{
+ size_t written = 0;
+ const wchar_t *run = *src;
+
+ if (ps == NULL)
+ ps = &internal;
+
+ if (dst == NULL)
+ /* The LEN parameter has to be ignored if we don't actually write
+ anything. */
+ len = ~0;
+
+ while (written < len && nwc-- > 0)
+ {
+ wchar_t wc = *run++;
+
+ if (wc < 0 || wc > 0x7fffffff)
+ {
+ /* This is no correct ISO 10646 character. */
+ __set_errno (EILSEQ);
+ return (size_t) -1;
+ }
+
+ if (wc < 0x80)
+ {
+ /* It's an one byte sequence. */
+ if (dst != NULL)
+ *dst++ = (char) wc;
+ ++written;
+ }
+ else
+ {
+ size_t step;
+
+ for (step = 2; step < 6; ++step)
+ if ((wc & encoding_mask[step - 2]) == 0)
+ break;
+
+ if (written + step >= len)
+ /* Too long. */
+ break;
+
+ if (dst != NULL)
+ {
+ size_t cnt = step;
+
+ dst[0] = encoding_byte[cnt - 2];
+
+ --cnt;
+ do
+ {
+ dst[cnt] = 0x80 | (wc & 0x3f);
+ wc >>= 6;
+ }
+ while (--cnt > 0);
+ dst[0] |= wc;
+
+ dst += step;
+ }
+
+ written += step;
+ }
+ }
+
+ /* Store position of first unprocessed word. */
+ *src = run;
+
+ return written;
+}
+weak_alias (__wmemrtombs, wmemrtombs)
diff --git a/wcsmbs/wmemrtowcs.c b/wcsmbs/wmemrtowcs.c
new file mode 100644
index 0000000..1686229
--- /dev/null
+++ b/wcsmbs/wmemrtowcs.c
@@ -0,0 +1,134 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@gnu.org>, 1997.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <errno.h>
+#include <wchar.h>
+
+#ifndef EILSEQ
+#define EILSEQ EINVAL
+#endif
+
+
+/* We don't need the state really because we don't have shift states
+ to maintain between calls to this function. */
+static mbstate_t internal;
+
+/* This is a non-standard function but it is very useful in the
+ implementation of stdio because we have to deal with unterminated
+ buffers. At most NMC bytes will be converted. */
+size_t
+__wmemrtowcs (dst, src, nmc, len, ps)
+ wchar_t *dst;
+ const char **src;
+ size_t nmc;
+ size_t len;
+ mbstate_t *ps;
+{
+ size_t written = 0;
+ const char *run = *src;
+ const char *last = run + nmc;
+
+ if (ps == NULL)
+ ps = &internal;
+
+ if (dst == NULL)
+ /* The LEN parameter has to be ignored if we don't actually write
+ anything. */
+ len = ~0;
+
+ /* Copy all words. */
+ while (written < len && run < last)
+ {
+ wchar_t value;
+ size_t count;
+ unsigned char byte = *run++;
+
+ /* We expect a start of a new multibyte character. */
+ if (byte < 0x80)
+ {
+ /* One byte sequence. */
+ count = 0;
+ value = byte;
+ }
+ else if ((byte & 0xe0) == 0xc0)
+ {
+ count = 1;
+ value = byte & 0x1f;
+ }
+ else if ((byte & 0xf0) == 0xe0)
+ {
+ /* We expect three bytes. */
+ count = 2;
+ value = byte & 0x0f;
+ }
+ else if ((byte & 0xf8) == 0xf0)
+ {
+ /* We expect four bytes. */
+ count = 3;
+ value = byte & 0x07;
+ }
+ else if ((byte & 0xfc) == 0xf8)
+ {
+ /* We expect five bytes. */
+ count = 4;
+ value = byte & 0x03;
+ }
+ else if ((byte & 0xfe) == 0xfc)
+ {
+ /* We expect six bytes. */
+ count = 5;
+ value = byte & 0x01;
+ }
+ else
+ {
+ /* This is an illegal encoding. */
+ __set_errno (EILSEQ);
+ return (size_t) -1;
+ }
+
+ /* Read the possible remaining bytes. */
+ while (count-- > 0)
+ {
+ byte = *run++;
+
+ if ((byte & 0xc0) != 0x80)
+ {
+ /* This is an illegal encoding. */
+ __set_errno (EILSEQ);
+ return (size_t) -1;
+ }
+
+ value <<= 6;
+ value |= byte & 0x3f;
+ }
+
+ /* Store value is required. */
+ if (dst != NULL)
+ *dst++ = value;
+
+ /* Increment counter of produced words. */
+ ++written;
+ }
+
+ /* Store address of next byte to process. */
+ *src = run;
+
+ return written;
+}
+weak_alias (__wmemrtowcs, wmemrtowcs)