1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-22 17:35:59 +03:00
lvm2/tools/lvm.c
Zdenek Kabelac 39b7d1ba8f cleanup: typos in comments
Collection of typos in code comments.
Should have no runtime effect.
2024-08-30 16:51:15 +02:00

373 lines
9.3 KiB
C

/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "tools.h"
#include "lvm2cmdline.h"
int main(int argc, char **argv)
{
/* coverity[os_cmd_sink] intentionally passing argv */
return lvm2_main(argc, argv);
}
#if defined(READLINE_SUPPORT) || defined(EDITLINE_SUPPORT)
# ifdef READLINE_SUPPORT
# include <readline/readline.h>
# include <readline/history.h>
# ifndef HAVE_RL_COMPLETION_MATCHES
# define rl_completion_matches(a, b) completion_matches((char *)a, b)
# define rl_completion_func_t CPPFunction
# endif
# elif defined(EDITLINE_SUPPORT)
# include <editline/readline.h>
# endif
static struct cmdline_context *_cmdline;
/* List matching commands */
static char *_list_cmds(const char *text, int state)
{
static int i = 0;
static size_t len = 0;
/* Initialise if this is a new completion attempt */
if (!state) {
i = 0;
len = strlen(text);
}
for (;i < _cmdline->num_command_names;++i)
if (!strncmp(text, _cmdline->command_names[i].name, len))
/* increase position for next iteration */
return strdup(_cmdline->command_names[i++].name);
return NULL;
}
/* List matching arguments */
static char *_list_args(const char *text, int state)
{
static int match_no = 0;
static size_t len = 0;
static const struct command_name *cname;
static const struct command_name_args *cna;
/* Initialise if this is a new completion attempt */
if (!state) {
char *s = rl_line_buffer;
int j;
match_no = 0;
cname = NULL;
cna = NULL;
len = strlen(text);
/* Find start of first word in line buffer */
while (isspace(*s))
s++;
/* Look for word in list of command names */
for (j = 0; j < _cmdline->num_command_names; j++) {
const char *p;
char *q = s;
p = _cmdline->command_names[j].name;
while (*p == *q) {
p++;
q++;
}
if ((!*p) && *q == ' ') {
cname = _cmdline->command_names + j;
cna = _cmdline->command_names_args + j;
break;
}
}
}
if (!cname)
return NULL;
/* Short form arguments */
if (len < 3) {
while (match_no < cna->num_args) {
char s[3];
/* increase position for next iteration */
char c = _cmdline->opt_names[cna->valid_args[match_no++]].short_opt;
if (c) {
sprintf(s, "-%c", c);
if (!strncmp(text, s, len))
return strdup(s);
}
}
}
/* Long form arguments */
if (match_no < cna->num_args)
match_no = cna->num_args;
while ((match_no - cna->num_args) < cna->num_args) {
/* increase position for next iteration */
const char *l = _cmdline->opt_names[cna->valid_args[match_no++ - cna->num_args]].long_opt;
if (*(l + 2) && !strncmp(text, l, len))
return strdup(l);
}
return NULL;
}
/* Custom completion function */
static char **_completion(const char *text, int start_pos,
int end_pos __attribute__((unused)))
{
char **match_list = NULL;
int p = 0;
while (isspace((int) *(rl_line_buffer + p)))
p++;
/* First word should be one of our commands */
if (start_pos == p)
match_list = rl_completion_matches(text, _list_cmds);
else if (*text == '-')
match_list = rl_completion_matches(text, _list_args);
/* else other args */
/* No further completion */
rl_attempted_completion_over = 1;
return match_list;
}
static int _hist_file(char *buffer, size_t size)
{
char *e = getenv("HOME");
if (dm_snprintf(buffer, size, "%s%s.lvm_history", e ? :"", e ? "/" : "") < 0) {
log_error("$HOME/.lvm_history: path too long");
return 0;
}
return 1;
}
static void _read_history(struct cmd_context *cmd)
{
char hist_file[PATH_MAX];
if (!_hist_file(hist_file, sizeof(hist_file)))
return;
if (read_history(hist_file))
log_very_verbose("Couldn't read history from %s.", hist_file);
stifle_history(find_config_tree_int(cmd, shell_history_size_CFG, NULL));
}
static void _write_history(void)
{
char hist_file[PATH_MAX];
if (!_hist_file(hist_file, sizeof(hist_file)))
return;
if (write_history(hist_file))
log_very_verbose("Couldn't write history to %s.", hist_file);
}
static int _log_shell_command_status(struct cmd_context *cmd, int ret_code)
{
log_report_t log_state;
if (!cmd->cmd_report.log_rh)
return 1;
log_state = log_get_report_state();
return report_cmdlog(cmd->cmd_report.log_rh, REPORT_OBJECT_CMDLOG_NAME,
log_get_report_context_name(log_state.context),
log_get_report_object_type_name(log_state.object_type),
log_state.object_name, log_state.object_id,
log_state.object_group, log_state.object_group_id,
ret_code == ECMD_PROCESSED ? REPORT_OBJECT_CMDLOG_SUCCESS
: REPORT_OBJECT_CMDLOG_FAILURE,
stored_errno(), ret_code);
}
static void _discard_log_report_content(struct cmd_context *cmd)
{
if (cmd->cmd_report.log_rh)
dm_report_destroy_rows(cmd->cmd_report.log_rh);
}
int lvm_shell(struct cmd_context *cmd, struct cmdline_context *cmdline)
{
log_report_t saved_log_report_state = log_get_report_state();
char *orig_command_log_selection = NULL;
int is_lastlog_cmd = 0, argc, ret, i;
char *input = NULL, *args[MAX_ARGS], **argv;
rl_readline_name = "lvm";
rl_attempted_completion_function = (rl_completion_func_t *) _completion;
_read_history(cmd);
_cmdline = cmdline;
cmd->is_interactive = 1;
if (!report_format_init(cmd))
return_ECMD_FAILED;
orig_command_log_selection = dm_pool_strdup(cmd->libmem, find_config_tree_str(cmd, log_command_log_selection_CFG, NULL));
log_set_report_context(LOG_REPORT_CONTEXT_SHELL);
log_set_report_object_type(LOG_REPORT_OBJECT_TYPE_PRE_CMD);
while (1) {
/*
* Note: If we need to output the log report before we get to the dm_report_group_output_and_pop_all
* at the end of this loop, like hitting a failure situation before we execute the command itself,
* don't forget to directly call dm_report_group_output_and_pop_all, otherwise no log message will
* appear on output (for output formats other than 'basic').
*
* Obviously, you can't output the 'log report' if the error is in initializing or setting
* the report itself. In this case, we can only return an error code, but no message.
*/
report_reset_cmdlog_seqnum();
if (cmd->cmd_report.log_rh) {
/*
* If previous command was lastlog, reset log report selection to
* its original value as set by log/command_log_selection config setting.
*/
if (is_lastlog_cmd &&
!dm_report_set_selection(cmd->cmd_report.log_rh, orig_command_log_selection))
log_error("Failed to reset log report selection.");
}
log_set_report_object_type(LOG_REPORT_OBJECT_TYPE_PRE_CMD);
log_set_report(cmd->cmd_report.log_rh);
log_set_report_object_name_and_id(NULL, NULL);
free(input);
input = readline("lvm> ");
/* EOF */
if (!input) {
_discard_log_report_content(cmd);
/* readline sends prompt to stdout */
printf("\n");
break;
}
/* empty line */
if (!*input) {
_discard_log_report_content(cmd);
continue;
}
log_set_report_object_name_and_id(input, NULL);
add_history(input);
for (i = 0; i < MAX_ARGS; i++)
args[i] = NULL;
argv = args;
if (lvm_split(input, &argc, argv, MAX_ARGS) == MAX_ARGS) {
_discard_log_report_content(cmd);
log_error("Too many arguments, sorry.");
goto report_log;
}
if (!argc) {
_discard_log_report_content(cmd);
continue;
}
if (!strcmp(argv[0], "lvm")) {
argv++;
argc--;
}
if (!argc) {
_discard_log_report_content(cmd);
continue;
}
log_set_report_object_type(LOG_REPORT_OBJECT_TYPE_CMD);
log_set_report_object_name_and_id(argv[0], NULL);
is_lastlog_cmd = !strcmp(argv[0], "lastlog");
if (!is_lastlog_cmd)
_discard_log_report_content(cmd);
if (!strcmp(argv[0], "quit") || !strcmp(argv[0], "exit")) {
_discard_log_report_content(cmd);
remove_history(history_length - 1);
log_error("Exiting.");
break;
}
ret = lvm_run_command(cmd, argc, argv);
if (ret == ENO_SUCH_CMD)
log_error("No such command '%s'. Try 'help'.",
argv[0]);
if ((ret != ECMD_PROCESSED) && !error_message_produced()) {
log_debug(INTERNAL_ERROR "Failed command did not use log_error");
log_error("Command failed with status code %d.", ret);
}
_write_history();
if (!is_lastlog_cmd)
_log_shell_command_status(cmd, ret);
report_log:
log_set_report(NULL);
dm_report_group_output_and_pop_all(cmd->cmd_report.report_group);
if (cmd->cmd_report.log_rh &&
!(dm_report_group_push(cmd->cmd_report.report_group,
cmd->cmd_report.log_rh,
(void *) cmd->cmd_report.log_name))) {
log_set_report(NULL);
log_error("Failed to add log report.");
break;
}
}
log_restore_report_state(saved_log_report_state);
cmd->is_interactive = 0;
free(input);
if (cmd->cmd_report.report_group) {
if (!dm_report_group_destroy(cmd->cmd_report.report_group))
stack;
cmd->cmd_report.report_group = NULL;
}
if (cmd->cmd_report.log_rh) {
dm_report_free(cmd->cmd_report.log_rh);
cmd->cmd_report.report_group = NULL;
}
return 0;
}
#endif /* READLINE_SUPPORT || EDITLINE_SUPPORT */