Updated from NewPG

This commit is contained in:
Werner Koch 2003-01-09 12:36:05 +00:00
parent d3b880b74c
commit 11d5db1dcb
18 changed files with 3105 additions and 0 deletions

124
jnlib/ChangeLog Normal file
View File

@ -0,0 +1,124 @@
2002-06-04 Werner Koch <wk@gnupg.org>
* stringhelp.c (print_sanitized_utf8_string): New. No real
implementation for now.
(print_sanitized_utf8_buffer): Ditto.
2002-04-04 Werner Koch <wk@gnupg.org>
* logging.c (log_get_prefix): New.
2002-03-15 Werner Koch <wk@gnupg.org>
* argparse.c (optfile_parse): Fixed missing argument handling.
2002-02-25 Werner Koch <wk@gnupg.org>
* stringhelp.c (ascii_memcasemem): New.
2002-02-14 Werner Koch <wk@gnupg.org>
* Makefile.am (INCLUDES): Add cflags for libgcrypt.
2002-02-07 Werner Koch <wk@gnupg.org>
* logging.c (log_set_fd): New.
* stringhelp.c (print_sanitized_buffer): New.
(print_sanitized_string): New.
2002-01-24 Werner Koch <wk@gnupg.org>
* argparse.c (strusage): Set default copyright notice year to 2002.
Fixed the copyright notice of this file, as it has always been
part of GnuPG and therefore belongs to the FSF.
2001-11-01 Marcus Brinkmann <marcus@g10code.de>
* logging.c (log_printf): Do not initialize ARG_PTR with 0, we
don't know the correct type. Instead, run va_start and va_end
unconditionally.
Reported by Jose Carlos Garcia Sogo <jsogo@debian.org>.
2002-01-19 Werner Koch <wk@gnupg.org>
* logging.c (log_get_stream): New.
2001-12-05 Werner Koch <wk@gnupg.org>
* logging.c (log_set_prefix): New.
(do_logv): Include prefix and pid only if enabled. Print time only
when explicitly enabled.
(log_logv): New.
* logging.h: Include log_logv() only when requested.
2001-11-06 Werner Koch <wk@gnupg.org>
* strlist.c, strlist.h: New. Taken from pgnupg/util/strgutil.c
2001-08-30 Werner Koch <wk@gnupg.org>
* logging.c (log_printf): Don't pass NULL instead of arg_ptr.
2001-07-19 Werner Koch <wk@gnupg.org>
* stringhelp.c (ascii_memistr,ascii_isupper,ascii_islower,
ascii_toupper,ascii_tolower, ascii_strcasecmp, ascii_memcasecmp): New.
2000-07-26 10:02:51 Werner Koch (wk@habibti.openit.de)
* stringhelp.c.: Add stdarg.h
* argparse.h: s/ulong/unsigned long/ although this should be defined
by types.h.
2000-06-28 19:40:23 Werner Koch (wk@habibti.openit.de)
* Makefile.am: Replaced second logging.c by .h
2000-05-24 08:58:15 Werner Koch (wk@habibti.openit.de)
* logging.c (log_get_errorcount): New.
2000-05-24 08:44:47 Werner Koch (wk@habibti.openit.de)
* stringhelp.c: Added a few filename related helper functions.
2000-05-11 18:04:43 Werner Koch (wk@habibti.openit.de)
* xmalloc.c (xstrcat2): Replaced stpcpy to quickly address W32
problems.
2000-05-02 19:43:38 Werner Koch (wk@habibti.openit.de)
* xmalloc.c (xstrcat2): New.
Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de>
* README: New.
* Makefile.am: new.
* argparse.c argparse.h logging.c logging.h
mischelp.h stringhelp.c stringhelp.h xmalloc.c
xmalloc.h dotlock.c: Moved from ../util to here.
* dotlock.h: New.
* libjnlib-config.h: New.
* logging.c (log_set_file): New.
(log_printf): New.
(do_logv): Add kludge to insert LFs.
***********************************************************
* Please note that Jnlib is maintained as part of GnuPG. *
* You may find it source-copied in other packages. *
***********************************************************
Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without
modifications, as long as this notice is preserved.
This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

40
jnlib/Makefile.am Normal file
View File

@ -0,0 +1,40 @@
# Copyright (C) 1999, 2000, 2001 Feee Software Soundation, Inc.
#
# This file is part of GnuPG
#
# GnuPG 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.
#
# GnuPG 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
## Process this file with automake to produce Makefile.in
EXTRA_DIST = README
# We need libgcrypt becuase libjnlib-confilig includes gcrypt.h
INCLUDES = -I$(top_srcdir)/intl $(LIBGCRYPT_CFLAGS)
noinst_LIBRARIES = libjnlib.a
#libjnlib_a_LDFLAGS =
libjnlib_a_SOURCES = \
libjnlib-config.h \
stringhelp.c stringhelp.h \
strlist.c strlist.h \
argparse.c argparse.h \
logging.c logging.h \
dotlock.c dotlock.h \
types.h mischelp.h
# xmalloc.c xmalloc.h

7
jnlib/README Normal file
View File

@ -0,0 +1,7 @@
jnlib - this is a collection of utility function which are
too small to put into a library.
libjnlib-config.h should be be modified for each project
to make these functions fit into the software. Mainly these
are memory functions in case you need another allocator.

997
jnlib/argparse.c Normal file
View File

@ -0,0 +1,997 @@
/* [argparse.c wk 17.06.97] Argument Parser for option handling
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 <ctype.h>
#include <string.h>
#include "libjnlib-config.h"
#include "mischelp.h"
#include "stringhelp.h"
#include "logging.h"
#include "argparse.h"
/*********************************
* @Summary arg_parse
* #include <wk/lib.h>
*
* typedef struct {
* char *argc; pointer to argc (value subject to change)
* char ***argv; pointer to argv (value subject to change)
* unsigned flags; Global flags (DO NOT CHANGE)
* int err; print error about last option
* 1 = warning, 2 = abort
* int r_opt; return option
* int r_type; type of return value (0 = no argument found)
* union {
* int ret_int;
* long ret_long
* ulong ret_ulong;
* char *ret_str;
* } r; Return values
* struct {
* int idx;
* const char *last;
* void *aliases;
* } internal; DO NOT CHANGE
* } ARGPARSE_ARGS;
*
* typedef struct {
* int short_opt;
* const char *long_opt;
* unsigned flags;
* } ARGPARSE_OPTS;
*
* int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts );
*
* @Description
* This is my replacement for getopt(). See the example for a typical usage.
* Global flags are:
* Bit 0 : Do not remove options form argv
* Bit 1 : Do not stop at last option but return other args
* with r_opt set to -1.
* Bit 2 : Assume options and real args are mixed.
* Bit 3 : Do not use -- to stop option processing.
* Bit 4 : Do not skip the first arg.
* Bit 5 : allow usage of long option with only one dash
* Bit 6 : ignore --version
* all other bits must be set to zero, this value is modified by the
* function, so assume this is write only.
* Local flags (for each option):
* Bit 2-0 : 0 = does not take an argument
* 1 = takes int argument
* 2 = takes string argument
* 3 = takes long argument
* 4 = takes ulong argument
* Bit 3 : argument is optional (r_type will the be set to 0)
* Bit 4 : allow 0x etc. prefixed values.
* Bit 7 : this is a command and not an option
* You stop the option processing by setting opts to NULL, the function will
* then return 0.
* @Return Value
* Returns the args.r_opt or 0 if ready
* r_opt may be -2/-7 to indicate an unknown option/command.
* @See Also
* ArgExpand
* @Notes
* You do not need to process the options 'h', '--help' or '--version'
* because this function includes standard help processing; but if you
* specify '-h', '--help' or '--version' you have to do it yourself.
* The option '--' stops argument processing; if bit 1 is set the function
* continues to return normal arguments.
* To process float args or unsigned args you must use a string args and do
* the conversion yourself.
* @Example
*
* ARGPARSE_OPTS opts[] = {
* { 'v', "verbose", 0 },
* { 'd', "debug", 0 },
* { 'o', "output", 2 },
* { 'c', "cross-ref", 2|8 },
* { 'm', "my-option", 1|8 },
* { 500, "have-no-short-option-for-this-long-option", 0 },
* {0} };
* ARGPARSE_ARGS pargs = { &argc, &argv, 0 }
*
* while( ArgParse( &pargs, &opts) ) {
* switch( pargs.r_opt ) {
* case 'v': opt.verbose++; break;
* case 'd': opt.debug++; break;
* case 'o': opt.outfile = pargs.r.ret_str; break;
* case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
* case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
* case 500: opt.a_long_one++; break
* default : pargs.err = 1; break; -- force warning output --
* }
* }
* if( argc > 1 )
* log_fatal( "Too many args");
*
*/
typedef struct alias_def_s *ALIAS_DEF;
struct alias_def_s {
ALIAS_DEF next;
char *name; /* malloced buffer with name, \0, value */
const char *value; /* ptr into name */
};
static const char *(*strusage_handler)( int ) = NULL;
static int set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s);
static void show_help(ARGPARSE_OPTS *opts, unsigned flags);
static void show_version(void);
static void
initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
{
if( !(arg->flags & (1<<15)) ) { /* initialize this instance */
arg->internal.idx = 0;
arg->internal.last = NULL;
arg->internal.inarg = 0;
arg->internal.stopped = 0;
arg->internal.aliases = NULL;
arg->internal.cur_alias = NULL;
arg->err = 0;
arg->flags |= 1<<15; /* mark initialized */
if( *arg->argc < 0 )
jnlib_log_bug("Invalid argument for ArgParse\n");
}
if( arg->err ) { /* last option was erroneous */
const char *s;
if( filename ) {
if( arg->r_opt == -6 )
s = "%s:%u: argument not expected\n";
else if( arg->r_opt == -5 )
s = "%s:%u: read error\n";
else if( arg->r_opt == -4 )
s = "%s:%u: keyword too long\n";
else if( arg->r_opt == -3 )
s = "%s:%u: missing argument\n";
else if( arg->r_opt == -7 )
s = "%s:%u: invalid command\n";
else if( arg->r_opt == -10 )
s = "%s:%u: invalid alias definition\n";
else
s = "%s:%u: invalid option\n";
jnlib_log_error(s, filename, *lineno );
}
else {
if( arg->r_opt == -3 )
s = "Missing argument for option \"%.50s\"\n";
else if( arg->r_opt == -6 )
s = "Option \"%.50s\" does not expect an argument\n";
else if( arg->r_opt == -7 )
s = "Invalid command \"%.50s\"\n";
else if( arg->r_opt == -8 )
s = "Option \"%.50s\" is ambiguous\n";
else if( arg->r_opt == -9 )
s = "Command \"%.50s\" is ambiguous\n";
else
s = "Invalid option \"%.50s\"\n";
jnlib_log_error(s, arg->internal.last? arg->internal.last:"[??]" );
}
if( arg->err != 1 )
exit(2);
arg->err = 0;
}
/* clearout the return value union */
arg->r.ret_str = NULL;
arg->r.ret_long= 0;
}
static void
store_alias( ARGPARSE_ARGS *arg, char *name, char *value )
{
/* TODO: replace this dummy function with a rea one
* and fix the probelms IRIX has with (ALIAS_DEV)arg..
* used as lvalue
*/
#if 0
ALIAS_DEF a = jnlib_xmalloc( sizeof *a );
a->name = name;
a->value = value;
a->next = (ALIAS_DEF)arg->internal.aliases;
(ALIAS_DEF)arg->internal.aliases = a;
#endif
}
/****************
* Get options from a file.
* Lines starting with '#' are comment lines.
* Syntax is simply a keyword and the argument.
* Valid keywords are all keywords from the long_opt list without
* the leading dashes. The special keywords "help", "warranty" and "version"
* are not valid here.
* The special keyword "alias" may be used to store alias definitions,
* which are later expanded like long options.
* Caller must free returned strings.
* If called with FP set to NULL command line args are parse instead.
*
* Q: Should we allow the syntax
* keyword = value
* and accept for boolean options a value of 1/0, yes/no or true/false?
* Note: Abbreviation of options is here not allowed.
*/
int
optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
{
int state, i, c;
int idx=0;
char keyword[100];
char *buffer = NULL;
size_t buflen = 0;
int inverse=0;
int in_alias=0;
if( !fp ) /* same as arg_parse() in this case */
return arg_parse( arg, opts );
initialize( arg, filename, lineno );
/* find the next keyword */
state = i = 0;
for(;;) {
c=getc(fp);
if( c == '\n' || c== EOF ) {
if( c != EOF )
++*lineno;
if( state == -1 )
break;
else if( state == 2 ) {
keyword[i] = 0;
for(i=0; opts[i].short_opt; i++ )
if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
break;
idx = i;
arg->r_opt = opts[idx].short_opt;
if( inverse ) /* this does not have an effect, hmmm */
arg->r_opt = -arg->r_opt;
if( !opts[idx].short_opt ) /* unknown command/option */
arg->r_opt = (opts[idx].flags & 256)? -7:-2;
else if( !(opts[idx].flags & 7) ) /* does not take an arg */
arg->r_type = 0; /* okay */
else if( (opts[idx].flags & 8) ) /* argument is optional */
arg->r_type = 0; /* okay */
else /* required argument */
arg->r_opt = -3; /* error */
break;
}
else if( state == 3 ) { /* no argument found */
if( in_alias )
arg->r_opt = -3; /* error */
else if( !(opts[idx].flags & 7) ) /* does not take an arg */
arg->r_type = 0; /* okay */
else if( (opts[idx].flags & 8) ) /* no optional argument */
arg->r_type = 0; /* okay */
else /* no required argument */
arg->r_opt = -3; /* error */
break;
}
else if( state == 4 ) { /* have an argument */
if( in_alias ) {
if( !buffer )
arg->r_opt = -6;
else {
char *p;
buffer[i] = 0;
p = strpbrk( buffer, " \t" );
if( p ) {
*p++ = 0;
trim_spaces( p );
}
if( !p || !*p ) {
jnlib_free( buffer );
arg->r_opt = -10;
}
else {
store_alias( arg, buffer, p );
}
}
}
else if( !(opts[idx].flags & 7) ) /* does not take an arg */
arg->r_opt = -6; /* error */
else {
char *p;
if( !buffer ) {
keyword[i] = 0;
buffer = jnlib_xstrdup(keyword);
}
else
buffer[i] = 0;
trim_spaces( buffer );
p = buffer;
if( *p == '"' ) { /* remove quotes */
p++;
if( *p && p[strlen(p)-1] == '"' )
p[strlen(p)-1] = 0;
}
if( !set_opt_arg(arg, opts[idx].flags, p) )
jnlib_free(buffer);
}
break;
}
else if( c == EOF ) {
if( ferror(fp) )
arg->r_opt = -5; /* read error */
else
arg->r_opt = 0; /* eof */
break;
}
state = 0;
i = 0;
}
else if( state == -1 )
; /* skip */
else if( !state && isspace(c) )
; /* skip leading white space */
else if( !state && c == '#' )
state = 1; /* start of a comment */
else if( state == 1 )
; /* skip comments */
else if( state == 2 && isspace(c) ) {
keyword[i] = 0;
for(i=0; opts[i].short_opt; i++ )
if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
break;
idx = i;
arg->r_opt = opts[idx].short_opt;
if( !opts[idx].short_opt ) {
if( !strcmp( keyword, "alias" ) ) {
in_alias = 1;
state = 3;
}
else {
arg->r_opt = (opts[idx].flags & 256)? -7:-2;
state = -1; /* skip rest of line and leave */
}
}
else
state = 3;
}
else if( state == 3 ) { /* skip leading spaces of the argument */
if( !isspace(c) ) {
i = 0;
keyword[i++] = c;
state = 4;
}
}
else if( state == 4 ) { /* collect the argument */
if( buffer ) {
if( i < buflen-1 )
buffer[i++] = c;
else {
buflen += 50;
buffer = jnlib_xrealloc(buffer, buflen);
buffer[i++] = c;
}
}
else if( i < DIM(keyword)-1 )
keyword[i++] = c;
else {
buflen = DIM(keyword)+50;
buffer = jnlib_xmalloc(buflen);
memcpy(buffer, keyword, i);
buffer[i++] = c;
}
}
else if( i >= DIM(keyword)-1 ) {
arg->r_opt = -4; /* keyword to long */
state = -1; /* skip rest of line and leave */
}
else {
keyword[i++] = c;
state = 2;
}
}
return arg->r_opt;
}
static int
find_long_option( ARGPARSE_ARGS *arg,
ARGPARSE_OPTS *opts, const char *keyword )
{
int i;
size_t n;
/* Would be better if we can do a binary search, but it is not
possible to reorder our option table because we would mess
up our help strings - What we can do is: Build a nice option
lookup table wehn this function is first invoked */
if( !*keyword )
return -1;
for(i=0; opts[i].short_opt; i++ )
if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
return i;
#if 0
{
ALIAS_DEF a;
/* see whether it is an alias */
for( a = args->internal.aliases; a; a = a->next ) {
if( !strcmp( a->name, keyword) ) {
/* todo: must parse the alias here */
args->internal.cur_alias = a;
return -3; /* alias available */
}
}
}
#endif
/* not found, see whether it is an abbreviation */
/* aliases may not be abbreviated */
n = strlen( keyword );
for(i=0; opts[i].short_opt; i++ ) {
if( opts[i].long_opt && !strncmp( opts[i].long_opt, keyword, n ) ) {
int j;
for(j=i+1; opts[j].short_opt; j++ ) {
if( opts[j].long_opt
&& !strncmp( opts[j].long_opt, keyword, n ) )
return -2; /* abbreviation is ambiguous */
}
return i;
}
}
return -1;
}
int
arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
{
int idx;
int argc;
char **argv;
char *s, *s2;
int i;
initialize( arg, NULL, NULL );
argc = *arg->argc;
argv = *arg->argv;
idx = arg->internal.idx;
if( !idx && argc && !(arg->flags & (1<<4)) ) { /* skip the first entry */
argc--; argv++; idx++;
}
next_one:
if( !argc ) { /* no more args */
arg->r_opt = 0;
goto leave; /* ready */
}
s = *argv;
arg->internal.last = s;
if( arg->internal.stopped && (arg->flags & (1<<1)) ) {
arg->r_opt = -1; /* not an option but a argument */
arg->r_type = 2;
arg->r.ret_str = s;
argc--; argv++; idx++; /* set to next one */
}
else if( arg->internal.stopped ) { /* ready */
arg->r_opt = 0;
goto leave;
}
else if( *s == '-' && s[1] == '-' ) { /* long option */
char *argpos;
arg->internal.inarg = 0;
if( !s[2] && !(arg->flags & (1<<3)) ) { /* stop option processing */
arg->internal.stopped = 1;
argc--; argv++; idx++;
goto next_one;
}
argpos = strchr( s+2, '=' );
if( argpos )
*argpos = 0;
i = find_long_option( arg, opts, s+2 );
if( argpos )
*argpos = '=';
if( i < 0 && !strcmp( "help", s+2) )
show_help(opts, arg->flags);
else if( i < 0 && !strcmp( "version", s+2) ) {
if( !(arg->flags & (1<<6)) ) {
show_version();
exit(0);
}
}
else if( i < 0 && !strcmp( "warranty", s+2) ) {
puts( strusage(16) );
exit(0);
}
else if( i < 0 && !strcmp( "dump-options", s+2) ) {
for(i=0; opts[i].short_opt; i++ ) {
if( opts[i].long_opt )
printf( "--%s\n", opts[i].long_opt );
}
fputs("--dump-options\n--help\n--version\n--warranty\n", stdout );
exit(0);
}
if( i == -2 ) /* ambiguous option */
arg->r_opt = -8;
else if( i == -1 ) {
arg->r_opt = -2;
arg->r.ret_str = s+2;
}
else
arg->r_opt = opts[i].short_opt;
if( i < 0 )
;
else if( (opts[i].flags & 7) ) {
if( argpos ) {
s2 = argpos+1;
if( !*s2 )
s2 = NULL;
}
else
s2 = argv[1];
if( !s2 && (opts[i].flags & 8) ) { /* no argument but it is okay*/
arg->r_type = 0; /* because it is optional */
}
else if( !s2 ) {
arg->r_opt = -3; /* missing argument */
}
else if( !argpos && *s2 == '-' && (opts[i].flags & 8) ) {
/* the argument is optional and the next seems to be
* an option. We do not check this possible option
* but assume no argument */
arg->r_type = 0;
}
else {
set_opt_arg(arg, opts[i].flags, s2);
if( !argpos ) {
argc--; argv++; idx++; /* skip one */
}
}
}
else { /* does not take an argument */
if( argpos )
arg->r_type = -6; /* argument not expected */
else
arg->r_type = 0;
}
argc--; argv++; idx++; /* set to next one */
}
else if( (*s == '-' && s[1]) || arg->internal.inarg ) { /* short option */
int dash_kludge = 0;
i = 0;
if( !arg->internal.inarg ) {
arg->internal.inarg++;
if( arg->flags & (1<<5) ) {
for(i=0; opts[i].short_opt; i++ )
if( opts[i].long_opt && !strcmp( opts[i].long_opt, s+1)) {
dash_kludge=1;
break;
}
}
}
s += arg->internal.inarg;
if( !dash_kludge ) {
for(i=0; opts[i].short_opt; i++ )
if( opts[i].short_opt == *s )
break;
}
if( !opts[i].short_opt && ( *s == 'h' || *s == '?' ) )
show_help(opts, arg->flags);
arg->r_opt = opts[i].short_opt;
if( !opts[i].short_opt ) {
arg->r_opt = (opts[i].flags & 256)? -7:-2;
arg->internal.inarg++; /* point to the next arg */
arg->r.ret_str = s;
}
else if( (opts[i].flags & 7) ) {
if( s[1] && !dash_kludge ) {
s2 = s+1;
set_opt_arg(arg, opts[i].flags, s2);
}
else {
s2 = argv[1];
if( !s2 && (opts[i].flags & 8) ) { /* no argument but it is okay*/
arg->r_type = 0; /* because it is optional */
}
else if( !s2 ) {
arg->r_opt = -3; /* missing argument */
}
else if( *s2 == '-' && s2[1] && (opts[i].flags & 8) ) {
/* the argument is optional and the next seems to be
* an option. We do not check this possible option
* but assume no argument */
arg->r_type = 0;
}
else {
set_opt_arg(arg, opts[i].flags, s2);
argc--; argv++; idx++; /* skip one */
}
}
s = "x"; /* so that !s[1] yields false */
}
else { /* does not take an argument */
arg->r_type = 0;
arg->internal.inarg++; /* point to the next arg */
}
if( !s[1] || dash_kludge ) { /* no more concatenated short options */
arg->internal.inarg = 0;
argc--; argv++; idx++;
}
}
else if( arg->flags & (1<<2) ) {
arg->r_opt = -1; /* not an option but a argument */
arg->r_type = 2;
arg->r.ret_str = s;
argc--; argv++; idx++; /* set to next one */
}
else {
arg->internal.stopped = 1; /* stop option processing */
goto next_one;
}
leave:
*arg->argc = argc;
*arg->argv = argv;
arg->internal.idx = idx;
return arg->r_opt;
}
static int
set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s)
{
int base = (flags & 16)? 0 : 10;
switch( arg->r_type = (flags & 7) ) {
case 1: /* takes int argument */
arg->r.ret_int = (int)strtol(s,NULL,base);
return 0;
case 3: /* takes long argument */
arg->r.ret_long= strtol(s,NULL,base);
return 0;
case 4: /* takes ulong argument */
arg->r.ret_ulong= strtoul(s,NULL,base);
return 0;
case 2: /* takes string argument */
default:
arg->r.ret_str = s;
return 1;
}
}
static size_t
long_opt_strlen( ARGPARSE_OPTS *o )
{
size_t n = strlen(o->long_opt);
if( o->description && *o->description == '|' ) {
const char *s;
s=o->description+1;
if( *s != '=' )
n++;
for(; *s && *s != '|'; s++ )
n++;
}
return n;
}
/****************
* Print formatted help. The description string has some special
* meanings:
* - A description string which is "@" suppresses help output for
* this option
* - a description,ine which starts with a '@' and is followed by
* any other characters is printed as is; this may be used for examples
* ans such.
* - A description which starts with a '|' outputs the string between this
* bar and the next one as arguments of the long option.
*/
static void
show_help( ARGPARSE_OPTS *opts, unsigned flags )
{
const char *s;
show_version();
putchar('\n');
s = strusage(41);
puts(s);
if( opts[0].description ) { /* auto format the option description */
int i,j, indent;
/* get max. length of long options */
for(i=indent=0; opts[i].short_opt; i++ ) {
if( opts[i].long_opt )
if( !opts[i].description || *opts[i].description != '@' )
if( (j=long_opt_strlen(opts+i)) > indent && j < 35 )
indent = j;
}
/* example: " -v, --verbose Viele Sachen ausgeben" */
indent += 10;
if( *opts[0].description != '@' )
puts("Options:");
for(i=0; opts[i].short_opt; i++ ) {
s = _( opts[i].description );
if( s && *s== '@' && !s[1] ) /* hide this line */
continue;
if( s && *s == '@' ) { /* unindented comment only line */
for(s++; *s; s++ ) {
if( *s == '\n' ) {
if( s[1] )
putchar('\n');
}
else
putchar(*s);
}
putchar('\n');
continue;
}
j = 3;
if( opts[i].short_opt < 256 ) {
printf(" -%c", opts[i].short_opt );
if( !opts[i].long_opt ) {
if(s && *s == '|' ) {
putchar(' '); j++;
for(s++ ; *s && *s != '|'; s++, j++ )
putchar(*s);
if( *s )
s++;
}
}
}
else
fputs(" ", stdout);
if( opts[i].long_opt ) {
j += printf("%c --%s", opts[i].short_opt < 256?',':' ',
opts[i].long_opt );
if(s && *s == '|' ) {
if( *++s != '=' ) {
putchar(' ');
j++;
}
for( ; *s && *s != '|'; s++, j++ )
putchar(*s);
if( *s )
s++;
}
fputs(" ", stdout);
j += 3;
}
for(;j < indent; j++ )
putchar(' ');
if( s ) {
if( *s && j > indent ) {
putchar('\n');
for(j=0;j < indent; j++ )
putchar(' ');
}
for(; *s; s++ ) {
if( *s == '\n' ) {
if( s[1] ) {
putchar('\n');
for(j=0;j < indent; j++ )
putchar(' ');
}
}
else
putchar(*s);
}
}
putchar('\n');
}
if( flags & 32 )
puts("\n(A single dash may be used instead of the double ones)");
}
if( (s=strusage(19)) ) { /* bug reports to ... */
putchar('\n');
fputs(s, stdout);
}
fflush(stdout);
exit(0);
}
static void
show_version()
{
const char *s;
int i;
/* version line */
fputs(strusage(11), stdout);
if( (s=strusage(12)) )
printf(" (%s)", s );
printf(" %s\n", strusage(13) );
/* additional version lines */
for(i=20; i < 30; i++ )
if( (s=strusage(i)) )
printf("%s\n", s );
/* copyright string */
if( (s=strusage(14)) )
printf("%s\n", s );
/* copying conditions */
if( (s=strusage(15)) )
fputs(s, stdout);
/* thanks */
if( (s=strusage(18)) )
fputs(s, stdout);
/* additional program info */
for(i=30; i < 40; i++ )
if( (s=strusage(i)) )
fputs( (const byte*)s, stdout);
fflush(stdout);
}
void
usage( int level )
{
if( !level ) {
fprintf(stderr,"%s %s; %s\n", strusage(11), strusage(13),
strusage(14) );
fflush(stderr);
}
else if( level == 1 ) {
fputs(strusage(40),stderr);
exit(2);
}
else if( level == 2 ) {
puts(strusage(41));
exit(0);
}
}
/* Level
* 0: Copyright String auf stderr ausgeben
* 1: Kurzusage auf stderr ausgeben und beenden
* 2: Langusage auf stdout ausgeben und beenden
* 11: name of program
* 12: optional name of package which includes this program.
* 13: version string
* 14: copyright string
* 15: Short copying conditions (with LFs)
* 16: Long copying conditions (with LFs)
* 17: Optional printable OS name
* 18: Optional thanks list (with LFs)
* 19: Bug report info
*20..29: Additional lib version strings.
*30..39: Additional program info (with LFs)
* 40: short usage note (with LF)
* 41: long usage note (with LF)
*/
const char *
strusage( int level )
{
const char *p = strusage_handler? strusage_handler(level) : NULL;
if( p )
return p;
switch( level ) {
case 11: p = "foo"; break;
case 13: p = "0.0"; break;
case 14: p = "Copyright (C) 2002 Free Software Foundation, Inc."; break;
case 15: p =
"This program comes with ABSOLUTELY NO WARRANTY.\n"
"This is free software, and you are welcome to redistribute it\n"
"under certain conditions. See the file COPYING for details.\n"; break;
case 16: p =
"This is free software; you can redistribute it and/or modify\n"
"it under the terms of the GNU General Public License as published by\n"
"the Free Software Foundation; either version 2 of the License, or\n"
"(at your option) any later version.\n\n"
"It is distributed in the hope that it will be useful,\n"
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
"GNU General Public License for more details.\n\n"
"You should have received a copy of the GNU General Public License\n"
"along with this program; if not, write to the Free Software\n"
"Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n";
break;
case 40: /* short and long usage */
case 41: p = ""; break;
}
return p;
}
void
set_strusage( const char *(*f)( int ) )
{
strusage_handler = f;
}
#ifdef TEST
static struct {
int verbose;
int debug;
char *outfile;
char *crf;
int myopt;
int echo;
int a_long_one;
}opt;
int
main(int argc, char **argv)
{
ARGPARSE_OPTS opts[] = {
{ 'v', "verbose", 0 , "Laut sein"},
{ 'e', "echo" , 0 , "Zeile ausgeben, damit wir sehen, was wir einegegeben haben"},
{ 'd', "debug", 0 , "Debug\nfalls mal etasws\nSchief geht"},
{ 'o', "output", 2 },
{ 'c', "cross-ref", 2|8, "cross-reference erzeugen\n" },
{ 'm', "my-option", 1|8 },
{ 500, "a-long-option", 0 },
{0} };
ARGPARSE_ARGS pargs = { &argc, &argv, 2|4|32 };
int i;
while( ArgParse( &pargs, opts) ) {
switch( pargs.r_opt ) {
case -1 : printf( "arg=`%s'\n", pargs.r.ret_str); break;
case 'v': opt.verbose++; break;
case 'e': opt.echo++; break;
case 'd': opt.debug++; break;
case 'o': opt.outfile = pargs.r.ret_str; break;
case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
case 500: opt.a_long_one++; break;
default : pargs.err = 1; break; /* force warning output */
}
}
for(i=0; i < argc; i++ )
printf("%3d -> (%s)\n", i, argv[i] );
puts("Options:");
if( opt.verbose )
printf(" verbose=%d\n", opt.verbose );
if( opt.debug )
printf(" debug=%d\n", opt.debug );
if( opt.outfile )
printf(" outfile=`%s'\n", opt.outfile );
if( opt.crf )
printf(" crffile=`%s'\n", opt.crf );
if( opt.myopt )
printf(" myopt=%d\n", opt.myopt );
if( opt.a_long_one )
printf(" a-long-one=%d\n", opt.a_long_one );
if( opt.echo )
printf(" echo=%d\n", opt.echo );
return 0;
}
#endif
/**** bottom of file ****/

67
jnlib/argparse.h Normal file
View File

@ -0,0 +1,67 @@
/* argparse.h
* Copyright (C) 1998,1999,2000,2001 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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
*/
#ifndef LIBJNLIB_ARGPARSE_H
#define LIBJNLIB_ARGPARSE_H
#include <stdio.h>
#include "types.h"
typedef struct {
int *argc; /* pointer to argc (value subject to change) */
char ***argv; /* pointer to argv (value subject to change) */
unsigned flags; /* Global flags (DO NOT CHANGE) */
int err; /* print error about last option */
/* 1 = warning, 2 = abort */
int r_opt; /* return option */
int r_type; /* type of return value (0 = no argument found)*/
union {
int ret_int;
long ret_long;
unsigned long ret_ulong;
char *ret_str;
} r; /* Return values */
struct {
int idx;
int inarg;
int stopped;
const char *last;
void *aliases;
const void *cur_alias;
} internal; /* DO NOT CHANGE */
} ARGPARSE_ARGS;
typedef struct {
int short_opt;
const char *long_opt;
unsigned flags;
const char *description; /* optional option description */
} ARGPARSE_OPTS;
int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts);
int optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts);
void usage( int level );
const char *strusage( int level );
void set_strusage( const char *(*f)( int ) );
#endif /*LIBJNLIB_ARGPARSE_H*/

346
jnlib/dotlock.c Normal file
View File

@ -0,0 +1,346 @@
/* dotlock.c - dotfile locking
* Copyright (C) 1998,2000,2001 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#ifndef HAVE_DOSISH_SYSTEM
#include <sys/utsname.h>
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include "libjnlib-config.h"
#include "dotlock.h"
struct dotlock_handle {
struct dotlock_handle *next;
char *tname; /* name of lockfile template */
char *lockname; /* name of the real lockfile */
int locked; /* lock status */
};
static DOTLOCK all_lockfiles;
static int read_lockfile( const char *name );
static void remove_lockfiles(void);
/****************
* Create a lockfile with the given name and return an object of
* type DOTLOCK which may be used later to actually do the lock.
* A cleanup routine gets installed to cleanup left over locks
* or other files used together with the lockmechanism.
* Althoug the function is called dotlock, this does not necessarily
* mean that real lockfiles are used - the function may decide to
* use fcntl locking. Calling the function with NULL only install
* the atexit handler and maybe used to assure that the cleanup
* is called after all other atexit handlers.
*
* Notes: This function creates a lock file in the same directory
* as file_to_lock with the name "file_to_lock.lock"
* A temporary file ".#lk.<hostname>.pid[.threadid] is used.
* This function does nothing for Windoze.
*/
DOTLOCK
create_dotlock( const char *file_to_lock )
{
static int initialized;
DOTLOCK h;
int fd = -1;
char pidstr[16];
#ifndef HAVE_DOSISH_SYSTEM
struct utsname utsbuf;
#endif
const char *nodename;
const char *dirpart;
int dirpartlen;
if( !initialized ) {
atexit( remove_lockfiles );
initialized = 1;
}
if( !file_to_lock )
return NULL;
h = jnlib_xcalloc( 1, sizeof *h );
#ifndef HAVE_DOSISH_SYSTEM
sprintf( pidstr, "%10d\n", (int)getpid() );
/* fixme: add the hostname to the second line (FQDN or IP addr?) */
/* create a temporary file */
if( uname( &utsbuf ) )
nodename = "unknown";
else
nodename = utsbuf.nodename;
if( !(dirpart = strrchr( file_to_lock, '/' )) ) {
dirpart = ".";
dirpartlen = 1;
}
else {
dirpartlen = dirpart - file_to_lock;
dirpart = file_to_lock;
}
#ifdef _REENTRANT
/* fixme: aquire mutex on all_lockfiles */
#endif
h->next = all_lockfiles;
all_lockfiles = h;
h->tname = jnlib_xmalloc( dirpartlen + 6+30+ strlen(nodename) + 11 );
sprintf( h->tname, "%.*s/.#lk%p.%s.%d",
dirpartlen, dirpart, h, nodename, (int)getpid() );
do {
errno = 0;
fd = open( h->tname, O_WRONLY|O_CREAT|O_EXCL,
S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR );
} while( fd == -1 && errno == EINTR );
if( fd == -1 ) {
all_lockfiles = h->next;
log_error( "failed to create temporary file `%s': %s\n",
h->tname, strerror(errno));
jnlib_free(h->tname);
jnlib_free(h);
return NULL;
}
if( write(fd, pidstr, 11 ) != 11 ) {
all_lockfiles = h->next;
#ifdef _REENTRANT
/* release mutex */
#endif
log_fatal( "error writing to `%s': %s\n", h->tname, strerror(errno) );
close(fd);
unlink(h->tname);
jnlib_free(h->tname);
jnlib_free(h);
return NULL;
}
if( close(fd) ) {
all_lockfiles = h->next;
#ifdef _REENTRANT
/* release mutex */
#endif
log_error( "error closing `%s': %s\n", h->tname, strerror(errno));
unlink(h->tname);
jnlib_free(h->tname);
jnlib_free(h);
return NULL;
}
#ifdef _REENTRANT
/* release mutex */
#endif
#endif /* !HAVE_DOSISH_SYSTEM */
h->lockname = jnlib_xmalloc( strlen(file_to_lock) + 6 );
strcpy(stpcpy(h->lockname, file_to_lock), ".lock");
return h;
}
static int
maybe_deadlock( DOTLOCK h )
{
DOTLOCK r;
for( r=all_lockfiles; r; r = r->next ) {
if( r != h && r->locked )
return 1;
}
return 0;
}
/****************
* Do a lock on H. A TIMEOUT of 0 returns immediately,
* -1 waits forever (hopefully not), other
* values are timeouts in milliseconds.
* Returns: 0 on success
*/
int
make_dotlock( DOTLOCK h, long timeout )
{
#ifdef HAVE_DOSISH_SYSTEM
return 0;
#else
int pid;
const char *maybe_dead="";
int backoff=0;
if( h->locked ) {
log_debug("oops, `%s' is already locked\n", h->lockname );
return 0;
}
for(;;) {
if( !link(h->tname, h->lockname) ) {
/* fixme: better use stat to check the link count */
h->locked = 1;
return 0; /* okay */
}
if( errno != EEXIST ) {
log_error( "lock not made: link() failed: %s\n", strerror(errno) );
return -1;
}
if( (pid = read_lockfile(h->lockname)) == -1 ) {
if( errno != ENOENT ) {
log_info("cannot read lockfile\n");
return -1;
}
log_info( "lockfile disappeared\n");
continue;
}
else if( pid == getpid() ) {
log_info( "Oops: lock already hold by us\n");
h->locked = 1;
return 0; /* okay */
}
else if( kill(pid, 0) && errno == ESRCH ) {
maybe_dead = " - probably dead";
#if 0 /* we should not do this without checking the permissions */
/* and the hostname */
log_info( "removing stale lockfile (created by %d)", pid );
#endif
}
if( timeout == -1 ) {
struct timeval tv;
log_info( "waiting for lock (hold by %d%s) %s...\n",
pid, maybe_dead, maybe_deadlock(h)? "(deadlock?) ":"");
/* can't use sleep, cause signals may be blocked */
tv.tv_sec = 1 + backoff;
tv.tv_usec = 0;
select(0, NULL, NULL, NULL, &tv);
if( backoff < 10 )
backoff++ ;
}
else
return -1;
}
/*not reached */
#endif /* !HAVE_DOSISH_SYSTEM */
}
/****************
* release a lock
* Returns: 0 := success
*/
int
release_dotlock( DOTLOCK h )
{
#ifdef HAVE_DOSISH_SYSTEM
return 0;
#else
int pid;
if( !h->locked ) {
log_debug("oops, `%s' is not locked\n", h->lockname );
return 0;
}
pid = read_lockfile( h->lockname );
if( pid == -1 ) {
log_error( "release_dotlock: lockfile error\n");
return -1;
}
if( pid != getpid() ) {
log_error( "release_dotlock: not our lock (pid=%d)\n", pid);
return -1;
}
if( unlink( h->lockname ) ) {
log_error( "release_dotlock: error removing lockfile `%s'",
h->lockname);
return -1;
}
/* fixme: check that the link count is now 1 */
h->locked = 0;
return 0;
#endif /* !HAVE_DOSISH_SYSTEM */
}
/****************
* Read the lock file and return the pid, returns -1 on error.
*/
static int
read_lockfile( const char *name )
{
#ifdef HAVE_DOSISH_SYSTEM
return 0;
#else
int fd, pid;
char pidstr[16];
if( (fd = open(name, O_RDONLY)) == -1 ) {
int e = errno;
log_debug("error opening lockfile `%s': %s\n", name, strerror(errno) );
errno = e;
return -1;
}
if( read(fd, pidstr, 10 ) != 10 ) { /* Read 10 digits w/o newline */
log_debug("error reading lockfile `%s'", name );
close(fd);
errno = 0;
return -1;
}
pidstr[10] = 0; /* terminate pid string */
close(fd);
pid = atoi(pidstr);
if( !pid || pid == -1 ) {
log_error("invalid pid %d in lockfile `%s'", pid, name );
errno = 0;
return -1;
}
return pid;
#endif
}
static void
remove_lockfiles()
{
#ifndef HAVE_DOSISH_SYSTEM
DOTLOCK h, h2;
h = all_lockfiles;
all_lockfiles = NULL;
while( h ) {
h2 = h->next;
if( h->locked )
unlink( h->lockname );
unlink(h->tname);
jnlib_free(h->tname);
jnlib_free(h->lockname);
jnlib_free(h);
h = h2;
}
#endif
}

32
jnlib/dotlock.h Normal file
View File

@ -0,0 +1,32 @@
/* dotlock.h
* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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
*/
#ifndef LIBJNLIB_DOTLOCK_H
#define LIBJNLIB_DOTLOCK_H
struct dotlock_handle;
typedef struct dotlock_handle *DOTLOCK;
DOTLOCK create_dotlock( const char *file_to_lock );
int make_dotlock( DOTLOCK h, long timeout );
int release_dotlock( DOTLOCK h );
#endif /*LIBJNLIB_DOTLOCK_H*/

72
jnlib/libjnlib-config.h Normal file
View File

@ -0,0 +1,72 @@
/* libjnlib-config.h - local configuration of the jnlib functions
* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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
*/
/****************
* This header is to be included only by the files in this directory
* it should not be used by other modules.
*/
#ifndef LIBJNLIB_CONFIG_H
#define LIBJNLIB_CONFIG_H
#include <gcrypt.h> /* gcry_malloc & Cie. */
#include "logging.h"
#ifdef USE_SIMPLE_GETTEXT
int set_gettext_file( const char *filename );
const char *gettext( const char *msgid );
#define _(a) gettext (a)
#define N_(a) (a)
#else
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
#ifdef ENABLE_NLS
#include <libintl.h>
#define _(a) gettext (a)
#ifdef gettext_noop
#define N_(a) gettext_noop (a)
#else
#define N_(a) (a)
#endif
#else
#define _(a) (a)
#define N_(a) (a)
#endif
#endif /* !USE_SIMPLE_GETTEXT */
#define jnlib_xmalloc(a) gcry_xmalloc( (a) )
#define jnlib_xcalloc(a,b) gcry_xcalloc( (a), (b) )
#define jnlib_xrealloc(a,n) gcry_xrealloc( (a), (n) )
#define jnlib_xstrdup(a) gcry_xstrdup( (a) )
#define jnlib_free(a) gcry_free( (a) )
#define jnlib_log_debug log_debug
#define jnlib_log_info log_info
#define jnlib_log_error log_error
#define jnlib_log_fatal log_fatal
#define jnlib_log_bug log_bug
#endif /*LIBJNUTIL_CONFIG_H*/

347
jnlib/logging.c Normal file
View File

@ -0,0 +1,347 @@
/* logging.c - useful logging functions
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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
*/
/* This file should replace logger.c in the future - for now it is not
* used by GnuPG but by GPA.
* It is a quite simple implemenation but sufficient for most purposes.
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef __MINGW32__
#include <io.h>
#endif
#define JNLIB_NEED_LOG_LOGV 1
#include "libjnlib-config.h"
#include "logging.h"
static FILE *logstream;
static char prefix_buffer[80];
static int with_time;
static int with_prefix;
static int with_pid;
static int missing_lf;
static int errorcount;
#if 0
static void
write2stderr( const char *s )
{
write( 2, s, strlen(s) );
}
static void
do_die(int rc, const char *text )
{
write2stderr("\nFatal error: ");
write2stderr(text);
write2stderr("\n");
abort();
}
#endif
int
log_get_errorcount (int clear)
{
int n = errorcount;
if( clear )
errorcount = 0;
return n;
}
void
log_set_file( const char *name )
{
FILE *fp = (name && strcmp(name,"-"))? fopen(name, "a") : stderr;
if( !fp ) {
fprintf(stderr, "failed to open log file `%s': %s\n",
name, strerror(errno));
return;
}
setvbuf( fp, NULL, _IOLBF, 0 );
if (logstream && logstream != stderr && logstream != stdout)
fclose( logstream );
logstream = fp;
missing_lf = 0;
}
void
log_set_fd (int fd)
{
FILE *fp;
if (fd == 1)
fp = stdout;
else if (fd == 2)
fp = stderr;
else
fp = fdopen (fd, "a");
if (!fp)
{
fprintf (stderr, "failed to fdopen log fd %d: %s\n",
fd, strerror(errno));
return;
}
setvbuf (fp, NULL, _IOLBF, 0);
if (logstream && logstream != stderr && logstream != stdout)
fclose( logstream);
logstream = fp;
missing_lf = 0;
}
void
log_set_prefix (const char *text, unsigned int flags)
{
if (text)
{
strncpy (prefix_buffer, text, sizeof (prefix_buffer)-1);
prefix_buffer[sizeof (prefix_buffer)-1] = 0;
}
with_prefix = (flags & 1);
with_time = (flags & 2);
with_pid = (flags & 4);
}
const char *
log_get_prefix (unsigned int *flags)
{
if (flags)
{
*flags = 0;
if (with_prefix)
*flags |= 1;
if (with_time)
*flags |= 2;
if (with_pid)
*flags |=4;
}
return prefix_buffer;
}
int
log_get_fd()
{
return fileno(logstream?logstream:stderr);
}
FILE *
log_get_stream ()
{
return logstream?logstream:stderr;
}
static void
do_logv( int level, const char *fmt, va_list arg_ptr )
{
if (!logstream)
logstream = stderr;
if (missing_lf && level != JNLIB_LOG_CONT)
putc('\n', logstream );
missing_lf = 0;
if (level != JNLIB_LOG_CONT)
{ /* Note this does not work for multiple line logging as we would
* need to print to a buffer first */
if (with_time)
{
struct tm *tp;
time_t atime = time (NULL);
tp = localtime (&atime);
fprintf (logstream, "%04d-%02d-%02d %02d:%02d:%02d ",
1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
tp->tm_hour, tp->tm_min, tp->tm_sec );
}
if (with_prefix)
fputs (prefix_buffer, logstream);
if (with_pid)
fprintf (logstream, "[%u]", (unsigned int)getpid ());
if (!with_time)
putc (':', logstream);
putc (' ', logstream);
}
switch (level)
{
case JNLIB_LOG_BEGIN: break;
case JNLIB_LOG_CONT: break;
case JNLIB_LOG_INFO: break;
case JNLIB_LOG_WARN: break;
case JNLIB_LOG_ERROR: break;
case JNLIB_LOG_FATAL: fputs("Fatal: ",logstream ); break;
case JNLIB_LOG_BUG: fputs("Ohhhh jeeee: ", logstream); break;
case JNLIB_LOG_DEBUG: fputs("DBG: ", logstream ); break;
default: fprintf(logstream,"[Unknown log level %d]: ", level ); break;
}
if (fmt)
{
vfprintf(logstream,fmt,arg_ptr) ;
if (*fmt && fmt[strlen(fmt)-1] != '\n')
missing_lf = 1;
}
if (level == JNLIB_LOG_FATAL)
exit(2);
if (level == JNLIB_LOG_BUG)
abort();
}
static void
do_log( int level, const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
do_logv( level, fmt, arg_ptr );
va_end(arg_ptr);
}
void
log_logv (int level, const char *fmt, va_list arg_ptr)
{
do_logv (level, fmt, arg_ptr);
}
void
log_info( const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
do_logv( JNLIB_LOG_INFO, fmt, arg_ptr );
va_end(arg_ptr);
}
void
log_error( const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
do_logv( JNLIB_LOG_ERROR, fmt, arg_ptr );
va_end(arg_ptr);
/* protect against counter overflow */
if( errorcount < 30000 )
errorcount++;
}
void
log_fatal( const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
do_logv( JNLIB_LOG_FATAL, fmt, arg_ptr );
va_end(arg_ptr);
abort(); /* never called, bugs it makes the compiler happy */
}
void
log_bug( const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
do_logv( JNLIB_LOG_BUG, fmt, arg_ptr );
va_end(arg_ptr);
abort(); /* never called, but it makes the compiler happy */
}
void
log_debug( const char *fmt, ... )
{
va_list arg_ptr ;
va_start( arg_ptr, fmt ) ;
do_logv( JNLIB_LOG_DEBUG, fmt, arg_ptr );
va_end(arg_ptr);
}
void
log_printf (const char *fmt, ...)
{
va_list arg_ptr;
va_start (arg_ptr, fmt);
do_logv (fmt ? JNLIB_LOG_CONT : JNLIB_LOG_BEGIN, fmt, arg_ptr);
va_end (arg_ptr);
}
/* Print a hexdump of BUFFER. With TEXT of NULL print just the raw
dump, with TEXT just an empty string, print a trailing linefeed,
otherwise print an entire debug line. */
void
log_printhex (const char *text, const void *buffer, size_t length)
{
if (text && *text)
log_debug ("%s ", text);
if (length)
{
const unsigned char *p = buffer;
log_printf ("%02X", *p);
for (length--, p++; length--; p++)
log_printf (" %02X", *p);
}
if (text)
log_printf ("\n");
}
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
void
bug_at( const char *file, int line, const char *func )
{
do_log( JNLIB_LOG_BUG,
("... this is a bug (%s:%d:%s)\n"), file, line, func );
abort(); /* never called, but it makes the compiler happy */
}
#else
void
bug_at( const char *file, int line )
{
do_log( JNLIB_LOG_BUG,
_("you found a bug ... (%s:%d)\n"), file, line);
abort(); /* never called, but it makes the compiler happy */
}
#endif

76
jnlib/logging.h Normal file
View File

@ -0,0 +1,76 @@
/* logging.h
* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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
*/
#ifndef LIBJNLIB_LOGGING_H
#define LIBJNLIB_LOGGING_H
#include <stdio.h>
#include "mischelp.h"
int log_get_errorcount (int clear);
void log_set_file( const char *name );
void log_set_fd (int fd);
void log_set_prefix (const char *text, unsigned int flags);
const char *log_get_prefix (unsigned int *flags);
int log_get_fd(void);
FILE *log_get_stream (void);
#ifdef JNLIB_GCC_M_FUNCTION
void bug_at( const char *file, int line, const char *func ) JNLIB_GCC_A_NR;
# define BUG() bug_at( __FILE__ , __LINE__, __FUNCTION__ )
#else
void bug_at( const char *file, int line );
# define BUG() bug_at( __FILE__ , __LINE__ )
#endif
/* To avoid mandatory inclusion of stdarg and other stuff, do it only
if explicitly requested to do so. */
#ifdef JNLIB_NEED_LOG_LOGV
#include <stdarg.h>
enum jnlib_log_levels {
JNLIB_LOG_BEGIN,
JNLIB_LOG_CONT,
JNLIB_LOG_INFO,
JNLIB_LOG_WARN,
JNLIB_LOG_ERROR,
JNLIB_LOG_FATAL,
JNLIB_LOG_BUG,
JNLIB_LOG_DEBUG
};
void log_logv (int level, const char *fmt, va_list arg_ptr);
#endif /*JNLIB_NEED_LOG_LOGV*/
void log_bug( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2);
void log_fatal( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2);
void log_error( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
void log_info( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
void log_debug( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
void log_printf( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
void log_printhex (const char *text, const void *buffer, size_t length);
#endif /*LIBJNLIB_LOGGING_H*/

43
jnlib/mischelp.h Normal file
View File

@ -0,0 +1,43 @@
/* mischelp.h
* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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
*/
#ifndef LIBJNLIB_MISCHELP_H
#define LIBJNLIB_MISCHHELP_H
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
#define DIMof(type,member) DIM(((type *)0)->member)
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
# define JNLIB_GCC_M_FUNCTION 1
# define JNLIB_GCC_A_NR __attribute__ ((noreturn))
# define JNLIB_GCC_A_PRINTF( f, a ) __attribute__ ((format (printf,f,a)))
# define JNLIB_GCC_A_NR_PRINTF( f, a ) \
__attribute__ ((noreturn, format (printf,f,a)))
#else
# define JNLIB_GCC_A_NR
# define JNLIB_GCC_A_PRINTF( f, a )
# define JNLIB_GCC_A_NR_PRINTF( f, a )
#endif
#endif /*LIBJNLIB_MISCHELP_H*/

474
jnlib/stringhelp.c Normal file
View File

@ -0,0 +1,474 @@
/* stringhelp.c - standard string helper functions
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include "libjnlib-config.h"
#include "stringhelp.h"
/****************
* look for the substring SUB in buffer and return a pointer to that
* substring in BUF or NULL if not found.
* Comparison is case-insensitive.
*/
const char *
memistr( const char *buf, size_t buflen, const char *sub )
{
const byte *t, *s ;
size_t n;
for( t=buf, n=buflen, s=sub ; n ; t++, n-- )
if( toupper(*t) == toupper(*s) ) {
for( buf=t++, buflen = n--, s++;
n && toupper(*t) == toupper(*s); t++, s++, n-- )
;
if( !*s )
return buf;
t = buf; n = buflen; s = sub ;
}
return NULL ;
}
/****************
* Wie strncpy(), aber es werden maximal n-1 zeichen kopiert und ein
* '\0' angehängt. Ist n = 0, so geschieht nichts, ist Destination
* gleich NULL, so wird via jnlib_xmalloc Speicher besorgt, ist dann nicht
* genügend Speicher vorhanden, so bricht die funktion ab.
*/
char *
mem2str( char *dest , const void *src , size_t n )
{
char *d;
const char *s;
if( n ) {
if( !dest )
dest = jnlib_xmalloc( n ) ;
d = dest;
s = src ;
for(n--; n && *s; n-- )
*d++ = *s++;
*d = '\0' ;
}
return dest ;
}
/****************
* remove leading and trailing white spaces
*/
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 ;
}
/****************
* remove trailing white spaces
*/
char *
trim_trailing_spaces( char *string )
{
char *p, *mark;
for( mark = NULL, p = string; *p; p++ ) {
if( isspace( *(byte*)p ) ) {
if( !mark )
mark = p;
}
else
mark = NULL;
}
if( mark )
*mark = '\0' ;
return string ;
}
unsigned
trim_trailing_chars( byte *line, unsigned len, const char *trimchars )
{
byte *p, *mark;
unsigned n;
for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
if( strchr(trimchars, *p ) ) {
if( !mark )
mark = p;
}
else
mark = NULL;
}
if( mark ) {
*mark = 0;
return mark - line;
}
return len;
}
/****************
* remove trailing white spaces and return the length of the buffer
*/
unsigned
trim_trailing_ws( byte *line, unsigned len )
{
return trim_trailing_chars( line, len, " \t\r\n" );
}
/***************
* Extract from a given path the filename component.
*
*/
char *
make_basename(const char *filepath)
{
char *p;
if ( !(p=strrchr(filepath, '/')) )
#ifdef HAVE_DRIVE_LETTERS
if ( !(p=strrchr(filepath, '\\')) )
if ( !(p=strrchr(filepath, ':')) )
#endif
{
return jnlib_xstrdup(filepath);
}
return jnlib_xstrdup(p+1);
}
/***************
* Extract from a given filename the path prepended to it.
* If their isn't a path prepended to the filename, a dot
* is returned ('.').
*
*/
char *
make_dirname(const char *filepath)
{
char *dirname;
int dirname_length;
char *p;
if ( !(p=strrchr(filepath, '/')) )
#ifdef HAVE_DRIVE_LETTERS
if ( !(p=strrchr(filepath, '\\')) )
if ( !(p=strrchr(filepath, ':')) )
#endif
{
return jnlib_xstrdup(".");
}
dirname_length = p-filepath;
dirname = jnlib_xmalloc(dirname_length+1);
strncpy(dirname, filepath, dirname_length);
dirname[dirname_length] = 0;
return dirname;
}
/****************
* Construct a filename from the NULL terminated list of parts.
* Tilde expansion is done here.
*/
char *
make_filename( const char *first_part, ... )
{
va_list arg_ptr ;
size_t n;
const char *s;
char *name, *home, *p;
va_start( arg_ptr, first_part ) ;
n = strlen(first_part)+1;
while( (s=va_arg(arg_ptr, const char *)) )
n += strlen(s) + 1;
va_end(arg_ptr);
home = NULL;
if( *first_part == '~' && first_part[1] == '/'
&& (home = getenv("HOME")) && *home )
n += strlen(home);
name = jnlib_xmalloc(n);
p = home ? stpcpy(stpcpy(name,home), first_part+1)
: stpcpy(name, first_part);
va_start( arg_ptr, first_part ) ;
while( (s=va_arg(arg_ptr, const char *)) )
p = stpcpy(stpcpy(p,"/"), s);
va_end(arg_ptr);
return name;
}
int
compare_filenames( const char *a, const char *b )
{
/* ? check whether this is an absolute filename and
* resolve symlinks?
*/
#ifdef HAVE_DRIVE_LETTERS
return stricmp(a,b);
#else
return strcmp(a,b);
#endif
}
/* Print a BUFFER to stream FP while replacing all control characters
and the character DELIM with standard C eescape sequences. Returns
the number of characters printed. */
size_t
print_sanitized_buffer (FILE *fp, const void *buffer, size_t length, int delim)
{
const unsigned char *p = buffer;
size_t count = 0;
for (; length; length--, p++, count++)
{
if (*p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim)
{
putc ('\\', fp);
count++;
if (*p == '\n')
putc ('n', fp);
else if (*p == '\r')
putc ('r', fp);
else if (*p == '\f')
putc ('f', fp);
else if (*p == '\v')
putc ('v', fp);
else if (*p == '\b')
putc ('b', fp);
else if (!*p)
putc('0', fp);
else
{
fprintf (fp, "x%02x", *p);
count += 2;
}
}
else
putc (*p, fp);
}
return count;
}
size_t
print_sanitized_utf8_buffer (FILE *fp, const void *buffer,
size_t length, int delim)
{
/* FIXME: convert to local characterset */
return print_sanitized_buffer (fp, buffer, length, delim);
}
size_t
print_sanitized_string (FILE *fp, const char *string, int delim)
{
return string? print_sanitized_buffer (fp, string, strlen (string), delim):0;
}
size_t
print_sanitized_utf8_string (FILE *fp, const char *string, int delim)
{
/* FIXME: convert to local characterset */
return print_sanitized_string (fp, string, delim);
}
/****************************************************
******** locale insensitive ctype functions ********
****************************************************/
/* FIXME: replace them by a table lookup and macros */
int
ascii_isupper (int c)
{
return c >= 'A' && c <= 'Z';
}
int
ascii_islower (int c)
{
return c >= 'a' && c <= 'z';
}
int
ascii_toupper (int c)
{
if (c >= 'a' && c <= 'z')
c &= ~0x20;
return c;
}
int
ascii_tolower (int c)
{
if (c >= 'A' && c <= 'Z')
c |= 0x20;
return c;
}
int
ascii_strcasecmp( const char *a, const char *b )
{
if (a == b)
return 0;
for (; *a && *b; a++, b++) {
if (*a != *b && ascii_toupper(*a) != ascii_toupper(*b))
break;
}
return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
}
int
ascii_memcasecmp( const char *a, const char *b, size_t n )
{
if (a == b)
return 0;
for ( ; n; n--, a++, b++ ) {
if( *a != *b && ascii_toupper (*a) != ascii_toupper (*b) )
return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
}
return 0;
}
int
ascii_strcmp( const char *a, const char *b )
{
if (a == b)
return 0;
for (; *a && *b; a++, b++) {
if (*a != *b )
break;
}
return *a == *b? 0 : (*(signed char *)a - *(signed char *)b);
}
void *
ascii_memcasemem (const void *haystack, size_t nhaystack,
const void *needle, size_t nneedle)
{
if (!nneedle)
return (void*)haystack; /* finding an empty needle is really easy */
if (nneedle <= nhaystack)
{
const unsigned char *a = haystack;
const unsigned char *b = a + nhaystack - nneedle;
for (; a <= b; a++)
{
if ( !ascii_memcasecmp (a, needle, nneedle) )
return (void *)a;
}
}
return NULL;
}
/*********************************************
********** missing string functions *********
*********************************************/
#ifndef HAVE_STPCPY
char *
stpcpy(char *a,const char *b)
{
while( *b )
*a++ = *b++;
*a = 0;
return (char*)a;
}
#endif
#ifndef HAVE_STRLWR
char *
strlwr(char *s)
{
char *p;
for(p=s; *p; p++ )
*p = tolower(*p);
return s;
}
#endif
#ifndef HAVE_STRCASECMP
int
strcasecmp( const char *a, const char *b )
{
for( ; *a && *b; a++, b++ ) {
if( *a != *b && toupper(*a) != toupper(*b) )
break;
}
return *(const byte*)a - *(const byte*)b;
}
#endif
/****************
* mingw32/cpd has a memicmp()
*/
#ifndef HAVE_MEMICMP
int
memicmp( const char *a, const char *b, size_t n )
{
for( ; n; n--, a++, b++ )
if( *a != *b && toupper(*(const byte*)a) != toupper(*(const byte*)b) )
return *(const byte *)a - *(const byte*)b;
return 0;
}
#endif

84
jnlib/stringhelp.h Normal file
View File

@ -0,0 +1,84 @@
/* stringhelp.h
* Copyright (C) 1998,1999,2000,2001 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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
*/
#ifndef LIBJNLIB_STRINGHELP_H
#define LIBJNLIB_STRINGHELP_H
#include "types.h"
const char *memistr( const char *buf, size_t buflen, const char *sub );
char *mem2str( char *, const void *, size_t);
char *trim_spaces( char *string );
char *trim_trailing_spaces( char *string );
unsigned int trim_trailing_chars( unsigned char *line, unsigned len,
const char *trimchars);
unsigned int trim_trailing_ws( unsigned char *line, unsigned len );
char *make_basename(const char *filepath);
char *make_dirname(const char *filepath);
char *make_filename( const char *first_part, ... );
int compare_filenames( const char *a, const char *b );
size_t print_sanitized_buffer (FILE *fp, const void *buffer, size_t length,
int delim);
size_t print_sanitized_utf8_buffer (FILE *fp, const void *buffer,
size_t length, int delim);
size_t print_sanitized_string (FILE *fp, const char *string, int delim);
size_t print_sanitized_utf8_string (FILE *fp, const char *string, int delim);
const char *ascii_memistr( const char *buf, size_t buflen, const char *sub );
int ascii_isupper (int c);
int ascii_islower (int c);
int ascii_toupper (int c);
int ascii_tolower (int c);
int ascii_strcasecmp( const char *a, const char *b );
int ascii_memcasecmp( const char *a, const char *b, size_t n );
void *ascii_memcasemem (const void *haystack, size_t nhaystack,
const void *needle, size_t nneedle);
#ifndef HAVE_MEMICMP
int memicmp( const char *a, const char *b, size_t n );
#endif
#ifndef HAVE_STPCPY
char *stpcpy(char *a,const char *b);
#endif
#ifndef HAVE_STRLWR
char *strlwr(char *a);
#endif
#ifndef HAVE_STRTOUL
#define strtoul(a,b,c) ((unsigned long)strtol((a),(b),(c)))
#endif
#ifndef HAVE_MEMMOVE
#define memmove(d, s, n) bcopy((s), (d), (n))
#endif
#ifndef HAVE_STRICMP
#define stricmp(a,b) strcasecmp( (a), (b) )
#endif
#ifndef STR
#define STR(v) #v
#endif
#define STR2(v) STR(v)
#endif /*LIBJNLIB_STRINGHELP_H*/

133
jnlib/strlist.c Normal file
View File

@ -0,0 +1,133 @@
/* strlist.c - string helpers
* Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include "libjnlib-config.h"
#include "strlist.h"
void
free_strlist( STRLIST sl )
{
STRLIST sl2;
for(; sl; sl = sl2 ) {
sl2 = sl->next;
jnlib_free(sl);
}
}
STRLIST
add_to_strlist( STRLIST *list, const char *string )
{
STRLIST sl;
sl = jnlib_xmalloc( sizeof *sl + strlen(string));
sl->flags = 0;
strcpy(sl->d, string);
sl->next = *list;
*list = sl;
return sl;
}
#if 0
/****************
* same as add_to_strlist() but if is_utf8 is *not* set a conversion
* to UTF8 is done
*/
STRLIST
add_to_strlist2( STRLIST *list, const char *string, int is_utf8 )
{
STRLIST sl;
if( is_utf8 )
sl = add_to_strlist( list, string );
else {
char *p = native_to_utf8( string );
sl = add_to_strlist( list, p );
m_free( p );
}
return sl;
}
#endif
STRLIST
append_to_strlist( STRLIST *list, const char *string )
{
STRLIST r, sl;
sl = jnlib_xmalloc( sizeof *sl + strlen(string));
sl->flags = 0;
strcpy(sl->d, string);
sl->next = NULL;
if( !*list )
*list = sl;
else {
for( r = *list; r->next; r = r->next )
;
r->next = sl;
}
return sl;
}
#if 0
STRLIST
append_to_strlist2( STRLIST *list, const char *string, int is_utf8 )
{
STRLIST sl;
if( is_utf8 )
sl = append_to_strlist( list, string );
else {
char *p = native_to_utf8( string );
sl = append_to_strlist( list, p );
m_free( p );
}
return sl;
}
#endif
STRLIST
strlist_prev( STRLIST head, STRLIST node )
{
STRLIST n;
for(n=NULL; head && head != node; head = head->next )
n = head;
return n;
}
STRLIST
strlist_last( STRLIST node )
{
if( node )
for( ; node->next ; node = node->next )
;
return node;
}

43
jnlib/strlist.h Normal file
View File

@ -0,0 +1,43 @@
/* strlist.h
* Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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
*/
#ifndef LIBJNLIB_STRLIST_H
#define LIBJNLIB_STRLIST_H
struct string_list {
struct string_list *next;
unsigned int flags;
char d[1];
};
typedef struct string_list *STRLIST;
void free_strlist( STRLIST sl );
STRLIST add_to_strlist( STRLIST *list, const char *string );
STRLIST add_to_strlist2( STRLIST *list, const char *string, int is_utf8 );
STRLIST append_to_strlist( STRLIST *list, const char *string );
STRLIST append_to_strlist2( STRLIST *list, const char *string, int is_utf8 );
STRLIST strlist_prev( STRLIST head, STRLIST node );
STRLIST strlist_last( STRLIST node );
#define FREE_STRLIST(a) do { free_strlist((a)); (a) = NULL ; } while(0)
#endif /*LIBJNLIB_STRLIST_H*/

101
jnlib/types.h Normal file
View File

@ -0,0 +1,101 @@
/* types.h
* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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
*/
#ifndef LIBJNLIB_TYPES_H
#define LIBJNLIB_TYPES_H
/* The AC_CHECK_SIZEOF() in configure fails for some machines.
* we provide some fallback values here */
#if !SIZEOF_UNSIGNED_SHORT
#undef SIZEOF_UNSIGNED_SHORT
#define SIZEOF_UNSIGNED_SHORT 2
#endif
#if !SIZEOF_UNSIGNED_INT
#undef SIZEOF_UNSIGNED_INT
#define SIZEOF_UNSIGNED_INT 4
#endif
#if !SIZEOF_UNSIGNED_LONG
#undef SIZEOF_UNSIGNED_LONG
#define SIZEOF_UNSIGNED_LONG 4
#endif
#include <sys/types.h>
#ifndef HAVE_BYTE_TYPEDEF
#undef byte /* maybe there is a macro with this name */
typedef unsigned char byte;
#define HAVE_BYTE_TYPEDEF
#endif
#ifndef HAVE_USHORT_TYPEDEF
#undef ushort /* maybe there is a macro with this name */
typedef unsigned short ushort;
#define HAVE_USHORT_TYPEDEF
#endif
#ifndef HAVE_ULONG_TYPEDEF
#undef ulong /* maybe there is a macro with this name */
typedef unsigned long ulong;
#define HAVE_ULONG_TYPEDEF
#endif
#ifndef HAVE_U16_TYPEDEF
#undef u16 /* maybe there is a macro with this name */
#if SIZEOF_UNSIGNED_INT == 2
typedef unsigned int u16;
#elif SIZEOF_UNSIGNED_SHORT == 2
typedef unsigned short u16;
#else
#error no typedef for u16
#endif
#define HAVE_U16_TYPEDEF
#endif
#ifndef HAVE_U32_TYPEDEF
#undef u32 /* maybe there is a macro with this name */
#if SIZEOF_UNSIGNED_INT == 4
typedef unsigned int u32;
#elif SIZEOF_UNSIGNED_LONG == 4
typedef unsigned long u32;
#else
#error no typedef for u32
#endif
#define HAVE_U32_TYPEDEF
#endif
#ifndef HAVE_U64_TYPEDEF
#undef u64 /* maybe there is a macro with this name */
#if SIZEOF_UNSIGNED_INT == 8
typedef unsigned int u64;
#define HAVE_U64_TYPEDEF
#elif SIZEOF_UNSIGNED_LONG == 8
typedef unsigned long u64;
#define HAVE_U64_TYPEDEF
#elif __GNUC__ >= 2 || defined(__SUNPRO_C)
typedef unsigned long long u64;
#define HAVE_U64_TYPEDEF
#endif
#endif
#endif /*LIBJNLIB_TYPES_H*/

88
jnlib/xmalloc.c Normal file
View File

@ -0,0 +1,88 @@
/* xmalloc.c - standard malloc wrappers
* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "libjnlib-config.h"
#include "xmalloc.h"
static void
out_of_core(void)
{
fputs("\nfatal: out of memory\n", stderr );
exit(2);
}
void *
xmalloc( size_t n )
{
void *p = malloc( n );
if( !p )
out_of_core();
return p;
}
void *
xrealloc( void *a, size_t n )
{
void *p = realloc( a, n );
if( !p )
out_of_core();
return p;
}
void *
xcalloc( size_t n, size_t m )
{
void *p = calloc( n, m );
if( !p )
out_of_core();
return p;
}
char *
xstrdup( const char *string )
{
void *p = xmalloc( strlen(string)+1 );
strcpy( p, string );
return p;
}
char *
xstrcat2( const char *a, const char *b )
{
size_t n1;
char *p;
if( !b )
return xstrdup( a );
n1 = strlen(a);
p = xmalloc( n1 + strlen(b) + 1 );
memcpy(p, a, n1 );
strcpy(p+n1, b );
return p;
}

31
jnlib/xmalloc.h Normal file
View File

@ -0,0 +1,31 @@
/* xmalloc.h
* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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
*/
#ifndef LIBJNLIB_XMALLOC_H
#define LIBJNLIB_XMALLOC_H
void *xmalloc( size_t n );
void *xrealloc( void *a, size_t n );
void *xcalloc( size_t n, size_t m );
char *xstrdup( const char *string );
char *xstrcat2( const char *a, const char *b );
#endif /*LIBJNLIB_XMALLOC_H*/