Sync usage with man page.
[netbsd-mini2440.git] / external / gpl2 / lvm2 / dist / tools / lvm.c
blobc007a1df4c48139688ba9c80342d8eedcb4568b9
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
9 * This copyrighted material is made available to anyone wishing to use,
10 * modify, copy, or redistribute it subject to the terms and conditions
11 * of the GNU General Public License v.2.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #include "tools.h"
19 #include "lvm2cmdline.h"
21 int main(int argc, char **argv)
23 return lvm2_main(argc, argv);
26 #ifdef READLINE_SUPPORT
28 # include <readline/readline.h>
29 # include <readline/history.h>
30 # ifndef HAVE_RL_COMPLETION_MATCHES
31 # define rl_completion_matches(a, b) completion_matches((char *)a, b)
32 # endif
34 static struct cmdline_context *_cmdline;
36 /* List matching commands */
37 static char *_list_cmds(const char *text, int state)
39 static int i = 0;
40 static size_t len = 0;
42 /* Initialise if this is a new completion attempt */
43 if (!state) {
44 i = 0;
45 len = strlen(text);
48 while (i < _cmdline->num_commands)
49 if (!strncmp(text, _cmdline->commands[i++].name, len))
50 return strdup(_cmdline->commands[i - 1].name);
52 return NULL;
55 /* List matching arguments */
56 static char *_list_args(const char *text, int state)
58 static int match_no = 0;
59 static size_t len = 0;
60 static struct command *com;
62 /* Initialise if this is a new completion attempt */
63 if (!state) {
64 char *s = rl_line_buffer;
65 int j = 0;
67 match_no = 0;
68 com = NULL;
69 len = strlen(text);
71 /* Find start of first word in line buffer */
72 while (isspace(*s))
73 s++;
75 /* Look for word in list of commands */
76 for (j = 0; j < _cmdline->num_commands; j++) {
77 const char *p;
78 char *q = s;
80 p = _cmdline->commands[j].name;
81 while (*p == *q) {
82 p++;
83 q++;
85 if ((!*p) && *q == ' ') {
86 com = _cmdline->commands + j;
87 break;
91 if (!com)
92 return NULL;
95 /* Short form arguments */
96 if (len < 3) {
97 while (match_no < com->num_args) {
98 char s[3];
99 char c;
100 if (!(c = (_cmdline->the_args +
101 com->valid_args[match_no++])->short_arg))
102 continue;
104 sprintf(s, "-%c", c);
105 if (!strncmp(text, s, len))
106 return strdup(s);
110 /* Long form arguments */
111 if (match_no < com->num_args)
112 match_no = com->num_args;
114 while (match_no - com->num_args < com->num_args) {
115 const char *l;
116 l = (_cmdline->the_args +
117 com->valid_args[match_no++ - com->num_args])->long_arg;
118 if (*(l + 2) && !strncmp(text, l, len))
119 return strdup(l);
122 return NULL;
125 /* Custom completion function */
126 static char **_completion(const char *text, int start_pos,
127 int end_pos __attribute((unused)))
129 char **match_list = NULL;
130 int p = 0;
132 while (isspace((int) *(rl_line_buffer + p)))
133 p++;
135 /* First word should be one of our commands */
136 if (start_pos == p)
137 match_list = rl_completion_matches(text, _list_cmds);
139 else if (*text == '-')
140 match_list = rl_completion_matches(text, _list_args);
141 /* else other args */
143 /* No further completion */
144 rl_attempted_completion_over = 1;
145 return match_list;
148 static int _hist_file(char *buffer, size_t size)
150 char *e = getenv("HOME");
152 if (dm_snprintf(buffer, size, "%s/.lvm_history", e) < 0) {
153 log_error("$HOME/.lvm_history: path too long");
154 return 0;
157 return 1;
160 static void _read_history(struct cmd_context *cmd)
162 char hist_file[PATH_MAX];
164 if (!_hist_file(hist_file, sizeof(hist_file)))
165 return;
167 if (read_history(hist_file))
168 log_very_verbose("Couldn't read history from %s.", hist_file);
170 stifle_history(find_config_tree_int(cmd, "shell/history_size",
171 DEFAULT_MAX_HISTORY));
175 static void _write_history(void)
177 char hist_file[PATH_MAX];
179 if (!_hist_file(hist_file, sizeof(hist_file)))
180 return;
182 if (write_history(hist_file))
183 log_very_verbose("Couldn't write history to %s.", hist_file);
186 int lvm_shell(struct cmd_context *cmd, struct cmdline_context *cmdline)
188 int argc, ret;
189 char *input = NULL, *args[MAX_ARGS], **argv;
191 rl_readline_name = "lvm";
192 rl_attempted_completion_function = (CPPFunction *) _completion;
194 _read_history(cmd);
196 _cmdline = cmdline;
198 _cmdline->interactive = 1;
199 while (1) {
200 free(input);
201 input = readline("lvm> ");
203 /* EOF */
204 if (!input) {
205 printf("\n");
206 break;
209 /* empty line */
210 if (!*input)
211 continue;
213 add_history(input);
215 argv = args;
217 if (lvm_split(input, &argc, argv, MAX_ARGS) == MAX_ARGS) {
218 log_error("Too many arguments, sorry.");
219 continue;
222 if (!strcmp(argv[0], "lvm")) {
223 argv++;
224 argc--;
227 if (!argc)
228 continue;
230 if (!strcmp(argv[0], "quit") || !strcmp(argv[0], "exit")) {
231 remove_history(history_length - 1);
232 log_error("Exiting.");
233 break;
236 ret = lvm_run_command(cmd, argc, argv);
237 if (ret == ENO_SUCH_CMD)
238 log_error("No such command '%s'. Try 'help'.",
239 argv[0]);
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);
245 _write_history();
248 free(input);
249 return 0;
252 #endif /* READLINE_SUPPORT */