gpgme/gpgme/debug.c
2001-06-12 07:37:15 +00:00

241 lines
5.4 KiB
C

/* debug.c
* Copyright (C) 2001 g10 Code GmbH
*
* This file is part of GPGME.
*
* GPGME is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GPGME is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <ctype.h>
#ifndef HAVE_DOSISH_SYSTEM
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#endif
#include <assert.h>
#include "util.h"
#include "sema.h"
DEFINE_STATIC_LOCK (debug_lock);
struct debug_control_s {
FILE *fp;
char fname[100];
};
static int debug_level = 0;
static FILE *errfp = NULL;
/****************
* remove leading and trailing white spaces
*/
static char *
trim_spaces( char *str )
{
char *string, *p, *mark;
string = str;
/* find first non space character */
for( p=string; *p && isspace( *(byte*)p ) ; p++ )
;
/* move characters */
for( (mark = NULL); (*string = *p); string++, p++ )
if( isspace( *(byte*)p ) ) {
if( !mark )
mark = string ;
}
else
mark = NULL ;
if( mark )
*mark = '\0' ; /* remove trailing spaces */
return str ;
}
static void
debug_init (void)
{
static volatile int initialized = 0;
if (initialized)
return;
LOCK (debug_lock);
if (!initialized) {
const char *e = getenv ("GPGME_DEBUG");
const char *s1, *s2;;
initialized = 1;
debug_level = 0;
errfp = stderr;
if (e) {
debug_level = atoi (e);
s1 = strchr (e, ':');
if (s1
#ifndef HAVE_DOSISH_SYSTEM
&& getuid () == geteuid ()
#endif
) {
char *p;
FILE *fp;
s1++;
if ( !(s2 = strchr (s1, ':')) )
s2 = s1 + strlen(s1);
p = xtrymalloc (s2-s1+1);
if (p) {
memcpy (p, s1, s2-s1);
p[s2-s1] = 0;
trim_spaces (p);
fp = fopen (p,"a");
if (fp) {
setvbuf (fp, NULL, _IOLBF, 0);
errfp = fp;
}
xfree (p);
}
}
}
if (debug_level > 0)
fprintf (errfp,"gpgme_debug: level=%d\n", debug_level);
}
UNLOCK (debug_lock);
}
int
_gpgme_debug_level ()
{
return debug_level;
}
void
_gpgme_debug (int level, const char *format, ...)
{
va_list arg_ptr ;
debug_init ();
if ( debug_level < level )
return;
va_start ( arg_ptr, format ) ;
LOCK (debug_lock);
vfprintf (errfp, format, arg_ptr) ;
va_end ( arg_ptr ) ;
if( format && *format && format[strlen(format)-1] != '\n' )
putc ('\n', errfp);
UNLOCK (debug_lock);
fflush (errfp);
}
void
_gpgme_debug_begin ( void **helper, int level, const char *text)
{
struct debug_control_s *ctl;
debug_init ();
*helper = NULL;
if ( debug_level < level )
return;
ctl = xtrycalloc (1, sizeof *ctl );
if (!ctl) {
_gpgme_debug (255, __FILE__ ":" STR2(__LINE__)": out of core");
return;
}
/* Oh what a pitty that we don't have a asprintf or snprintf under
* Windoze. We definitely should write our own clib for W32! */
sprintf ( ctl->fname, "/tmp/gpgme_debug.%d.%p", getpid (), ctl );
#if defined (__GLIBC__) || defined (HAVE_DOSISH_SYSTEM)
ctl->fp = fopen (ctl->fname, "w+x");
#else
{
int fd = open (ctl->fname, O_WRONLY|O_TRUNC|O_CREAT|O_EXCL,
S_IRUSR|S_IWUSR );
if (fd == -1)
ctl->fp = NULL;
else
ctl->fp = fdopen (fd, "w+");
}
#endif
if (!ctl->fp) {
_gpgme_debug (255,__FILE__ ":" STR2(__LINE__)": failed to create `%s'",
ctl->fname );
xfree (ctl);
return;
}
*helper = ctl;
_gpgme_debug_add (helper, "%s", text );
}
int
_gpgme_debug_enabled (void **helper)
{
return helper && *helper;
}
void
_gpgme_debug_add (void **helper, const char *format, ...)
{
struct debug_control_s *ctl = *helper;
va_list arg_ptr ;
if ( !*helper )
return;
va_start ( arg_ptr, format ) ;
vfprintf (ctl->fp, format, arg_ptr) ;
va_end ( arg_ptr ) ;
}
void
_gpgme_debug_end (void **helper, const char *text)
{
struct debug_control_s *ctl = *helper;
int c, last_c=EOF;
if ( !*helper )
return;
_gpgme_debug_add (helper, "%s", text );
fflush (ctl->fp); /* we need this for the buggy Windoze libc */
rewind (ctl->fp);
LOCK (debug_lock);
while ( (c=getc (ctl->fp)) != EOF ) {
putc (c, errfp);
last_c = c;
}
if (last_c != '\n')
putc ('\n', errfp);
UNLOCK (debug_lock);
fclose (ctl->fp);
remove (ctl->fname);
xfree (ctl);
*helper = NULL;
}