gpg: Add dedicated error code for PGP-2 keys.
[gnupg.git] / common / logging.c
index 4c2d61b..40d098c 100644 (file)
@@ -1,21 +1,32 @@
 /* logging.c - Useful logging functions
- * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 
+ * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
  *               2009, 2010 Free Software Foundation, Inc.
  *
- * This file is part of JNLIB.
+ * This file is part of JNLIB, which is a subsystem of GnuPG.
  *
  * 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 3 of
- * the License, or (at your option) any later version.
+ * under the terms of either
+ *
+ *   - the GNU Lesser General Public License as published by the Free
+ *     Software Foundation; either version 3 of the License, or (at
+ *     your option) any later version.
+ *
+ * or
+ *
+ *   - the GNU General Public License as published by the Free
+ *     Software Foundation; either version 2 of the License, or (at
+ *     your option) any later version.
+ *
+ * or both in parallel, as here.
  *
  * 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.
+ * 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, see <http://www.gnu.org/licenses/>.
+ * You should have received a copies of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, see <http://www.gnu.org/licenses/>.
  */
 
 
@@ -30,6 +41,9 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #ifdef HAVE_W32_SYSTEM
+# ifdef HAVE_WINSOCK2_H
+#  include <winsock2.h>
+# endif
 # include <windows.h>
 #else /*!HAVE_W32_SYSTEM*/
 # include <sys/socket.h>
@@ -68,6 +82,9 @@
 #ifndef EAFNOSUPPORT
 # define EAFNOSUPPORT EINVAL
 #endif
+#ifndef INADDR_NONE  /* Slowaris is missing that.  */
+#define INADDR_NONE  ((unsigned long)(-1))
+#endif /*INADDR_NONE*/
 
 #ifdef HAVE_W32_SYSTEM
 #define sock_close(a)  closesocket(a)
@@ -82,6 +99,9 @@ static char prefix_buffer[80];
 static int with_time;
 static int with_prefix;
 static int with_pid;
+#ifdef HAVE_W32_SYSTEM
+static int no_registry;
+#endif
 static int (*get_pid_suffix_cb)(unsigned long *r_value);
 static int running_detached;
 static int force_prefixes;
@@ -114,6 +134,9 @@ struct fun_cookie_s
   int quiet;
   int want_socket;
   int is_socket;
+#ifdef HAVE_W32CE_SYSTEM
+  int use_writefile;
+#endif
   char name[1];
 };
 
@@ -128,7 +151,7 @@ writen (int fd, const void *buffer, size_t nbytes, int is_socket)
 #ifndef HAVE_W32_SYSTEM
   (void)is_socket; /* Not required.  */
 #endif
-  
+
   while (nleft > 0)
     {
 #ifdef HAVE_W32_SYSTEM
@@ -145,14 +168,14 @@ writen (int fd, const void *buffer, size_t nbytes, int is_socket)
       nleft -= nwritten;
       buf = buf + nwritten;
     }
-  
+
   return 0;
 }
 
 
 /* Returns true if STR represents a valid port number in decimal
    notation and no garbage is following.  */
-static int 
+static int
 parse_portno (const char *str, unsigned short *r_port)
 {
   unsigned int value;
@@ -171,7 +194,7 @@ parse_portno (const char *str, unsigned short *r_port)
 }
 
 
-static ssize_t 
+static ssize_t
 fun_writer (void *cookie_arg, const void *buffer, size_t size)
 {
   struct fun_cookie_s *cookie = cookie_arg;
@@ -216,7 +239,7 @@ fun_writer (void *cookie_arg, const void *buffer, size_t size)
       else if (!strncmp (name, "socket://", 9) && name[9])
         name += 9;
 #endif
-      
+
       if (af == AF_LOCAL)
         {
 #ifdef HAVE_W32_SYSTEM
@@ -234,7 +257,9 @@ fun_writer (void *cookie_arg, const void *buffer, size_t size)
       else
         {
           char *addrstr, *p;
+#ifdef HAVE_INET_PTON
           void *addrbuf = NULL;
+#endif /*HAVE_INET_PTON*/
 
           addrstr = jnlib_malloc (strlen (name) + 1);
           if (!addrstr)
@@ -249,7 +274,7 @@ fun_writer (void *cookie_arg, const void *buffer, size_t size)
                   jnlib_set_errno (EINVAL);
                   addrlen = 0;
                 }
-              else 
+              else
                 {
                   *p = 0;
 #ifdef WITH_IPV6
@@ -258,7 +283,9 @@ fun_writer (void *cookie_arg, const void *buffer, size_t size)
                   memset (&srvr_addr_in6, 0, sizeof srvr_addr_in6);
                   srvr_addr_in6.sin6_family = af;
                   srvr_addr_in6.sin6_port = htons (port);
+#ifdef HAVE_INET_PTON
                   addrbuf = &srvr_addr_in6.sin6_addr;
+#endif /*HAVE_INET_PTON*/
                   srvr_addr = (struct sockaddr *)&srvr_addr_in6;
                   addrlen = sizeof srvr_addr_in6;
 #else
@@ -283,7 +310,9 @@ fun_writer (void *cookie_arg, const void *buffer, size_t size)
                   memset (&srvr_addr_in, 0, sizeof srvr_addr_in);
                   srvr_addr_in.sin_family = af;
                   srvr_addr_in.sin_port = htons (port);
+#ifdef HAVE_INET_PTON
                   addrbuf = &srvr_addr_in.sin_addr;
+#endif /*HAVE_INET_PTON*/
                   srvr_addr = (struct sockaddr *)&srvr_addr_in;
                   addrlen = sizeof srvr_addr_in;
                 }
@@ -304,7 +333,7 @@ fun_writer (void *cookie_arg, const void *buffer, size_t size)
                 addrlen = 0;
 #endif /*!HAVE_INET_PTON*/
             }
-      
+
           jnlib_free (addrstr);
         }
 
@@ -322,13 +351,13 @@ fun_writer (void *cookie_arg, const void *buffer, size_t size)
             {
               if (!cookie->quiet && !running_detached
                   && isatty (es_fileno (es_stderr)))
-                es_fprintf (es_stderr, "can't connect to `%s': %s\n",
+                es_fprintf (es_stderr, "can't connect to '%s': %s\n",
                             cookie->name, strerror(errno));
               sock_close (cookie->fd);
               cookie->fd = -1;
             }
         }
-      
+
       if (cookie->fd == -1)
         {
           if (!running_detached)
@@ -351,16 +380,28 @@ fun_writer (void *cookie_arg, const void *buffer, size_t size)
           cookie->is_socket = 1;
         }
     }
-  
+
   log_socket = cookie->fd;
-  if (cookie->fd != -1 && !writen (cookie->fd, buffer, size, cookie->is_socket))
-    return (ssize_t)size; /* Okay. */ 
-  
+  if (cookie->fd != -1)
+    {
+#ifdef HAVE_W32CE_SYSTEM
+      if (cookie->use_writefile)
+        {
+          DWORD nwritten;
+
+          WriteFile ((HANDLE)cookie->fd, buffer, size, &nwritten, NULL);
+          return (ssize_t)size; /* Okay.  */
+        }
+#endif
+      if (!writen (cookie->fd, buffer, size, cookie->is_socket))
+        return (ssize_t)size; /* Okay. */
+    }
+
   if (!running_detached && cookie->fd != -1
       && isatty (es_fileno (es_stderr)))
     {
       if (*cookie->name)
-        es_fprintf (es_stderr, "error writing to `%s': %s\n",
+        es_fprintf (es_stderr, "error writing to '%s': %s\n",
                     cookie->name, strerror(errno));
       else
         es_fprintf (es_stderr, "error writing to file descriptor %d: %s\n",
@@ -372,7 +413,7 @@ fun_writer (void *cookie_arg, const void *buffer, size_t size)
       cookie->fd = -1;
       log_socket = -1;
     }
-  
+
   return (ssize_t)size;
 }
 
@@ -393,10 +434,13 @@ fun_closer (void *cookie_arg)
 /* Common function to either set the logging to a file or a file
    descriptor. */
 static void
-set_file_fd (const char *name, int fd) 
+set_file_fd (const char *name, int fd)
 {
   estream_t fp;
   int want_socket;
+#ifdef HAVE_W32CE_SYSTEM
+  int use_writefile = 0;
+#endif
   struct fun_cookie_s *cookie;
 
   /* Close an open log stream.  */
@@ -420,6 +464,23 @@ set_file_fd (const char *name, int fd)
   else if (name && !strncmp (name, "socket://", 9) && name[9])
     want_socket = 2;
 #endif /*HAVE_W32_SYSTEM*/
+#ifdef HAVE_W32CE_SYSTEM
+  else if (name && !strcmp (name, "GPG2:"))
+    {
+      HANDLE hd;
+
+      ActivateDevice (L"Drivers\\"GNUPG_NAME"_Log", 0);
+      /* Ignore a filename and write the debug output to the GPG2:
+         device.  */
+      hd = CreateFile (L"GPG2:", GENERIC_WRITE,
+                       FILE_SHARE_READ | FILE_SHARE_WRITE,
+                       NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+      fd = (hd == INVALID_HANDLE_VALUE)? -1 : (int)hd;
+      name = NULL;
+      force_prefixes = 1;
+      use_writefile = 1;
+    }
+#endif /*HAVE_W32CE_SYSTEM*/
 
   /* Setup a new stream.  */
 
@@ -431,6 +492,9 @@ set_file_fd (const char *name, int fd)
   cookie->quiet = 0;
   cookie->is_socket = 0;
   cookie->want_socket = want_socket;
+#ifdef HAVE_W32CE_SYSTEM
+  cookie->use_writefile = use_writefile;
+#endif
   if (!name)
     cookie->fd = fd;
   else if (want_socket)
@@ -448,7 +512,7 @@ set_file_fd (const char *name, int fd)
     es_cookie_io_functions_t io = { NULL };
     io.func_write = fun_writer;
     io.func_close = fun_closer;
-    
+
     fp = es_fopencookie (cookie, "w", io);
   }
 
@@ -457,7 +521,7 @@ set_file_fd (const char *name, int fd)
     fp = es_stderr;
 
   es_setvbuf (fp, NULL, _IOLBF, 0);
-  
+
   logstream = fp;
 
   /* We always need to print the prefix and the pid for socket mode,
@@ -477,7 +541,7 @@ set_file_fd (const char *name, int fd)
    tries the next time again to connect the socket.
   */
 void
-log_set_file (const char *name) 
+log_set_file (const char *name)
 {
   set_file_fd (name? name: "-", -1);
 }
@@ -504,11 +568,14 @@ log_set_prefix (const char *text, unsigned int flags)
       strncpy (prefix_buffer, text, sizeof (prefix_buffer)-1);
       prefix_buffer[sizeof (prefix_buffer)-1] = 0;
     }
-  
+
   with_prefix = (flags & JNLIB_LOG_WITH_PREFIX);
   with_time = (flags & JNLIB_LOG_WITH_TIME);
   with_pid  = (flags & JNLIB_LOG_WITH_PID);
   running_detached = (flags & JNLIB_LOG_RUN_DETACHED);
+#ifdef HAVE_W32_SYSTEM
+  no_registry = (flags & JNLIB_LOG_NO_REGISTRY);
+#endif
 }
 
 
@@ -526,6 +593,10 @@ log_get_prefix (unsigned int *flags)
         *flags |= JNLIB_LOG_WITH_PID;
       if (running_detached)
         *flags |= JNLIB_LOG_RUN_DETACHED;
+#ifdef HAVE_W32_SYSTEM
+      if (no_registry)
+        *flags |= JNLIB_LOG_NO_REGISTRY;
+#endif
     }
   return prefix_buffer;
 }
@@ -572,9 +643,11 @@ do_logv (int level, int ignore_arg_ptr, const char *fmt, va_list arg_ptr)
 #ifdef HAVE_W32_SYSTEM
       char *tmp;
 
-      tmp = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG",
-                                            "DefaultLogFile");
-      log_set_file (tmp);
+      tmp = (no_registry
+             ? NULL
+             : read_w32_registry_string (NULL, GNUPG_REGISTRY_DIR,
+                                         "DefaultLogFile"));
+      log_set_file (tmp && *tmp? tmp : NULL);
       jnlib_free (tmp);
 #else
       log_set_file (NULL); /* Make sure a log stream has been set.  */
@@ -594,7 +667,7 @@ do_logv (int level, int ignore_arg_ptr, const char *fmt, va_list arg_ptr)
         {
           struct tm *tp;
           time_t atime = time (NULL);
-          
+
           tp = localtime (&atime);
           es_fprintf_unlocked (logstream, "%04d-%02d-%02d %02d:%02d:%02d ",
                                1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
@@ -633,7 +706,7 @@ do_logv (int level, int ignore_arg_ptr, const char *fmt, va_list arg_ptr)
     case JNLIB_LOG_FATAL: es_fputs_unlocked ("Fatal: ",logstream ); break;
     case JNLIB_LOG_BUG:   es_fputs_unlocked ("Ohhhh jeeee: ", logstream); break;
     case JNLIB_LOG_DEBUG: es_fputs_unlocked ("DBG: ", logstream ); break;
-    default: 
+    default:
       es_fprintf_unlocked (logstream,"[Unknown log level %d]: ", level);
       break;
     }
@@ -667,11 +740,11 @@ do_logv (int level, int ignore_arg_ptr, const char *fmt, va_list arg_ptr)
 }
 
 
-static void
-do_log (int level, const char *fmt, ...)
+void
+log_log (int level, const char *fmt, ...)
 {
   va_list arg_ptr ;
-  
+
   va_start (arg_ptr, fmt) ;
   do_logv (level, 0, fmt, arg_ptr);
   va_end (arg_ptr);
@@ -709,7 +782,7 @@ void
 log_info (const char *fmt, ...)
 {
   va_list arg_ptr ;
-  
+
   va_start (arg_ptr, fmt);
   do_logv (JNLIB_LOG_INFO, 0, fmt, arg_ptr);
   va_end (arg_ptr);
@@ -720,7 +793,7 @@ void
 log_error (const char *fmt, ...)
 {
   va_list arg_ptr ;
-  
+
   va_start (arg_ptr, fmt);
   do_logv (JNLIB_LOG_ERROR, 0, fmt, arg_ptr);
   va_end (arg_ptr);
@@ -734,7 +807,7 @@ void
 log_fatal (const char *fmt, ...)
 {
   va_list arg_ptr ;
-  
+
   va_start (arg_ptr, fmt);
   do_logv (JNLIB_LOG_FATAL, 0, fmt, arg_ptr);
   va_end (arg_ptr);
@@ -758,7 +831,7 @@ void
 log_debug (const char *fmt, ...)
 {
   va_list arg_ptr ;
-  
+
   va_start (arg_ptr, fmt);
   do_logv (JNLIB_LOG_DEBUG, 0, fmt, arg_ptr);
   va_end (arg_ptr);
@@ -769,7 +842,7 @@ void
 log_printf (const char *fmt, ...)
 {
   va_list arg_ptr;
-  
+
   va_start (arg_ptr, fmt);
   do_logv (fmt ? JNLIB_LOG_CONT : JNLIB_LOG_BEGIN, 0, fmt, arg_ptr);
   va_end (arg_ptr);
@@ -805,19 +878,58 @@ log_printhex (const char *text, const void *buffer, size_t length)
 }
 
 
+/*
+void
+log_printcanon () {}
+is found in sexputils.c
+*/
+
+/*
+void
+log_printsexp () {}
+is found in sexputils.c
+*/
+
+
+void
+log_clock (const char *string)
+{
+#if 0
+  static unsigned long long initial;
+  struct timespec tv;
+  unsigned long long now;
+
+  if (clock_gettime (CLOCK_REALTIME, &tv))
+    {
+      log_debug ("error getting the realtime clock value\n");
+      return;
+    }
+  now = tv.tv_sec * 1000000000ull;
+  now += tv.tv_nsec;
+
+  if (!initial)
+    initial = now;
+
+  log_debug ("[%6llu] %s", (now - initial)/1000, string);
+#else
+  /* You need to link with -ltr to enable the above code.  */
+  log_debug ("[not enabled in the source] %s", string);
+#endif
+}
+
+
 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
 void
 bug_at( const char *file, int line, const char *func )
 {
-  do_log (JNLIB_LOG_BUG, ("... this is a bug (%s:%d:%s)\n"), file, line, func);
+  log_log (JNLIB_LOG_BUG, ("... this is a bug (%s:%d:%s)\n"), file, line, func);
   abort (); /* Never called; just to make the compiler happy.  */
 }
 #else
 void
 bug_at( const char *file, int line )
 {
-  do_log (JNLIB_LOG_BUG, _("you found a bug ... (%s:%d)\n"), file, line);
+  log_log (JNLIB_LOG_BUG, _("you found a bug ... (%s:%d)\n"), file, line);
   abort (); /* Never called; just to make the compiler happy.  */
 }
 #endif
-