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:
parent
704eb738c0
commit
0070faa0ff
88 changed files with 887 additions and 3998 deletions
|
@ -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.
|
||||
|
|
|
@ -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
7
util/README
Normal 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.
|
||||
|
||||
|
996
util/argparse.c
996
util/argparse.c
|
@ -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 ****/
|
|
@ -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*/
|
346
util/dotlock.c
346
util/dotlock.c
|
@ -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
|
||||
}
|
||||
|
|
@ -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 ) ;
|
||||
|
|
20
util/http.c
20
util/http.c
|
@ -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 */
|
||||
|
|
92
util/iobuf.c
92
util/iobuf.c
|
@ -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 */
|
||||
|
|
|
@ -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*/
|
|
@ -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;
|
||||
}
|
||||
|
|
170
util/logging.c
170
util/logging.c
|
@ -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
|
||||
|
|
@ -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*/
|
651
util/memory.c
651
util/memory.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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*/
|
|
@ -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++ = '\\';
|
||||
|
|
422
util/secmem.c
422
util/secmem.c
|
@ -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 );
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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*/
|
16
util/ttyio.c
16
util/ttyio.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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*/
|
Loading…
Add table
Add a link
Reference in a new issue