diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/gpg-card.c | 56 | ||||
-rw-r--r-- | tools/gpg-card.h | 2 | ||||
-rw-r--r-- | tools/gpg-connect-agent.c | 35 |
3 files changed, 91 insertions, 2 deletions
diff --git a/tools/gpg-card.c b/tools/gpg-card.c index 96b2bcf44..2fcc120fb 100644 --- a/tools/gpg-card.c +++ b/tools/gpg-card.c @@ -48,6 +48,8 @@ #define CONTROL_D ('D' - 'A' + 1) +#define HISTORYNAME ".gpg-card_history" + /* Constants to identify the commands and options. */ enum opt_values { @@ -73,6 +75,7 @@ enum opt_values oLCmessages, oNoKeyLookup, + oNoHistory, oDummy }; @@ -99,6 +102,8 @@ static gpgrt_opt_t opts[] = { ARGPARSE_s_s (oLCmessages, "lc-messages","@"), ARGPARSE_s_n (oNoKeyLookup,"no-key-lookup", "use --no-key-lookup for \"list\""), + ARGPARSE_s_n (oNoHistory,"no-history", + "do not use the command history file"), ARGPARSE_end () }; @@ -228,6 +233,7 @@ parse_arguments (gpgrt_argparse_t *pargs, gpgrt_opt_t *popts) case oLCmessages: opt.lc_messages = pargs->r.ret_str; break; case oNoKeyLookup: opt.no_key_lookup = 1; break; + case oNoHistory: opt.no_history = 1; break; default: pargs->err = 2; break; } @@ -315,6 +321,9 @@ main (int argc, char **argv) } opt.interactive = !cmdidx; + if (!opt.interactive) + opt.no_history = 1; + if (opt.interactive) { interactive_loop (); @@ -3498,6 +3507,32 @@ cmd_apdu (card_info_t info, char *argstr) } +static gpg_error_t +cmd_history (card_info_t info, char *argstr) +{ + int opt_list, opt_clear; + + opt_list = has_option (argstr, "--list"); + opt_clear = has_option (argstr, "--clear"); + + if (!info || !(opt_list || opt_clear)) + return print_help + ("HISTORY --list\n" + " List the command history\n" + "HISTORY --clear\n" + " Clear the command history", + 0); + + if (opt_list) + tty_printf ("Sorry, history listing not yet possible\n"); + + if (opt_clear) + tty_read_history (NULL, 0); + + return 0; +} + + /* Data used by the command parser. This needs to be outside of the @@ -3509,7 +3544,7 @@ enum cmdids cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSALUT, cmdCAFPR, cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO, cmdWRITECERT, cmdREADCERT, cmdWRITEKEY, cmdUNBLOCK, cmdFACTRST, cmdKDFSETUP, - cmdUIF, cmdAUTH, cmdYUBIKEY, cmdAPDU, + cmdUIF, cmdAUTH, cmdYUBIKEY, cmdAPDU, cmdHISTORY, cmdINVCMD }; @@ -3551,6 +3586,7 @@ static struct { "writekey", cmdWRITEKEY, N_("store a private key to a data object")}, { "yubikey", cmdYUBIKEY, N_("Yubikey management commands")}, { "apdu", cmdAPDU, NULL}, + { "history", cmdHISTORY, N_("manage the command history")}, { NULL, cmdINVCMD, NULL } }; @@ -3679,6 +3715,7 @@ dispatch_command (card_info_t info, const char *orig_command) case cmdUIF: err = cmd_uif (info, argstr); break; case cmdYUBIKEY: err = cmd_yubikey (info, argstr); break; case cmdAPDU: err = cmd_apdu (info, argstr); break; + case cmdHISTORY: err = 0; break; /* Only used in interactive mode. */ case cmdINVCMD: default: @@ -3735,10 +3772,19 @@ interactive_loop (void) card_info_t info = &info_buffer; char *p; int i; + const char *historyname = NULL; /* In the interactive mode we do not want to print the program prefix. */ log_set_prefix (NULL, 0); + if (!opt.no_history) + { + historyname = make_filename (gnupg_homedir (), HISTORYNAME, NULL); + if (tty_read_history (historyname, 500)) + log_info ("error reading '%s': %s\n", + historyname, gpg_strerror (gpg_error_from_syserror ())); + } + for (;;) { if (help_arg) @@ -3818,7 +3864,7 @@ interactive_loop (void) argstr = answer + strlen (answer); if (!(cmd == cmdNOP || cmd == cmdQUIT || cmd == cmdHELP - || cmd == cmdINVCMD)) + || cmd == cmdHISTORY || cmd == cmdINVCMD)) { /* If redisplay is set we know that there was an error reading * the card. In this case we force a LIST command to retry. */ @@ -3926,6 +3972,7 @@ interactive_loop (void) case cmdUIF: err = cmd_uif (info, argstr); break; case cmdYUBIKEY: err = cmd_yubikey (info, argstr); break; case cmdAPDU: err = cmd_apdu (info, argstr); break; + case cmdHISTORY: err = cmd_history (info, argstr); break; case cmdINVCMD: default: @@ -3962,7 +4009,12 @@ interactive_loop (void) } /* End of main menu loop. */ leave: + if (historyname && tty_write_history (historyname)) + log_info ("error writing '%s': %s\n", + historyname, gpg_strerror (gpg_error_from_syserror ())); + release_card_info (info); + xfree (historyname); xfree (answer); } diff --git a/tools/gpg-card.h b/tools/gpg-card.h index 56e117bf3..067720d6c 100644 --- a/tools/gpg-card.h +++ b/tools/gpg-card.h @@ -40,6 +40,8 @@ struct int no_key_lookup; /* Assume --no-key-lookup for "list". */ + int no_history; /* Do not use the command line history. */ + /* Options passed to the gpg-agent: */ session_env_t session_env; char *lc_ctype; diff --git a/tools/gpg-connect-agent.c b/tools/gpg-connect-agent.c index 746ac7daf..cde086770 100644 --- a/tools/gpg-connect-agent.c +++ b/tools/gpg-connect-agent.c @@ -44,6 +44,9 @@ #define CONTROL_D ('D' - 'A' + 1) #define octdigitp(p) (*(p) >= '0' && *(p) <= '7') +#define HISTORYNAME ".gpg-connect_history" + + /* Constants to identify the commands and options. */ enum cmd_and_opt_values { @@ -67,6 +70,7 @@ enum cmd_and_opt_values oDirmngr, oKeyboxd, oUIServer, + oNoHistory, oNoAutostart }; @@ -97,6 +101,8 @@ static gpgrt_opt_t opts[] = { ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"), ARGPARSE_s_n (oNoVerbose, "no-verbose", "@"), + ARGPARSE_s_n (oNoHistory,"no-history", + "do not use the command history file"), ARGPARSE_s_s (oHomedir, "homedir", "@" ), ARGPARSE_s_s (oAgentProgram, "agent-program", "@"), ARGPARSE_s_s (oDirmngrProgram, "dirmngr-program", "@"), @@ -127,6 +133,7 @@ struct unsigned int connect_flags; /* Flags used for connecting. */ int enable_varsubst; /* Set if variable substitution is enabled. */ int trim_leading_spaces; + int no_history; } opt; @@ -1178,6 +1185,7 @@ main (int argc, char **argv) } loopstack[20]; int loopidx; char **cmdline_commands = NULL; + char *historyname = NULL; early_system_init (); gnupg_rl_initialize (); @@ -1210,6 +1218,7 @@ main (int argc, char **argv) case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break; case oKeyboxdProgram: opt.keyboxd_program = pargs.r.ret_str; break; case oNoAutostart: opt.autostart = 0; break; + case oNoHistory: opt.no_history = 1; break; case oHex: opt.hex = 1; break; case oDecode: opt.decode = 1; break; case oDirmngr: opt.use_dirmngr = 1; break; @@ -1422,6 +1431,15 @@ main (int argc, char **argv) { keep_line = 0; xfree (line); + if (!historyname && !opt.no_history) + { + historyname = make_filename (gnupg_homedir (), HISTORYNAME, NULL); + if (tty_read_history (historyname, 500)) + log_info ("error reading '%s': %s\n", + historyname, + gpg_strerror (gpg_error_from_syserror ())); + } + line = tty_get ("> "); n = strlen (line); if (n==1 && *line == CONTROL_D) @@ -1817,6 +1835,15 @@ main (int argc, char **argv) { gnupg_sleep (1); } + else if (!strcmp (cmd, "history")) + { + if (!strcmp (p, "--clear")) + { + tty_read_history (NULL, 0); + } + else + log_error ("Only \"/history --clear\" is supported\n"); + } else if (!strcmp (cmd, "help")) { puts ( @@ -1843,6 +1870,7 @@ main (int argc, char **argv) "/if VAR Begin conditional block controlled by VAR.\n" "/while VAR Begin loop controlled by VAR.\n" "/end End loop or condition\n" +"/history Manage the history\n" "/bye Terminate gpg-connect-agent.\n" "/help Print this help."); } @@ -1895,6 +1923,12 @@ main (int argc, char **argv) opt.use_keyboxd? "keyboxd" : "agent"); + + if (historyname && tty_write_history (historyname)) + log_info ("error writing '%s': %s\n", + historyname, gpg_strerror (gpg_error_from_syserror ())); + + /* XXX: We would like to release the context here, but libassuan nicely says good bye to the server, which results in a SIGPIPE if the server died. Unfortunately, libassuan does not ignore @@ -1904,6 +1938,7 @@ main (int argc, char **argv) assuan_release (ctx); else gpgrt_annotate_leaked_object (ctx); + xfree (historyname); xfree (line); return 0; } |