Update. cvs/libc-ud-971123
authorUlrich Drepper <drepper@redhat.com>
Mon, 24 Nov 1997 02:08:40 +0000 (02:08 +0000)
committerUlrich Drepper <drepper@redhat.com>
Mon, 24 Nov 1997 02:08:40 +0000 (02:08 +0000)
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.

19 files changed:
ChangeLog
elf/dl-support.c
iconv/gconv.c
iconv/gconv.h
iconv/gconv_builtin.h
iconv/gconv_close.c
iconv/gconv_conf.c
iconv/gconv_db.c
iconv/gconv_dl.c
iconv/gconv_open.c
iconv/gconv_simple.c
iconv/iconv.c
iconv/iconv_close.c
iconv/iconv_open.c
sysdeps/generic/enbl-secure.c
wcsmbs/Makefile
wcsmbs/wchar.h
wcsmbs/wmemrtombs.c [new file with mode: 0644]
wcsmbs/wmemrtowcs.c [new file with mode: 0644]

index d18f75f..ad17e4f 100644 (file)
--- 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.
index 41997cc..8b69ef0 100644 (file)
@@ -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);
index 0cbb052..5df1635 100644 (file)
@@ -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;
index 2c42f99..879db49 100644 (file)
@@ -37,6 +37,7 @@ enum
   GCONV_EMPTY_INPUT,
   GCONV_FULL_OUTPUT,
   GCONV_ILLEGAL_INPUT,
+  GCONV_INCOMPLETE_INPUT,
 
   GCONV_ILLEGAL_DESCRIPTOR,
   GCONV_INTERNAL_ERROR
index a3070a5..8dcc3aa 100644 (file)
    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)
index d3d023f..791c025 100644 (file)
@@ -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;
index d3c13d7..8a72c7a 100644 (file)
@@ -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);
 }
index ceb94be..b1320ac 100644 (file)
@@ -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,
index a0003a8..a80e5ef 100644 (file)
@@ -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;
index 0e789df..343cb70 100644 (file)
@@ -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;
+                   }
                }
            }
        }
index 582c6f5..f769795 100644 (file)
@@ -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)
index e5b0eb7..8804e85 100644 (file)
    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;
 }
index d3123e2..ccd9d5f 100644 (file)
@@ -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>
 int
 iconv_close (iconv_t cd)
 {
+  if (cd == (iconv_t *) -1L)
+    {
+      __set_errno (EBADF);
+      return -1;
+    }
+
   return __gconv_close ((gconv_t) cd) ? -1 : 0;
 }
index 82802b7..bfff00d 100644 (file)
 
 
 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)
     {
index b4c8e00..fdf6f15 100644 (file)
@@ -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 ());
index 985f595..5dd46da 100644 (file)
@@ -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 \
index 966d20c..4c8f9a4 100644 (file)
@@ -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 (file)
index 0000000..2bbd667
--- /dev/null
@@ -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 (file)
index 0000000..1686229
--- /dev/null
@@ -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)