root / cmd.c @ fb5590f7
History | View | Annotate | Download (12.2 kB)
1 | e3aff4f6 | aliguori | /*
|
---|---|---|---|
2 | e3aff4f6 | aliguori | * Copyright (c) 2003-2005 Silicon Graphics, Inc.
|
3 | e3aff4f6 | aliguori | * All Rights Reserved.
|
4 | e3aff4f6 | aliguori | *
|
5 | e3aff4f6 | aliguori | * This program is free software; you can redistribute it and/or
|
6 | e3aff4f6 | aliguori | * modify it under the terms of the GNU General Public License as
|
7 | e3aff4f6 | aliguori | * published by the Free Software Foundation.
|
8 | e3aff4f6 | aliguori | *
|
9 | e3aff4f6 | aliguori | * This program is distributed in the hope that it would be useful,
|
10 | e3aff4f6 | aliguori | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11 | e3aff4f6 | aliguori | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12 | e3aff4f6 | aliguori | * GNU General Public License for more details.
|
13 | e3aff4f6 | aliguori | *
|
14 | e3aff4f6 | aliguori | * You should have received a copy of the GNU General Public License
|
15 | 8167ee88 | Blue Swirl | * along with this program; if not, see <http://www.gnu.org/licenses/>.
|
16 | e3aff4f6 | aliguori | */
|
17 | e3aff4f6 | aliguori | |
18 | e3aff4f6 | aliguori | #include <stdio.h> |
19 | e3aff4f6 | aliguori | #include <stdlib.h> |
20 | e3aff4f6 | aliguori | #include <string.h> |
21 | e3aff4f6 | aliguori | #include <ctype.h> |
22 | e3aff4f6 | aliguori | #include <errno.h> |
23 | c32d766a | Stefan Weil | #include <sys/time.h> |
24 | 22a2bdcb | Blue Swirl | #include <getopt.h> |
25 | e3aff4f6 | aliguori | |
26 | e3aff4f6 | aliguori | #include "cmd.h" |
27 | 7d7d975c | MORITA Kazutaka | #include "qemu-aio.h" |
28 | e3aff4f6 | aliguori | |
29 | e3aff4f6 | aliguori | #define _(x) x /* not gettext support yet */ |
30 | e3aff4f6 | aliguori | |
31 | e3aff4f6 | aliguori | /* from libxcmd/command.c */
|
32 | e3aff4f6 | aliguori | |
33 | e3aff4f6 | aliguori | cmdinfo_t *cmdtab; |
34 | e3aff4f6 | aliguori | int ncmds;
|
35 | e3aff4f6 | aliguori | |
36 | e3aff4f6 | aliguori | static argsfunc_t args_func;
|
37 | e3aff4f6 | aliguori | static checkfunc_t check_func;
|
38 | e3aff4f6 | aliguori | static int ncmdline; |
39 | e3aff4f6 | aliguori | static char **cmdline; |
40 | e3aff4f6 | aliguori | |
41 | e3aff4f6 | aliguori | static int |
42 | e3aff4f6 | aliguori | compare(const void *a, const void *b) |
43 | e3aff4f6 | aliguori | { |
44 | e3aff4f6 | aliguori | return strcmp(((const cmdinfo_t *)a)->name, |
45 | e3aff4f6 | aliguori | ((const cmdinfo_t *)b)->name);
|
46 | e3aff4f6 | aliguori | } |
47 | e3aff4f6 | aliguori | |
48 | 81beeec4 | Pavel Borzenkov | void add_command(const cmdinfo_t *ci) |
49 | e3aff4f6 | aliguori | { |
50 | ba7806ad | Pavel Borzenkov | cmdtab = g_realloc((void *)cmdtab, ++ncmds * sizeof(*cmdtab)); |
51 | 81beeec4 | Pavel Borzenkov | cmdtab[ncmds - 1] = *ci;
|
52 | 81beeec4 | Pavel Borzenkov | qsort(cmdtab, ncmds, sizeof(*cmdtab), compare);
|
53 | e3aff4f6 | aliguori | } |
54 | e3aff4f6 | aliguori | |
55 | e3aff4f6 | aliguori | static int |
56 | e3aff4f6 | aliguori | check_command( |
57 | e3aff4f6 | aliguori | const cmdinfo_t *ci)
|
58 | e3aff4f6 | aliguori | { |
59 | e3aff4f6 | aliguori | if (check_func)
|
60 | e3aff4f6 | aliguori | return check_func(ci);
|
61 | e3aff4f6 | aliguori | return 1; |
62 | e3aff4f6 | aliguori | } |
63 | e3aff4f6 | aliguori | |
64 | e3aff4f6 | aliguori | void
|
65 | e3aff4f6 | aliguori | add_check_command( |
66 | e3aff4f6 | aliguori | checkfunc_t cf) |
67 | e3aff4f6 | aliguori | { |
68 | e3aff4f6 | aliguori | check_func = cf; |
69 | e3aff4f6 | aliguori | } |
70 | e3aff4f6 | aliguori | |
71 | e3aff4f6 | aliguori | int
|
72 | e3aff4f6 | aliguori | command_usage( |
73 | e3aff4f6 | aliguori | const cmdinfo_t *ci)
|
74 | e3aff4f6 | aliguori | { |
75 | e3aff4f6 | aliguori | printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
|
76 | e3aff4f6 | aliguori | return 0; |
77 | e3aff4f6 | aliguori | } |
78 | e3aff4f6 | aliguori | |
79 | e3aff4f6 | aliguori | int
|
80 | e3aff4f6 | aliguori | command( |
81 | e3aff4f6 | aliguori | const cmdinfo_t *ct,
|
82 | e3aff4f6 | aliguori | int argc,
|
83 | e3aff4f6 | aliguori | char **argv)
|
84 | e3aff4f6 | aliguori | { |
85 | e3aff4f6 | aliguori | char *cmd = argv[0]; |
86 | e3aff4f6 | aliguori | |
87 | e3aff4f6 | aliguori | if (!check_command(ct))
|
88 | e3aff4f6 | aliguori | return 0; |
89 | e3aff4f6 | aliguori | |
90 | e3aff4f6 | aliguori | if (argc-1 < ct->argmin || (ct->argmax != -1 && argc-1 > ct->argmax)) { |
91 | e3aff4f6 | aliguori | if (ct->argmax == -1) |
92 | e3aff4f6 | aliguori | fprintf(stderr, |
93 | e3aff4f6 | aliguori | _("bad argument count %d to %s, expected at least %d arguments\n"),
|
94 | e3aff4f6 | aliguori | argc-1, cmd, ct->argmin);
|
95 | e3aff4f6 | aliguori | else if (ct->argmin == ct->argmax) |
96 | e3aff4f6 | aliguori | fprintf(stderr, |
97 | e3aff4f6 | aliguori | _("bad argument count %d to %s, expected %d arguments\n"),
|
98 | e3aff4f6 | aliguori | argc-1, cmd, ct->argmin);
|
99 | e3aff4f6 | aliguori | else
|
100 | e3aff4f6 | aliguori | fprintf(stderr, |
101 | e3aff4f6 | aliguori | _("bad argument count %d to %s, expected between %d and %d arguments\n"),
|
102 | e3aff4f6 | aliguori | argc-1, cmd, ct->argmin, ct->argmax);
|
103 | e3aff4f6 | aliguori | return 0; |
104 | e3aff4f6 | aliguori | } |
105 | e3aff4f6 | aliguori | optind = 0;
|
106 | e3aff4f6 | aliguori | return ct->cfunc(argc, argv);
|
107 | e3aff4f6 | aliguori | } |
108 | e3aff4f6 | aliguori | |
109 | e3aff4f6 | aliguori | const cmdinfo_t *
|
110 | e3aff4f6 | aliguori | find_command( |
111 | e3aff4f6 | aliguori | const char *cmd) |
112 | e3aff4f6 | aliguori | { |
113 | e3aff4f6 | aliguori | cmdinfo_t *ct; |
114 | e3aff4f6 | aliguori | |
115 | e3aff4f6 | aliguori | for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
|
116 | e3aff4f6 | aliguori | if (strcmp(ct->name, cmd) == 0 || |
117 | e3aff4f6 | aliguori | (ct->altname && strcmp(ct->altname, cmd) == 0))
|
118 | e3aff4f6 | aliguori | return (const cmdinfo_t *)ct; |
119 | e3aff4f6 | aliguori | } |
120 | e3aff4f6 | aliguori | return NULL; |
121 | e3aff4f6 | aliguori | } |
122 | e3aff4f6 | aliguori | |
123 | 81beeec4 | Pavel Borzenkov | void add_user_command(char *optarg) |
124 | e3aff4f6 | aliguori | { |
125 | ba7806ad | Pavel Borzenkov | cmdline = g_realloc(cmdline, ++ncmdline * sizeof(char *)); |
126 | 81beeec4 | Pavel Borzenkov | cmdline[ncmdline-1] = optarg;
|
127 | e3aff4f6 | aliguori | } |
128 | e3aff4f6 | aliguori | |
129 | e3aff4f6 | aliguori | static int |
130 | e3aff4f6 | aliguori | args_command( |
131 | e3aff4f6 | aliguori | int index)
|
132 | e3aff4f6 | aliguori | { |
133 | e3aff4f6 | aliguori | if (args_func)
|
134 | e3aff4f6 | aliguori | return args_func(index);
|
135 | e3aff4f6 | aliguori | return 0; |
136 | e3aff4f6 | aliguori | } |
137 | e3aff4f6 | aliguori | |
138 | e3aff4f6 | aliguori | void
|
139 | e3aff4f6 | aliguori | add_args_command( |
140 | e3aff4f6 | aliguori | argsfunc_t af) |
141 | e3aff4f6 | aliguori | { |
142 | e3aff4f6 | aliguori | args_func = af; |
143 | e3aff4f6 | aliguori | } |
144 | e3aff4f6 | aliguori | |
145 | 7d7d975c | MORITA Kazutaka | static void prep_fetchline(void *opaque) |
146 | 7d7d975c | MORITA Kazutaka | { |
147 | 7d7d975c | MORITA Kazutaka | int *fetchable = opaque;
|
148 | 7d7d975c | MORITA Kazutaka | |
149 | 7d7d975c | MORITA Kazutaka | qemu_aio_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL, NULL, NULL); |
150 | 7d7d975c | MORITA Kazutaka | *fetchable= 1;
|
151 | 7d7d975c | MORITA Kazutaka | } |
152 | 7d7d975c | MORITA Kazutaka | |
153 | 7d7d975c | MORITA Kazutaka | static char *get_prompt(void); |
154 | 7d7d975c | MORITA Kazutaka | |
155 | 81beeec4 | Pavel Borzenkov | void command_loop(void) |
156 | e3aff4f6 | aliguori | { |
157 | 81beeec4 | Pavel Borzenkov | int c, i, j = 0, done = 0, fetchable = 0, prompted = 0; |
158 | 81beeec4 | Pavel Borzenkov | char *input;
|
159 | 81beeec4 | Pavel Borzenkov | char **v;
|
160 | 81beeec4 | Pavel Borzenkov | const cmdinfo_t *ct;
|
161 | 81beeec4 | Pavel Borzenkov | |
162 | 81beeec4 | Pavel Borzenkov | for (i = 0; !done && i < ncmdline; i++) { |
163 | 81beeec4 | Pavel Borzenkov | input = strdup(cmdline[i]); |
164 | 81beeec4 | Pavel Borzenkov | if (!input) {
|
165 | 81beeec4 | Pavel Borzenkov | fprintf(stderr, _("cannot strdup command '%s': %s\n"),
|
166 | 81beeec4 | Pavel Borzenkov | cmdline[i], strerror(errno)); |
167 | 81beeec4 | Pavel Borzenkov | exit(1);
|
168 | 81beeec4 | Pavel Borzenkov | } |
169 | 81beeec4 | Pavel Borzenkov | v = breakline(input, &c); |
170 | 81beeec4 | Pavel Borzenkov | if (c) {
|
171 | 81beeec4 | Pavel Borzenkov | ct = find_command(v[0]);
|
172 | 81beeec4 | Pavel Borzenkov | if (ct) {
|
173 | 81beeec4 | Pavel Borzenkov | if (ct->flags & CMD_FLAG_GLOBAL) {
|
174 | 81beeec4 | Pavel Borzenkov | done = command(ct, c, v); |
175 | 81beeec4 | Pavel Borzenkov | } else {
|
176 | 81beeec4 | Pavel Borzenkov | j = 0;
|
177 | 81beeec4 | Pavel Borzenkov | while (!done && (j = args_command(j))) {
|
178 | 81beeec4 | Pavel Borzenkov | done = command(ct, c, v); |
179 | 81beeec4 | Pavel Borzenkov | } |
180 | 81beeec4 | Pavel Borzenkov | } |
181 | 81beeec4 | Pavel Borzenkov | } else {
|
182 | 81beeec4 | Pavel Borzenkov | fprintf(stderr, _("command \"%s\" not found\n"), v[0]); |
183 | 81beeec4 | Pavel Borzenkov | } |
184 | e3aff4f6 | aliguori | } |
185 | 81beeec4 | Pavel Borzenkov | doneline(input, v); |
186 | 81beeec4 | Pavel Borzenkov | } |
187 | 81beeec4 | Pavel Borzenkov | if (cmdline) {
|
188 | ba7806ad | Pavel Borzenkov | g_free(cmdline); |
189 | 81beeec4 | Pavel Borzenkov | return;
|
190 | 81beeec4 | Pavel Borzenkov | } |
191 | 7d7d975c | MORITA Kazutaka | |
192 | 81beeec4 | Pavel Borzenkov | while (!done) {
|
193 | 7d7d975c | MORITA Kazutaka | if (!prompted) {
|
194 | 7d7d975c | MORITA Kazutaka | printf("%s", get_prompt());
|
195 | 7d7d975c | MORITA Kazutaka | fflush(stdout); |
196 | 7d7d975c | MORITA Kazutaka | qemu_aio_set_fd_handler(STDIN_FILENO, prep_fetchline, NULL, NULL, |
197 | 7d7d975c | MORITA Kazutaka | NULL, &fetchable);
|
198 | 7d7d975c | MORITA Kazutaka | prompted = 1;
|
199 | 7d7d975c | MORITA Kazutaka | } |
200 | 7d7d975c | MORITA Kazutaka | |
201 | 7d7d975c | MORITA Kazutaka | qemu_aio_wait(); |
202 | 7d7d975c | MORITA Kazutaka | |
203 | 7d7d975c | MORITA Kazutaka | if (!fetchable) {
|
204 | 7d7d975c | MORITA Kazutaka | continue;
|
205 | 7d7d975c | MORITA Kazutaka | } |
206 | 81beeec4 | Pavel Borzenkov | input = fetchline(); |
207 | 81beeec4 | Pavel Borzenkov | if (input == NULL) { |
208 | 81beeec4 | Pavel Borzenkov | break;
|
209 | 81beeec4 | Pavel Borzenkov | } |
210 | 81beeec4 | Pavel Borzenkov | v = breakline(input, &c); |
211 | 81beeec4 | Pavel Borzenkov | if (c) {
|
212 | 81beeec4 | Pavel Borzenkov | ct = find_command(v[0]);
|
213 | 81beeec4 | Pavel Borzenkov | if (ct) {
|
214 | 81beeec4 | Pavel Borzenkov | done = command(ct, c, v); |
215 | 81beeec4 | Pavel Borzenkov | } else {
|
216 | 81beeec4 | Pavel Borzenkov | fprintf(stderr, _("command \"%s\" not found\n"), v[0]); |
217 | 81beeec4 | Pavel Borzenkov | } |
218 | 81beeec4 | Pavel Borzenkov | } |
219 | 81beeec4 | Pavel Borzenkov | doneline(input, v); |
220 | 7d7d975c | MORITA Kazutaka | |
221 | 7d7d975c | MORITA Kazutaka | prompted = 0;
|
222 | 7d7d975c | MORITA Kazutaka | fetchable = 0;
|
223 | 81beeec4 | Pavel Borzenkov | } |
224 | 7d7d975c | MORITA Kazutaka | qemu_aio_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL, NULL, NULL); |
225 | e3aff4f6 | aliguori | } |
226 | e3aff4f6 | aliguori | |
227 | e3aff4f6 | aliguori | /* from libxcmd/input.c */
|
228 | e3aff4f6 | aliguori | |
229 | e3aff4f6 | aliguori | #if defined(ENABLE_READLINE)
|
230 | e3aff4f6 | aliguori | # include <readline/history.h> |
231 | e3aff4f6 | aliguori | # include <readline/readline.h> |
232 | e3aff4f6 | aliguori | #elif defined(ENABLE_EDITLINE)
|
233 | e3aff4f6 | aliguori | # include <histedit.h> |
234 | e3aff4f6 | aliguori | #endif
|
235 | e3aff4f6 | aliguori | |
236 | e3aff4f6 | aliguori | static char * |
237 | e3aff4f6 | aliguori | get_prompt(void)
|
238 | e3aff4f6 | aliguori | { |
239 | e3aff4f6 | aliguori | static char prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ]; |
240 | e3aff4f6 | aliguori | |
241 | e3aff4f6 | aliguori | if (!prompt[0]) |
242 | e3aff4f6 | aliguori | snprintf(prompt, sizeof(prompt), "%s> ", progname); |
243 | e3aff4f6 | aliguori | return prompt;
|
244 | e3aff4f6 | aliguori | } |
245 | e3aff4f6 | aliguori | |
246 | e3aff4f6 | aliguori | #if defined(ENABLE_READLINE)
|
247 | e3aff4f6 | aliguori | char *
|
248 | e3aff4f6 | aliguori | fetchline(void)
|
249 | e3aff4f6 | aliguori | { |
250 | e3aff4f6 | aliguori | char *line;
|
251 | e3aff4f6 | aliguori | |
252 | e3aff4f6 | aliguori | line = readline(get_prompt()); |
253 | e3aff4f6 | aliguori | if (line && *line)
|
254 | e3aff4f6 | aliguori | add_history(line); |
255 | e3aff4f6 | aliguori | return line;
|
256 | e3aff4f6 | aliguori | } |
257 | e3aff4f6 | aliguori | #elif defined(ENABLE_EDITLINE)
|
258 | e3aff4f6 | aliguori | static char *el_get_prompt(EditLine *e) { return get_prompt(); } |
259 | e3aff4f6 | aliguori | char *
|
260 | e3aff4f6 | aliguori | fetchline(void)
|
261 | e3aff4f6 | aliguori | { |
262 | e3aff4f6 | aliguori | static EditLine *el;
|
263 | e3aff4f6 | aliguori | static History *hist;
|
264 | e3aff4f6 | aliguori | HistEvent hevent; |
265 | e3aff4f6 | aliguori | char *line;
|
266 | e3aff4f6 | aliguori | int count;
|
267 | e3aff4f6 | aliguori | |
268 | e3aff4f6 | aliguori | if (!el) {
|
269 | e3aff4f6 | aliguori | hist = history_init(); |
270 | e3aff4f6 | aliguori | history(hist, &hevent, H_SETSIZE, 100);
|
271 | e3aff4f6 | aliguori | el = el_init(progname, stdin, stdout, stderr); |
272 | e3aff4f6 | aliguori | el_source(el, NULL);
|
273 | e3aff4f6 | aliguori | el_set(el, EL_SIGNAL, 1);
|
274 | e3aff4f6 | aliguori | el_set(el, EL_PROMPT, el_get_prompt); |
275 | e3aff4f6 | aliguori | el_set(el, EL_HIST, history, (const char *)hist); |
276 | e3aff4f6 | aliguori | } |
277 | e3aff4f6 | aliguori | line = strdup(el_gets(el, &count)); |
278 | e3aff4f6 | aliguori | if (line) {
|
279 | e3aff4f6 | aliguori | if (count > 0) |
280 | e3aff4f6 | aliguori | line[count-1] = '\0'; |
281 | e3aff4f6 | aliguori | if (*line)
|
282 | e3aff4f6 | aliguori | history(hist, &hevent, H_ENTER, line); |
283 | e3aff4f6 | aliguori | } |
284 | e3aff4f6 | aliguori | return line;
|
285 | e3aff4f6 | aliguori | } |
286 | e3aff4f6 | aliguori | #else
|
287 | e3aff4f6 | aliguori | # define MAXREADLINESZ 1024 |
288 | e3aff4f6 | aliguori | char *
|
289 | e3aff4f6 | aliguori | fetchline(void)
|
290 | e3aff4f6 | aliguori | { |
291 | e3aff4f6 | aliguori | char *p, *line = malloc(MAXREADLINESZ);
|
292 | e3aff4f6 | aliguori | |
293 | e3aff4f6 | aliguori | if (!line)
|
294 | e3aff4f6 | aliguori | return NULL; |
295 | e3aff4f6 | aliguori | if (!fgets(line, MAXREADLINESZ, stdin)) {
|
296 | e3aff4f6 | aliguori | free(line); |
297 | e3aff4f6 | aliguori | return NULL; |
298 | e3aff4f6 | aliguori | } |
299 | e3aff4f6 | aliguori | p = line + strlen(line); |
300 | e3aff4f6 | aliguori | if (p != line && p[-1] == '\n') |
301 | e3aff4f6 | aliguori | p[-1] = '\0'; |
302 | e3aff4f6 | aliguori | return line;
|
303 | e3aff4f6 | aliguori | } |
304 | e3aff4f6 | aliguori | #endif
|
305 | e3aff4f6 | aliguori | |
306 | c32d766a | Stefan Weil | static char *qemu_strsep(char **input, const char *delim) |
307 | c32d766a | Stefan Weil | { |
308 | c32d766a | Stefan Weil | char *result = *input;
|
309 | c32d766a | Stefan Weil | if (result != NULL) { |
310 | 88bf7950 | Blue Swirl | char *p;
|
311 | 88bf7950 | Blue Swirl | |
312 | 50da01ed | Stefan Weil | for (p = result; *p != '\0'; p++) { |
313 | 50da01ed | Stefan Weil | if (strchr(delim, *p)) {
|
314 | c32d766a | Stefan Weil | break;
|
315 | c32d766a | Stefan Weil | } |
316 | c32d766a | Stefan Weil | } |
317 | c32d766a | Stefan Weil | if (*p == '\0') { |
318 | c32d766a | Stefan Weil | *input = NULL;
|
319 | c32d766a | Stefan Weil | } else {
|
320 | c32d766a | Stefan Weil | *p = '\0';
|
321 | c32d766a | Stefan Weil | *input = p + 1;
|
322 | c32d766a | Stefan Weil | } |
323 | c32d766a | Stefan Weil | } |
324 | c32d766a | Stefan Weil | return result;
|
325 | c32d766a | Stefan Weil | } |
326 | c32d766a | Stefan Weil | |
327 | 81beeec4 | Pavel Borzenkov | char **breakline(char *input, int *count) |
328 | e3aff4f6 | aliguori | { |
329 | 81beeec4 | Pavel Borzenkov | int c = 0; |
330 | 81beeec4 | Pavel Borzenkov | char *p;
|
331 | 81beeec4 | Pavel Borzenkov | char **rval = calloc(sizeof(char *), 1); |
332 | 47e8dd8f | Pavel Borzenkov | char **tmp;
|
333 | 81beeec4 | Pavel Borzenkov | |
334 | 81beeec4 | Pavel Borzenkov | while (rval && (p = qemu_strsep(&input, " ")) != NULL) { |
335 | 81beeec4 | Pavel Borzenkov | if (!*p) {
|
336 | 81beeec4 | Pavel Borzenkov | continue;
|
337 | 81beeec4 | Pavel Borzenkov | } |
338 | 81beeec4 | Pavel Borzenkov | c++; |
339 | 47e8dd8f | Pavel Borzenkov | tmp = realloc(rval, sizeof(*rval) * (c + 1)); |
340 | 47e8dd8f | Pavel Borzenkov | if (!tmp) {
|
341 | 47e8dd8f | Pavel Borzenkov | free(rval); |
342 | 47e8dd8f | Pavel Borzenkov | rval = NULL;
|
343 | 81beeec4 | Pavel Borzenkov | c = 0;
|
344 | 81beeec4 | Pavel Borzenkov | break;
|
345 | 47e8dd8f | Pavel Borzenkov | } else {
|
346 | 47e8dd8f | Pavel Borzenkov | rval = tmp; |
347 | 81beeec4 | Pavel Borzenkov | } |
348 | 81beeec4 | Pavel Borzenkov | rval[c - 1] = p;
|
349 | 81beeec4 | Pavel Borzenkov | rval[c] = NULL;
|
350 | 81beeec4 | Pavel Borzenkov | } |
351 | 81beeec4 | Pavel Borzenkov | *count = c; |
352 | 81beeec4 | Pavel Borzenkov | return rval;
|
353 | e3aff4f6 | aliguori | } |
354 | e3aff4f6 | aliguori | |
355 | e3aff4f6 | aliguori | void
|
356 | e3aff4f6 | aliguori | doneline( |
357 | e3aff4f6 | aliguori | char *input,
|
358 | e3aff4f6 | aliguori | char **vec)
|
359 | e3aff4f6 | aliguori | { |
360 | e3aff4f6 | aliguori | free(input); |
361 | e3aff4f6 | aliguori | free(vec); |
362 | e3aff4f6 | aliguori | } |
363 | e3aff4f6 | aliguori | |
364 | e3aff4f6 | aliguori | #define EXABYTES(x) ((long long)(x) << 60) |
365 | e3aff4f6 | aliguori | #define PETABYTES(x) ((long long)(x) << 50) |
366 | e3aff4f6 | aliguori | #define TERABYTES(x) ((long long)(x) << 40) |
367 | e3aff4f6 | aliguori | #define GIGABYTES(x) ((long long)(x) << 30) |
368 | e3aff4f6 | aliguori | #define MEGABYTES(x) ((long long)(x) << 20) |
369 | e3aff4f6 | aliguori | #define KILOBYTES(x) ((long long)(x) << 10) |
370 | e3aff4f6 | aliguori | |
371 | e3aff4f6 | aliguori | long long |
372 | e3aff4f6 | aliguori | cvtnum( |
373 | e3aff4f6 | aliguori | char *s)
|
374 | e3aff4f6 | aliguori | { |
375 | e3aff4f6 | aliguori | long long i; |
376 | e3aff4f6 | aliguori | char *sp;
|
377 | e3aff4f6 | aliguori | int c;
|
378 | e3aff4f6 | aliguori | |
379 | e3aff4f6 | aliguori | i = strtoll(s, &sp, 0);
|
380 | e3aff4f6 | aliguori | if (i == 0 && sp == s) |
381 | e3aff4f6 | aliguori | return -1LL; |
382 | e3aff4f6 | aliguori | if (*sp == '\0') |
383 | e3aff4f6 | aliguori | return i;
|
384 | e3aff4f6 | aliguori | |
385 | e3aff4f6 | aliguori | if (sp[1] != '\0') |
386 | e3aff4f6 | aliguori | return -1LL; |
387 | e3aff4f6 | aliguori | |
388 | 7b0a03a1 | Christoph Egger | c = qemu_tolower(*sp); |
389 | e3aff4f6 | aliguori | switch (c) {
|
390 | e3aff4f6 | aliguori | default:
|
391 | e3aff4f6 | aliguori | return i;
|
392 | e3aff4f6 | aliguori | case 'k': |
393 | e3aff4f6 | aliguori | return KILOBYTES(i);
|
394 | e3aff4f6 | aliguori | case 'm': |
395 | e3aff4f6 | aliguori | return MEGABYTES(i);
|
396 | e3aff4f6 | aliguori | case 'g': |
397 | e3aff4f6 | aliguori | return GIGABYTES(i);
|
398 | e3aff4f6 | aliguori | case 't': |
399 | e3aff4f6 | aliguori | return TERABYTES(i);
|
400 | e3aff4f6 | aliguori | case 'p': |
401 | e3aff4f6 | aliguori | return PETABYTES(i);
|
402 | e3aff4f6 | aliguori | case 'e': |
403 | e3aff4f6 | aliguori | return EXABYTES(i);
|
404 | e3aff4f6 | aliguori | } |
405 | e3aff4f6 | aliguori | return -1LL; |
406 | e3aff4f6 | aliguori | } |
407 | e3aff4f6 | aliguori | |
408 | e3aff4f6 | aliguori | #define TO_EXABYTES(x) ((x) / EXABYTES(1)) |
409 | e3aff4f6 | aliguori | #define TO_PETABYTES(x) ((x) / PETABYTES(1)) |
410 | e3aff4f6 | aliguori | #define TO_TERABYTES(x) ((x) / TERABYTES(1)) |
411 | e3aff4f6 | aliguori | #define TO_GIGABYTES(x) ((x) / GIGABYTES(1)) |
412 | e3aff4f6 | aliguori | #define TO_MEGABYTES(x) ((x) / MEGABYTES(1)) |
413 | e3aff4f6 | aliguori | #define TO_KILOBYTES(x) ((x) / KILOBYTES(1)) |
414 | e3aff4f6 | aliguori | |
415 | e3aff4f6 | aliguori | void
|
416 | e3aff4f6 | aliguori | cvtstr( |
417 | e3aff4f6 | aliguori | double value,
|
418 | e3aff4f6 | aliguori | char *str,
|
419 | e3aff4f6 | aliguori | size_t size) |
420 | e3aff4f6 | aliguori | { |
421 | e3aff4f6 | aliguori | const char *fmt; |
422 | e3aff4f6 | aliguori | int precise;
|
423 | e3aff4f6 | aliguori | |
424 | e3aff4f6 | aliguori | precise = ((double)value * 1000 == (double)(int)value * 1000); |
425 | e3aff4f6 | aliguori | |
426 | e3aff4f6 | aliguori | if (value >= EXABYTES(1)) { |
427 | e3aff4f6 | aliguori | fmt = precise ? "%.f EiB" : "%.3f EiB"; |
428 | e3aff4f6 | aliguori | snprintf(str, size, fmt, TO_EXABYTES(value)); |
429 | e3aff4f6 | aliguori | } else if (value >= PETABYTES(1)) { |
430 | e3aff4f6 | aliguori | fmt = precise ? "%.f PiB" : "%.3f PiB"; |
431 | e3aff4f6 | aliguori | snprintf(str, size, fmt, TO_PETABYTES(value)); |
432 | e3aff4f6 | aliguori | } else if (value >= TERABYTES(1)) { |
433 | e3aff4f6 | aliguori | fmt = precise ? "%.f TiB" : "%.3f TiB"; |
434 | e3aff4f6 | aliguori | snprintf(str, size, fmt, TO_TERABYTES(value)); |
435 | e3aff4f6 | aliguori | } else if (value >= GIGABYTES(1)) { |
436 | e3aff4f6 | aliguori | fmt = precise ? "%.f GiB" : "%.3f GiB"; |
437 | e3aff4f6 | aliguori | snprintf(str, size, fmt, TO_GIGABYTES(value)); |
438 | e3aff4f6 | aliguori | } else if (value >= MEGABYTES(1)) { |
439 | e3aff4f6 | aliguori | fmt = precise ? "%.f MiB" : "%.3f MiB"; |
440 | e3aff4f6 | aliguori | snprintf(str, size, fmt, TO_MEGABYTES(value)); |
441 | e3aff4f6 | aliguori | } else if (value >= KILOBYTES(1)) { |
442 | e3aff4f6 | aliguori | fmt = precise ? "%.f KiB" : "%.3f KiB"; |
443 | e3aff4f6 | aliguori | snprintf(str, size, fmt, TO_KILOBYTES(value)); |
444 | e3aff4f6 | aliguori | } else {
|
445 | e3aff4f6 | aliguori | snprintf(str, size, "%f bytes", value);
|
446 | e3aff4f6 | aliguori | } |
447 | e3aff4f6 | aliguori | } |
448 | e3aff4f6 | aliguori | |
449 | e3aff4f6 | aliguori | struct timeval
|
450 | e3aff4f6 | aliguori | tsub(struct timeval t1, struct timeval t2) |
451 | e3aff4f6 | aliguori | { |
452 | e3aff4f6 | aliguori | t1.tv_usec -= t2.tv_usec; |
453 | e3aff4f6 | aliguori | if (t1.tv_usec < 0) { |
454 | e3aff4f6 | aliguori | t1.tv_usec += 1000000;
|
455 | e3aff4f6 | aliguori | t1.tv_sec--; |
456 | e3aff4f6 | aliguori | } |
457 | e3aff4f6 | aliguori | t1.tv_sec -= t2.tv_sec; |
458 | e3aff4f6 | aliguori | return t1;
|
459 | e3aff4f6 | aliguori | } |
460 | e3aff4f6 | aliguori | |
461 | e3aff4f6 | aliguori | double
|
462 | e3aff4f6 | aliguori | tdiv(double value, struct timeval tv) |
463 | e3aff4f6 | aliguori | { |
464 | e3aff4f6 | aliguori | return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0)); |
465 | e3aff4f6 | aliguori | } |
466 | e3aff4f6 | aliguori | |
467 | e3aff4f6 | aliguori | #define HOURS(sec) ((sec) / (60 * 60)) |
468 | e3aff4f6 | aliguori | #define MINUTES(sec) (((sec) % (60 * 60)) / 60) |
469 | e3aff4f6 | aliguori | #define SECONDS(sec) ((sec) % 60) |
470 | e3aff4f6 | aliguori | |
471 | e3aff4f6 | aliguori | void
|
472 | e3aff4f6 | aliguori | timestr( |
473 | e3aff4f6 | aliguori | struct timeval *tv,
|
474 | e3aff4f6 | aliguori | char *ts,
|
475 | e3aff4f6 | aliguori | size_t size, |
476 | e3aff4f6 | aliguori | int format)
|
477 | e3aff4f6 | aliguori | { |
478 | e3aff4f6 | aliguori | double usec = (double)tv->tv_usec / 1000000.0; |
479 | e3aff4f6 | aliguori | |
480 | e3aff4f6 | aliguori | if (format & TERSE_FIXED_TIME) {
|
481 | e3aff4f6 | aliguori | if (!HOURS(tv->tv_sec)) {
|
482 | e3aff4f6 | aliguori | snprintf(ts, size, "%u:%02u.%02u",
|
483 | e3aff4f6 | aliguori | (unsigned int) MINUTES(tv->tv_sec), |
484 | e3aff4f6 | aliguori | (unsigned int) SECONDS(tv->tv_sec), |
485 | bcd2491a | Frediano Ziglio | (unsigned int) (usec * 100)); |
486 | e3aff4f6 | aliguori | return;
|
487 | e3aff4f6 | aliguori | } |
488 | e3aff4f6 | aliguori | format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
|
489 | e3aff4f6 | aliguori | } |
490 | e3aff4f6 | aliguori | |
491 | e3aff4f6 | aliguori | if ((format & VERBOSE_FIXED_TIME) || tv->tv_sec) {
|
492 | e3aff4f6 | aliguori | snprintf(ts, size, "%u:%02u:%02u.%02u",
|
493 | e3aff4f6 | aliguori | (unsigned int) HOURS(tv->tv_sec), |
494 | e3aff4f6 | aliguori | (unsigned int) MINUTES(tv->tv_sec), |
495 | e3aff4f6 | aliguori | (unsigned int) SECONDS(tv->tv_sec), |
496 | bcd2491a | Frediano Ziglio | (unsigned int) (usec * 100)); |
497 | e3aff4f6 | aliguori | } else {
|
498 | bcd2491a | Frediano Ziglio | snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000)); |
499 | e3aff4f6 | aliguori | } |
500 | e3aff4f6 | aliguori | } |
501 | e3aff4f6 | aliguori | |
502 | e3aff4f6 | aliguori | |
503 | e3aff4f6 | aliguori | /* from libxcmd/quit.c */
|
504 | e3aff4f6 | aliguori | |
505 | e3aff4f6 | aliguori | static cmdinfo_t quit_cmd;
|
506 | e3aff4f6 | aliguori | |
507 | e3aff4f6 | aliguori | /* ARGSUSED */
|
508 | e3aff4f6 | aliguori | static int |
509 | e3aff4f6 | aliguori | quit_f( |
510 | e3aff4f6 | aliguori | int argc,
|
511 | e3aff4f6 | aliguori | char **argv)
|
512 | e3aff4f6 | aliguori | { |
513 | e3aff4f6 | aliguori | return 1; |
514 | e3aff4f6 | aliguori | } |
515 | e3aff4f6 | aliguori | |
516 | e3aff4f6 | aliguori | void
|
517 | e3aff4f6 | aliguori | quit_init(void)
|
518 | e3aff4f6 | aliguori | { |
519 | e3aff4f6 | aliguori | quit_cmd.name = _("quit");
|
520 | e3aff4f6 | aliguori | quit_cmd.altname = _("q");
|
521 | e3aff4f6 | aliguori | quit_cmd.cfunc = quit_f; |
522 | e3aff4f6 | aliguori | quit_cmd.argmin = -1;
|
523 | e3aff4f6 | aliguori | quit_cmd.argmax = -1;
|
524 | e3aff4f6 | aliguori | quit_cmd.flags = CMD_FLAG_GLOBAL; |
525 | e3aff4f6 | aliguori | quit_cmd.oneline = _("exit the program");
|
526 | e3aff4f6 | aliguori | |
527 | e3aff4f6 | aliguori | add_command(&quit_cmd); |
528 | e3aff4f6 | aliguori | } |
529 | e3aff4f6 | aliguori | |
530 | e3aff4f6 | aliguori | /* from libxcmd/help.c */
|
531 | e3aff4f6 | aliguori | |
532 | e3aff4f6 | aliguori | static cmdinfo_t help_cmd;
|
533 | e3aff4f6 | aliguori | static void help_onecmd(const char *cmd, const cmdinfo_t *ct); |
534 | e3aff4f6 | aliguori | static void help_oneline(const char *cmd, const cmdinfo_t *ct); |
535 | e3aff4f6 | aliguori | |
536 | e3aff4f6 | aliguori | static void |
537 | e3aff4f6 | aliguori | help_all(void)
|
538 | e3aff4f6 | aliguori | { |
539 | e3aff4f6 | aliguori | const cmdinfo_t *ct;
|
540 | e3aff4f6 | aliguori | |
541 | e3aff4f6 | aliguori | for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++)
|
542 | e3aff4f6 | aliguori | help_oneline(ct->name, ct); |
543 | e3aff4f6 | aliguori | printf(_("\nUse 'help commandname' for extended help.\n"));
|
544 | e3aff4f6 | aliguori | } |
545 | e3aff4f6 | aliguori | |
546 | e3aff4f6 | aliguori | static int |
547 | e3aff4f6 | aliguori | help_f( |
548 | e3aff4f6 | aliguori | int argc,
|
549 | e3aff4f6 | aliguori | char **argv)
|
550 | e3aff4f6 | aliguori | { |
551 | e3aff4f6 | aliguori | const cmdinfo_t *ct;
|
552 | e3aff4f6 | aliguori | |
553 | e3aff4f6 | aliguori | if (argc == 1) { |
554 | e3aff4f6 | aliguori | help_all(); |
555 | e3aff4f6 | aliguori | return 0; |
556 | e3aff4f6 | aliguori | } |
557 | e3aff4f6 | aliguori | ct = find_command(argv[1]);
|
558 | e3aff4f6 | aliguori | if (ct == NULL) { |
559 | e3aff4f6 | aliguori | printf(_("command %s not found\n"), argv[1]); |
560 | e3aff4f6 | aliguori | return 0; |
561 | e3aff4f6 | aliguori | } |
562 | e3aff4f6 | aliguori | help_onecmd(argv[1], ct);
|
563 | e3aff4f6 | aliguori | return 0; |
564 | e3aff4f6 | aliguori | } |
565 | e3aff4f6 | aliguori | |
566 | e3aff4f6 | aliguori | static void |
567 | e3aff4f6 | aliguori | help_onecmd( |
568 | e3aff4f6 | aliguori | const char *cmd, |
569 | e3aff4f6 | aliguori | const cmdinfo_t *ct)
|
570 | e3aff4f6 | aliguori | { |
571 | e3aff4f6 | aliguori | help_oneline(cmd, ct); |
572 | e3aff4f6 | aliguori | if (ct->help)
|
573 | e3aff4f6 | aliguori | ct->help(); |
574 | e3aff4f6 | aliguori | } |
575 | e3aff4f6 | aliguori | |
576 | e3aff4f6 | aliguori | static void |
577 | e3aff4f6 | aliguori | help_oneline( |
578 | e3aff4f6 | aliguori | const char *cmd, |
579 | e3aff4f6 | aliguori | const cmdinfo_t *ct)
|
580 | e3aff4f6 | aliguori | { |
581 | e3aff4f6 | aliguori | if (cmd)
|
582 | e3aff4f6 | aliguori | printf("%s ", cmd);
|
583 | e3aff4f6 | aliguori | else {
|
584 | e3aff4f6 | aliguori | printf("%s ", ct->name);
|
585 | e3aff4f6 | aliguori | if (ct->altname)
|
586 | e3aff4f6 | aliguori | printf("(or %s) ", ct->altname);
|
587 | e3aff4f6 | aliguori | } |
588 | e3aff4f6 | aliguori | if (ct->args)
|
589 | e3aff4f6 | aliguori | printf("%s ", ct->args);
|
590 | e3aff4f6 | aliguori | printf("-- %s\n", ct->oneline);
|
591 | e3aff4f6 | aliguori | } |
592 | e3aff4f6 | aliguori | |
593 | e3aff4f6 | aliguori | void
|
594 | e3aff4f6 | aliguori | help_init(void)
|
595 | e3aff4f6 | aliguori | { |
596 | e3aff4f6 | aliguori | help_cmd.name = _("help");
|
597 | e3aff4f6 | aliguori | help_cmd.altname = _("?");
|
598 | e3aff4f6 | aliguori | help_cmd.cfunc = help_f; |
599 | e3aff4f6 | aliguori | help_cmd.argmin = 0;
|
600 | e3aff4f6 | aliguori | help_cmd.argmax = 1;
|
601 | e3aff4f6 | aliguori | help_cmd.flags = CMD_FLAG_GLOBAL; |
602 | e3aff4f6 | aliguori | help_cmd.args = _("[command]");
|
603 | e3aff4f6 | aliguori | help_cmd.oneline = _("help for one or all commands");
|
604 | e3aff4f6 | aliguori | |
605 | e3aff4f6 | aliguori | add_command(&help_cmd); |
606 | e3aff4f6 | aliguori | } |