mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Support a history file in gpg-card and gpg-connect-agent.
* common/gpgrlhelp.c (read_write_history): New. (gnupg_rl_initialize): Register new function. * common/ttyio.c (my_rl_rw_history): New var. (tty_private_set_rl_hooks): Add arg read_write_history. (tty_read_history): New. (tty_write_history): New. * tools/gpg-card.c (HISTORYNAME): New. (oNoHistory): New enum value. (opts): New option --no-history. (cmd_history): New. (cmds): New command "history". (interactive_loop): Read and save the history. * tools/gpg-connect-agent.c (HISTORYNAME): New. (opts): New option --no-history. (main): Read and save the history. New command /history. -- Yeah, finally we have stored history; I should have added this much earlier. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
07aef873eb
commit
d70b8769c8
@ -47,7 +47,8 @@ void tty_private_set_rl_hooks (void (*init_stream) (FILE *),
|
|||||||
void (*inhibit_completion) (int),
|
void (*inhibit_completion) (int),
|
||||||
void (*cleanup_after_signal) (void),
|
void (*cleanup_after_signal) (void),
|
||||||
char *(*readline_fun) (const char*),
|
char *(*readline_fun) (const char*),
|
||||||
void (*add_history_fun) (const char*));
|
void (*add_history_fun) (const char*),
|
||||||
|
int (*rw_history_fun)(const char *, int, int));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,11 +77,77 @@ init_stream (FILE *fp)
|
|||||||
rl_inhibit_completion = 1;
|
rl_inhibit_completion = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Read or write the history to or from the file FILENAME. The
|
||||||
|
* behaviour depends on the flag WRITE_MODE:
|
||||||
|
*
|
||||||
|
* In read mode (WRITE_MODE is false) these semantics are used:
|
||||||
|
*
|
||||||
|
* If NLINES is positive only this number of lines are read from the
|
||||||
|
* history and the history is always limited to that number of
|
||||||
|
* lines. A negative value for NLINES is undefined.
|
||||||
|
*
|
||||||
|
* If FILENAME is NULL the current history is cleared. If NLINES is
|
||||||
|
* positive the number of lines stored in the history is limited to
|
||||||
|
* that number. A negative value for NLINES is undefined.
|
||||||
|
*
|
||||||
|
* If WRITE_MODE is true these semantics are used:
|
||||||
|
*
|
||||||
|
* If NLINES is negative the history and the history file are
|
||||||
|
* cleared; if it is zero the entire history is written to the file;
|
||||||
|
* if it is positive the history is written to the file and the file
|
||||||
|
* is truncated to this number of lines.
|
||||||
|
*
|
||||||
|
* If FILENAME is NULL no file operations are done but if NLINES is
|
||||||
|
* negative the entire history is cleared.
|
||||||
|
*
|
||||||
|
* On success 0 is returned; on error -1 is returned and ERRNO is set.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
read_write_history (const char *filename, int write_mode, int nlines)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (write_mode)
|
||||||
|
{
|
||||||
|
if (nlines < 0)
|
||||||
|
clear_history ();
|
||||||
|
rc = filename? write_history (filename) : 0;
|
||||||
|
if (!rc && filename && nlines > 0)
|
||||||
|
rc = history_truncate_file (filename, nlines);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
gpg_err_set_errno (rc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clear_history ();
|
||||||
|
if (filename)
|
||||||
|
{
|
||||||
|
if (nlines)
|
||||||
|
rc = read_history_range (filename, 0, nlines);
|
||||||
|
else
|
||||||
|
rc = read_history (filename);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
gpg_err_set_errno (rc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nlines > 0)
|
||||||
|
stifle_history (nlines);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /*HAVE_LIBREADLINE*/
|
#endif /*HAVE_LIBREADLINE*/
|
||||||
|
|
||||||
|
|
||||||
/* Initialize our readline code. This should be called as early as
|
/* Initialize our readline code. This should be called as early as
|
||||||
possible as it is actually a constructur. */
|
* possible as it is actually a constructor. */
|
||||||
void
|
void
|
||||||
gnupg_rl_initialize (void)
|
gnupg_rl_initialize (void)
|
||||||
{
|
{
|
||||||
@ -91,7 +157,8 @@ gnupg_rl_initialize (void)
|
|||||||
inhibit_completion,
|
inhibit_completion,
|
||||||
cleanup_after_signal,
|
cleanup_after_signal,
|
||||||
readline,
|
readline,
|
||||||
add_history);
|
add_history,
|
||||||
|
read_write_history);
|
||||||
rl_readline_name = GNUPG_NAME;
|
rl_readline_name = GNUPG_NAME;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ static void (*my_rl_cleanup_after_signal) (void);
|
|||||||
static void (*my_rl_init_stream) (FILE *);
|
static void (*my_rl_init_stream) (FILE *);
|
||||||
static char *(*my_rl_readline) (const char*);
|
static char *(*my_rl_readline) (const char*);
|
||||||
static void (*my_rl_add_history) (const char*);
|
static void (*my_rl_add_history) (const char*);
|
||||||
|
static int (*my_rl_rw_history)(const char *, int, int);
|
||||||
|
|
||||||
/* This is a wrapper around ttyname so that we can use it even when
|
/* This is a wrapper around ttyname so that we can use it even when
|
||||||
the standard streams are redirected. It figures the name out the
|
the standard streams are redirected. It figures the name out the
|
||||||
@ -703,7 +703,8 @@ tty_private_set_rl_hooks (void (*init_stream) (FILE *),
|
|||||||
void (*inhibit_completion) (int),
|
void (*inhibit_completion) (int),
|
||||||
void (*cleanup_after_signal) (void),
|
void (*cleanup_after_signal) (void),
|
||||||
char *(*readline_fun) (const char*),
|
char *(*readline_fun) (const char*),
|
||||||
void (*add_history_fun) (const char*))
|
void (*add_history_fun) (const char*),
|
||||||
|
int (*rw_history_fun)(const char *, int, int))
|
||||||
{
|
{
|
||||||
my_rl_init_stream = init_stream;
|
my_rl_init_stream = init_stream;
|
||||||
my_rl_set_completer = set_completer;
|
my_rl_set_completer = set_completer;
|
||||||
@ -711,6 +712,40 @@ tty_private_set_rl_hooks (void (*init_stream) (FILE *),
|
|||||||
my_rl_cleanup_after_signal = cleanup_after_signal;
|
my_rl_cleanup_after_signal = cleanup_after_signal;
|
||||||
my_rl_readline = readline_fun;
|
my_rl_readline = readline_fun;
|
||||||
my_rl_add_history = add_history_fun;
|
my_rl_add_history = add_history_fun;
|
||||||
|
my_rl_rw_history = rw_history_fun;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Read the history from FILENAME or limit the size of the history.
|
||||||
|
* If FILENAME is NULL and NLINES is zero the current history is
|
||||||
|
* cleared. Returns 0 on success or -1 on error and sets ERRNO. No
|
||||||
|
* error is return if readline support is not available. */
|
||||||
|
int
|
||||||
|
tty_read_history (const char *filename, int nlines)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (!my_rl_rw_history)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
rc = my_rl_rw_history (filename, 0, nlines);
|
||||||
|
if (rc && gpg_err_code_from_syserror () == GPG_ERR_ENOENT)
|
||||||
|
rc = 0;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Write the current history to the file FILENAME. Returns 0 on
|
||||||
|
* success or -1 on error and sets ERRNO. No error is return if
|
||||||
|
* readline support is not available. */
|
||||||
|
int
|
||||||
|
tty_write_history (const char *filename)
|
||||||
|
{
|
||||||
|
if (!my_rl_rw_history)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return my_rl_rw_history (filename, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,6 +66,8 @@ void tty_disable_completion (void);
|
|||||||
#define tty_enable_completion(x)
|
#define tty_enable_completion(x)
|
||||||
#define tty_disable_completion()
|
#define tty_disable_completion()
|
||||||
#endif
|
#endif
|
||||||
|
int tty_read_history (const char *filename, int nlines);
|
||||||
|
int tty_write_history (const char *filename);
|
||||||
void tty_cleanup_after_signal (void);
|
void tty_cleanup_after_signal (void);
|
||||||
void tty_cleanup_rl_after_signal (void);
|
void tty_cleanup_rl_after_signal (void);
|
||||||
|
|
||||||
|
@ -105,6 +105,12 @@ Do not start the gpg-agent if it has not yet been started and its
|
|||||||
service is required. This option is mostly useful on machines where
|
service is required. This option is mostly useful on machines where
|
||||||
the connection to gpg-agent has been redirected to another machines.
|
the connection to gpg-agent has been redirected to another machines.
|
||||||
|
|
||||||
|
@item --no-history
|
||||||
|
@opindex --no-history
|
||||||
|
In interactive mode the command line history is usually saved and
|
||||||
|
restored to and from a file below the GnuPG home directory. This
|
||||||
|
option inhibits the use of that file.
|
||||||
|
|
||||||
@item --agent-program @var{file}
|
@item --agent-program @var{file}
|
||||||
@opindex agent-program
|
@opindex agent-program
|
||||||
Specify the agent program to be started if none is running. The
|
Specify the agent program to be started if none is running. The
|
||||||
|
@ -1391,6 +1391,12 @@ passing. This option makes it use the old mode.
|
|||||||
Do not start the gpg-agent or the dirmngr if it has not yet been
|
Do not start the gpg-agent or the dirmngr if it has not yet been
|
||||||
started.
|
started.
|
||||||
|
|
||||||
|
@item --no-history
|
||||||
|
@opindex --no-history
|
||||||
|
In interactive mode the command line history is usually saved and
|
||||||
|
restored to and from a file below the GnuPG home directory. This
|
||||||
|
option inhibits the use of that file.
|
||||||
|
|
||||||
@item -r @var{file}
|
@item -r @var{file}
|
||||||
@itemx --run @var{file}
|
@itemx --run @var{file}
|
||||||
@opindex run
|
@opindex run
|
||||||
@ -1611,6 +1617,9 @@ string @code{true} or @code{yes}. The evaluation is done by passing
|
|||||||
@item /run @var{file}
|
@item /run @var{file}
|
||||||
Run commands from @var{file}.
|
Run commands from @var{file}.
|
||||||
|
|
||||||
|
@item /history --clear
|
||||||
|
Clear the command history.
|
||||||
|
|
||||||
@item /bye
|
@item /bye
|
||||||
Terminate the connection and the program.
|
Terminate the connection and the program.
|
||||||
|
|
||||||
|
@ -48,6 +48,8 @@
|
|||||||
|
|
||||||
#define CONTROL_D ('D' - 'A' + 1)
|
#define CONTROL_D ('D' - 'A' + 1)
|
||||||
|
|
||||||
|
#define HISTORYNAME ".gpg-card_history"
|
||||||
|
|
||||||
/* Constants to identify the commands and options. */
|
/* Constants to identify the commands and options. */
|
||||||
enum opt_values
|
enum opt_values
|
||||||
{
|
{
|
||||||
@ -73,6 +75,7 @@ enum opt_values
|
|||||||
oLCmessages,
|
oLCmessages,
|
||||||
|
|
||||||
oNoKeyLookup,
|
oNoKeyLookup,
|
||||||
|
oNoHistory,
|
||||||
|
|
||||||
oDummy
|
oDummy
|
||||||
};
|
};
|
||||||
@ -99,6 +102,8 @@ static gpgrt_opt_t opts[] = {
|
|||||||
ARGPARSE_s_s (oLCmessages, "lc-messages","@"),
|
ARGPARSE_s_s (oLCmessages, "lc-messages","@"),
|
||||||
ARGPARSE_s_n (oNoKeyLookup,"no-key-lookup",
|
ARGPARSE_s_n (oNoKeyLookup,"no-key-lookup",
|
||||||
"use --no-key-lookup for \"list\""),
|
"use --no-key-lookup for \"list\""),
|
||||||
|
ARGPARSE_s_n (oNoHistory,"no-history",
|
||||||
|
"do not use the command history file"),
|
||||||
|
|
||||||
ARGPARSE_end ()
|
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 oLCmessages: opt.lc_messages = pargs->r.ret_str; break;
|
||||||
|
|
||||||
case oNoKeyLookup: opt.no_key_lookup = 1; break;
|
case oNoKeyLookup: opt.no_key_lookup = 1; break;
|
||||||
|
case oNoHistory: opt.no_history = 1; break;
|
||||||
|
|
||||||
default: pargs->err = 2; break;
|
default: pargs->err = 2; break;
|
||||||
}
|
}
|
||||||
@ -315,6 +321,9 @@ main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
opt.interactive = !cmdidx;
|
opt.interactive = !cmdidx;
|
||||||
|
|
||||||
|
if (!opt.interactive)
|
||||||
|
opt.no_history = 1;
|
||||||
|
|
||||||
if (opt.interactive)
|
if (opt.interactive)
|
||||||
{
|
{
|
||||||
interactive_loop ();
|
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
|
/* 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,
|
cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSALUT, cmdCAFPR,
|
||||||
cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO, cmdWRITECERT,
|
cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO, cmdWRITECERT,
|
||||||
cmdREADCERT, cmdWRITEKEY, cmdUNBLOCK, cmdFACTRST, cmdKDFSETUP,
|
cmdREADCERT, cmdWRITEKEY, cmdUNBLOCK, cmdFACTRST, cmdKDFSETUP,
|
||||||
cmdUIF, cmdAUTH, cmdYUBIKEY, cmdAPDU,
|
cmdUIF, cmdAUTH, cmdYUBIKEY, cmdAPDU, cmdHISTORY,
|
||||||
cmdINVCMD
|
cmdINVCMD
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3551,6 +3586,7 @@ static struct
|
|||||||
{ "writekey", cmdWRITEKEY, N_("store a private key to a data object")},
|
{ "writekey", cmdWRITEKEY, N_("store a private key to a data object")},
|
||||||
{ "yubikey", cmdYUBIKEY, N_("Yubikey management commands")},
|
{ "yubikey", cmdYUBIKEY, N_("Yubikey management commands")},
|
||||||
{ "apdu", cmdAPDU, NULL},
|
{ "apdu", cmdAPDU, NULL},
|
||||||
|
{ "history", cmdHISTORY, N_("manage the command history")},
|
||||||
{ NULL, cmdINVCMD, NULL }
|
{ 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 cmdUIF: err = cmd_uif (info, argstr); break;
|
||||||
case cmdYUBIKEY: err = cmd_yubikey (info, argstr); break;
|
case cmdYUBIKEY: err = cmd_yubikey (info, argstr); break;
|
||||||
case cmdAPDU: err = cmd_apdu (info, argstr); break;
|
case cmdAPDU: err = cmd_apdu (info, argstr); break;
|
||||||
|
case cmdHISTORY: err = 0; break; /* Only used in interactive mode. */
|
||||||
|
|
||||||
case cmdINVCMD:
|
case cmdINVCMD:
|
||||||
default:
|
default:
|
||||||
@ -3735,10 +3772,19 @@ interactive_loop (void)
|
|||||||
card_info_t info = &info_buffer;
|
card_info_t info = &info_buffer;
|
||||||
char *p;
|
char *p;
|
||||||
int i;
|
int i;
|
||||||
|
const char *historyname = NULL;
|
||||||
|
|
||||||
/* In the interactive mode we do not want to print the program prefix. */
|
/* In the interactive mode we do not want to print the program prefix. */
|
||||||
log_set_prefix (NULL, 0);
|
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 (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (help_arg)
|
if (help_arg)
|
||||||
@ -3818,7 +3864,7 @@ interactive_loop (void)
|
|||||||
argstr = answer + strlen (answer);
|
argstr = answer + strlen (answer);
|
||||||
|
|
||||||
if (!(cmd == cmdNOP || cmd == cmdQUIT || cmd == cmdHELP
|
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
|
/* 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. */
|
||||||
@ -3926,6 +3972,7 @@ interactive_loop (void)
|
|||||||
case cmdUIF: err = cmd_uif (info, argstr); break;
|
case cmdUIF: err = cmd_uif (info, argstr); break;
|
||||||
case cmdYUBIKEY: err = cmd_yubikey (info, argstr); break;
|
case cmdYUBIKEY: err = cmd_yubikey (info, argstr); break;
|
||||||
case cmdAPDU: err = cmd_apdu (info, argstr); break;
|
case cmdAPDU: err = cmd_apdu (info, argstr); break;
|
||||||
|
case cmdHISTORY: err = cmd_history (info, argstr); break;
|
||||||
|
|
||||||
case cmdINVCMD:
|
case cmdINVCMD:
|
||||||
default:
|
default:
|
||||||
@ -3962,7 +4009,12 @@ interactive_loop (void)
|
|||||||
} /* End of main menu loop. */
|
} /* End of main menu loop. */
|
||||||
|
|
||||||
leave:
|
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);
|
release_card_info (info);
|
||||||
|
xfree (historyname);
|
||||||
xfree (answer);
|
xfree (answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,8 @@ struct
|
|||||||
|
|
||||||
int no_key_lookup; /* Assume --no-key-lookup for "list". */
|
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: */
|
/* Options passed to the gpg-agent: */
|
||||||
session_env_t session_env;
|
session_env_t session_env;
|
||||||
char *lc_ctype;
|
char *lc_ctype;
|
||||||
|
@ -44,6 +44,9 @@
|
|||||||
#define CONTROL_D ('D' - 'A' + 1)
|
#define CONTROL_D ('D' - 'A' + 1)
|
||||||
#define octdigitp(p) (*(p) >= '0' && *(p) <= '7')
|
#define octdigitp(p) (*(p) >= '0' && *(p) <= '7')
|
||||||
|
|
||||||
|
#define HISTORYNAME ".gpg-connect_history"
|
||||||
|
|
||||||
|
|
||||||
/* Constants to identify the commands and options. */
|
/* Constants to identify the commands and options. */
|
||||||
enum cmd_and_opt_values
|
enum cmd_and_opt_values
|
||||||
{
|
{
|
||||||
@ -67,6 +70,7 @@ enum cmd_and_opt_values
|
|||||||
oDirmngr,
|
oDirmngr,
|
||||||
oKeyboxd,
|
oKeyboxd,
|
||||||
oUIServer,
|
oUIServer,
|
||||||
|
oNoHistory,
|
||||||
oNoAutostart
|
oNoAutostart
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -97,6 +101,8 @@ static gpgrt_opt_t opts[] = {
|
|||||||
|
|
||||||
ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"),
|
ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"),
|
||||||
ARGPARSE_s_n (oNoVerbose, "no-verbose", "@"),
|
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 (oHomedir, "homedir", "@" ),
|
||||||
ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
|
ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
|
||||||
ARGPARSE_s_s (oDirmngrProgram, "dirmngr-program", "@"),
|
ARGPARSE_s_s (oDirmngrProgram, "dirmngr-program", "@"),
|
||||||
@ -127,6 +133,7 @@ struct
|
|||||||
unsigned int connect_flags; /* Flags used for connecting. */
|
unsigned int connect_flags; /* Flags used for connecting. */
|
||||||
int enable_varsubst; /* Set if variable substitution is enabled. */
|
int enable_varsubst; /* Set if variable substitution is enabled. */
|
||||||
int trim_leading_spaces;
|
int trim_leading_spaces;
|
||||||
|
int no_history;
|
||||||
} opt;
|
} opt;
|
||||||
|
|
||||||
|
|
||||||
@ -1178,6 +1185,7 @@ main (int argc, char **argv)
|
|||||||
} loopstack[20];
|
} loopstack[20];
|
||||||
int loopidx;
|
int loopidx;
|
||||||
char **cmdline_commands = NULL;
|
char **cmdline_commands = NULL;
|
||||||
|
char *historyname = NULL;
|
||||||
|
|
||||||
early_system_init ();
|
early_system_init ();
|
||||||
gnupg_rl_initialize ();
|
gnupg_rl_initialize ();
|
||||||
@ -1210,6 +1218,7 @@ main (int argc, char **argv)
|
|||||||
case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break;
|
case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break;
|
||||||
case oKeyboxdProgram: opt.keyboxd_program = pargs.r.ret_str; break;
|
case oKeyboxdProgram: opt.keyboxd_program = pargs.r.ret_str; break;
|
||||||
case oNoAutostart: opt.autostart = 0; break;
|
case oNoAutostart: opt.autostart = 0; break;
|
||||||
|
case oNoHistory: opt.no_history = 1; break;
|
||||||
case oHex: opt.hex = 1; break;
|
case oHex: opt.hex = 1; break;
|
||||||
case oDecode: opt.decode = 1; break;
|
case oDecode: opt.decode = 1; break;
|
||||||
case oDirmngr: opt.use_dirmngr = 1; break;
|
case oDirmngr: opt.use_dirmngr = 1; break;
|
||||||
@ -1422,6 +1431,15 @@ main (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
keep_line = 0;
|
keep_line = 0;
|
||||||
xfree (line);
|
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 ("> ");
|
line = tty_get ("> ");
|
||||||
n = strlen (line);
|
n = strlen (line);
|
||||||
if (n==1 && *line == CONTROL_D)
|
if (n==1 && *line == CONTROL_D)
|
||||||
@ -1817,6 +1835,15 @@ main (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
gnupg_sleep (1);
|
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"))
|
else if (!strcmp (cmd, "help"))
|
||||||
{
|
{
|
||||||
puts (
|
puts (
|
||||||
@ -1843,6 +1870,7 @@ main (int argc, char **argv)
|
|||||||
"/if VAR Begin conditional block controlled by VAR.\n"
|
"/if VAR Begin conditional block controlled by VAR.\n"
|
||||||
"/while VAR Begin loop controlled by VAR.\n"
|
"/while VAR Begin loop controlled by VAR.\n"
|
||||||
"/end End loop or condition\n"
|
"/end End loop or condition\n"
|
||||||
|
"/history Manage the history\n"
|
||||||
"/bye Terminate gpg-connect-agent.\n"
|
"/bye Terminate gpg-connect-agent.\n"
|
||||||
"/help Print this help.");
|
"/help Print this help.");
|
||||||
}
|
}
|
||||||
@ -1895,6 +1923,12 @@ main (int argc, char **argv)
|
|||||||
opt.use_keyboxd? "keyboxd" :
|
opt.use_keyboxd? "keyboxd" :
|
||||||
"agent");
|
"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
|
/* XXX: We would like to release the context here, but libassuan
|
||||||
nicely says good bye to the server, which results in a SIGPIPE if
|
nicely says good bye to the server, which results in a SIGPIPE if
|
||||||
the server died. Unfortunately, libassuan does not ignore
|
the server died. Unfortunately, libassuan does not ignore
|
||||||
@ -1904,6 +1938,7 @@ main (int argc, char **argv)
|
|||||||
assuan_release (ctx);
|
assuan_release (ctx);
|
||||||
else
|
else
|
||||||
gpgrt_annotate_leaked_object (ctx);
|
gpgrt_annotate_leaked_object (ctx);
|
||||||
|
xfree (historyname);
|
||||||
xfree (line);
|
xfree (line);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user