* mkdtemp.c: New (moved from g10/), setenv.c: New, unsetenv.c: New.
[gnupg.git] / util / argparse.c
index b693414..30b403f 100644 (file)
@@ -1,5 +1,7 @@
 /* [argparse.c wk 17.06.97] Argument Parser for option handling
- *     Copyright (C) 1998,1999 Free Software Foundation, Inc.
+ *  Copyright (C) 1998, 1999, 2000, 2001, 2003
+ *                2004 Free Software Foundation, Inc.
+ *
  *  This file is part of GnuPG.
  *
  *  GnuPG is free software; you can redistribute it and/or modify
@@ -73,7 +75,7 @@
  *     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
+ *     Bit 6 : ignore --version and --help
  *     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):
@@ -157,41 +159,44 @@ initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
 
 
     if( arg->err ) { /* last option was erroneous */
-       const char *s;
 
        if( filename ) {
            if( arg->r_opt == -6 )
-               s = "%s:%u: argument not expected\n";
+             log_error("%s:%u: argument not expected\n", filename, *lineno );
            else if( arg->r_opt == -5 )
-               s = "%s:%u: read error\n";
+             log_error("%s:%u: read error\n", filename, *lineno );
            else if( arg->r_opt == -4 )
-               s = "%s:%u: keyword too long\n";
+             log_error("%s:%u: keyword too long\n", filename, *lineno );
            else if( arg->r_opt == -3 )
-               s = "%s:%u: missing argument\n";
+             log_error("%s:%u: missing argument\n", filename, *lineno );
            else if( arg->r_opt == -7 )
-               s = "%s:%u: invalid command\n";
+             log_error("%s:%u: invalid command\n", filename, *lineno );
            else if( arg->r_opt == -10 )
-               s = "%s:%u: invalid alias definition\n";
+             log_error("%s:%u: invalid alias definition\n",filename,*lineno);
            else
-               s = "%s:%u: invalid option\n";
-           log_error(s, filename, *lineno );
+             log_error("%s:%u: invalid option\n", filename, *lineno );
        }
        else {
            if( arg->r_opt == -3 )
-               s = "Missing argument for option \"%.50s\"\n";
+             log_error("Missing argument for option \"%.50s\"\n",
+                       arg->internal.last? arg->internal.last:"[??]" );
            else if( arg->r_opt == -6 )
-               s = "Option \"%.50s\" does not expect an argument\n";
+             log_error("Option \"%.50s\" does not expect an argument\n",
+                       arg->internal.last? arg->internal.last:"[??]" );
            else if( arg->r_opt == -7 )
-               s = "Invalid command \"%.50s\"\n";
+             log_error("Invalid command \"%.50s\"\n",
+                       arg->internal.last? arg->internal.last:"[??]" );
            else if( arg->r_opt == -8 )
-               s = "Option \"%.50s\" is ambiguous\n";
+             log_error("Option \"%.50s\" is ambiguous\n",
+                       arg->internal.last? arg->internal.last:"[??]" );
            else if( arg->r_opt == -9 )
-               s = "Command \"%.50s\" is ambiguous\n";
+             log_error("Command \"%.50s\" is ambiguous\n",
+                       arg->internal.last? arg->internal.last:"[??]" );
            else
-               s = "Invalid option \"%.50s\"\n";
-           log_error(s, arg->internal.last? arg->internal.last:"[??]" );
+             log_error("Invalid option \"%.50s\"\n",
+                       arg->internal.last? arg->internal.last:"[??]" );
        }
-       if( arg->err != 1 )
+       if( arg->err != 1 || arg->r_opt == -5 )
            exit(2);
        arg->err = 0;
     }
@@ -272,10 +277,12 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
                    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 */
+               else if( !(opts[idx].flags & 7) ) /* does not take an arg */
                    arg->r_type = 0;           /* okay */
+               else if( (opts[idx].flags & 8) )  /* argument is optional */
+                    arg->r_type = 0;          /* okay */
+               else                           /* required argument */
+                   arg->r_opt = -3;           /* error */
                break;
            }
            else if( state == 3 ) {            /* no argument found */
@@ -324,10 +331,19 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
 
                    trim_spaces( buffer );
                    p = buffer;
-                   if( *p == '"' ) { /* remove quotes */
-                       p++;
-                       if( *p && p[strlen(p)-1] == '"' )
-                           p[strlen(p)-1] = 0;
+                   /* remove quotes if they totally enclose the
+                       string, and do not occur within the string */
+                   if( *p == '"' && p[strlen(p)-1]=='"') {
+                       char *p2=p;
+
+                       while(*(++p2))
+                         if(*p2=='"')
+                           break;
+
+                       if(*p2=='"' && *(p2+1)=='\0') {
+                         p[strlen(p)-1] = 0;
+                         p++;
+                       }
                    }
                    if( !set_opt_arg(arg, opts[idx].flags, p) )
                        m_free(buffer);
@@ -429,7 +445,7 @@ find_long_option( ARGPARSE_ARGS *arg,
     for(i=0; opts[i].short_opt; i++ )
        if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
            return i;
-  #if 0
+#if 0
     {
        ALIAS_DEF a;
        /* see whether it is an alias */
@@ -441,7 +457,7 @@ find_long_option( ARGPARSE_ARGS *arg,
            }
        }
     }
-  #endif
+#endif
     /* not found, see whether it is an abbreviation */
     /* aliases may not be abbreviated */
     n = strlen( keyword );
@@ -513,8 +529,11 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
        if( argpos )
            *argpos = '=';
 
-       if( i < 0 && !strcmp( "help", s+2) )
-           show_help(opts, arg->flags);
+       if( i < 0 && !strcmp( "help", s+2) ) {
+           if( !(arg->flags & (1<<6)) ) {
+               show_help(opts, arg->flags);
+           }
+       }
        else if( i < 0 && !strcmp( "version", s+2) ) {
            if( !(arg->flags & (1<<6)) ) {
                show_version();
@@ -526,9 +545,11 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
            exit(0);
        }
        else if( i < 0 && !strcmp( "dump-options", s+2) ) {
-           for(i=0; opts[i].short_opt; i++ )
+           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);
        }
 
@@ -598,8 +619,11 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
                    break;
        }
 
-       if( !opts[i].short_opt && ( *s == 'h' || *s == '?' ) )
-           show_help(opts, arg->flags);
+       if( !opts[i].short_opt && ( *s == 'h' || *s == '?' ) ) {
+           if( !(arg->flags & (1<<6)) ) {
+               show_help(opts, arg->flags);
+           }
+       }
 
        arg->r_opt = opts[i].short_opt;
        if( !opts[i].short_opt ) {
@@ -842,7 +866,7 @@ show_version()
     /* additional program info */
     for(i=30; i < 40; i++ )
        if( (s=strusage(i)) )
-           fputs(s, stdout);
+           fputs( (const byte*)s, stdout);
     fflush(stdout);
 }
 
@@ -890,7 +914,7 @@ default_strusage( int level )
     switch( level ) {
       case 11: p = "foo"; break;
       case 13: p = "0.0"; break;
-      case 14: p = "Copyright (C) 1999 Free Software Foundation, Inc."; break;
+      case 14: p = "Copyright (C) 2004 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"