LCOV - code coverage report
Current view: top level - src - debug.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 53 131 40.5 %
Date: 2018-11-14 16:53:58 Functions: 9 11 81.8 %

          Line data    Source code
       1             : /* debug.c - helpful output in desperate situations
       2             :    Copyright (C) 2000 Werner Koch (dd9jn)
       3             :    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2009 g10 Code GmbH
       4             : 
       5             :    This file is part of GPGME.
       6             : 
       7             :    GPGME is free software; you can redistribute it and/or modify it
       8             :    under the terms of the GNU Lesser General Public License as
       9             :    published by the Free Software Foundation; either version 2.1 of
      10             :    the License, or (at your option) any later version.
      11             : 
      12             :    GPGME is distributed in the hope that it will be useful, but
      13             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :    Lesser General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU Lesser General Public
      18             :    License along with this program; if not, write to the Free Software
      19             :    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
      20             :    MA 02110-1301, USA.  */
      21             : 
      22             : #if HAVE_CONFIG_H
      23             : #include <config.h>
      24             : #endif
      25             : #include <stdio.h>
      26             : #include <stdlib.h>
      27             : #include <string.h>
      28             : #include <stdarg.h>
      29             : #ifdef HAVE_UNISTD_H
      30             : # include <unistd.h>
      31             : #endif
      32             : #include <ctype.h>
      33             : #include <errno.h>
      34             : #include <time.h>
      35             : #ifndef HAVE_DOSISH_SYSTEM
      36             : # ifdef HAVE_SYS_TYPES_H
      37             : #  include <sys/types.h>
      38             : # endif
      39             : # ifdef HAVE_SYS_STAT_H
      40             : #  include <sys/stat.h>
      41             : # endif
      42             : # include <fcntl.h>
      43             : #endif
      44             : #include <assert.h>
      45             : 
      46             : #include "util.h"
      47             : #include "ath.h"
      48             : #include "sema.h"
      49             : #include "sys-util.h"
      50             : #include "debug.h"
      51             : 
      52             : 
      53             : /* Lock to serialize initialization of the debug output subsystem and
      54             :    output of actual debug messages.  */
      55             : DEFINE_STATIC_LOCK (debug_lock);
      56             : 
      57             : /* The amount of detail requested by the user, per environment
      58             :    variable GPGME_DEBUG.  */
      59             : static int debug_level;
      60             : 
      61             : /* The output stream for the debug messages.  */
      62             : static FILE *errfp;
      63             : 
      64             : /* If not NULL, this malloced string is used instead of the
      65             :    GPGME_DEBUG envvar.  It must have been set before the debug
      66             :    subsystem has been initialized.  Using it later may or may not have
      67             :    any effect.  */
      68             : static char *envvar_override;
      69             : 
      70             : 
      71             : #ifdef HAVE_TLS
      72             : #define FRAME_NR
      73             : static __thread int frame_nr = 0;
      74             : #endif
      75             : 
      76             : void
      77      100328 : _gpgme_debug_frame_begin (void)
      78             : {
      79             : #ifdef FRAME_NR
      80      100328 :   frame_nr++;
      81             : #endif
      82      100328 : }
      83             : 
      84      100215 : int _gpgme_debug_frame_end (void)
      85             : {
      86             : #ifdef FRAME_NR
      87      100215 :   frame_nr--;
      88             : #endif
      89      100215 :   return 0;
      90             : }
      91             : 
      92             : 
      93             : 
      94             : /* Remove leading and trailing white spaces.  */
      95             : static char *
      96           0 : trim_spaces (char *str)
      97             : {
      98             :   char *string, *p, *mark;
      99             : 
     100           0 :   string = str;
     101             :   /* Find first non space character.  */
     102           0 :   for (p = string; *p && isspace (*(unsigned char *) p); p++)
     103             :     ;
     104             :   /* Move characters.  */
     105           0 :   for (mark = NULL; (*string = *p); string++, p++)
     106           0 :     if (isspace (*(unsigned char *) p))
     107             :       {
     108           0 :         if (!mark)
     109           0 :           mark = string;
     110             :       }
     111             :     else
     112           0 :       mark = NULL;
     113           0 :   if (mark)
     114           0 :     *mark = '\0';       /* Remove trailing spaces.  */
     115             : 
     116           0 :   return str;
     117             : }
     118             : 
     119             : 
     120             : /* This is an internal function to set debug info.  The caller must
     121             :    assure that this function is called only by one thread at a time.
     122             :    The function may have no effect if called after the debug system
     123             :    has been initialized.  Returns 0 on success.  */
     124             : int
     125           0 : _gpgme_debug_set_debug_envvar (const char *value)
     126             : {
     127           0 :   free (envvar_override);
     128           0 :   envvar_override = strdup (value);
     129           0 :   return !envvar_override;
     130             : }
     131             : 
     132             : 
     133             : static void
     134         100 : debug_init (void)
     135             : {
     136             :   static int initialized;
     137             : 
     138         100 :   LOCK (debug_lock);
     139         100 :   if (!initialized)
     140             :     {
     141             :       gpgme_error_t err;
     142             :       char *e;
     143             :       const char *s1, *s2;;
     144             : 
     145         100 :       if (envvar_override)
     146             :         {
     147           0 :           e = strdup (envvar_override);
     148           0 :           free (envvar_override);
     149           0 :           envvar_override = NULL;
     150             :         }
     151             :       else
     152             :         {
     153         100 :           err = _gpgme_getenv ("GPGME_DEBUG", &e);
     154         100 :           if (err)
     155             :             {
     156           0 :               UNLOCK (debug_lock);
     157           0 :               return;
     158             :             }
     159             :         }
     160             : 
     161         100 :       initialized = 1;
     162         100 :       errfp = stderr;
     163         100 :       if (e)
     164             :         {
     165           0 :           debug_level = atoi (e);
     166           0 :           s1 = strchr (e, PATHSEP_C);
     167           0 :           if (s1)
     168             :             {
     169             : #ifndef HAVE_DOSISH_SYSTEM
     170           0 :               if (getuid () == geteuid ()
     171             : #if defined(HAVE_GETGID) && defined(HAVE_GETEGID)
     172           0 :                   && getgid () == getegid ()
     173             : #endif
     174             :                   )
     175             :                 {
     176             : #endif
     177             :                   char *p;
     178             :                   FILE *fp;
     179             : 
     180           0 :                   s1++;
     181           0 :                   if (!(s2 = strchr (s1, PATHSEP_C)))
     182           0 :                     s2 = s1 + strlen (s1);
     183           0 :                   p = malloc (s2 - s1 + 1);
     184           0 :                   if (p)
     185             :                     {
     186           0 :                       memcpy (p, s1, s2 - s1);
     187           0 :                       p[s2-s1] = 0;
     188           0 :                       trim_spaces (p);
     189           0 :                       fp = fopen (p,"a");
     190           0 :                       if (fp)
     191             :                         {
     192           0 :                           setvbuf (fp, NULL, _IOLBF, 0);
     193           0 :                           errfp = fp;
     194             :                         }
     195           0 :                       free (p);
     196             :                     }
     197             : #ifndef HAVE_DOSISH_SYSTEM
     198             :                 }
     199             : #endif
     200             :             }
     201           0 :           free (e);
     202             :         }
     203             :     }
     204         100 :   UNLOCK (debug_lock);
     205             : 
     206         100 :   if (debug_level > 0)
     207             :     {
     208           0 :       _gpgme_debug (DEBUG_INIT, "gpgme_debug: level=%d\n", debug_level);
     209             : #ifdef HAVE_W32_SYSTEM
     210             :       {
     211             :         const char *name = _gpgme_get_inst_dir ();
     212             :         _gpgme_debug (DEBUG_INIT, "gpgme_debug: gpgme='%s'\n",
     213             :                       name? name: "?");
     214             :       }
     215             : #endif
     216             :     }
     217             : }
     218             : 
     219             : 
     220             : 
     221             : /* This should be called as soon as the locks are initialized.  It is
     222             :    required so that the assuan logging gets conncted to the gpgme log
     223             :    stream as early as possible.  */
     224             : void
     225         100 : _gpgme_debug_subsystem_init (void)
     226             : {
     227         100 :   debug_init ();
     228         100 : }
     229             : 
     230             : 
     231             : 
     232             : 
     233             : /* Log the formatted string FORMAT at debug level LEVEL or higher.
     234             :  *
     235             :  * Returns: 0
     236             :  *
     237             :  * Note that we always return 0 because the old TRACE macro evaluated
     238             :  * to 0 which issues a warning with newer gcc version about an unused
     239             :  * values.  By using a return value of this function this can be
     240             :  * avoided.  Fixme: It might be useful to check whether the return
     241             :  * value from the TRACE macros are actually used somewhere.
     242             :  */
     243             : int
     244      392880 : _gpgme_debug (int level, const char *format, ...)
     245             : {
     246             :   va_list arg_ptr;
     247             :   int saved_errno;
     248             : 
     249      392880 :   saved_errno = errno;
     250      392879 :   if (debug_level < level)
     251      392879 :     return 0;
     252             : 
     253           0 :   va_start (arg_ptr, format);
     254           0 :   LOCK (debug_lock);
     255             :   {
     256             :     struct tm *tp;
     257           0 :     time_t atime = time (NULL);
     258             : 
     259           0 :     tp = localtime (&atime);
     260           0 :     fprintf (errfp, "GPGME %04d-%02d-%02d %02d:%02d:%02d <0x%04llx>  ",
     261           0 :              1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
     262             :              tp->tm_hour, tp->tm_min, tp->tm_sec,
     263           0 :              (unsigned long long) ath_self ());
     264             :   }
     265             : #ifdef FRAME_NR
     266             :   {
     267             :     int indent;
     268             : 
     269           0 :     indent = frame_nr > 0? (2 * (frame_nr - 1)):0;
     270           0 :     fprintf (errfp, "%*s", indent < 40? indent : 40, "");
     271             :   }
     272             : #endif
     273             : 
     274           0 :   vfprintf (errfp, format, arg_ptr);
     275           0 :   va_end (arg_ptr);
     276           0 :   if(format && *format && format[strlen (format) - 1] != '\n')
     277           0 :     putc ('\n', errfp);
     278           0 :   UNLOCK (debug_lock);
     279           0 :   fflush (errfp);
     280             : 
     281           0 :   gpg_err_set_errno (saved_errno);
     282           0 :   return 0;
     283             : }
     284             : 
     285             : 
     286             : /* Start a new debug line in *LINE, logged at level LEVEL or higher,
     287             :    and starting with the formatted string FORMAT.  */
     288             : void
     289       33210 : _gpgme_debug_begin (void **line, int level, const char *format, ...)
     290             : {
     291             :   va_list arg_ptr;
     292             :   int res;
     293             : 
     294       33210 :   if (debug_level < level)
     295             :     {
     296             :       /* Disable logging of this line.  */
     297       33210 :       *line = NULL;
     298       33210 :       return;
     299             :     }
     300             : 
     301           0 :   va_start (arg_ptr, format);
     302           0 :   res = gpgrt_vasprintf ((char **) line, format, arg_ptr);
     303           0 :   va_end (arg_ptr);
     304           0 :   if (res < 0)
     305           0 :     *line = NULL;
     306             : }
     307             : 
     308             : 
     309             : /* Add the formatted string FORMAT to the debug line *LINE.  */
     310             : void
     311       46307 : _gpgme_debug_add (void **line, const char *format, ...)
     312             : {
     313             :   va_list arg_ptr;
     314             :   char *toadd;
     315             :   char *result;
     316             :   int res;
     317             : 
     318       46307 :   if (!*line)
     319       46307 :     return;
     320             : 
     321           0 :   va_start (arg_ptr, format);
     322           0 :   res = gpgrt_vasprintf (&toadd, format, arg_ptr);
     323           0 :   va_end (arg_ptr);
     324           0 :   if (res < 0)
     325             :     {
     326           0 :       gpgrt_free (*line);
     327           0 :       *line = NULL;
     328             :     }
     329           0 :   res = gpgrt_asprintf (&result, "%s%s", *(char **) line, toadd);
     330           0 :   gpgrt_free (toadd);
     331           0 :   gpgrt_free (*line);
     332           0 :   if (res < 0)
     333           0 :     *line = NULL;
     334             :   else
     335           0 :     *line = result;
     336             : }
     337             : 
     338             : 
     339             : /* Finish construction of *LINE and send it to the debug output
     340             :    stream.  */
     341             : void
     342       16762 : _gpgme_debug_end (void **line)
     343             : {
     344       16762 :   if (!*line)
     345       16762 :     return;
     346             : 
     347             :   /* The smallest possible level is 1, so force logging here by
     348             :      using that.  */
     349           0 :   _gpgme_debug (1, "%s", *line);
     350           0 :   gpgrt_free (*line);
     351           0 :   *line = NULL;
     352             : }
     353             : 
     354             : 
     355             : #define TOHEX(val) (((val) < 10) ? ((val) + '0') : ((val) - 10 + 'a'))
     356             : 
     357             : void
     358       11125 : _gpgme_debug_buffer (int lvl, const char *const fmt,
     359             :                      const char *const func, const char *const buffer,
     360             :                      size_t len)
     361             : {
     362       11125 :   int idx = 0;
     363             :   int j;
     364             : 
     365             :   if (!_gpgme_debug_trace ())
     366             :     return;
     367             : 
     368       11125 :   if (!buffer)
     369           0 :     return;
     370             : 
     371      186297 :   while (idx < len)
     372             :     {
     373             :       char str[51];
     374      164053 :       char *strp = str;
     375      164053 :       char *strp2 = &str[34];
     376             : 
     377     2737932 :       for (j = 0; j < 16; j++)
     378             :         {
     379             :           unsigned char val;
     380     2540221 :           if (idx < len)
     381             :             {
     382     2468934 :               val = buffer[idx++];
     383     2468934 :               *(strp++) = TOHEX (val >> 4);
     384     2468934 :               *(strp++) = TOHEX (val % 16);
     385     2468934 :               *(strp2++) = isprint (val) ? val : '.';
     386             :             }
     387             :           else
     388             :             {
     389       71287 :               *(strp++) = ' ';
     390       71287 :               *(strp++) = ' ';
     391             :             }
     392     2573879 :           if (j == 7)
     393      197698 :             *(strp++) = ' ';
     394             :         }
     395      197711 :       *(strp++) = ' ';
     396      197711 :       *(strp2) = '\0';
     397             : 
     398      197711 :       _gpgme_debug (lvl, fmt, func, str);
     399             :     }
     400             : }

Generated by: LCOV version 1.13