]> sourceware.org Git - lvm2.git/blame - tools/lvm.c
thin: tighten discard string conversions
[lvm2.git] / tools / lvm.c
CommitLineData
269930c0 1/*
67cdbd7e 2 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
be684599 3 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
269930c0 4 *
6606c3ae
AK
5 * This file is part of LVM2.
6 *
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.
10 *
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
269930c0
AK
14 */
15
f359c9b8 16#include "tools.h"
7fa2d1a0 17#include "lvm2cmdline.h"
5a52dca9
AK
18
19int main(int argc, char **argv)
20{
02961979 21 return lvm2_main(argc, argv);
5a52dca9 22}
f359c9b8
AK
23
24#ifdef READLINE_SUPPORT
25
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)
30# endif
31
32static struct cmdline_context *_cmdline;
33
34/* List matching commands */
35static char *_list_cmds(const char *text, int state)
36{
37 static int i = 0;
38 static size_t len = 0;
39
40 /* Initialise if this is a new completion attempt */
41 if (!state) {
42 i = 0;
43 len = strlen(text);
44 }
45
46 while (i < _cmdline->num_commands)
47 if (!strncmp(text, _cmdline->commands[i++].name, len))
48 return strdup(_cmdline->commands[i - 1].name);
49
50 return NULL;
51}
52
53/* List matching arguments */
54static char *_list_args(const char *text, int state)
55{
56 static int match_no = 0;
57 static size_t len = 0;
58 static struct command *com;
59
60 /* Initialise if this is a new completion attempt */
61 if (!state) {
62 char *s = rl_line_buffer;
a6292f2a 63 int j;
f359c9b8
AK
64
65 match_no = 0;
66 com = NULL;
67 len = strlen(text);
68
69 /* Find start of first word in line buffer */
70 while (isspace(*s))
71 s++;
72
73 /* Look for word in list of commands */
74 for (j = 0; j < _cmdline->num_commands; j++) {
75 const char *p;
76 char *q = s;
77
78 p = _cmdline->commands[j].name;
79 while (*p == *q) {
80 p++;
81 q++;
82 }
83 if ((!*p) && *q == ' ') {
84 com = _cmdline->commands + j;
85 break;
86 }
87 }
f359c9b8
AK
88 }
89
30b36dc0
ZK
90 if (!com)
91 return NULL;
92
f359c9b8
AK
93 /* Short form arguments */
94 if (len < 3) {
95 while (match_no < com->num_args) {
96 char s[3];
97 char c;
f8452d8c 98 if (!(c = (_cmdline->arg_props +
f359c9b8
AK
99 com->valid_args[match_no++])->short_arg))
100 continue;
101
102 sprintf(s, "-%c", c);
103 if (!strncmp(text, s, len))
104 return strdup(s);
105 }
106 }
107
108 /* Long form arguments */
109 if (match_no < com->num_args)
110 match_no = com->num_args;
111
112 while (match_no - com->num_args < com->num_args) {
113 const char *l;
f8452d8c 114 l = (_cmdline->arg_props +
f359c9b8
AK
115 com->valid_args[match_no++ - com->num_args])->long_arg;
116 if (*(l + 2) && !strncmp(text, l, len))
117 return strdup(l);
118 }
119
120 return NULL;
121}
122
123/* Custom completion function */
4e9083db 124static char **_completion(const char *text, int start_pos,
08f1ddea 125 int end_pos __attribute__((unused)))
f359c9b8
AK
126{
127 char **match_list = NULL;
128 int p = 0;
129
130 while (isspace((int) *(rl_line_buffer + p)))
131 p++;
132
133 /* First word should be one of our commands */
134 if (start_pos == p)
135 match_list = rl_completion_matches(text, _list_cmds);
136
137 else if (*text == '-')
138 match_list = rl_completion_matches(text, _list_args);
139 /* else other args */
140
141 /* No further completion */
142 rl_attempted_completion_over = 1;
143 return match_list;
144}
145
146static int _hist_file(char *buffer, size_t size)
147{
148 char *e = getenv("HOME");
149
150 if (dm_snprintf(buffer, size, "%s/.lvm_history", e) < 0) {
151 log_error("$HOME/.lvm_history: path too long");
152 return 0;
153 }
154
155 return 1;
156}
157
158static void _read_history(struct cmd_context *cmd)
159{
160 char hist_file[PATH_MAX];
161
162 if (!_hist_file(hist_file, sizeof(hist_file)))
163 return;
164
165 if (read_history(hist_file))
166 log_very_verbose("Couldn't read history from %s.", hist_file);
167
168 stifle_history(find_config_tree_int(cmd, "shell/history_size",
169 DEFAULT_MAX_HISTORY));
f359c9b8
AK
170}
171
172static void _write_history(void)
173{
174 char hist_file[PATH_MAX];
175
176 if (!_hist_file(hist_file, sizeof(hist_file)))
177 return;
178
179 if (write_history(hist_file))
180 log_very_verbose("Couldn't write history to %s.", hist_file);
181}
182
183int lvm_shell(struct cmd_context *cmd, struct cmdline_context *cmdline)
184{
185 int argc, ret;
186 char *input = NULL, *args[MAX_ARGS], **argv;
187
188 rl_readline_name = "lvm";
189 rl_attempted_completion_function = (CPPFunction *) _completion;
190
191 _read_history(cmd);
192
193 _cmdline = cmdline;
194
195 _cmdline->interactive = 1;
196 while (1) {
197 free(input);
198 input = readline("lvm> ");
199
200 /* EOF */
201 if (!input) {
202 printf("\n");
203 break;
204 }
205
206 /* empty line */
207 if (!*input)
208 continue;
209
210 add_history(input);
211
212 argv = args;
213
214 if (lvm_split(input, &argc, argv, MAX_ARGS) == MAX_ARGS) {
215 log_error("Too many arguments, sorry.");
216 continue;
217 }
218
89dd7d52
AK
219 if (!argc)
220 continue;
221
f359c9b8
AK
222 if (!strcmp(argv[0], "lvm")) {
223 argv++;
224 argc--;
225 }
226
227 if (!argc)
228 continue;
229
230 if (!strcmp(argv[0], "quit") || !strcmp(argv[0], "exit")) {
231 remove_history(history_length - 1);
232 log_error("Exiting.");
233 break;
234 }
235
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]);
240
ec40d928 241 if ((ret != ECMD_PROCESSED) && !error_message_produced()) {
550cae23 242 log_debug(INTERNAL_ERROR "Failed command did not use log_error");
ec40d928
AK
243 log_error("Command failed with status code %d.", ret);
244 }
f359c9b8
AK
245 _write_history();
246 }
247
248 free(input);
249 return 0;
250}
251
252#endif /* READLINE_SUPPORT */
This page took 0.119517 seconds and 5 git commands to generate.