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