1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

See ChangeLog: Mon Jan 24 13:04:28 CET 2000 Werner Koch

This commit is contained in:
Werner Koch 2000-01-24 11:55:49 +00:00
parent 704eb738c0
commit 0070faa0ff
88 changed files with 887 additions and 3998 deletions

View file

@ -1,3 +1,19 @@
Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de>
* memory.c: Removed
* secmem.c: Moved to ../gcrypt.
* argparse.c argparse.h logging.c logging.h
mischelp.h stringhelp.c stringhelp.h xmalloc.c
xmalloc.h dotlock.c: Moved to ../jnlib
* libutil-config.h: Removed.
* logging.c (log_set_file): New.
(log_printf): New.
(do_logv): Add kludge to insert LFs.
* Replaced all m_ memory fucntions by gcry_ ones.
* README: New.
Fri Dec 31 12:48:31 CET 1999 Werner Koch <wk@gnupg.de>
* memory.c (m_is_secure): New.

View file

@ -1,21 +1,14 @@
## Process this file with automake to produce Makefile.in
# Those 2 files are in the CVS but currently not used.
EXTRA_DIST = xmalloc.c xmalloc.h logging.c logging.c
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl
EXTRA_DIST = README
noinst_LTLIBRARIES = libutil.la
libutil_la_LDFLAGS =
libutil_la_SOURCES = logger.c fileutil.c miscutil.c strgutil.c \
ttyio.c memory.c secmem.c errors.c iobuf.c \
dotlock.c http.c simple-gettext.c \
libutil-config.h \
mischelp.h \
stringhelp.h stringhelp.c \
argparse.h argparse.c
ttyio.c errors.c iobuf.c \
http.c simple-gettext.c
http-test: http.c

7
util/README Normal file
View file

@ -0,0 +1,7 @@
Here you find supporting code for GnuPG and the tools. It needs some
support from libgcrypt.
util is not a good name, so at some time we should rename the whole source
tree. However this is not easy for CVS and diff reasons.

View file

@ -1,996 +0,0 @@
/* [argparse.c wk 17.06.97] Argument Parser for option handling
* 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 <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "libutil-config.h"
#include "mischelp.h"
#include "stringhelp.h"
#ifndef LIBUTIL_CONFIG_OF_GNUPG
#include "logging.h" /* currently not used in GnUPG */
#endif
#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 )
libutil_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";
libutil_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";
libutil_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 = m_alloc( 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 ) {
libutil_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 = libutil_strdup(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) )
libutil_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 = libutil_realloc(buffer, buflen);
buffer[i++] = c;
}
}
else if( i < DIM(keyword)-1 )
keyword[i++] = c;
else {
buflen = DIM(keyword)+50;
buffer = libutil_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) 1999 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 ****/

View file

@ -1,64 +0,0 @@
/* 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 LIBUTIL_ARGPARSE_H
#define LIBUTIL_ARGPARSE_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;
ulong 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 /*LIBUTIL_ARGPARSE_H*/

View file

@ -1,346 +0,0 @@
/* dotlock.c - dotfile locking
* Copyright (C) 1998 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 "types.h"
#include "util.h"
#include "memory.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 = m_alloc_clear( 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 = m_alloc( 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));
m_free(h->tname);
m_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);
m_free(h->tname);
m_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);
m_free(h->tname);
m_free(h);
return NULL;
}
#ifdef _REENTRANT
/* release mutex */
#endif
#endif /* !HAVE_DOSISH_SYSTEM */
h->lockname = m_alloc( 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);
m_free(h->tname);
m_free(h->lockname);
m_free(h);
h = h2;
}
#endif
}

View file

@ -45,10 +45,10 @@ make_basename(const char *filepath)
if ( !(p=strrchr(filepath, ':')) )
#endif
{
return m_strdup(filepath);
return gcry_xstrdup(filepath);
}
return m_strdup(p+1);
return gcry_xstrdup(p+1);
}
@ -72,11 +72,11 @@ make_dirname(const char *filepath)
if ( !(p=strrchr(filepath, ':')) )
#endif
{
return m_strdup(".");
return gcry_xstrdup(".");
}
dirname_length = p-filepath;
dirname = m_alloc(dirname_length+1);
dirname = gcry_xmalloc(dirname_length+1);
strncpy(dirname, filepath, dirname_length);
dirname[dirname_length] = 0;
@ -108,7 +108,7 @@ make_filename( const char *first_part, ... )
&& (home = getenv("HOME")) && *home )
n += strlen(home);
name = m_alloc(n);
name = gcry_xmalloc(n);
p = home ? stpcpy(stpcpy(name,home), first_part+1)
: stpcpy(name, first_part);
va_start( arg_ptr, first_part ) ;

View file

@ -175,7 +175,7 @@ http_close( HTTP_HD hd )
iobuf_close( hd->fp_read );
iobuf_close( hd->fp_write );
release_parsed_uri( hd->uri );
m_free( hd->buffer );
gcry_free( hd->buffer );
hd->initialized = 0;
}
@ -189,7 +189,7 @@ http_close( HTTP_HD hd )
static int
parse_uri( PARSED_URI *ret_uri, const char *uri )
{
*ret_uri = m_alloc_clear( sizeof(**ret_uri) + strlen(uri) );
*ret_uri = gcry_xcalloc( 1, sizeof(**ret_uri) + strlen(uri) );
strcpy( (*ret_uri)->buffer, uri );
return do_parse_uri( *ret_uri, 0 );
}
@ -203,9 +203,9 @@ release_parsed_uri( PARSED_URI uri )
for( r = uri->query; r; r = r2 ) {
r2 = r->next;
m_free( r );
gcry_free( r );
}
m_free( uri );
gcry_free( uri );
}
}
@ -397,7 +397,7 @@ parse_tuple( byte *string )
return NULL; /* bad URI */
if( n != strlen( p ) )
return NULL; /* name with a Nul in it */
tuple = m_alloc_clear( sizeof *tuple );
tuple = gcry_xcalloc( 1, sizeof *tuple );
tuple->name = p;
if( !p2 ) {
/* we have only the name, so we assume an empty value string */
@ -406,7 +406,7 @@ parse_tuple( byte *string )
}
else { /* name and value */
if( (n = remove_escapes( p2 )) < 0 ) {
m_free( tuple );
gcry_free( tuple );
return NULL; /* bad URI */
}
tuple->value = p2;
@ -436,16 +436,16 @@ send_request( HTTP_HD hd )
return G10ERR_NETWORK;
p = build_rel_path( hd->uri );
request = m_alloc( strlen(p) + 20 );
request = gcry_xmalloc( strlen(p) + 20 );
sprintf( request, "%s %s%s HTTP/1.0\r\n",
hd->req_type == HTTP_REQ_GET ? "GET" :
hd->req_type == HTTP_REQ_HEAD? "HEAD":
hd->req_type == HTTP_REQ_POST? "POST": "OOPS",
*p == '/'? "":"/", p );
m_free(p);
gcry_free(p);
rc = write_server( hd->sock, request, strlen(request) );
m_free( request );
gcry_free( request );
return rc;
}
@ -476,7 +476,7 @@ build_rel_path( PARSED_URI uri )
n++;
/* now allocate and copy */
p = rel_path = m_alloc( n );
p = rel_path = gcry_xmalloc( n );
n = insert_escapes( p, uri->path, "%;?&" );
p += n;
/* todo: add params */

View file

@ -132,7 +132,7 @@ file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
fclose(fp);
}
fp = NULL;
m_free(a); /* we can free our context now */
gcry_free(a); /* we can free our context now */
}
return rc;
@ -267,7 +267,7 @@ block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
if( nbytes < OP_MIN_PARTIAL_CHUNK ) {
/* not enough to write a partial block out; so we store it*/
if( !a->buffer )
a->buffer = m_alloc( OP_MIN_PARTIAL_CHUNK );
a->buffer = gcry_xmalloc( OP_MIN_PARTIAL_CHUNK );
memcpy( a->buffer + a->buflen, buf, size );
a->buflen += size;
}
@ -305,7 +305,7 @@ block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
assert( !a->buflen );
assert( nbytes < OP_MIN_PARTIAL_CHUNK );
if( !a->buffer )
a->buffer = m_alloc( OP_MIN_PARTIAL_CHUNK );
a->buffer = gcry_xmalloc( OP_MIN_PARTIAL_CHUNK );
memcpy( a->buffer, p, nbytes );
a->buflen = nbytes;
}
@ -393,7 +393,7 @@ block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
log_error("block_filter: write error: %s\n",strerror(errno));
rc = G10ERR_WRITE_FILE;
}
m_free( a->buffer ); a->buffer = NULL; a->buflen = 0;
gcry_free( a->buffer ); a->buffer = NULL; a->buflen = 0;
}
else {
iobuf_writebyte(chain, 0);
@ -405,7 +405,7 @@ block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
}
if( DBG_IOBUF )
log_debug("free block_filter %p\n", a );
m_free(a); /* we can free our context now */
gcry_free(a); /* we can free our context now */
}
return rc;
@ -449,9 +449,9 @@ iobuf_alloc(int use, size_t bufsize)
IOBUF a;
static int number=0;
a = m_alloc_clear(sizeof *a);
a = gcry_xcalloc( 1,sizeof *a);
a->use = use;
a->d.buf = m_alloc( bufsize );
a->d.buf = gcry_xmalloc( bufsize );
a->d.size = bufsize;
a->no = ++number;
a->subno = 0;
@ -470,7 +470,7 @@ iobuf_close( IOBUF a )
if( a && a->directfp ) {
fclose( a->directfp );
m_free( a->real_fname );
gcry_free( a->real_fname );
if( DBG_IOBUF )
log_debug("iobuf_close -> %p\n", a->directfp );
return 0;
@ -486,9 +486,9 @@ iobuf_close( IOBUF a )
if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE,
a->chain, NULL, &dummy_len)) )
log_error("IOBUFCTRL_FREE failed on close: %s\n", g10_errstr(rc) );
m_free(a->real_fname);
m_free(a->d.buf);
m_free(a);
gcry_free(a->real_fname);
gcry_free(a->d.buf);
gcry_free(a);
}
return rc;
}
@ -556,12 +556,12 @@ iobuf_open( const char *fname )
else if( !(fp = fopen(fname, "rb")) )
return NULL;
a = iobuf_alloc(1, 8192 );
fcx = m_alloc( sizeof *fcx + strlen(fname) );
fcx = gcry_xmalloc( sizeof *fcx + strlen(fname) );
fcx->fp = fp;
fcx->print_only_name = print_only;
strcpy(fcx->fname, fname );
if( !print_only )
a->real_fname = m_strdup( fname );
a->real_fname = gcry_xstrdup( fname );
a->filter = file_filter;
a->filter_ov = fcx;
file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
@ -588,7 +588,7 @@ iobuf_fdopen( int fd, const char *mode )
if( !(fp = fdopen(fd, mode)) )
return NULL;
a = iobuf_alloc( strchr( mode, 'w')? 2:1, 8192 );
fcx = m_alloc( sizeof *fcx + 20 );
fcx = gcry_xmalloc( sizeof *fcx + 20 );
fcx->fp = fp;
fcx->print_only_name = 1;
sprintf(fcx->fname, "[fd %d]", fd );
@ -622,12 +622,12 @@ iobuf_create( const char *fname )
else if( !(fp = fopen(fname, "wb")) )
return NULL;
a = iobuf_alloc(2, 8192 );
fcx = m_alloc( sizeof *fcx + strlen(fname) );
fcx = gcry_xmalloc( sizeof *fcx + strlen(fname) );
fcx->fp = fp;
fcx->print_only_name = print_only;
strcpy(fcx->fname, fname );
if( !print_only )
a->real_fname = m_strdup( fname );
a->real_fname = gcry_xstrdup( fname );
a->filter = file_filter;
a->filter_ov = fcx;
file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
@ -655,10 +655,10 @@ iobuf_append( const char *fname )
else if( !(fp = fopen(fname, "ab")) )
return NULL;
a = iobuf_alloc(2, 8192 );
fcx = m_alloc( sizeof *fcx + strlen(fname) );
fcx = gcry_xmalloc( sizeof *fcx + strlen(fname) );
fcx->fp = fp;
strcpy(fcx->fname, fname );
a->real_fname = m_strdup( fname );
a->real_fname = gcry_xstrdup( fname );
a->filter = file_filter;
a->filter_ov = fcx;
file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
@ -682,10 +682,10 @@ iobuf_openrw( const char *fname )
else if( !(fp = fopen(fname, "r+b")) )
return NULL;
a = iobuf_alloc(2, 8192 );
fcx = m_alloc( sizeof *fcx + strlen(fname) );
fcx = gcry_xmalloc( sizeof *fcx + strlen(fname) );
fcx->fp = fp;
strcpy(fcx->fname, fname );
a->real_fname = m_strdup( fname );
a->real_fname = gcry_xstrdup( fname );
a->filter = file_filter;
a->filter_ov = fcx;
file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
@ -719,7 +719,7 @@ iobuf_fopen( const char *fname, const char *mode )
return NULL;
a = iobuf_alloc(1, 8192 );
a->directfp = fp;
a->real_fname = m_strdup( fname );
a->real_fname = gcry_xstrdup( fname );
if( DBG_IOBUF )
log_debug("iobuf_fopen -> %p\n", a->directfp );
@ -760,12 +760,12 @@ iobuf_push_filter2( IOBUF a,
* The contents of the buffers are transferred to the
* new stream.
*/
b = m_alloc(sizeof *b);
b = gcry_xmalloc(sizeof *b);
memcpy(b, a, sizeof *b );
/* fixme: it is stupid to keep a copy of the name at every level
* but we need the name somewhere because the name known by file_filter
* may have been released when we need the name of the file */
b->real_fname = a->real_fname? m_strdup(a->real_fname):NULL;
b->real_fname = a->real_fname? gcry_xstrdup(a->real_fname):NULL;
/* remove the filter stuff from the new stream */
a->filter = NULL;
a->filter_ov = NULL;
@ -775,12 +775,12 @@ iobuf_push_filter2( IOBUF a,
a->use = 2; /* make a write stream from a temp stream */
if( a->use == 2 ) { /* allocate a fresh buffer for the original stream */
b->d.buf = m_alloc( a->d.size );
b->d.buf = gcry_xmalloc( a->d.size );
b->d.len = 0;
b->d.start = 0;
}
else { /* allocate a fresh buffer for the new stream */
a->d.buf = m_alloc( a->d.size );
a->d.buf = gcry_xmalloc( a->d.size );
a->d.len = 0;
a->d.start = 0;
}
@ -831,10 +831,10 @@ pop_filter( IOBUF a, int (*f)(void *opaque, int control,
if( !a->filter ) { /* this is simple */
b = a->chain;
assert(b);
m_free(a->d.buf);
m_free(a->real_fname);
gcry_free(a->d.buf);
gcry_free(a->real_fname);
memcpy(a,b, sizeof *a);
m_free(b);
gcry_free(b);
return 0;
}
for(b=a ; b; b = b->chain )
@ -855,7 +855,7 @@ pop_filter( IOBUF a, int (*f)(void *opaque, int control,
return rc;
}
if( b->filter_ov && b->filter_ov_owner ) {
m_free( b->filter_ov );
gcry_free( b->filter_ov );
b->filter_ov = NULL;
}
@ -868,10 +868,10 @@ pop_filter( IOBUF a, int (*f)(void *opaque, int control,
* a flush has been done on the to be removed entry
*/
b = a->chain;
m_free(a->d.buf);
m_free(a->real_fname);
gcry_free(a->d.buf);
gcry_free(a->real_fname);
memcpy(a,b, sizeof *a);
m_free(b);
gcry_free(b);
if( DBG_IOBUF )
log_debug("iobuf-%d.%d: popped filter\n", a->no, a->subno );
}
@ -906,10 +906,10 @@ underflow(IOBUF a)
if( DBG_IOBUF )
log_debug("iobuf-%d.%d: pop `%s' in underflow\n",
a->no, a->subno, a->desc );
m_free(a->d.buf);
m_free(a->real_fname);
gcry_free(a->d.buf);
gcry_free(a->real_fname);
memcpy(a, b, sizeof *a);
m_free(b);
gcry_free(b);
print_chain(a);
}
else
@ -962,7 +962,7 @@ underflow(IOBUF a)
NULL, &dummy_len)) )
log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) );
if( a->filter_ov && a->filter_ov_owner ) {
m_free( a->filter_ov );
gcry_free( a->filter_ov );
a->filter_ov = NULL;
}
a->filter = NULL;
@ -975,10 +975,10 @@ underflow(IOBUF a)
log_debug("iobuf-%d.%d: pop `%s' in underflow (!len)\n",
a->no, a->subno, a->desc );
print_chain(a);
m_free(a->d.buf);
m_free(a->real_fname);
gcry_free(a->d.buf);
gcry_free(a->real_fname);
memcpy(a,b, sizeof *a);
m_free(b);
gcry_free(b);
print_chain(a);
}
}
@ -1019,9 +1019,9 @@ iobuf_flush(IOBUF a)
log_debug("increasing temp iobuf from %lu to %lu\n",
(ulong)a->d.size, (ulong)newsize );
newbuf = m_alloc( newsize );
newbuf = gcry_xmalloc( newsize );
memcpy( newbuf, a->d.buf, a->d.len );
m_free(a->d.buf);
gcry_free(a->d.buf);
a->d.buf = newbuf;
a->d.size = newsize;
return 0;
@ -1057,7 +1057,7 @@ iobuf_readbyte(IOBUF a)
if( a->unget.buf ) {
if( a->unget.start < a->unget.len )
return a->unget.buf[a->unget.start++];
m_free(a->unget.buf);
gcry_free(a->unget.buf);
a->unget.buf = NULL;
a->nofast &= ~2;
}
@ -1401,7 +1401,7 @@ iobuf_get_fname( IOBUF a )
void
iobuf_set_block_mode( IOBUF a, size_t n )
{
block_filter_ctx_t *ctx = m_alloc_clear( sizeof *ctx );
block_filter_ctx_t *ctx = gcry_xcalloc( 1, sizeof *ctx );
assert( a->use == 1 || a->use == 2 );
ctx->use = a->use;
@ -1423,7 +1423,7 @@ iobuf_set_block_mode( IOBUF a, size_t n )
void
iobuf_set_partial_block_mode( IOBUF a, size_t len )
{
block_filter_ctx_t *ctx = m_alloc_clear( sizeof *ctx );
block_filter_ctx_t *ctx = gcry_xcalloc( 1, sizeof *ctx );
assert( a->use == 1 || a->use == 2 );
ctx->use = a->use;
@ -1478,7 +1478,7 @@ iobuf_read_line( IOBUF a, byte **addr_of_buffer,
if( !buffer ) { /* must allocate a new buffer */
length = 256;
buffer = m_alloc( length );
buffer = gcry_xmalloc( length );
*addr_of_buffer = buffer;
*length_of_buffer = length;
}
@ -1498,7 +1498,7 @@ iobuf_read_line( IOBUF a, byte **addr_of_buffer,
}
length += 3; /* correct for the reserved byte */
length += length < 1024? 256 : 1024;
buffer = m_realloc( buffer, length );
buffer = gcry_xrealloc( buffer, length );
*addr_of_buffer = buffer;
*length_of_buffer = length;
length -= 3; /* and reserve again */

View file

@ -1,56 +0,0 @@
/* libutil-config.h - configuration of the libutil functions
* 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
*/
/****************
* This header is to be included only by the files in this directory
* it should not be used by other modules.
*/
#ifndef LIBUTIL_CONFIG_H
#define LIBUTIL_CONFIG_H
#define LIBUTIL_CONFIG_OF_GNUPG 1 /* currently we need this kludge */
#include <sys/types.h>
#ifndef HAVE_BYTE_TYPEDEF
#undef byte /* (this matches the test used by configure) */
typedef unsigned char byte;
#define HAVE_BYTE_TYPEDEF
#endif
#include "types.h"
#include "memory.h"
#include "util.h"
#include "i18n.h"
#define libutil_xmalloc(a) m_alloc( (a) )
#define libutil_realloc(a,n) m_realloc( (a), (n) )
#define libutil_strdup(a) m_strdup( (a) )
#define libutil_free(a) m_free( (a) )
#define libutil_log_debug log_debug
#define libutil_log_info log_info
#define libutil_log_error log_error
#define libutil_log_fatal log_fatal
#define libutil_log_bug log_bug
#endif /*LIBUTIL_CONFIGH*/

View file

@ -69,9 +69,9 @@ log_stream()
void
log_set_name( const char *name )
{
m_free(pgm_name);
gcry_free(pgm_name);
if( name )
pgm_name = m_strdup(name);
pgm_name = gcry_xstrdup(name);
else
pgm_name = NULL;
}

View file

@ -1,170 +0,0 @@
/* logging.c - useful logging 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
*/
/* This file should replace logger.c in the future - for now it is not
* used GnuPG.
* 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 "libutil-config.h"
#include "logging.h"
enum my_log_levels {
MY_LOG_CONT,
MY_LOG_INFO,
MY_LOG_WARN,
MY_LOG_ERROR,
MY_LOG_FATAL,
MY_LOG_BUG,
MY_LOG_DEBUG
};
#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
static void
do_logv( int level, const char *fmt, va_list arg_ptr )
{
switch ( level ) {
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: ",stderr ); break;
case MY_LOG_BUG: fputs("Ohhhh jeeee: ", stderr); break;
case MY_LOG_DEBUG: fputs("DBG: ", stderr ); break;
default: fprintf(stderr,"[Unknown log level %d]: ", level ); break;
}
vfprintf(stderr,fmt,arg_ptr) ;
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);
}
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, bugs 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);
}
#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

View file

@ -1,41 +0,0 @@
/* logging.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 LIBUTIL_LOGGING_H
#define LIBUTIL_LOGGING_H
#include "mischelp.h"
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
void bug_at( const char *file, int line, const char *func ) LIBUTIL_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, ... ) LIBUTIL_GCC_A_NR_PRINTF(1,2);
void log_fatal( const char *fmt, ... ) LIBUTIL_GCC_A_NR_PRINTF(1,2);
void log_error( const char *fmt, ... ) LIBUTIL_GCC_A_PRINTF(1,2);
void log_info( const char *fmt, ... ) LIBUTIL_GCC_A_PRINTF(1,2);
void log_debug( const char *fmt, ... ) LIBUTIL_GCC_A_PRINTF(1,2);
#endif /*LIBUTIL_LOGGING_H*/

View file

@ -1,651 +0,0 @@
/* memory.c - memory allocation
* Copyright (C) 1998 Free Software Foundation, Inc.
*
* We use our own memory allocation functions instead of plain malloc(),
* so that we can provide some special enhancements:
* a) functions to provide memory from a secure memory.
* b) by looking at the requested allocation size we
* can reuse memory very quickly (e.g. MPI storage)
* (really needed?)
* c) memory usage reporting if compiled with M_DEBUG
* d) memory checking if compiled with M_GUARD
*
* 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 <string.h>
#include <stdarg.h>
#include "types.h"
#include "memory.h"
#include "util.h"
/* FXIME: ugly hack. Need a prototype here but can't include g10lib.h */
int g10_private_is_secure( const void *p );
#define MAGIC_NOR_BYTE 0x55
#define MAGIC_SEC_BYTE 0xcc
#define MAGIC_END_BYTE 0xaa
#if SIZEOF_UNSIGNED_LONG == 8
#define EXTRA_ALIGN 4
#else
#define EXTRA_ALIGN 0
#endif
#if defined(M_DEBUG) || defined(M_GUARD)
static void membug( const char *fmt, ... );
#endif
#ifdef M_DEBUG
#ifndef M_GUARD
#define M_GUARD 1
#endif
#undef m_alloc
#undef m_alloc_clear
#undef m_alloc_secure
#undef m_alloc_secure_clear
#undef m_realloc
#undef m_free
#undef m_check
#undef m_strdup
#define FNAME(a) m_debug_ ##a
#define FNAMEPRT , const char *info
#define FNAMEARG , info
#define store_len(p,n,m) do { add_entry(p,n,m, \
info, __FUNCTION__); } while(0)
#else
#define FNAME(a) m_ ##a
#define FNAMEPRT
#define FNAMEARG
#define store_len(p,n,m) do { ((byte*)p)[EXTRA_ALIGN+0] = n; \
((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ; \
((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ; \
((byte*)p)[EXTRA_ALIGN+3] = m? MAGIC_SEC_BYTE \
: MAGIC_NOR_BYTE; \
} while(0)
#endif
#ifdef M_GUARD
static long used_memory;
#endif
#ifdef M_DEBUG /* stuff used for memory debuging */
struct info_entry {
struct info_entry *next;
unsigned count; /* call count */
const char *info; /* the reference to the info string */
};
struct memtbl_entry {
const void *user_p; /* for reference: the pointer given to the user */
size_t user_n; /* length requested by the user */
struct memtbl_entry *next; /* to build a list of unused entries */
const struct info_entry *info; /* points into the table with */
/* the info strings */
unsigned inuse:1; /* this entry is in use */
unsigned count:31;
};
#define INFO_BUCKETS 53
#define info_hash(p) ( *(u32*)((p)) % INFO_BUCKETS )
static struct info_entry *info_strings[INFO_BUCKETS]; /* hash table */
static struct memtbl_entry *memtbl; /* the table with the memory info */
static unsigned memtbl_size; /* number of allocated entries */
static unsigned memtbl_len; /* number of used entries */
static struct memtbl_entry *memtbl_unused;/* to keep track of unused entries */
static void dump_table_at_exit(void);
static void dump_table(void);
static void check_allmem( const char *info );
/****************
* Put the new P into the debug table and return a pointer to the table entry.
* mode is true for security. BY is the name of the function which called us.
*/
static void
add_entry( byte *p, unsigned n, int mode, const char *info, const char *by )
{
unsigned index;
struct memtbl_entry *e;
struct info_entry *ie;
if( memtbl_len < memtbl_size )
index = memtbl_len++;
else {
struct memtbl_entry *e;
/* look for a used entry in the table. We take the first one,
* so that freed entries remain as long as possible in the table
* (free appends a new one)
*/
if( (e = memtbl_unused) ) {
index = e - memtbl;
memtbl_unused = e->next;
e->next = NULL;
}
else { /* no free entries in the table: extend the table */
if( !memtbl_size ) { /* first time */
memtbl_size = 100;
if( !(memtbl = calloc( memtbl_size, sizeof *memtbl )) )
membug("memory debug table malloc failed\n");
index = 0;
memtbl_len = 1;
atexit( dump_table_at_exit );
}
else { /* realloc */
unsigned n = memtbl_size / 4; /* enlarge by 25% */
if(!(memtbl = realloc(memtbl, (memtbl_size+n)*sizeof *memtbl)))
membug("memory debug table realloc failed\n");
memset(memtbl+memtbl_size, 0, n*sizeof *memtbl );
memtbl_size += n;
index = memtbl_len++;
}
}
}
e = memtbl+index;
if( e->inuse )
membug("Ooops: entry %u is flagged as in use\n", index);
e->user_p = p + 4;
e->user_n = n;
e->count++;
if( e->next )
membug("Ooops: entry is in free entry list\n");
/* do we already have this info string */
for( ie = info_strings[info_hash(info)]; ie; ie = ie->next )
if( ie->info == info )
break;
if( !ie ) { /* no: make a new entry */
if( !(ie = malloc( sizeof *ie )) )
membug("can't allocate info entry\n");
ie->next = info_strings[info_hash(info)];
info_strings[info_hash(info)] = ie;
ie->info = info;
ie->count = 0;
}
ie->count++;
e->info = ie;
e->inuse = 1;
/* put the index at the start of the memory */
p[0] = index;
p[1] = index >> 8 ;
p[2] = index >> 16 ;
p[3] = mode? MAGIC_SEC_BYTE : MAGIC_NOR_BYTE ;
if( DBG_MEMORY )
log_debug( "%s allocates %u bytes using %s\n", info, e->user_n, by );
}
/****************
* Check that the memory block is correct. The magic byte has already been
* checked. Checks which are done here:
* - see whether the index points into our memory table
* - see whether P is the same as the one stored in the table
* - see whether we have already freed this block.
*/
struct memtbl_entry *
check_mem( const byte *p, const char *info )
{
unsigned n;
struct memtbl_entry *e;
n = p[EXTRA_ALIGN+0];
n |= p[EXTRA_ALIGN+1] << 8;
n |= p[EXTRA_ALIGN+2] << 16;
if( n >= memtbl_len )
membug("memory at %p corrupted: index=%u table_len=%u (%s)\n",
p+EXTRA_ALIGN+4, n, memtbl_len, info );
e = memtbl+n;
if( e->user_p != p+EXTRA_ALIGN+4 )
membug("memory at %p corrupted: reference mismatch (%s)\n",
p+EXTRA_ALIGN+4, info );
if( !e->inuse )
membug("memory at %p corrupted: marked as free (%s)\n",
p+EXTRA_ALIGN+4, info );
if( !(p[EXTRA_ALIGN+3] == MAGIC_NOR_BYTE
|| p[EXTRA_ALIGN+3] == MAGIC_SEC_BYTE) )
membug("memory at %p corrupted: underflow=%02x (%s)\n",
p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+3], info );
if( p[EXTRA_ALIGN+4+e->user_n] != MAGIC_END_BYTE )
membug("memory at %p corrupted: overflow=%02x (%s)\n",
p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+4+e->user_n], info );
return e;
}
/****************
* free the entry and the memory (replaces free)
*/
static void
free_entry( byte *p, const char *info )
{
struct memtbl_entry *e, *e2;
check_allmem("add_entry");
e = check_mem(p, info);
if( DBG_MEMORY )
log_debug( "%s frees %u bytes alloced by %s\n",
info, e->user_n, e->info->info );
if( !e->inuse ) {
if( e->user_p == p + EXTRA_ALIGN+ 4 )
membug("freeing an already freed pointer at %p\n", p+EXTRA_ALIGN+4 );
else
membug("freeing pointer %p which is flagged as freed\n", p+EXTRA_ALIGN+4 );
}
e->inuse = 0;
e->next = NULL;
if( !memtbl_unused )
memtbl_unused = e;
else {
for(e2=memtbl_unused; e2->next; e2 = e2->next )
;
e2->next = e;
}
memset(p,'f', e->user_n+5);
free(p);
}
static void
dump_entry(struct memtbl_entry *e )
{
unsigned n = e - memtbl;
fprintf(stderr, "mem %4u%c %5u %p %5u %s (%u)\n",
n, e->inuse?'a':'u', e->count, e->user_p, e->user_n,
e->info->info, e->info->count );
}
static void
dump_table_at_exit( void)
{
if( DBG_MEMSTAT )
dump_table();
}
static void
dump_table( void)
{
unsigned n;
struct memtbl_entry *e;
ulong sum = 0, chunks =0;
for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
if(e->inuse) {
dump_entry(e);
sum += e->user_n;
chunks++;
}
}
fprintf(stderr, " memory used: %8lu bytes in %ld chunks\n",
sum, chunks );
}
static void
check_allmem( const char *info )
{
unsigned n;
struct memtbl_entry *e;
for( e = memtbl, n = 0; n < memtbl_len; n++, e++ )
if( e->inuse )
check_mem(e->user_p-4-EXTRA_ALIGN, info);
}
#endif /* M_DEBUG */
#if defined(M_DEBUG) || defined(M_GUARD)
static void
membug( const char *fmt, ... )
{
va_list arg_ptr ;
fprintf(stderr, "\nMemory Error: " ) ;
va_start( arg_ptr, fmt ) ;
vfprintf(stderr,fmt,arg_ptr) ;
va_end(arg_ptr);
fflush(stderr);
#ifdef M_DEBUG
if( DBG_MEMSTAT )
dump_table();
#endif
abort();
}
#endif
void
m_print_stats( const char *prefix )
{
#ifdef M_DEBUG
unsigned n;
struct memtbl_entry *e;
ulong sum = 0, chunks =0;
for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
if(e->inuse) {
sum += e->user_n;
chunks++;
}
}
log_debug( "%s%smemstat: %8lu bytes in %ld chunks used\n",
prefix? prefix:"", prefix? ": ":"", sum, chunks );
#elif defined(M_GUARD)
log_debug( "%s%smemstat: %8ld bytes\n",
prefix? prefix:"", prefix? ": ":"", used_memory );
#endif
}
void
m_dump_table( const char *prefix )
{
#if M_DEBUG
fprintf(stderr,"Memory-Table-Dump: %s\n", prefix);
dump_table();
#endif
m_print_stats( prefix );
}
static void
out_of_core(size_t n, int secure)
{
log_fatal("out of %s memory while allocating %u bytes\n",
secure? "secure":"" ,(unsigned)n );
}
/****************
* Allocate memory of size n.
* Return NULL if we are out of memory.
*/
void *
g10_private_malloc( size_t n)
{
char *p;
#ifdef M_GUARD
if( !(p = malloc( n + EXTRA_ALIGN+5 )) )
return NULL;
store_len(p,n,0);
used_memory += n;
p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
return p+EXTRA_ALIGN+4;
#else /* fixme: This can be done with a macro */
return malloc( n );
#endif
}
/****************
* Allocate memory of size n.
* This function gives up if we do not have enough memory
*/
void *
FNAME(alloc)( size_t n FNAMEPRT )
{
char *p = g10_private_malloc( n );
if( !p )
out_of_core(n,0);
return p;
}
/****************
* Allocate memory of size n from the secure memory pool.
* Return NULL if we are out of memory.
*/
void *
g10_private_malloc_secure( size_t n)
{
char *p;
#ifdef M_GUARD
if( !(p = secmem_malloc( n +EXTRA_ALIGN+ 5 )) )
return NULL;
store_len(p,n,1);
p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
return p+EXTRA_ALIGN+4;
#else
return secmem_malloc( n );
#endif
}
/****************
* Allocate memory of size n from the secure memory pool.
* This function gives up if we do not have enough memory
*/
void *
FNAME(alloc_secure)( size_t n FNAMEPRT )
{
char *p = g10_private_malloc_secure( n );
if( !p )
out_of_core(n,1);
return p;
}
void *
FNAME(alloc_clear)( size_t n FNAMEPRT )
{
void *p;
p = FNAME(alloc)( n FNAMEARG );
memset(p, 0, n );
return p;
}
void *
FNAME(alloc_secure_clear)( size_t n FNAMEPRT)
{
void *p;
p = FNAME(alloc_secure)( n FNAMEARG );
memset(p, 0, n );
return p;
}
/****************
* realloc and clear the old space
* Return NULL if there is not enoug memory.
*/
void *
g10_private_realloc( void *a, size_t n )
{
#ifdef M_GUARD
unsigned char *p = a;
void *b;
size_t len = m_size(a);
if( len >= n ) /* we don't shrink for now */
return a;
if( p[-1] == MAGIC_SEC_BYTE )
b = g10_private_malloc_secure(n);
else
b = g10_private_malloc(n);
if( !b )
return NULL;
memset(p, 0, n );
FNAME(check)(NULL FNAMEARG);
memcpy(b, a, len );
FNAME(free)(p FNAMEARG);
return b;
#else
if( g10_private_is_secure(a) ) {
return secmem_realloc( a, n );
}
else {
return realloc( a, n );
}
#endif
}
/****************
* realloc and clear the old space
*/
void *
FNAME(realloc)( void *a, size_t n FNAMEPRT )
{
void *b = g10_private_realloc( a, n );
if( !b )
out_of_core(n, g10_private_is_secure(a));
return b;
}
/****************
* Free a pointer
*/
void
FNAME(free)( void *a FNAMEPRT )
{
byte *p = a;
if( !p )
return;
#ifdef M_DEBUG
free_entry(p-EXTRA_ALIGN-4, info);
#elif M_GUARD
m_check(p);
if( g10_private_is_secure(a) )
secmem_free(p-EXTRA_ALIGN-4);
else {
used_memory -= m_size(a);
free(p-EXTRA_ALIGN-4);
}
#else
if( g10_private_is_secure(a) )
secmem_free(p);
else
free(p);
#endif
}
void
g10_private_free( void *a )
{
m_free(a);
}
void
FNAME(check)( const void *a FNAMEPRT )
{
#ifdef M_GUARD
const byte *p = a;
#ifdef M_DEBUG
if( p )
check_mem(p-EXTRA_ALIGN-4, info);
else
check_allmem(info);
#else
if( !p )
return;
if( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) )
membug("memory at %p corrupted (underflow=%02x)\n", p, p[-1] );
else if( p[m_size(p)] != MAGIC_END_BYTE )
membug("memory at %p corrupted (overflow=%02x)\n", p, p[-1] );
#endif
#endif
}
void
g10_private_check_heap( const void *p )
{
m_check(p);
}
size_t
m_size( const void *a )
{
#ifndef M_GUARD
log_debug("Ooops, m_size called\n");
return 0;
#else
const byte *p = a;
size_t n;
#ifdef M_DEBUG
n = check_mem(p-EXTRA_ALIGN-4, "m_size")->user_n;
#else
n = ((byte*)p)[-4];
n |= ((byte*)p)[-3] << 8;
n |= ((byte*)p)[-2] << 16;
#endif
return n;
#endif
}
#if 0 /* not used */
/****************
* Make a copy of the memory block at a
*/
void *
FNAME(copy)( const void *a FNAMEPRT )
{
void *b;
size_t n;
if( !a )
return NULL;
n = m_size(a); Aiiiih woher nehmen
if( g10_private_is_secure(a) )
b = FNAME(alloc_secure)(n FNAMEARG);
else
b = FNAME(alloc)(n FNAMEARG);
memcpy(b, a, n );
return b;
}
#endif
char *
FNAME(strdup)( const char *a FNAMEPRT )
{
size_t n = strlen(a);
char *p = FNAME(alloc)(n+1 FNAMEARG);
strcpy(p, a);
return p;
}
int
m_is_secure( const void *a )
{
return g10_private_is_secure(a);
}

View file

@ -1,42 +0,0 @@
/* 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 LIBUTIL_MISCHELP_H
#define LIBUTIL_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 LIBUTIL_GCC_A_NR __attribute__ ((noreturn))
# define LIBUTIL_GCC_A_PRINTF( f, a ) __attribute__ ((format (printf,f,a)))
# define LIBUTIL_GCC_A_NR_PRINTF( f, a ) \
__attribute__ ((noreturn, format (printf,f,a)))
#else
# define LIBUTIL_GCC_A_NR
# define LIBUTIL_GCC_A_PRINTF( f, a )
# define LIBUTIL_GCC_A_NR_PRINTF( f, a )
#endif
#endif /*LIBUTIL_MISCHELP_H*/

View file

@ -210,7 +210,7 @@ print_utf8_string( FILE *fp, const byte *p, size_t n )
if( i < n ) {
buf = utf8_to_native( p, n );
fputs( buf, fp );
m_free( buf );
gcry_free( buf );
}
else
print_string( fp, p, n, 0 );
@ -218,7 +218,7 @@ print_utf8_string( FILE *fp, const byte *p, size_t n )
/****************
* This function returns a string which is suitable for printing
* Caller must release it with m_free()
* Caller must release it with gcry_free()
*/
char *
make_printable_string( const byte *p, size_t n, int delim )
@ -242,7 +242,7 @@ make_printable_string( const byte *p, size_t n, int delim )
p = save_p;
n = save_n;
/* and now make the string */
d = buffer = m_alloc( buflen );
d = buffer = gcry_xmalloc( buflen );
for( ; n; n--, p++ ) {
if( iscntrl( *p ) || *p == delim ) {
*d++ = '\\';

View file

@ -1,422 +0,0 @@
/* secmem.c - memory allocation from a secure heap
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <unistd.h>
#if defined(HAVE_MLOCK) || defined(HAVE_MMAP)
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#ifdef USE_CAPABILITIES
#include <sys/capability.h>
#endif
#endif
#include "types.h"
#include "memory.h"
#include "util.h"
#include "i18n.h"
#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
#define MAP_ANONYMOUS MAP_ANON
#endif
#define DEFAULT_POOLSIZE 16384
typedef struct memblock_struct MEMBLOCK;
struct memblock_struct {
unsigned size;
union {
MEMBLOCK *next;
PROPERLY_ALIGNED_TYPE aligned;
} u;
};
static void *pool;
static volatile int pool_okay; /* may be checked in an atexit function */
static int pool_is_mmapped;
static size_t poolsize; /* allocated length */
static size_t poollen; /* used length */
static MEMBLOCK *unused_blocks;
static unsigned max_alloced;
static unsigned cur_alloced;
static unsigned max_blocks;
static unsigned cur_blocks;
static int disable_secmem;
static int show_warning;
static int no_warning;
static int suspend_warning;
static void
print_warn(void)
{
if( !no_warning )
log_info(_("Warning: using insecure memory!\n"));
}
static void
lock_pool( void *p, size_t n )
{
#if defined(USE_CAPABILITIES) && defined(HAVE_MLOCK)
int err;
cap_set_proc( cap_from_text("cap_ipc_lock+ep") );
err = mlock( p, n );
if( err && errno )
err = errno;
cap_set_proc( cap_from_text("cap_ipc_lock+p") );
if( err ) {
if( errno != EPERM
#ifdef EAGAIN /* OpenBSD returns this */
&& errno != EAGAIN
#endif
#ifdef ENOSYS /* Some SCOs return this (function not implemented) */
&& errno != ENOSYS
#endif
)
log_error("can't lock memory: %s\n", strerror(err));
show_warning = 1;
}
#elif defined(HAVE_MLOCK)
uid_t uid;
int err;
uid = getuid();
#ifdef HAVE_BROKEN_MLOCK
if( uid ) {
errno = EPERM;
err = errno;
}
else {
err = mlock( p, n );
if( err && errno )
err = errno;
}
#else
err = mlock( p, n );
if( err && errno )
err = errno;
#endif
if( uid && !geteuid() ) {
if( setuid( uid ) || getuid() != geteuid() )
log_fatal("failed to reset uid: %s\n", strerror(errno));
}
if( err ) {
if( errno != EPERM
#ifdef EAGAIN /* OpenBSD returns this */
&& errno != EAGAIN
#endif
#ifdef ENOSYS /* Some SCOs return this (function not implemented) */
&& errno != ENOSYS
#endif
)
log_error("can't lock memory: %s\n", strerror(err));
show_warning = 1;
}
#else
log_info("Please note that you don't have secure memory on this system\n");
#endif
}
static void
init_pool( size_t n)
{
size_t pgsize;
poolsize = n;
if( disable_secmem )
log_bug("secure memory is disabled");
#ifdef HAVE_GETPAGESIZE
pgsize = getpagesize();
#else
pgsize = 4096;
#endif
#if HAVE_MMAP
poolsize = (poolsize + pgsize -1 ) & ~(pgsize-1);
#ifdef MAP_ANONYMOUS
pool = mmap( 0, poolsize, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
#else /* map /dev/zero instead */
{ int fd;
fd = open("/dev/zero", O_RDWR);
if( fd == -1 ) {
log_error("can't open /dev/zero: %s\n", strerror(errno) );
pool = (void*)-1;
}
else {
pool = mmap( 0, poolsize, PROT_READ|PROT_WRITE,
MAP_PRIVATE, fd, 0);
}
}
#endif
if( pool == (void*)-1 )
log_info("can't mmap pool of %u bytes: %s - using malloc\n",
(unsigned)poolsize, strerror(errno));
else {
pool_is_mmapped = 1;
pool_okay = 1;
}
#endif
if( !pool_okay ) {
pool = malloc( poolsize );
if( !pool )
log_fatal("can't allocate memory pool of %u bytes\n",
(unsigned)poolsize);
else
pool_okay = 1;
}
lock_pool( pool, poolsize );
poollen = 0;
}
/* concatenate unused blocks */
static void
compress_pool(void)
{
/* fixme: we really should do this */
}
void
secmem_set_flags( unsigned flags )
{
int was_susp = suspend_warning;
no_warning = flags & 1;
suspend_warning = flags & 2;
/* and now issue the warning if it is not longer suspended */
if( was_susp && !suspend_warning && show_warning ) {
show_warning = 0;
print_warn();
}
}
unsigned
secmem_get_flags(void)
{
unsigned flags;
flags = no_warning ? 1:0;
flags |= suspend_warning ? 2:0;
return flags;
}
void
secmem_init( size_t n )
{
if( !n ) {
#ifdef USE_CAPABILITIES
/* drop all capabilities */
cap_set_proc( cap_from_text("all-eip") );
#elif !defined(HAVE_DOSISH_SYSTEM)
uid_t uid;
disable_secmem=1;
uid = getuid();
if( uid != geteuid() ) {
if( setuid( uid ) || getuid() != geteuid() )
log_fatal("failed to drop setuid\n" );
}
#endif
}
else {
if( n < DEFAULT_POOLSIZE )
n = DEFAULT_POOLSIZE;
if( !pool_okay )
init_pool(n);
else
log_error("Oops, secure memory pool already initialized\n");
}
}
void *
secmem_malloc( size_t size )
{
MEMBLOCK *mb, *mb2;
int compressed=0;
if( !pool_okay ) {
log_info(
_("operation is not possible without initialized secure memory\n"));
log_info(_("(you may have used the wrong program for this task)\n"));
exit(2);
}
if( show_warning && !suspend_warning ) {
show_warning = 0;
print_warn();
}
/* blocks are always a multiple of 32 */
size += sizeof(MEMBLOCK);
size = ((size + 31) / 32) * 32;
retry:
/* try to get it from the used blocks */
for(mb = unused_blocks,mb2=NULL; mb; mb2=mb, mb = mb->u.next )
if( mb->size >= size ) {
if( mb2 )
mb2->u.next = mb->u.next;
else
unused_blocks = mb->u.next;
goto leave;
}
/* allocate a new block */
if( (poollen + size <= poolsize) ) {
mb = (void*)((char*)pool + poollen);
poollen += size;
mb->size = size;
}
else if( !compressed ) {
compressed=1;
compress_pool();
goto retry;
}
else
return NULL;
leave:
cur_alloced += mb->size;
cur_blocks++;
if( cur_alloced > max_alloced )
max_alloced = cur_alloced;
if( cur_blocks > max_blocks )
max_blocks = cur_blocks;
return &mb->u.aligned.c;
}
void *
secmem_realloc( void *p, size_t newsize )
{
MEMBLOCK *mb;
size_t size;
void *a;
mb = (MEMBLOCK*)((char*)p - ((size_t) &((MEMBLOCK*)0)->u.aligned.c));
size = mb->size;
if( newsize < size )
return p; /* it is easier not to shrink the memory */
a = secmem_malloc( newsize );
memcpy(a, p, size);
memset((char*)a+size, 0, newsize-size);
secmem_free(p);
return a;
}
void
secmem_free( void *a )
{
MEMBLOCK *mb;
size_t size;
if( !a )
return;
mb = (MEMBLOCK*)((char*)a - ((size_t) &((MEMBLOCK*)0)->u.aligned.c));
size = mb->size;
/* This does not make much sense: probably this memory is held in the
* cache. We do it anyway: */
memset(mb, 0xff, size );
memset(mb, 0xaa, size );
memset(mb, 0x55, size );
memset(mb, 0x00, size );
mb->size = size;
mb->u.next = unused_blocks;
unused_blocks = mb;
cur_blocks--;
cur_alloced -= size;
}
int
g10_private_is_secure( const void *p )
{
return p >= pool && p < (void*)((char*)pool+poolsize);
}
/****************
* Warning: This code might be called by an interrupt handler
* and frankly, there should really be such a handler,
* to make sure that the memory is wiped out.
* We hope that the OS wipes out mlocked memory after
* receiving a SIGKILL - it really should do so, otherwise
* there is no chance to get the secure memory cleaned.
*/
void
secmem_term()
{
if( !pool_okay )
return;
memset( pool, 0xff, poolsize);
memset( pool, 0xaa, poolsize);
memset( pool, 0x55, poolsize);
memset( pool, 0x00, poolsize);
#if HAVE_MMAP
if( pool_is_mmapped )
munmap( pool, poolsize );
#endif
pool = NULL;
pool_okay = 0;
poolsize=0;
poollen=0;
unused_blocks=NULL;
}
void
secmem_dump_stats()
{
if( disable_secmem )
return;
fprintf(stderr,
"secmem usage: %u/%u bytes in %u/%u blocks of pool %lu/%lu\n",
cur_alloced, max_alloced, cur_blocks, max_blocks,
(ulong)poollen, (ulong)poolsize );
}

View file

@ -96,7 +96,7 @@ free_strlist( STRLIST sl )
for(; sl; sl = sl2 ) {
sl2 = sl->next;
m_free(sl);
gcry_free(sl);
}
}
@ -106,7 +106,7 @@ add_to_strlist( STRLIST *list, const char *string )
{
STRLIST sl;
sl = m_alloc( sizeof *sl + strlen(string));
sl = gcry_xmalloc( sizeof *sl + strlen(string));
sl->flags = 0;
strcpy(sl->d, string);
sl->next = *list;
@ -128,7 +128,7 @@ add_to_strlist2( STRLIST *list, const char *string, int is_utf8 )
else {
char *p = native_to_utf8( string );
sl = add_to_strlist( list, p );
m_free( p );
gcry_free( p );
}
return sl;
}
@ -138,7 +138,7 @@ append_to_strlist( STRLIST *list, const char *string )
{
STRLIST r, sl;
sl = m_alloc( sizeof *sl + strlen(string));
sl = gcry_xmalloc( sizeof *sl + strlen(string));
sl->flags = 0;
strcpy(sl->d, string);
sl->next = NULL;
@ -162,7 +162,7 @@ append_to_strlist2( STRLIST *list, const char *string, int is_utf8 )
else {
char *p = native_to_utf8( string );
sl = append_to_strlist( list, p );
m_free( p );
gcry_free( p );
}
return sl;
}
@ -299,7 +299,7 @@ native_to_utf8( const char *string )
if( *s & 0x80 )
length += 2; /* we may need 3 bytes */
}
buffer = m_alloc( length + 1 );
buffer = gcry_xmalloc( length + 1 );
for(p=buffer, s=string; *s; s++ ) {
if( *s & 0x80 ) {
ushort val = active_charset[ *s & 0x7f ];
@ -324,7 +324,7 @@ native_to_utf8( const char *string )
if( *s & 0x80 )
length++;
}
buffer = m_alloc( length + 1 );
buffer = gcry_xmalloc( length + 1 );
for(p=buffer, s=string; *s; s++ ) {
if( *s & 0x80 ) {
*p++ = 0xc0 | ((*s >> 6) & 3);
@ -485,7 +485,7 @@ utf8_to_native( const char *string, size_t length )
}
}
if( !buffer ) { /* allocate the buffer after the first pass */
buffer = p = m_alloc( n + 1 );
buffer = p = gcry_xmalloc( n + 1 );
}
else {
*p = 0; /* make a string */

View file

@ -1,219 +0,0 @@
/* 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 <ctype.h>
#include "libutil-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 libutil_malloc 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 = libutil_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" );
}
/*********************************************
********** 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

View file

@ -1,60 +0,0 @@
/* 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 LIBUTIL_STRINGHELP_H
#define LIBUTIL_STRINGHELP_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 );
#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 /*LIBUTIL_STRINGHELP_H*/

View file

@ -161,19 +161,19 @@ tty_printf( const char *fmt, ... )
* it, so we use a static buffer for now */
do {
if( n == -1 || !buf ) {
m_free(buf);
gcry_free(buf);
bufsize += 200;
/* better check the new size; (we use M$ functions) */
if( bufsize > 50000 )
log_bug("vsnprintf probably failed\n");
buf = m_alloc( bufsize );
buf = gcry_xmalloc( bufsize );
}
n = _vsnprintf(buf, bufsize-1, fmt, arg_ptr);
} while( n == -1 );
#else
if( !buf ) {
bufsize += 1000;
buf = m_alloc( bufsize );
buf = gcry_xmalloc( bufsize );
}
n = vsprintf(buf, fmt, arg_ptr);
if( n == -1 )
@ -252,7 +252,7 @@ tty_print_utf8_string( byte *p, size_t n )
if( i < n ) {
buf = utf8_to_native( p, n );
tty_printf("%s", buf );
m_free( buf );
gcry_free( buf );
}
else
tty_print_string( p, n );
@ -284,7 +284,7 @@ do_get( const char *prompt, int hidden )
last_prompt_len = 0;
tty_printf( prompt );
buf = m_alloc(n=50);
buf = gcry_xmalloc(n=50);
i = 0;
#ifdef __MINGW32__ /* windoze version */
@ -313,7 +313,7 @@ do_get( const char *prompt, int hidden )
continue;
if( !(i < n-1) ) {
n += 50;
buf = m_realloc( buf, n );
buf = gcry_xrealloc( buf, n );
}
buf[i++] = c;
}
@ -353,7 +353,7 @@ do_get( const char *prompt, int hidden )
continue;
if( !(i < n-1) ) {
n += 50;
buf = m_realloc( buf, n );
buf = gcry_xrealloc( buf, n );
}
buf[i++] = c;
}
@ -425,7 +425,7 @@ tty_get_answer_is_yes( const char *prompt )
char *p = tty_get( prompt );
tty_kill_prompt();
yes = answer_is_yes(p);
m_free(p);
gcry_free(p);
return yes;
}

View file

@ -1,70 +0,0 @@
/* 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 <stdio.h>
#include "libutil-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;
}

View file

@ -1,30 +0,0 @@
/* 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 LIBUTIL_XMALLOC_H
#define LIBUTIL_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 );
#endif /*LIBUTIL_XMALLOC_H*/