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