common,w32: Silence an unused arg warning message.
[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
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 || 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         es_putc_unlocked (' ', logstream);
698     }
699
700   switch (level)
701     {
702     case GPGRT_LOG_BEGIN: break;
703     case GPGRT_LOG_CONT: break;
704     case GPGRT_LOG_INFO: break;
705     case GPGRT_LOG_WARN: break;
706     case GPGRT_LOG_ERROR: break;
707     case GPGRT_LOG_FATAL: es_fputs_unlocked ("Fatal: ",logstream ); break;
708     case GPGRT_LOG_BUG:   es_fputs_unlocked ("Ohhhh jeeee: ", logstream); break;
709     case GPGRT_LOG_DEBUG: es_fputs_unlocked ("DBG: ", logstream ); break;
710     default:
711       es_fprintf_unlocked (logstream,"[Unknown log level %d]: ", level);
712       break;
713     }
714
715   if (fmt)
716     {
717       if (ignore_arg_ptr)
718         { /* This is used by log_string and comes with the extra
719            * feature that after a LF the next line is indent at the
720            * length of the prefix.  Note that we do not yet include
721            * the length of the timestamp and pid in the indent
722            * computation.  */
723           const char *p, *pend;
724
725           for (p = fmt; (pend = strchr (p, '\n')); p = pend+1)
726             es_fprintf_unlocked (logstream, "%*s%.*s",
727                                  (int)((p != fmt
728                                         && (with_prefix || force_prefixes))
729                                        ?strlen (prefix_buffer)+2:0), "",
730                                  (int)(pend - p)+1, p);
731           es_fputs_unlocked (p, logstream);
732         }
733       else
734         es_vfprintf_unlocked (logstream, fmt, arg_ptr);
735       if (*fmt && fmt[strlen(fmt)-1] != '\n')
736         missing_lf = 1;
737     }
738
739   if (level == GPGRT_LOG_FATAL)
740     {
741       if (missing_lf)
742         es_putc_unlocked ('\n', logstream);
743       es_funlockfile (logstream);
744       exit (2);
745     }
746   else if (level == GPGRT_LOG_BUG)
747     {
748       if (missing_lf)
749         es_putc_unlocked ('\n', logstream );
750       es_funlockfile (logstream);
751       abort ();
752     }
753   else
754     es_funlockfile (logstream);
755 }
756
757
758 void
759 log_log (int level, const char *fmt, ...)
760 {
761   va_list arg_ptr ;
762
763   va_start (arg_ptr, fmt) ;
764   do_logv (level, 0, fmt, arg_ptr);
765   va_end (arg_ptr);
766 }
767
768
769 void
770 log_logv (int level, const char *fmt, va_list arg_ptr)
771 {
772   do_logv (level, 0, fmt, arg_ptr);
773 }
774
775
776 static void
777 do_log_ignore_arg (int level, const char *str, ...)
778 {
779   va_list arg_ptr;
780   va_start (arg_ptr, str);
781   do_logv (level, 1, str, arg_ptr);
782   va_end (arg_ptr);
783 }
784
785
786 /* Log STRING at LEVEL but indent from the second line on by the
787  * length of the prefix.  */
788 void
789 log_string (int level, const char *string)
790 {
791   /* We need a dummy arg_ptr, but there is no portable way to create
792    * one.  So we call the do_logv function through a variadic wrapper. */
793   do_log_ignore_arg (level, string);
794 }
795
796
797 void
798 log_info (const char *fmt, ...)
799 {
800   va_list arg_ptr ;
801
802   va_start (arg_ptr, fmt);
803   do_logv (GPGRT_LOG_INFO, 0, fmt, arg_ptr);
804   va_end (arg_ptr);
805 }
806
807
808 void
809 log_error (const char *fmt, ...)
810 {
811   va_list arg_ptr ;
812
813   va_start (arg_ptr, fmt);
814   do_logv (GPGRT_LOG_ERROR, 0, fmt, arg_ptr);
815   va_end (arg_ptr);
816   /* Protect against counter overflow.  */
817   if (errorcount < 30000)
818     errorcount++;
819 }
820
821
822 void
823 log_fatal (const char *fmt, ...)
824 {
825   va_list arg_ptr ;
826
827   va_start (arg_ptr, fmt);
828   do_logv (GPGRT_LOG_FATAL, 0, fmt, arg_ptr);
829   va_end (arg_ptr);
830   abort (); /* Never called; just to make the compiler happy.  */
831 }
832
833
834 void
835 log_bug (const char *fmt, ...)
836 {
837   va_list arg_ptr ;
838
839   va_start (arg_ptr, fmt);
840   do_logv (GPGRT_LOG_BUG, 0, fmt, arg_ptr);
841   va_end (arg_ptr);
842   abort (); /* Never called; just to make the compiler happy.  */
843 }
844
845
846 void
847 log_debug (const char *fmt, ...)
848 {
849   va_list arg_ptr ;
850
851   va_start (arg_ptr, fmt);
852   do_logv (GPGRT_LOG_DEBUG, 0, fmt, arg_ptr);
853   va_end (arg_ptr);
854 }
855
856
857 void
858 log_printf (const char *fmt, ...)
859 {
860   va_list arg_ptr;
861
862   va_start (arg_ptr, fmt);
863   do_logv (fmt ? GPGRT_LOG_CONT : GPGRT_LOG_BEGIN, 0, fmt, arg_ptr);
864   va_end (arg_ptr);
865 }
866
867
868 /* Flush the log - this is useful to make sure that the trailing
869    linefeed has been printed.  */
870 void
871 log_flush (void)
872 {
873   do_log_ignore_arg (GPGRT_LOG_CONT, NULL);
874 }
875
876
877 /* Print a hexdump of BUFFER.  With TEXT of NULL print just the raw
878    dump, with TEXT just an empty string, print a trailing linefeed,
879    otherwise print an entire debug line. */
880 void
881 log_printhex (const char *text, const void *buffer, size_t length)
882 {
883   if (text && *text)
884     log_debug ("%s ", text);
885   if (length)
886     {
887       const unsigned char *p = buffer;
888       log_printf ("%02X", *p);
889       for (length--, p++; length--; p++)
890         log_printf (" %02X", *p);
891     }
892   if (text)
893     log_printf ("\n");
894 }
895
896
897 /*
898 void
899 log_printcanon () {}
900 is found in sexputils.c
901 */
902
903 /*
904 void
905 log_printsexp () {}
906 is found in sexputils.c
907 */
908
909
910 void
911 log_clock (const char *string)
912 {
913 #if 0
914   static unsigned long long initial;
915   struct timespec tv;
916   unsigned long long now;
917
918   if (clock_gettime (CLOCK_REALTIME, &tv))
919     {
920       log_debug ("error getting the realtime clock value\n");
921       return;
922     }
923   now = tv.tv_sec * 1000000000ull;
924   now += tv.tv_nsec;
925
926   if (!initial)
927     initial = now;
928
929   log_debug ("[%6llu] %s", (now - initial)/1000, string);
930 #else
931   /* You need to link with -ltr to enable the above code.  */
932   log_debug ("[not enabled in the source] %s", string);
933 #endif
934 }
935
936
937 #ifdef GPGRT_HAVE_MACRO_FUNCTION
938 void
939 bug_at( const char *file, int line, const char *func )
940 {
941   log_log (GPGRT_LOG_BUG, "... this is a bug (%s:%d:%s)\n", file, line, func);
942   abort (); /* Never called; just to make the compiler happy.  */
943 }
944 #else /*!GPGRT_HAVE_MACRO_FUNCTION*/
945 void
946 bug_at( const char *file, int line )
947 {
948   log_log (GPGRT_LOG_BUG, "you found a bug ... (%s:%d)\n", file, line);
949   abort (); /* Never called; just to make the compiler happy.  */
950 }
951 #endif /*!GPGRT_HAVE_MACRO_FUNCTION*/
952
953
954 #ifdef GPGRT_HAVE_MACRO_FUNCTION
955 void
956 _log_assert (const char *expr, const char *file, int line, const char *func)
957 {
958   log_log (GPGRT_LOG_BUG, "Assertion \"%s\" in %s failed (%s:%d)\n",
959            expr, func, file, line);
960   abort (); /* Never called; just to make the compiler happy.  */
961 }
962 #else /*!GPGRT_HAVE_MACRO_FUNCTION*/
963 void
964 _log_assert (const char *expr, const char *file, int line)
965 {
966   log_log (GPGRT_LOG_BUG, "Assertion \"%s\" failed (%s:%d)\n",
967            file, line, func);
968   abort (); /* Never called; just to make the compiler happy.  */
969 }
970 #endif /*!GPGRT_HAVE_MACRO_FUNCTION*/