diff --git a/examples/cli.c b/examples/cli.c index 0fd4bae..87bea1a 100644 --- a/examples/cli.c +++ b/examples/cli.c @@ -160,6 +160,7 @@ int main(int argc, char *argv[]) .history_size = 10, .app_name = "example_cli", .prompt = "my_cli", + .hist_file = "/tmp/icli_history", .cmd_hook = cli_cmd_hook, .out_hook = cli_out_hook, .err_hook = cli_err_hook}; diff --git a/icli.c b/icli.c index 403447f..e330710 100644 --- a/icli.c +++ b/icli.c @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -71,7 +72,7 @@ struct icli { struct icli_command *curr_cmd; char *curr_prompt; const char *prompt; - + const char *hist_file; int rows; int cols; int curr_row; @@ -936,6 +937,7 @@ int icli_register_command(struct icli_command_params *params, struct icli_comman int icli_init(struct icli_params *params) { memset(&icli, 0, sizeof(icli)); + int ret = 0; icli.root_cmd = calloc(1, sizeof(struct icli_command)); if (!icli.root_cmd) { @@ -951,6 +953,20 @@ int icli_init(struct icli_params *params) icli.user_data = params->user_data; icli.prompt = strdup(params->prompt); + if (!icli.prompt) { + icli_api_printf("Unable to allocate memory for prompt\n"); + ret = -1; + goto err; + } + + if (params->hist_file) { + icli.hist_file = strdup(params->hist_file); + if (!icli.hist_file) { + icli_api_printf("Unable to allocate memory for hist_file\n"); + ret = -1; + goto err; + } + } icli.cmd_hook = params->cmd_hook; icli.out_hook = params->out_hook; @@ -958,6 +974,11 @@ int icli_init(struct icli_params *params) /* Allow conditional parsing of the ~/.inputrc file. */ rl_readline_name = strdup(params->app_name); + if (!rl_readline_name) { + icli_api_printf("Unable to allocate memory for rl_readline_name\n"); + ret = -1; + goto err; + } /* Tell the completer that we want a crack first. */ rl_attempted_completion_function = icli_completion; @@ -965,6 +986,15 @@ int icli_init(struct icli_params *params) using_history(); stifle_history(params->history_size); + if (icli.hist_file) { + ret = read_history(icli.hist_file); + if (ret && ret != ENOENT) { + icli_api_printf("Unable to read history from %s (%d)\n", icli.hist_file, ret); + ret = -1; + goto err; + } + } + rl_get_screen_size(&icli.rows, &icli.cols); icli_build_prompt(icli.curr_cmd); @@ -977,7 +1007,7 @@ int icli_init(struct icli_params *params) .argc = 1, .argv = execute_args}}; struct icli_command *commands[array_len(cmd_params)] = {}; - int ret = icli_register_commands(cmd_params, commands, array_len(cmd_params)); + ret = icli_register_commands(cmd_params, commands, array_len(cmd_params)); if (ret) { goto err; } @@ -1001,8 +1031,6 @@ void icli_cleanup(void) { icli_clean_command(icli.root_cmd); - rl_callback_handler_remove(); - HISTORY_STATE *hist_state = history_get_history_state(); HIST_ENTRY **mylist = history_list(); @@ -1012,13 +1040,24 @@ void icli_cleanup(void) free(mylist); free(hist_state); + if (icli.hist_file) { + int ret = write_history(icli.hist_file); + if (ret) + icli_api_printf("Unable to save history to %s (%d)\n", icli.hist_file, ret); + } + clear_history(); + rl_callback_handler_remove(); + free(rl_readline_name); rl_readline_name = ""; free((void *)icli.prompt); free((void *)icli.curr_prompt); + free((void *)icli.hist_file); + + memset(&icli, 0, sizeof(icli)); } void icli_run(void) diff --git a/icli.h b/icli.h index 9fcb397..4993e0a 100644 --- a/icli.h +++ b/icli.h @@ -56,6 +56,7 @@ struct icli_params { int history_size; /**< how many commands to keep in history */ const char *app_name; /**< name of application for interfacing ~/.inputrc */ const char *prompt; /**< prompt string (will be post-fixed by "> " */ + const char *hist_file; /**< history file to load/store history. can be NULL for not saving history */ icli_cmd_hook_t cmd_hook; /**< hook to be called before command is executed */ icli_output_hook_t out_hook; /**< hook to be called when there is output */ icli_output_hook_t err_hook; /**< hook to be called when there is error print */