mirror of
git://git.gnupg.org/gnupg.git
synced 2024-06-16 00:29:50 +02:00
card: Implement non-interactive mode.
* tools/card-tool.h (opt): Add field 'initialized'. * tools/card-call-scd.c (scd_learn): Set it. * tools/gpg-card-tool.c (main): Reworked. (dispatch_command): New. -- This work is not yet finished because most commands need some tweaks for non-interactive work. What you already can do are things like: $ gpg-card-tool list -- 'auth <oldkey' \ -- auth --setkey --raw 123456781234567812345678 -- help auth Which will list the current card, authenticate using a hex encoded key from the file "oldkey", set the new admin key to "123...78", and print help for the auth command. Note that the -- acts as a delimiter between commands. To use a double dash as argument to a command the entire command must be quoted. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
da38325740
commit
1c0fa3e6f7
|
@ -956,6 +956,8 @@ scd_learn (card_info_t info)
|
||||||
/* Also try to get some other key attributes. */
|
/* Also try to get some other key attributes. */
|
||||||
if (!err)
|
if (!err)
|
||||||
{
|
{
|
||||||
|
info->initialized = 1;
|
||||||
|
|
||||||
err = scd_getattr ("KEY-ATTR", info);
|
err = scd_getattr ("KEY-ATTR", info);
|
||||||
if (gpg_err_code (err) == GPG_ERR_INV_NAME
|
if (gpg_err_code (err) == GPG_ERR_INV_NAME
|
||||||
|| gpg_err_code (err) == GPG_ERR_UNSUPPORTED_OPERATION)
|
|| gpg_err_code (err) == GPG_ERR_UNSUPPORTED_OPERATION)
|
||||||
|
@ -964,7 +966,6 @@ scd_learn (card_info_t info)
|
||||||
if (gpg_err_code (err) == GPG_ERR_INV_NAME
|
if (gpg_err_code (err) == GPG_ERR_INV_NAME
|
||||||
|| gpg_err_code (err) == GPG_ERR_UNSUPPORTED_OPERATION)
|
|| gpg_err_code (err) == GPG_ERR_UNSUPPORTED_OPERATION)
|
||||||
err = 0; /* Not implemented or GETATTR not supported. */
|
err = 0; /* Not implemented or GETATTR not supported. */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info == &dummyinfo)
|
if (info == &dummyinfo)
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
/* We keep all global options in the structure OPT. */
|
/* We keep all global options in the structure OPT. */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
int interactive;
|
||||||
int verbose;
|
int verbose;
|
||||||
unsigned int debug;
|
unsigned int debug;
|
||||||
int quiet;
|
int quiet;
|
||||||
|
@ -137,6 +138,7 @@ typedef struct key_info_s *key_info_t;
|
||||||
*/
|
*/
|
||||||
struct card_info_s
|
struct card_info_s
|
||||||
{
|
{
|
||||||
|
int initialized; /* True if a learn command was successful. */
|
||||||
int error; /* private. */
|
int error; /* private. */
|
||||||
char *reader; /* Reader information. */
|
char *reader; /* Reader information. */
|
||||||
char *cardtype; /* NULL or type of the card. */
|
char *cardtype; /* NULL or type of the card. */
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
#define CONTROL_D ('D' - 'A' + 1)
|
#define CONTROL_D ('D' - 'A' + 1)
|
||||||
|
|
||||||
/* Constants to identify the commands and options. */
|
/* Constants to identify the commands and options. */
|
||||||
enum cmd_and_opt_values
|
enum opt_values
|
||||||
{
|
{
|
||||||
aNull = 0,
|
aNull = 0,
|
||||||
|
|
||||||
|
@ -69,18 +69,12 @@ enum cmd_and_opt_values
|
||||||
oLCctype,
|
oLCctype,
|
||||||
oLCmessages,
|
oLCmessages,
|
||||||
|
|
||||||
aTest,
|
|
||||||
|
|
||||||
|
|
||||||
oDummy
|
oDummy
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* The list of commands and options. */
|
/* The list of commands and options. */
|
||||||
static ARGPARSE_OPTS opts[] = {
|
static ARGPARSE_OPTS opts[] = {
|
||||||
ARGPARSE_group (300, ("@Commands:\n ")),
|
|
||||||
ARGPARSE_c (aTest, "test", "test command"),
|
|
||||||
|
|
||||||
ARGPARSE_group (301, ("@\nOptions:\n ")),
|
ARGPARSE_group (301, ("@\nOptions:\n ")),
|
||||||
|
|
||||||
ARGPARSE_s_n (oVerbose, "verbose", ("verbose")),
|
ARGPARSE_s_n (oVerbose, "verbose", ("verbose")),
|
||||||
|
@ -133,7 +127,7 @@ typedef struct keyinfolabel_s *keyinfolabel_t;
|
||||||
|
|
||||||
|
|
||||||
/* Local prototypes. */
|
/* Local prototypes. */
|
||||||
static void wrong_args (const char *text) GPGRT_ATTR_NORETURN;
|
static gpg_error_t dispatch_command (card_info_t info, const char *command);
|
||||||
static void interactive_loop (void);
|
static void interactive_loop (void);
|
||||||
#ifdef HAVE_LIBREADLINE
|
#ifdef HAVE_LIBREADLINE
|
||||||
static char **command_completion (const char *text, int start, int end);
|
static char **command_completion (const char *text, int start, int end);
|
||||||
|
@ -157,11 +151,14 @@ my_strusage( int level )
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
case 40:
|
case 40:
|
||||||
p = ("Usage: gpg-card-tool [command] [options] [args] (-h for help)");
|
p = ("Usage: gpg-card-tool"
|
||||||
|
" [options] [{[--] command [args]}] (-h for help)");
|
||||||
break;
|
break;
|
||||||
case 41:
|
case 41:
|
||||||
p = ("Syntax: gpg-card-tool [command] [options] [args]\n"
|
p = ("Syntax: gpg-card-tool"
|
||||||
"Tool to configure cards and tokens\n");
|
" [options] [command [args] {-- command [args]}]\n\n"
|
||||||
|
"Tool to manage cards and tokens. With a command an interactive\n"
|
||||||
|
"mode is used. Use command \"help\" to list all commands.");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: p = NULL; break;
|
default: p = NULL; break;
|
||||||
|
@ -170,14 +167,6 @@ my_strusage( int level )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
wrong_args (const char *text)
|
|
||||||
{
|
|
||||||
es_fprintf (es_stderr, _("usage: %s [options] %s\n"), strusage (11), text);
|
|
||||||
exit (2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_opt_session_env (const char *name, const char *value)
|
set_opt_session_env (const char *name, const char *value)
|
||||||
{
|
{
|
||||||
|
@ -192,13 +181,10 @@ set_opt_session_env (const char *name, const char *value)
|
||||||
|
|
||||||
|
|
||||||
/* Command line parsing. */
|
/* Command line parsing. */
|
||||||
static enum cmd_and_opt_values
|
static void
|
||||||
parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts)
|
parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts)
|
||||||
{
|
{
|
||||||
enum cmd_and_opt_values cmd = 0;
|
while (optfile_parse (NULL, NULL, NULL, pargs, popts))
|
||||||
int no_more_options = 0;
|
|
||||||
|
|
||||||
while (!no_more_options && optfile_parse (NULL, NULL, NULL, pargs, popts))
|
|
||||||
{
|
{
|
||||||
switch (pargs->r_opt)
|
switch (pargs->r_opt)
|
||||||
{
|
{
|
||||||
|
@ -231,15 +217,9 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts)
|
||||||
case oLCctype: opt.lc_ctype = pargs->r.ret_str; break;
|
case oLCctype: opt.lc_ctype = pargs->r.ret_str; break;
|
||||||
case oLCmessages: opt.lc_messages = pargs->r.ret_str; break;
|
case oLCmessages: opt.lc_messages = pargs->r.ret_str; break;
|
||||||
|
|
||||||
case aTest:
|
|
||||||
cmd = pargs->r_opt;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: pargs->err = 2; break;
|
default: pargs->err = 2; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -250,7 +230,9 @@ main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
ARGPARSE_ARGS pargs;
|
ARGPARSE_ARGS pargs;
|
||||||
enum cmd_and_opt_values cmd;
|
char **command_list = NULL;
|
||||||
|
int cmdidx;
|
||||||
|
char *command;
|
||||||
|
|
||||||
gnupg_reopen_std ("gpg-card-tool");
|
gnupg_reopen_std ("gpg-card-tool");
|
||||||
set_strusage (my_strusage);
|
set_strusage (my_strusage);
|
||||||
|
@ -276,44 +258,80 @@ main (int argc, char **argv)
|
||||||
pargs.argc = &argc;
|
pargs.argc = &argc;
|
||||||
pargs.argv = &argv;
|
pargs.argv = &argv;
|
||||||
pargs.flags = ARGPARSE_FLAG_KEEP;
|
pargs.flags = ARGPARSE_FLAG_KEEP;
|
||||||
cmd = parse_arguments (&pargs, opts);
|
parse_arguments (&pargs, opts);
|
||||||
|
|
||||||
if (log_get_errorcount (0))
|
if (log_get_errorcount (0))
|
||||||
exit (2);
|
exit (2);
|
||||||
|
|
||||||
/* Print a warning if an argument looks like an option. */
|
|
||||||
if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0; i < argc; i++)
|
|
||||||
if (argv[i][0] == '-' && argv[i][1] == '-')
|
|
||||||
log_info (("NOTE: '%s' is not considered an option\n"), argv[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set defaults for non given options. */
|
/* Set defaults for non given options. */
|
||||||
if (!opt.gpg_program)
|
if (!opt.gpg_program)
|
||||||
opt.gpg_program = gnupg_module_name (GNUPG_MODULE_NAME_GPG);
|
opt.gpg_program = gnupg_module_name (GNUPG_MODULE_NAME_GPG);
|
||||||
if (!opt.gpgsm_program)
|
if (!opt.gpgsm_program)
|
||||||
opt.gpgsm_program = gnupg_module_name (GNUPG_MODULE_NAME_GPGSM);
|
opt.gpgsm_program = gnupg_module_name (GNUPG_MODULE_NAME_GPGSM);
|
||||||
|
|
||||||
/* Run the selected command. */
|
/* Now build the list of commands. We guess the size of the array
|
||||||
switch (cmd)
|
* by assuming each item is a complete command. Obviously this will
|
||||||
|
* be rarely the case, but it is less code to allocate a possible
|
||||||
|
* too large array. */
|
||||||
|
command_list = xcalloc (argc+1, sizeof *command_list);
|
||||||
|
cmdidx = 0;
|
||||||
|
command = NULL;
|
||||||
|
while (argc)
|
||||||
{
|
{
|
||||||
case aTest:
|
for ( ; argc && strcmp (*argv, "--"); argc--, argv++)
|
||||||
if (!argc)
|
{
|
||||||
wrong_args ("--test KEYGRIP");
|
if (!command)
|
||||||
err = test_get_matching_keys (*argv);
|
command = xstrdup (*argv);
|
||||||
break;
|
else
|
||||||
|
{
|
||||||
|
char *tmp = xstrconcat (command, " ", *argv, NULL);
|
||||||
|
xfree (command);
|
||||||
|
command = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (argc)
|
||||||
|
{ /* Skip the double dash. */
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
if (command)
|
||||||
|
{
|
||||||
|
command_list[cmdidx++] = command;
|
||||||
|
command = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opt.interactive = !cmdidx;
|
||||||
|
|
||||||
default:
|
if (opt.interactive)
|
||||||
|
{
|
||||||
interactive_loop ();
|
interactive_loop ();
|
||||||
err = 0;
|
err = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct card_info_s info_buffer;
|
||||||
|
card_info_t info = &info_buffer;
|
||||||
|
|
||||||
|
err = 0;
|
||||||
|
for (cmdidx=0; (command = command_list[cmdidx]); cmdidx++)
|
||||||
|
{
|
||||||
|
err = dispatch_command (info, command);
|
||||||
|
if (err)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (gpg_err_code (err) == GPG_ERR_EOF)
|
||||||
|
err = 0; /* This was a "quit". */
|
||||||
|
else if (command && !opt.quiet)
|
||||||
|
log_info ("stopped at command '%s'\n", command);
|
||||||
|
}
|
||||||
|
|
||||||
flush_keyblock_cache ();
|
flush_keyblock_cache ();
|
||||||
|
if (command_list)
|
||||||
|
{
|
||||||
|
for (cmdidx=0; command_list[cmdidx]; cmdidx++)
|
||||||
|
xfree (command_list[cmdidx]);
|
||||||
|
xfree (command_list);
|
||||||
|
}
|
||||||
if (err)
|
if (err)
|
||||||
gnupg_status_printf (STATUS_FAILURE, "- %u", err);
|
gnupg_status_printf (STATUS_FAILURE, "- %u", err);
|
||||||
else if (log_get_errorcount (0))
|
else if (log_get_errorcount (0))
|
||||||
|
@ -421,22 +439,24 @@ put_data_to_file (const char *fname, const void *buffer, size_t length)
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
print_help (const char *text, ...)
|
print_help (const char *text, ...)
|
||||||
{
|
{
|
||||||
|
estream_t fp;
|
||||||
va_list arg_ptr;
|
va_list arg_ptr;
|
||||||
int value;
|
int value;
|
||||||
int any = 0;
|
int any = 0;
|
||||||
|
|
||||||
tty_fprintf (NULL, "%s\n", text);
|
fp = opt.interactive? NULL : es_stdout;
|
||||||
|
tty_fprintf (fp, "%s\n", text);
|
||||||
|
|
||||||
va_start (arg_ptr, text);
|
va_start (arg_ptr, text);
|
||||||
while ((value = va_arg (arg_ptr, int)))
|
while ((value = va_arg (arg_ptr, int)))
|
||||||
{
|
{
|
||||||
if (!any)
|
if (!any)
|
||||||
tty_fprintf (NULL, "[Supported by: ");
|
tty_fprintf (fp, "[Supported by: ");
|
||||||
tty_fprintf (NULL, "%s%s", any?", ":"", app_type_string (value));
|
tty_fprintf (fp, "%s%s", any?", ":"", app_type_string (value));
|
||||||
any = 1;
|
any = 1;
|
||||||
}
|
}
|
||||||
if (any)
|
if (any)
|
||||||
tty_fprintf (NULL, "]\n");
|
tty_fprintf (fp, "]\n");
|
||||||
|
|
||||||
va_end (arg_ptr);
|
va_end (arg_ptr);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -588,18 +608,6 @@ mem_is_zero (const char *mem, unsigned int memlen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Return true if the buffer MEM or length MEMLEN consists only of 0xFF. */
|
|
||||||
static int
|
|
||||||
mem_is_ff (const char *mem, unsigned int memlen)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0; i < memlen && mem[i] == '\xff'; i++)
|
|
||||||
;
|
|
||||||
return (i == memlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Helper to list a single keyref. */
|
/* Helper to list a single keyref. */
|
||||||
static void
|
static void
|
||||||
|
@ -909,7 +917,7 @@ list_piv (card_info_t info, estream_t fp)
|
||||||
static void
|
static void
|
||||||
list_card (card_info_t info)
|
list_card (card_info_t info)
|
||||||
{
|
{
|
||||||
estream_t fp = NULL;
|
estream_t fp = opt.interactive? NULL : es_stdout;
|
||||||
|
|
||||||
tty_fprintf (fp, "Reader ...........: %s\n",
|
tty_fprintf (fp, "Reader ...........: %s\n",
|
||||||
info->reader? info->reader : "[none]");
|
info->reader? info->reader : "[none]");
|
||||||
|
@ -2716,6 +2724,7 @@ static struct
|
||||||
{ "verify" , cmdVERIFY, 0, N_("verify the PIN and list all data")},
|
{ "verify" , cmdVERIFY, 0, N_("verify the PIN and list all data")},
|
||||||
{ "unblock" , cmdUNBLOCK,0, N_("unblock the PIN using a Reset Code")},
|
{ "unblock" , cmdUNBLOCK,0, N_("unblock the PIN using a Reset Code")},
|
||||||
{ "authenticate",cmdAUTHENTICATE, 0,N_("authenticate to the card")},
|
{ "authenticate",cmdAUTHENTICATE, 0,N_("authenticate to the card")},
|
||||||
|
{ "auth" , cmdAUTHENTICATE, 0, NULL },
|
||||||
{ "reset" , cmdRESET, 0, N_("send a reset to the card daemon")},
|
{ "reset" , cmdRESET, 0, N_("send a reset to the card daemon")},
|
||||||
{ "factory-reset", cmdFACTORYRESET, 1, N_("destroy all keys and data")},
|
{ "factory-reset", cmdFACTORYRESET, 1, N_("destroy all keys and data")},
|
||||||
{ "kdf-setup", cmdKDFSETUP, 1, N_("setup KDF for PIN authentication")},
|
{ "kdf-setup", cmdKDFSETUP, 1, N_("setup KDF for PIN authentication")},
|
||||||
|
@ -2729,7 +2738,169 @@ static struct
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* The main loop. */
|
/* The command line command dispatcher. */
|
||||||
|
static gpg_error_t
|
||||||
|
dispatch_command (card_info_t info, const char *orig_command)
|
||||||
|
{
|
||||||
|
gpg_error_t err = 0;
|
||||||
|
enum cmdids cmd; /* The command. */
|
||||||
|
char *command; /* A malloced copy of ORIG_COMMAND. */
|
||||||
|
char *argstr; /* The argument as a string. */
|
||||||
|
int i;
|
||||||
|
int ignore_error;
|
||||||
|
|
||||||
|
if ((ignore_error = *orig_command == '-'))
|
||||||
|
orig_command++;
|
||||||
|
command = xstrdup (orig_command);
|
||||||
|
argstr = NULL;
|
||||||
|
if ((argstr = strchr (command, ' ')))
|
||||||
|
{
|
||||||
|
*argstr++ = 0;
|
||||||
|
trim_spaces (command);
|
||||||
|
trim_spaces (argstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; cmds[i].name; i++ )
|
||||||
|
if (!ascii_strcasecmp (command, cmds[i].name ))
|
||||||
|
break;
|
||||||
|
cmd = cmds[i].id; /* (If not found this will be cmdINVCMD). */
|
||||||
|
|
||||||
|
/* Make sure we have valid strings for the args. They are allowed
|
||||||
|
* to be modified and must thus point to a buffer. */
|
||||||
|
if (!argstr)
|
||||||
|
argstr = command + strlen (command);
|
||||||
|
|
||||||
|
/* For most commands we need to make sure that we have a card. */
|
||||||
|
if (!info)
|
||||||
|
; /* Help mode */
|
||||||
|
else if (!(cmd == cmdNOP || cmd == cmdQUIT || cmd == cmdHELP
|
||||||
|
|| cmd == cmdINVCMD)
|
||||||
|
&& !info->initialized)
|
||||||
|
{
|
||||||
|
err = scd_learn (info);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error ("Error reading card: %s\n", gpg_strerror (err));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case cmdNOP:
|
||||||
|
if (!info)
|
||||||
|
print_help ("NOP\n\n"
|
||||||
|
"Dummy command.", 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cmdQUIT:
|
||||||
|
if (!info)
|
||||||
|
print_help ("QUIT\n\n"
|
||||||
|
"Stop processing.", 0);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = gpg_error (GPG_ERR_EOF);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cmdHELP:
|
||||||
|
if (!info)
|
||||||
|
print_help ("HELP [command]\n\n"
|
||||||
|
"Show all commands. With an argument show help\n"
|
||||||
|
"for that command.", 0);
|
||||||
|
else if (*argstr)
|
||||||
|
dispatch_command (NULL, argstr);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
es_printf
|
||||||
|
("List of commands (\"help <command>\" for details):\n");
|
||||||
|
for (i=0; cmds[i].name; i++ )
|
||||||
|
if(cmds[i].desc)
|
||||||
|
es_printf("%-14s %s\n", cmds[i].name, _(cmds[i].desc) );
|
||||||
|
es_printf ("Prefix a command with a dash to ignore its error.\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cmdLIST:
|
||||||
|
if (!info)
|
||||||
|
print_help ("LIST\n\n"
|
||||||
|
"Show content of the card.", 0);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = scd_learn (info);
|
||||||
|
if (err)
|
||||||
|
log_error ("Error reading card: %s\n", gpg_strerror (err));
|
||||||
|
else
|
||||||
|
list_card (info);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cmdRESET:
|
||||||
|
if (!info)
|
||||||
|
print_help ("RESET\n\n"
|
||||||
|
"Send a RESET to the card daemon.", 0);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
flush_keyblock_cache ();
|
||||||
|
err = scd_apdu (NULL, NULL);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cmdADMIN:
|
||||||
|
/* This is a NOP in non-interactive mode. */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cmdVERIFY: err = cmd_verify (info, argstr); break;
|
||||||
|
case cmdAUTHENTICATE: err = cmd_authenticate (info, argstr); break;
|
||||||
|
case cmdNAME: err = cmd_name (info, argstr); break;
|
||||||
|
case cmdURL: err = cmd_url (info, argstr); break;
|
||||||
|
case cmdFETCH: err = cmd_fetch (info); break;
|
||||||
|
case cmdLOGIN: err = cmd_login (info, argstr); break;
|
||||||
|
case cmdLANG: err = cmd_lang (info, argstr); break;
|
||||||
|
case cmdSALUT: err = cmd_salut (info, argstr); break;
|
||||||
|
case cmdCAFPR: err = cmd_cafpr (info, argstr); break;
|
||||||
|
case cmdPRIVATEDO: err = cmd_privatedo (info, argstr); break;
|
||||||
|
case cmdWRITECERT: err = cmd_writecert (info, argstr); break;
|
||||||
|
case cmdREADCERT: err = cmd_readcert (info, argstr); break;
|
||||||
|
case cmdFORCESIG: err = cmd_forcesig (info); break;
|
||||||
|
case cmdGENERATE: err = cmd_generate (info); break;
|
||||||
|
case cmdPASSWD: err = cmd_passwd (info, 1); break;
|
||||||
|
case cmdUNBLOCK: err = cmd_unblock (info); break;
|
||||||
|
case cmdFACTORYRESET: err = cmd_factoryreset (info); break;
|
||||||
|
case cmdKDFSETUP: err = cmd_kdfsetup (info, argstr); break;
|
||||||
|
case cmdKEYATTR: err = cmd_keyattr (info, argstr); break;
|
||||||
|
case cmdUIF: err = cmd_uif (info, argstr); break;
|
||||||
|
|
||||||
|
case cmdINVCMD:
|
||||||
|
default:
|
||||||
|
log_error (_("Invalid command (try \"help\")\n"));
|
||||||
|
break;
|
||||||
|
} /* End command switch. */
|
||||||
|
|
||||||
|
|
||||||
|
leave:
|
||||||
|
/* Return GPG_ERR_EOF only if its origin was "quit". */
|
||||||
|
es_fflush (es_stdout);
|
||||||
|
if (gpg_err_code (err) == GPG_ERR_EOF && cmd != cmdQUIT)
|
||||||
|
err = gpg_error (GPG_ERR_GENERAL);
|
||||||
|
if (err && gpg_err_code (err) != GPG_ERR_EOF)
|
||||||
|
{
|
||||||
|
if (ignore_error)
|
||||||
|
{
|
||||||
|
log_info ("Command '%s' failed: %s\n", command, gpg_strerror (err));
|
||||||
|
err = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
log_error ("Command '%s' failed: %s\n", command, gpg_strerror (err));
|
||||||
|
}
|
||||||
|
xfree (command);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* The interactive main loop. */
|
||||||
static void
|
static void
|
||||||
interactive_loop (void)
|
interactive_loop (void)
|
||||||
{
|
{
|
||||||
|
@ -2825,11 +2996,12 @@ interactive_loop (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure we have valid strings for the args. They are
|
/* Make sure we have valid strings for the args. They are
|
||||||
* allowed to be modifed and must thus point to a buffer. */
|
* allowed to be modified and must thus point to a buffer. */
|
||||||
if (!argstr)
|
if (!argstr)
|
||||||
argstr = answer + strlen (answer);
|
argstr = answer + strlen (answer);
|
||||||
|
|
||||||
if (!(cmd == cmdNOP || cmd == cmdQUIT || cmd == cmdHELP))
|
if (!(cmd == cmdNOP || cmd == cmdQUIT || cmd == cmdHELP
|
||||||
|
|| cmd == cmdINVCMD))
|
||||||
{
|
{
|
||||||
/* If redisplay is set we know that there was an error reading
|
/* If redisplay is set we know that there was an error reading
|
||||||
* the card. In this case we force a LIST command to retry. */
|
* the card. In this case we force a LIST command to retry. */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user