1
0
Fork 0
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:
Werner Koch 1997-12-12 12:03:58 +00:00
parent 935965049d
commit 68ea0f4353
38 changed files with 2772 additions and 551 deletions

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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
*/

View file

@ -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;
}