common: Change license of mbox-util to LGPLv2.1+.
[gnupg.git] / common / logging.c
1 /* logging.c - Useful logging functions
2  * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
3  *               2009, 2010 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify it
8  * under the terms of either
9  *
10  *   - the GNU Lesser General Public License as published by the Free
11  *     Software Foundation; either version 3 of the License, or (at
12  *     your option) any later version.
13  *
14  * or
15  *
16  *   - the GNU General Public License as published by the Free
17  *     Software Foundation; either version 2 of the License, or (at
18  *     your option) any later version.
19  *
20  * or both in parallel, as here.
21  *
22  * GnuPG is distributed in the hope that it will be useful, but
23  * WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * General Public License for more details.
26  *
27  * You should have received a copies of the GNU General Public License
28  * and the GNU Lesser General Public License along with this program;
29  * if not, see <http://www.gnu.org/licenses/>.
30  */
31
32
33 #include <config.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <stdarg.h>
38 #include <stddef.h>
39 #include <errno.h>
40 #include <time.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #ifdef HAVE_W32_SYSTEM
44 # ifdef HAVE_WINSOCK2_H
45 #  include <winsock2.h>
46 # endif
47 # include <windows.h>
48 #else /*!HAVE_W32_SYSTEM*/
49 # include <sys/socket.h>
50 # include <sys/un.h>
51 # include <netinet/in.h>
52 # include <arpa/inet.h>
53 #endif /*!HAVE_W32_SYSTEM*/
54 #include <unistd.h>
55 #include <fcntl.h>
56 #include <assert.h>
57 /* #include <execinfo.h> */
58
59 #define GNUPG_COMMON_NEED_AFLOCAL 1
60 #include "util.h"
61 #include "i18n.h"
62 #include "common-defs.h"
63 #include "logging.h"
64
65 #ifdef HAVE_W32_SYSTEM
66 # define S_IRGRP S_IRUSR
67 # define S_IROTH S_IRUSR
68 # define S_IWGRP S_IWUSR
69 # define S_IWOTH S_IWUSR
70 #endif
71
72
73 #ifdef HAVE_W32CE_SYSTEM
74 # define isatty(a)  (0)
75 #endif
76
77 #undef WITH_IPV6
78 #if defined (AF_INET6) && defined(PF_INET) \
79     && defined (INET6_ADDRSTRLEN) && defined(HAVE_INET_PTON)
80 # define WITH_IPV6 1
81 #endif
82
83 #ifndef EAFNOSUPPORT
84 # define EAFNOSUPPORT EINVAL
85 #endif
86 #ifndef INADDR_NONE  /* Slowaris is missing that.  */
87 #define INADDR_NONE  ((unsigned long)(-1))
88 #endif /*INADDR_NONE*/
89
90 #ifdef HAVE_W32_SYSTEM
91 #define sock_close(a)  closesocket(a)
92 #else
93 #define sock_close(a)  close(a)
94 #endif
95
96
97 static estream_t logstream;
98 static int log_socket = -1;
99 static char prefix_buffer[80];
100 static int with_time;
101 static int with_prefix;
102 static int with_pid;
103 #ifdef HAVE_W32_SYSTEM
104 static int no_registry;
105 #endif
106 static int (*get_pid_suffix_cb)(unsigned long *r_value);
107 static int running_detached;
108 static int force_prefixes;
109
110 static int missing_lf;
111 static int errorcount;
112
113
114 int
115 log_get_errorcount (int clear)
116 {
117     int n = errorcount;
118     if( clear )
119         errorcount = 0;
120     return n;
121 }
122
123 void
124 log_inc_errorcount (void)
125 {
126    errorcount++;
127 }
128
129
130 /* The following 3 functions are used by es_fopencookie to write logs
131    to a socket.  */
132 struct fun_cookie_s
133 {
134   int fd;
135   int quiet;
136   int want_socket;
137   int is_socket;
138 #ifdef HAVE_W32CE_SYSTEM
139   int use_writefile;
140 #endif
141   char name[1];
142 };
143
144
145 /* Write NBYTES of BUFFER to file descriptor FD. */
146 static int
147 writen (int fd, const void *buffer, size_t nbytes, int is_socket)
148 {
149   const char *buf = buffer;
150   size_t nleft = nbytes;
151   int nwritten;
152 #ifndef HAVE_W32_SYSTEM
153   (void)is_socket; /* Not required.  */
154 #endif
155
156   while (nleft > 0)
157     {
158 #ifdef HAVE_W32_SYSTEM
159       if (is_socket)
160         nwritten = send (fd, buf, nleft, 0);
161       else
162 #endif
163         nwritten = write (fd, buf, nleft);
164
165       if (nwritten < 0 && errno == EINTR)
166         continue;
167       if (nwritten < 0)
168         return -1;
169       nleft -= nwritten;
170       buf = buf + nwritten;
171     }
172
173   return 0;
174 }
175
176
177 /* Returns true if STR represents a valid port number in decimal
178    notation and no garbage is following.  */
179 static int
180 parse_portno (const char *str, unsigned short *r_port)
181 {
182   unsigned int value;
183
184   for (value=0; *str && (*str >= '0' && *str <= '9'); str++)
185     {
186       value = value * 10 + (*str - '0');
187       if (value > 65535)
188         return 0;
189     }
190   if (*str || !value)
191     return 0;
192
193   *r_port = value;
194   return 1;
195 }
196
197
198 static gpgrt_ssize_t
199 fun_writer (void *cookie_arg, const void *buffer, size_t size)
200 {
201   struct fun_cookie_s *cookie = cookie_arg;
202
203   /* FIXME: Use only estream with a callback for socket writing.  This
204      avoids the ugly mix of fd and estream code.  */
205
206   /* Note that we always try to reconnect to the socket but print
207      error messages only the first time an error occurred.  If
208      RUNNING_DETACHED is set we don't fall back to stderr and even do
209      not print any error messages.  This is needed because detached
210      processes often close stderr and by writing to file descriptor 2
211      we might send the log message to a file not intended for logging
212      (e.g. a pipe or network connection). */
213   if (cookie->want_socket && cookie->fd == -1)
214     {
215 #ifdef WITH_IPV6
216       struct sockaddr_in6 srvr_addr_in6;
217 #endif
218       struct sockaddr_in srvr_addr_in;
219 #ifndef HAVE_W32_SYSTEM
220       struct sockaddr_un srvr_addr_un;
221 #endif
222       size_t addrlen;
223       struct sockaddr *srvr_addr = NULL;
224       unsigned short port = 0;
225       int af = AF_LOCAL;
226       int pf = PF_LOCAL;
227       const char *name = cookie->name;
228
229       /* Not yet open or meanwhile closed due to an error. */
230       cookie->is_socket = 0;
231
232       /* Check whether this is a TCP socket or a local socket.  */
233       if (!strncmp (name, "tcp://", 6) && name[6])
234         {
235           name += 6;
236           af = AF_INET;
237           pf = PF_INET;
238         }
239 #ifndef HAVE_W32_SYSTEM
240       else if (!strncmp (name, "socket://", 9) && name[9])
241         name += 9;
242 #endif
243
244       if (af == AF_LOCAL)
245         {
246 #ifdef HAVE_W32_SYSTEM
247           addrlen = 0;
248 #else
249           memset (&srvr_addr, 0, sizeof srvr_addr);
250           srvr_addr_un.sun_family = af;
251           strncpy (srvr_addr_un.sun_path,
252                    name, sizeof (srvr_addr_un.sun_path)-1);
253           srvr_addr_un.sun_path[sizeof (srvr_addr_un.sun_path)-1] = 0;
254           srvr_addr = (struct sockaddr *)&srvr_addr_un;
255           addrlen = SUN_LEN (&srvr_addr_un);
256 #endif
257         }
258       else
259         {
260           char *addrstr, *p;
261 #ifdef HAVE_INET_PTON
262           void *addrbuf = NULL;
263 #endif /*HAVE_INET_PTON*/
264
265           addrstr = xtrymalloc (strlen (name) + 1);
266           if (!addrstr)
267             addrlen = 0; /* This indicates an error.  */
268           else if (*name == '[')
269             {
270               /* Check for IPv6 literal address.  */
271               strcpy (addrstr, name+1);
272               p = strchr (addrstr, ']');
273               if (!p || p[1] != ':' || !parse_portno (p+2, &port))
274                 {
275                   gpg_err_set_errno (EINVAL);
276                   addrlen = 0;
277                 }
278               else
279                 {
280                   *p = 0;
281 #ifdef WITH_IPV6
282                   af = AF_INET6;
283                   pf = PF_INET6;
284                   memset (&srvr_addr_in6, 0, sizeof srvr_addr_in6);
285                   srvr_addr_in6.sin6_family = af;
286                   srvr_addr_in6.sin6_port = htons (port);
287 #ifdef HAVE_INET_PTON
288                   addrbuf = &srvr_addr_in6.sin6_addr;
289 #endif /*HAVE_INET_PTON*/
290                   srvr_addr = (struct sockaddr *)&srvr_addr_in6;
291                   addrlen = sizeof srvr_addr_in6;
292 #else
293                   gpg_err_set_errno (EAFNOSUPPORT);
294                   addrlen = 0;
295 #endif
296                 }
297             }
298           else
299             {
300               /* Check for IPv4 literal address.  */
301               strcpy (addrstr, name);
302               p = strchr (addrstr, ':');
303               if (!p || !parse_portno (p+1, &port))
304                 {
305                   gpg_err_set_errno (EINVAL);
306                   addrlen = 0;
307                 }
308               else
309                 {
310                   *p = 0;
311                   memset (&srvr_addr_in, 0, sizeof srvr_addr_in);
312                   srvr_addr_in.sin_family = af;
313                   srvr_addr_in.sin_port = htons (port);
314 #ifdef HAVE_INET_PTON
315                   addrbuf = &srvr_addr_in.sin_addr;
316 #endif /*HAVE_INET_PTON*/
317                   srvr_addr = (struct sockaddr *)&srvr_addr_in;
318                   addrlen = sizeof srvr_addr_in;
319                 }
320             }
321
322           if (addrlen)
323             {
324 #ifdef HAVE_INET_PTON
325               if (inet_pton (af, addrstr, addrbuf) != 1)
326                 addrlen = 0;
327 #else /*!HAVE_INET_PTON*/
328               /* We need to use the old function.  If we are here v6
329                  support isn't enabled anyway and thus we can do fine
330                  without.  Note that Windows has a compatible inet_pton
331                  function named inetPton, but only since Vista.  */
332               srvr_addr_in.sin_addr.s_addr = inet_addr (addrstr);
333               if (srvr_addr_in.sin_addr.s_addr == INADDR_NONE)
334                 addrlen = 0;
335 #endif /*!HAVE_INET_PTON*/
336             }
337
338           xfree (addrstr);
339         }
340
341       cookie->fd = addrlen? socket (pf, SOCK_STREAM, 0) : -1;
342       if (cookie->fd == -1)
343         {
344           if (!cookie->quiet && !running_detached
345               && isatty (es_fileno (es_stderr)))
346             es_fprintf (es_stderr, "failed to create socket for logging: %s\n",
347                         strerror(errno));
348         }
349       else
350         {
351           if (connect (cookie->fd, srvr_addr, addrlen) == -1)
352             {
353               if (!cookie->quiet && !running_detached
354                   && isatty (es_fileno (es_stderr)))
355                 es_fprintf (es_stderr, "can't connect to '%s': %s\n",
356                             cookie->name, strerror(errno));
357               sock_close (cookie->fd);
358               cookie->fd = -1;
359             }
360         }
361
362       if (cookie->fd == -1)
363         {
364           if (!running_detached)
365             {
366               /* Due to all the problems with apps not running
367                  detached but being called with stderr closed or used
368                  for a different purposes, it does not make sense to
369                  switch to stderr.  We therefore disable it. */
370               if (!cookie->quiet)
371                 {
372                   /* fputs ("switching logging to stderr\n", stderr);*/
373                   cookie->quiet = 1;
374                 }
375               cookie->fd = -1; /*fileno (stderr);*/
376             }
377         }
378       else /* Connection has been established. */
379         {
380           cookie->quiet = 0;
381           cookie->is_socket = 1;
382         }
383     }
384
385   log_socket = cookie->fd;
386   if (cookie->fd != -1)
387     {
388 #ifdef HAVE_W32CE_SYSTEM
389       if (cookie->use_writefile)
390         {
391           DWORD nwritten;
392
393           WriteFile ((HANDLE)cookie->fd, buffer, size, &nwritten, NULL);
394           return (gpgrt_ssize_t)size; /* Okay.  */
395         }
396 #endif
397       if (!writen (cookie->fd, buffer, size, cookie->is_socket))
398         return (gpgrt_ssize_t)size; /* Okay. */
399     }
400
401   if (!running_detached && cookie->fd != -1
402       && isatty (es_fileno (es_stderr)))
403     {
404       if (*cookie->name)
405         es_fprintf (es_stderr, "error writing to '%s': %s\n",
406                     cookie->name, strerror(errno));
407       else
408         es_fprintf (es_stderr, "error writing to file descriptor %d: %s\n",
409                     cookie->fd, strerror(errno));
410     }
411   if (cookie->is_socket && cookie->fd != -1)
412     {
413       sock_close (cookie->fd);
414       cookie->fd = -1;
415       log_socket = -1;
416     }
417
418   return (gpgrt_ssize_t)size;
419 }
420
421
422 static int
423 fun_closer (void *cookie_arg)
424 {
425   struct fun_cookie_s *cookie = cookie_arg;
426
427   if (cookie->fd != -1 && cookie->fd != 2)
428     sock_close (cookie->fd);
429   xfree (cookie);
430   log_socket = -1;
431   return 0;
432 }
433
434
435 /* Common function to either set the logging to a file or a file
436    descriptor. */
437 static void
438 set_file_fd (const char *name, int fd)
439 {
440   estream_t fp;
441   int want_socket;
442 #ifdef HAVE_W32CE_SYSTEM
443   int use_writefile = 0;
444 #endif
445   struct fun_cookie_s *cookie;
446
447   /* Close an open log stream.  */
448   if (logstream)
449     {
450       es_fclose (logstream);
451       logstream = NULL;
452     }
453
454   /* Figure out what kind of logging we want.  */
455   if (name && !strcmp (name, "-"))
456     {
457       name = NULL;
458       fd = es_fileno (es_stderr);
459     }
460
461   want_socket = 0;
462   if (name && !strncmp (name, "tcp://", 6) && name[6])
463     want_socket = 1;
464 #ifndef HAVE_W32_SYSTEM
465   else if (name && !strncmp (name, "socket://", 9) && name[9])
466     want_socket = 2;
467 #endif /*HAVE_W32_SYSTEM*/
468 #ifdef HAVE_W32CE_SYSTEM
469   else if (name && !strcmp (name, "GPG2:"))
470     {
471       HANDLE hd;
472
473       ActivateDevice (L"Drivers\\"GNUPG_NAME"_Log", 0);
474       /* Ignore a filename and write the debug output to the GPG2:
475          device.  */
476       hd = CreateFile (L"GPG2:", GENERIC_WRITE,
477                        FILE_SHARE_READ | FILE_SHARE_WRITE,
478                        NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
479       fd = (hd == INVALID_HANDLE_VALUE)? -1 : (int)hd;
480       name = NULL;
481       force_prefixes = 1;
482       use_writefile = 1;
483     }
484 #endif /*HAVE_W32CE_SYSTEM*/
485
486   /* Setup a new stream.  */
487
488   /* The xmalloc below is justified because we can expect that this
489      function is called only during initialization and there is no
490      easy way out of this error condition.  */
491   cookie = xmalloc (sizeof *cookie + (name? strlen (name):0));
492   strcpy (cookie->name, name? name:"");
493   cookie->quiet = 0;
494   cookie->is_socket = 0;
495   cookie->want_socket = want_socket;
496 #ifdef HAVE_W32CE_SYSTEM
497   cookie->use_writefile = use_writefile;
498 #endif
499   if (!name)
500     cookie->fd = fd;
501   else if (want_socket)
502     cookie->fd = -1;
503   else
504     {
505       do
506         cookie->fd = open (name, O_WRONLY|O_APPEND|O_CREAT,
507                            (S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH));
508       while (cookie->fd == -1 && errno == EINTR);
509     }
510   log_socket = cookie->fd;
511
512   {
513     es_cookie_io_functions_t io = { NULL };
514     io.func_write = fun_writer;
515     io.func_close = fun_closer;
516
517     fp = es_fopencookie (cookie, "w", io);
518   }
519
520   /* On error default to a stderr based estream.  */
521   if (!fp)
522     fp = es_stderr;
523
524   es_setvbuf (fp, NULL, _IOLBF, 0);
525
526   logstream = fp;
527
528   /* We always need to print the prefix and the pid for socket mode,
529      so that the server reading the socket can do something
530      meaningful. */
531   force_prefixes = want_socket;
532
533   missing_lf = 0;
534 }
535
536
537 /* Set the file to write log to.  The special names NULL and "-" may
538    be used to select stderr and names formatted like
539    "socket:///home/foo/mylogs" may be used to write the logging to the
540    socket "/home/foo/mylogs".  If the connection to the socket fails
541    or a write error is detected, the function writes to stderr and
542    tries the next time again to connect the socket.
543   */
544 void
545 log_set_file (const char *name)
546 {
547   set_file_fd (name? name: "-", -1);
548 }
549
550 void
551 log_set_fd (int fd)
552 {
553   set_file_fd (NULL, fd);
554 }
555
556
557 void
558 log_set_pid_suffix_cb (int (*cb)(unsigned long *r_value))
559 {
560   get_pid_suffix_cb = cb;
561 }
562
563
564 void
565 log_set_prefix (const char *text, unsigned int flags)
566 {
567   if (text)
568     {
569       strncpy (prefix_buffer, text, sizeof (prefix_buffer)-1);
570       prefix_buffer[sizeof (prefix_buffer)-1] = 0;
571     }
572
573   with_prefix = (flags & GPGRT_LOG_WITH_PREFIX);
574   with_time = (flags & GPGRT_LOG_WITH_TIME);
575   with_pid  = (flags & GPGRT_LOG_WITH_PID);
576   running_detached = (flags & GPGRT_LOG_RUN_DETACHED);
577 #ifdef HAVE_W32_SYSTEM
578   no_registry = (flags & GPGRT_LOG_NO_REGISTRY);
579 #endif
580 }
581
582
583 const char *
584 log_get_prefix (unsigned int *flags)
585 {
586   if (flags)
587     {
588       *flags = 0;
589       if (with_prefix)
590         *flags |= GPGRT_LOG_WITH_PREFIX;
591       if (with_time)
592         *flags |= GPGRT_LOG_WITH_TIME;
593       if (with_pid)
594         *flags |= GPGRT_LOG_WITH_PID;
595       if (running_detached)
596         *flags |= GPGRT_LOG_RUN_DETACHED;
597 #ifdef HAVE_W32_SYSTEM
598       if (no_registry)
599         *flags |= GPGRT_LOG_NO_REGISTRY;
600 #endif
601     }
602   return prefix_buffer;
603 }
604
605 /* This function returns true if the file descriptor FD is in use for
606    logging.  This is preferable over a test using log_get_fd in that
607    it allows the logging code to use more then one file descriptor.  */
608 int
609 log_test_fd (int fd)
610 {
611   if (logstream)
612     {
613       int tmp = es_fileno (logstream);
614       if ( tmp != -1 && tmp == fd)
615         return 1;
616     }
617   if (log_socket != -1 && log_socket == fd)
618     return 1;
619   return 0;
620 }
621
622 int
623 log_get_fd ()
624 {
625   return logstream? es_fileno(logstream) : -1;
626 }
627
628 estream_t
629 log_get_stream ()
630 {
631   if (!logstream)
632     {
633       log_set_file (NULL); /* Make sure a log stream has been set.  */
634       assert (logstream);
635     }
636   return logstream;
637 }
638
639 static void
640 do_logv (int level, int ignore_arg_ptr, const char *fmt, va_list arg_ptr)
641 {
642   if (!logstream)
643     {
644 #ifdef HAVE_W32_SYSTEM
645       char *tmp;
646
647       tmp = (no_registry
648              ? NULL
649              : read_w32_registry_string (NULL, GNUPG_REGISTRY_DIR,
650                                          "DefaultLogFile"));
651       log_set_file (tmp && *tmp? tmp : NULL);
652       xfree (tmp);
653 #else
654       log_set_file (NULL); /* Make sure a log stream has been set.  */
655 #endif
656       assert (logstream);
657     }
658
659   es_flockfile (logstream);
660   if (missing_lf && level != GPGRT_LOG_CONT)
661     es_putc_unlocked ('\n', logstream );
662   missing_lf = 0;
663
664   if (level != GPGRT_LOG_CONT)
665     { /* Note this does not work for multiple line logging as we would
666        * need to print to a buffer first */
667       if (with_time && !force_prefixes)
668         {
669           struct tm *tp;
670           time_t atime = time (NULL);
671
672           tp = localtime (&atime);
673           es_fprintf_unlocked (logstream, "%04d-%02d-%02d %02d:%02d:%02d ",
674                                1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
675                                tp->tm_hour, tp->tm_min, tp->tm_sec );
676         }
677       if (with_prefix || force_prefixes)
678         es_fputs_unlocked (prefix_buffer, logstream);
679       if (with_pid || force_prefixes)
680         {
681           unsigned long pidsuf;
682           int pidfmt;
683
684           if (get_pid_suffix_cb && (pidfmt=get_pid_suffix_cb (&pidsuf)))
685             es_fprintf_unlocked (logstream, pidfmt == 1? "[%u.%lu]":"[%u.%lx]",
686                                  (unsigned int)getpid (), pidsuf);
687           else
688             es_fprintf_unlocked (logstream, "[%u]", (unsigned int)getpid ());
689         }
690       if ((!with_time && (with_prefix || with_pid)) || force_prefixes)
691         es_putc_unlocked (':', logstream);
692       /* A leading backspace suppresses the extra space so that we can
693          correctly output, programname, filename and linenumber. */
694       if (fmt && *fmt == '\b')
695         fmt++;
696       else
697         if (with_time || with_prefix || with_pid || force_prefixes)
698           es_putc_unlocked (' ', logstream);
699     }
700
701   switch (level)
702     {
703     case GPGRT_LOG_BEGIN: break;
704     case GPGRT_LOG_CONT: break;
705     case GPGRT_LOG_INFO: break;
706     case GPGRT_LOG_WARN: break;
707     case GPGRT_LOG_ERROR: break;
708     case GPGRT_LOG_FATAL: es_fputs_unlocked ("Fatal: ",logstream ); break;
709     case GPGRT_LOG_BUG:   es_fputs_unlocked ("Ohhhh jeeee: ", logstream); break;
710     case GPGRT_LOG_DEBUG: es_fputs_unlocked ("DBG: ", logstream ); break;
711     default:
712       es_fprintf_unlocked (logstream,"[Unknown log level %d]: ", level);
713       break;
714     }
715
716   if (fmt)
717     {
718       if (ignore_arg_ptr)
719         { /* This is used by log_string and comes with the extra
720            * feature that after a LF the next line is indent at the
721            * length of the prefix.  Note that we do not yet include
722            * the length of the timestamp and pid in the indent
723            * computation.  */
724           const char *p, *pend;
725
726           for (p = fmt; (pend = strchr (p, '\n')); p = pend+1)
727             es_fprintf_unlocked (logstream, "%*s%.*s",
728                                  (int)((p != fmt
729                                         && (with_prefix || force_prefixes))
730                                        ?strlen (prefix_buffer)+2:0), "",
731                                  (int)(pend - p)+1, p);
732           es_fputs_unlocked (p, logstream);
733         }
734       else
735         es_vfprintf_unlocked (logstream, fmt, arg_ptr);
736       if (*fmt && fmt[strlen(fmt)-1] != '\n')
737         missing_lf = 1;
738     }
739
740   if (level == GPGRT_LOG_FATAL)
741     {
742       if (missing_lf)
743         es_putc_unlocked ('\n', logstream);
744       es_funlockfile (logstream);
745       exit (2);
746     }
747   else if (level == GPGRT_LOG_BUG)
748     {
749       if (missing_lf)
750         es_putc_unlocked ('\n', logstream );
751       es_funlockfile (logstream);
752       /* Using backtrace requires a configure test and to pass
753        * -rdynamic to gcc.  Thus we do not enable it now.  */
754       /* { */
755       /*   void *btbuf[20]; */
756       /*   int btidx, btlen; */
757       /*   char **btstr; */
758
759       /*   btlen = backtrace (btbuf, DIM (btbuf)); */
760       /*   btstr = backtrace_symbols (btbuf, btlen); */
761       /*   if (btstr) */
762       /*     for (btidx=0; btidx < btlen; btidx++) */
763       /*       log_debug ("[%d] %s\n", btidx, btstr[btidx]); */
764       /* } */
765       abort ();
766     }
767   else
768     es_funlockfile (logstream);
769 }
770
771
772 void
773 log_log (int level, const char *fmt, ...)
774 {
775   va_list arg_ptr ;
776
777   va_start (arg_ptr, fmt) ;
778   do_logv (level, 0, fmt, arg_ptr);
779   va_end (arg_ptr);
780 }
781
782
783 void
784 log_logv (int level, const char *fmt, va_list arg_ptr)
785 {
786   do_logv (level, 0, fmt, arg_ptr);
787 }
788
789
790 static void
791 do_log_ignore_arg (int level, const char *str, ...)
792 {
793   va_list arg_ptr;
794   va_start (arg_ptr, str);
795   do_logv (level, 1, str, arg_ptr);
796   va_end (arg_ptr);
797 }
798
799
800 /* Log STRING at LEVEL but indent from the second line on by the
801  * length of the prefix.  */
802 void
803 log_string (int level, const char *string)
804 {
805   /* We need a dummy arg_ptr, but there is no portable way to create
806    * one.  So we call the do_logv function through a variadic wrapper. */
807   do_log_ignore_arg (level, string);
808 }
809
810
811 void
812 log_info (const char *fmt, ...)
813 {
814   va_list arg_ptr ;
815
816   va_start (arg_ptr, fmt);
817   do_logv (GPGRT_LOG_INFO, 0, fmt, arg_ptr);
818   va_end (arg_ptr);
819 }
820
821
822 void
823 log_error (const char *fmt, ...)
824 {
825   va_list arg_ptr ;
826
827   va_start (arg_ptr, fmt);
828   do_logv (GPGRT_LOG_ERROR, 0, fmt, arg_ptr);
829   va_end (arg_ptr);
830   /* Protect against counter overflow.  */
831   if (errorcount < 30000)
832     errorcount++;
833 }
834
835
836 void
837 log_fatal (const char *fmt, ...)
838 {
839   va_list arg_ptr ;
840
841   va_start (arg_ptr, fmt);
842   do_logv (GPGRT_LOG_FATAL, 0, fmt, arg_ptr);
843   va_end (arg_ptr);
844   abort (); /* Never called; just to make the compiler happy.  */
845 }
846
847
848 void
849 log_bug (const char *fmt, ...)
850 {
851   va_list arg_ptr ;
852
853   va_start (arg_ptr, fmt);
854   do_logv (GPGRT_LOG_BUG, 0, fmt, arg_ptr);
855   va_end (arg_ptr);
856   abort (); /* Never called; just to make the compiler happy.  */
857 }
858
859
860 void
861 log_debug (const char *fmt, ...)
862 {
863   va_list arg_ptr ;
864
865   va_start (arg_ptr, fmt);
866   do_logv (GPGRT_LOG_DEBUG, 0, fmt, arg_ptr);
867   va_end (arg_ptr);
868 }
869
870
871 void
872 log_printf (const char *fmt, ...)
873 {
874   va_list arg_ptr;
875
876   va_start (arg_ptr, fmt);
877   do_logv (fmt ? GPGRT_LOG_CONT : GPGRT_LOG_BEGIN, 0, fmt, arg_ptr);
878   va_end (arg_ptr);
879 }
880
881
882 /* Flush the log - this is useful to make sure that the trailing
883    linefeed has been printed.  */
884 void
885 log_flush (void)
886 {
887   do_log_ignore_arg (GPGRT_LOG_CONT, NULL);
888 }
889
890
891 /* Print a hexdump of BUFFER.  With TEXT of NULL print just the raw
892    dump, with TEXT just an empty string, print a trailing linefeed,
893    otherwise print an entire debug line. */
894 void
895 log_printhex (const char *text, const void *buffer, size_t length)
896 {
897   if (text && *text)
898     log_debug ("%s ", text);
899   if (length)
900     {
901       const unsigned char *p = buffer;
902       log_printf ("%02X", *p);
903       for (length--, p++; length--; p++)
904         log_printf (" %02X", *p);
905     }
906   if (text)
907     log_printf ("\n");
908 }
909
910
911 /*
912 void
913 log_printcanon () {}
914 is found in sexputils.c
915 */
916
917 /*
918 void
919 log_printsexp () {}
920 is found in sexputils.c
921 */
922
923
924 void
925 log_clock (const char *string)
926 {
927 #if 0
928   static unsigned long long initial;
929   struct timespec tv;
930   unsigned long long now;
931
932   if (clock_gettime (CLOCK_REALTIME, &tv))
933     {
934       log_debug ("error getting the realtime clock value\n");
935       return;
936     }
937   now = tv.tv_sec * 1000000000ull;
938   now += tv.tv_nsec;
939
940   if (!initial)
941     initial = now;
942
943   log_debug ("[%6llu] %s", (now - initial)/1000, string);
944 #else
945   /* You need to link with -ltr to enable the above code.  */
946   log_debug ("[not enabled in the source] %s", string);
947 #endif
948 }
949
950
951 #ifdef GPGRT_HAVE_MACRO_FUNCTION
952 void
953 bug_at( const char *file, int line, const char *func )
954 {
955   log_log (GPGRT_LOG_BUG, "... this is a bug (%s:%d:%s)\n", file, line, func);
956   abort (); /* Never called; just to make the compiler happy.  */
957 }
958 #else /*!GPGRT_HAVE_MACRO_FUNCTION*/
959 void
960 bug_at( const char *file, int line )
961 {
962   log_log (GPGRT_LOG_BUG, "you found a bug ... (%s:%d)\n", file, line);
963   abort (); /* Never called; just to make the compiler happy.  */
964 }
965 #endif /*!GPGRT_HAVE_MACRO_FUNCTION*/
966
967
968 #ifdef GPGRT_HAVE_MACRO_FUNCTION
969 void
970 _log_assert (const char *expr, const char *file, int line, const char *func)
971 {
972   log_log (GPGRT_LOG_BUG, "Assertion \"%s\" in %s failed (%s:%d)\n",
973            expr, func, file, line);
974   abort (); /* Never called; just to make the compiler happy.  */
975 }
976 #else /*!GPGRT_HAVE_MACRO_FUNCTION*/
977 void
978 _log_assert (const char *expr, const char *file, int line)
979 {
980   log_log (GPGRT_LOG_BUG, "Assertion \"%s\" failed (%s:%d)\n",
981            file, line, func);
982   abort (); /* Never called; just to make the compiler happy.  */
983 }
984 #endif /*!GPGRT_HAVE_MACRO_FUNCTION*/