2 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
5 * This file is part of LVM2.
7 * This copyrighted material is made available to anyone wishing to use,
8 * modify, copy, or redistribute it subject to the terms and conditions
9 * of the GNU General Public License v.2.
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software Foundation,
13 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 #include "lvm2cmdline.h"
19 int main(int argc
, char **argv
)
21 return lvm2_main(argc
, argv
);
24 #ifdef READLINE_SUPPORT
26 # include <readline/readline.h>
27 # include <readline/history.h>
28 # ifndef HAVE_RL_COMPLETION_MATCHES
29 # define rl_completion_matches(a, b) completion_matches((char *)a, b)
32 static struct cmdline_context
*_cmdline
;
34 /* List matching commands */
35 static char *_list_cmds(const char *text
, int state
)
38 static size_t len
= 0;
40 /* Initialise if this is a new completion attempt */
46 while (i
< _cmdline
->num_commands
)
47 if (!strncmp(text
, _cmdline
->commands
[i
++].name
, len
))
48 return strdup(_cmdline
->commands
[i
- 1].name
);
53 /* List matching arguments */
54 static char *_list_args(const char *text
, int state
)
56 static int match_no
= 0;
57 static size_t len
= 0;
58 static struct command
*com
;
60 /* Initialise if this is a new completion attempt */
62 char *s
= rl_line_buffer
;
69 /* Find start of first word in line buffer */
73 /* Look for word in list of commands */
74 for (j
= 0; j
< _cmdline
->num_commands
; j
++) {
78 p
= _cmdline
->commands
[j
].name
;
83 if ((!*p
) && *q
== ' ') {
84 com
= _cmdline
->commands
+ j
;
93 /* Short form arguments */
95 while (match_no
< com
->num_args
) {
98 if (!(c
= (_cmdline
->arg_props
+
99 com
->valid_args
[match_no
++])->short_arg
))
102 sprintf(s
, "-%c", c
);
103 if (!strncmp(text
, s
, len
))
108 /* Long form arguments */
109 if (match_no
< com
->num_args
)
110 match_no
= com
->num_args
;
112 while (match_no
- com
->num_args
< com
->num_args
) {
114 l
= (_cmdline
->arg_props
+
115 com
->valid_args
[match_no
++ - com
->num_args
])->long_arg
;
116 if (*(l
+ 2) && !strncmp(text
, l
, len
))
123 /* Custom completion function */
124 static char **_completion(const char *text
, int start_pos
,
125 int end_pos
__attribute__((unused
)))
127 char **match_list
= NULL
;
130 while (isspace((int) *(rl_line_buffer
+ p
)))
133 /* First word should be one of our commands */
135 match_list
= rl_completion_matches(text
, _list_cmds
);
137 else if (*text
== '-')
138 match_list
= rl_completion_matches(text
, _list_args
);
139 /* else other args */
141 /* No further completion */
142 rl_attempted_completion_over
= 1;
146 static int _hist_file(char *buffer
, size_t size
)
148 char *e
= getenv("HOME");
150 if (dm_snprintf(buffer
, size
, "%s/.lvm_history", e
) < 0) {
151 log_error("$HOME/.lvm_history: path too long");
158 static void _read_history(struct cmd_context
*cmd
)
160 char hist_file
[PATH_MAX
];
162 if (!_hist_file(hist_file
, sizeof(hist_file
)))
165 if (read_history(hist_file
))
166 log_very_verbose("Couldn't read history from %s.", hist_file
);
168 stifle_history(find_config_tree_int(cmd
, "shell/history_size",
169 DEFAULT_MAX_HISTORY
));
172 static void _write_history(void)
174 char hist_file
[PATH_MAX
];
176 if (!_hist_file(hist_file
, sizeof(hist_file
)))
179 if (write_history(hist_file
))
180 log_very_verbose("Couldn't write history to %s.", hist_file
);
183 int lvm_shell(struct cmd_context
*cmd
, struct cmdline_context
*cmdline
)
186 char *input
= NULL
, *args
[MAX_ARGS
], **argv
;
188 rl_readline_name
= "lvm";
189 rl_attempted_completion_function
= (CPPFunction
*) _completion
;
195 _cmdline
->interactive
= 1;
198 input
= readline("lvm> ");
214 if (lvm_split(input
, &argc
, argv
, MAX_ARGS
) == MAX_ARGS
) {
215 log_error("Too many arguments, sorry.");
222 if (!strcmp(argv
[0], "lvm")) {
230 if (!strcmp(argv
[0], "quit") || !strcmp(argv
[0], "exit")) {
231 remove_history(history_length
- 1);
232 log_error("Exiting.");
236 ret
= lvm_run_command(cmd
, argc
, argv
);
237 if (ret
== ENO_SUCH_CMD
)
238 log_error("No such command '%s'. Try 'help'.",
241 if ((ret
!= ECMD_PROCESSED
) && !error_message_produced()) {
242 log_debug(INTERNAL_ERROR
"Failed command did not use log_error");
243 log_error("Command failed with status code %d.", ret
);
252 #endif /* READLINE_SUPPORT */