mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-03 22:56:33 +02:00
added option file handling
This commit is contained in:
parent
935965049d
commit
68ea0f4353
38 changed files with 2772 additions and 551 deletions
233
util/argparse.c
233
util/argparse.c
|
@ -23,6 +23,7 @@
|
|||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util.h"
|
||||
|
@ -124,10 +125,202 @@
|
|||
*/
|
||||
|
||||
|
||||
static void set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s);
|
||||
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.index = 0;
|
||||
arg->internal.last = NULL;
|
||||
arg->internal.inarg = 0;
|
||||
arg->internal.stopped= 0;
|
||||
arg->err = 0;
|
||||
arg->flags |= 1<<15; /* mark initialized */
|
||||
if( *arg->argc < 0 )
|
||||
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
|
||||
s = "%s:%u: invalid option\n";
|
||||
log_error(s, filename, *lineno );
|
||||
}
|
||||
else {
|
||||
if( arg->r_opt == -3 )
|
||||
s = "Missing argument for option \"%.50s\"\n";
|
||||
else
|
||||
s = "Invalid option \"%.50s\"\n";
|
||||
log_error(s, arg->internal.last? arg->internal.last:"[??]" );
|
||||
}
|
||||
if( arg->err != 1 )
|
||||
exit(2);
|
||||
arg->err = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* 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.
|
||||
* Caller must free returned strings.
|
||||
* If called with FP set to NULL command line args are parse instead.
|
||||
*/
|
||||
int
|
||||
optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
|
||||
ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
|
||||
{
|
||||
char *s, *s2;
|
||||
int state, i, c;
|
||||
int index=0;
|
||||
char keyword[100];
|
||||
char *buffer = NULL;
|
||||
size_t buflen = 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;
|
||||
index = i;
|
||||
arg->r_opt = opts[index].short_opt;
|
||||
if( !opts[index].short_opt )
|
||||
arg->r_opt = -2; /* unknown option */
|
||||
else if( (opts[index].flags & 8) ) /* no optional argument */
|
||||
arg->r_type = 0; /* okay */
|
||||
else /* no required argument */
|
||||
arg->r_opt = -3; /* error */
|
||||
break;
|
||||
}
|
||||
else if( state == 3 ) { /* no argument found */
|
||||
if( !(opts[index].flags & 7) ) /* does not take an argument */
|
||||
arg->r_type = 0; /* okay */
|
||||
else if( (opts[index].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( !(opts[index].flags & 7) ) /* does not take an argument */
|
||||
arg->r_opt = -6; /* error */
|
||||
else {
|
||||
if( !buffer ) {
|
||||
keyword[i] = 0;
|
||||
buffer = m_strdup(keyword);
|
||||
}
|
||||
else
|
||||
buffer[i] = 0;
|
||||
|
||||
if( !set_opt_arg(arg, opts[index].flags, buffer) )
|
||||
m_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;
|
||||
index = i;
|
||||
arg->r_opt = opts[index].short_opt;
|
||||
if( !opts[index].short_opt ) {
|
||||
arg->r_opt = -2; /* unknown option */
|
||||
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 = m_realloc(buffer, buflen);
|
||||
buffer[i++] = c;
|
||||
}
|
||||
}
|
||||
else if( i < DIM(keyword)-1 )
|
||||
keyword[i++] = c;
|
||||
else {
|
||||
buflen = DIM(keyword)+50;
|
||||
buffer = m_alloc(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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
|
||||
|
@ -138,31 +331,11 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
|
|||
char *s, *s2;
|
||||
int i;
|
||||
|
||||
if( !(arg->flags & (1<<15)) ) { /* initialize this instance */
|
||||
arg->internal.index = 0;
|
||||
arg->internal.last = NULL;
|
||||
arg->internal.inarg = 0;
|
||||
arg->internal.stopped= 0;
|
||||
arg->err = 0;
|
||||
arg->flags |= 1<<15; /* mark initialized */
|
||||
if( *arg->argc < 0 )
|
||||
log_bug("Invalid argument for ArgParse\n");
|
||||
}
|
||||
initialize( arg, NULL, NULL );
|
||||
argc = *arg->argc;
|
||||
argv = *arg->argv;
|
||||
index = arg->internal.index;
|
||||
|
||||
if( arg->err ) { /* last option was erroneous */
|
||||
if( arg->r_opt == -3 )
|
||||
s = "Missing argument for option \"%.50s\"\n";
|
||||
else
|
||||
s = "Invalid option \"%.50s\"\n";
|
||||
log_error(s, arg->internal.last? arg->internal.last:"[??]" );
|
||||
if( arg->err != 1 )
|
||||
exit(2);
|
||||
arg->err = 0;
|
||||
}
|
||||
|
||||
if( !index && argc && !(arg->flags & (1<<4)) ) { /* skip the first entry */
|
||||
argc--; argv++; index++;
|
||||
}
|
||||
|
@ -322,7 +495,7 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
|
|||
|
||||
|
||||
|
||||
static void
|
||||
static int
|
||||
set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s)
|
||||
{
|
||||
int base = (flags & 16)? 0 : 10;
|
||||
|
@ -330,17 +503,17 @@ set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s)
|
|||
switch( arg->r_type = (flags & 7) ) {
|
||||
case 1: /* takes int argument */
|
||||
arg->r.ret_int = (int)strtol(s,NULL,base);
|
||||
break;
|
||||
default:
|
||||
case 2: /* takes string argument */
|
||||
arg->r.ret_str = s;
|
||||
break;
|
||||
return 0;
|
||||
case 3: /* takes long argument */
|
||||
arg->r.ret_long= strtol(s,NULL,base);
|
||||
break;
|
||||
return 0;
|
||||
case 4: /* takes ulong argument */
|
||||
arg->r.ret_ulong= strtoul(s,NULL,base);
|
||||
break;
|
||||
return 0;
|
||||
case 2: /* takes string argument */
|
||||
default:
|
||||
arg->r.ret_str = s;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
|
@ -29,3 +30,37 @@
|
|||
#include "ttyio.h"
|
||||
|
||||
|
||||
/****************
|
||||
* Construct a filename form 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 = m_alloc(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;
|
||||
}
|
||||
|
||||
|
|
71
util/iobuf.c
71
util/iobuf.c
|
@ -271,7 +271,6 @@ 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->recorder.buf);
|
||||
m_free(a->d.buf);
|
||||
m_free(a);
|
||||
}
|
||||
|
@ -406,9 +405,8 @@ iobuf_push_filter( IOBUF a,
|
|||
a->d.start = 0;
|
||||
}
|
||||
/* disable nlimit for the new stream */
|
||||
a->ntotal = b->ntotal + b->nbytes;
|
||||
a->nlimit = a->nbytes = 0;
|
||||
/* disable recorder for the original stream */
|
||||
b->recorder.buf = NULL;
|
||||
/* make a link from the new stream to the original stream */
|
||||
a->chain = b;
|
||||
a->opaque = b->opaque;
|
||||
|
@ -601,14 +599,6 @@ iobuf_readbyte(IOBUF a)
|
|||
return -1; /* EOF */
|
||||
|
||||
a->nbytes++;
|
||||
|
||||
if( a->recorder.buf ) {
|
||||
if( a->recorder.len >= a->recorder.size ) {
|
||||
a->recorder.size += 500;
|
||||
a->recorder.buf = m_realloc( a->recorder.buf, a->recorder.size );
|
||||
}
|
||||
((byte*)a->recorder.buf)[a->recorder.len++] = c;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
@ -678,47 +668,12 @@ void
|
|||
iobuf_set_limit( IOBUF a, unsigned long nlimit )
|
||||
{
|
||||
a->nlimit = nlimit;
|
||||
a->ntotal += a->nbytes;
|
||||
a->nbytes = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
iobuf_start_recorder( IOBUF a )
|
||||
{
|
||||
m_free(a->recorder.buf);
|
||||
a->recorder.size = 500;
|
||||
a->recorder.buf = m_alloc(a->recorder.size);
|
||||
a->recorder.len = 0;
|
||||
}
|
||||
|
||||
void
|
||||
iobuf_push_recorder( IOBUF a, int c )
|
||||
{
|
||||
if( a->recorder.buf ) {
|
||||
if( a->recorder.len >= a->recorder.size ) {
|
||||
a->recorder.size += 500;
|
||||
a->recorder.buf = m_realloc( a->recorder.buf, a->recorder.size );
|
||||
}
|
||||
((byte*)a->recorder.buf)[a->recorder.len++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
iobuf_stop_recorder( IOBUF a, size_t *n )
|
||||
{
|
||||
char *p;
|
||||
if( !a->recorder.buf )
|
||||
log_bug("iobuf_recorder not started\n");
|
||||
p = a->recorder.buf;
|
||||
if( n )
|
||||
*n = a->recorder.len;
|
||||
a->recorder.buf = NULL;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Return the length of an open file
|
||||
*/
|
||||
|
@ -741,6 +696,28 @@ iobuf_get_filelength( IOBUF a )
|
|||
return 0;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Tell the file position, where the next read will take place
|
||||
*/
|
||||
ulong
|
||||
iobuf_tell( IOBUF a )
|
||||
{
|
||||
return a->ntotal + a->nbytes;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
iobuf_seek( IOBUF a, ulong newpos )
|
||||
{
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Retrieve the filename
|
||||
*/
|
||||
|
|
|
@ -54,6 +54,7 @@ const void membug( const char *fmt, ... );
|
|||
#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
|
||||
|
@ -370,7 +371,7 @@ FNAME(alloc_secure_clear)( size_t n FNAMEPRT)
|
|||
|
||||
|
||||
/****************
|
||||
* realloc and clear the new space
|
||||
* realloc and clear the old space
|
||||
*/
|
||||
void *
|
||||
FNAME(realloc)( void *a, size_t n FNAMEPRT )
|
||||
|
@ -461,13 +462,13 @@ m_is_secure( const void *p )
|
|||
* Make a copy of the memory block at a
|
||||
*/
|
||||
void *
|
||||
FNAME(copy)( void *a FNAMEPRT )
|
||||
FNAME(copy)( const void *a FNAMEPRT )
|
||||
{
|
||||
void *b;
|
||||
size_t n;
|
||||
|
||||
if( !a )
|
||||
return a;
|
||||
return NULL;
|
||||
|
||||
n = m_size(a);
|
||||
if( m_is_secure(a) )
|
||||
|
@ -479,3 +480,12 @@ FNAME(copy)( void *a FNAMEPRT )
|
|||
}
|
||||
|
||||
|
||||
char *
|
||||
FNAME(strdup)( const char *a FNAMEPRT )
|
||||
{
|
||||
size_t n = strlen(a);
|
||||
char *p = FNAME(alloc)(n+1 FNAMEARG);
|
||||
strcpy(p, a);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue