Converted all m_free to xfree etc.
[gnupg.git] / util / strgutil.c
index 67dafce..cffdfcf 100644 (file)
@@ -1,6 +1,6 @@
 /* strgutil.c -  string utilities
  * Copyright (C) 1994, 1998, 1999, 2000, 2001,
- *               2003 Free Software Foundation, Inc.
+ *               2003, 2004, 2005 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -16,7 +16,8 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
  */
 
 #include <config.h>
@@ -142,8 +143,10 @@ load_libiconv (void)
         }
       if (!handle || !iconv_close)
         {
-          log_error (_("error loading `%s': %s\n"),
+          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;
@@ -165,7 +168,7 @@ free_strlist( STRLIST sl )
 
     for(; sl; sl = sl2 ) {
        sl2 = sl->next;
-       m_free(sl);
+       xfree(sl);
     }
 }
 
@@ -175,7 +178,7 @@ add_to_strlist( STRLIST *list, const char *string )
 {
     STRLIST sl;
 
-    sl = m_alloc( sizeof *sl + strlen(string));
+    sl = xmalloc( sizeof *sl + strlen(string));
     sl->flags = 0;
     strcpy(sl->d, string);
     sl->next = *list;
@@ -197,7 +200,7 @@ add_to_strlist2( STRLIST *list, const char *string, int is_utf8 )
     else {
        char *p = native_to_utf8( string );
        sl = add_to_strlist( list, p );
-       m_free( p );
+       xfree( p );
     }
     return sl;
 }
@@ -207,7 +210,7 @@ append_to_strlist( STRLIST *list, const char *string )
 {
     STRLIST r, sl;
 
-    sl = m_alloc( sizeof *sl + strlen(string));
+    sl = xmalloc( sizeof *sl + strlen(string));
     sl->flags = 0;
     strcpy(sl->d, string);
     sl->next = NULL;
@@ -231,7 +234,7 @@ append_to_strlist2( STRLIST *list, const char *string, int is_utf8 )
     else {
        char *p = native_to_utf8( string );
        sl = append_to_strlist( list, p );
-       m_free( p );
+       xfree( p );
     }
     return sl;
 }
@@ -264,11 +267,11 @@ pop_strlist( STRLIST *list )
 
   if(sl)
     {
-      str=m_alloc(strlen(sl->d)+1);
+      str=xmalloc(strlen(sl->d)+1);
       strcpy(str,sl->d);
 
       *list=sl->next;
-      m_free(sl);
+      xfree(sl);
     }
 
   return str;
@@ -320,7 +323,7 @@ ascii_memistr( const char *buf, size_t buflen, const char *sub )
 
 /* Like strncpy() but copy at max N-1 bytes and append a '\0'.  With
  * N given as 0 nothing is copied at all. With DEST given as NULL
- * sufficient memory is allocated using m_alloc (note that m_alloc is
+ * sufficient memory is allocated using xmalloc (note that xmalloc is
  * guaranteed to succeed or to abort the process).  */
 char *
 mem2str( char *dest , const void *src , size_t n )
@@ -330,7 +333,7 @@ mem2str( char *dest , const void *src , size_t n )
 
     if( n ) {
        if( !dest )
-           dest = m_alloc( n ) ;
+           dest = xmalloc( n ) ;
        d = dest;
        s = src ;
        for(n--; n && *s; n-- )
@@ -451,10 +454,33 @@ static void
 handle_iconv_error (const char *to, const char *from, int use_fallback)
 {
   if (errno == EINVAL)
-    log_error (_("conversion from `%s' to `%s' not available\n"),
-               from, to);
+    {
+      static int shown1, shown2;
+      int x;
+
+      if (to && !strcmp (to, "utf-8"))
+        {
+          x = shown1;
+          shown1 = 1;
+        }
+      else
+        {
+          x = shown2;
+          shown2 = 1;
+        }
+
+      if (!x)
+        log_info (_("conversion from `%s' to `%s' not available\n"),
+                  from, to);
+    }
   else
-    log_error (_("iconv_open failed: %s\n"), strerror (errno));
+    {
+      static int shown;
+
+      if (!shown)
+        log_info (_("iconv_open failed: %s\n"), strerror (errno));
+      shown = 1;
+    }
 
   if (use_fallback)
     {
@@ -479,28 +505,79 @@ set_native_charset( const char *newset )
     if (!newset) {
 #ifdef _WIN32
         static char codepage[30];
+        unsigned int cpno;
+        const char *aliases;
 
         /* We are a console program thus we need to use the
-           GetConsoleOutputCP fucntion and not the the GetACP which
+           GetConsoleOutputCP function and not the the GetACP which
            would give the codepage for a GUI program.  Note this is
            not a bulletproof detection because GetConsoleCP might
-           retrun a different one for console input.  Not sure how to
-           cope with that.  */
-        sprintf (codepage, "CP%u", (unsigned int)GetConsoleOutputCP ());
-        /* If it is the Windows name for Latin-1 we use the standard
-           name instead to avoid loading of iconv.dll.  Unfortunately
-           it is often CP850 and we don't have a custom translation
-           for it. */
-        if (!strcmp (codepage, "CP1252"))
-            newset = "iso-8859-1";
-        else
-            newset = codepage;
+           return a different one for console input.  Not sure how to
+           cope with that.  If the console Code page is not known we
+           fall back to the system code page.  */
+        cpno = GetConsoleOutputCP ();
+        if (!cpno)
+          cpno = GetACP ();
+        sprintf (codepage, "CP%u", cpno );
+        /* Resolve alias.  We use a long string string and not the
+           usual array to optimize if the code is taken to a DSO.
+           Taken from libiconv 1.9.2. */
+        newset = codepage;
+        for (aliases = ("CP936"   "\0" "GBK" "\0"
+                        "CP1361"  "\0" "JOHAB" "\0"
+                        "CP20127" "\0" "ASCII" "\0"
+                        "CP20866" "\0" "KOI8-R" "\0"
+                        "CP21866" "\0" "KOI8-RU" "\0"
+                        "CP28591" "\0" "ISO-8859-1" "\0"
+                        "CP28592" "\0" "ISO-8859-2" "\0"
+                        "CP28593" "\0" "ISO-8859-3" "\0"
+                        "CP28594" "\0" "ISO-8859-4" "\0"
+                        "CP28595" "\0" "ISO-8859-5" "\0"
+                        "CP28596" "\0" "ISO-8859-6" "\0"
+                        "CP28597" "\0" "ISO-8859-7" "\0"
+                        "CP28598" "\0" "ISO-8859-8" "\0"
+                        "CP28599" "\0" "ISO-8859-9" "\0"
+                        "CP28605" "\0" "ISO-8859-15" "\0"
+                       "CP65001" "\0" "UTF-8" "\0");
+             *aliases;
+             aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1)
+          {
+            if (!strcmp (codepage, aliases) ||(*aliases == '*' && !aliases[1]))
+              {
+                newset = aliases + strlen (aliases) + 1;
+                break;
+              }
+          }
+
 #else
 #ifdef HAVE_LANGINFO_CODESET
         newset = nl_langinfo (CODESET);
-#else
-        newset = "iso-8859-1";
-#endif
+#else /* !HAVE_LANGINFO_CODESET */
+        /* Try to get the used charset from environment variables.  */
+        static char codepage[30];
+        const char *lc, *dot, *mod;
+
+        strcpy (codepage, "iso-8859-1");
+        lc = getenv ("LC_ALL");
+        if (!lc || !*lc) {
+            lc = getenv ("LC_CTYPE");
+            if (!lc || !*lc)
+                lc = getenv ("LANG");
+        }
+        if (lc && *lc) {
+            dot = strchr (lc, '.');
+            if (dot) {
+                mod = strchr (++dot, '@');
+                if (!mod)
+                    mod = dot + strlen (dot);
+                if (mod - dot < sizeof codepage && dot != mod) {
+                    memcpy (codepage, dot, mod - dot);
+                    codepage [mod - dot] = 0;
+                }
+            }
+        }
+        newset = codepage;
+#endif  /* !HAVE_LANGINFO_CODESET */
 #endif
     }
 
@@ -511,9 +588,18 @@ set_native_charset( const char *newset )
             newset++;
     }
 
+    /* Note that we silently assume that plain ASCII is actually meant
+       as Latin-1.  This makes sense because many Unix system don't
+       have their locale set up properly and thus would get annoying
+       error messages and we have to handle all the "bug"
+       reports. Latin-1 has always been the character set used for 8
+       bit characters on Unix systems. */
     if( !*newset
         || !ascii_strcasecmp (newset, "8859-1" )
-        || !ascii_strcasecmp (newset, "8859-15" ) ) {
+        || !ascii_strcasecmp (newset, "646" )
+        || !ascii_strcasecmp (newset, "ASCII" )
+        || !ascii_strcasecmp (newset, "ANSI_X3.4-1968" )
+        ) {
         active_charset_name = "iso-8859-1";
         no_translation = 0;
        active_charset = NULL;
@@ -591,7 +677,7 @@ native_to_utf8( const char *string )
   
   if (no_translation)
     { /* Already utf-8 encoded. */
-      buffer = m_strdup (string);
+      buffer = xstrdup (string);
     }
   else if( !active_charset && !use_iconv) /* Shortcut implementation
                                              for Latin-1.  */
@@ -602,7 +688,7 @@ native_to_utf8( const char *string )
           if( *s & 0x80 )
             length++;
        }
-      buffer = m_alloc( length + 1 );
+      buffer = xmalloc( length + 1 );
       for(p=buffer, s=string; *s; s++ )
         {
           if( *s & 0x80 )
@@ -636,7 +722,7 @@ native_to_utf8( const char *string )
           if ((*s & 0x80))
             length += 5; /* We may need up to 6 bytes for the utf8 output. */
         }
-      buffer = m_alloc (length + 1);
+      buffer = xmalloc (length + 1);
 
       inptr = string;
       inbytes = strlen (string);
@@ -645,8 +731,12 @@ native_to_utf8( const char *string )
       if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes,
                   &outptr, &outbytes) == (size_t)-1)
         {
-          log_error (_("conversion from `%s' to `%s' failed: %s\n"),
-                       active_charset_name, "utf-8", strerror (errno));
+          static int shown;
+
+          if (!shown)
+            log_info (_("conversion from `%s' to `%s' failed: %s\n"),
+                      active_charset_name, "utf-8", strerror (errno));
+          shown = 1;
           /* We don't do any conversion at all but use the strings as is. */
           strcpy (buffer, string);
         }
@@ -666,7 +756,7 @@ native_to_utf8( const char *string )
           if( *s & 0x80 )
             length += 2; /* We may need up to 3 bytes. */
         }
-      buffer = m_alloc( length + 1 );
+      buffer = xmalloc( length + 1 );
       for(p=buffer, s=string; *s; s++ ) {
         if( *s & 0x80 ) {
           ushort val = active_charset[ *s & 0x7f ];
@@ -888,7 +978,7 @@ utf8_to_native( const char *string, size_t length, int delim )
            }
        }
        if( !buffer ) { /* allocate the buffer after the first pass */
-           buffer = p = m_alloc( n + 1 );
+           buffer = p = xmalloc( n + 1 );
        }
 #ifdef USE_GNUPG_ICONV
         else if(use_iconv) {
@@ -904,7 +994,7 @@ utf8_to_native( const char *string, size_t length, int delim )
             if (cd == (iconv_t)-1)
                 {
                     handle_iconv_error (active_charset_name, "utf-8", 1);
-                    m_free (buffer);
+                    xfree (buffer);
                     return utf8_to_native (string, length, delim);
                 }
 
@@ -916,16 +1006,20 @@ utf8_to_native( const char *string, size_t length, int delim )
             outbytes = n * MB_LEN_MAX;
             if (outbytes / MB_LEN_MAX != n) 
                 BUG (); /* Actually an overflow. */
-            outbuf = outptr = m_alloc (outbytes);
+            outbuf = outptr = xmalloc (outbytes);
             if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes,
                         &outptr, &outbytes) == (size_t)-1) {
-                log_error (_("conversion from `%s' to `%s' failed: %s\n"),
-                           "utf-8", active_charset_name, strerror (errno));
+                static int shown;
+                
+                if (!shown)
+                  log_info (_("conversion from `%s' to `%s' failed: %s\n"),
+                            "utf-8", active_charset_name, strerror (errno));
+                shown = 1;
                 /* Didn't worked out.  Temporary disable the use of
                  * iconv and fall back to our old code. */
-                m_free (buffer);
+                xfree (buffer);
                 buffer = NULL;
-                m_free (outbuf);
+                xfree (outbuf);
                 use_iconv = 0;
                 outbuf = utf8_to_native (string, length, delim);
                 use_iconv = 1;
@@ -935,7 +1029,7 @@ utf8_to_native( const char *string, size_t length, int delim )
                 /* We could realloc the buffer now but I doubt that it makes
                    much sense given that it will get freed anyway soon
                    after.  */
-                m_free (buffer);
+                xfree (buffer);
             }
             iconv_close (cd);
             return outbuf;
@@ -1157,7 +1251,7 @@ strncasecmp( const char *a, const char *b, size_t n )
 #ifdef _WIN32
 /* 
  * Like vsprintf but provides a pointer to malloc'd storage, which
- * must be freed by the caller (m_free).  Taken from libiberty as
+ * must be freed by the caller (xfree).  Taken from libiberty as
  * found in gcc-2.95.2 and a little bit modernized.
  * FIXME: Write a new CRT for W32.
  */
@@ -1241,7 +1335,7 @@ vasprintf (char **result, const char *format, va_list args)
            }
        }
     }
-  *result = m_alloc (total_width);
+  *result = xmalloc (total_width);
   if (*result != NULL)
     return vsprintf (*result, format, args);
   else
@@ -1260,4 +1354,20 @@ asprintf (char **buf, const char *fmt, ...)
   return status;  
 }
 
+const char *
+w32_strerror (int w32_errno)
+{
+  static char strerr[256];
+  int ec = (int)GetLastError ();
+  
+  if (w32_errno == 0)
+    w32_errno = ec;
+  FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, w32_errno,
+                 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+                 strerr, DIM (strerr)-1, NULL);
+  return strerr;    
+}
 #endif /*_WIN32*/
+
+
+