gpgme-tool: Switch to argparse.c for option parsing.
* src/argparse.c, src/argparse.h: New. Taken from current gnupg. * src/Makefile.am (gpgme_tool_SOURCES): New. * src/gpgme-tool.c: Remove all argp.h stuff. (my_strusage): New. (main): Change to use argparse. -- As a GnuPG related tool the user should get the same experience in option parsing as with gpg et al. Thus we use the same parser. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
c4b6b35bfa
commit
f0ccce855b
@ -128,6 +128,7 @@ endif
|
||||
AM_CPPFLAGS = @GPG_ERROR_CFLAGS@ @QT4_CORE_CFLAGS@
|
||||
AM_CFLAGS = @LIBASSUAN_CFLAGS@ @GLIB_CFLAGS@ @QT4_CORE_CFLAGS@
|
||||
|
||||
gpgme_tool_SOURCES = gpgme-tool.c argparse.c argparse.h
|
||||
gpgme_tool_LDADD = libgpgme.la @LIBASSUAN_LIBS@
|
||||
|
||||
|
||||
|
1609
src/argparse.c
Normal file
1609
src/argparse.c
Normal file
File diff suppressed because it is too large
Load Diff
203
src/argparse.h
Normal file
203
src/argparse.h
Normal file
@ -0,0 +1,203 @@
|
||||
/* argparse.h - Argument parser for option handling.
|
||||
* Copyright (C) 1998,1999,2000,2001,2006 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 either
|
||||
*
|
||||
* - the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* or
|
||||
*
|
||||
* - 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.
|
||||
*
|
||||
* or both in parallel, as here.
|
||||
*
|
||||
* 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 copies of the GNU General Public License
|
||||
* and the GNU Lesser General Public License along with this program;
|
||||
* if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GNUPG_COMMON_ARGPARSE_H
|
||||
#define GNUPG_COMMON_ARGPARSE_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int *argc; /* Pointer to ARGC (value subject to change). */
|
||||
char ***argv; /* Pointer to ARGV (value subject to change). */
|
||||
unsigned int flags; /* Global flags. May be set prior to calling the
|
||||
parser. The parser may change the value. */
|
||||
int err; /* Print error description for last option.
|
||||
Either 0, ARGPARSE_PRINT_WARNING or
|
||||
ARGPARSE_PRINT_ERROR. */
|
||||
|
||||
int r_opt; /* Returns option code. */
|
||||
int r_type; /* Returns type of option value. */
|
||||
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;
|
||||
void *iio_list;
|
||||
} internal; /* Private - do not change. */
|
||||
} ARGPARSE_ARGS;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int short_opt;
|
||||
const char *long_opt;
|
||||
unsigned int flags;
|
||||
const char *description; /* Optional option description. */
|
||||
} ARGPARSE_OPTS;
|
||||
|
||||
|
||||
/* Global flags (ARGPARSE_ARGS). */
|
||||
#define ARGPARSE_FLAG_KEEP 1 /* Do not remove options form argv. */
|
||||
#define ARGPARSE_FLAG_ALL 2 /* Do not stop at last option but return
|
||||
remaining args with R_OPT set to -1. */
|
||||
#define ARGPARSE_FLAG_MIXED 4 /* Assume options and args are mixed. */
|
||||
#define ARGPARSE_FLAG_NOSTOP 8 /* Do not stop processing at "--". */
|
||||
#define ARGPARSE_FLAG_ARG0 16 /* Do not skip the first arg. */
|
||||
#define ARGPARSE_FLAG_ONEDASH 32 /* Allow long options with one dash. */
|
||||
#define ARGPARSE_FLAG_NOVERSION 64 /* No output for "--version". */
|
||||
|
||||
#define ARGPARSE_FLAG_STOP_SEEN 256 /* Set to true if a "--" has been seen. */
|
||||
|
||||
/* Flags for each option (ARGPARSE_OPTS). The type code may be
|
||||
ORed with the OPT flags. */
|
||||
#define ARGPARSE_TYPE_NONE 0 /* Does not take an argument. */
|
||||
#define ARGPARSE_TYPE_INT 1 /* Takes an int argument. */
|
||||
#define ARGPARSE_TYPE_STRING 2 /* Takes a string argument. */
|
||||
#define ARGPARSE_TYPE_LONG 3 /* Takes a long argument. */
|
||||
#define ARGPARSE_TYPE_ULONG 4 /* Takes an unsigned long argument. */
|
||||
#define ARGPARSE_OPT_OPTIONAL (1<<3) /* Argument is optional. */
|
||||
#define ARGPARSE_OPT_PREFIX (1<<4) /* Allow 0x etc. prefixed values. */
|
||||
#define ARGPARSE_OPT_IGNORE (1<<6) /* Ignore command or option. */
|
||||
#define ARGPARSE_OPT_COMMAND (1<<7) /* The argument is a command. */
|
||||
|
||||
#define ARGPARSE_TYPE_MASK 7 /* Mask for the type values (internal). */
|
||||
|
||||
/* A set of macros to make option definitions easier to read. */
|
||||
#define ARGPARSE_x(s,l,t,f,d) \
|
||||
{ (s), (l), ARGPARSE_TYPE_ ## t | (f), (d) }
|
||||
|
||||
#define ARGPARSE_s(s,l,t,d) \
|
||||
{ (s), (l), ARGPARSE_TYPE_ ## t, (d) }
|
||||
#define ARGPARSE_s_n(s,l,d) \
|
||||
{ (s), (l), ARGPARSE_TYPE_NONE, (d) }
|
||||
#define ARGPARSE_s_i(s,l,d) \
|
||||
{ (s), (l), ARGPARSE_TYPE_INT, (d) }
|
||||
#define ARGPARSE_s_s(s,l,d) \
|
||||
{ (s), (l), ARGPARSE_TYPE_STRING, (d) }
|
||||
#define ARGPARSE_s_l(s,l,d) \
|
||||
{ (s), (l), ARGPARSE_TYPE_LONG, (d) }
|
||||
#define ARGPARSE_s_u(s,l,d) \
|
||||
{ (s), (l), ARGPARSE_TYPE_ULONG, (d) }
|
||||
|
||||
#define ARGPARSE_o(s,l,t,d) \
|
||||
{ (s), (l), (ARGPARSE_TYPE_ ## t | ARGPARSE_OPT_OPTIONAL), (d) }
|
||||
#define ARGPARSE_o_n(s,l,d) \
|
||||
{ (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_OPTIONAL), (d) }
|
||||
#define ARGPARSE_o_i(s,l,d) \
|
||||
{ (s), (l), (ARGPARSE_TYPE_INT | ARGPARSE_OPT_OPTIONAL), (d) }
|
||||
#define ARGPARSE_o_s(s,l,d) \
|
||||
{ (s), (l), (ARGPARSE_TYPE_STRING | ARGPARSE_OPT_OPTIONAL), (d) }
|
||||
#define ARGPARSE_o_l(s,l,d) \
|
||||
{ (s), (l), (ARGPARSE_TYPE_LONG | ARGPARSE_OPT_OPTIONAL), (d) }
|
||||
#define ARGPARSE_o_u(s,l,d) \
|
||||
{ (s), (l), (ARGPARSE_TYPE_ULONG | ARGPARSE_OPT_OPTIONAL), (d) }
|
||||
|
||||
#define ARGPARSE_p(s,l,t,d) \
|
||||
{ (s), (l), (ARGPARSE_TYPE_ ## t | ARGPARSE_OPT_PREFIX), (d) }
|
||||
#define ARGPARSE_p_n(s,l,d) \
|
||||
{ (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_PREFIX), (d) }
|
||||
#define ARGPARSE_p_i(s,l,d) \
|
||||
{ (s), (l), (ARGPARSE_TYPE_INT | ARGPARSE_OPT_PREFIX), (d) }
|
||||
#define ARGPARSE_p_s(s,l,d) \
|
||||
{ (s), (l), (ARGPARSE_TYPE_STRING | ARGPARSE_OPT_PREFIX), (d) }
|
||||
#define ARGPARSE_p_l(s,l,d) \
|
||||
{ (s), (l), (ARGPARSE_TYPE_LONG | ARGPARSE_OPT_PREFIX), (d) }
|
||||
#define ARGPARSE_p_u(s,l,d) \
|
||||
{ (s), (l), (ARGPARSE_TYPE_ULONG | ARGPARSE_OPT_PREFIX), (d) }
|
||||
|
||||
#define ARGPARSE_op(s,l,t,d) \
|
||||
{ (s), (l), (ARGPARSE_TYPE_ ## t \
|
||||
| ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
|
||||
#define ARGPARSE_op_n(s,l,d) \
|
||||
{ (s), (l), (ARGPARSE_TYPE_NONE \
|
||||
| ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
|
||||
#define ARGPARSE_op_i(s,l,d) \
|
||||
{ (s), (l), (ARGPARSE_TYPE_INT \
|
||||
| ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
|
||||
#define ARGPARSE_op_s(s,l,d) \
|
||||
{ (s), (l), (ARGPARSE_TYPE_STRING \
|
||||
| ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
|
||||
#define ARGPARSE_op_l(s,l,d) \
|
||||
{ (s), (l), (ARGPARSE_TYPE_LONG \
|
||||
| ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
|
||||
#define ARGPARSE_op_u(s,l,d) \
|
||||
{ (s), (l), (ARGPARSE_TYPE_ULONG \
|
||||
| ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
|
||||
|
||||
#define ARGPARSE_c(s,l,d) \
|
||||
{ (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_COMMAND), (d) }
|
||||
|
||||
#define ARGPARSE_ignore(s,l) \
|
||||
{ (s), (l), (ARGPARSE_OPT_IGNORE), "@" }
|
||||
|
||||
#define ARGPARSE_group(s,d) \
|
||||
{ (s), NULL, 0, (d) }
|
||||
|
||||
#define ARGPARSE_end() { 0, NULL, 0, NULL }
|
||||
|
||||
|
||||
/* Other constants. */
|
||||
#define ARGPARSE_PRINT_WARNING 1
|
||||
#define ARGPARSE_PRINT_ERROR 2
|
||||
|
||||
|
||||
/* Error values. */
|
||||
#define ARGPARSE_IS_ARG (-1)
|
||||
#define ARGPARSE_INVALID_OPTION (-2)
|
||||
#define ARGPARSE_MISSING_ARG (-3)
|
||||
#define ARGPARSE_KEYWORD_TOO_LONG (-4)
|
||||
#define ARGPARSE_READ_ERROR (-5)
|
||||
#define ARGPARSE_UNEXPECTED_ARG (-6)
|
||||
#define ARGPARSE_INVALID_COMMAND (-7)
|
||||
#define ARGPARSE_AMBIGUOUS_OPTION (-8)
|
||||
#define ARGPARSE_AMBIGUOUS_COMMAND (-9)
|
||||
#define ARGPARSE_INVALID_ALIAS (-10)
|
||||
#define ARGPARSE_OUT_OF_CORE (-11)
|
||||
#define ARGPARSE_INVALID_ARG (-12)
|
||||
|
||||
|
||||
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 ));
|
||||
void argparse_register_outfnc (int (*fnc)(int, const char *));
|
||||
|
||||
#endif /*GNUPG_COMMON_ARGPARSE_H*/
|
540
src/gpgme-tool.c
540
src/gpgme-tool.c
@ -32,12 +32,10 @@
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
#ifdef HAVE_ARGP_H
|
||||
#include <argp.h>
|
||||
#endif
|
||||
|
||||
#include <assuan.h>
|
||||
|
||||
#include "argparse.h"
|
||||
#include "gpgme.h"
|
||||
|
||||
/* GCC attributes. */
|
||||
@ -59,421 +57,6 @@
|
||||
#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
|
||||
|
||||
|
||||
|
||||
#ifndef HAVE_ARGP_H
|
||||
/* Minimal argp implementation. */
|
||||
|
||||
/* Differences to ARGP:
|
||||
argp_program_version: Required.
|
||||
argp_program_bug_address: Required.
|
||||
argp_program_version_hook: Not supported.
|
||||
argp_err_exit_status: Required.
|
||||
struct argp: Children and help_filter not supported.
|
||||
argp_domain: Not supported.
|
||||
struct argp_option: Group not supported. Options are printed in
|
||||
order given. Flags OPTION_ALIAS, OPTION_DOC and OPTION_NO_USAGE
|
||||
are not supported.
|
||||
argp_parse: No flags are supported (ARGP_PARSE_ARGV0, ARGP_NO_ERRS,
|
||||
ARGP_NO_ARGS, ARGP_IN_ORDER, ARGP_NO_HELP, ARGP_NO_EXIT,
|
||||
ARGP_LONG_ONLY, ARGP_SILENT). ARGP must not be NULL.
|
||||
argp_help: Flag ARGP_HELP_LONG_ONLY not supported.
|
||||
argp_state: argc, argv, next may not be modified and should not be used. */
|
||||
|
||||
extern const char *argp_program_version;
|
||||
extern const char *argp_program_bug_address;
|
||||
extern error_t argp_err_exit_status;
|
||||
|
||||
struct argp_option
|
||||
{
|
||||
const char *name;
|
||||
int key;
|
||||
const char *arg;
|
||||
#define OPTION_ARG_OPTIONAL 0x1
|
||||
#define OPTION_HIDDEN 0x2
|
||||
int flags;
|
||||
const char *doc;
|
||||
int group;
|
||||
};
|
||||
|
||||
struct argp;
|
||||
struct argp_state
|
||||
{
|
||||
const struct argp *const root_argp;
|
||||
int argc;
|
||||
char **argv;
|
||||
int next;
|
||||
unsigned flags;
|
||||
unsigned arg_num;
|
||||
int quoted;
|
||||
void *input;
|
||||
void **child_inputs;
|
||||
void *hook;
|
||||
char *name;
|
||||
FILE *err_stream;
|
||||
FILE *out_stream;
|
||||
void *pstate;
|
||||
};
|
||||
|
||||
#ifdef EDEADLK
|
||||
# define ARGP_ERR_UNKNOWN EDEADLK /* POSIX */
|
||||
#else
|
||||
# define ARGP_ERR_UNKNOWN EDEADLOCK /* *GNU/kFreebsd does not define this) */
|
||||
#endif
|
||||
#define ARGP_KEY_ARG 0
|
||||
#define ARGP_KEY_ARGS 0x1000006
|
||||
#define ARGP_KEY_END 0x1000001
|
||||
#define ARGP_KEY_NO_ARGS 0x1000002
|
||||
#define ARGP_KEY_INIT 0x1000003
|
||||
#define ARGP_KEY_FINI 0x1000007
|
||||
#define ARGP_KEY_SUCCESS 0x1000004
|
||||
#define ARGP_KEY_ERROR 0x1000005
|
||||
typedef error_t (*argp_parser_t) (int key, char *arg, struct argp_state *state);
|
||||
|
||||
struct argp
|
||||
{
|
||||
const struct argp_option *options;
|
||||
argp_parser_t parser;
|
||||
const char *args_doc;
|
||||
const char *doc;
|
||||
|
||||
const struct argp_child *children;
|
||||
char *(*help_filter) (int key, const char *text, void *input);
|
||||
const char *argp_domain;
|
||||
};
|
||||
|
||||
#define ARGP_HELP_USAGE ARGP_HELP_SHORT_USAGE
|
||||
#define ARGP_HELP_SHORT_USAGE 0x02
|
||||
#define ARGP_HELP_SEE 0x04
|
||||
#define ARGP_HELP_LONG 0x08
|
||||
#define ARGP_HELP_PRE_DOC 0x10
|
||||
#define ARGP_HELP_POST_DOC 0x20
|
||||
#define ARGP_HELP_DOC (ARGP_HELP_PRE_DOC | ARGP_HELP_POST_DOC)
|
||||
#define ARGP_HELP_BUG_ADDR 0x40
|
||||
#define ARGP_HELP_EXIT_ERR 0x100
|
||||
#define ARGP_HELP_EXIT_OK 0x200
|
||||
#define ARGP_HELP_STD_ERR (ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
|
||||
#define ARGP_HELP_STD_USAGE \
|
||||
(ARGP_HELP_SHORT_USAGE | ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
|
||||
#define ARGP_HELP_STD_HELP \
|
||||
(ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_EXIT_OK \
|
||||
| ARGP_HELP_DOC | ARGP_HELP_BUG_ADDR)
|
||||
|
||||
|
||||
void argp_error (const struct argp_state *state,
|
||||
const char *fmt, ...) GT_GCC_A_PRINTF(2, 3);
|
||||
|
||||
|
||||
|
||||
char *
|
||||
_argp_pname (char *name)
|
||||
{
|
||||
char *pname = name;
|
||||
char *bname = strrchr (pname, '/');
|
||||
if (! bname)
|
||||
bname = strrchr (pname, '\\');
|
||||
if (bname)
|
||||
pname = bname + 1;
|
||||
return pname;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_argp_state_help (const struct argp *argp, const struct argp_state *state,
|
||||
FILE *stream, unsigned flags, char *name)
|
||||
{
|
||||
if (state)
|
||||
name = state->name;
|
||||
|
||||
if (flags & ARGP_HELP_SHORT_USAGE)
|
||||
fprintf (stream, "Usage: %s [OPTIONS...] %s\n", name, argp->args_doc);
|
||||
if (flags & ARGP_HELP_SEE)
|
||||
fprintf (stream, "Try `%s --help' or `%s --usage' for more information.\n",
|
||||
name, name);
|
||||
if (flags & ARGP_HELP_PRE_DOC)
|
||||
{
|
||||
char buf[1024];
|
||||
char *end;
|
||||
strncpy (buf, argp->doc, sizeof (buf));
|
||||
buf[sizeof (buf) - 1] = '\0';
|
||||
end = strchr (buf, '\v');
|
||||
if (end)
|
||||
*end = '\0';
|
||||
fprintf (stream, "%s\n%s", buf, buf[0] ? "\n" : "");
|
||||
}
|
||||
if (flags & ARGP_HELP_LONG)
|
||||
{
|
||||
const struct argp_option *opt = argp->options;
|
||||
while (opt->key)
|
||||
{
|
||||
#define NSPACES 29
|
||||
char spaces[NSPACES + 1] = " ";
|
||||
int len = 0;
|
||||
fprintf (stream, " ");
|
||||
len += 2;
|
||||
if (isascii (opt->key))
|
||||
{
|
||||
fprintf (stream, "-%c", opt->key);
|
||||
len += 2;
|
||||
if (opt->name)
|
||||
{
|
||||
fprintf (stream, ", ");
|
||||
len += 2;
|
||||
}
|
||||
}
|
||||
if (opt->name)
|
||||
{
|
||||
fprintf (stream, "--%s", opt->name);
|
||||
len += 2 + strlen (opt->name);
|
||||
}
|
||||
if (opt->arg && (opt->flags & OPTION_ARG_OPTIONAL))
|
||||
{
|
||||
fprintf (stream, "[=%s]", opt->arg);
|
||||
len += 3 + strlen (opt->arg);
|
||||
}
|
||||
else if (opt->arg)
|
||||
{
|
||||
fprintf (stream, "=%s", opt->arg);
|
||||
len += 1 + strlen (opt->arg);
|
||||
}
|
||||
if (len >= NSPACES)
|
||||
len = NSPACES - 1;
|
||||
spaces[NSPACES - len] = '\0';
|
||||
fprintf (stream, "%s%s\n", spaces, opt->doc);
|
||||
opt++;
|
||||
}
|
||||
fprintf (stream, " -?, --help Give this help list\n");
|
||||
fprintf (stream, " --usage Give a short usage "
|
||||
"message\n");
|
||||
}
|
||||
if (flags & ARGP_HELP_POST_DOC)
|
||||
{
|
||||
char buf[1024];
|
||||
char *end;
|
||||
strncpy (buf, argp->doc, sizeof (buf));
|
||||
buf[sizeof (buf) - 1] = '\0';
|
||||
end = strchr (buf, '\v');
|
||||
if (end)
|
||||
{
|
||||
end++;
|
||||
if (*end)
|
||||
fprintf (stream, "\n%s\n", end);
|
||||
}
|
||||
fprintf (stream, "\nMandatory or optional arguments to long options are also mandatory or optional\n");
|
||||
fprintf (stream, "for any corresponding short options.\n");
|
||||
}
|
||||
if (flags & ARGP_HELP_BUG_ADDR)
|
||||
fprintf (stream, "\nReport bugs to %s.\n", argp_program_bug_address);
|
||||
|
||||
if (flags & ARGP_HELP_EXIT_ERR)
|
||||
exit (argp_err_exit_status);
|
||||
if (flags & ARGP_HELP_EXIT_OK)
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
argp_usage (const struct argp_state *state)
|
||||
{
|
||||
_argp_state_help (state->root_argp, state, state->err_stream,
|
||||
ARGP_HELP_STD_USAGE, state->name);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags)
|
||||
{
|
||||
_argp_state_help (state->root_argp, state, stream, flags, state->name);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
argp_error (const struct argp_state *state, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
fprintf (state->err_stream, "%s: ", state->name);
|
||||
va_start (ap, fmt);
|
||||
vfprintf (state->err_stream, fmt, ap);
|
||||
va_end (ap);
|
||||
fprintf (state->err_stream, "\n");
|
||||
argp_state_help (state, state->err_stream, ARGP_HELP_STD_ERR);
|
||||
exit (argp_err_exit_status);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
argp_help (const struct argp *argp, FILE *stream, unsigned flags, char *name)
|
||||
{
|
||||
_argp_state_help (argp, NULL, stream, flags, name);
|
||||
}
|
||||
|
||||
|
||||
error_t
|
||||
argp_parse (const struct argp *argp, int argc,
|
||||
char **argv, unsigned flags, int *arg_index, void *input)
|
||||
{
|
||||
int rc = 0;
|
||||
struct argp_state state = { argp, argc, argv, 1, flags, 0, 0, input,
|
||||
NULL, NULL, _argp_pname (argv[0]),
|
||||
stderr, stdout, NULL };
|
||||
/* All non-option arguments are collected at the beginning of
|
||||
&argv[1] during processing. This is a counter for their number. */
|
||||
int non_opt_args = 0;
|
||||
|
||||
rc = argp->parser (ARGP_KEY_INIT, NULL, &state);
|
||||
if (rc && rc != ARGP_ERR_UNKNOWN)
|
||||
goto argperror;
|
||||
|
||||
while (state.next < state.argc - non_opt_args)
|
||||
{
|
||||
int idx = state.next;
|
||||
state.next++;
|
||||
|
||||
if (! strcasecmp (state.argv[idx], "--"))
|
||||
{
|
||||
state.quoted = idx;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (state.quoted || state.argv[idx][0] != '-')
|
||||
{
|
||||
char *arg_saved = state.argv[idx];
|
||||
non_opt_args++;
|
||||
memmove (&state.argv[idx], &state.argv[idx + 1],
|
||||
(state.argc - 1 - idx) * sizeof (char *));
|
||||
state.argv[argc - 1] = arg_saved;
|
||||
state.next--;
|
||||
}
|
||||
else if (! strcasecmp (state.argv[idx], "--help")
|
||||
|| !strcmp (state.argv[idx], "-?"))
|
||||
{
|
||||
argp_state_help (&state, state.out_stream, ARGP_HELP_STD_HELP);
|
||||
}
|
||||
else if (! strcasecmp (state.argv[idx], "--usage"))
|
||||
{
|
||||
argp_state_help (&state, state.out_stream,
|
||||
ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
|
||||
}
|
||||
else if (! strcasecmp (state.argv[idx], "--version")
|
||||
|| !strcmp (state.argv[idx], "-V"))
|
||||
{
|
||||
fprintf (state.out_stream, "%s\n", argp_program_version);
|
||||
exit (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Search for option and call parser with its KEY. */
|
||||
int key = ARGP_KEY_ARG; /* Just some dummy value. */
|
||||
const struct argp_option *opt = argp->options;
|
||||
char *arg = NULL;
|
||||
int found = 0;
|
||||
|
||||
/* Check for --opt=value syntax. */
|
||||
arg = strchr (state.argv[idx], '=');
|
||||
if (arg)
|
||||
{
|
||||
*arg = '\0';
|
||||
arg++;
|
||||
}
|
||||
|
||||
if (state.argv[idx][1] != '-')
|
||||
key = state.argv[idx][1];
|
||||
|
||||
while (! found && opt->key)
|
||||
{
|
||||
if (key == opt->key
|
||||
|| (key == ARGP_KEY_ARG
|
||||
&& ! strcasecmp (&state.argv[idx][2], opt->name)))
|
||||
{
|
||||
if (arg && !opt->arg)
|
||||
argp_error (&state, "Option %s does not take an argument",
|
||||
state.argv[idx]);
|
||||
if (opt->arg && state.next < state.argc
|
||||
&& state.argv[idx + 1][0] != '-')
|
||||
{
|
||||
arg = state.argv[idx + 1];
|
||||
state.next++;
|
||||
}
|
||||
if (opt->arg && !(opt->flags & OPTION_ARG_OPTIONAL))
|
||||
argp_error (&state, "Option %s requires an argument",
|
||||
state.argv[idx]);
|
||||
|
||||
rc = argp->parser (opt->key, arg, &state);
|
||||
if (rc == ARGP_ERR_UNKNOWN)
|
||||
break;
|
||||
else if (rc)
|
||||
goto argperror;
|
||||
found = 1;
|
||||
}
|
||||
opt++;
|
||||
}
|
||||
if (! found)
|
||||
argp_error (&state, "Unknown option %s", state.argv[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
while (state.next < state.argc)
|
||||
{
|
||||
/* Call parser for all non-option args. */
|
||||
int idx = state.next;
|
||||
state.next++;
|
||||
rc = argp->parser (ARGP_KEY_ARG, state.argv[idx], &state);
|
||||
if (rc && rc != ARGP_ERR_UNKNOWN)
|
||||
goto argperror;
|
||||
if (rc == ARGP_ERR_UNKNOWN)
|
||||
{
|
||||
int old_next = state.next;
|
||||
rc = argp->parser (ARGP_KEY_ARGS, NULL, &state);
|
||||
if (rc == ARGP_ERR_UNKNOWN)
|
||||
{
|
||||
argp_error (&state, "Too many arguments");
|
||||
goto argperror;
|
||||
}
|
||||
if (! rc && state.next == old_next)
|
||||
{
|
||||
state.arg_num += state.argc - state.next;
|
||||
state.next = state.argc;
|
||||
}
|
||||
}
|
||||
else
|
||||
state.arg_num++;
|
||||
}
|
||||
|
||||
if (state.arg_num == 0)
|
||||
{
|
||||
rc = argp->parser (ARGP_KEY_NO_ARGS, NULL, &state);
|
||||
if (rc && rc != ARGP_ERR_UNKNOWN)
|
||||
goto argperror;
|
||||
}
|
||||
if (state.next == state.argc)
|
||||
{
|
||||
rc = argp->parser (ARGP_KEY_END, NULL, &state);
|
||||
if (rc && rc != ARGP_ERR_UNKNOWN)
|
||||
goto argperror;
|
||||
}
|
||||
rc = argp->parser (ARGP_KEY_FINI, NULL, &state);
|
||||
if (rc && rc != ARGP_ERR_UNKNOWN)
|
||||
goto argperror;
|
||||
|
||||
rc = 0;
|
||||
argp->parser (ARGP_KEY_SUCCESS, NULL, &state);
|
||||
|
||||
argperror:
|
||||
if (rc)
|
||||
{
|
||||
argp_error (&state, "unexpected error: %s", strerror (rc));
|
||||
argp->parser (ARGP_KEY_ERROR, NULL, &state);
|
||||
}
|
||||
|
||||
argp->parser (ARGP_KEY_FINI, NULL, &state);
|
||||
|
||||
if (arg_index)
|
||||
*arg_index = state.next - 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* MEMBUF */
|
||||
|
||||
@ -3722,85 +3305,51 @@ gpgme_server (gpgme_tool_t gt)
|
||||
|
||||
|
||||
|
||||
/* MAIN PROGRAM STARTS HERE. */
|
||||
|
||||
const char *argp_program_version = VERSION;
|
||||
const char *argp_program_bug_address = "bug-gpgme@gnupg.org";
|
||||
error_t argp_err_exit_status = 1;
|
||||
|
||||
static char doc[] = "GPGME Tool -- Assuan server exposing GPGME operations";
|
||||
static char args_doc[] = "COMMAND [OPTIONS...]";
|
||||
|
||||
static struct argp_option options[] = {
|
||||
{ "server", 's', 0, 0, "Server mode" },
|
||||
{ "gpg-binary", 501, "FILE", 0, "Use FILE for the GPG backend" },
|
||||
{ "lib-version", 502, 0, 0, "Show library version" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static error_t parse_options (int key, char *arg, struct argp_state *state);
|
||||
static struct argp argp = { options, parse_options, args_doc, doc };
|
||||
|
||||
struct args
|
||||
static const char *
|
||||
my_strusage( int level )
|
||||
{
|
||||
enum { CMD_DEFAULT, CMD_SERVER, CMD_LIBVERSION } cmd;
|
||||
const char *gpg_binary;
|
||||
};
|
||||
const char *p;
|
||||
|
||||
void
|
||||
args_init (struct args *args)
|
||||
{
|
||||
memset (args, '\0', sizeof (*args));
|
||||
args->cmd = CMD_DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
static error_t
|
||||
parse_options (int key, char *arg, struct argp_state *state)
|
||||
{
|
||||
struct args *args = state->input;
|
||||
|
||||
switch (key)
|
||||
switch (level)
|
||||
{
|
||||
case 's':
|
||||
args->cmd = CMD_SERVER;
|
||||
case 11: p = "gpgme-tool"; break;
|
||||
case 13: p = PACKAGE_VERSION; break;
|
||||
case 14: p = "Copyright (C) 2015 g10 Code GmbH"; break;
|
||||
case 19: p = "Please report bugs to <" PACKAGE_BUGREPORT ">.\n"; break;
|
||||
case 1:
|
||||
case 40:
|
||||
p = "Usage: gpgme-tool [OPTIONS] [COMMANDS]";
|
||||
break;
|
||||
|
||||
case 501:
|
||||
args->gpg_binary = arg;
|
||||
case 41:
|
||||
p = "GPGME Tool -- Assuan server exposing GPGME operations\n";
|
||||
break;
|
||||
|
||||
case 502:
|
||||
args->cmd = CMD_LIBVERSION;
|
||||
case 42:
|
||||
p = "1"; /* Flag print 40 as part of 41. */
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case ARGP_KEY_ARG:
|
||||
if (state->arg_num >= 2)
|
||||
argp_usage (state);
|
||||
printf ("Arg[%i] = %s\n", state->arg_num, arg);
|
||||
break;
|
||||
case ARGP_KEY_END:
|
||||
if (state->arg_num < 2)
|
||||
argp_usage (state);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
default: p = NULL; break;
|
||||
}
|
||||
return 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
struct args args;
|
||||
static ARGPARSE_OPTS opts[] = {
|
||||
ARGPARSE_c ('s', "server", "Server mode"),
|
||||
ARGPARSE_s_s(501, "gpg-binary", "|FILE|Use FILE for the GPG backend"),
|
||||
ARGPARSE_c (502, "lib-version", "Show library version"),
|
||||
ARGPARSE_end()
|
||||
};
|
||||
ARGPARSE_ARGS pargs = { &argc, &argv, 0 };
|
||||
enum { CMD_DEFAULT, CMD_SERVER, CMD_LIBVERSION } cmd = CMD_DEFAULT;
|
||||
const char *gpg_binary = NULL;
|
||||
struct gpgme_tool gt;
|
||||
gpg_error_t err;
|
||||
int needgt = 1;
|
||||
|
||||
set_strusage (my_strusage);
|
||||
|
||||
#ifdef HAVE_SETLOCALE
|
||||
setlocale (LC_ALL, "");
|
||||
#endif
|
||||
@ -3812,30 +3361,40 @@ main (int argc, char *argv[])
|
||||
gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
|
||||
#endif
|
||||
|
||||
args_init (&args);
|
||||
|
||||
argp_parse (&argp, argc, argv, 0, 0, &args);
|
||||
log_init ();
|
||||
|
||||
if (args.cmd == CMD_LIBVERSION)
|
||||
while (arg_parse (&pargs, opts))
|
||||
{
|
||||
switch (pargs.r_opt)
|
||||
{
|
||||
case 's': cmd = CMD_SERVER; break;
|
||||
case 501: gpg_binary = pargs.r.ret_str; break;
|
||||
case 502: cmd = CMD_LIBVERSION; break;
|
||||
default:
|
||||
pargs.err = ARGPARSE_PRINT_WARNING;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd == CMD_LIBVERSION)
|
||||
needgt = 0;
|
||||
|
||||
if (needgt && args.gpg_binary)
|
||||
if (needgt && gpg_binary)
|
||||
{
|
||||
if (access (args.gpg_binary, X_OK))
|
||||
if (access (gpg_binary, X_OK))
|
||||
err = gpg_error_from_syserror ();
|
||||
else
|
||||
err = gpgme_set_engine_info (GPGME_PROTOCOL_OpenPGP,
|
||||
args.gpg_binary, NULL);
|
||||
gpg_binary, NULL);
|
||||
if (err)
|
||||
log_error (1, err, "error witching OpenPGP engine to '%s'",
|
||||
args.gpg_binary);
|
||||
gpg_binary);
|
||||
}
|
||||
|
||||
if (needgt)
|
||||
gt_init (>);
|
||||
|
||||
switch (args.cmd)
|
||||
switch (cmd)
|
||||
{
|
||||
case CMD_DEFAULT:
|
||||
case CMD_SERVER:
|
||||
@ -3860,4 +3419,3 @@ main (int argc, char *argv[])
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user