diff options
Diffstat (limited to 'jnlib')
| -rw-r--r-- | jnlib/ChangeLog | 41 | ||||
| -rw-r--r-- | jnlib/README | 7 | ||||
| -rw-r--r-- | jnlib/argparse.c | 995 | ||||
| -rw-r--r-- | jnlib/argparse.h | 67 | ||||
| -rw-r--r-- | jnlib/dotlock.c | 346 | ||||
| -rw-r--r-- | jnlib/dotlock.h | 32 | ||||
| -rw-r--r-- | jnlib/libjnlib-config.h | 75 | ||||
| -rw-r--r-- | jnlib/logging.c | 257 | ||||
| -rw-r--r-- | jnlib/logging.h | 47 | ||||
| -rw-r--r-- | jnlib/mischelp.h | 43 | ||||
| -rw-r--r-- | jnlib/stringhelp.c | 323 | ||||
| -rw-r--r-- | jnlib/stringhelp.h | 65 | ||||
| -rw-r--r-- | jnlib/types.h | 101 | ||||
| -rw-r--r-- | jnlib/xmalloc.c | 88 | ||||
| -rw-r--r-- | jnlib/xmalloc.h | 31 | 
15 files changed, 2518 insertions, 0 deletions
| diff --git a/jnlib/ChangeLog b/jnlib/ChangeLog new file mode 100644 index 00000000..ed5e20a4 --- /dev/null +++ b/jnlib/ChangeLog @@ -0,0 +1,41 @@ +2000-07-26 10:02:51  Werner Koch  ([email protected]) + +  * 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  ([email protected]) + +  * Makefile.am: Replaced second logging.c by .h + +2000-05-24 08:58:15  Werner Koch  ([email protected]) + +  * logging.c (log_get_errorcount): New. + +2000-05-24 08:44:47  Werner Koch  ([email protected]) + +  * stringhelp.c: Added a few filename related helper functions. + +2000-05-11 18:04:43  Werner Koch  ([email protected]) + +  * xmalloc.c (xstrcat2):  Replaced stpcpy to quickly address W32 +    problems. + +2000-05-02 19:43:38  Werner Koch  ([email protected]) + +  * xmalloc.c (xstrcat2): New. + +Mon Jan 24 13:04:28 CET 2000  Werner Koch  <[email protected]> + +  * 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. + diff --git a/jnlib/README b/jnlib/README new file mode 100644 index 00000000..e49ef445 --- /dev/null +++ b/jnlib/README @@ -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. + diff --git a/jnlib/argparse.c b/jnlib/argparse.c new file mode 100644 index 00000000..0384c5d2 --- /dev/null +++ b/jnlib/argparse.c @@ -0,0 +1,995 @@ +/* [argparse.c wk 17.06.97] Argument Parser for option handling + *	Copyright (C) 1998, 1999, 2000 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 & 8) ) /* no argument */ +		    arg->r_opt = -3;	       /* error */ +		else			       /* no or optional argument */ +		    arg->r_type = 0;	       /* okay */ +		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) 2000 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 ****/ diff --git a/jnlib/argparse.h b/jnlib/argparse.h new file mode 100644 index 00000000..3668a21c --- /dev/null +++ b/jnlib/argparse.h @@ -0,0 +1,67 @@ +/* argparse.h + *	Copyright (C) 1998,1999 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*/ diff --git a/jnlib/dotlock.c b/jnlib/dotlock.c new file mode 100644 index 00000000..8e61f7a0 --- /dev/null +++ b/jnlib/dotlock.c @@ -0,0 +1,346 @@ +/* dotlock.c - dotfile locking + *	Copyright (C) 1998,2000 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 +} + diff --git a/jnlib/dotlock.h b/jnlib/dotlock.h new file mode 100644 index 00000000..d54219e2 --- /dev/null +++ b/jnlib/dotlock.h @@ -0,0 +1,32 @@ +/* dotlock.h + *	Copyright (C) 2000 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*/ diff --git a/jnlib/libjnlib-config.h b/jnlib/libjnlib-config.h new file mode 100644 index 00000000..4cc57b29 --- /dev/null +++ b/jnlib/libjnlib-config.h @@ -0,0 +1,75 @@ +/* libjnlib-config.h - local configuration of the jnlib functions + *	Copyright (C) 2000 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 "xmalloc.h" +#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)    xmalloc( (a) ) +#define jnlib_xcalloc(a,b)  xcalloc( (a), (b) ) +#define jnlib_xrealloc(a,n) xrealloc( (a), (n) ) +#define jnlib_xstrdup(a)    xstrdup( (a) ) +#define jnlib_free(a)	    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*/ + diff --git a/jnlib/logging.c b/jnlib/logging.c new file mode 100644 index 00000000..7ab2cb57 --- /dev/null +++ b/jnlib/logging.c @@ -0,0 +1,257 @@ +/* logging.c -	useful logging functions + *	Copyright (C) 1998, 1999, 2000 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> +#ifdef __MINGW32__ +  #include <io.h> +#endif + +#include "libjnlib-config.h" +#include "logging.h" + +enum my_log_levels { +    MY_LOG_BEGIN,  /* only print the timestamp if configured */ +    MY_LOG_CONT, +    MY_LOG_INFO, +    MY_LOG_WARN, +    MY_LOG_ERROR, +    MY_LOG_FATAL, +    MY_LOG_BUG, +    MY_LOG_DEBUG +}; + +static FILE *logstream; +static int use_time; +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 ) +	fclose( logstream ); +    logstream = fp; +    use_time = fp != stderr; +    missing_lf = 0; +} + + +int +log_get_fd() +{ +    return fileno(logstream?logstream:stderr); +} + +static void +do_logv( int level, const char *fmt, va_list arg_ptr ) +{ +    if( !logstream ) +	logstream = stderr; + +    if( missing_lf && level != MY_LOG_CONT ) +	putc('\n', logstream ); +    missing_lf = 0; + +    if( use_time && level != MY_LOG_CONT ) { +	/* Note this does not work for multiple line logging as we would +	 * need to print to a buffer first */ +	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 ); +    } + +    switch ( level ) { +      case MY_LOG_BEGIN: break; +      case MY_LOG_CONT: break; +      case MY_LOG_INFO: break; +      case MY_LOG_WARN: break; +      case MY_LOG_ERROR: break; +      case MY_LOG_FATAL: fputs("Fatal: ",logstream ); break; +      case MY_LOG_BUG: fputs("Ohhhh jeeee: ", logstream); break; +      case MY_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 == MY_LOG_FATAL ) +	exit(2); +    if( level == MY_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_info( const char *fmt, ... ) +{ +    va_list arg_ptr ; + +    va_start( arg_ptr, fmt ) ; +    do_logv( MY_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( MY_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( MY_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( MY_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( MY_LOG_DEBUG, fmt, arg_ptr ); +    va_end(arg_ptr); +} + + +void +log_printf( const char *fmt, ... ) +{ +    va_list arg_ptr ; + +    if( !fmt ) { +	do_logv( MY_LOG_BEGIN, NULL, NULL ); +    } +    else { +	va_start( arg_ptr, fmt ) ; +	do_logv( MY_LOG_CONT, fmt, arg_ptr ); +	va_end(arg_ptr); +    } +} + + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) +void +bug_at( const char *file, int line, const char *func ) +{ +    do_log( MY_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( MY_LOG_BUG, +	     _("you found a bug ... (%s:%d)\n"), file, line); +    abort(); /* never called, but it makes the compiler happy */ +} +#endif + diff --git a/jnlib/logging.h b/jnlib/logging.h new file mode 100644 index 00000000..5084b71b --- /dev/null +++ b/jnlib/logging.h @@ -0,0 +1,47 @@ +/* logging.h + *	Copyright (C) 1999, 2000 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 ); +int  log_get_fd(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 + +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); + + +#endif /*LIBJNLIB_LOGGING_H*/ diff --git a/jnlib/mischelp.h b/jnlib/mischelp.h new file mode 100644 index 00000000..684a6973 --- /dev/null +++ b/jnlib/mischelp.h @@ -0,0 +1,43 @@ +/* mischelp.h + *	Copyright (C) 1999 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*/ diff --git a/jnlib/stringhelp.c b/jnlib/stringhelp.c new file mode 100644 index 00000000..59345f27 --- /dev/null +++ b/jnlib/stringhelp.c @@ -0,0 +1,323 @@ +/* stringhelp.c -  standard string helper functions + *	Copyright (C) 1998, 1999 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 +} + + +/********************************************* + ********** 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 + + + diff --git a/jnlib/stringhelp.h b/jnlib/stringhelp.h new file mode 100644 index 00000000..ebdd7b27 --- /dev/null +++ b/jnlib/stringhelp.h @@ -0,0 +1,65 @@ +/* stringhelp.h + *	Copyright (C) 1998,1999 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 ); + +#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*/ diff --git a/jnlib/types.h b/jnlib/types.h new file mode 100644 index 00000000..a5d0e42d --- /dev/null +++ b/jnlib/types.h @@ -0,0 +1,101 @@ +/* types.h + *	Copyright (C) 1999, 2000 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*/ diff --git a/jnlib/xmalloc.c b/jnlib/xmalloc.c new file mode 100644 index 00000000..34ecc28a --- /dev/null +++ b/jnlib/xmalloc.c @@ -0,0 +1,88 @@ +/* xmalloc.c -	standard malloc wrappers + *	Copyright (C) 1999 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; +} + diff --git a/jnlib/xmalloc.h b/jnlib/xmalloc.h new file mode 100644 index 00000000..4dd88ec2 --- /dev/null +++ b/jnlib/xmalloc.h @@ -0,0 +1,31 @@ +/* xmalloc.h + *	Copyright (C) 1999 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*/ | 
