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