Add missing jnlib directory
This commit is contained in:
parent
6b4ca13dd4
commit
b08b3dd7e6
41
jnlib/ChangeLog
Normal file
41
jnlib/ChangeLog
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
2000-07-26 10:02:51 Werner Koch (wk@habibti.openit.de)
|
||||||
|
|
||||||
|
* stringhelp.c.: Add stdarg.h
|
||||||
|
* argparse.h: s/ulong/unsigned long/ although this should be defined
|
||||||
|
by types.h.
|
||||||
|
|
||||||
|
2000-06-28 19:40:23 Werner Koch (wk@habibti.openit.de)
|
||||||
|
|
||||||
|
* Makefile.am: Replaced second logging.c by .h
|
||||||
|
|
||||||
|
2000-05-24 08:58:15 Werner Koch (wk@habibti.openit.de)
|
||||||
|
|
||||||
|
* logging.c (log_get_errorcount): New.
|
||||||
|
|
||||||
|
2000-05-24 08:44:47 Werner Koch (wk@habibti.openit.de)
|
||||||
|
|
||||||
|
* stringhelp.c: Added a few filename related helper functions.
|
||||||
|
|
||||||
|
2000-05-11 18:04:43 Werner Koch (wk@habibti.openit.de)
|
||||||
|
|
||||||
|
* xmalloc.c (xstrcat2): Replaced stpcpy to quickly address W32
|
||||||
|
problems.
|
||||||
|
|
||||||
|
2000-05-02 19:43:38 Werner Koch (wk@habibti.openit.de)
|
||||||
|
|
||||||
|
* xmalloc.c (xstrcat2): New.
|
||||||
|
|
||||||
|
Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de>
|
||||||
|
|
||||||
|
* README: New.
|
||||||
|
* Makefile.am: new.
|
||||||
|
* argparse.c argparse.h logging.c logging.h
|
||||||
|
mischelp.h stringhelp.c stringhelp.h xmalloc.c
|
||||||
|
xmalloc.h dotlock.c: Moved from ../util to here.
|
||||||
|
* dotlock.h: New.
|
||||||
|
* libjnlib-config.h: New.
|
||||||
|
|
||||||
|
* logging.c (log_set_file): New.
|
||||||
|
(log_printf): New.
|
||||||
|
(do_logv): Add kludge to insert LFs.
|
||||||
|
|
7
jnlib/README
Normal file
7
jnlib/README
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
jnlib - this is a collection of utility function which are
|
||||||
|
too small to put into a library.
|
||||||
|
|
||||||
|
libjnlib-config.h should be be modified for each project
|
||||||
|
to make these functions fit into the software. Mainly these
|
||||||
|
are memory functions in case you need another allocator.
|
||||||
|
|
995
jnlib/argparse.c
Normal file
995
jnlib/argparse.c
Normal file
@ -0,0 +1,995 @@
|
|||||||
|
/* [argparse.c wk 17.06.97] Argument Parser for option handling
|
||||||
|
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "libjnlib-config.h"
|
||||||
|
#include "mischelp.h"
|
||||||
|
#include "stringhelp.h"
|
||||||
|
#include "logging.h"
|
||||||
|
#include "argparse.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************
|
||||||
|
* @Summary arg_parse
|
||||||
|
* #include <wk/lib.h>
|
||||||
|
*
|
||||||
|
* typedef struct {
|
||||||
|
* char *argc; pointer to argc (value subject to change)
|
||||||
|
* char ***argv; pointer to argv (value subject to change)
|
||||||
|
* unsigned flags; Global flags (DO NOT CHANGE)
|
||||||
|
* int err; print error about last option
|
||||||
|
* 1 = warning, 2 = abort
|
||||||
|
* int r_opt; return option
|
||||||
|
* int r_type; type of return value (0 = no argument found)
|
||||||
|
* union {
|
||||||
|
* int ret_int;
|
||||||
|
* long ret_long
|
||||||
|
* ulong ret_ulong;
|
||||||
|
* char *ret_str;
|
||||||
|
* } r; Return values
|
||||||
|
* struct {
|
||||||
|
* int idx;
|
||||||
|
* const char *last;
|
||||||
|
* void *aliases;
|
||||||
|
* } internal; DO NOT CHANGE
|
||||||
|
* } ARGPARSE_ARGS;
|
||||||
|
*
|
||||||
|
* typedef struct {
|
||||||
|
* int short_opt;
|
||||||
|
* const char *long_opt;
|
||||||
|
* unsigned flags;
|
||||||
|
* } ARGPARSE_OPTS;
|
||||||
|
*
|
||||||
|
* int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts );
|
||||||
|
*
|
||||||
|
* @Description
|
||||||
|
* This is my replacement for getopt(). See the example for a typical usage.
|
||||||
|
* Global flags are:
|
||||||
|
* Bit 0 : Do not remove options form argv
|
||||||
|
* Bit 1 : Do not stop at last option but return other args
|
||||||
|
* with r_opt set to -1.
|
||||||
|
* Bit 2 : Assume options and real args are mixed.
|
||||||
|
* Bit 3 : Do not use -- to stop option processing.
|
||||||
|
* Bit 4 : Do not skip the first arg.
|
||||||
|
* Bit 5 : allow usage of long option with only one dash
|
||||||
|
* Bit 6 : ignore --version
|
||||||
|
* all other bits must be set to zero, this value is modified by the
|
||||||
|
* function, so assume this is write only.
|
||||||
|
* Local flags (for each option):
|
||||||
|
* Bit 2-0 : 0 = does not take an argument
|
||||||
|
* 1 = takes int argument
|
||||||
|
* 2 = takes string argument
|
||||||
|
* 3 = takes long argument
|
||||||
|
* 4 = takes ulong argument
|
||||||
|
* Bit 3 : argument is optional (r_type will the be set to 0)
|
||||||
|
* Bit 4 : allow 0x etc. prefixed values.
|
||||||
|
* Bit 7 : this is a command and not an option
|
||||||
|
* You stop the option processing by setting opts to NULL, the function will
|
||||||
|
* then return 0.
|
||||||
|
* @Return Value
|
||||||
|
* Returns the args.r_opt or 0 if ready
|
||||||
|
* r_opt may be -2/-7 to indicate an unknown option/command.
|
||||||
|
* @See Also
|
||||||
|
* ArgExpand
|
||||||
|
* @Notes
|
||||||
|
* You do not need to process the options 'h', '--help' or '--version'
|
||||||
|
* because this function includes standard help processing; but if you
|
||||||
|
* specify '-h', '--help' or '--version' you have to do it yourself.
|
||||||
|
* The option '--' stops argument processing; if bit 1 is set the function
|
||||||
|
* continues to return normal arguments.
|
||||||
|
* To process float args or unsigned args you must use a string args and do
|
||||||
|
* the conversion yourself.
|
||||||
|
* @Example
|
||||||
|
*
|
||||||
|
* ARGPARSE_OPTS opts[] = {
|
||||||
|
* { 'v', "verbose", 0 },
|
||||||
|
* { 'd', "debug", 0 },
|
||||||
|
* { 'o', "output", 2 },
|
||||||
|
* { 'c', "cross-ref", 2|8 },
|
||||||
|
* { 'm', "my-option", 1|8 },
|
||||||
|
* { 500, "have-no-short-option-for-this-long-option", 0 },
|
||||||
|
* {0} };
|
||||||
|
* ARGPARSE_ARGS pargs = { &argc, &argv, 0 }
|
||||||
|
*
|
||||||
|
* while( ArgParse( &pargs, &opts) ) {
|
||||||
|
* switch( pargs.r_opt ) {
|
||||||
|
* case 'v': opt.verbose++; break;
|
||||||
|
* case 'd': opt.debug++; break;
|
||||||
|
* case 'o': opt.outfile = pargs.r.ret_str; break;
|
||||||
|
* case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
|
||||||
|
* case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
|
||||||
|
* case 500: opt.a_long_one++; break
|
||||||
|
* default : pargs.err = 1; break; -- force warning output --
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* if( argc > 1 )
|
||||||
|
* log_fatal( "Too many args");
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct alias_def_s *ALIAS_DEF;
|
||||||
|
struct alias_def_s {
|
||||||
|
ALIAS_DEF next;
|
||||||
|
char *name; /* malloced buffer with name, \0, value */
|
||||||
|
const char *value; /* ptr into name */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *(*strusage_handler)( int ) = NULL;
|
||||||
|
|
||||||
|
static int set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s);
|
||||||
|
static void show_help(ARGPARSE_OPTS *opts, unsigned flags);
|
||||||
|
static void show_version(void);
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
|
||||||
|
{
|
||||||
|
if( !(arg->flags & (1<<15)) ) { /* initialize this instance */
|
||||||
|
arg->internal.idx = 0;
|
||||||
|
arg->internal.last = NULL;
|
||||||
|
arg->internal.inarg = 0;
|
||||||
|
arg->internal.stopped = 0;
|
||||||
|
arg->internal.aliases = NULL;
|
||||||
|
arg->internal.cur_alias = NULL;
|
||||||
|
arg->err = 0;
|
||||||
|
arg->flags |= 1<<15; /* mark initialized */
|
||||||
|
if( *arg->argc < 0 )
|
||||||
|
jnlib_log_bug("Invalid argument for ArgParse\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( arg->err ) { /* last option was erroneous */
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
if( filename ) {
|
||||||
|
if( arg->r_opt == -6 )
|
||||||
|
s = "%s:%u: argument not expected\n";
|
||||||
|
else if( arg->r_opt == -5 )
|
||||||
|
s = "%s:%u: read error\n";
|
||||||
|
else if( arg->r_opt == -4 )
|
||||||
|
s = "%s:%u: keyword too long\n";
|
||||||
|
else if( arg->r_opt == -3 )
|
||||||
|
s = "%s:%u: missing argument\n";
|
||||||
|
else if( arg->r_opt == -7 )
|
||||||
|
s = "%s:%u: invalid command\n";
|
||||||
|
else if( arg->r_opt == -10 )
|
||||||
|
s = "%s:%u: invalid alias definition\n";
|
||||||
|
else
|
||||||
|
s = "%s:%u: invalid option\n";
|
||||||
|
jnlib_log_error(s, filename, *lineno );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if( arg->r_opt == -3 )
|
||||||
|
s = "Missing argument for option \"%.50s\"\n";
|
||||||
|
else if( arg->r_opt == -6 )
|
||||||
|
s = "Option \"%.50s\" does not expect an argument\n";
|
||||||
|
else if( arg->r_opt == -7 )
|
||||||
|
s = "Invalid command \"%.50s\"\n";
|
||||||
|
else if( arg->r_opt == -8 )
|
||||||
|
s = "Option \"%.50s\" is ambiguous\n";
|
||||||
|
else if( arg->r_opt == -9 )
|
||||||
|
s = "Command \"%.50s\" is ambiguous\n";
|
||||||
|
else
|
||||||
|
s = "Invalid option \"%.50s\"\n";
|
||||||
|
jnlib_log_error(s, arg->internal.last? arg->internal.last:"[??]" );
|
||||||
|
}
|
||||||
|
if( arg->err != 1 )
|
||||||
|
exit(2);
|
||||||
|
arg->err = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clearout the return value union */
|
||||||
|
arg->r.ret_str = NULL;
|
||||||
|
arg->r.ret_long= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
store_alias( ARGPARSE_ARGS *arg, char *name, char *value )
|
||||||
|
{
|
||||||
|
/* TODO: replace this dummy function with a rea one
|
||||||
|
* and fix the probelms IRIX has with (ALIAS_DEV)arg..
|
||||||
|
* used as lvalue
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
ALIAS_DEF a = jnlib_xmalloc( sizeof *a );
|
||||||
|
a->name = name;
|
||||||
|
a->value = value;
|
||||||
|
a->next = (ALIAS_DEF)arg->internal.aliases;
|
||||||
|
(ALIAS_DEF)arg->internal.aliases = a;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* Get options from a file.
|
||||||
|
* Lines starting with '#' are comment lines.
|
||||||
|
* Syntax is simply a keyword and the argument.
|
||||||
|
* Valid keywords are all keywords from the long_opt list without
|
||||||
|
* the leading dashes. The special keywords "help", "warranty" and "version"
|
||||||
|
* are not valid here.
|
||||||
|
* The special keyword "alias" may be used to store alias definitions,
|
||||||
|
* which are later expanded like long options.
|
||||||
|
* Caller must free returned strings.
|
||||||
|
* If called with FP set to NULL command line args are parse instead.
|
||||||
|
*
|
||||||
|
* Q: Should we allow the syntax
|
||||||
|
* keyword = value
|
||||||
|
* and accept for boolean options a value of 1/0, yes/no or true/false?
|
||||||
|
* Note: Abbreviation of options is here not allowed.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
|
||||||
|
ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
|
||||||
|
{
|
||||||
|
int state, i, c;
|
||||||
|
int idx=0;
|
||||||
|
char keyword[100];
|
||||||
|
char *buffer = NULL;
|
||||||
|
size_t buflen = 0;
|
||||||
|
int inverse=0;
|
||||||
|
int in_alias=0;
|
||||||
|
|
||||||
|
if( !fp ) /* same as arg_parse() in this case */
|
||||||
|
return arg_parse( arg, opts );
|
||||||
|
|
||||||
|
initialize( arg, filename, lineno );
|
||||||
|
|
||||||
|
/* find the next keyword */
|
||||||
|
state = i = 0;
|
||||||
|
for(;;) {
|
||||||
|
c=getc(fp);
|
||||||
|
if( c == '\n' || c== EOF ) {
|
||||||
|
if( c != EOF )
|
||||||
|
++*lineno;
|
||||||
|
if( state == -1 )
|
||||||
|
break;
|
||||||
|
else if( state == 2 ) {
|
||||||
|
keyword[i] = 0;
|
||||||
|
for(i=0; opts[i].short_opt; i++ )
|
||||||
|
if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
|
||||||
|
break;
|
||||||
|
idx = i;
|
||||||
|
arg->r_opt = opts[idx].short_opt;
|
||||||
|
if( inverse ) /* this does not have an effect, hmmm */
|
||||||
|
arg->r_opt = -arg->r_opt;
|
||||||
|
if( !opts[idx].short_opt ) /* unknown command/option */
|
||||||
|
arg->r_opt = (opts[idx].flags & 256)? -7:-2;
|
||||||
|
else if( (opts[idx].flags & 8) ) /* no argument */
|
||||||
|
arg->r_opt = -3; /* error */
|
||||||
|
else /* no or optional argument */
|
||||||
|
arg->r_type = 0; /* okay */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if( state == 3 ) { /* no argument found */
|
||||||
|
if( in_alias )
|
||||||
|
arg->r_opt = -3; /* error */
|
||||||
|
else if( !(opts[idx].flags & 7) ) /* does not take an arg */
|
||||||
|
arg->r_type = 0; /* okay */
|
||||||
|
else if( (opts[idx].flags & 8) ) /* no optional argument */
|
||||||
|
arg->r_type = 0; /* okay */
|
||||||
|
else /* no required argument */
|
||||||
|
arg->r_opt = -3; /* error */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if( state == 4 ) { /* have an argument */
|
||||||
|
if( in_alias ) {
|
||||||
|
if( !buffer )
|
||||||
|
arg->r_opt = -6;
|
||||||
|
else {
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
buffer[i] = 0;
|
||||||
|
p = strpbrk( buffer, " \t" );
|
||||||
|
if( p ) {
|
||||||
|
*p++ = 0;
|
||||||
|
trim_spaces( p );
|
||||||
|
}
|
||||||
|
if( !p || !*p ) {
|
||||||
|
jnlib_free( buffer );
|
||||||
|
arg->r_opt = -10;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
store_alias( arg, buffer, p );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( !(opts[idx].flags & 7) ) /* does not take an arg */
|
||||||
|
arg->r_opt = -6; /* error */
|
||||||
|
else {
|
||||||
|
char *p;
|
||||||
|
if( !buffer ) {
|
||||||
|
keyword[i] = 0;
|
||||||
|
buffer = jnlib_xstrdup(keyword);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
buffer[i] = 0;
|
||||||
|
|
||||||
|
trim_spaces( buffer );
|
||||||
|
p = buffer;
|
||||||
|
if( *p == '"' ) { /* remove quotes */
|
||||||
|
p++;
|
||||||
|
if( *p && p[strlen(p)-1] == '"' )
|
||||||
|
p[strlen(p)-1] = 0;
|
||||||
|
}
|
||||||
|
if( !set_opt_arg(arg, opts[idx].flags, p) )
|
||||||
|
jnlib_free(buffer);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if( c == EOF ) {
|
||||||
|
if( ferror(fp) )
|
||||||
|
arg->r_opt = -5; /* read error */
|
||||||
|
else
|
||||||
|
arg->r_opt = 0; /* eof */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
state = 0;
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
else if( state == -1 )
|
||||||
|
; /* skip */
|
||||||
|
else if( !state && isspace(c) )
|
||||||
|
; /* skip leading white space */
|
||||||
|
else if( !state && c == '#' )
|
||||||
|
state = 1; /* start of a comment */
|
||||||
|
else if( state == 1 )
|
||||||
|
; /* skip comments */
|
||||||
|
else if( state == 2 && isspace(c) ) {
|
||||||
|
keyword[i] = 0;
|
||||||
|
for(i=0; opts[i].short_opt; i++ )
|
||||||
|
if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
|
||||||
|
break;
|
||||||
|
idx = i;
|
||||||
|
arg->r_opt = opts[idx].short_opt;
|
||||||
|
if( !opts[idx].short_opt ) {
|
||||||
|
if( !strcmp( keyword, "alias" ) ) {
|
||||||
|
in_alias = 1;
|
||||||
|
state = 3;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
arg->r_opt = (opts[idx].flags & 256)? -7:-2;
|
||||||
|
state = -1; /* skip rest of line and leave */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
state = 3;
|
||||||
|
}
|
||||||
|
else if( state == 3 ) { /* skip leading spaces of the argument */
|
||||||
|
if( !isspace(c) ) {
|
||||||
|
i = 0;
|
||||||
|
keyword[i++] = c;
|
||||||
|
state = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( state == 4 ) { /* collect the argument */
|
||||||
|
if( buffer ) {
|
||||||
|
if( i < buflen-1 )
|
||||||
|
buffer[i++] = c;
|
||||||
|
else {
|
||||||
|
buflen += 50;
|
||||||
|
buffer = jnlib_xrealloc(buffer, buflen);
|
||||||
|
buffer[i++] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( i < DIM(keyword)-1 )
|
||||||
|
keyword[i++] = c;
|
||||||
|
else {
|
||||||
|
buflen = DIM(keyword)+50;
|
||||||
|
buffer = jnlib_xmalloc(buflen);
|
||||||
|
memcpy(buffer, keyword, i);
|
||||||
|
buffer[i++] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( i >= DIM(keyword)-1 ) {
|
||||||
|
arg->r_opt = -4; /* keyword to long */
|
||||||
|
state = -1; /* skip rest of line and leave */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
keyword[i++] = c;
|
||||||
|
state = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return arg->r_opt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
find_long_option( ARGPARSE_ARGS *arg,
|
||||||
|
ARGPARSE_OPTS *opts, const char *keyword )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
/* Would be better if we can do a binary search, but it is not
|
||||||
|
possible to reorder our option table because we would mess
|
||||||
|
up our help strings - What we can do is: Build a nice option
|
||||||
|
lookup table wehn this function is first invoked */
|
||||||
|
if( !*keyword )
|
||||||
|
return -1;
|
||||||
|
for(i=0; opts[i].short_opt; i++ )
|
||||||
|
if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
|
||||||
|
return i;
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
ALIAS_DEF a;
|
||||||
|
/* see whether it is an alias */
|
||||||
|
for( a = args->internal.aliases; a; a = a->next ) {
|
||||||
|
if( !strcmp( a->name, keyword) ) {
|
||||||
|
/* todo: must parse the alias here */
|
||||||
|
args->internal.cur_alias = a;
|
||||||
|
return -3; /* alias available */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* not found, see whether it is an abbreviation */
|
||||||
|
/* aliases may not be abbreviated */
|
||||||
|
n = strlen( keyword );
|
||||||
|
for(i=0; opts[i].short_opt; i++ ) {
|
||||||
|
if( opts[i].long_opt && !strncmp( opts[i].long_opt, keyword, n ) ) {
|
||||||
|
int j;
|
||||||
|
for(j=i+1; opts[j].short_opt; j++ ) {
|
||||||
|
if( opts[j].long_opt
|
||||||
|
&& !strncmp( opts[j].long_opt, keyword, n ) )
|
||||||
|
return -2; /* abbreviation is ambiguous */
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
|
char *s, *s2;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
initialize( arg, NULL, NULL );
|
||||||
|
argc = *arg->argc;
|
||||||
|
argv = *arg->argv;
|
||||||
|
idx = arg->internal.idx;
|
||||||
|
|
||||||
|
if( !idx && argc && !(arg->flags & (1<<4)) ) { /* skip the first entry */
|
||||||
|
argc--; argv++; idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
next_one:
|
||||||
|
if( !argc ) { /* no more args */
|
||||||
|
arg->r_opt = 0;
|
||||||
|
goto leave; /* ready */
|
||||||
|
}
|
||||||
|
|
||||||
|
s = *argv;
|
||||||
|
arg->internal.last = s;
|
||||||
|
|
||||||
|
if( arg->internal.stopped && (arg->flags & (1<<1)) ) {
|
||||||
|
arg->r_opt = -1; /* not an option but a argument */
|
||||||
|
arg->r_type = 2;
|
||||||
|
arg->r.ret_str = s;
|
||||||
|
argc--; argv++; idx++; /* set to next one */
|
||||||
|
}
|
||||||
|
else if( arg->internal.stopped ) { /* ready */
|
||||||
|
arg->r_opt = 0;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
else if( *s == '-' && s[1] == '-' ) { /* long option */
|
||||||
|
char *argpos;
|
||||||
|
|
||||||
|
arg->internal.inarg = 0;
|
||||||
|
if( !s[2] && !(arg->flags & (1<<3)) ) { /* stop option processing */
|
||||||
|
arg->internal.stopped = 1;
|
||||||
|
argc--; argv++; idx++;
|
||||||
|
goto next_one;
|
||||||
|
}
|
||||||
|
|
||||||
|
argpos = strchr( s+2, '=' );
|
||||||
|
if( argpos )
|
||||||
|
*argpos = 0;
|
||||||
|
i = find_long_option( arg, opts, s+2 );
|
||||||
|
if( argpos )
|
||||||
|
*argpos = '=';
|
||||||
|
|
||||||
|
if( i < 0 && !strcmp( "help", s+2) )
|
||||||
|
show_help(opts, arg->flags);
|
||||||
|
else if( i < 0 && !strcmp( "version", s+2) ) {
|
||||||
|
if( !(arg->flags & (1<<6)) ) {
|
||||||
|
show_version();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( i < 0 && !strcmp( "warranty", s+2) ) {
|
||||||
|
puts( strusage(16) );
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
else if( i < 0 && !strcmp( "dump-options", s+2) ) {
|
||||||
|
for(i=0; opts[i].short_opt; i++ ) {
|
||||||
|
if( opts[i].long_opt )
|
||||||
|
printf( "--%s\n", opts[i].long_opt );
|
||||||
|
}
|
||||||
|
fputs("--dump-options\n--help\n--version\n--warranty\n", stdout );
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( i == -2 ) /* ambiguous option */
|
||||||
|
arg->r_opt = -8;
|
||||||
|
else if( i == -1 ) {
|
||||||
|
arg->r_opt = -2;
|
||||||
|
arg->r.ret_str = s+2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
arg->r_opt = opts[i].short_opt;
|
||||||
|
if( i < 0 )
|
||||||
|
;
|
||||||
|
else if( (opts[i].flags & 7) ) {
|
||||||
|
if( argpos ) {
|
||||||
|
s2 = argpos+1;
|
||||||
|
if( !*s2 )
|
||||||
|
s2 = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s2 = argv[1];
|
||||||
|
if( !s2 && (opts[i].flags & 8) ) { /* no argument but it is okay*/
|
||||||
|
arg->r_type = 0; /* because it is optional */
|
||||||
|
}
|
||||||
|
else if( !s2 ) {
|
||||||
|
arg->r_opt = -3; /* missing argument */
|
||||||
|
}
|
||||||
|
else if( !argpos && *s2 == '-' && (opts[i].flags & 8) ) {
|
||||||
|
/* the argument is optional and the next seems to be
|
||||||
|
* an option. We do not check this possible option
|
||||||
|
* but assume no argument */
|
||||||
|
arg->r_type = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
set_opt_arg(arg, opts[i].flags, s2);
|
||||||
|
if( !argpos ) {
|
||||||
|
argc--; argv++; idx++; /* skip one */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { /* does not take an argument */
|
||||||
|
if( argpos )
|
||||||
|
arg->r_type = -6; /* argument not expected */
|
||||||
|
else
|
||||||
|
arg->r_type = 0;
|
||||||
|
}
|
||||||
|
argc--; argv++; idx++; /* set to next one */
|
||||||
|
}
|
||||||
|
else if( (*s == '-' && s[1]) || arg->internal.inarg ) { /* short option */
|
||||||
|
int dash_kludge = 0;
|
||||||
|
i = 0;
|
||||||
|
if( !arg->internal.inarg ) {
|
||||||
|
arg->internal.inarg++;
|
||||||
|
if( arg->flags & (1<<5) ) {
|
||||||
|
for(i=0; opts[i].short_opt; i++ )
|
||||||
|
if( opts[i].long_opt && !strcmp( opts[i].long_opt, s+1)) {
|
||||||
|
dash_kludge=1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s += arg->internal.inarg;
|
||||||
|
|
||||||
|
if( !dash_kludge ) {
|
||||||
|
for(i=0; opts[i].short_opt; i++ )
|
||||||
|
if( opts[i].short_opt == *s )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !opts[i].short_opt && ( *s == 'h' || *s == '?' ) )
|
||||||
|
show_help(opts, arg->flags);
|
||||||
|
|
||||||
|
arg->r_opt = opts[i].short_opt;
|
||||||
|
if( !opts[i].short_opt ) {
|
||||||
|
arg->r_opt = (opts[i].flags & 256)? -7:-2;
|
||||||
|
arg->internal.inarg++; /* point to the next arg */
|
||||||
|
arg->r.ret_str = s;
|
||||||
|
}
|
||||||
|
else if( (opts[i].flags & 7) ) {
|
||||||
|
if( s[1] && !dash_kludge ) {
|
||||||
|
s2 = s+1;
|
||||||
|
set_opt_arg(arg, opts[i].flags, s2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
s2 = argv[1];
|
||||||
|
if( !s2 && (opts[i].flags & 8) ) { /* no argument but it is okay*/
|
||||||
|
arg->r_type = 0; /* because it is optional */
|
||||||
|
}
|
||||||
|
else if( !s2 ) {
|
||||||
|
arg->r_opt = -3; /* missing argument */
|
||||||
|
}
|
||||||
|
else if( *s2 == '-' && s2[1] && (opts[i].flags & 8) ) {
|
||||||
|
/* the argument is optional and the next seems to be
|
||||||
|
* an option. We do not check this possible option
|
||||||
|
* but assume no argument */
|
||||||
|
arg->r_type = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
set_opt_arg(arg, opts[i].flags, s2);
|
||||||
|
argc--; argv++; idx++; /* skip one */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s = "x"; /* so that !s[1] yields false */
|
||||||
|
}
|
||||||
|
else { /* does not take an argument */
|
||||||
|
arg->r_type = 0;
|
||||||
|
arg->internal.inarg++; /* point to the next arg */
|
||||||
|
}
|
||||||
|
if( !s[1] || dash_kludge ) { /* no more concatenated short options */
|
||||||
|
arg->internal.inarg = 0;
|
||||||
|
argc--; argv++; idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( arg->flags & (1<<2) ) {
|
||||||
|
arg->r_opt = -1; /* not an option but a argument */
|
||||||
|
arg->r_type = 2;
|
||||||
|
arg->r.ret_str = s;
|
||||||
|
argc--; argv++; idx++; /* set to next one */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
arg->internal.stopped = 1; /* stop option processing */
|
||||||
|
goto next_one;
|
||||||
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
|
*arg->argc = argc;
|
||||||
|
*arg->argv = argv;
|
||||||
|
arg->internal.idx = idx;
|
||||||
|
return arg->r_opt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s)
|
||||||
|
{
|
||||||
|
int base = (flags & 16)? 0 : 10;
|
||||||
|
|
||||||
|
switch( arg->r_type = (flags & 7) ) {
|
||||||
|
case 1: /* takes int argument */
|
||||||
|
arg->r.ret_int = (int)strtol(s,NULL,base);
|
||||||
|
return 0;
|
||||||
|
case 3: /* takes long argument */
|
||||||
|
arg->r.ret_long= strtol(s,NULL,base);
|
||||||
|
return 0;
|
||||||
|
case 4: /* takes ulong argument */
|
||||||
|
arg->r.ret_ulong= strtoul(s,NULL,base);
|
||||||
|
return 0;
|
||||||
|
case 2: /* takes string argument */
|
||||||
|
default:
|
||||||
|
arg->r.ret_str = s;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
long_opt_strlen( ARGPARSE_OPTS *o )
|
||||||
|
{
|
||||||
|
size_t n = strlen(o->long_opt);
|
||||||
|
|
||||||
|
if( o->description && *o->description == '|' ) {
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
s=o->description+1;
|
||||||
|
if( *s != '=' )
|
||||||
|
n++;
|
||||||
|
for(; *s && *s != '|'; s++ )
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* Print formatted help. The description string has some special
|
||||||
|
* meanings:
|
||||||
|
* - A description string which is "@" suppresses help output for
|
||||||
|
* this option
|
||||||
|
* - a description,ine which starts with a '@' and is followed by
|
||||||
|
* any other characters is printed as is; this may be used for examples
|
||||||
|
* ans such.
|
||||||
|
* - A description which starts with a '|' outputs the string between this
|
||||||
|
* bar and the next one as arguments of the long option.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
show_help( ARGPARSE_OPTS *opts, unsigned flags )
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
show_version();
|
||||||
|
putchar('\n');
|
||||||
|
s = strusage(41);
|
||||||
|
puts(s);
|
||||||
|
if( opts[0].description ) { /* auto format the option description */
|
||||||
|
int i,j, indent;
|
||||||
|
/* get max. length of long options */
|
||||||
|
for(i=indent=0; opts[i].short_opt; i++ ) {
|
||||||
|
if( opts[i].long_opt )
|
||||||
|
if( !opts[i].description || *opts[i].description != '@' )
|
||||||
|
if( (j=long_opt_strlen(opts+i)) > indent && j < 35 )
|
||||||
|
indent = j;
|
||||||
|
}
|
||||||
|
/* example: " -v, --verbose Viele Sachen ausgeben" */
|
||||||
|
indent += 10;
|
||||||
|
if( *opts[0].description != '@' )
|
||||||
|
puts("Options:");
|
||||||
|
for(i=0; opts[i].short_opt; i++ ) {
|
||||||
|
s = _( opts[i].description );
|
||||||
|
if( s && *s== '@' && !s[1] ) /* hide this line */
|
||||||
|
continue;
|
||||||
|
if( s && *s == '@' ) { /* unindented comment only line */
|
||||||
|
for(s++; *s; s++ ) {
|
||||||
|
if( *s == '\n' ) {
|
||||||
|
if( s[1] )
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
putchar(*s);
|
||||||
|
}
|
||||||
|
putchar('\n');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
j = 3;
|
||||||
|
if( opts[i].short_opt < 256 ) {
|
||||||
|
printf(" -%c", opts[i].short_opt );
|
||||||
|
if( !opts[i].long_opt ) {
|
||||||
|
if(s && *s == '|' ) {
|
||||||
|
putchar(' '); j++;
|
||||||
|
for(s++ ; *s && *s != '|'; s++, j++ )
|
||||||
|
putchar(*s);
|
||||||
|
if( *s )
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fputs(" ", stdout);
|
||||||
|
if( opts[i].long_opt ) {
|
||||||
|
j += printf("%c --%s", opts[i].short_opt < 256?',':' ',
|
||||||
|
opts[i].long_opt );
|
||||||
|
if(s && *s == '|' ) {
|
||||||
|
if( *++s != '=' ) {
|
||||||
|
putchar(' ');
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
for( ; *s && *s != '|'; s++, j++ )
|
||||||
|
putchar(*s);
|
||||||
|
if( *s )
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
fputs(" ", stdout);
|
||||||
|
j += 3;
|
||||||
|
}
|
||||||
|
for(;j < indent; j++ )
|
||||||
|
putchar(' ');
|
||||||
|
if( s ) {
|
||||||
|
if( *s && j > indent ) {
|
||||||
|
putchar('\n');
|
||||||
|
for(j=0;j < indent; j++ )
|
||||||
|
putchar(' ');
|
||||||
|
}
|
||||||
|
for(; *s; s++ ) {
|
||||||
|
if( *s == '\n' ) {
|
||||||
|
if( s[1] ) {
|
||||||
|
putchar('\n');
|
||||||
|
for(j=0;j < indent; j++ )
|
||||||
|
putchar(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
putchar(*s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
if( flags & 32 )
|
||||||
|
puts("\n(A single dash may be used instead of the double ones)");
|
||||||
|
}
|
||||||
|
if( (s=strusage(19)) ) { /* bug reports to ... */
|
||||||
|
putchar('\n');
|
||||||
|
fputs(s, stdout);
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
show_version()
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
int i;
|
||||||
|
/* version line */
|
||||||
|
fputs(strusage(11), stdout);
|
||||||
|
if( (s=strusage(12)) )
|
||||||
|
printf(" (%s)", s );
|
||||||
|
printf(" %s\n", strusage(13) );
|
||||||
|
/* additional version lines */
|
||||||
|
for(i=20; i < 30; i++ )
|
||||||
|
if( (s=strusage(i)) )
|
||||||
|
printf("%s\n", s );
|
||||||
|
/* copyright string */
|
||||||
|
if( (s=strusage(14)) )
|
||||||
|
printf("%s\n", s );
|
||||||
|
/* copying conditions */
|
||||||
|
if( (s=strusage(15)) )
|
||||||
|
fputs(s, stdout);
|
||||||
|
/* thanks */
|
||||||
|
if( (s=strusage(18)) )
|
||||||
|
fputs(s, stdout);
|
||||||
|
/* additional program info */
|
||||||
|
for(i=30; i < 40; i++ )
|
||||||
|
if( (s=strusage(i)) )
|
||||||
|
fputs( (const byte*)s, stdout);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
usage( int level )
|
||||||
|
{
|
||||||
|
if( !level ) {
|
||||||
|
fprintf(stderr,"%s %s; %s\n", strusage(11), strusage(13),
|
||||||
|
strusage(14) );
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
else if( level == 1 ) {
|
||||||
|
fputs(strusage(40),stderr);
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
else if( level == 2 ) {
|
||||||
|
puts(strusage(41));
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Level
|
||||||
|
* 0: Copyright String auf stderr ausgeben
|
||||||
|
* 1: Kurzusage auf stderr ausgeben und beenden
|
||||||
|
* 2: Langusage auf stdout ausgeben und beenden
|
||||||
|
* 11: name of program
|
||||||
|
* 12: optional name of package which includes this program.
|
||||||
|
* 13: version string
|
||||||
|
* 14: copyright string
|
||||||
|
* 15: Short copying conditions (with LFs)
|
||||||
|
* 16: Long copying conditions (with LFs)
|
||||||
|
* 17: Optional printable OS name
|
||||||
|
* 18: Optional thanks list (with LFs)
|
||||||
|
* 19: Bug report info
|
||||||
|
*20..29: Additional lib version strings.
|
||||||
|
*30..39: Additional program info (with LFs)
|
||||||
|
* 40: short usage note (with LF)
|
||||||
|
* 41: long usage note (with LF)
|
||||||
|
*/
|
||||||
|
const char *
|
||||||
|
strusage( int level )
|
||||||
|
{
|
||||||
|
const char *p = strusage_handler? strusage_handler(level) : NULL;
|
||||||
|
|
||||||
|
if( p )
|
||||||
|
return p;
|
||||||
|
|
||||||
|
switch( level ) {
|
||||||
|
case 11: p = "foo"; break;
|
||||||
|
case 13: p = "0.0"; break;
|
||||||
|
case 14: p = "Copyright (C) 2000 Free Software Foundation, Inc."; break;
|
||||||
|
case 15: p =
|
||||||
|
"This program comes with ABSOLUTELY NO WARRANTY.\n"
|
||||||
|
"This is free software, and you are welcome to redistribute it\n"
|
||||||
|
"under certain conditions. See the file COPYING for details.\n"; break;
|
||||||
|
case 16: p =
|
||||||
|
"This is free software; you can redistribute it and/or modify\n"
|
||||||
|
"it under the terms of the GNU General Public License as published by\n"
|
||||||
|
"the Free Software Foundation; either version 2 of the License, or\n"
|
||||||
|
"(at your option) any later version.\n\n"
|
||||||
|
"It is distributed in the hope that it will be useful,\n"
|
||||||
|
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||||
|
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
||||||
|
"GNU General Public License for more details.\n\n"
|
||||||
|
"You should have received a copy of the GNU General Public License\n"
|
||||||
|
"along with this program; if not, write to the Free Software\n"
|
||||||
|
"Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n";
|
||||||
|
break;
|
||||||
|
case 40: /* short and long usage */
|
||||||
|
case 41: p = ""; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_strusage( const char *(*f)( int ) )
|
||||||
|
{
|
||||||
|
strusage_handler = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TEST
|
||||||
|
static struct {
|
||||||
|
int verbose;
|
||||||
|
int debug;
|
||||||
|
char *outfile;
|
||||||
|
char *crf;
|
||||||
|
int myopt;
|
||||||
|
int echo;
|
||||||
|
int a_long_one;
|
||||||
|
}opt;
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
ARGPARSE_OPTS opts[] = {
|
||||||
|
{ 'v', "verbose", 0 , "Laut sein"},
|
||||||
|
{ 'e', "echo" , 0 , "Zeile ausgeben, damit wir sehen, was wir einegegeben haben"},
|
||||||
|
{ 'd', "debug", 0 , "Debug\nfalls mal etasws\nSchief geht"},
|
||||||
|
{ 'o', "output", 2 },
|
||||||
|
{ 'c', "cross-ref", 2|8, "cross-reference erzeugen\n" },
|
||||||
|
{ 'm', "my-option", 1|8 },
|
||||||
|
{ 500, "a-long-option", 0 },
|
||||||
|
{0} };
|
||||||
|
ARGPARSE_ARGS pargs = { &argc, &argv, 2|4|32 };
|
||||||
|
int i;
|
||||||
|
|
||||||
|
while( ArgParse( &pargs, opts) ) {
|
||||||
|
switch( pargs.r_opt ) {
|
||||||
|
case -1 : printf( "arg=`%s'\n", pargs.r.ret_str); break;
|
||||||
|
case 'v': opt.verbose++; break;
|
||||||
|
case 'e': opt.echo++; break;
|
||||||
|
case 'd': opt.debug++; break;
|
||||||
|
case 'o': opt.outfile = pargs.r.ret_str; break;
|
||||||
|
case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
|
||||||
|
case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
|
||||||
|
case 500: opt.a_long_one++; break;
|
||||||
|
default : pargs.err = 1; break; /* force warning output */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(i=0; i < argc; i++ )
|
||||||
|
printf("%3d -> (%s)\n", i, argv[i] );
|
||||||
|
puts("Options:");
|
||||||
|
if( opt.verbose )
|
||||||
|
printf(" verbose=%d\n", opt.verbose );
|
||||||
|
if( opt.debug )
|
||||||
|
printf(" debug=%d\n", opt.debug );
|
||||||
|
if( opt.outfile )
|
||||||
|
printf(" outfile=`%s'\n", opt.outfile );
|
||||||
|
if( opt.crf )
|
||||||
|
printf(" crffile=`%s'\n", opt.crf );
|
||||||
|
if( opt.myopt )
|
||||||
|
printf(" myopt=%d\n", opt.myopt );
|
||||||
|
if( opt.a_long_one )
|
||||||
|
printf(" a-long-one=%d\n", opt.a_long_one );
|
||||||
|
if( opt.echo )
|
||||||
|
printf(" echo=%d\n", opt.echo );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**** bottom of file ****/
|
67
jnlib/argparse.h
Normal file
67
jnlib/argparse.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/* argparse.h
|
||||||
|
* Copyright (C) 1998,1999 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBJNLIB_ARGPARSE_H
|
||||||
|
#define LIBJNLIB_ARGPARSE_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int *argc; /* pointer to argc (value subject to change) */
|
||||||
|
char ***argv; /* pointer to argv (value subject to change) */
|
||||||
|
unsigned flags; /* Global flags (DO NOT CHANGE) */
|
||||||
|
int err; /* print error about last option */
|
||||||
|
/* 1 = warning, 2 = abort */
|
||||||
|
int r_opt; /* return option */
|
||||||
|
int r_type; /* type of return value (0 = no argument found)*/
|
||||||
|
union {
|
||||||
|
int ret_int;
|
||||||
|
long ret_long;
|
||||||
|
unsigned long ret_ulong;
|
||||||
|
char *ret_str;
|
||||||
|
} r; /* Return values */
|
||||||
|
struct {
|
||||||
|
int idx;
|
||||||
|
int inarg;
|
||||||
|
int stopped;
|
||||||
|
const char *last;
|
||||||
|
void *aliases;
|
||||||
|
const void *cur_alias;
|
||||||
|
} internal; /* DO NOT CHANGE */
|
||||||
|
} ARGPARSE_ARGS;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int short_opt;
|
||||||
|
const char *long_opt;
|
||||||
|
unsigned flags;
|
||||||
|
const char *description; /* optional option description */
|
||||||
|
} ARGPARSE_OPTS;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts);
|
||||||
|
int optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
|
||||||
|
ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts);
|
||||||
|
void usage( int level );
|
||||||
|
const char *strusage( int level );
|
||||||
|
void set_strusage( const char *(*f)( int ) );
|
||||||
|
|
||||||
|
#endif /*LIBJNLIB_ARGPARSE_H*/
|
346
jnlib/dotlock.c
Normal file
346
jnlib/dotlock.c
Normal file
@ -0,0 +1,346 @@
|
|||||||
|
/* dotlock.c - dotfile locking
|
||||||
|
* Copyright (C) 1998,2000 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#ifndef HAVE_DOSISH_SYSTEM
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#endif
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include "libjnlib-config.h"
|
||||||
|
#include "dotlock.h"
|
||||||
|
|
||||||
|
struct dotlock_handle {
|
||||||
|
struct dotlock_handle *next;
|
||||||
|
char *tname; /* name of lockfile template */
|
||||||
|
char *lockname; /* name of the real lockfile */
|
||||||
|
int locked; /* lock status */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static DOTLOCK all_lockfiles;
|
||||||
|
|
||||||
|
static int read_lockfile( const char *name );
|
||||||
|
static void remove_lockfiles(void);
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* Create a lockfile with the given name and return an object of
|
||||||
|
* type DOTLOCK which may be used later to actually do the lock.
|
||||||
|
* A cleanup routine gets installed to cleanup left over locks
|
||||||
|
* or other files used together with the lockmechanism.
|
||||||
|
* Althoug the function is called dotlock, this does not necessarily
|
||||||
|
* mean that real lockfiles are used - the function may decide to
|
||||||
|
* use fcntl locking. Calling the function with NULL only install
|
||||||
|
* the atexit handler and maybe used to assure that the cleanup
|
||||||
|
* is called after all other atexit handlers.
|
||||||
|
*
|
||||||
|
* Notes: This function creates a lock file in the same directory
|
||||||
|
* as file_to_lock with the name "file_to_lock.lock"
|
||||||
|
* A temporary file ".#lk.<hostname>.pid[.threadid] is used.
|
||||||
|
* This function does nothing for Windoze.
|
||||||
|
*/
|
||||||
|
DOTLOCK
|
||||||
|
create_dotlock( const char *file_to_lock )
|
||||||
|
{
|
||||||
|
static int initialized;
|
||||||
|
DOTLOCK h;
|
||||||
|
int fd = -1;
|
||||||
|
char pidstr[16];
|
||||||
|
#ifndef HAVE_DOSISH_SYSTEM
|
||||||
|
struct utsname utsbuf;
|
||||||
|
#endif
|
||||||
|
const char *nodename;
|
||||||
|
const char *dirpart;
|
||||||
|
int dirpartlen;
|
||||||
|
|
||||||
|
if( !initialized ) {
|
||||||
|
atexit( remove_lockfiles );
|
||||||
|
initialized = 1;
|
||||||
|
}
|
||||||
|
if( !file_to_lock )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
h = jnlib_xcalloc( 1, sizeof *h );
|
||||||
|
#ifndef HAVE_DOSISH_SYSTEM
|
||||||
|
sprintf( pidstr, "%10d\n", (int)getpid() );
|
||||||
|
/* fixme: add the hostname to the second line (FQDN or IP addr?) */
|
||||||
|
|
||||||
|
/* create a temporary file */
|
||||||
|
if( uname( &utsbuf ) )
|
||||||
|
nodename = "unknown";
|
||||||
|
else
|
||||||
|
nodename = utsbuf.nodename;
|
||||||
|
|
||||||
|
if( !(dirpart = strrchr( file_to_lock, '/' )) ) {
|
||||||
|
dirpart = ".";
|
||||||
|
dirpartlen = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dirpartlen = dirpart - file_to_lock;
|
||||||
|
dirpart = file_to_lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _REENTRANT
|
||||||
|
/* fixme: aquire mutex on all_lockfiles */
|
||||||
|
#endif
|
||||||
|
h->next = all_lockfiles;
|
||||||
|
all_lockfiles = h;
|
||||||
|
|
||||||
|
h->tname = jnlib_xmalloc( dirpartlen + 6+30+ strlen(nodename) + 11 );
|
||||||
|
sprintf( h->tname, "%.*s/.#lk%p.%s.%d",
|
||||||
|
dirpartlen, dirpart, h, nodename, (int)getpid() );
|
||||||
|
|
||||||
|
do {
|
||||||
|
errno = 0;
|
||||||
|
fd = open( h->tname, O_WRONLY|O_CREAT|O_EXCL,
|
||||||
|
S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR );
|
||||||
|
} while( fd == -1 && errno == EINTR );
|
||||||
|
if( fd == -1 ) {
|
||||||
|
all_lockfiles = h->next;
|
||||||
|
log_error( "failed to create temporary file `%s': %s\n",
|
||||||
|
h->tname, strerror(errno));
|
||||||
|
jnlib_free(h->tname);
|
||||||
|
jnlib_free(h);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if( write(fd, pidstr, 11 ) != 11 ) {
|
||||||
|
all_lockfiles = h->next;
|
||||||
|
#ifdef _REENTRANT
|
||||||
|
/* release mutex */
|
||||||
|
#endif
|
||||||
|
log_fatal( "error writing to `%s': %s\n", h->tname, strerror(errno) );
|
||||||
|
close(fd);
|
||||||
|
unlink(h->tname);
|
||||||
|
jnlib_free(h->tname);
|
||||||
|
jnlib_free(h);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if( close(fd) ) {
|
||||||
|
all_lockfiles = h->next;
|
||||||
|
#ifdef _REENTRANT
|
||||||
|
/* release mutex */
|
||||||
|
#endif
|
||||||
|
log_error( "error closing `%s': %s\n", h->tname, strerror(errno));
|
||||||
|
unlink(h->tname);
|
||||||
|
jnlib_free(h->tname);
|
||||||
|
jnlib_free(h);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _REENTRANT
|
||||||
|
/* release mutex */
|
||||||
|
#endif
|
||||||
|
#endif /* !HAVE_DOSISH_SYSTEM */
|
||||||
|
h->lockname = jnlib_xmalloc( strlen(file_to_lock) + 6 );
|
||||||
|
strcpy(stpcpy(h->lockname, file_to_lock), ".lock");
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
maybe_deadlock( DOTLOCK h )
|
||||||
|
{
|
||||||
|
DOTLOCK r;
|
||||||
|
|
||||||
|
for( r=all_lockfiles; r; r = r->next ) {
|
||||||
|
if( r != h && r->locked )
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* Do a lock on H. A TIMEOUT of 0 returns immediately,
|
||||||
|
* -1 waits forever (hopefully not), other
|
||||||
|
* values are timeouts in milliseconds.
|
||||||
|
* Returns: 0 on success
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
make_dotlock( DOTLOCK h, long timeout )
|
||||||
|
{
|
||||||
|
#ifdef HAVE_DOSISH_SYSTEM
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
int pid;
|
||||||
|
const char *maybe_dead="";
|
||||||
|
int backoff=0;
|
||||||
|
|
||||||
|
if( h->locked ) {
|
||||||
|
log_debug("oops, `%s' is already locked\n", h->lockname );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
if( !link(h->tname, h->lockname) ) {
|
||||||
|
/* fixme: better use stat to check the link count */
|
||||||
|
h->locked = 1;
|
||||||
|
return 0; /* okay */
|
||||||
|
}
|
||||||
|
if( errno != EEXIST ) {
|
||||||
|
log_error( "lock not made: link() failed: %s\n", strerror(errno) );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if( (pid = read_lockfile(h->lockname)) == -1 ) {
|
||||||
|
if( errno != ENOENT ) {
|
||||||
|
log_info("cannot read lockfile\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
log_info( "lockfile disappeared\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if( pid == getpid() ) {
|
||||||
|
log_info( "Oops: lock already hold by us\n");
|
||||||
|
h->locked = 1;
|
||||||
|
return 0; /* okay */
|
||||||
|
}
|
||||||
|
else if( kill(pid, 0) && errno == ESRCH ) {
|
||||||
|
maybe_dead = " - probably dead";
|
||||||
|
#if 0 /* we should not do this without checking the permissions */
|
||||||
|
/* and the hostname */
|
||||||
|
log_info( "removing stale lockfile (created by %d)", pid );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if( timeout == -1 ) {
|
||||||
|
struct timeval tv;
|
||||||
|
log_info( "waiting for lock (hold by %d%s) %s...\n",
|
||||||
|
pid, maybe_dead, maybe_deadlock(h)? "(deadlock?) ":"");
|
||||||
|
|
||||||
|
|
||||||
|
/* can't use sleep, cause signals may be blocked */
|
||||||
|
tv.tv_sec = 1 + backoff;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
select(0, NULL, NULL, NULL, &tv);
|
||||||
|
if( backoff < 10 )
|
||||||
|
backoff++ ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/*not reached */
|
||||||
|
#endif /* !HAVE_DOSISH_SYSTEM */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* release a lock
|
||||||
|
* Returns: 0 := success
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
release_dotlock( DOTLOCK h )
|
||||||
|
{
|
||||||
|
#ifdef HAVE_DOSISH_SYSTEM
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
int pid;
|
||||||
|
|
||||||
|
if( !h->locked ) {
|
||||||
|
log_debug("oops, `%s' is not locked\n", h->lockname );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = read_lockfile( h->lockname );
|
||||||
|
if( pid == -1 ) {
|
||||||
|
log_error( "release_dotlock: lockfile error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if( pid != getpid() ) {
|
||||||
|
log_error( "release_dotlock: not our lock (pid=%d)\n", pid);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if( unlink( h->lockname ) ) {
|
||||||
|
log_error( "release_dotlock: error removing lockfile `%s'",
|
||||||
|
h->lockname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* fixme: check that the link count is now 1 */
|
||||||
|
h->locked = 0;
|
||||||
|
return 0;
|
||||||
|
#endif /* !HAVE_DOSISH_SYSTEM */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* Read the lock file and return the pid, returns -1 on error.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
read_lockfile( const char *name )
|
||||||
|
{
|
||||||
|
#ifdef HAVE_DOSISH_SYSTEM
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
int fd, pid;
|
||||||
|
char pidstr[16];
|
||||||
|
|
||||||
|
if( (fd = open(name, O_RDONLY)) == -1 ) {
|
||||||
|
int e = errno;
|
||||||
|
log_debug("error opening lockfile `%s': %s\n", name, strerror(errno) );
|
||||||
|
errno = e;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if( read(fd, pidstr, 10 ) != 10 ) { /* Read 10 digits w/o newline */
|
||||||
|
log_debug("error reading lockfile `%s'", name );
|
||||||
|
close(fd);
|
||||||
|
errno = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pidstr[10] = 0; /* terminate pid string */
|
||||||
|
close(fd);
|
||||||
|
pid = atoi(pidstr);
|
||||||
|
if( !pid || pid == -1 ) {
|
||||||
|
log_error("invalid pid %d in lockfile `%s'", pid, name );
|
||||||
|
errno = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return pid;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
remove_lockfiles()
|
||||||
|
{
|
||||||
|
#ifndef HAVE_DOSISH_SYSTEM
|
||||||
|
DOTLOCK h, h2;
|
||||||
|
|
||||||
|
h = all_lockfiles;
|
||||||
|
all_lockfiles = NULL;
|
||||||
|
|
||||||
|
while( h ) {
|
||||||
|
h2 = h->next;
|
||||||
|
if( h->locked )
|
||||||
|
unlink( h->lockname );
|
||||||
|
unlink(h->tname);
|
||||||
|
jnlib_free(h->tname);
|
||||||
|
jnlib_free(h->lockname);
|
||||||
|
jnlib_free(h);
|
||||||
|
h = h2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
32
jnlib/dotlock.h
Normal file
32
jnlib/dotlock.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* dotlock.h
|
||||||
|
* Copyright (C) 2000 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBJNLIB_DOTLOCK_H
|
||||||
|
#define LIBJNLIB_DOTLOCK_H
|
||||||
|
|
||||||
|
struct dotlock_handle;
|
||||||
|
typedef struct dotlock_handle *DOTLOCK;
|
||||||
|
|
||||||
|
DOTLOCK create_dotlock( const char *file_to_lock );
|
||||||
|
int make_dotlock( DOTLOCK h, long timeout );
|
||||||
|
int release_dotlock( DOTLOCK h );
|
||||||
|
|
||||||
|
|
||||||
|
#endif /*LIBJNLIB_DOTLOCK_H*/
|
75
jnlib/libjnlib-config.h
Normal file
75
jnlib/libjnlib-config.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/* libjnlib-config.h - local configuration of the jnlib functions
|
||||||
|
* Copyright (C) 2000 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* This header is to be included only by the files in this directory
|
||||||
|
* it should not be used by other modules.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBJNLIB_CONFIG_H
|
||||||
|
#define LIBJNLIB_CONFIG_H
|
||||||
|
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "logging.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_SIMPLE_GETTEXT
|
||||||
|
int set_gettext_file( const char *filename );
|
||||||
|
const char *gettext( const char *msgid );
|
||||||
|
|
||||||
|
#define _(a) gettext (a)
|
||||||
|
#define N_(a) (a)
|
||||||
|
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_LOCALE_H
|
||||||
|
#include <locale.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_NLS
|
||||||
|
#include <libintl.h>
|
||||||
|
#define _(a) gettext (a)
|
||||||
|
#ifdef gettext_noop
|
||||||
|
#define N_(a) gettext_noop (a)
|
||||||
|
#else
|
||||||
|
#define N_(a) (a)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define _(a) (a)
|
||||||
|
#define N_(a) (a)
|
||||||
|
#endif
|
||||||
|
#endif /* !USE_SIMPLE_GETTEXT */
|
||||||
|
|
||||||
|
|
||||||
|
#define jnlib_xmalloc(a) xmalloc( (a) )
|
||||||
|
#define jnlib_xcalloc(a,b) xcalloc( (a), (b) )
|
||||||
|
#define jnlib_xrealloc(a,n) xrealloc( (a), (n) )
|
||||||
|
#define jnlib_xstrdup(a) xstrdup( (a) )
|
||||||
|
#define jnlib_free(a) free( (a) )
|
||||||
|
|
||||||
|
#define jnlib_log_debug log_debug
|
||||||
|
#define jnlib_log_info log_info
|
||||||
|
#define jnlib_log_error log_error
|
||||||
|
#define jnlib_log_fatal log_fatal
|
||||||
|
#define jnlib_log_bug log_bug
|
||||||
|
|
||||||
|
|
||||||
|
#endif /*LIBJNUTIL_CONFIG_H*/
|
||||||
|
|
257
jnlib/logging.c
Normal file
257
jnlib/logging.c
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
/* logging.c - useful logging functions
|
||||||
|
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* This file should replace logger.c in the future - for now it is not
|
||||||
|
* used by GnuPG but by GPA.
|
||||||
|
* It is a quite simple implemenation but sufficient for most purposes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <time.h>
|
||||||
|
#ifdef __MINGW32__
|
||||||
|
#include <io.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "libjnlib-config.h"
|
||||||
|
#include "logging.h"
|
||||||
|
|
||||||
|
enum my_log_levels {
|
||||||
|
MY_LOG_BEGIN, /* only print the timestamp if configured */
|
||||||
|
MY_LOG_CONT,
|
||||||
|
MY_LOG_INFO,
|
||||||
|
MY_LOG_WARN,
|
||||||
|
MY_LOG_ERROR,
|
||||||
|
MY_LOG_FATAL,
|
||||||
|
MY_LOG_BUG,
|
||||||
|
MY_LOG_DEBUG
|
||||||
|
};
|
||||||
|
|
||||||
|
static FILE *logstream;
|
||||||
|
static int use_time;
|
||||||
|
static int missing_lf;
|
||||||
|
static int errorcount;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static void
|
||||||
|
write2stderr( const char *s )
|
||||||
|
{
|
||||||
|
write( 2, s, strlen(s) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_die(int rc, const char *text )
|
||||||
|
{
|
||||||
|
write2stderr("\nFatal error: ");
|
||||||
|
write2stderr(text);
|
||||||
|
write2stderr("\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
log_get_errorcount (int clear)
|
||||||
|
{
|
||||||
|
int n = errorcount;
|
||||||
|
if( clear )
|
||||||
|
errorcount = 0;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
log_set_file( const char *name )
|
||||||
|
{
|
||||||
|
FILE *fp = (name && strcmp(name,"-"))? fopen(name, "a") : stderr;
|
||||||
|
if( !fp ) {
|
||||||
|
fprintf(stderr, "failed to open log file `%s': %s\n",
|
||||||
|
name, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setvbuf( fp, NULL, _IOLBF, 0 );
|
||||||
|
|
||||||
|
if( logstream && logstream != stderr )
|
||||||
|
fclose( logstream );
|
||||||
|
logstream = fp;
|
||||||
|
use_time = fp != stderr;
|
||||||
|
missing_lf = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
log_get_fd()
|
||||||
|
{
|
||||||
|
return fileno(logstream?logstream:stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_logv( int level, const char *fmt, va_list arg_ptr )
|
||||||
|
{
|
||||||
|
if( !logstream )
|
||||||
|
logstream = stderr;
|
||||||
|
|
||||||
|
if( missing_lf && level != MY_LOG_CONT )
|
||||||
|
putc('\n', logstream );
|
||||||
|
missing_lf = 0;
|
||||||
|
|
||||||
|
if( use_time && level != MY_LOG_CONT ) {
|
||||||
|
/* Note this does not work for multiple line logging as we would
|
||||||
|
* need to print to a buffer first */
|
||||||
|
struct tm *tp;
|
||||||
|
time_t atime = time(NULL);
|
||||||
|
|
||||||
|
tp = localtime( &atime );
|
||||||
|
fprintf( logstream, "%04d-%02d-%02d %02d:%02d:%02d ",
|
||||||
|
1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
|
||||||
|
tp->tm_hour, tp->tm_min, tp->tm_sec );
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( level ) {
|
||||||
|
case MY_LOG_BEGIN: break;
|
||||||
|
case MY_LOG_CONT: break;
|
||||||
|
case MY_LOG_INFO: break;
|
||||||
|
case MY_LOG_WARN: break;
|
||||||
|
case MY_LOG_ERROR: break;
|
||||||
|
case MY_LOG_FATAL: fputs("Fatal: ",logstream ); break;
|
||||||
|
case MY_LOG_BUG: fputs("Ohhhh jeeee: ", logstream); break;
|
||||||
|
case MY_LOG_DEBUG: fputs("DBG: ", logstream ); break;
|
||||||
|
default: fprintf(logstream,"[Unknown log level %d]: ", level ); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( fmt ) {
|
||||||
|
vfprintf(logstream,fmt,arg_ptr) ;
|
||||||
|
if( *fmt && fmt[strlen(fmt)-1] != '\n' )
|
||||||
|
missing_lf = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( level == MY_LOG_FATAL )
|
||||||
|
exit(2);
|
||||||
|
if( level == MY_LOG_BUG )
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_log( int level, const char *fmt, ... )
|
||||||
|
{
|
||||||
|
va_list arg_ptr ;
|
||||||
|
|
||||||
|
va_start( arg_ptr, fmt ) ;
|
||||||
|
do_logv( level, fmt, arg_ptr );
|
||||||
|
va_end(arg_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
log_info( const char *fmt, ... )
|
||||||
|
{
|
||||||
|
va_list arg_ptr ;
|
||||||
|
|
||||||
|
va_start( arg_ptr, fmt ) ;
|
||||||
|
do_logv( MY_LOG_INFO, fmt, arg_ptr );
|
||||||
|
va_end(arg_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
log_error( const char *fmt, ... )
|
||||||
|
{
|
||||||
|
va_list arg_ptr ;
|
||||||
|
|
||||||
|
va_start( arg_ptr, fmt ) ;
|
||||||
|
do_logv( MY_LOG_ERROR, fmt, arg_ptr );
|
||||||
|
va_end(arg_ptr);
|
||||||
|
/* protect against counter overflow */
|
||||||
|
if( errorcount < 30000 )
|
||||||
|
errorcount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
log_fatal( const char *fmt, ... )
|
||||||
|
{
|
||||||
|
va_list arg_ptr ;
|
||||||
|
|
||||||
|
va_start( arg_ptr, fmt ) ;
|
||||||
|
do_logv( MY_LOG_FATAL, fmt, arg_ptr );
|
||||||
|
va_end(arg_ptr);
|
||||||
|
abort(); /* never called, bugs it makes the compiler happy */
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
log_bug( const char *fmt, ... )
|
||||||
|
{
|
||||||
|
va_list arg_ptr ;
|
||||||
|
|
||||||
|
va_start( arg_ptr, fmt ) ;
|
||||||
|
do_logv( MY_LOG_BUG, fmt, arg_ptr );
|
||||||
|
va_end(arg_ptr);
|
||||||
|
abort(); /* never called, but it makes the compiler happy */
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
log_debug( const char *fmt, ... )
|
||||||
|
{
|
||||||
|
va_list arg_ptr ;
|
||||||
|
|
||||||
|
va_start( arg_ptr, fmt ) ;
|
||||||
|
do_logv( MY_LOG_DEBUG, fmt, arg_ptr );
|
||||||
|
va_end(arg_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
log_printf( const char *fmt, ... )
|
||||||
|
{
|
||||||
|
va_list arg_ptr ;
|
||||||
|
|
||||||
|
if( !fmt ) {
|
||||||
|
do_logv( MY_LOG_BEGIN, NULL, NULL );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
va_start( arg_ptr, fmt ) ;
|
||||||
|
do_logv( MY_LOG_CONT, fmt, arg_ptr );
|
||||||
|
va_end(arg_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
|
||||||
|
void
|
||||||
|
bug_at( const char *file, int line, const char *func )
|
||||||
|
{
|
||||||
|
do_log( MY_LOG_BUG,
|
||||||
|
("... this is a bug (%s:%d:%s)\n"), file, line, func );
|
||||||
|
abort(); /* never called, but it makes the compiler happy */
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void
|
||||||
|
bug_at( const char *file, int line )
|
||||||
|
{
|
||||||
|
do_log( MY_LOG_BUG,
|
||||||
|
_("you found a bug ... (%s:%d)\n"), file, line);
|
||||||
|
abort(); /* never called, but it makes the compiler happy */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
47
jnlib/logging.h
Normal file
47
jnlib/logging.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/* logging.h
|
||||||
|
* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBJNLIB_LOGGING_H
|
||||||
|
#define LIBJNLIB_LOGGING_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "mischelp.h"
|
||||||
|
|
||||||
|
int log_get_errorcount (int clear);
|
||||||
|
void log_set_file( const char *name );
|
||||||
|
int log_get_fd(void);
|
||||||
|
|
||||||
|
#ifdef JNLIB_GCC_M_FUNCTION
|
||||||
|
void bug_at( const char *file, int line, const char *func ) JNLIB_GCC_A_NR;
|
||||||
|
# define BUG() bug_at( __FILE__ , __LINE__, __FUNCTION__ )
|
||||||
|
#else
|
||||||
|
void bug_at( const char *file, int line );
|
||||||
|
# define BUG() bug_at( __FILE__ , __LINE__ )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void log_bug( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2);
|
||||||
|
void log_fatal( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2);
|
||||||
|
void log_error( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
|
||||||
|
void log_info( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
|
||||||
|
void log_debug( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
|
||||||
|
void log_printf( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /*LIBJNLIB_LOGGING_H*/
|
43
jnlib/mischelp.h
Normal file
43
jnlib/mischelp.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/* mischelp.h
|
||||||
|
* Copyright (C) 1999 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBJNLIB_MISCHELP_H
|
||||||
|
#define LIBJNLIB_MISCHHELP_H
|
||||||
|
|
||||||
|
|
||||||
|
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
|
||||||
|
#define DIMof(type,member) DIM(((type *)0)->member)
|
||||||
|
|
||||||
|
|
||||||
|
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
|
||||||
|
# define JNLIB_GCC_M_FUNCTION 1
|
||||||
|
# define JNLIB_GCC_A_NR __attribute__ ((noreturn))
|
||||||
|
# define JNLIB_GCC_A_PRINTF( f, a ) __attribute__ ((format (printf,f,a)))
|
||||||
|
# define JNLIB_GCC_A_NR_PRINTF( f, a ) \
|
||||||
|
__attribute__ ((noreturn, format (printf,f,a)))
|
||||||
|
#else
|
||||||
|
# define JNLIB_GCC_A_NR
|
||||||
|
# define JNLIB_GCC_A_PRINTF( f, a )
|
||||||
|
# define JNLIB_GCC_A_NR_PRINTF( f, a )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /*LIBJNLIB_MISCHELP_H*/
|
323
jnlib/stringhelp.c
Normal file
323
jnlib/stringhelp.c
Normal file
@ -0,0 +1,323 @@
|
|||||||
|
/* stringhelp.c - standard string helper functions
|
||||||
|
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "libjnlib-config.h"
|
||||||
|
#include "stringhelp.h"
|
||||||
|
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* look for the substring SUB in buffer and return a pointer to that
|
||||||
|
* substring in BUF or NULL if not found.
|
||||||
|
* Comparison is case-insensitive.
|
||||||
|
*/
|
||||||
|
const char *
|
||||||
|
memistr( const char *buf, size_t buflen, const char *sub )
|
||||||
|
{
|
||||||
|
const byte *t, *s ;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
for( t=buf, n=buflen, s=sub ; n ; t++, n-- )
|
||||||
|
if( toupper(*t) == toupper(*s) ) {
|
||||||
|
for( buf=t++, buflen = n--, s++;
|
||||||
|
n && toupper(*t) == toupper(*s); t++, s++, n-- )
|
||||||
|
;
|
||||||
|
if( !*s )
|
||||||
|
return buf;
|
||||||
|
t = buf; n = buflen; s = sub ;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* Wie strncpy(), aber es werden maximal n-1 zeichen kopiert und ein
|
||||||
|
* '\0' angehängt. Ist n = 0, so geschieht nichts, ist Destination
|
||||||
|
* gleich NULL, so wird via jnlib_xmalloc Speicher besorgt, ist dann nicht
|
||||||
|
* genügend Speicher vorhanden, so bricht die funktion ab.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
mem2str( char *dest , const void *src , size_t n )
|
||||||
|
{
|
||||||
|
char *d;
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
if( n ) {
|
||||||
|
if( !dest )
|
||||||
|
dest = jnlib_xmalloc( n ) ;
|
||||||
|
d = dest;
|
||||||
|
s = src ;
|
||||||
|
for(n--; n && *s; n-- )
|
||||||
|
*d++ = *s++;
|
||||||
|
*d = '\0' ;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* remove leading and trailing white spaces
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
trim_spaces( char *str )
|
||||||
|
{
|
||||||
|
char *string, *p, *mark;
|
||||||
|
|
||||||
|
string = str;
|
||||||
|
/* find first non space character */
|
||||||
|
for( p=string; *p && isspace( *(byte*)p ) ; p++ )
|
||||||
|
;
|
||||||
|
/* move characters */
|
||||||
|
for( (mark = NULL); (*string = *p); string++, p++ )
|
||||||
|
if( isspace( *(byte*)p ) ) {
|
||||||
|
if( !mark )
|
||||||
|
mark = string ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mark = NULL ;
|
||||||
|
if( mark )
|
||||||
|
*mark = '\0' ; /* remove trailing spaces */
|
||||||
|
|
||||||
|
return str ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* remove trailing white spaces
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
trim_trailing_spaces( char *string )
|
||||||
|
{
|
||||||
|
char *p, *mark;
|
||||||
|
|
||||||
|
for( mark = NULL, p = string; *p; p++ ) {
|
||||||
|
if( isspace( *(byte*)p ) ) {
|
||||||
|
if( !mark )
|
||||||
|
mark = p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mark = NULL;
|
||||||
|
}
|
||||||
|
if( mark )
|
||||||
|
*mark = '\0' ;
|
||||||
|
|
||||||
|
return string ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
trim_trailing_chars( byte *line, unsigned len, const char *trimchars )
|
||||||
|
{
|
||||||
|
byte *p, *mark;
|
||||||
|
unsigned n;
|
||||||
|
|
||||||
|
for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
|
||||||
|
if( strchr(trimchars, *p ) ) {
|
||||||
|
if( !mark )
|
||||||
|
mark = p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mark = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( mark ) {
|
||||||
|
*mark = 0;
|
||||||
|
return mark - line;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* remove trailing white spaces and return the length of the buffer
|
||||||
|
*/
|
||||||
|
unsigned
|
||||||
|
trim_trailing_ws( byte *line, unsigned len )
|
||||||
|
{
|
||||||
|
return trim_trailing_chars( line, len, " \t\r\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************
|
||||||
|
* Extract from a given path the filename component.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
make_basename(const char *filepath)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if ( !(p=strrchr(filepath, '/')) )
|
||||||
|
#ifdef HAVE_DRIVE_LETTERS
|
||||||
|
if ( !(p=strrchr(filepath, '\\')) )
|
||||||
|
if ( !(p=strrchr(filepath, ':')) )
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
return jnlib_xstrdup(filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return jnlib_xstrdup(p+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************
|
||||||
|
* Extract from a given filename the path prepended to it.
|
||||||
|
* If their isn't a path prepended to the filename, a dot
|
||||||
|
* is returned ('.').
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
make_dirname(const char *filepath)
|
||||||
|
{
|
||||||
|
char *dirname;
|
||||||
|
int dirname_length;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if ( !(p=strrchr(filepath, '/')) )
|
||||||
|
#ifdef HAVE_DRIVE_LETTERS
|
||||||
|
if ( !(p=strrchr(filepath, '\\')) )
|
||||||
|
if ( !(p=strrchr(filepath, ':')) )
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
return jnlib_xstrdup(".");
|
||||||
|
}
|
||||||
|
|
||||||
|
dirname_length = p-filepath;
|
||||||
|
dirname = jnlib_xmalloc(dirname_length+1);
|
||||||
|
strncpy(dirname, filepath, dirname_length);
|
||||||
|
dirname[dirname_length] = 0;
|
||||||
|
|
||||||
|
return dirname;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* Construct a filename from the NULL terminated list of parts.
|
||||||
|
* Tilde expansion is done here.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
make_filename( const char *first_part, ... )
|
||||||
|
{
|
||||||
|
va_list arg_ptr ;
|
||||||
|
size_t n;
|
||||||
|
const char *s;
|
||||||
|
char *name, *home, *p;
|
||||||
|
|
||||||
|
va_start( arg_ptr, first_part ) ;
|
||||||
|
n = strlen(first_part)+1;
|
||||||
|
while( (s=va_arg(arg_ptr, const char *)) )
|
||||||
|
n += strlen(s) + 1;
|
||||||
|
va_end(arg_ptr);
|
||||||
|
|
||||||
|
home = NULL;
|
||||||
|
if( *first_part == '~' && first_part[1] == '/'
|
||||||
|
&& (home = getenv("HOME")) && *home )
|
||||||
|
n += strlen(home);
|
||||||
|
|
||||||
|
name = jnlib_xmalloc(n);
|
||||||
|
p = home ? stpcpy(stpcpy(name,home), first_part+1)
|
||||||
|
: stpcpy(name, first_part);
|
||||||
|
va_start( arg_ptr, first_part ) ;
|
||||||
|
while( (s=va_arg(arg_ptr, const char *)) )
|
||||||
|
p = stpcpy(stpcpy(p,"/"), s);
|
||||||
|
va_end(arg_ptr);
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
compare_filenames( const char *a, const char *b )
|
||||||
|
{
|
||||||
|
/* ? check whether this is an absolute filename and
|
||||||
|
* resolve symlinks?
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_DRIVE_LETTERS
|
||||||
|
return stricmp(a,b);
|
||||||
|
#else
|
||||||
|
return strcmp(a,b);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
********** missing string functions *********
|
||||||
|
*********************************************/
|
||||||
|
|
||||||
|
#ifndef HAVE_STPCPY
|
||||||
|
char *
|
||||||
|
stpcpy(char *a,const char *b)
|
||||||
|
{
|
||||||
|
while( *b )
|
||||||
|
*a++ = *b++;
|
||||||
|
*a = 0;
|
||||||
|
|
||||||
|
return (char*)a;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_STRLWR
|
||||||
|
char *
|
||||||
|
strlwr(char *s)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
for(p=s; *p; p++ )
|
||||||
|
*p = tolower(*p);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef HAVE_STRCASECMP
|
||||||
|
int
|
||||||
|
strcasecmp( const char *a, const char *b )
|
||||||
|
{
|
||||||
|
for( ; *a && *b; a++, b++ ) {
|
||||||
|
if( *a != *b && toupper(*a) != toupper(*b) )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return *(const byte*)a - *(const byte*)b;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/****************
|
||||||
|
* mingw32/cpd has a memicmp()
|
||||||
|
*/
|
||||||
|
#ifndef HAVE_MEMICMP
|
||||||
|
int
|
||||||
|
memicmp( const char *a, const char *b, size_t n )
|
||||||
|
{
|
||||||
|
for( ; n; n--, a++, b++ )
|
||||||
|
if( *a != *b && toupper(*(const byte*)a) != toupper(*(const byte*)b) )
|
||||||
|
return *(const byte *)a - *(const byte*)b;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
65
jnlib/stringhelp.h
Normal file
65
jnlib/stringhelp.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/* stringhelp.h
|
||||||
|
* Copyright (C) 1998,1999 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBJNLIB_STRINGHELP_H
|
||||||
|
#define LIBJNLIB_STRINGHELP_H
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
const char *memistr( const char *buf, size_t buflen, const char *sub );
|
||||||
|
char *mem2str( char *, const void *, size_t);
|
||||||
|
char *trim_spaces( char *string );
|
||||||
|
char *trim_trailing_spaces( char *string );
|
||||||
|
unsigned int trim_trailing_chars( unsigned char *line, unsigned len,
|
||||||
|
const char *trimchars);
|
||||||
|
unsigned int trim_trailing_ws( unsigned char *line, unsigned len );
|
||||||
|
|
||||||
|
|
||||||
|
char *make_basename(const char *filepath);
|
||||||
|
char *make_dirname(const char *filepath);
|
||||||
|
char *make_filename( const char *first_part, ... );
|
||||||
|
int compare_filenames( const char *a, const char *b );
|
||||||
|
|
||||||
|
#ifndef HAVE_MEMICMP
|
||||||
|
int memicmp( const char *a, const char *b, size_t n );
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_STPCPY
|
||||||
|
char *stpcpy(char *a,const char *b);
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_STRLWR
|
||||||
|
char *strlwr(char *a);
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_STRTOUL
|
||||||
|
#define strtoul(a,b,c) ((unsigned long)strtol((a),(b),(c)))
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_MEMMOVE
|
||||||
|
#define memmove(d, s, n) bcopy((s), (d), (n))
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_STRICMP
|
||||||
|
#define stricmp(a,b) strcasecmp( (a), (b) )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef STR
|
||||||
|
#define STR(v) #v
|
||||||
|
#endif
|
||||||
|
#define STR2(v) STR(v)
|
||||||
|
|
||||||
|
|
||||||
|
#endif /*LIBJNLIB_STRINGHELP_H*/
|
101
jnlib/types.h
Normal file
101
jnlib/types.h
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/* types.h
|
||||||
|
* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBJNLIB_TYPES_H
|
||||||
|
#define LIBJNLIB_TYPES_H
|
||||||
|
|
||||||
|
/* The AC_CHECK_SIZEOF() in configure fails for some machines.
|
||||||
|
* we provide some fallback values here */
|
||||||
|
#if !SIZEOF_UNSIGNED_SHORT
|
||||||
|
#undef SIZEOF_UNSIGNED_SHORT
|
||||||
|
#define SIZEOF_UNSIGNED_SHORT 2
|
||||||
|
#endif
|
||||||
|
#if !SIZEOF_UNSIGNED_INT
|
||||||
|
#undef SIZEOF_UNSIGNED_INT
|
||||||
|
#define SIZEOF_UNSIGNED_INT 4
|
||||||
|
#endif
|
||||||
|
#if !SIZEOF_UNSIGNED_LONG
|
||||||
|
#undef SIZEOF_UNSIGNED_LONG
|
||||||
|
#define SIZEOF_UNSIGNED_LONG 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef HAVE_BYTE_TYPEDEF
|
||||||
|
#undef byte /* maybe there is a macro with this name */
|
||||||
|
typedef unsigned char byte;
|
||||||
|
#define HAVE_BYTE_TYPEDEF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_USHORT_TYPEDEF
|
||||||
|
#undef ushort /* maybe there is a macro with this name */
|
||||||
|
typedef unsigned short ushort;
|
||||||
|
#define HAVE_USHORT_TYPEDEF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_ULONG_TYPEDEF
|
||||||
|
#undef ulong /* maybe there is a macro with this name */
|
||||||
|
typedef unsigned long ulong;
|
||||||
|
#define HAVE_ULONG_TYPEDEF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_U16_TYPEDEF
|
||||||
|
#undef u16 /* maybe there is a macro with this name */
|
||||||
|
#if SIZEOF_UNSIGNED_INT == 2
|
||||||
|
typedef unsigned int u16;
|
||||||
|
#elif SIZEOF_UNSIGNED_SHORT == 2
|
||||||
|
typedef unsigned short u16;
|
||||||
|
#else
|
||||||
|
#error no typedef for u16
|
||||||
|
#endif
|
||||||
|
#define HAVE_U16_TYPEDEF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_U32_TYPEDEF
|
||||||
|
#undef u32 /* maybe there is a macro with this name */
|
||||||
|
#if SIZEOF_UNSIGNED_INT == 4
|
||||||
|
typedef unsigned int u32;
|
||||||
|
#elif SIZEOF_UNSIGNED_LONG == 4
|
||||||
|
typedef unsigned long u32;
|
||||||
|
#else
|
||||||
|
#error no typedef for u32
|
||||||
|
#endif
|
||||||
|
#define HAVE_U32_TYPEDEF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_U64_TYPEDEF
|
||||||
|
#undef u64 /* maybe there is a macro with this name */
|
||||||
|
#if SIZEOF_UNSIGNED_INT == 8
|
||||||
|
typedef unsigned int u64;
|
||||||
|
#define HAVE_U64_TYPEDEF
|
||||||
|
#elif SIZEOF_UNSIGNED_LONG == 8
|
||||||
|
typedef unsigned long u64;
|
||||||
|
#define HAVE_U64_TYPEDEF
|
||||||
|
#elif __GNUC__ >= 2 || defined(__SUNPRO_C)
|
||||||
|
typedef unsigned long long u64;
|
||||||
|
#define HAVE_U64_TYPEDEF
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /*LIBJNLIB_TYPES_H*/
|
88
jnlib/xmalloc.c
Normal file
88
jnlib/xmalloc.c
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/* xmalloc.c - standard malloc wrappers
|
||||||
|
* Copyright (C) 1999 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "libjnlib-config.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
out_of_core(void)
|
||||||
|
{
|
||||||
|
fputs("\nfatal: out of memory\n", stderr );
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
xmalloc( size_t n )
|
||||||
|
{
|
||||||
|
void *p = malloc( n );
|
||||||
|
if( !p )
|
||||||
|
out_of_core();
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
xrealloc( void *a, size_t n )
|
||||||
|
{
|
||||||
|
void *p = realloc( a, n );
|
||||||
|
if( !p )
|
||||||
|
out_of_core();
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
xcalloc( size_t n, size_t m )
|
||||||
|
{
|
||||||
|
void *p = calloc( n, m );
|
||||||
|
if( !p )
|
||||||
|
out_of_core();
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
xstrdup( const char *string )
|
||||||
|
{
|
||||||
|
void *p = xmalloc( strlen(string)+1 );
|
||||||
|
strcpy( p, string );
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
xstrcat2( const char *a, const char *b )
|
||||||
|
{
|
||||||
|
size_t n1;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if( !b )
|
||||||
|
return xstrdup( a );
|
||||||
|
|
||||||
|
n1 = strlen(a);
|
||||||
|
p = xmalloc( n1 + strlen(b) + 1 );
|
||||||
|
memcpy(p, a, n1 );
|
||||||
|
strcpy(p+n1, b );
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
31
jnlib/xmalloc.h
Normal file
31
jnlib/xmalloc.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/* xmalloc.h
|
||||||
|
* Copyright (C) 1999 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBJNLIB_XMALLOC_H
|
||||||
|
#define LIBJNLIB_XMALLOC_H
|
||||||
|
|
||||||
|
void *xmalloc( size_t n );
|
||||||
|
void *xrealloc( void *a, size_t n );
|
||||||
|
void *xcalloc( size_t n, size_t m );
|
||||||
|
char *xstrdup( const char *string );
|
||||||
|
char *xstrcat2( const char *a, const char *b );
|
||||||
|
|
||||||
|
|
||||||
|
#endif /*LIBJNLIB_XMALLOC_H*/
|
Loading…
Reference in New Issue
Block a user